我正在使用 asn1c
以便从一个或多个 .asn1
文件将一系列 .h
和 .c
文件生成到给定文件夹中。
这些 C 文件在名称上与原始 asn1
文件没有对应关系。
这些文件必须与我的文件链接在一起才能获得可运行的可执行文件。我希望能够:
add_custom_target
完成) asn1c
文件之一更新时自动运行 .asn1
可执行文件。 由于预先不知道生成的文件,因此可以只对
asn1c
命令的输出目录的任何内容进行 glob - 只要该目录不为空,我就很高兴。
最佳答案
CMake 期望将 完整的源列表 传递给 add_executable()
。也就是说,您不能在构建阶段生成 glob 文件 - 为时已晚。
有几种方法可以在不知道源文件名称的情况下处理生成源文件:
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})
.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 通配生成的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44076307/