【问题标题】:cmake install library and development files as separate components using PUBLIC_HEADERcmake 使用 PUBLIC_HEADER 将库和开发文件安装为单独的组件
【发布时间】:2018-03-24 14:23:57
【问题描述】:

我希望创建两个包,一个包含共享库,另一个包含供开发使用的标头。

一个可行的解决方案是:

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。 有没有办法做到这一点? 与 install DIRECTORY 相比,PUBLIC_HEADER 有什么优势吗?

【问题讨论】:

  • 我一直在尝试使用 PUBLIC_HEADERS 来达到这个目的。它在 Daniel Pfeiffer 关于现代 cmake 的演讲中间接得到了体现,并且在 Windows 上运行时可以工作/安装它们。无法弄清楚我在 linux 上做错了什么......
  • @JonathanOlson 你搞定了吗?

标签: cmake


【解决方案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}")

文档:

【讨论】:

    【解决方案2】:

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

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

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

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

    您也应该避免为此使用 glob 表达式,因为与显式提供文件相比可能节省的时间并不能证明它们在中断时带来的麻烦。

    【讨论】:

    • 我不确定文档是否如此清晰:。我(误)读到“在非 Apple 平台上,可以使用 install(TARGETS) 命令的 PUBLIC_HEADER 选项安装这些标头。”暗示这是一个很好的方法。以某种方式分离公共和私有标头的想法也很有吸引力。
    • @BruceAdams 我同意,这是一个很容易犯的错误,特别是如果您正在寻找一个符合您要求的功能。
    • CMake 确实有一种推断公共与私有标头的方法。当您不使用 $ 和 $ 作为公共标头尽管拒绝在 Windows 上进行任何安装时,它甚至会抱怨
    猜你喜欢
    • 2013-02-03
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多