cmake

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}
)

Solution

  • 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.