Reputation: 942
I had a project which uses CMake as build tool and made a simple template for me and my colleagues to use. As I searched for best and easy to use practices online, I've came across different approaches to make a library.
In this template, I've listed header files and source files in two separate variables, and I'm not passing the headers to add_library
command - just sources. And then I use set_target_properties
with PUBLIC_HEADER
variable to give the header-file list.
So far it seems to work, but I wonder if I'm making thing unnecessarily complex. Some people online give header files to add_library command as well and doesn't even use set_target_properties
and such.
In short:
Should we include header files to add_library
or should we not (as a best practice)? And impacts of the two usage.
What is purpose being served by adding headers in the add_library/add_executable? As they seem working even without it (seems forward declaration and symbols only). confirm on understanding please.
Here is the template I'm talking about:
cmake_minimum_required(VERSION 3.1.0)
project(lae CXX C)
set(CMAKE_CXX_STANDARD 14)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
)
set(SOURCE_FILES
...
)
set(HEADER_FILES
...
)
set( PRIVATE_HEADER_FILES
...
)
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} )
set( REQUIRED_LIBRARIES
...
)
target_link_libraries(${PROJECT_NAME} ${REQUIRED_LIBRARIES} )
SET_TARGET_PROPERTIES(
${PROJECT_NAME}
PROPERTIES
FRAMEWORK ON
SOVERSION 0
VERSION 0.1.0
PUBLIC_HEADER "${HEADER_FILES}"
PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
ARCHIVE_OUTPUT_DIRECTORY "lib"
LIBRARY_OUTPUT_DIRECTORY "lib"
OUTPUT_NAME ${PROJECT_NAME}
)
Upvotes: 57
Views: 43104
Reputation: 50205
For add_library
and add_executable
, it can cause CMake to generate certain IDE-integrated buildsystems like Visual Studio to display those header files in a perhaps more-desirable way, but to my knowledge, that's it. It doesn't have impact on whether the buildsystem itself functions properly or not with respect to doing builds. Whether you do this or not is up to you. I'm not aware of any clear downsides to specifying headers in add_library
or add_executable
.
Do note that CMake does build in some (very very basic) heuristics to detect headers associated to source files, so it can sometimes handle this for your without you needing to do anything (see also my answer to How to properly add include directories with CMake).
If you have cmake_minimum_require(VERSION 3.23)
and want to do something that has possible usefulness beyond that, take a look at the target_sources(... FILE_SET HEADERS ...)
command, which can have usefulness for doing installs of public headers for targets.
The PUBLIC_HEADER
target property is to specify files in a FRAMEWORK
shared library target (a thing for building for macOS) to be put in the Headers/
directory of the framework folder. On non-Apple platforms, you can also use this target property with the PUBLIC_HEADERS
option in the install(TARGETS ...)
command (some similarities to the FILE_SET
thing stated above).
Upvotes: 4
Reputation: 5925
In our projects we use a "simple" way of yours - add_library
with both headers and sources.
If you add only sources, then you won't see headers in IDE-generated project.
However, when installing, we have to do it like that, using two install
commands:
install(TARGETS library_name
LIBRARY DESTINATION lib)
install(FILES ${PUBLIC_HEADERS}
DESTINATION include/library_name)
If you want to do it as a single command, you can use set_target_properties
with PUBLIC_HEADER
, as you suggested.
Then, this kind of install
is possible:
install(TARGETS library_name
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include/library_name)
Choose the one you like the most and stick to it.
Upvotes: 28