Unfortunately Ubuntu packages a fairly old (5.3.0) version of gcc-avr at the time of writing. Versions of gcc-avr from 8.3.0 onwards will produce significantly smaller binaries. The steps of building and installing a cutting-edge AVR toolchain on Ubuntu (tested on 20.04/WSL2 and 20.10/Baremetal) are outlined below.
Most of the procedure is loosely based on this manpage.
It's a good idea to run all of this from a folder dedicated to it.
$ mkdir -p avr_toolchain && cd avr_toolchain
Your life will be easier if you separate these tools from the rest of your stuff, else it'll bite you back at random, unless your system is dedicated to cross-compiling for AVR.
Feel free to choose a different path for this, as long as you keep it consistent while executing the build & installation process.
$ PREFIX=/usr/local/avr
$ export PREFIX
$ sudo mkdir -p $PREFIX
$ sudo chown -R "$(id -u):$(id -g)" $PREFIX
You'll want to prepend this directory to your PATH so it overrides whatever else you might already have lurking in your system.
$ PATH=$PREFIX/bin:$PATH
$ export PATH
Mind you that export statements are temporary, so once you quit the current shell session you'll have to set them again or you'll end up looking at confusing error messages (or worse).
Acquire the sources for appropriate releases of GNU binutils, gcc and avr-libc. The full lists of releases can be found at:
- binutils: http://ftp.gnu.org/gnu/binutils/
- gcc: https://ftp.mpi-inf.mpg.de/pub/gnu/mirror/gcc.gnu.org/pub/gcc/releases/
- avr-libc: http://download.savannah.gnu.org/releases/avr-libc/
Different release versions might not always be compatible with each other. This procedure has been tested using the archives shown below. If one of them is unavailable, too slow, or otherwise broken, look for a mirror at the links listed above.
$ wget -qO- http://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.gz | tar xzvf -
$ wget -qO- https://ftp.mpi-inf.mpg.de/pub/gnu/mirror/gcc.gnu.org/pub/gcc/releases/gcc-10.2.0/gcc-10.2.0.tar.gz | tar xzvf -
$ wget -qO- http://download.savannah.gnu.org/releases/avr-libc/avr-libc-2.0.0.tar.bz2 | tar xjvf -
Before continuing, you'll need a working host toolchain (i.e. the appropriate tools to build software for the system you're using right now). This includes GNU make, a compiler (preferably GCC), a linker, etc. Google is your friend. If I recall correctly, something along the lines of apt install build-essential
should get you most, if not all of the way there on Debian based distros. If you're not sure what you have or need, just continue with the process and work your way through error messages complaining about missing files until you're there.
If you're not in a hurry, it might make sense to check out the configure
scripts for each of these to see what they do and if things could perhaps be en- or disabled to better suit your use case. You can also pass optimizing compiler and linker flags to the make
invocation in each of these steps, but your mileage may vary; if all you do is compile firmware for keyboards occasionally (a comparatively trivial task) you'd unlikely gain non-negligible benefits from that, at the expense of making the toolchain build process (what you're working through right now) take quite a bit longer.
Start out by building and installing GNU binutils. It's recommended to create an output directory to not pollute the source files with build artifacts.
$ cd binutils-2.35
$ mkdir -p obj-avr && cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --disable-nls
If that worked, you can build and install it:
$ make -j$(nproc)
$ make install
Take note of how you don't need to sudo
the make install
command because you're installing into a non-system directory.
On to gcc. You'll need to fetch some prequisite packages. The GNU folks graciously provide a script to make this easy.
$ cd gcc-10.2.0
$ ./contrib/download_prerequisites
Same as above, work from a subdirectory. Compilation will take a while, so grab a cup of your favourite beverage while it's running. The following steps have only been tested with coffee and are not guaranteed to work with anything else.
$ mkdir -p obj-avr && cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++,lto --disable-nls --disable-libssp --with-dwarf2
$ make -j$(nproc)
$ make install
Compiling this with debug symbols enabled is optional but recommended.
$ cd avr-libc-2.0.0
$ mkdir -p obj-avr && cd obj-avr
$ ../configure --prefix=$PREFIX --build=`../config.guess` --host=avr --enable-debug-info=dwarf-2
$ make -j$(nproc)
$ make install
If the above completed successfully, which avr-gcc
should return the path you specified as PREFIX
and avr-gcc -v
should return the version of gcc you opted for.
Try compiling firmware for a board to make sure everything works. After that, you can permanently add the installation directory to your PATH
or assign it to QMK make
by prepending it to the command through other means (e.g. PATH=/usr/local/avr/bin:$PATH LD_LIBRARY_PATH=/usr/local/avr/lib:$LD_LIBRARY_PATH make keyboard:keymap
from the command line or a wrapping shell script).