Gamebuino META Makefile
It's always been a goal to build my Gamebuino games with
make from the shell instead of having to go through the Arduino IDE. This was a breeze thanks to the Arduino-Makefile project and its support for the Arduino Zero (SAMD) board. The advantages of bypassing the IDE include much faster build times, no waiting for the Java application to start, and control over compiler flags and other build settings.
At the time I wrote this page I was using Linux Mint 18.3 and 19.1 with the 64bit Arduino 1.8.9 from the Arduino website. Arduino-Makefile is compatible with Windows and Mac too though, so read on even if you're not using Linux!
Install Arduino and the Gamebuino META Board & Library#
You first need to setup your system for Gamebuino development. For simplicity, this article assumes everything, including the IDE, is installed in your home folder,
$HOME. Without repeating much, launch the Arduino IDE and:
- Install the Arduino SAMD (ARM) boards package
- Add Gamebuino META board package URL* and install the Gamebuino META board package
- Install the Gamebuino META library
*Board URL is
Test Your Setup#
Test that everything is working by building one of the example sketches:
- File > Examples > Examples from Custom Libraries: Gamebuino META > Basics > Hello
- Sketch > Verify/Compile
- Sketch > Upload
We will come back to this sketch later, and build it with a Makefile from its source folder instead.
Clone the latest Arduino-Makefile from the project repo. The version in the Ubuntu repos is too old and does not support ARM boards like the META.
$ cd ~ $ git clone https://github.com/sudar/Arduino-Makefile
If you want to use
make upload to flash the Gamebuino from the command line, you might also need to install the PySerial Python module:
$ sudo apt install python-serial
Build with Make#
Write a Project Makefile#
Let's go back to the example sketch:
$ cd ~/Arduino/libraries/Gamebuino_META/examples/1.Basics/a_Hello
In that folder, create a new file called
Makefile with this content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# # Arduino IDE and Arduino-Makefile paths # ARDUINO_DIR = $(HOME)/arduino ARDMK_DIR = $(HOME)/Arduino-Makefile # # Specify the custom board and its path # BOARD_TAG = gamebuino_meta_native ALTERNATE_CORE_PATH = \ $(wildcard $(HOME)/.arduino15/packages/gamebuino/hardware/samd/1.*) # # The Arduino libraries the game uses # ARDUINO_LIBS = Gamebuino_META SPI # # Now that everything is configured, include Arduino-Makefile # include $(ARDMK_DIR)/Sam.mk # # Gamebuino_META expects __SKETCH_NAME__ defined by the IDE, # and does not build well with Link Time Optimization. # CFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" -fno-lto CXXFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" -fno-lto LDFLAGS += -fno-lto
This file tells Arduino-Makefile where all the Arduino tools and libraries are installed, so it can use them to build the project. All the variables need to be named exactly as above.
The paths on your computer may be different, you can check what they are by compiling and uploading the sketch with the IDE and looking at the output log. Make sure to enable verbose output from File > Preferences:
Build the Project#
1 2 3 4 5 6 7 8 9 10 11 12 13 14
$ cd ~/Arduino/libraries/Gamebuino_META/examples/1.Basics/a_Hello # Confirm that the new Makefile is there $ ls a_Hello.ino Makefile # Build project $ make # Build even faster with parallel jobs $ make -j8 # Flash the BIN to device $ make upload
Customize the Project Layout#
The default Arduino project is structured like this:
1 2 3 4 5 6
MyProject/ └── a_Hello/ ├── a_Hello-build-gamebuino_meta_native/ │ └── a_Hello.bin ├── a_Hello.ino └── Makefile
However, I build my games for multiple platforms not just Gamebuino, and I like to keep the source code, Makefiles, and build files in separate non-nested folders. I want my project to look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
MyProject/ ├── a_Hello/ │ └── a_Hello.ino ├── build/ │ ├── gamebuino/ │ │ └── a_Hello.bin │ ├── linux/ │ │ └── a_Hello │ └── windows/ │ └── a_Hello.exe └── make/ ├── Makefile.gamebuino ├── Makefile.linux └── Makefile.windows
MyProject/build/gamebuino/a_Hello.bin, I'd like to just do this:
$ cd MyProject/make/ $ make -f Makefile.gamebuino
There's a problem though, Arduino-Makefile expects you to invoke make from
MyProject/a_Hello instead of from
MyProject/make. One workaround would be to call make like this instead:
$ cd MyProject/a_Hello/ $ make -f ../make/Makefile.gamebuino
But this is inconvenient to do every time, and inconsistent with how I build for every other system. Instead, I rewrote the Makefile to set up the correct paths, then call itself recursively from the source folder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
ifndef ACTUALLY_BUILD MY_PROJECT_ROOT := $(realpath ..) MY_PROJECT_DIR_MAKE = $(MY_PROJECT_ROOT)/make MY_PROJECT_DIR_SOURCE = $(MY_PROJECT_ROOT)/a_Hello MY_PROJECT_DIR_BUILD = $(MY_PROJECT_ROOT)/build MY_COMMAND := $(MAKE) \ -f $(MY_PROJECT_DIR_MAKE)/$(lastword $(MAKEFILE_LIST)) \ -C $(MY_PROJECT_DIR_SOURCE) \ OBJDIR=$(MY_PROJECT_DIR_BUILD) \ ACTUALLY_BUILD=1 all : $(MY_COMMAND) upload : all $(MY_COMMAND) reset do_sam_upload % : $(MY_COMMAND) $@ else # # Arduino IDE and Arduino-Makefile paths # ARDUINO_DIR = $(HOME)/arduino ARDMK_DIR = $(HOME)/Arduino-Makefile # # Specify the custom board and its path # BOARD_TAG = gamebuino_meta_native ALTERNATE_CORE_PATH = \ $(wildcard $(HOME)/.arduino15/packages/gamebuino/hardware/samd/1.*) # # The Arduino libraries the game uses # ARDUINO_LIBS = Gamebuino_META SPI # # Now that everything is configured, include Arduino-Makefile # include $(ARDMK_DIR)/Sam.mk # # Gamebuino_META expects __SKETCH_NAME__ defined by the IDE, # and does not build well with Link Time Optimization. # CFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" -fno-lto CXXFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" -fno-lto LDFLAGS += -fno-lto endif
How Does It Work?#
- Lines 1-22 run when you call
make -f Makefile.gamebuino. From there we setup a recursive call from the source directory, which will go to:
- Lines 23-56 are the part that do the work, which is the same as the earlier example.
- I redefined the
uploadtarget on line 17, because the default Arduino-Makefile rule assumes default project paths so it does not work with this custom layout.
% :on line 20 is a last-resort target that matches any specific target and passes it to the recursive call.
Check What Platform You're Building For#
When you build the same code for multiple platforms, it's useful to distinguish between them so you can implement platform-specific features. One option is to check
__SAMD21G18A__, which is defined by both Arduino-Makefile and the official IDE when building for the Gamebuino board:
1 2 3 4 5
#ifdef __SAMD21G18A__ // Gamebuino META code #else // Code for other platforms #endif