Gamebuino META Makefile
This is something I wanted to get going for a while: build my Gamebuino games with a Makefile from the command line, instead of with the Arduino IDE. I've already been using an external editor to write the code, so why not drop the IDE altogether? This was a breeze thanks to the Arduino-Makefile project.
The advantages of bypassing the IDE include much faster build times, no more waiting for the application to start, and greater control over build settings.
I ran these steps on Linux Mint 18.3 and 19.1 with the current 64bit Arduino 1.8.x from the Arduino website. Arduino-Makefile is compatible with Windows and Mac too, though!
Setup for Gamebuino Development
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, the outline is:
- Install the Arduino IDE, then launch it and:
- Install the Arduino SAMD (ARM) boards package
- Install the Gamebuino META board package
- Install the Gamebuino META library
Test that everything is working by building one of the example sketches:
- Open the IDE, and from the top menu:
- File > Examples > Examples from Custom Libraries: Gamebuino META > Basics > Hello
- Sketch > Verify/Compile, Upload
We'll come back to this sketch later, and build it with a Makefile instead.
I installed the latest Arduino-Makefile from the project's Git repo, which has support for ARM-based devices like the Arduino Zero or Gamebuino META.
$ cd ~ $ git clone https://github.com/sudar/Arduino-Makefile
Write a Project Makefile
Let's build the first example sketch from the Gamebuino library:
$ 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
# Where you unzipped the Arduino IDE and cloned Arduino-Makefile ARDUINO_DIR = $(HOME)/arduino ARDMK_DIR = $(HOME)/Arduino-Makefile # Specify the custom Gamebuino board and where it's installed BOARD_TAG = gamebuino_meta_native ALTERNATE_CORE_PATH = \ $(HOME)/.arduino15/packages/gamebuino/hardware/samd/1.2.1 # The Arduino libraries the game uses ARDUINO_LIBS = Gamebuino_META SPI # The META lib expects __SKETCH_NAME__ to be defined CFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" CXXFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" # Now that everything is configured, include Arduino-Makefile include $(ARDMK_DIR)/Sam.mk
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
$ cd ~/Arduino/libraries/Gamebuino_META/examples/1.Basics/a_Hello # Check that the Makefile you wrote is there $ ls a_Hello.ino Makefile # Build project and flash BIN to device $ make $ make upload
PS: Build with
make -j for even faster builds that take advantage of your multi-core computer.
Customize the Project
By default, the project is structured like this:
1 2 3 4 5 6
MyProject/ ┗━ a_Hello/ ┣━ a_Hello-build-gamebuino_meta_native/ ┃ ┗━ # Gamebuino .BIN file and other build-generated files ┣━ a_Hello.ino ┗━ Makefile
However, I build my games for multiple platforms, not just Gamebuino, and I like keeping the source code, Makefiles, and build-generated objects in separate non-nested folders, like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
MyProject/ ┣━ a_Hello/ ┃ ┗━ a_Hello.ino ┣━ build/ ┃ ┣━ gamebuino/ ┃ ┃ ┗━ # Game.bin file, and other build-generated files ┃ ┣━ windows/ ┃ ┃ ┗━ # Game.exe file, and other build-generated files ┃ ┗━ ... ┗━ make/ ┣━ Makefile.gamebuino ┣━ Makefile.linux ┣━ Makefile.windows ┗━ ...
To build Game.bin, I'd like to be able to do this:
1 2 3 4 5 6 7 8 9 10
$ cd path/to/MyProject/ $ ls a_Hello build make $ ls make/ Makefile.gamebuino Makefile.linux Makefile.windows ... $ cd make/ $ make -f Makefile.gamebuino
There's a little problem though: Arduino-Makefile expects Makefile.gamebuino to be in MyProject/a_Hello instead of MyProject/make, and also that you call it from there. This is what I wrote to work around this, lines
1-32 are new:
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
# # Start project config # # Relative to this Makefile's location (and where it's called from) MY_PROJECT_ROOT := $(realpath ..) MY_MAKE_DIR = $(MY_PROJECT_ROOT)/make MY_SOURCE_DIR = $(MY_PROJECT_ROOT)/a_Hello MY_BUILD_DIR = $(MY_PROJECT_ROOT)/a_Hello_build # # End project config # ifndef ACTUALLY_BUILD MAKE_COMMAND := $(MAKE) \ -C $(MY_SOURCE_DIR) \ -f $(MY_MAKE_DIR)/$(lastword $(MAKEFILE_LIST)) \ ACTUALLY_BUILD=1 all : $(MAKE_COMMAND) all clean : $(MAKE_COMMAND) clean upload : $(MAKE_COMMAND) upload else # Where to place the .BIN file and build object files OBJDIR = $(MY_BUILD_DIR) # Where you unzipped the Arduino IDE and cloned Arduino-Makefile ARDUINO_DIR = /opt/arduino ARDMK_DIR = /opt/Arduino-Makefile # Specify the custom Gamebuino board and where it's installed BOARD_TAG = gamebuino_meta_native ALTERNATE_CORE_PATH = \ $(HOME)/.arduino15/packages/gamebuino/hardware/samd/1.2.1 # Libraries the game uses ARDUINO_LIBS = Gamebuino_META SPI # The META lib expects __SKETCH_NAME__ to be defined CFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" CXXFLAGS += -D__SKETCH_NAME__=\"$(TARGET).ino\" # Now that everything is configured, include Arduino-Makefile include $(ARDMK_DIR)/Sam.mk endif
How Does It Work?
When you run it with
make -f Makefile.gamebuino, it takes the branch at line
16, which handles three rules from Arduino-Makefile. Each of those rules call the makefile again recursively.
When it runs recursively, it takes the branch at line
32, where it configures and includes Arduino-Makefile as usual, but as if called from MyProject/a_Hello instead of MyProject/make.
Check What Platform You're Building For
When a code base builds for multiple platforms, it's useful to distinguish between them so you can implement platform-specific features. One option is to check if
__SAMD21G18A__ is defined, which is set by both Arduino-Makefile and the official IDE:
1 2 3 4 5
#ifdef __SAMD21G18A__ // Gamebuino META code #else // Code for other platforms #endif