3

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:

  • When I compile with command line nm main shows that objects are initialized

    0000000000601050 D _binary_res_txt_end
    000000000000000c A _binary_res_txt_size
    0000000000601044 D _binary_res_txt_start
    
  • When I compile it with CMake then those objects are not initialized:

    U _binary_res_txt_end
    U _binary_res_txt_start
    
  • It looks like CMake ignores linker option that I have passed, so I tried also with LINK_FLAGS, so I removed -Wl ... from COMPILE_FLAGS_MAIN and I modified set_target_properties call to:

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

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.

  • When I pass wrong path to file in COMPILE_FLAGS_MAIN then nothing happens.

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

2
  • Does this answer your question? Embed resources (eg, shader code; images) into executable/library with CMake Commented Dec 13, 2022 at 2:48
  • @snake_case I think the questions here and there are not exactly the same, since this one already has a work approach outside of CMake and wants to "hook it in" to CMake, whereas the other doesn't ask for a approach in as specific a way as here. But this answer there does look possibly related/useful in resolving this question. Commented Dec 16, 2022 at 1:37

1 Answer 1

7

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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.