3

I have a C++ program which I'd like to have output a certain text file at some point. Of course I could have it open, read, and output the text file, but then I have to keep the binary and the text file in sync and located together. I'd rather just compile the file in as a string in some part of my build process.

I've seen things like this done as parts of various IDEs. However I'm building from the command line with gcc or clang.

Of course I could just write my own script that produces a temporary .cpp file at compile time and make that a build step in my Makefile, but I was wondering if there was a more established option for doing this.

I would prefer not to take on a lot of other dependencies just to do this.

Daniel McLaury
  • 4,047
  • 1
  • 15
  • 37
  • I've used `xxd -i datafile.txt > datafile.cpp` to create a compilable "container" of the bytes of the resource (whether text, audio, image, video). – Eljay Dec 12 '19 at 18:56
  • This proposal exist: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1040r4.html – dalle Dec 12 '19 at 19:02
  • I'd do this: https://balau82.wordpress.com/2012/02/19/linking-a-binary-blob-with-gcc/ – HolyBlackCat Dec 12 '19 at 19:25

3 Answers3

6

There is a proposal to add std::embed: p1040r4. Its purpose is to provide pretty much this feature.

Until that proposal is standardised and implemented, you are going to have to either

  1. Generate the source file from the input file. Tools exist for this. xxd for example.

  2. Generate an object file from the input. A generic tool for this: objcopy.

  3. Inject with assembler: .incbin

The source approach is most portable.


Note that embedding is not necessarily the best choice. Using a non-embedded, separate file can often be advantageous since it can allow easy modification of the input file without re-building the executable. It might even be worth it to let the user pass a path to the file so that they can substitute their own. My point is that you'll be trading one convenience with another.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

C and C++ don't currently have direct support for this.

One option is to convert the data to a valid C string literal, or array declaration. In the array case, while a {0x10, 0x40, 0x90} style declaration might seem big, it should be compiled down to just the original bytes.

There are many tools for this, for example on Linux (or if you get a Windows port) you probably have xxd from vim, xxd -i hello_world.txt:

unsigned char helloworld_txt[] = {
  0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21,
  0x0a, 0x0a
};
unsigned int helloworld_txt_len = 14;

Additionally, many specific platforms also have a means to embed additional resource files in the program, this isn't part of the IDE, it's part of your target platform / toolchain.

For example on Windows there is LoadResource etc. along with a bunch of specific ones for strings, icons, images, etc., and a "Resource Compiler" to embed them (as well as the MS one, MinGW at least supports this). OSX has bundles. And on Linux you can add files into the ELF (using objcopy), which you can access in C/C++ as special extern symbols.

Fire Lancer
  • 29,364
  • 31
  • 116
  • 182
0

This is ugly and requires to escape ", but it is simple and works:

// contents of file: resource
"hello world"

#include<iostream>

int main() {

const std::string x = 
#include "resource"
;
std::cout << x;  
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 1
    Since you need to have specially prepared the "resource" file to be a valid string (with escape codes etc.), I think having that declare a variable constant is preferable. Also with a string literal already in memory, using something like `string_view` would be useful for large items. – Fire Lancer Dec 12 '19 at 19:12
  • @FireLancer yeah right, I was hoping that it is possible to not include the `"` in the file, but then realized that it isnt. I'll just leave it and wait for the downvotes – 463035818_is_not_an_ai Dec 12 '19 at 19:15
  • Could a raw string literal be used with this technique? – drescherjm Dec 12 '19 at 19:20
  • 2
    @drescherjm It would be better. Still, there would be one sequence that must not be present in the input string. – eerorika Dec 12 '19 at 19:24