48

How do I compile and upload Arduino sketches from the command line on Mac and Linux? I've installed the Arduino programming environment. Are there some sample makefiles anywhere?

Mads Skjern
  • 5,648
  • 6
  • 36
  • 40
Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
  • This question is similar to the following question on Arduino StackExchange: http://arduino.stackexchange.com/questions/15893/how-to-compile-upload-and-monitor-via-the-linux-command-line – Metamorphic Jun 05 '16 at 22:40

13 Answers13

37

There is a command-line Arduino toolkit named Ino. It just does that.

nkrkv
  • 7,030
  • 4
  • 28
  • 36
16

Compiling and uploading sketches (as apposed to C/C++ sources) on the command line (on Windows, Mac, and Linux) is supported directly via flags to the arduino executable since 1.5.0.

An ino can be compiled and uploaded with arduino --upload [sketch.ino]

Documentation

timlyo
  • 2,086
  • 1
  • 23
  • 35
user1823664
  • 1,071
  • 9
  • 16
10

This is my boilerplate gnu make include for AVR projects, you may need to adapt some of it to fit your environment. It creates dependencies, has a host of standard gcc options I find useful or that optimize for size, as well as a library dir I use. I used this successfully to compile arduino software, I also previously hacked the PdePreprocessor in the arduino editor to be run from the command line to generate all the voodoo:

https://github.com/wesen/mididuino/blob/master/app/src/processing/app/preproc/PdePreprocessor.java

#
# generic AVR makefile
#
# (c)  July 2011 - Manuel Odendahl - wesen@ruinwesen.com
#

# include this into your main Makefile, after having defined TARGET and TARGET_OBJS

all: $(TARGET).hex

CURDIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(CURDIR)MidiCtrl.mk

CC             = avr-gcc
CXX            = avr-g++
OBJCOPY        = avr-objcopy
AVR_ARCH       ?= atmega64
LDAVR_ARCH     ?= avrmega64
FLASH_PROTOCOL = jtag2

CFLAGS   += -Os -ffunction-sections -DAVR -I. -mmcu=$(AVR_ARCH) -mcall-prologues -fshort-enums -fpack-struct -Wall -Werror
CFLAGS   += -Wall -DLITTLE_ENDIAN -g -flto

CFLAGS += no-tree-loop-optimize -ffreestanding -morder1 -funsigned-char -funsigned-bitfields -fshort-enums -fpack-struct
CFLAGS += -fdata-sections -fno-split-wide-types -fno-inline-small-functions -mcall-prologues

CLDFLAGS += -Wl,--relax,--gc-sections -ffunction-sections
CLDFLAGS += -mmcu=$(AVR_ARCH)
LDFLAGS  = -m $(LDAVR_ARCH) -M

# generate list
# CFLAGS += -Wa,-adhlns=$@.lst

%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@

%.o: %.c
        $(CC) $(CFLAGS) -c $< -o $@

%.o: %.s
        $(CC) $(CFLAGS) -c $< -o $@

%.s: %.c
        $(CC) -S $(CFLAGS) -fverbose-asm $< -o $@

%.o: %.S
        $(CC) $(CFLAGS) -c $< -o $@

%.syx: %.hex
        ihex2sysex $< $@

%.srec: %.elf
        $(OBJCOPY) -j .text -j .data -O srec $< $@

%.hex: %.elf
        $(OBJCOPY) -j .text -j .data -O ihex $< $@

%.ee_srec: %.elf
        $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@

AVR_BASE_DIR  ?= $(abspath $(CURDIR)..)
AVR_LIB_DIR   ?= $(AVR_BASE_DIR)/hardware/libraries

AVR_LIBS       += CommonTools Midi
AVR_LIB_DIRS   += $(foreach lib,$(AVR_LIBS),$(AVR_LIB_DIR)/$(lib))
AVR_INC_FLAGS  += $(foreach dir,$(AVR_LIB_DIRS),-I$(dir))
AVR_OBJS       += $(foreach dir,$(AVR_LIB_DIRS),$(foreach file,$(wildcard $(dir)/*.cpp),$(subst .cpp,.o,$(file))))
AVR_OBJS       += $(foreach dir,$(AVR_LIB_DIRS),$(foreach file,$(filter-out $(AVR_HOST_EXCLUDE),$(wildcard $(dir)/*.c)),$(subst .c,.o,$(file))))
AVR_DEPS       += $(subst .o,.d,$(AVR_OBJS))

# AVR_HOST_EXCLUDE can be used to exclude specific files later on

CXXFLAGS += $(AVR_INC_FLAGS)
CFLAGS += $(AVR_INC_FLAGS)

CXXFlags += -Werror -Wall
CFLAGS += -Werror -Wall

default: all

%.d:%.c
        set -e; $(CC) -MM $(CFLAGS) $< \
        | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ ; \
        [ -s $@ ] || rm -f $@

%.d:%.cpp
        set -e; $(CXX) -MM $(CXXFLAGS) $< \
        | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ ; \
        [ -s $@ ] || rm -f $@

%.host.d:%.c
        set -e; $(CC) -MM $(CFLAGS) $< \
        | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ ; \
        [ -s $@ ] || rm -f $@

%.host.d:%.cpp
        set -e; $(CXX) -MM $(CXXFLAGS) $< \
        | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@ ; \
        [ -s $@ ] || rm -f $@

printlibs:
        echo $(AVR_LIBS)

$(TARGET).elf: $(TARGET).o $(TARGET_OBJS) $(AVR_OBJS)
        $(CXX) $(CLDFLAGS) -g -o $@ $^

_clean:
        - rm *.elf *.hex *.o .midictrl.flags

libclean:
        rm -rf $(TARGET_OBJS) $(OBJS)

# concrete settings for development environment

UNAME=$(shell uname)
ISWIN=$(findstring CYGWIN,$(UNAME))
ISMAC=$(findstring Darwin,$(UNAME))

CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
AVR_ARCH = atmega64
F_CPU = 16000000L
CORE = minicommand2
wesen
  • 631
  • 6
  • 10
7

Official CLI tool

The arduino team is developing a cli client https://github.com/arduino/arduino-cli

Announcement: https://blog.arduino.cc/2018/08/24/announcing-the-arduino-command-line-interface-cli/

You can do almost everything with this, from downloading boards and libraries, to compile and upload scripts. What's missing is the monitoring part.

To monitor in linux you can still use the commands stty to configure port and cat to read it.

stty -F /dev/ttyACM0 38400 # <-- Baud rate. The number in Serial.begin()
cat /dev/ttyACM0 # <-- Port

You can find the port with arduino-cli

arduino-cli board list

Full instructions in the Github repo and the man page:

    $ arduino-cli Arduino Command Line Interface (arduino-cli).

    Usage:   arduino-cli [command]

    Examples: arduino <command> [flags...]

    Available Commands:
      board         Arduino board commands.
      compile       Compiles Arduino sketches.
      config        Arduino Configuration Commands.
      core          Arduino Core operations.
      help          Help about any command
      lib           Arduino commands about libraries.
      sketch        Arduino CLI Sketch Commands.
      upload        Upload Arduino sketches.
      version       Shows version number of Arduino CLI.
Madacol
  • 3,611
  • 34
  • 33
5

You need to actually create a viable cpp file out of your arduino sketch. The arduino environment does that for you automatically. One trick to get to those files is to open your arduino preferences.txt (it's in ~/Library/Arduino on the mac, I think in your Documents and Settings or Application Data on windows, don't remember exactly), and set build.verbose=true and upload.verbose=true. Start arduino, and compile your sketch (don't upload it). The console at the bottom will show you which files were compiled. You can now go to that directory, which will contain the cpp file, and compiled object files for all the core arduino objects. You can copy those into your project and use the cpp file to do further hacking. Let me know if you need more information about the Makefile, I can provide you with those I have.

wesen
  • 631
  • 6
  • 10
  • 10
    Telling someone to start a gui in order to use a command line tool is not a helpful suggestion... – Cerin Feb 23 '13 at 11:50
  • This trick only works in Arduino 1.6 or so if you add the build.path setting to the preference file (which on Mac is at ~/Library/Arduino15/preferences.txt). Create the build folder first. For example: 'build.path=/Users/user1/Documents/Arduino/build' – Elise van Looij Aug 12 '17 at 14:23
3

You can use biicode (it's a project I'm working in) which is based on CMake (but you don't actually need to write any cmake file) and is also a tool to manage Arduino libraries

It's main features are:

  • Dependencies resolution, transitively, as maven does, but without config files: reads dependencies directly from source code.
  • Central repository, anyone can upload their libraries. They can be explored, navigated and discovered in the web
  • Version control: it checks versions compatibility and allows safe updates of dependencies
  • You can use it with any text editor (it has optional eclipse integration)
  • It manages project setup and compilations, flashes generated firmware to the board

You can see a quick demo here and read more in the documentation.

hithwen
  • 2,154
  • 28
  • 46
  • The project moved now to [conan.io](https://conan.io/) but I dont know if it still supports arduino. I'm no longer involved – hithwen Apr 07 '20 at 15:32
3

You can actually use the arduino GUI to compile and upload, and set the editor to external in the preferences. That way, you can edit the C++ (PDE) files from xcode, and have arduino generate the actual CPP and build the whole shebang.

You can also use XCode to write plain C++/C for the arduino, using the avr-gcc compiler.

Have a look at: https://stackoverflow.com/a/8192762/153835

You can then use the plain avrdude upload tool to program the arduino. Have a look at: http://www.ladyada.net/library/arduino/bootloader.html

It used to be that the protocol spoken by Arduino was a modification of the STK500 protocol, and that only the avrdude bundled with arduino could speak it. I don't know if the mainstream avrdude was upgraded, or if you still have to resort to the avrdude inside the Arduino folder.

Community
  • 1
  • 1
wesen
  • 631
  • 6
  • 10
2

I use platformio, quite like it. It also has extensions into Visual Studio Code, so you can do everything from there. It has library manager and uploader built-in.

My setup is a NFS drive where I have the code, mounted on my linux laptop, and also mounted on my Raspberry Pi that sits next to my Arduino's.

When it's time to compile, I do so on my laptop, and as the RPi is next to the Arduino, I upload from there..

After installing and configuring, the basics are simple; 'platformio run' will compile your code. 'platformio run -t upload' will compile & upload.

I also have a bash function to upload without compiling;

function th(){
    if [ "${1}" = "upload" ];then
    if [ ! -f platformio.ini ]; then
        echo platformio.ini not found
    else 
        UPLOAD_PORT=`cat platformio.ini | grep upload_port | awk '{print $3}'`
        if [ "${UPLOAD_PORT}" = "" ]; then
            echo no upload port
        else
            if [ "${2}" != "" ]; then
                FIRMWARE=${2}
            else
#the firmware location seems to have moved
#               FIRMWARE='.pioenvs/megaatmega2560/firmware.hex'
                FIRMWARE='.pio/build/megaatmega2560/firmware.hex'
            fi
            if [ -f "${FIRMWARE}" ]; then
                avrdude -v -p atmega2560 -C /home/stevenk/.platformio/packages/tool-avrdude/avrdude.conf -c wiring -b 115200 -D -P "${UPLOAD_PORT}" -U flash:w:$FIRMWARE:i
            else
                echo ${FIRMWARE} not found
            fi
        fi
    fi
    else 
            wget --timeout 8 -qO- http://192.168.178.212/$1
    fi
}
stevux
  • 21
  • 2
2

If you can use cmake then there are some links in the same web (this and this for example). GNU makefile is a little bit different from cmake but nothing complicated. Just Google a little bit and you can find a lot of Makefile examples how to compile AVR code.

skaz
  • 21,962
  • 20
  • 69
  • 98
Cougar
  • 651
  • 4
  • 11
1

If you do not insist on make there is also scons/sconstruct scons/sconstruct. Since this in basically written in Python it is much simpler to tweak than make. In addition it can be debugged with any Python debugger.

Udo Klein
  • 6,784
  • 1
  • 36
  • 61
1

I have a makefile for Arduino which can be used to compile and upload Arduino (or plain AVR C) programs to Arduino.

Following are some of the important features of this makefile

  • Supports upload via Arduino as ISP or any programmer
  • Supports compiling plain AVR C programs
  • Supports user as well as system libraries.
  • Generate assembly and symbol files
  • Program using alternate Arduino core (like ATtiny or Arduino alternate cores)
Sudar
  • 18,954
  • 30
  • 85
  • 131
1

There's an official Arduino CLI tool:

https://blog.arduino.cc/2021/02/15/arduino-cli-0-16-0-is-ready-for-you-all/?queryID=undefined

It works pretty well, in my opinion. The GitHub repo is here:

https://github.com/arduino/arduino-cli

It's version 0.16.0. so sort of beta, but not really....

g3holliday
  • 21
  • 9
0

You can find the libraries and sample codes included in the Arduino under "file->examples".