使用 CMake 将二进制数据嵌入到可执行文件中

Art*_*zuk 1 c++ cmake

当我使用 CMake 时,我在将二进制数据嵌入到可执行文件中时遇到了一些问题。两个选项的代码相同,如下所示:

\n\n
#include <iostream>\n\nextern char _binary_res_txt_start;\nextern char _binary_res_txt_end;\n\nint main (int, char**) {\n    for (char* c = &_binary_res_txt_start; c != &_binary_res_txt_end; ++c) {\n        std::cout << *c;\n    }   \n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当我用 GCC 编译它时:

\n\n
g++ -std=c++17 -Wall -Wextra -Wpedantic -Werror=return-type -Wl,--format=binary -Wl,res.txt -Wl,--format=default  main.cpp -o main\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的res.txt文件存储简单的“HELLO WORLD”文本,我得到适当的输出,所以一切都按预期进行。

\n\n

现在我想使用 CMake 编译这段代码,所以我的尝试是:

\n\n
cmake_minimum_required(VERSION 3.10)\nset(app_name main)\nproject(${app_name} CXX)\nset(BIN_DIR "${PROJECT_SOURCE_DIR}/bin")\nset(OPTIMIZATION_LEVEL " -O0")\nset(COMPILE_FLAGS_MAIN "-Wall -Wextra -Wpedantic -Wno-deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wl,--format=binary -Wl,res.txt -Wl,--format=default")\nset(COMPILE_FLAGS_RELEASE "${COMPILE_FLAGS_MAIN} ${OPTIMIZATION_LEVEL}")\nset(CPP_STD "17")\nset(CPP_STD_REQUIRED "ON")\nset(CPP_EXTENSION_REQUIRED "OFF")\n\nfile(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/cpp/*.cpp")\n\nadd_executable(${app_name} ${SOURCES})\n\nset_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_DIR}\n                                                COMPILE_FLAGS ${COMPILE_FLAGS_RELEASE}\n                                                CXX_STANDARD ${CPP_STD}\n                                                CXX_STANDARD_REQUIRED ${CPP_STD_REQUIRED}\n                                                CXX_EXTENSIONS ${CPP_EXTENSION_REQUIRED})\n
Run Code Online (Sandbox Code Playgroud)\n\n

不幸的是,在链接过程中我得到了:

\n\n
main.cpp:(.text+0x13): undefined reference to `_binary_res_txt_start\'\nmain.cpp:(.text+0x1b): undefined reference to `_binary_res_txt_end\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

我做了:cmake -Bbuild -H. && cmake --build build我的“项目”结构如下所示:

\n\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 CMakeLists.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 res.txt\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 src\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 cpp\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.cpp\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的观察和到目前为止我所做的事情:

\n\n
    \n
  • 当我使用命令行nm main进行编译时,显示对象已初始化

    \n\n
    0000000000601050 D _binary_res_txt_end\n000000000000000c A _binary_res_txt_size\n0000000000601044 D _binary_res_txt_start\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
  • 当我用 CMake 编译它时,这些对象没有初始化:

    \n\n
    U _binary_res_txt_end\nU _binary_res_txt_start\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
  • 看起来 CMake 忽略了我通过的链接器选项,所以我也尝试使用 LINK_FLAGS,所以我-Wl ...从 COMPILE_FLAGS_MAIN 中删除,并将 set_target_properties 调用修改为:

    \n\n
    set_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_DIR}\n                                                    COMPILE_FLAGS ${COMPILE_FLAGS_RELEASE}\n                                                    CXX_STANDARD ${CPP_STD}\n                                                    CXX_STANDARD_REQUIRED ${CPP_STD_REQUIRED}\n                                                    CXX_EXTENSIONS ${CPP_EXTENSION_REQUIRED}\n                                                    LINK_FLAGS "-Wl,--format=binary -Wl,${PROJECT_SOURCE_DIR}/res.txt -Wl,--format=default")\n
    Run Code Online (Sandbox Code Playgroud)
  • \n
\n\n

因此,当我传递不存在的文件时,链接器会哭泣,这就是我使用 PROJECT_SOURCE_DIR 但仍然不起作用的原因。

\n\n
    \n
  • 当我将错误的路径传递给 COMPILE_FLAGS_MAIN 中的文件时,什么也不会发生。
  • \n
\n\n

有人能帮我解决这个问题吗?我不确定我做错了什么。

\n

Bot*_*tje 6

您可以为其创建一个单独的构建规则,而不是将自定义资源硬塞到链接标志中:(想法取自此处

add_custom_command(
        OUTPUT res.o
        COMMAND ld -r -b binary -o res.o res.txt
        DEPENDS res.txt)
add_executable(${app_name} ${sources} res.o)
Run Code Online (Sandbox Code Playgroud)