cmake使用PUBLIC_HEADER将库和开发文件作为单独的组件安装

时间:2017-10-12 15:13:05

标签: cmake

我希望创建两个包含共享库的包,另一个包含用于开发的头文件。

有效的解决方案是:

INSTALL(TARGETS mylib
  COMPONENT core
  LIBRARY DESTINATION ${LIBDIR}
)
INSTALL (
    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMPONENT devel
    DESTINATION ${INCLUDEDIR}
    FILES_MATCHING PATTERN "*.h")

然而,CMake还有一个“PUBLIC_HEADER”目的地。 这样你就可以做到:

INSTALL(TARGETS mylib
  LIBRARY DESTINATION ${LIBDIR}
  PUBLIC_HEADER DESTINATION ${INCLUDEDIR}
)

我似乎无法让这个工作。即使将头文件显式添加到ADD_LIBRARY(),也不会将任何内容安装到$ {INCLUDEDIR}。有人能指出一个如何运作的例子吗?

这个问题的另一个问题是我想要不同包中的库和标题,理想情况下我想要:

INSTALL(TARGETS mylib
  COMPONENT core
  LIBRARY DESTINATION ${LIBDIR}
)
INSTALL(TARGETS mylib
  COMPONENT devel
  PUBLIC_HEADER DESTINATION ${INCLUDEDIR}
)

但是PUBLIC_HEADER似乎需要设置LIBRARY DESTINATION。 有没有办法做到这一点? 相比PUBLIC_HEADER优于安装DIRECTORY还有什么优势吗?

2 个答案:

答案 0 :(得分:1)

PUBLIC_HEADER几乎肯定是这里工作的错误工具,除非你的共享库真的是一个OSX框架库。文档也明确指出了这一点。

如果您希望在安装步骤中复制头文件,则应使用install(FILES ...) command

install(FILES ${MY_PUBLIC_HEADERS} DESTINATION ${INCLUDEDIR} COMPONENT devel)

这是有道理的,因为CMake无法通过查看目标来推断您可能或可能不想成为安装集的一部分。因此,手动指定文件列表实际上是指定安装标头的唯一明智方法,install(FILES ...)就是这样做。

你也应该避免使用glob表达式,因为明确提供文件所带来的潜在时间节省并不能证明它们在中断时引入的麻烦。

答案 1 :(得分:1)

您必须实际设置库的 PUBLIC_HEADER 属性才能使其正常工作。

我将标头放入 include/mylib 中,以便它们位于自己的“命名空间”中以避免冲突。

这样做:

# initializes ${CMAKE_INSTALL_*DIR} to sane defaults
include(GNUInstallDirs)

add_library(
    mylib
    src/src1.cpp src/src2.cpp
    include/mylib/header1.h include/mylib/header2.h
)

# this needs to be a list, so a ; separated string in cmake
set_target_properties(mylib PROPERTIES PUBLIC_HEADER "include/header1.h;include/header2.h")

# headers are now installed to ${CMAKE_INSTALL_PREFIX}/include/mylib, and
# library into ${CMAKE_INSTALL_PREFIX}/lib or ${CMAKE_INSTALL_PREFIX}/lib64 depending on arch
install(
    TARGETS mylib
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib
)

你可以通过创建一个像这样的变量来解决列表中有点难看的设置:

set(MYLIB_HEADERS include/mylib/header1.h include/mylib/header2.h)
set_target_properties(mylib PROPERTIES PUBLIC_HEADER "${MYLIB_HEADERS}")

文档: