Generate archives
- Open the
library.properties
file from the root folder of your library in a text editor. - Add this line to the file (reference):
dot_a_linkage=true
- Save the file.
- In the Arduino IDE, select a target from the Tools > Board menu.
- Select File > Preferences from the Arduino IDE menus.
- Check the box next to Show verbose output during: ☐ compilation.
- Click the OK button.
- Compile any sketch that has an
#include
directive for your library.
This could just be a bare minimum sketch. For example, if the library had a headerSomeLibrary.h
:#include <SomeLibrary.h> void setup() {} void loop() {}
- After the compilation finishes, examine the contents of the black console window of the Arduino IDE window.
The first thing you need to find is the location of the temporary build folder. This should be shown in (among other places) the final command of the output.
In my case, the command looks like this:
so I know the build folder is at this path:"C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/ avr-size" -A "C:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003/PrecompiledTest.ino.elf"
C:\Users\per\AppData\Local\Temp\arduino_build_602003
- The other thing you need to find in the output is the
-mmcu
flag passed to the compiler (may be-mcpu
instead when compiling for other architectures).
In my case it was in this command:
so you can see the flag was:"C:\\Users\\per\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino5/bin/avr-gcc" -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections,--relax -mmcu=atmega2560 -o "C:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003/PrecompiledTest.ino.elf" "C:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003\\sketch\\PrecompiledTest.ino.cpp.o" "C:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003\\libraries\\PrecompiledTest\\PrecompiledTest.a" "C:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003/..\\arduino_cache_483105\\core\\core_arduino_avr_mega_cpu_atmega2560_99b4804b5450ac10a663b47fdad40a36.a" "-LC:\\Users\\per\\AppData\\Local\\Temp\\arduino_build_602003" -lm
because I was compiling for the Mega 2560-mmcu=atmega2560
- Copy the
.a
file from the<temporary build folder>/libraries/<library name>
folder to appropriate subfolder of the library, as specified here (usuallysrc/<target MCU>
).
In my case, the.a
file was at this path:
and I copied it to theC:\Users\per\AppData\Local\Temp\arduino_build_602003\libraries\PrecompiledTest\PrecompiledTest.a
libraries/PrecompiledTest/src/atmega2560
folder. - Rename the
.a
file by adding "lib
" to the start (reference).
In my case, it was renamed fromPrecompiledTest.a
tolibPrecompiledTest.a
- Repeat the above process for all other targets you want to support.
Configure library metadata
- You can now remove the source files from the library, since they are replaced by the precompiled file.
You also have the option of leaving the source files in place in order to allow compilation on demand for targets you haven't provided a pre-compiled binary for. - Open
library.properties
in a text editor. - Remove the line:
dot_a_linkage=true
- Add the
precompiled
field to thelibrary.properties
file.
Usually you will want to set this field tofull
:
However, there is another "precompiled=full
true
" configuration option used for mixed pre-compiled libraries that contain precompiled components in addition to source code that should be compiled on demand.
See the Arduino Library Specification for details.precompiled=true
- Save the file
ldflags
field
You may also find the ldflags
field of library.properties
useful.
My understanding from reading this, and my test, is that defining ldflags
is not needed in the case where you have used the expected filename for the .a
file: lib<library name>.a
, where <library name>
is the value of the library's library.properties
name
field. In the case where you need to use a different file name, then you can specify this with the ldflags
field. For example, if the library name was foo
, but the archive file name was libbar.a
, then you would need to add this line to library.properties
:
ldflags=-lbar
note that you don't specify the "lib
" or ".a
" parts of the filename in the -l
flag.
Boards platform configuration
Some Arduino boards platforms might also need adjustments to their platform.txt
configuration file in order to support precompiled libraries, as documented here.
I discovered that in my simple proof of concept test library (which does use Arduino.h
), I was able to use the stock "Arduino AVR Boards" platform version 1.8.2 without any modifications.
But this issue report indicates that might not always be so? I think it is only needed if you use the ldflags
field in library.properties
. In that case, you need to make sure platform.txt
contains two things:
-
recipe.c.combine.pattern
must contain the{compiler.libraries.ldflags}
reference and it must be in the right position in the recipe, as shown here. - This line, anywhere in
platform.txt
:
This sets a default definition of that property for cases when it is not automatically defined by the Arduino build system, which would otherwise result in a compilation failure.compiler.libraries.ldflags=
Arduino IDE support
Precompiled libraries are only supported in Arduino IDE 1.8.6 and newer, so the users of your library won't be able to use it with outdated versions of the Arduino IDE.