How to configure CMakeLists.txt to install public headers of a shared library?

我是研究僧i 提交于 2020-04-10 09:13:20

问题


I want to use cmake to install my library edv but when I execute:

cmake --build . --target install

It installs but it only creates the bin/edv.dll and lib/ < empty >. How can I make cmake to install the EDV_PUBLIC_INCLUDE_DIRECTORIES inside an include/... ?

Here's my CMakeLists.txt:

cmake_minimum_required(VERSION 3.12)

project(edv)

# include PUBLIC directories
set(EDV_PUBLIC_INCLUDE_DIRECTORIES      include/ )

set(EDV_PRIVATE_INCLUDE_DIRECTORIES     src/   )

# Edv source files list
file(GLOB_RECURSE EDV_SOURCE_FILES "src/*.cpp" "src/*.hpp*")


# build the library
add_library(${PROJECT_NAME} SHARED ${EDV_SOURCE_FILES} )

target_include_directories(${PROJECT_NAME} PUBLIC ${EDV_PUBLIC_INCLUDE_DIRECTORIES})
target_include_directories(${PROJECT_NAME} PRIVATE ${EDV_PRIVATE_INCLUDE_DIRECTORIES})

install (TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    PUBLIC_HEADER DESTINATION include
)

回答1:


CMake cannot deduce the set of header files to be installed from the target. This makes sense, as the target may contain both private and public header files, but CMake does not differentiate between those. As a consequence, you have to list the header files explicitly in an INSTALL(FILES ...) command:

install(FILES ${MY_HEADER_FILES} DESTINATION include)

The PUBLIC_HEADER field that you stumbled upon is related to the OSX framework mechanism, which is its very own can of worms. I suggest you stay clear of it, unless you actually want to deploy your library as a .framework on OSX.

Take special note of the INCLUDES DESTINATION option to the INSTALL(TARGET ...) command. While this does not actually copy any files itself, it allows the include directory to be added to the imported target provided by the config package script automatically. If you intend to provide a package config script to your users (which you probably should, at least if you expect your users to also use CMake), you probably want to set this option.

Since the install mechanism is quite complicated overall, I have a small github project of mine where you can observe all the elements in action.




回答2:


To install all headers present in the ./include folder, all you need to do is:

  • set a list with all the header files you want to install (i.e. define EDV_INCLUDE_FILES),

  • set the target property PUBLIC_HEADER with all those header files,

  • set the PUBLIC_HEADER argument in install(TARGETS ...) with the installation directory.

This method is also the basis for CMake's support of macOS frameworks.

I've updated the example above with the settings to install the project's public headers in ./include in the project's target output directory. Caveat: I haven't personally tested the project definition, thus it may require some minor tweaks to work.

cmake_minimum_required(VERSION 3.12)

project(edv)

# include PUBLIC directories
set(EDV_PUBLIC_INCLUDE_DIRECTORIES      include/ )

set(EDV_PRIVATE_INCLUDE_DIRECTORIES     src/   )

# Edv source files list
file(GLOB_RECURSE EDV_SOURCE_FILES "src/*.cpp" "src/*.hpp*")

file(GLOB_RECURSE EDV_INCLUDE_FILES "include/*.hpp*")

# build the library
add_library(${PROJECT_NAME} SHARED ${EDV_INCLUDE_FILES} ${EDV_SOURCE_FILES} )

target_include_directories(${PROJECT_NAME} PUBLIC ${EDV_PUBLIC_INCLUDE_DIRECTORIES})
target_include_directories(${PROJECT_NAME} PRIVATE ${EDV_PRIVATE_INCLUDE_DIRECTORIES})

set_target_properties(
    PUBLIC_HEADER "${EDV_INCLUDE_FILES}"
)

install (TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    PUBLIC_HEADER DESTINATION include
)


来源:https://stackoverflow.com/questions/54271925/how-to-configure-cmakelists-txt-to-install-public-headers-of-a-shared-library

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!