Is it possible to read a file at compile time?
Building on teivaz's idea, I wonder if the usual "stringize after expansion" trick will work:
#define STRINGIZE(...) #__VA_ARGS__
#define EXPAND_AND_STRINGIZE(...) STRINGIZE(__VA_ARGS__)
constexpr std::string shader_source = EXPAND_AND_STRINGIZE(
#include "~/.foo.glsl"
);
Still, I would go for a conventional extern const char[]
declaration resolved to the content by the linker. The article "Embedding a File in an Executable, aka Hello World, Version 5967" has an example:
# objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 data.txt data.o
Naturally you should change the --output
and --binary-architecture
commands to match your platform. The filename from the object file ends up in the symbol name, so you can use it like so:
#include <stdio.h>
/* here "data" comes from the filename data.o */
extern "C" char _binary_data_txt_start;
extern "C" char _binary_data_txt_end;
main()
{
char* p = &_binary_data_txt_start;
while ( p != &_binary_data_txt_end ) putchar(*p++);
}
How to read a file at compile time in C++?
the classic way to do this is to write an awk or perl script that reads the data file and generates a .H file
Read File At Compile Time (constexpr or other)
C++20 might ship with std::embed
. Have a look at P1040. If this lands, you can
constexpr std::span<const std::byte> someBytes = std::embed("pathToFile");
Import a text file to std::string at complie time
Google is full of C-ish answers.
Those answers will work in C++ as well. C++ doesn't have features that would make this easier... yet 1.
An overview of options that are available:
- Copy the content into a compiled object file. This is not portable across language implementations. May be achieved with a tool such as
objcopy
. - Include the file with a linker script. This is not portable across language implementations.
- Generate a source file (based on the input file) which initialises an array of bytes that have the content.
xxd
tool (from thevim
editor) can be used to do this. This is portable, although there may be implementation specific limits to how large files can be included like this.
It is also worth it to re-consider whether importing text file at compile time is even a good idea for your use case. Often, it is more useful to read the file at runtime because it allows the file to easily be changed without requiring re-compilation.
1 There is a proposal to add such feature to a future standard.
How to read in files with a specific file ending at compile time in nim?
Thanks to enthus1ast from nim's discord server I arrived at an answer: using the collect macro with the walkDir
iterator.
The walkDir
iterator does not make use of things that are only available at runtime and thus can be safely used at compiletime. With the collect macro you can iterate over all your files in a specific directory and collect their paths into a compile-time seq!
Basically you start writing collect-block, which is a simple for-loop that at its end evaluates to some form of value. The collect macro will put them all into a seq at the end.
The end result looks pretty much like this:
import std/[sequtils, sugar, strutils, strformat, os]
import webgui
const resourceFolder = "/home/philipp/dev/imagestable/html"
proc getFilesWithEnding(folder: string, fileEnding: string): seq[string] {.compileTime.} =
result = collect:
for path in walkDir(folder):
if path.path.endswith(fmt".{fileEnding}"): path.path
proc readFilesWithEnding(folder: string, fileEnding: string): seq[string] {.compileTime.} =
result = getFilesWithEnding(folder, fileEnding).mapIt(staticRead(it))
Related Topics
Store Results of Std::Stack .Pop() Method into a Variable
Assert That Code Does Not Compile
Fatal Error C1083: Cannot Open Include File: 'Xyz.H': No Such File or Directory
How to Output Array of Doubles to Hard Drive
G++' Is Not Recognized as an Internal or External Command, Operable Program or Batch File
What Exactly Is a Namespace and Why Is It Necessary
Clang-Omp in Xcode Under El Capitan
Use Const Wherever Possible in C++
Convert Std::Variant to Another Std::Variant with Super-Set of Types
Immediate Exit of 'While' Loop in C++
Why Class Size Depend Only on Data Members and Not on Member Functions
Is Clrscr(); a Function in C++
Set the Digits After Decimal Point
Partial Specialization Ordering with Non-Deduced Context