-1

I'm working on a project that has a directory of files: myFiles.

I need something like:

const vector<string> configs = { contents_of_file0, contents_of_file1, ... };

It is desired that the contents of these files be part of the binary, as opposed to being read at runtime.

Is there a clean way to do this?

Today, there is a massive hack, the contents of all the files are concatenated into a single #define, by a build script.

#define contents "a supper massive string that is too large for some compilers to ingest"

This #define is later parsed at runtime.

I'm looking for a cleaner way...

CraigDavid
  • 1,046
  • 1
  • 12
  • 26
  • Would it be possible to slightly modify the files and enclose their contents into raw strings? If so, then you could just `#include` them into the vector's initializer list. – Quimby Aug 27 '21 at 00:12
  • You might link them into the executable like [this](https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc). This is about GCC, but maybe other compilers/linkers support it – Lala5th Aug 27 '21 at 00:14
  • 2
    `It is desired that the contents of these files be part of the binary` -- it sounds like what you want is a *resource file* to be linked into your executable. That's possible to do, but it's not part of C++, so different OS's and compilers have different ways to do it. – Jeremy Friesner Aug 27 '21 at 00:15
  • You could write a script to write header files with that content, and call it as part of the build process. – Kenny Ostrom Aug 27 '21 at 01:32
  • 2
    *"This #define is later parsed at runtime."* -- sorry, no. All `#define`s are parsed by the pre-processor at compile time. However, it might be that the resulting string literal is parsed at runtime. – JaMiT Aug 27 '21 at 01:54
  • Does this answer your question? [Import text file into raw string literal at compile time](https://stackoverflow.com/questions/37292222/import-text-file-into-raw-string-literal-at-compile-time) – JaMiT Aug 27 '21 at 02:00
  • Thank you all for the resources! I ended up solving the problem by using xxd -i – CraigDavid Aug 27 '21 at 23:59

2 Answers2

1

Is there a clean way to do this?

There is proposed feature for this purpose that may end up in a future standard.

Until then, you can use meta programming: Generate source code from the input file. The generated source should contain the initialiser based on the file. An open source program exists that can do this: xxd

concatenated into a single #define

I don't see an advantage to this. If you want separate strings, then generate separate initialisers. I also don't see a need for a macro.


I also recommend carefully re-considering whether it even makes sense to want this. Loading a massive executable isn't any faster than reading large files, and reading files is more flexible.

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

This #define is later parsed at runtime. This is the wrong statement, define is a preprocessor, which is done in the very early stage of compiling. And for static strings, it can be parsed in build time since c++17, this is also a consideration solution to generate constepr vector when combined with constexpr vector from c++2a.

May consider using the include hack for simplicity, if you use it please don't forget to set up the dependency for tbl file in makefile:

For the source file:

int main(int argc, char* argv[]) {
  std::vector<std::string> vec = {
#include "1.tbl"
#include "2.tbl"
  };

  for (auto& v : vec) {
    std::cout << v << std::endl;
  }
  return 0;
}

For the table file 1.tbl:

"1","2","3",

For the table file 2.tbl:

"a", "b","c",

We get the output:

1
2
3
a
b
c
prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42