www.alxm.org

Gamebuino META Makefile

(Updated Sep 18, 2019 after the big Arduino SAMD update)

This is something I wanted to get going for a while, build my Gamebuino games with make from the command line instead of the Arduino IDE. 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 Java application to start, and greater control over build settings.

I ran these steps on 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!


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, launch the Arduino IDE and:

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

We'll 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 doesn't 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

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
# 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 = \
    $(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

# The META lib expects __SKETCH_NAME__ to be defined,
# and doesn't 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
$ 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: Try building with make -j for even faster parallel builds that take advantage of your multi-core computer!


Customize the Project

By default, the Arduino project is structured like this:

1
2
3
4
5
6
7
MyProject/
└── a_Hello/
    ├── a_Hello-build-gamebuino_meta_native/
    │   └── # The Gamebuino program .BIN and other build files# are placed in this sub-folder by Arduino-Makefile
    ├── 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 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/
│   │   └── # Game.bin and other build-generated files
│   ├── windows/
│   │   └── # Game.exe and other build-generated files
│   └── ...
└── make/
    ├── Makefile.gamebuino
    ├── Makefile.linux
    ├── Makefile.windows
    └── ...

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

1
2
$ cd MyProject/make/
$ make -f Makefile.gamebuino

There's one problem though: Arduino-Makefile expects you to run this command from MyProject/a_Hello instead of MyProject/make. One workaround is to build like this instead:

1
2
$ cd MyProject/a_Hello/
$ make -f ../make/Makefile.gamebuino

But this is inconvenient to do every time, and is inconsistent to how I build my games for every other platform. Instead, I rewrote the Makefile to set up the correct paths, then call itself recursively as if 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
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)

% :
    $(MY_COMMAND) $@

else

# 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 = \
    $(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

# The META lib expects __SKETCH_NAME__ to be defined,
# and doesn't 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?

The Makefile is split in two parts that never run at the same time:

  1. Lines 1-20 run when you call make. There we set up for a recursive call to:
  2. Lines 20-40, the part that does the actual work, which is same as the last example.

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 if __SAMD21G18A__ is defined, which is set 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