如何配置CMakeLists.txt以安装共享库的公共头?

时间:2019-01-19 22:30:28

标签: c++ cmake

我想使用cmake安装我的库“ edv”,但是在执行时:

  

cmake --build。 --target安装

它会安装,但只会创建“ bin / edv.dll”和“ lib / ”。我该如何在cmake的“ include / ...”内部安装EDV_PUBLIC_INCLUDE_DIRECTORIES?

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
)

2 个答案:

答案 0 :(得分:1)

CMake无法从目标推导出要安装的头文件集。这是有道理的,因为目标可能同时包含私有和公共头文件,但是CMake不会区分它们。因此,您必须在INSTALL(FILES ...)命令中明确列出头文件:

install(FILES ${MY_HEADER_FILES} DESTINATION include)

您偶然发现的PUBLIC_HEADER字段与OSX框架机制有关,它是蠕虫本身。我建议您不要使用它,除非您实际上想在OSX上将库作为.framework部署。

请特别注意INSTALL(TARGET ...)命令的INCLUDES DESTINATION选项。尽管这实际上并不复制任何文件,但它允许将include目录自动添加到config软件包脚本提供的导入目标中。如果您打算向用户提供程序包配置脚本(至少在您希望用户也使用CMake的情况下,您可能应该这样做),则可能需要设置此选项。

由于安装机制总体而言非常复杂,因此我拥有a small github project,您可以在其中观察所有运行中的元素。

答案 1 :(得分:0)

要安装./include文件夹中存在的所有标头,您需要做的是:

  • 设置一个包含所有要安装的头文件的列表(即,定义EDV_INCLUDE_FILES

  • 使用所有这些头文件设置目标属性PUBLIC_HEADERS

  • 使用安装目录在PUBLIC_HEADERS中设置install(TARGETS ....)参数。

此方法也是CMake支持macOS框架的基础。

我已使用设置更新了上面的示例,以将项目的公共标头安装在项目目标输出目录的./include中。警告:我尚未亲自测试项目定义,因此可能需要一些细微调整才能起作用。

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_HEADERS "${EDV_INCLUDE_FILES}"
)

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