如何在CMake中生成全局唯一的目标名称?
CMake生成全局唯一自定义目标名的方法
在CMake中编写自定义函数,通过add_custom_command生成文件并将其设为主可执行文件的依赖时,必须确保中间自定义目标的名称全局唯一——直接用文件路径会因含斜杠等非法字符报错,仅用文件名又会出现重名冲突。以下是几种可行的解决方法:
方案1:路径字符替换生成唯一名称
将输出文件的完整路径中的斜杠(包括Windows下的反斜杠)替换为下划线,再添加前缀避免与其他目标冲突。由于完整路径全局唯一,替换后的名称也能保证唯一性,同时保留一定的可读性。
function(my_function output_file ...) add_custom_command( OUTPUT ${output_file} # 此处填写你的COMMAND等参数 ... ) # 将路径中的斜杠/和反斜杠\替换为下划线_ string(REPLACE "/" "_" tmp_target ${output_file}) string(REPLACE "\\" "_" tmp_target ${tmp_target}) # 添加前缀,进一步降低冲突概率 set(tmp_target "generated_file_${tmp_target}") add_custom_target(${tmp_target} DEPENDS ${output_file}) add_dependencies(main_executable ${tmp_target}) endfunction(my_function)
方案2:基于UUID生成绝对唯一名称
利用CMake 3.20及以上版本提供的string(UUID)命令,结合输出文件路径生成唯一标识符作为目标名的一部分。这种方法能保证名称绝对唯一,即使路径存在特殊字符也不受影响。
function(my_function output_file ...) add_custom_command( OUTPUT ${output_file} ... ) # 以输出文件路径为命名空间生成SHA1类型的UUID string(UUID tmp_target NAMESPACE ${output_file} TYPE SHA1) set(tmp_target "gen_target_${tmp_target}") add_custom_target(${tmp_target} DEPENDS ${output_file}) add_dependencies(main_executable ${tmp_target}) endfunction(my_function)
方案3:结合目录与文件名生成名称
提取输出文件的目录和文件名,将目录部分的斜杠替换后与文件名组合,既能保证唯一性,又能让目标名更直观。
function(my_function output_file ...) add_custom_command( OUTPUT ${output_file} ... ) # 提取文件名和目录 get_filename_component(file_name ${output_file} NAME) get_filename_component(file_dir ${output_file} DIRECTORY) # 替换目录中的斜杠 string(REPLACE "/" "_" dir_part ${file_dir}) string(REPLACE "\\" "_" dir_part ${dir_part}) set(tmp_target "gen_${dir_part}_${file_name}") add_custom_target(${tmp_target} DEPENDS ${output_file}) add_dependencies(main_executable ${tmp_target}) endfunction(my_function)
注意事项
- CMake目标名仅允许包含字母、数字、下划线(
_)和连字符(-),所以必须将路径中的所有非法字符替换为合法字符。 - 若需要兼容旧版本CMake,优先选择方案1或方案3;若追求绝对唯一性且使用CMake 3.20+,方案2更合适。
内容的提问来源于stack exchange,提问作者DBear
相关产品推荐
相关产品推荐

