Building firmware on Gentoo, the hard way

I know all of this is Doing It Wrong™ but I’d like to see how far I can get with it anyway. I’m only about 75% of the way to doing a successful build I got it to work, see below, but hopefully someone will find my rubber duck rambling useful.

Okay, so the distro has a pre-existing Arduino package (good!). But it’s 1.0.5, which is incredibly ancient - Kaleidoscope needs 1.6.10 or higher. But I’m in luck because people have already been working on a 1.8.5 package and it’s already available. So I’ve installed that and now have a generic AVR cross-compile toolchain set up, the Arduino IDE runs too but I’ll ignore that for the time being.

Let’s try to build the keyboard firmware:

cd kaleidoscope/Kaleidoscope/

# BOARD_HARDWARE_PATH="/home/ant/Arduino/hardware" /home/ant/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope/bin//kaleidoscope-builder build-all
# Building output/AppSwitcher/AppSwitcher (0.0.1-gfe71) ...
# /home/ant/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope/bin//kaleidoscope-builder: line 134: /usr/local/arduino/arduino-builder: No such file or directory
# make: *** [/home/ant/Arduino/hardware/keyboardio/avr/build-tools/makefiles// build-all] Error 127

Right, that won’t work because the build script assumes I did the sensible thing and followed the instructions. I can fix most of that by telling it where the binaries really live:

cat > ~/Arduino/rc
export ARDUINO_PATH="/usr/share/arduino"
export AVR_SIZE="/usr/bin/avr-size"
export AVR_NM="/usr/bin/avr-nm"
export AVR_OBJDUMP="/usr/bin/avr-objdump"
export AVRDUDE="/usr/bin/avrdude"
export AVRDUDE_CONF="/etc/avrdude.conf"
export ARDUINO_TOOLS_PATH="/usr/bin/"
source ~/Arduino/rc

That gets me a different error, at least:

# Building output/AppSwitcher/AppSwitcher (0.0.1-gfe71) ...
# open /usr/share/arduino/tools-builder: no such file or directory
# make: *** [/home/ant/Arduino/hardware/keyboardio/avr/build-tools/makefiles// build-all] Error 1

That’s coming from the -tools "${ARDUINO_PATH}/tools-builder" in bin/kaleidoscope-builder. But I don’t have/need that folder (all my tools are in $PATH already).

What happens if I just delete the line entirely (from the repo I’m in and the other copy under ~/Arduino)? This:

# Building output/AppSwitcher/AppSwitcher (0.0.1-gfe71-dirty) ...
# fork/exec /bin/avr-g++: no such file or directory

Time to figure out where that’s coming from…

ack 'avr-g\+\+' ~/kaleidoscope/
# Arduino-Boards/platform.txt
# 27:compiler.cpp.cmd=avr-g++

ack -o '.*compiler.cpp.cmd' ~/kaleidoscope/
# Arduino-Boards/platform.txt
# 27:compiler.cpp.cmd
# 57:recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd
# 86:recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd
# 89:recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd

ack 'compiler.path=' ~/kaleidoscope/
# Arduino-Boards/platform.txt
# 21:compiler.path={}/bin/

That leads me back to ./etc/kaleidoscope-builder.conf. I needed to set another thing:

echo 'export AVR_GCC_PREFIX="/usr"' >> ~/Arduino/rc && source ~/Arduino/rc

(and then a slight half hour detour because Gentoo doesn’t install avr-g++ by default, oops)

# Building output/AppSwitcher/AppSwitcher (0.0.1-gfe71-dirty) ...
# In file included from /home/ant/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-Macros/src/Kaleidoscope-Macros.h:6:
# ,
#                  from /tmp/tmp.waMDUiSTff/sketch/Macros.h:22,
#                  from /tmp/tmp.waMDUiSTff/sketch/Macros.cpp:24:
# /tmp/tmp.waMDUiSTff/sketch/Macros.cpp: In function ‘const macro_t* macroAppSwitch(uint8_t)’:
# /home/ant/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope-Macros/src/MacroSteps.h:21:43: error: variable ‘__m’ with
# dynamic initialization put into program memory area
#  #define MACRO(...) ({static const macro_t __m[] PROGMEM = { __VA_ARGS__, MACRO_ACTION_END }; &__m[0]; })
#                                            ^
# /tmp/tmp.waMDUiSTff/sketch/Macros.cpp:38:12: note: in expansion of macro ‘MACRO’
#      return MACRO(Dr(mod), D(Tab));
#             ^~~~~
# (...bunch more lines like this...)
# exit status 1
# make: *** [/home/ant/Arduino/hardware/keyboardio/avr/build-tools/makefiles// build-all] Error 1

A scary-sounding GCC error! At least we’re getting somewhere interesting now, I think I’ve solved most of the self-inflicted environment problems, and this looks like actual bug report territory… so I’ll come back when I make more progress.

1 Like

After re-reading the instructions, it turns out they’ve changed since I began attempting this (that’s what I get for procrastinating on it so long). It originally only mentioned the Kaleidoscope code.

So I tried building Model01-Firmware instead and that went much better:

# BOARD_HARDWARE_PATH="/home/ant/Arduino/hardware" /home/ant/Arduino/hardware/keyboardio/avr/libraries/Kaleidoscope/bin//kaleidoscope-builder build-all
# Building output/Model01-Firmware/Model01-Firmware (0.0.0-gv1.22-3-gb745) ...
# /home/ant/Arduino/hardware/keyboardio/avr/libraries/KeyboardioScanner/twi.c: In function ‘__vector_36’:
# /home/ant/Arduino/hardware/keyboardio/avr/libraries/KeyboardioScanner/twi.c:446:47: warning: this statement may fall through [-Wimplicit-fallthrough=]
#      twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
#                                                ^
# /home/ant/Arduino/hardware/keyboardio/avr/libraries/KeyboardioScanner/twi.c:447:3: note: here
#    case TW_MR_SLA_ACK:  // address sent, ack received
#    ^~~~
# - Size: firmware/Model01-Firmware/Model01-Firmware-0.0.0-gv1.22-3-gb745.elf
# /usr/bin/avr-size: invalid option -- 'C'
# Usage: /usr/bin/avr-size [option(s)] [file(s)]
# awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
# make: *** [/home/ant/Arduino/hardware/keyboardio/avr/build-tools/makefiles// build-all] Error 2

Despite the error, I compiled a firmware file! It just errors out because (I’m guessing) Arduino bundles a completely different size program to the standard one. Let’s hack up bin/kaleidoscope-builder again so it runs…

--- a/bin/kaleidoscope-builder
+++ b/bin/kaleidoscope-builder
@@ -33,11 +33,11 @@ firmware_size () {

-    output="$($@ | grep "\\(Program\\|Data\\):" | sed -e 's,^,  - ,' && echo)"
+    output=$("${AVR_SIZE}" "${ELF_FILE_PATH}")

-    PROGSIZE="$(echo "${output}" | grep Program: | cut -d: -f2 | awk '{print $1}')"
+    PROGSIZE=$(echo "${output}" | awk 'NR==2 {print $4}')

     PERCENT="$(echo ${PROGSIZE} ${MAX_PROG_SIZE} | awk "{ printf \"%02.01f\", \$1 / \$2 * 100 }")"

-    echo "${output}" | sed -e "s/\(Program:.*\)(\([0-9\.]*%\) Full)/\1(${PERCENT}% Full)/"
+    echo "${PROGSIZE} (${PERCENT}% Full)"

Looks reasonable:

- Size: firmware/Model01-Firmware/Model01-Firmware-0.0.0-gv1.22-3-gb745.elf
20981 (73.2% Full)

Run make flash and…

Keyboardio Model 01 - Kaleidoscope locally built

It works!


I see the same absence of tools-builder when installing Arduino from packages on openSUSE Leap 42.3. Can @jesse or anyone comment whether this is really needed? Because this thread suggests it is not.

I did indeed; many thanks! I’ve started my own rubber duck thread here: Building firmware on openSUSE, the hard way