代码之家  ›  专栏  ›  技术社区  ›  yorel

在依赖于配置的目录中添加自定义命令输出

  •  0
  • yorel  · 技术社区  · 11 月前

    我想在每个配置的构建目录中生成文件:

    add_executable(test_generator_gen test_generator.cpp)
    target_compile_definitions(test_generator_gen PRIVATE GENERATE)
    target_link_libraries(test_generator_gen YOMM2::yomm2)
    
    add_custom_command(
        OUTPUT ${GENERATED_FILES}
        DEPENDS test_generator_gen
        COMMAND test_generator_gen
        WORKING_DIRECTORY $<TARGET_FILE_DIR:test_generator_gen>
    )
    

    文件在我想要的地方生成(例如。 ./builds/headers-only/tests/Debug/test_generator_slots.hpp 以及另一个文件)。我的问题是,我该放什么 ${GENERATED_FILES} ? 如果我把 "${CMAKE_CURRENT_BINARY_DIR}/test_generator_slots.hpp" ,我在撒谎 cmake ,文件一次又一次地生成。我尝试了我觉得很自然的方法:

    add_custom_command(
        OUTPUT $<TARGET_FILE_DIR:test_generator_gen>/test_generator_slots.hpp
        DEPENDS test_generator_gen
        COMMAND test_generator_gen
        WORKING_DIRECTORY $<TARGET_FILE_DIR:test_generator_gen>
    )
    # ...
    

    …但我收到一个错误:

    CMake Error at tests/CMakeLists.txt:95 (add_custom_command):
    [cmake]   Error evaluating generator expression:
    [cmake] 
    [cmake]     $<TARGET_FILE_DIR:test_generator_gen>
    [cmake] 
    [cmake]   No target "test_generator_gen"
    

    我很困惑。为什么某些参数接受同一命令中的同一生成器表达式,而其他参数则不接受?如何正确指定OUTPUT?

    cmake 3.22.1

    1 回复  |  直到 11 月前
        1
  •  1
  •   Tsyvarev    11 月前

    虽然错误消息看起来令人困惑 documentation 很清楚:

    论点 OUTPUT 可以使用一组受限的生成器表达式。不允许使用依赖目标的表达式。

    众所周知,对于多配置生成器,可执行文件和库的默认输出目录的名称与配置名称相同。所以你可以使用 $<CONFIG> 表达方式:

      OUTPUT ${CMAKE_BINARY_DIR}/$<CONFIG>/test_generator_slots.hpp
    

    为了使项目同时使用多配置生成器和单配置生成器,您需要使用 if :

    if(CMAKE_CONFIGURATION_TYPES)
      # Multi-configuration generator
      set(output_dir ${CMAKE_BINARY_DIR}/$<CONFIG>)
    else()
      # Single-configuration generator
      set(output_dir ${CMAKE_BINARY_DIR})
    endif()
    add_custom_command(
      OUTPUT ${output_dir}/test_generator_slots.hpp
      ...
    )
    

    或者,您可以显式设置 CMAKE_RUNTIME_OUTPUT_DIRECTORY 用于控制可执行文件输出目录的变量。并在需要引用该目录时使用该变量:

    if(CMAKE_CONFIGURATION_TYPES)
      # Multi-configuration generator
      #
      # Explicitly use generator expression,
      # so CMake won't automatically append the subdirectory with a config name.
      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/$<CONFIG>/bin)
    else()
      # Single-configuration generator
      #
      # While it is allowable to create config-specific directory,
      # we don't do that: every configuration already has its own build tree.
      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
    endif()
    
    # The executable will be created in the directory specified by
    # CMAKE_RUNTIME_OUTPUT_DIRECTORY variable.
    add_executable(test_generator_gen test_generator.cpp)
    
    
    add_custom_command(
      OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_generator_slots.hpp
      ...
    )