A Makefile for Arduino Sketches

When I started tinkering with Arduinos I started out with the standard Arduino IDE. It's great for getting started quickly but for more complex work, such as those involving libraries shared between Sketches, it quickly becomes limiting. What I wanted was to continue using the standard Arduino libraries but to switch to a more capable IDE. I already use NetBeans so I wanted to try to use that if possible. The first step was to come up with a way of building Arduino Sketches from outside the Arduino IDE. The Arduino distribution includes a number of old, deprecated Makefiles, but nothing that was really usable. I therefore set to and wrote my own. I've followed the standard layout we use at work, with a 'master' Makefile that contains most of the logic, which is then included into a per-project Makefile that sets up the required configuration for the rules in the master Makefile. It is available here. An example project Makefile looks like this:

BOARD = atmega328
PORT = /dev/term/0
LIB_DIRS = ../Common/Task ../Common/VirtualWire
include ../Makefile.master

Some notes about how to use the Makefile:

  • At the moment the Makefile is pretty Solaris-specific, because I haven't had the time to get it all going under a Linux VM, although the required changes are simple. Patches are welcome :-)

  • You'll need the standard Arduino environment installed first, either version 0018 or 0019.

  • You must use gmake as your make implementation - not usually a problem as it comes included in the Arduino environment.

  • The valid values for BOARD are those found in the standard boards.txt file, that file is parsed to extract the relevant values for the Makefile. PORT is the path of the USB port that the Arduino is attached to. LIB_DIRS is a list of directories containing any libraries that you want to use.

  • The following targets are provided in the Makefile:

    • all - build everything (default).
    • clean - remove all generated files.
    • upload - build everything and upload to the board.
    • monitor - run the serial monitor.
    • upload_monitor - build everything, upload to the board and run the serial monitor.

  • You don't need to explicitly list the various .c, .cpp and .pde files that make up your application, the makefile assumes that any such files it finds in the various source directories are all to be compiled.

  • The processing of the Sketch (.pde) files is very simplistic, much more so than the processing done by the Arduino IDE. There's talk on the Arduino development list of splitting the Sketch-to-C++ processing out into a separate library so it can be reused, but it hasn't happened yet. I've actually stopped using .pde files and now just write my own main.cpp, it's simple enough not to be any sort of an inconvenience to do so.

  • The output is all created in the build subdirectory of the Sketch's directory. That means it doesn't interfere with anything if you still want to be able to use the standard Arduino environment.

  • Unlike the Arduino IDE which rebuilds everything every time, the Makefile only builds files that have changed. One caveat: if you change the board type in the Makefile, be sure to run make clean; make afterwards to rebuild everything correctly.

  • The Makefile builds three archive libraries in the build directory:

    • libarduino.a - this contains the object code of the standard Arduino run-time libraries.
    • liblibrary.a - this contains the object code of any libraries you specified in the LIB_DIRS Makefile variable.
    • libsketch.a - this contains the object code of the files that comprise your Sketch.

    The use of archive libraries allows the linker to only include object files that provide referenced symbols, which will result in smaller executables if you use libraries that contain code that you don't actually use in your Sketch.

I tried offering the Makefile to the Arduino developers but they seem a little, ummm... reluctant to take contributions in areas outside of their immediate goals. I understand they want to concentrate their efforts on their priorities, but if they want to grow the pool of people developing the Arduino platform (as opposed to growing the community developing on the platform) they are going to have to change their approach. It's not just me that has had this experience, the changes for the Solaris Arduino port also haven't made their way back in.

I'll write a followup post on how I've used the Makefile to enable me to use NetBeans as my Arduino development environment, including all the nice features such as code completion, pre-compilation error checking and syntax highlighting, so please check back for more!

Update

Martin Oldfield has done more-or less the same thing, with more of a Linux slant. His version can be found here.

Categories : Solaris, AVR, Tech


Re: A Makefile for Arduino Sketches

 Sorry to trouble you ...\

I have read your makefile carefully ... and mostly it all makes sense ...

However in the command beginning cat $^   I do not know what the $^ means 

Could you please tell me ...

Thanks

Re: A Makefile for Arduino Sketches

It's a list of the prerequisites for the target - see www.gnu.org/software/make/manual/make.html#Automatic-Variables

Re: A Makefile for Arduino Sketches

greate makfile!

I was looking for this for some time

 

I think I found a bug

 you can not compile a single pde file

it should be:

ifneq "$(strip $(SKT_PDE_SRC))" ""
    SKT_PDE_OBJ = $(BUILD_DIR)/$(SKETCH)_pde.o
endif

ifneq "$(strip $(SKT_C_SRC) $(SKT_CXX_SRC))" ""
    SKT_C_OBJ = $(patsubst %.c,%.o,$(SKT_C_SRC))
    SKT_CXX_OBJ = $(patsubst %.cpp,%.o,$(SKT_CXX_SRC))
    SKT_LIB = sketch
    SKT_AR = $(BUILD_DIR)/lib$(SKT_LIB).a
    SKT_AR_OBJ = $(SKT_AR)/($(SKT_C_OBJ) $(SKT_CXX_OBJ))
    SKT_LD_FLAG = -l$(SKT_LIB)
endif

 

 

 

you can reinclude the main.cpp file

#ARD_CXX_SRC = $(filter-out %/main.cpp,$(wildcard $(ARD_SRC_DIR)/*.cpp))
ARD_CXX_SRC = $(wildcard $(ARD_SRC_DIR)/*.cpp)

and remove it from the source file

$(SKT_PDE_OBJ) : $(SKT_PDE_SRC)
    echo '#include <WProgram.h>' | cat - $^ > $(BUILD_DIR)/$(SKETCH)_pde.cpp
    #cat $(ARD_MAIN) $^ > $(BUILD_DIR)/$(SKETCH)_pde.cpp

 

so you do not need to add the main() function to the source.cpp file

please add the path for ARD_BIN and AVRDUDE to the settings section

you have to customise it to work with the ubuntu version from the repository

 

Re: A Makefile for Arduino Sketches

Thanks for the feedback, I've included the changes you suggested.

Re: A Makefile for Arduino Sketches

it needs another fix to get it linking correctly with cpp files only

$(IMAGE).hex : $(ARD_AR_OBJ) $(LIB_AR_OBJ) $(SKT_AR_OBJ) $(SKT_PDE_OBJ)
    @echo **********LINK**************** $(SKT_LD_FLAG)
    $(CXX) $(CXX_FLAGS) $(OPT_FLAGS) $(ARD_FLAGS) -L$(BUILD_DIR) \
        $(SKT_PDE_OBJ) $(ARD_LD_FLAG) $(SKT_LD_FLAG) $(LIB_LD_FLAG) $(ARD_LD_FLAG)  \
        -o $(IMAGE).elf

Re: A Makefile for Arduino Sketches

Not quite sure what that's supposed to do as $(ARD_LD_FLAG) is already included in the link line, the only thing I can think of is that you've introduced some sort of circular dependency in your object files.

Re: A Makefile for Arduino Sketches

FYI,  guess the download link to the most recent version of the makefile is broken...