在cmake中make install后进行后处理

问题描述 投票:0回答:2

我正在尝试在“make install”末尾制作可执行文件的副本

我需要做类似的事情:

cp bin/prog bin/prog1

我已将以下内容添加为 CMakelists.txt 中的最后一行

install (CODE  "execute_process(COMMAND /src/copyExe.sh ${BIN_DIR})")

copyExe.sh 是一个执行复制操作的 bash 脚本。 为了达到预期的效果,我需要运行“make install”两次。 第一次它抱怨prog不存在,然后将文件复制到bin中。 第二次它找到 prog 并且能够制作副本。

有没有办法确保我的 copyExe 脚本在文件复制到 bin 后运行?

目录结构

site
    bin
    src
        CMakeLists.txt ( contains add_dir(foo) and install(CODE....))
    foo
        CMakeLists.txt ( contains install( TARGET..... ))
cmake
2个回答
3
投票

虽然 CMake documentation for

install
命令说(关于安装逻辑):

目录之间的顺序未定义。

看起来它倾向于以与 add_subdirectory() 调用相同的顺序

处理不同
子目录中的安装逻辑。

但是,它会处理

当前目录
中的install()调用的安装逻辑在子目录中的

之前。

您可以将 
install(CODE)
 移动到某个子目录(例如,
fix_binaries
),然后将此子目录添加到 
CMakeLists.txt
src

的末尾:

src/fix_binaries/CMakeLists.txt

:

install(CODE ...)

src/CMakeLists.txt


... add_subdirectory(foo) ... # After all add_subdirectory() calls add_subdirectory(fix_binaries)

这种方法适用于我参与的一个项目(相关代码

)。

0
投票

所以,这里发生的是 
install(CODE)
 - 就像所有 CMake 
install 命令一样 - 实际上什么也不做,只是
将代码插入到当前构建目录中生成的 
cmake_install.cmake
脚本
(也就是说,与调用它的源目录)。与任何其他 
install()
 形式的唯一区别是,使用 
install(CODE)
 (或 
install(SCRIPT)

),您可以直接定义该代码,而不是让 CMake 根据您的参数生成它。

使用 
execute_process()

调用诸如 Bourne shell 脚本之类的东西来编写不可移植的安装时操作脚本是一个非常糟糕的主意。 (对于初学者来说,您的 Windows 用户不会很喜欢这一点。)

最好使用 CMake 的内置

-E 模式工具
 以及 
execute_process()
${CMAKE_COMMAND} 变量(is

在安装时可用的变量之一)。

就复制已安装的文件而言,实现该操作的唯一方法是将复制命令放在与安装 
first
 副本的 
CMakeLists.txt 命令相同的 install()
 中,以便您可以控制订单。 (给定目录中的 
install()
 命令按照发出的顺序在该目录的 
cmake_install.cmake

脚本中创建代码。)

因此,在 
foo 子目录中,this

将创建一个安装脚本,用于安装可执行目标的两个副本:
add_executable(foo ...)

install(TARGETS foo
  RUNTIME DESTINATION "bin"
)

install(CODE [[
  execute_process(
    COMMAND
      "${CMAKE_COMMAND}" -E copy
      "$<TARGET_FILE_NAME:foo>"
      "foo_second_name"
    WORKING_DIRECTORY "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin"
  )
]])

因为 
install(CODE)
 代码位于 
[[
 围栏块中,所以任何变量都不会被扩展(它们将作为变量引用进入 
cmake_install.cmake 文件),双引号也是如此。但是获取目标输出文件名的生成器表达式将在代码写出时立即展开。

复制也会在 CMake 在

install(TARGETS)
处理
foo
目标输出文件期间进行的所有剥离和其他处理之后发生。这是您无法保证复制代码是否位于目标安装同一目录之外的任何地方。

(从技术上讲,副本仍然有可能无法工作,如果(比方说)您为

COMPONENT
install(TARGETS)
命令分配了不同的
install(CODE)
,然后运行
cmake --install
命令仅安装一个或但是,只是......不要使用相同的
COMPONENT
,或者。没有。)

© www.soinside.com 2019 - 2024. All rights reserved.