【问题标题】:CMake install TARGETS given target which is not an executable, library, or moduleCMake install TARGETS 给定的目标不是可执行文件、库或模块
【发布时间】:2017-05-26 21:06:42
【问题描述】:

我正在尝试构建一个包含单个 bash 脚本的 debian 包。该脚本由以下人员生成:

go.sh:

#!/bin/bash

cat >main <<EOF
#!/bin/bash
echo $@
EOF

chmod +x main

还有我的CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

add_custom_command(OUTPUT main ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME})

add_custom_target(main ALL)

install(
    TARGETS main
    DESTINATION /usr/local/lib/
)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

这只是给我一个神秘的错误消息:

CMake Error at CMakeLists.txt:7 (install):
  install TARGETS given target "main" which is not an executable, library, or
  module.

有谁知道这个错误信息是什么意思,我应该怎么做?

编辑 - 我很迷茫。

我已将go.sh 生成的脚本重命名为program,这样它就不会与应该生成文件的目标名称冲突:

#!/bin/bash

MAIN=program

cat >$MAIN <<EOF
#!/bin/bash
echo $@
EOF

chmod 'x $MAIN

我还更改了我的CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.5)

add_custom_target(
    main
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/program
)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/program
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME}
)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/program DESTINATION /usr/local/lib/)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

但是,我的构建仍然无法正常工作。在这种情况下,我的 main 目标没有建立。如果我跑:

rm -rf ./* &amp;&amp; cmake .. &amp;&amp; make package

我收到一个关于 file INSTALL cannot find program 的错误

我认为我从根本上误解了文件和目标之间的区别。我无法想象,使用cmake,可以为每个生成的文件命名,然后为每个生成的文件指定一个不同的目标名称来回避命名冲突。这对我来说没有任何意义。

【问题讨论】:

  • 目标名称和输出文件名相同对于某些生成器不起作用:对于每个目标,CMake 在构建树中创建具有相同名称的目录,因此它会与生成的文件冲突。
  • 我不明白。如果不是作为目标结果的文件的名称,那么目标名称是什么?
  • 在 CMake 中,目标名称只是出于某种目的的抽象标识符。它与它生成的文件不同。此外,单个目标可能会生成多个文件……或者一个都不会。顺便说一句,您的 add_custom_command 不起作用:您忘记为自定义目标添加 DEPENDS 选项 as here
  • 根据 CMake 文档,DEPENDS 用于“指定命令所依赖的文件”。就我而言,该命令不依赖于任何文件,所以我不确定我会在该子句中添加什么。
  • 您需要 add_custom_targetDEPENDS 对应于 add_custom_commandOUTPUT

标签: cmake deb cpack


【解决方案1】:

命令流install(TARGETS) 仅适用于使用add_executable()add_library() 创建的目标。

对于使用自定义目标构建的文件,请使用install(FILES)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/main DESTINATION /usr/local/lib/)

【讨论】:

  • 不起作用。在这种情况下安装命令找不到目标。
  • 找不到文件,因为您的add_custom_command 不起作用。请参阅我对问题帖子的评论。
【解决方案2】:

@tsyvarev 的回答为您指明了正确的方向,您编辑的问题几乎是正确的。您遗漏了add_custom_target()ALL 选项,这就是默认情况下未构建main 目标的原因。更正您的 CMakeLists.txt 文件以解决此问题,以下内容应该可以满足您的要求:

cmake_minimum_required(VERSION 3.5)

add_custom_target(
    main ALL
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/program
)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/program
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME}
)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/program DESTINATION /usr/local/lib/)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

这是一个非常标准的 CMake 模式,有一个自定义命令创建一个文件,一个自定义目标依赖于它,以便可以根据需要触发它。

【讨论】:

  • 根据 CMake 文档,ALL 表示“应将此目标添加到默认构建目标,以便每次都运行它”。那么额外的add_custom_command有什么区别呢。
  • 通过使自定义 target 成为 ALL 的一部分,它将始终被评估。它依赖于自定义的输出,因此输出将被重建如果它是过时的。因此,如果自定义输出已经存在,则不会重新生成。
  • 另一个问题:add_custom_target 子句中的main 的目的是什么?我知道这是目标名称,但没有将目标称为main,仅称为${CMAKE_CURRENT_BINARY_DIR}/program
  • ALL 目标隐式引用它。如果您使用Unix Makefiles 作为生成器,您将能够加载Makefile 文件并查看其中的依赖关系。即使没有,也可以创建没有任何内容的自定义目标。这可能很有用,例如,创建开发人员可以要求仅在需要时构建的按需目标,例如运行某种清理任务或特殊工具。
【解决方案3】:

修复它。我不得不将add_custom_command 折叠成add_custom_target

cmake_minimum_required(VERSION 3.5)

add_custom_target(
    main ALL
    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/go.sh ${PROJECT_NAME}
)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/main DESTINATION /usr/local/bin/)

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Me")

include(CPack)

【讨论】:

  • 这将导致main 脚本在每个构建中重新生成。对于像这样的小脚本来说可能不是什么大问题,但通常不是你想要的。
猜你喜欢
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
  • 2020-04-16
  • 2015-08-27
  • 2015-05-02
相关资源
最近更新 更多