Reason: In an embedded target, I need to highly taylor the static library for the end application.
A classic example is found in FreeRTOS
The specific file is: FreeRTOSConfig.h
A link to one example is here:
(Another example is LWIP, it uses the file: “lwipopts.h”)
The intent is each application provides this TAYLORING header file so it can taylor the library to the specific needs of the application.
In my case I have 7 applications (across 2 CPU cores and 7 boards) - each has a different tayloring header file for FreeRTOS and LWIP.
I want to build the “libFreeRTOS” via “add_lib…” Each applciation toplevel CMakeLists.txt would/should just “add_subdirectory” - for the LibFreeRTOS.
But the method Cmake sort of desires is the LibFreeRTOS is very self contained, ie: ALL Headers it requires are local to the project which is not true for me It depends on the board I am targeting.
Any suggstions on how I should handle this in the CMAKE Way?
Rather then my bastardized way of jamming an include path down the tools mouth?
NOTE: In addition to a standard #include - for compile time configuration, another package makes use of the GCC option: ‘–include’ - which forces the compiler to read a specific file in front of all other files it compiles, so I need to have a means to supply BOTH to the libraries being built.
Well, yes, but there’s no such thing as a static library so self-contained that it doesn’t require header files. They’re how a C/C++ library defines its API, both during its own build and for external users of the library. A library (static or shared) in a C/C++ program consists of the binary compiled object archive and the corresponding header files.
Yeah, FreeRTOS are doing some maybe-“clever” things there, with that customization-by-preconfigured-header thing. Still, if it works, then great.
Reordering two of your following statements…
That’s not a requirement at all. All CMake, or any other build system, needs is for the necessary headers be found in the include paths that it passes to the compiler when building the library. Your own code then needs to be built with those same include paths.
That’s certainly a possibility, though the need for a configuration header complicates things a tiny bit. Still, it’s not an unworkable goal. There are a couple of ways you could go:
Set up the CMakeLists.txt inside the libFreeRTOS subdirectory to expect a variable, say FREERTOS_CONFIG_DIR, that points to the location of the configFreeRTOS.h file that should be used for the particular build. Have it add that location to the include paths when building the library. Your outer application CMakeLists.txt can provide that variable, or you can set it on the cmake command line when configuring the project by adding -DFREERTOS_CONFIG_DIR=<path> to the arguments.
add_library(freertos STATIC ...)
target_include_directories(freertos PUBLIC
${FREERTOS_CONFIG_DIR}
)
Any code in the same project that links with the library should pick up the same include path.
# in the parent directory
# If you want to support -DFREERTOS_CONFIG_DIR as a
# build option, you can set a _default_ cache variable here
set(FREERTOS_CONFIG_DIR
"${CMAKE_CURRENT_SOURCE_DIR}/src/boardA_config"
CACHE STRING "Location of configFreeRTOS.h")
)
add_subdirectory(libFreeRTOS)
target_link_libraries(myapp PRIVATE freertos)
If you find the include dir isn’t propagating via target_link_libraries, just set the same include path for the application code:
target_include_directories(myapp PUBLIC
${FREERTOS_CONFIG_DIR}
)
…Because you’re setting FREERTOS_CONFIG_DIR as a CACHE variable, but notFORCE-ing it, a CMake command line -DFREERTOS_CONFIG_DIR= argument will override the value above. That set() command gets skipped if the CACHE variable already has a value supplied by the user.
Or, you can make a copy of the libFreeRTOS source directory, place the specific configFreeRTOS.h you need inside it, and have the library pick up the include from inside its own source dir. That seems more like what the FreeRTOS team is expecting, that each different configuration will be integrated into its own copy of the library sources. Especially since the header has to be modified before it can be used, making it plug-and-play switchable really doesn’t seem to be a priority. Having a customized source tree definitely makes the build easier, at a sacrifice of a little disk space/redundancy.
To do it that way, when you wanted to build a project that uses libFreeRTOS configured for BoardA, you’d copy the libFreeRTOS directory to libFreeRTOS_BoardA, place the appropriate configuration header inside, customize it as needed, and then add_subdirectory(libFreeRTOS_BoardA) in your project’s outer CMakeLists.txt to build it with that configuration of the static library.
Everything else is pretty much the same. You’d still want the location of the header (in this case, inside the libFreeRTOS_BoardA dir) to be one of the PUBLIC include directories for the target: