Open the library.properties file that is in the root folder of your library in a text editor (
reference).
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.
File > Preferences
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.
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:
"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"
so I know the build folder is at:
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:
"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
so you can see the flag was:
-mmcu=atmega2560
because I was compiling for the Mega 2560
Copy the .a file from the {temporary build folder}/libraries/{library name} folder to the src/{target MCU} subfolder of your library (
reference). In my case, the .a file was at:
C:\Users\per\AppData\Local\Temp\arduino_build_602003\libraries\PrecompiledTest\PrecompiledTest.a
and I copied it to the libraries/PrecompiledTest/src/atmega2560 folder.
Rename the .a file, appending "lib" to the start of the name (
reference). In my case, it was renamed to libPrecompiledTest.a
Repeat the above process for all other targets you want to support.
You can now remove the source files from the library, since they are replaced by the precompiled file.
Open library.properties in a text editor.
Remove the line:
dot_a_linkage=true
Add the line:
precompiled=true
Save the file
That's all you need to do for your library. As for the platform.txt file, 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 1.8.2 without any modifications. But
this issue report indicates this 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 {compiler.libraries.ldflags} and it must be in the right position in the recipe, as shown in
https://github.com/arduino/ArduinoCore-avr/pull/52/files.This line, anywhere in platform.txt:
compiler.libraries.ldflags=
which sets a default definition of that property for cases when it is not automatically defined by arduino-builder. Otherwise it will result in compilation failures in those situations.
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.
Another thing to note is that 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 an outdated version of the Arduino IDE.