【问题标题】:CMake How to check target for buildCMake如何检查构建目标
【发布时间】:2017-10-07 02:38:10
【问题描述】:

我试图找到解决方案:如何检查构建目标?

考虑以下 CMake 脚本:

cmake_minimum_required(VERSION 3.5.1)
project(cppTests)

# How to check at this point the target of build
if(TARGET "cppTests")
    message(STATUS "Target is cppTests")
else()
    message(STATUS "Target is not cppTests")
endif()


message(STATUS "Target is ${TARGET}")
set(CMAKE_CXX_STANDARD 11)

set(SOURCE_FILES main.cpp)
add_executable(cppTests ${SOURCE_FILES})

然后我调用以下代码:

/home/username/Software/clion-2017.1.1/bin/cmake/bin/cmake --build /home/username/Projects/cppTests/cmake-build-debug --target cppTests -- -j 8

如何在 --target 选项之后检查 CMake 脚本中的目标 cppTests ? 我在 Makefiles 中寻找类似 MAKECMDGOALS 的东西。 我找到了任何有用的解决方案...

【问题讨论】:

    标签: c++ build cmake build-system


    【解决方案1】:

    开发者选择在 CMake 生成项目文件之后构建哪个目标。在运行 CMake 时,CMake 无法知道开发人员将构建什么目标。因此,您所要求的对于 CMake 项目来说并没有真正意义。在 Makefile 中,没有单独的配置步骤,它是构建的一部分,这就是它如何提供像 MAKECMDGOALS 这样的功能。如果你真的想要 Makefiles 的这个功能,也可能值得重新考虑,因为它isn't meant for typical use(强调我的):

    Make 会将特殊变量 MAKECMDGOALS 设置为您在命令行中指定的目标列表。如果命令行上没有给出目标,则此变量为空。 请注意,此变量仅应在特殊情况下使用。

    在您的示例中,您还滥用了if(TARGET...)。该构造用于测试项目是否已定义特定的 CMake 目标(在您的示例中,它直到 if() 命令之后才发生,因此它始终评估为 false)。详情请参阅文档here

    【讨论】:

    • 我可以用 add_custom_command(TARGET cppTests PRE_BUILD) 替换 MAKECMDGOALS,但实际上它不起作用,在现实生活中不是根据 CMake 的文档。我想在构建特定目标之前生成一些文件。如果 add_custom_command(TARGET cppTests PRE_BUILD) 可以解决我的问题
    【解决方案2】:

    您的要求在 CMake 世界中毫无意义。 CMake 项目的时间表包含 3 个不同的步骤:

    configure time  >  generate time  >  build time
    \---------------v--------------/     \---v----/
            CMake is running           make is running
    

    配置步骤中,CMake 读取并解析CMakeLists.txt 文件并将处理后的数据存储在内存中。当您在 CMake GUI 中按下 Configure 按钮时会发生这种情况。

    生成步骤中,CMake 作用于内存中的数据以生成构建系统文件(Makefile、Visual Studio 解决方案和项目等)。当您在 CMake GUI 中按下 Generate 按钮时会发生这种情况。

    从命令行运行 cmake 会立即执行配置,然后执行生成。

    然后 CMake 完成构建系统并终止其运行。您现在有一个可以由构建工具处理的工作构建系统(例如makemsbuild)。即使您使用cmake --build 运行此构建工具,cmake 的新调用也不会读取您的CMakeLists.txt 文件。它只是从生成的CMakeCache.txt 中访问最低限度,以确定要运行的构建工具,然后运行它。

    您没有具体说明您要使用这些信息实现什么目标,但也许您可以使用 add_custom_command(TARGET cppTests PRE_LINK) 之类的东西?

    【讨论】:

    • 你并不完全正确......实际上在cmake生成文件进行构建后,您可以使用cmake运行命令运行构建,例如:/home/redra/Software/clion-2017.1.1/bin/cmake/ bin/cmake --build /home/redra/Projects/cppTests/cmake-build-debug --target cppTests -- -j 8
    • add_custom_command(TARGET cppTests PRE_LINK) - 我需要 add_custom_command(TARGET cppTests PRE_BUILD) 替换 if else,但由于某种原因,它不适用于 Make 等 Linux 工具。文档中也提到了
    • @DenisKotov 我确实提到了cmake --build,但这是与配置或生成步骤完全不同的 CMake 运行。 “即使你使用cmake --build 运行这个构建工具......”就在答案中。 PRE_BUILD 不能与 Make 一起使用,因为 Makefile 中没有可以合理放置它的位置。如果你提出一个关于你真正需要它的新问题,也许有另一种方法可以实现它。
    • 我的任务是在构建主要目标之前生成文件。 CommonAPI 也许你知道我需要在构建目标之前生成一些文件。我已经用 add_custom_command 和 add_custom_target 实现了它,但我试图找到替代品
    • @DenisKotov 如果你做对了,它确实保证正确的重新生成。如果您在创建文件的add_custom_command() 中指定依赖项,CMake 将支持它们。
    【解决方案3】:

    我找到了解决办法:

    add_custom_command(
            OUTPUT fidl_files_generated
            DEPENDS "./interfaces/*.fidl"
            COMMAND touch fidl_files_generated
            COMMAND /home/redra/Projects/Automotive/cgen/commonapi-generator/commonapi-generator-linux-x86_64 -sk ../interfaces/ *.fidl
            COMMAND /home/redra/Projects/Automotive/cgen/commonapi_dbus_generator/commonapi-dbus-generator-linux-x86_64 ../interfaces/ *.fidl
    )
    
    add_custom_target(fidl_gen
                      DEPENDS fidl_files_generated)
    
    set(GENERATED_FILES "../cmake-build-debug/src-gen/v1/commonapi/HelloWorldDBusProxy.cpp"
                        "../cmake-build-debug/src-gen/v1/commonapi/HelloWorldDBusDeployment.cpp"
                        "../cmake-build-debug/src-gen/v1/commonapi/HelloWorldDBusStubAdapter.cpp"
                        "../cmake-build-debug/src-gen/v1/commonapi/HelloWorldStubDefault.cpp"
                        "../cmake-build-debug/src-gen/v1/commonapi/HelloWorldDBusDeployment.cpp")
    set_source_files_properties(${GENERATED_FILES} PROPERTIES GENERATED TRUE)
    
    add_executable(
            CommonAPI_Server
            ${SOURCE_FILES}
            ${GENERATED_FILES})
    add_dependencies(CommonAPI_Server fidl_gen)
    

    感谢大家的支持!!

    特别感谢Angew 的支持和帮助!!!!

    【讨论】:

    • 这一切都很好但是当你不知道你会得到什么 GENERATED_FILES 时不起作用:-( GLOB_RECURSE 在这里会失败,因为它在配置时是可操作的。真正的问题是 add_custom_command 不提供从命令中获取结果的工具。查看 execute_process - 你会得到返回值、错误等。所以你不能创建一个自定义命令来“返回”在某些目录中找到的 GENERATED 文件列表:-( 没关系只是大声思考。
    【解决方案4】:

    我不能 100% 确定我正确理解了您的问题,但根据我的理解,您正在寻找变量 CMAKE_PROJECT_NAMEPROJECT_NAME

    if (${CMAKE_PROJECT_NAME} STREQUAL "cppTests")
        message("CMAKE_PROJECT_NAME is \"cppTests\"")
    else ()
        message("CMAKE_PROJECT_NAME is NOT \"cppTests\"")
    endif ()
    

    查看常用变量列表here。当我做 CMake 时,我经常保持这个链接打开;我想你也会发现它很有用。

    【讨论】:

    • 不,我不是在寻找 ${CMAKE_PROJECT_NAME} 因为在同一个项目中可以有不同名称的各种目标,例如: add_executable(cppExe ${SOURCE_FILES});add_library(cppLib ${SOURCE_FILES })
    • 我在 Makefiles 中寻找类似 MAKECMDGOALS 的东西
    猜你喜欢
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    相关资源
    最近更新 更多