使用CMake

时间:2018-06-11 11:33:16

标签: c++ cmake

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

#include <iostream>

extern char _binary_res_txt_start;
extern char _binary_res_txt_end;

int main (int, char**) {
    for (char* c = &_binary_res_txt_start; c != &_binary_res_txt_end; ++c) {
        std::cout << *c;
    }   
    return 0;
}

当我用GCC编译它时:

g++ -std=c++17 -Wall -Wextra -Wpedantic -Werror=return-type -Wl,--format=binary -Wl,res.txt -Wl,--format=default  main.cpp -o main

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

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

cmake_minimum_required(VERSION 3.10)
set(app_name main)
project(${app_name} CXX)
set(BIN_DIR "${PROJECT_SOURCE_DIR}/bin")
set(OPTIMIZATION_LEVEL " -O0")
set(COMPILE_FLAGS_MAIN "-Wall -Wextra -Wpedantic -Wno-deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wl,--format=binary -Wl,res.txt -Wl,--format=default")
set(COMPILE_FLAGS_RELEASE "${COMPILE_FLAGS_MAIN} ${OPTIMIZATION_LEVEL}")
set(CPP_STD "17")
set(CPP_STD_REQUIRED "ON")
set(CPP_EXTENSION_REQUIRED "OFF")

file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/cpp/*.cpp")

add_executable(${app_name} ${SOURCES})

set_target_properties(${app_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BIN_DIR}
                                                COMPILE_FLAGS ${COMPILE_FLAGS_RELEASE}
                                                CXX_STANDARD ${CPP_STD}
                                                CXX_STANDARD_REQUIRED ${CPP_STD_REQUIRED}
                                                CXX_EXTENSIONS ${CPP_EXTENSION_REQUIRED})

不幸的是,在联系过程中,我得到了:

main.cpp:(.text+0x13): undefined reference to `_binary_res_txt_start'
main.cpp:(.text+0x1b): undefined reference to `_binary_res_txt_end'

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

├── CMakeLists.txt
├── res.txt
└── src
    └── cpp
        └── main.cpp

我的观察和迄今为止我所做的事情:

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

    0000000000601050 D _binary_res_txt_end
    000000000000000c A _binary_res_txt_size
    0000000000601044 D _binary_res_txt_start
    
  • 当我用CMake编译它时,那些对象没有被初始化:

    U _binary_res_txt_end
    U _binary_res_txt_start
    
  • 看起来CMake忽略了我已经传递的链接器选项,所以我也尝试了LINK_FLAGS,所以我从COMPILE_FLAGS_MAIN中删除了-Wl ...并修改了set_target_properties调用:

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

所以在这里,当我传递不存在的文件时,链接器会哭出这就是为什么我使用PROJECT_SOURCE_DIR但仍然无效。

  • 当我将错误的路径传递给COMPILE_FLAGS_MAIN中的文件时,没有任何反应。

有人可以帮我这个吗?我不确定我做错了什么。

1 个答案:

答案 0 :(得分:1)

您可以为自己创建一个单独的构建规则,而不是将自定义资源用于链接标记:(来自here的想法)

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)