Question
Answer and Explanation
Specifying the install name for a CMake header-only library is a bit different than for compiled libraries because header-only libraries are typically included directly in the consuming projects rather than being installed as separate artifacts. The install name, often referred to as the library name, primarily impacts how other CMake projects will use your header-only library when using CMake's find_package()
.
Here's how you manage the install name for a header-only library in CMake:
1. Define a CMake Target: Even for header-only libraries, you still define a target. It's just that this target won't have any actual source files. You'll use add_library
with the INTERFACE
keyword, which is specifically designed for header-only libraries:
add_library(MyHeaderOnlyLib INTERFACE)
- Here, MyHeaderOnlyLib
is the "install name" or the target name that consumers will use when using find_package()
or target_link_libraries()
.
2. Define the Interface Headers: You tell CMake where the public headers for your library are located using target_include_directories
with the INTERFACE
keyword:
target_include_directories(MyHeaderOnlyLib
INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
- This informs consumers of the library which directory to include to use the headers.
3. Create a Config File: The key part is creating a Config File, usually named MyHeaderOnlyLibConfig.cmake
(or MyHeaderOnlyLib-config.cmake
, note the case difference). This file is what CMake's find_package()
will use to locate the headers and information about your library. The file content should look something like this:
# MyHeaderOnlyLibConfig.cmake
include(CMakeFindDependencyMacro)
# Set the location of headers (for direct use)
set(MyHeaderOnlyLib_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/include")
# Set the library target for CMake (for use with find_package)
if(NOT TARGET MyHeaderOnlyLib::MyHeaderOnlyLib)
add_library(MyHeaderOnlyLib::MyHeaderOnlyLib INTERFACE IMPORTED)
target_include_directories(MyHeaderOnlyLib::MyHeaderOnlyLib INTERFACE "${MyHeaderOnlyLib_INCLUDE_DIRS}")
endif()
- Note that the target name MyHeaderOnlyLib::MyHeaderOnlyLib
here is a namespaced target to avoid collision ( recommended for CMake targets, though you can choose any name). This will let you use `target_link_libraries(YourTarget MyHeaderOnlyLib::MyHeaderOnlyLib)` without having to manage include directories. This is also what is used by find_package()
4. Install the Config File: You need to ensure that the config file (MyHeaderOnlyLibConfig.cmake
) is also installed during your library's installation phase. This is generally done as a part of the install
command:
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/MyHeaderOnlyLibConfig.cmake"
DESTINATION "lib/cmake/MyHeaderOnlyLib"
)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include"
DESTINATION "include"
FILES_MATCHING PATTERN ".h"
)
- The destination path for the config file is important as it should be in a location where find_package()
will look for it.
5. Using find_package
in a consumer project: Other CMake projects can now use find_package
like this:
find_package(MyHeaderOnlyLib REQUIRED)
target_link_libraries(YourTarget PRIVATE MyHeaderOnlyLib::MyHeaderOnlyLib)
When using find_package(MyHeaderOnlyLib)
, CMake will search for a file named MyHeaderOnlyLibConfig.cmake
(or MyHeaderOnlyLib-config.cmake
) in its module path, and will use this file to get the header directories.
In summary, the "install name" for a header-only library in CMake is primarily the target name, and it's defined using add_library(... INTERFACE)
. The config file and how it's installed plays a significant role in how CMake will locate your header-only library. The actual headers are simply included with their directory.