Compiling Arduino sketches using Makefile

Arduino

One of the main reasons why Arduino is very popular with beginners is that it is completely self-contained which makes it very easy to use. Once you have an Arduino board, all you have to do is to download the software and within minutes you can make your first led blink. The software has everything you need right from the IDE, to the compiler and even serial monitor to communicate with Arduino, all within one single package.

While the Arduino IDE is very good for beginners, you might start to feel its limitations, once you start working with it regularly. I use vim for everything and always wished writing Arduino sketches in vim.

I configured Arduino IDE, to use an external editor and started using vim to write code and then Arduino IDE to compile and upload. While this worked for sometime, I started to feel the need for a proper makefile so that I can do everything from vim itself.

Makefile for Arduino

My search landed me to a makefile created by Martin Oldfield. I started using it regularly and also contributed back my patches. Over a period of time, Martin lost interest in the project and now I took ownership of the project and maintain it.

The makefile is quite mature now and in most cases, you can use it to replace the Arduino IDE. There are still some corner cases, but I guess you may not hit them in your day to day use. Also the other advantage of using the makefile is that, you can even program directly using AVR C or assembly, which is not quite easy to do with the Arduino IDE.

Installation

The makefile requires the Arduino software to be installed. So if you have not installed it before, then you have to install it first.

There are three ways by which you can get the makefile

  • Install through package
  • Do a checkout from github
  • Download zip file from github

Install through package

Packages are available for Debian, Ubuntu and FreeBSD. The package name is arduino-mk. If you prefer to install a package, rather than checking out code from github, then you can install the package, if you are using Debian, Ubuntu or FreeBSD.

I also have plans to have a package for homebrew. I will post an update once the package is available for homebrew.

Do a checkout from github

The makefile is hosted in github. You can directly checkout from github. The advantage of this method is that it is every easy to get updates, since the project is currently under heavy development.

Download zip file from github

If you are not comfortable with git or don’t want to do a checkout, then you can also download the zip file from github.

Install dependencies

The Makefile delegates resetting the board to a short Perl program. You’ll need to install Device::SerialPort and YAML library.

On Debian or Ubuntu:

apt-get install libdevice-serialport-perl
apt-get install libyaml-perl

On Fedora:

yum install perl-Device-SerialPort
yum install perl-YAML

On Mac using MacPorts:

sudo port install p5-device-serialport
sudo port install p5-YAML

and use /opt/local/bin/perl5 instead of /usr/bin/perl

On other systems:

cpanm Device::SerialPort
cpanm YAML

Setup

Instead of copying the makefile to every sketch folder, you can just place the downloaded makefile separately in a common location and then create a small child makefile for every sketch.

Global variables

Once you have copied the makefile to a common location, or installed it through a package, you need to declare the following global variables. You can either declare them in your child makefile or set them as environmental variables.

  • ARDUINO_DIR – Directory where Arduino is installed
  • ARDMK_DIR – Directory where you have copied the makefile
  • AVR_TOOLS_DIR – Directory where avr tools are installed

I have the following setup in my ~/.bashrc file

export ARDUINO_DIR=/home/sudar/apps/arduino-1.0.5
export ARDMK_DIR=/home/sudar/Dropbox/code/Arduino-Makefile
export AVR_TOOLS_DIR=/usr

Per sketch variables

After the global settings, you will need to specify the following variables for each sketch

  • BOARD_TAG – The Arduino board that you are using. By default Uno is used
  • ARDUINO_PORT – The serial port where Arduino is connected
  • ARDUINO_LIBS – Space separated set of libraries that are used by your sketch

Usage

Compiling programs

To compile your programs you just have to invoke the command make.

The output is pretty verbose and will list down the configurations that the makefile is using and from where it got the values.

All the build files will be created under a subdirectory in your sketch folder.

If there were any errors then they will be displayed with line numbers, which you can correct.

Uploading programs

To upload the compiled program to your Arduino, just plug your Arduino and run the command make upload.

The program will be recompiled if needed and will be uploaded to your Arduino board.

Opening Serial monitor

The makefile can also be used to check the serial output from your Arduino. To do that just run the command make monitor.

This command will open a serial connection to your Arduino using screen.

The makefile tries to auto detect the baud rate. If it is not able to detect it properly, then you can manually set it using the variable MONITOR_BAUDRATE.

Advanced Usage

In addition to the above typical workflows, the makefile can also be used to do the following advanced stuff. I will write detailed guide for each of these use cases when I get some free time. Meanwhile you can also checkout some of the sample makefiles in the examples folder at github.

  • Compiling plain AVR C programs
  • Program using Arduino as ISP
  • Generate assembly and symbol files
  • Program using alternate Arduino core (like ATtiny or Arduino alternate cores)

Related projects

If you are using Vim as your editor for compiling Arduino programs then you might be interested in some of my following projects as well.

Do check them out as well :)

38 thoughts on “Compiling Arduino sketches using Makefile

  1. K

    Dude, really glad there’s someone to continue taking care of arduino-mk.

    Just wanted to say thanks – I’m sitting here with a Leonardo Nano and I thought I’d have to start tweaking to get it to work, but now I can just use your repo. Cheers!

    Reply
  2. Pingback: Use Arduino to program non-Arduino AVR microcontrollerHardware Fun | Hardware Fun

  3. Pingback: Use Arduino code in non-Arduino AVR microcontrollersHardware Fun | Hardware Fun

  4. Jay

    Sudar, firstly – great work, so please do keep it up.

    Actually, I started looking for latest version of Arduino-mk after I accidentally spotted it in Debian package list. However the first link that came up with this other version:
    http://ed.am/dev/make/arduino-mk

    Wondering if it would be possible to do a compare and contrast of the two ? I am sure there are more alternatives, but the other was, I think also has a link-back from arduino.cc !

    Also, have you considered something like picocom (little brother of minicom), for the serial communication. The other (ed.am) Arduino-mk was reportedly used by someone in conjunction with picocom. The benefit of picocom, as I understand is the ability to have bi-directional communication over serial port. Very useful tool for the poor-man’s debugging technique using serial.writes and serial.read (especially to emulate break-points, in a way). From what I understood, the Perl device-serial is just one way lane, or perhaps, I am mistaken !

    Reply
    1. Sudar Post author

      Nice to know that you like this.

      This is the first time I am hearing about the *other* arduino-mk. The link that you shared is currently down. I will have a detailed look at it latter, once the link is up.

      Meanwhile, the Perl device-serial is used only for resetting the board not for communicating with the board over serial. There is build in support for doing serial communication with Arduino. Checkout the *monitor* target in the makefile.

      Also the serial command can be easily overridden. So, in theory my makefile supports picocom (and other programs) without any change to it.

      Reply
  5. Sergey

    Hi Sudar,

    Thank you for your job. That is really gorgeous! One proposal:
    If you run make not from vim directly, but from command line, a nice to have feature is colorgcc (https://github.com/colorgcc/colorgcc). It adds a color output to gcc messages. It is extremely easy to set up. All what have to be done is:

    1.
    in ~/.colorgccrc add

    avr-g++: /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-g++
    avr-gcc: /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-gcc
    color-avr-g++: /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-g++
    color-avr-gcc: /Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-gcc

    2.
    put soft links to colorgcc.pl for avr-g++ and avr-gcc from somewhere in your PATH, i.e.

    PATH=${HOME}/bin:${PATH}

    ln -s path_to_colorgcc.pl ~/bin/avr-gcc
    ln -s path_to_colorgcc.pl ~/bin/avr-g++

    3.
    alter your project Makefile to look like:

    BOARD_TAG = uno
    MONITOR_PORT = /dev/cu.usb*
    ARDUINO_LIBS =

    include $(ARDMK_DIR)/Arduino.mk

    #
    # Override Arduino.mk defaults to point to my soft links to
    # colorgcc. Colorgcc reads the config from ~/.colorgccrc
    #
    CC = avr-gcc
    CXX = avr-g++

    4.
    and you will get a colored output in console for avr-gcc.

    Hope, that makes sense

    Reply
    1. Sudar Post author

      @Sergey,

      Thanks for mentioning colorgcc. I didn’t know about it before and it seems to be extremely useful. I will add notes about integrating the makefile with colorgcc

      One small issue though is that, I see there are a couple of open issues and pull requests for it in github, but no one seems to be maintaining it anymore.

      Reply
      1. Sergey

        I didn’t pay an attention to that. I’ve been using colorgcc for 3 years, may be, and I have never had any issue big enough to turn me off using it. It is extremely nice to have when you’re in the console. There is another one, called colorsvn if you like SVN. Git, which is better, of course, has embedded color support.

        Reply
  6. Pingback: Arduino Makefile hits v1.0.0Hardware Fun | Hardware Fun

  7. Pingback: Use Arduino as an ISP programmer to program non-Arduino AVR microcontrollersHardware Fun | Hardware Fun

  8. Pingback: Arduino Makefile v1.1.0 releasedHardware Fun | Hardware Fun

    1. Sudar Post author

      Both are very similar, but there are some fine differences.

      • Ino abstracts out most of the makefile, therefore it is quite easy, but if you need to tweak it, then it is not possible.
      • This makefile can be used to compile just plain AVR C, but that is not possible by Ino.
      • Ino doesn’t (as far as my understanding) support custom core, but this makefile supports it.

      In short, both do similar things, but this makefile gives you more control, while ino is very easy to get started.

      Reply
  9. lotsarats

    installed this with apt-get install arduino-mk with debain wheezy 7 and i received arduino.mk version 0.8 by martin.

    your “installation through package” appears to be incorrect as your not updating the official repositories

    Reply
  10. Peter

    Hello Sudar,

    I started to play with the Makefile and I like it! Especially the plain BlinkInAVRC example. I would like to upload the BlinkInAVRC on my Arduino micro, but I failed. I edited the BOARD_TAG and the MCU
    BOARD_TAG = atmega32u4
    MCU = atmega32u4
    F_CPU = 16000000L

    but I do have to do something with the programmer I guess. Can you give some advise?

    Cheers,
    Peter

    Reply
      1. Peter

        Hi Sudar,

        here it comes. Just as a comment, it works when I use leonardo as BOARD_TAG but then all the Arduino software is compiled and linked as well, I do only want to compile the pure blink.c

        Thanks for the help,
        Peter

        Makefile:

        # This sample Makefile, explains how you can compile plain AVR C file.
        #
        # Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile

        NO_CORE = Yes

        #BOARD_TAG = atmega16
        #MCU = atmega16
        BOARD_TAG = atmega32u4

        MCU = atmega32u4
        F_CPU = 16000000L

        ISP_PROG = stk500v1
        AVRDUDE_ISP_BAUDRATE = 19200

        include ../../Arduino.mk

        # !!! Important. You have to use make ispload to upload when using ISP programmer
        —————————————————————-

        The output of the commandline:

        – [COMPUTED] BOOTLOADER_PARENT = /usr/share/arduino/hardware/arduino/bootloaders (from ARDUINO_DIR)
        ————————-
        mkdir -p build-atmega32u4

        Maximum flash memory of atmega32u4 is not specified. Make sure the size of build-atmega32u4/BlinkInAVRC.hex is less than atmega32u4\’s flash memory

        make reset
        make[1]: Entering directory `/ubuntu/home/holterma/data/src/Arduino-Makefile.git/examples/BlinkInAVRC’
        /ubuntu/home/holterma/data/src/Arduino-Makefile.git/bin/ard-reset-arduino /dev/ttyACM3
        TIOCMBIC(21527) ioctl failed: Daten├╝bergabe unterbrochen (broken pipe) at /ubuntu/home/holterma/data/src/Arduino-Makefile.git/bin/ard-reset-arduino line 66
        dtr_active(0) ioctl: Daten├╝bergabe unterbrochen (broken pipe)
        could not restore from dtr on
        make[1]: Leaving directory `/ubuntu/home/holterma/data/src/Arduino-Makefile.git/examples/BlinkInAVRC’
        make do_upload
        make[1]: Entering directory `/ubuntu/home/holterma/data/src/Arduino-Makefile.git/examples/BlinkInAVRC’
        /usr/bin/avrdude -q -V -D -p atmega32u4 -c -b -P /dev/ttyACM3 \
        -U flash:w:build-atmega32u4/BlinkInAVRC.hex:i

        avrdude: Can’t find programmer id “-b”

        Reply
          1. Peter

            Its working with this Makefile,

            best,
            Peter

            # This sample Makefile, explains how you can compile plain AVR C file.
            #
            # Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile

            NO_CORE = Yes

            #BOARD_TAG = atmega16
            #MCU = atmega16
            BOARD_TAG = micro
            MCU = atmega32u4
            F_CPU = 16000000L

            #ISP_PROG = stk500v1
            #AVRDUDE_ISP_BAUDRATE = 19200

            AVRDUDE_ARD_PROGRAMMER = avr109
            AVRDUDE_ARD_BAUDRATE = 57600

            include ../../Arduino.mk

            # !!! Important. You have to use make ispload to upload when using ISP programmer

  11. Pingback: Arduino Makefile updatesHardware Fun | Hardware Fun

  12. Xavier

    Thank you for your work on this project: it worked during my first try on my side!

    And to make the documentation even better: you say in this page that the makefile delegates board resetting to a Perl script while it seems that it’s a Python script that does this. Maybe this page is not up to date? Moreover, the Arch Linux package to install for pySerial is “python-pyserial” so the command to install it is:
    # pacman -S python-pyserial

    Thanks again!

    Reply
    1. Sudar Post author

      Nice to know that you like the project.

      Yes, this page is slightly out of date. I was updating the github readme file, but didn’t updated this post. Will update this post as well.

      Reply
  13. Pingback: Arduino Makefile v1.3.4 releasedHardware Fun | Hardware Fun

  14. Gerhard

    Thank you for this great addition. It already helped me a lot.

    One thing I couldn’t figure out how to compile release code. I have a couple of ‘#ifdef DEBUG’ scattered in my code, but I want to remove these sections from the compiled hex for release by just adding something to the command line. Is this already possible?

    Reply
    1. Gerhard

      I found out myself. Always use a clean working directory… ;)

      $ make clean && CXXFLAGS_STD=-DDEBUG make upload
      $ make clean && make upload

      Reply
  15. Pingback: Fix Arduino Uno Error Compiling Windows XP, Vista, 7, 8 [Solved]

  16. Pingback: Fix Arduino Error Compiling Windows XP, Vista, 7, 8 [Solved]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>