Building the Arduino Libraries from the command line

If you're like me, (few probably are) then you're one of those that likes long-term solutions instead of short-term workarounds.

Well, I've been building an FM transmitter using an Ardunio(more details about that later). When I first went to write code for my Ardunio, I noticed that my libraries are massively out of date. So out of date that most of the Ardunio code I found would no longer work for me. So, it was time to upgrade. I don't remember how I got the Arduino library before, so I set out to download a copy of it...

After an hour of searching... hmmm no one hosts a copy of it for some reason. Well, I guess I'll build it. I look at the ill-documented mess that is the Arduino source tree... no makefile for the library. The common solution is to run the Arduino IDE once, build a sketch, and copy the library from there. Well, that's not good enough for me. So I made a makefile and set out to get it to build from the command line

Directions:

  1. Download a copy of the Arduino IDE source code
  2. Copy the contents of hardware/arduino/cores/arduino to a new directory I'll refer to as arduino_build
  3. Copy the pins_arduino.h file from whichever Arduino variant is yours from hardware/arduino/variants (check boards.txt if you're not sure) to arduino_build
  4. Add this makefile to arduino_build:

.

#<Copyright Header>
#Copyright (c) 2012 Jordan "Earlz" Earls  <http://lastyearswishes.com
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions
#are met:
#
#1. Redistributions of source code must retain the above copyright
#   notice, this list of conditions and the following disclaimer.
#2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#3. The name of the author may not be used to endorse or promote products
#   derived from this software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
#INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
#AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
#THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#</Copyright Header>

HDRS = Arduino.h binary.h Client.h HardwareSerial.h IPAddress.h new.h pins_arduino.h Platform.h Printable.h Print.h \
    Server.h Stream.h Udp.h USBAPI.h USBCore.h USBDesc.h WCharacter.h wiring_private.h WString.h


OBJS = WInterrupts.o wiring_analog.o wiring.o wiring_digital.o wiring_pulse.o wiring_shift.o CDC.o HardwareSerial.o \
    HID.o IPAddress.o main.o new.o Print.o Stream.o Tone.o USBCore.o WMath.o WString.o

#may need to adjust -mmcu if you have an older atmega168
#may also need to adjust F_CPU if your clock isn't set to 16Mhz
CFLAGS = -I./ -std=gnu99  -DF_CPU=16000000UL -Os -mmcu=atmega328p
CPPFLAGS = -I./ -DF_CPU=16000000UL -Os -mmcu=atmega328p

CC=avr-gcc
CPP=avr-g++
AR=avr-ar


default: libarduino.a

libarduino.a:   ${OBJS}
    ${AR} crs libarduino.a $(OBJS)

.c.o: ${HDRS}
    ${CC} ${CFLAGS} -c $*.c

.cpp.o: ${HDRS}
    ${CPP} ${CPPFLAGS} -c $*.cpp

clean:
    rm -f ${OBJS} core a.out errs

install: libarduino.a
    mkdir -p ${PREFIX}/lib
    mkdir -p ${PREFIX}/include
    cp *.h ${PREFIX}/include
    cp *.a ${PREFIX}/lib

And then just run

make
make install PREFIX=/usr/arduino (or whatever)

And then to make use of the compiled libraries and such you can use a simple makefile like this:

default:
    avr-g++ -L/usr/arduino/lib -I/usr/arduino/include -Wall -DF_CPU=16000000UL -Os -mmcu=atmega328p\
      -o main.elf main.c -larduino
    avr-objcopy -O ihex -R .eeprom main.elf out.hex
upload:
    avrdude -c arduino -p m328p -b 57600 -P /dev/ttyUSB0 -U flash:w:out.hex

all: default upload

Also, if you try to compile the libraries in libraries/ you'll get a linker error if you don't do things in the right order. For instance, I had to do this to use SoftwareSerial:

avr-g++ -L/usr/arduino/lib -I/usr/arduino/include -Wall -DF_CPU=16000000UL -Os -mmcu=atmega328p\
   -o main.elf main.c -lSoftwareSerial -larduino

The -larduino must be the last library on the command line

Anyway, this was a pretty easy way to compile it for me. As future versions of the Ardunio come out, this makefile should be fairly future-proof, requiring just a few modifications to OBJS and HDRS. Also, this makefile should work with both BSD make and GNU make

Also, if you're like me and you weren't interest in building the library, just wanted to download a copy of the binary, here is a copy: Arduino library (built using the "standard" pins_arduino.h)

Posted: 3/22/2012 7:24:54 PM