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

Fra*_*fer 11 c++ cmake

我想使用 cmake 来安装我的库,edv但是当我执行时:

cmake --build . --target install
Run Code Online (Sandbox Code Playgroud)

它会安装,但只会创建bin/edv.dlllib/ < empty >。我怎样才能让 cmake 安装在EDV_PUBLIC_INCLUDE_DIRECTORIES里面include/...

这是我的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
)
Run Code Online (Sandbox Code Playgroud)

Com*_*sMS 7

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

install(FILES ${MY_HEADER_FILES} DESTINATION include)
Run Code Online (Sandbox Code Playgroud)

PUBLIC_HEADER您偶然发现的领域与 OSX 框架机制有关,这是它自己的蠕虫罐。我建议你远离它,除非你真的想.framework在 OSX 上部署你的库。

请特别注意命令的INCLUDES DESTINATION选项INSTALL(TARGET ...)。虽然这实际上并不复制任何文件本身,但它允许将包含目录自动添加到由配置包脚本提供的导入目标。如果您打算向您的用户提供包配置脚本(您可能应该这样做,至少如果您希望您的用户也使用 CMake),您可能想要设置此选项。

由于安装机制总体上相当复杂,我有一个的小型 github 项目,您可以在其中观察所有元素的运行情况。

  • 只有在非常简单的情况下,“PUBLIC_HEADER”才是正确的方法。一旦标头有多个子目录,它就不再起作用,因为 CMake 会展平层次结构并将所有标头放入同一目录中。 (11认同)
  • `PUBLIC_HEADER` 字段是安装头文件的推荐方法。它绝不是 Apple 框架独有的。请参阅文档:“与库关联的任何 PUBLIC_HEADER 文件都安装在非 Apple 平台上 PUBLIC_HEADER 参数指定的目标中” (4认同)
  • 上述建议是错误的。不需要在“INSTALL(FILES ...)”中显式列出头文件,甚至根本不需要使用“INSTALL(FILES ....)”。所需要做的就是在“INSTALL(target ....)”中设置“PUBLIC_HEADERS”参数,然后使用所有头文件设置“PUBLIC_HEADER”目标属性。 (2认同)

RAM*_*RAM 6

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

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

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

  • PUBLIC_HEADER参数设置为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(${PROJECT_NAME}
    PROPERTIES
    PUBLIC_HEADER "${EDV_INCLUDE_FILES}"
)

install (TARGETS ${PROJECT_NAME}
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    PUBLIC_HEADER DESTINATION include
)
Run Code Online (Sandbox Code Playgroud)