2

我有一个包含一堆数据的文件。我想将其转换为 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有必要避免在原始字符串介绍器之后出现新行)。然而,这里发生的大量逃逸使得很难看到发生了什么。有没有办法编写这个函数,使它实际上是可读的?


请注意,我不能在这里使用file(READ ...)/configure_file(...)组合,因为source_file可能是 CMake 在构建时生成的东西,因此在配置时可能不存在。

4

1 回答 1

2

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

# Untested, just to show roughly how to do it
import sys

dest_file, source_file, literal_name = sys.argv[1:]

with open(dest_file) as dest, open(source_file) as source:
    literal_contents = source.read()
    dest.write(f'char const* {literal_name} = R"({literal_contents})";\n')

对应的CMake代码:

# String interpolation came in Python 3.6, thus the requirement on 3.6.
# If using CMake < 3.12, use find_package(PythonInterp) instead.
find_package(Python3 3.6 COMPONENTS Interpreter)

# Make sure this resolves correctly. ${CMAKE_CURRENT_LIST_DIR} is helpful;
# it's the directory containing the current file (this cmake file)
set(make_literal_from_file_script "path/to/make_literal_from_file.py")

function(make_literal_from_file dest_file source_file literal_name)              
    add_custom_command(                                                          
        OUTPUT "${dest_file}"
        COMMAND 
            "${Python3_EXECUTABLE}" "${make_literal_from_file_script}"
            "${dest_file}"
            "${source_file}"
            "${literal_name}"
        DEPENDS "${source_file}")                                                  
endfunction()

如果您不想依赖 Python,可以使用 C++(仅显示 CMake 代码):

add_executable(make_literal_from_file_exe
    path/to/cpp/file.cpp
)

function(make_literal_from_file dest_file source_file literal_name)              
    add_custom_command(                                                          
        OUTPUT "${dest_file}"
        COMMAND 
            make_literal_from_file_exe
            "${dest_file}"
            "${source_file}"
            "${literal_name}"
        DEPENDS "${source_file}")
endfunction()
于 2018-08-23T17:27:20.837 回答