-
Notifications
You must be signed in to change notification settings - Fork 39
Libraries
One of Arduino's most important features, as with any development system, are libraries. Arduino has 3 different types of libraries:
-
Built-in Libraries - Libraries included as part of the SDK or a custom platform.
These libraries conform to a certain format/standard determined by Arduino. For that reason they're also called "Arduino Libraries" in the Arduino-CMake terminology.
Besides, they consist only of sources - There are no pre-built binaries whatsoever. -
3rd Party Libraries - Libraries that conform to the Arduino standard, but are not part of the SDK.
These must include thelibrary.properties
file under their root directory and provide sources.
These libraries are usually located under Arduino IDE's Sketchbook Path if they were downloaded with the Library Manager.
These libraries can also be called "Arduino Libraries". -
User Libraries - Libraries that don't conform to the Arduino standard.
These libraries should be architecture and OS agnostic, and hopefully restrain from any heap-oriented code (such asmalloc
). They should also provide sources instead of pre-built binaries.
Some of you have already noticed that Arduino-CMake takes an approach similar to CMake itself regarding the targets API, that is of course to ease the use of the framework.
Libraries are no different. How?
In general, to use a certain library in your CMake project you must follow the following procedure:
- Either find the library or create it yourself.
Finding a library usually means finding a pre-built binary matching the requirements of the host OS. - Link the library target to some other target.
We've emphasized usually because as described earlier, Arduino libraries are almost always unbuilt sources. In our case, the library target will always be created and built by the project itself.
Arduino-CMake takes a similar approach.
The following passages relate to the different types of libraries and how to use them:
These libraries have to be found at first, then linked to another target, preferably the executable target.
To find a library, one should call the find_arduino_library
function. It accepts the following parameters:
Order | Name | Description | Required? |
---|---|---|---|
1st | _target_name | Library's target name as it will be registered by CMake. | Yes |
2nd | _library_name | Name of the library to search for. This is actually the name of the library's root directory. Name can be case-insensitive when searching Built-in Libraries, must be case-sensitive when searching 3rd Party libraries. |
Yes |
3rd | _board_id | Hardware Board's ID as retrieved by the get_board_id function. |
Yes |
- | 3RD_PARTY | Whether the searched library should be treated as a 3rd Party library | No |
Then, to link it, one would call the link_arduino_library
function. It accepts the following parameters:
Order | Name | Description |
---|---|---|
1st | _target_name | Name of the target to link to, usually an executable created with add_arduino_executable
|
2nd | _library_target_name | Name of a library target. If it's an Arduino Library, it's the name found earlier with find_arduino_library . Otherwise, it's the target created with CMake's add_library . |
3rd | _board_id | Hardware Board's ID as retrieved by the get_board_id function. |
The following example shows how the Stepper, Servo and Ethernet libraries are included in a project:
find_arduino_library(stepper_lib Stepper ${board_id})
link_arduino_library(my_target stepper_lib ${board_id})
find_arduino_library(servo_lib Servo ${board_id})
link_arduino_library(my_target servo_lib ${board_id})
find_arduino_library(ethernet_lib Ethernet ${board_id})
link_arduino_library(my_target ethernet_lib ${board_id})
Note that the example above assumes the my_target
target has already been created earlier.
Also, board's ID has been retrieved as well.
As well as Built-in Libraries, these should be found first and then linked to another target.
However, they can also be stored inside Arduino IDE's Sketchbook Location, controlled by the ARDUINO_CMAKE_SKETCHBOOK_PATH
variable.
By default this variable is automatically set to the location configured in Arduino IDE, however, this option could be turned off by setting the option AUTO_SET_SKETCHBOOK_PATH
to OFF
.
The ARDUINO_CMAKE_SKETCHBOOK_PATH
variable could then be passed a custom location, and that would be used to find 3rd Party libraries in instead.
The Arduino-CMake framework renames every given Arduino-Library name to an Arduino-Compliant name, which is PascalCase
.
However, 3rd Party libraries don't always conform to this naming standard (e.g the Adafruit_NeoPixel library), which creates an invalid symbol to search for the framework.
In order to avoid this behavior, one should pass the 3RD_PARTY
option to the find_arduino_library
function.
A user library's sources could be located anywhere in the host system, without any constraints.
It is the user's responsibility to "fond" them and pass their paths to the framework.
It's considered good practice to keep a user library's sources under the project's scope, especially if that library is created solely for the project at hand. It also makes it easy to "find" it.
As explained above, the library isn't found like an Arduino Library, thus no library target is magically created by some search process. Instead, the library should be created manually.
Creating a library target is really straightforward since it requires just the CMake library API!
To create a library, one would call the add_library
function.
Since the library is manually created using CMake's API, it also requires the user to manually specify include directories, so that other targets linking the library will have access to its' headers.
This is done by calling the target_include_directories
function, passing the name of the library target created earlier with add_library
, a PUBLIC
scope (So it will have effect during linkage) and the header directories themselves.
e.g target_include_directories(my_library_target PUBLIC include)
where include
is the directory containing all public headers.
At last, the library target should be linked to an existing target, just as you would do with an Arduino library.
The following is a list of common and recommended places where user libraries should be stored:
-
Inside the project's root directory, under a sub-directory named after the library.
Example:|-Project Root |-Library |-include |-Library.h |-src |-Library.c
-
Inside the project's root directory, under a sub-directory named dependencies where all other user libraries are located.
Note: This is recommended only for 3rd party user libraries, i.e. libraries that weren't created by the user itself.
The following example shows how a user library named Robotics is included in the project:
set(Robotics_lib_path ${CMAKE_SOURCE_DIR}/dependencies/Robotics-1.2)
add_library(Robotics_lib STATIC ${Robotics_lib_path}/src/Robotics.c)
target_include_directories(Robotics_lib PUBLIC ${Robotics_lib_path}/include)
link_arduino_library(my_target Robotics_lib ${board_id})
Where ${CMAKE_SOURCE_DIR}
is the parent directory of the project's main CMakeLists.txt
file.
The directory structure of the example is as follows:
|-Project Root
|-dependencies
|-include
|-Robotics.h
|-src
|-Robotics.c
|-src
|-CMakeLists.txt
Note that the example above assumes the my_target
target has already been created earlier.
Also, board's ID has been retrieved as well.