【问题标题】:CMake globbing generated filesCMake globbing 生成的文件
【发布时间】:2017-10-19 22:52:54
【问题描述】:

我使用asn1c 是为了从一个或多个.asn1 文件中生成一系列.h.c 文件到给定文件夹中。

这些 C 文件在名称上与原始 asn1 文件没有对应关系。

这些文件必须与我的链接在一起才能获得工作的可执行文件。我希望能够:

  • 自动生成构建目录中的文件,避免污染项目的其余部分(可能使用add_custom_target完成)
  • 指定我的可执行文件对这些文件的依赖关系,以便在文件丢失或.asn1 文件之一更新时自动运行asn1c 可执行文件。
  • 自动将所有生成的文件添加到我的可执行文件的编译中。

由于事先不知道生成的文件,因此可以将 asn1c 命令的输出目录的内容全部全局化 - 只要该目录不为空,我很高兴。

【问题讨论】:

    标签: cmake dependencies code-generation glob


    【解决方案1】:

    CMake 期望将完整列表源传递给add_executable()。也就是说,您不能在 构建阶段 生成 glob 文件 - 为时已晚。

    您有几种方法可以在不事先知道源文件名称的情况下处理生成源文件:

    1. 配置阶段使用execute_process 生成文件。之后,您可以使用file(GLOB) 收集源名称并将它们传递给add_executable()

      execute_process(COMMAND asn1c <list of .asn1 files>)
      file(GLOB generated_sources "${CMAKE_CURRENT_BINARY_DIR}/*.c")
      add_executable(my_exe <list of normal sources> ${generated_sources})
      

      如果将来不打算更改用于生成的输入文件(在您的情况下为.asn1),这是最简单的方法。

      如果您打算更改输入文件并希望 CMake 检测到这些更改并重新生成源,则应采取更多措施。例如,您可以先将输入文件复制到带有configure_file(COPY_ONLY) 的构建目录中。在这种情况下,将跟踪输入文件,如果更改,CMake 将重新运行:

      set(build_input_files) # Will be list of files copied into build tree
      foreach(input_file <list of .asn1 files>)
          # Extract name of the file for generate path of the file in the build tree
          get_filename_component(input_file_name ${input_file} NAME)
          # Path to the file created by copy
          set(build_input_file ${CMAKE_CURRENT_BINARY_DIR}/${input_file_name})
          # Copy file
          configure_file(${input_file} ${build_input_file} COPY_ONLY)
          # Add name of created file into the list
          list(APPEND build_input_files ${build_input_file})
      endforeach()
      
      execute_process(COMMAND asn1c ${build_input_files})
      file(GLOB generated_sources "${CMAKE_CURRENT_BINARY_DIR}/*.c")
      add_executable(my_exe <list of normal sources> ${generated_sources})
      
    2. 解析输入文件以确定哪些文件将从它们中创建。不确定它是否适用于 .asn1,但对于某些格式,它适用:

      set(input_files <list of .asn1 files>)
      execute_process(COMMAND <determine_output_files> ${input_files}
          OUTPUT_VARIABLE generated_sources)
      add_executable(my_exe <list of normal sources> ${generated_sources})
      add_custom_command(OUTPUT ${generated_sources}
          COMMAND asn1c ${input_files}
          DEPENDS ${input_files})
      

      在这种情况下,CMake 将检测输入文件中的更改(但如果要修改生成的源文件的列表,您需要重新运行cmake手动)。

    【讨论】:

    • 真正的问题是我还使用CMake 来实际构建asn1c 可执行文件,所以我无法在构建阶段之前运行它。
    • 您可以使用execute_process()配置阶段asn1c 构建为子项目。这看起来是一个不错的决定:无需在 构建阶段 推迟构建所有内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多