Ahmet Ipkin
Ahmet Ipkin

Reputation: 942

Why add header files into the add_library/add_executable commands in CMake?

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:

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

Answers (2)

starball
starball

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

dreamzor
dreamzor

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

Related Questions