Artur Pyszczuk
Artur Pyszczuk

Reputation: 1930

Embedd binary data in executable using CMake

I faced some problem with embedding binary data into executable when I use CMake. The code for both options is the same and as follows:

#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;
}

When I compile it with GCC:

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

And my res.txt file stores simple "HELLO WORLD" text I get appropriate output, so everything as expected.

Now I would like to compile this code using CMake, so my attemp was:

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})

And unfortunately during linkage I got:

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

I did: cmake -Bbuild -H. && cmake --build build and my "project" structure looks like this:

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

My observations and things that I have done so far:

So here when I pass file that does not exist, linker cries that's why I used PROJECT_SOURCE_DIR but still does not work.

Can anybody help me with this? I am not sure what wrong I am doing.

Upvotes: 1

Views: 3562

Answers (1)

Botje
Botje

Reputation: 30807

Instead of shoehorning the custom resource into your link flags, you could create a separate build rule for it: (idea taken from 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)

Upvotes: 5

Related Questions