www.alxm.org

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!

Contents

Setup#

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:

*Board URL is https://lab.gamebuino.com/arduino/package_gamebuino_index.json

Test Your Setup#

Test that everything is working by building one of the example sketches:

We will come back to this sketch later, and build it with a Makefile from its source folder instead.

Install Arduino-Makefile#

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.

1
2
$ 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:

1
$ sudo apt install python-serial

Build with Make#

Write a Project Makefile#

Let's go back to the example sketch:

1
$ 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#

Recursive Makefile#

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

To build MyProject/build/gamebuino/a_Hello.bin, I'd like to just do this:

1
2
$ 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:

1
2
$ 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?#

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