Cmake 在add_custom_命令中处理大量转义字符

Cmake 在add_custom_命令中处理大量转义字符,cmake,add-custom-command,Cmake,Add Custom Command,我有一个包含大量数据的文件。我想把它变成C++字符串文字,因为我需要把这个数据编译成二进制文件——我不能从磁盘读取它。 < >这样做的一种方法是生成一个C++源文件,它声明一个字符串名称,并带有已知的名称。要做到这一点,CMake代码非常简单,尽管有点糟糕: function(make_literal_from_file dest_file source_file literal_name) add_custom_command(

我有一个包含大量数据的文件。我想把它变成C++字符串文字,因为我需要把这个数据编译成二进制文件——我不能从磁盘读取它。 < >这样做的一种方法是生成一个C++源文件,它声明一个字符串名称,并带有已知的名称。要做到这一点,CMake代码非常简单,尽管有点糟糕:

function(make_literal_from_file dest_file source_file literal_name)              
    add_custom_command(                                                          
        OUTPUT ${dest_file}                                                      
        COMMAND printf \'char const* ${literal_name} = R\"\#\(\' > ${dest_file}  
        COMMAND cat ${source_file} >> ${dest_file}                               
        COMMAND printf \'\)\#\"\;\' >> ${dest_file}                              
        DEPENDS ${source_file})                                                  
endfunction()
这是有效的,并且符合我的要求(
printf
是避免在原始字符串导入器后面出现新行所必需的)。然而,这里发生的大量逃逸使得我们很难看到发生了什么。有没有一种方法来编写这个函数,使它实际上是可读的



请注意,我不能在这里使用
文件(READ…
/
配置文件(…)
组合,因为
源文件
可能是由CMake在构建时生成的,因此在配置时可能不存在。

我建议编写一个脚本来执行此操作。您可以用CMake编写,但我个人更喜欢更好的语言,如Python:

#未经测试,仅粗略演示如何操作
导入系统
dest_文件,source_文件,literal_name=sys.argv[1:]
打开(目标文件)作为目标,打开(源文件)作为源:
literal\u contents=source.read()
dest.write(f'char const*{literal\u name}=R“({literal\u contents})”;\n')
对应的CMake代码:

#字符串插值是在Python 3.6中出现的,因此3.6中的要求。
#如果使用CMake<3.12,则使用find_包(PythonInterp)。
find_包(Python3.6组件解释器)
#确保此问题正确解决${CMAKE_CURRENT_LIST_DIR}很有帮助;
#它是包含当前文件(此cmake文件)的目录
设置(从文件生成文本脚本“path/to/make\u literal\u from\u file.py”)
函数(从\u文件dest\u文件源\u文件literal\u名称生成\u literal\u)
添加自定义命令(
输出“${dest_file}”
命令
“${Python3\u EXECUTABLE}”“${make\u literal\u from\u file\u script}”
“${dest_file}”
“${source_file}”
“${literal_name}”
依赖于“${source_file}”)
endfunction()

如果不想对Python有依赖性,可以使用C++(只显示CGED代码):

添加\u可执行文件(从\u文件\u可执行文件生成\u文字\u
路径/to/cpp/file.cpp
)
函数(从\u文件dest\u文件源\u文件literal\u名称生成\u literal\u)
添加自定义命令(
输出“${dest_file}”
命令
从\u文件\u exe生成\u文字\u
“${dest_file}”
“${source_file}”
“${literal_name}”
依赖于“${source_file}”)
endfunction()

很抱歉挑三拣四,但是你能不能让标题更具描述性?无法想象这是非常可搜索的…@DanMašek更好?我想是的。谢谢:)嗯,您可以使用
配置_文件
,以及
文件(读取…
将源_文件的内容加载到变量中吗?对。解决此问题的一种可能方法是将file/configure_文件放入一个单独的.cmake脚本中,您可以从自定义命令调用该脚本。我使用类似的设置在编译时运行各种代码生成器。虽然,我承认,它使实现比您现在拥有的更加复杂。这是有效的(+1)。。。然而,它相当长一点,我想我更喜欢三个真正丑陋的CMake线,而不是有另一个外部的东西。“我[强烈]希望有一个解决方案能让逃跑变得更容易。”巴里,这是合理的。请注意,原始代码不是跨平台的AFAIK(
printf
不在Windows IIRC上)。@Barry您尝试过使用吗?我认为如果您这样做,
COMMAND printf'char const*${literal\u name}=R\'('>${dest\u file}
会起作用,可能需要用引号括起来(类似于
printf“'char const*${literal\u name}=R\”。“
或者
printf”char const*${literal\u name}=R\”(
).不关心跨平台。我无法想出一个有效的逐字排列(这并不意味着没有一个有效的排列-我就是想不出来)@Barry每次我尝试让CMake执行命令时都会遇到类似的问题,这些命令开始有任何复杂性,除非我将其分解成单独的脚本。我怀疑我是否也能解决这个问题。。。