I am writing an application in C++ which relies on various resources in my project. Right now, I have the relative path from the produced executable to each resource hard-coded in my sources, and that allows my program to open the files and read in the data in each resource. This works ok, but it requires that I start the executable from a specific path relative to the resources. So if I try to start my executable from anywhere else, it fails to open the files and cannot proceed.
Is there a portable way to have CMake embed my resources into the executables (or libraries) such that I can simply access them in memory at runtime instead of opening files whose paths are brittle? I have found a related question, and it looks like embedding resources can be done well enough with some ld
magic. So my question is how do I do this in a portable, cross platform manner using CMake? I actually need my application run on both x86 and ARM. I am ok with supporting only Linux (Embedded), but bonus points if anyone can suggest how to do this for Windows (Embedded) as well.
EDIT: I forgot to mention a desired property of the solution. I would like to be able to use CMake to cross-compile the application when I am building for ARM rather than have to compile it natively on my ARM target.
Also the embedded files should take advantage of CMake’s features and automatically keep the binary data up to date if the source file changes. The first thing we are interested in is figuring out how to get the data from an arbitrary file into CMake.
Sometimes it is necessary to embed resource such as icons, images, texts or even arbitrary binary data into executables. There several approaches for acomplishing this: Create a resource script, for instance resource.rc, and compile the resource to object code with the MSVC resource compiler. rc.exe or GCC/Mingw resource compiler, windres.exe.
There are several ways of embedding binary data into an executable using the linker, but that would not be cross platform across the many C++ compilers like GCC, Clang, and MSVC and others. Also the embedded files should take advantage of CMake’s features and automatically keep the binary data up to date if the source file changes.
As an alternative to the answer of sfstewman, here's a small cmake (2.8) function to convert all files in a specific folder to C data and write them in wished output file:
# Creates C resources file from files in given directory function(create_resources dir output) # Create empty output file file(WRITE ${output} "") # Collect input files file(GLOB bins ${dir}/*) # Iterate through input files foreach(bin ${bins}) # Get short filename string(REGEX MATCH "([^/]+)$" filename ${bin}) # Replace filename spaces & extension separator for C compatibility string(REGEX REPLACE "\\.| |-" "_" filename ${filename}) # Read hex data from file file(READ ${bin} filedata HEX) # Convert hex data for C compatibility string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata}) # Append data to output file file(APPEND ${output} "const unsigned char ${filename}[] = {${filedata}};\nconst unsigned ${filename}_size = sizeof(${filename});\n") endforeach() endfunction()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With