installation - CMake:从 'make install [all]' 中排除自定义安装目标

标签 installation cmake target

我有一个库,它是作为我的项目的一部分构建和链接的。我想提供一种设施,可以选择在系统范围内安装库(或设置 ${CMAKE_INSTALL_PREFIX} 的任何地方)。否则,默认情况下,项目的最终构建产品将静态链接到库,并且安装前者,但库二进制文件保留在构建目录中。

换句话说:

$ make
$ make install

将构建和安装程序,但只是类似于

$ make install.foo

会将库安装到 ${CMAKE_INSTALL_PREFIX},如果需要,首先构建它。

到目前为止我有这样的东西(从实际脚本中简化而来,所以可能有错误):

INCLUDE_DIRECTORIES( "${CMAKE_CURRENT_LIST_DIR}")
SET (FOO_LIBRARY "foo")

# Following builds library and makes it available to
# be linked other targets within project by:
# TARGET_LINK_LIBRARIES(${progname} ${FOO_LIBRARY})
ADD_LIBRARY(${FOO_LIBRARY}
    foo/foo.cpp # and other sources ...
    )

###########################################################
# Approach #1
# -----------
# Optionally allow users to install it by invoking:
#
#       cmake .. -DINSTALL_FOO="yes"
#
# This works, but it means that users will have to run
# cmake again to switch back and forth between the libary
# installation and non-library installation.
#
OPTION(INSTALL_FOO "Install foo" OFF)
IF (INSTALL_FOO)
    INSTALL(TARGETS ${FOO_LIBRARY} DESTINATION lib/foo)
    SET(FOO_HEADERS foo/foo.h)
    INSTALL(FILES ${FOO_HEADERS} DESTINATION include/foo)
    UNSET(INSTALL_FOO CACHE)
ENDIF()
###########################################################

###########################################################
# Approach #2
# -----------
# Optionally allow users to install it by invoking:
#
#       make install.foo
#
# Unfortunately, this gets installed by "make install",
# which I want to avoid
SET(FOO_INSTALL "install.foo")
ADD_CUSTOM_TARGET(${FOO_INSTALL}
    COMMAND ${CMAKE_COMMAND}
        -D COMPONENT=foo
        -P cmake_install.cmake)
ADD_DEPENDENCIES(${FOO_INSTALL} ${FOO_LIBRARY})
INSTALL(TARGETS ${FOO_LIBRRARY}
    DESTINATION lib/foo COMPONENT foo)
SET(FOO_HEADERS foo/foo.h)
INSTALL(FILES ${FOO_HEADERS}
    DESTINATION include/foo COMPONENT foo)
###########################################################

可以看出,方法 #1 可行,但安装库所需的步骤是:

$ cmake .. -DINSTALL_FOO="yes"
$ make && make install

然后,要返回“正常”构建,用户必须记住在没有“-DINSTALL_FOO”选项的情况下再次运行 cmake,否则库将在下一个“make install”时安装。

第二种方法在我运行“make install.foo”时有效,但如果我运行“make install”,它也会安装库。我想避免后者。

有人对如何实现这一目标有任何建议吗?

最佳答案

您的方法 2 走在正确的轨道上。您可以通过使用 installOPTIONAL 开关来欺骗 CMake 避免安装 FOO 相关文件。命令。

对于 FOO 库目标,必须按以下方式修改命令:

SET (FOO_LIBRARY "foo")
ADD_LIBRARY(${FOO_LIBRARY} EXCLUDE_FROM_ALL
    foo/foo.cpp 
    )
INSTALL(TARGETS ${FOO_LIBRARY}
    DESTINATION lib/foo COMPONENT foo OPTIONAL)

EXCLUDE_FROM_ALL 被添加到 ADD_LIBRARY 以防止在运行普通 make 时构建库。通过添加 OPTIONAL 开关,可以选择安装 FOO_LIBRARY

使 FOO_HEADERS 的安装成为可选需要进行以下更改:

SET(FOO_HEADERS foo/foo.h)
SET(BINARY_FOO_HEADERS "")
FOREACH (FOO_HEADER ${FOO_HEADERS})
    ADD_CUSTOM_COMMAND(
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER}
        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${FOO_HEADER} ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER}
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FOO_HEADER})
    LIST (APPEND BINARY_FOO_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${FOO_HEADER})
ENDFOREACH()
INSTALL(FILES ${BINARY_FOO_HEADERS}
    DESTINATION include/foo COMPONENT foo OPTIONAL)

FOREACH 循环设置自定义命令,将 FOO_HEADERS 逐字复制到相应的二进制目录。 INSTALL(FILES ... 命令不是直接使用当前源目录中的 header ,而是从二进制目录中获取复制的 header 。二进制目录中 header 的路径收集在变量中BINARY_FOO_HEADERS

最后,FOO_INSTALL 目标必须按以下方式设置:

SET(FOO_INSTALL "install.foo")
ADD_CUSTOM_TARGET(${FOO_INSTALL}
    COMMAND ${CMAKE_COMMAND}
        -D COMPONENT=foo
        -P cmake_install.cmake
    DEPENDS ${BINARY_FOO_HEADERS})
ADD_DEPENDENCIES(${FOO_INSTALL} ${FOO_LIBRARY})

自定义 FOO_INSTALL 添加了对 BINARY_FOO_HEADERS 的依赖,以触发头文件的复制。当您运行 make install.foo 时,对 FOO_LIBRARY 的目标级别依赖会触发库的构建。

但是该解决方案具有以下缺点:

  1. 配置 CMake 时会发出警告 目标“foo”已设置 EXCLUDE_FROM_ALL,默认情况下不会构建,但已为其提供安装规则。 然而,CMake 会做正确的事无论如何。

  2. 一旦您运行了 make install.foo,随后的 make install 命令也将安装所有 FOO 相关文件,因为构建了 FOO 库,头文件存在于二进制目录中。

关于installation - CMake:从 'make install [all]' 中排除自定义安装目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16486785/

相关文章:

node.js - windows 下Satellizer安装错误

c++ - 链接 cmake、icc 和 pthreads (linux)

cmake - 将环境变量传递给 CMake execute_process 中的 COMMAND

Android 错误 : This template requires a build target API version of at least 14,,当前版本为 7

windows - 安装程序以管理员权限运行后如何在非管理员窗口中打开应用程序

android - 如何热部署android项目?

jquery - 如果目标不为空,则删除 img 链接

visual-studio-2005 - 无法在 Visual Studio 2005 中将 objective-c PU 更改为 x86 或 x64

php - 安装 Laravel 所需的最低 php 版本

c++ - 如何使用 CMake 将 QtMultimedia 组件集成到项目中?