What linkerscript does Arduino IDE use when compiling for the Arduino UNO?

  arduino, avr, c++, gcc

My ultimate goal is to convert Arduino projects (sketches) into makefile-based self-contained C/C++ projects. At first I’ll attempt to do this manually. Later on, I can hopefully automate this.

Unfortunately, I got stuck. I can’t figure out what linkerscript the avr-gcc compiler is using to link the final .elf file.

1. My setup

I’ve got an Arduino UNO R3 which is based on the ATmega328P microcontroller. I’m working in Ubuntu 20.04.1 LTS.
I installed the Arduino IDE and created a new project from:

File > Examples > 01.Basics > Blink

I saved the new project at ~/Arduino/sketch_uno_blinky/sketch_uno_blinky.ino

Finally I ticked the checkmark at:

File > Preferences > Show verbose output

such that I can see the compilation output properly.

2. Compiler output

2.1 Sketch compilation

Apparently, Arduino does some preprocessing on the sketch file and transforms it into a .cpp file. This .cpp file gets stored in a temporary folder:

/tmp/arduino_build_467402/sketch/sketch_uno_blinky.ino.cpp

Arduino then compiles it into an object file:

/tmp/arduino_build_467402/sketch/sketch_uno_blinky.ino.cpp.o

2.2 Library compilations

All library source code for this project seems to be located at <ide installation>/hardware/arduino/avr/cores/arduino/. Arduino dives into this folder and compiles the following S-, c- and cpp-files:

wiring_pulse.S
WInterrupts.c
hooks.c
wiring_shift.c
wiring_digital.c
wiring_pulse.c
wiring_analog.c
wiring.c
USBCore.cpp
CDC.cpp
HardwareSerial3.cpp
Stream.cpp
Print.cpp
HardwareSerial0.cpp
IPAddress.cpp
HardwareSerial1.cpp
Tone.cpp
PluggableUSB.cpp
HardwareSerial2.cpp
HardwareSerial.cpp
WMath.cpp
WString.cpp
abi.cpp
main.cpp
new.cpp

The resulting object files all end up in the folder /tmp/arduino_build_467402/core/. Arduino then merges them into one big archive file:

/tmp/arduino_cache_6016/core/core_arduino_avr_uno_825fad80d33b8721a4df50671a83fbdb.a

3. Linker output

Finally, Arduino links the compiled sketch against the library archive:

avr-gcc -w
        -Os
        -g
        -flto
        -fuse-linker-plugin
        -Wl,--gc-sections
        -mmcu=atmega328p
        -o /tmp/arduino_build_467402/sketch_uno_blinky.ino.elf
        /tmp/arduino_build_467402/sketch/sketch_uno_blinky.ino.cpp.o
        /tmp/arduino_build_467402/core/core.a
        -L/tmp/arduino_build_467402
        -lm

This is where I got stuck. I can’t figure out where the linkerscript is that avr-gcc uses to do the linking. I thought the -L/tmp/arduino_build_467402 might give a clue, so I searched through this folder hoping to find a linkerscript. Nothing found.

Finally, I executed the linker command (the one given above) manually and added the -v flag to generate more output. So I got the following:

Using built-in specs.

Reading specs from <tools>/../lib/gcc/avr/7.3.0/device-specs/specs-atmega328p

COLLECT_GCC=<tools>/avr-gcc

COLLECT_LTO_WRAPPER=<tools>/../libexec/gcc/avr/7.3.0/lto-wrapper

Target: avr

Configured with:
../gcc/configure --enable-fixed-point
                 --enable-languages=c,c++
                 --prefix=/home/jenkins/workspace/avr-gcc-staging/label/debian7-x86_64/objdir
                 --disable-nls
                 --disable-libssp
                 --disable-libada
                 --disable-shared
                 --with-avrlibc=yes
                 --with-dwarf2
                 --disable-doc
                 --target=avr

Thread model: single
gcc version 7.3.0 (GCC) 

COMPILER_PATH=
    <tools>/../libexec/gcc/avr/7.3.0/
    :
    <tools>/../libexec/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/

LIBRARY_PATH=
    <tools>/../lib/gcc/avr/7.3.0/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/
    :
    <tools>/../lib/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/

COLLECT_GCC_OPTIONS='-w'
                    '-Os'
                    '-g'
                    '-flto'
                    '-fuse-linker-plugin'
                    '-o'
                    '/tmp/arduino_build_467402/sketch_uno_blinky.ino.elf'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'

 <tools>/../libexec/gcc/avr/7.3.0/collect2 -plugin <tools>/../libexec/gcc/avr/7.3.0/liblto_plugin.so
                                           -plugin-opt=<tools>/../libexec/gcc/avr/7.3.0/lto-wrapper
                                           -plugin-opt=-fresolution=/tmp/ccniSjnJ.res
                                           -plugin-opt=-pass-through=-lgcc
                                           -plugin-opt=-pass-through=-lm
                                           -plugin-opt=-pass-through=-lc
                                           -plugin-opt=-pass-through=-latmega328p
                                           -flto
                                           -mavr5
                                           -Tdata 0x800100
                                           -o /tmp/arduino_build_467402/sketch_uno_blinky.ino.elf
                                           <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5/crtatmega328p.o
                                           -L/tmp/arduino_build_467402
                                           -L<tools>/../lib/gcc/avr/7.3.0/avr5
                                           -L<tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5
                                           -L<tools>/../lib/gcc/avr/7.3.0
                                           -L<tools>/../lib/gcc
                                           -L<tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib
                                           --gc-sections
                                           /tmp/arduino_build_467402/sketch/sketch_uno_blinky.ino.cpp.o
                                           /tmp/arduino_build_467402/core/core.a
                                           -lm
                                           --start-group
                                           -lgcc
                                           -lm
                                           -lc
                                           -latmega328p
                                           --end-group
<tools>/avr-gcc @/tmp/ccsz4lb1

Using built-in specs.
Reading specs from <tools>/../lib/gcc/avr/7.3.0/device-specs/specs-atmega328p
Reading specs from <tools>/../lib/gcc/avr/7.3.0/device-specs/specs-avr5

COLLECT_GCC=<tools>/avr-gcc

Target: avr
Configured with:
../gcc/configure --enable-fixed-point
                 --enable-languages=c,c++
                 --prefix=/home/jenkins/workspace/avr-gcc-staging/label/debian7-x86_64/objdir
                 --disable-nls
                 --disable-libssp
                 --disable-libada
                 --disable-shared
                 --with-avrlibc=yes
                 --with-dwarf2
                 --disable-doc
                 --target=avr

Thread model: single
gcc version 7.3.0 (GCC) 

COLLECT_GCC_OPTIONS='-c'
                    '-fmath-errno'
                    '-fsigned-zeros'
                    '-ftrapping-math'
                    '-fno-trapv'
                    '-fno-openmp'
                    '-fno-openacc'
                    '-mn-flash=1'
                    '-mmcu=avr5'
                    '-Os'
                    '-mn-flash=1'
                    '-mno-skip-bug'
                    '-fno-exceptions'
                    '-w'
                    '-Os'
                    '-g'
                    '-fuse-linker-plugin'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'
                    '-dumpdir'
                    '/tmp/arduino_build_467402/'
                    '-dumpbase'
                    'sketch_uno_blinky.ino.elf.wpa'
                    '-fltrans-output-list=/tmp/ccrGGi42.ltrans.out'
                    '-fwpa'
                    '-fresolution=/tmp/ccniSjnJ.res'
                    '-flinker-output=exec'
                    '-specs=device-specs/specs-avr5'

 <tools>/../lib/gcc/../../libexec/gcc/avr/7.3.0/lto1 -mno-skip-bug
                                                     -quiet
                                                     -dumpdir 
                                                     /tmp/arduino_build_467402/
                                                     -dumpbase sketch_uno_blinky.ino.elf.wpa
                                                     -mn-flash=1
                                                     -mmcu=avr5
                                                     -mn-flash=1
                                                     -mno-skip-bug
                                                     -mmcu=avr5
                                                     -auxbase sketch_uno_blinky.ino.cpp
                                                     -g
                                                     -Os
                                                     -Os
                                                     -w
                                                     -version
                                                     -fmath-errno
                                                     -fsigned-zeros
                                                     -ftrapping-math
                                                     -fno-trapv
                                                     -fno-openmp
                                                     -fno-openacc
                                                     -fno-exceptions
                                                     -fuse-linker-plugin
                                                     -fltrans-output-list=/tmp/ccrGGi42.ltrans.out
                                                     -fwpa
                                                     -fresolution=/tmp/ccniSjnJ.res
                                                     -flinker-output=exec @/tmp/ccL4oHh5
GNU GIMPLE (GCC) version 7.3.0 (avr)
    compiled by GNU C version 4.7.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9, isl version none

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072

GNU GIMPLE (GCC) version 7.3.0 (avr)
    compiled by GNU C version 4.7.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9, isl version none

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072

COMPILER_PATH=
    <tools>/../lib/gcc/../../libexec/gcc/avr/7.3.0/
    :
    <tools>/../lib/gcc/../../libexec/gcc/
    :
    <tools>/../libexec/gcc/avr/7.3.0/
    :
    <tools>/../libexec/gcc/avr/7.3.0/
    :
    <tools>/../libexec/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/

LIBRARY_PATH=
    <tools>/../lib/gcc/avr/7.3.0/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/
    :
    <tools>/../lib/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/

COLLECT_GCC_OPTIONS='-c'
                    '-fmath-errno'
                    '-fsigned-zeros'
                    '-ftrapping-math'
                    '-fno-trapv'
                    '-fno-openmp'
                    '-fno-openacc'
                    '-mn-flash=1'
                    '-mmcu=avr5'
                    '-Os'
                    '-mn-flash=1'
                    '-mno-skip-bug'
                    '-fno-exceptions'
                    '-w'
                    '-Os'
                    '-g'
                    '-fuse-linker-plugin'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'
                    '-dumpdir'
                    '/tmp/arduino_build_467402/'
                    '-dumpbase'
                    'sketch_uno_blinky.ino.elf.wpa'
                    '-fltrans-output-list=/tmp/ccrGGi42.ltrans.out'
                    '-fwpa'
                    '-fresolution=/tmp/ccniSjnJ.res'
                    '-flinker-output=exec'
                    '-specs=device-specs/specs-avr5'

<tools>/avr-gcc @/tmp/ccYJ3b70

Using built-in specs.

Reading specs from <tools>/../lib/gcc/avr/7.3.0/device-specs/specs-atmega328p
Reading specs from <tools>/../lib/gcc/avr/7.3.0/device-specs/specs-avr5

COLLECT_GCC=<tools>/avr-gcc

Target: avr
Configured with:
../gcc/configure --enable-fixed-point
                 --enable-languages=c,c++
                 --prefix=/home/jenkins/workspace/avr-gcc-staging/label/debian7-x86_64/objdir
                 --disable-nls
                 --disable-libssp
                 --disable-libada
                 --disable-shared
                 --with-avrlibc=yes
                 --with-dwarf2
                 --disable-doc
                 --target=avr

Thread model: single
gcc version 7.3.0 (GCC) 

COLLECT_GCC_OPTIONS='-c'
                    '-fmath-errno'
                    '-fsigned-zeros'
                    '-ftrapping-math'
                    '-fno-trapv'
                    '-fno-openmp'
                    '-fno-openacc'
                    '-mn-flash=1'
                    '-mmcu=avr5'
                    '-Os'
                    '-mn-flash=1'
                    '-mno-skip-bug'
                    '-fno-exceptions'
                    '-w'
                    '-Os'
                    '-g'
                    '-fuse-linker-plugin'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'
                    '-dumpdir'
                    '/tmp/arduino_build_467402/'
                    '-dumpbase'
                    'sketch_uno_blinky.ino.elf.ltrans0'
                    '-fltrans'
                    '-o'
                    '/tmp/ccrGGi42.ltrans0.ltrans.o'
                    '-specs=device-specs/specs-avr5'

<tools>/../lib/gcc/../../libexec/gcc/avr/7.3.0/lto1 -mno-skip-bug
                                                    -quiet
                                                    -dumpdir /tmp/arduino_build_467402/
                                                    -dumpbase sketch_uno_blinky.ino.elf.ltrans0
                                                    -mn-flash=1
                                                    -mmcu=avr5
                                                    -mn-flash=1
                                                    -mno-skip-bug
                                                    -mmcu=avr5
                                                    -auxbase-strip
                                                    /tmp/ccrGGi42.ltrans0.ltrans.o
                                                    -g
                                                    -Os
                                                    -Os
                                                    -w
                                                    -version
                                                    -fmath-errno
                                                    -fsigned-zeros
                                                    -ftrapping-math
                                                    -fno-trapv
                                                    -fno-openmp
                                                    -fno-openacc
                                                    -fno-exceptions
                                                    -fuse-linker-plugin
                                                    -fltrans
                                                    @/tmp/cc8cEWbe
                                                    -o /tmp/ccSgSYse.s
 
GNU GIMPLE (GCC) version 7.3.0 (avr)
    compiled by GNU C version 4.7.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9, isl version none
    
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072

GNU GIMPLE (GCC) version 7.3.0 (avr)
    compiled by GNU C version 4.7.2, GMP version 5.0.2, MPFR version 3.1.0, MPC version 0.9, isl version none
    
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072

COLLECT_GCC_OPTIONS='-c'
                    '-fmath-errno'
                    '-fsigned-zeros'
                    '-ftrapping-math'
                    '-fno-trapv'
                    '-fno-openmp'
                    '-fno-openacc'
                    '-mn-flash=1'
                    '-mmcu=avr5'
                    '-Os'
                    '-mn-flash=1'
                    '-mno-skip-bug'
                    '-fno-exceptions'
                    '-w'
                    '-Os'
                    '-g'
                    '-fuse-linker-plugin'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'
                    '-dumpdir'
                    '/tmp/arduino_build_467402/'
                    '-dumpbase'
                    'sketch_uno_blinky.ino.elf.ltrans0'
                    '-fltrans'
                    '-o'
                    '/tmp/ccrGGi42.ltrans0.ltrans.o'
                    '-specs=device-specs/specs-avr5'

<tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/as -mmcu=avr5
                                                    -mno-skip-bug
                                                    -o /tmp/ccrGGi42.ltrans0.ltrans.o
                                                    /tmp/ccSgSYse.s

COMPILER_PATH=
    <tools>/../lib/gcc/../../libexec/gcc/avr/7.3.0/
    :
    <tools>/../lib/gcc/../../libexec/gcc/
    :
    <tools>/../libexec/gcc/avr/7.3.0/
    :
    <tools>/../libexec/gcc/avr/7.3.0/
    :
    <tools>/../libexec/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/bin/

LIBRARY_PATH=
    <tools>/../lib/gcc/avr/7.3.0/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/avr5/
    :
    <tools>/../lib/gcc/avr/7.3.0/
    :
    <tools>/../lib/gcc/
    :
    <tools>/../lib/gcc/avr/7.3.0/../../../../avr/lib/

COLLECT_GCC_OPTIONS='-c'
                    '-fmath-errno'
                    '-fsigned-zeros'
                    '-ftrapping-math'
                    '-fno-trapv'
                    '-fno-openmp'
                    '-fno-openacc'
                    '-mn-flash=1'
                    '-mmcu=avr5'
                    '-Os'
                    '-mn-flash=1'
                    '-mno-skip-bug'
                    '-fno-exceptions'
                    '-w'
                    '-Os'
                    '-g'
                    '-fuse-linker-plugin'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'
                    '-dumpdir'
                    '/tmp/arduino_build_467402/'
                    '-dumpbase'
                    'sketch_uno_blinky.ino.elf.ltrans0'
                    '-fltrans'
                    '-o'
                    '/tmp/ccrGGi42.ltrans0.ltrans.o'
                    '-specs=device-specs/specs-avr5'

COLLECT_GCC_OPTIONS='-w'
                    '-Os'
                    '-g'
                    '-flto'
                    '-fuse-linker-plugin'
                    '-o'
                    '/tmp/arduino_build_467402/sketch_uno_blinky.ino.elf'
                    '-L/tmp/arduino_build_467402'
                    '-v'
                    '-specs=device-specs/specs-atmega328p'
                    '-mmcu=avr5'

Please note that this is not the raw output. I’ve formatted the output a bit (adding newlines and spaces) to make it more human-friendly. I’ve also replaced the following path:

/home/kristof/Software/arduino-1.8.13/hardware/tools/avr/bin/

with this string:

<tools>

Even after analyzing this linker output, I can’t find what linkerscript is being used. Please reach out if you know.

Source: Windows Questions C++

LEAVE A COMMENT