Why a resource compiler in the 21st century?
Starting a c++ project that will potentially need static string resources (i.e. Lua scripts) makes one search for an easy way to embed large strings in an executable. There are many ways of including static resources, but there seems to be no simple but robust, platform-independent way [1. http://stackoverflow.com/questions/5479691/is-there-any-standard-way-of-embedding-resources-into-linux-executable-image]. For fast prototyping and one-shot projects, I’d like to have lightweight, minimum-configuration and install solution to the problem of embedding binary resources without having to use a large framework.
Premake, my favourite light-weight meta-build system contains a number of Lua scripts in its binary. These are embedded using a Lua script into a simple array of C-string constants. This is the simplicity that in my view should be strived for. ris is an attempt to do something similar for general c++ projects with a possibility of embedding binary blobs.
ris – cross-platform resource compiler for c++
The project (ris@github) is in its infancy, but seems already to be usable. Here’s a preview:
Defining and compiling resources
ris <path_to>/<resources>.json
with an input file as this self-explaining one:
{
"namespace" : "test",
"header" : "acceptance_test/resource.h",
"source" : "acceptance_test/resource.cpp",
"resources" : [
{
"name" : "string_test",
"source_type" : "string",
"source" : "plain text"
},
{
"name" : "binary_file_test",
"source_type" : "file",
"source" : "test.bin"
}
]
}
will generate two c++11 files to include in your project, enabling easy resource retrieval:
std::string res = test::Resource::string_test();
or
std::string res = test::Resource::Get("string_test");
Update 30.07.2015: now resources can be defined more concisely in YAML. A minimal resource definition in YAML looks like the following:
header: "res.h"
source: "res.cpp"
resources:
-
compression: "LZ4F"
name: "some_text"
source: "some text"
source_type: "string"
Enumerating the resources
Resource keys in the compiled resource can be enumerated passing a callable to GetKeys
:
std::vector<std::string> keys;
test::Resource::GetKeys([&keys](char const* key){
keys.emplace_back(key);
});
Compression
Using an optional compression library bundle, adding a compression
property to a resource description enables transparent (de)compression:
"compression" : "LZ4HC"
Customization
updated 24.11.2014:
ris now uses text resources generated and bootstrapped by its own early version. The goal is to make The code generator is customizable. The default template can be seen in template.json, and the generated header in template.h. The generation sequence can be seen in ris.cpp.
Using the second parameter to ris
, it’s possible to override strings in the generator template. See an example below.
C++03
updated 27.11.2014:
One such customization is available in template_cpp03.json, where the C++11 constructs are replaced with generateable C++03 constructs.
To generate the resources using the C++03 template:
ris my_template.json template_cpp03.json
Why C++?
Such code generator as ris
could most probably be developed more rapidly using any other programming language with a huge framework and a ton of libraries behind them. My personal preference for certain kinds of small projects lies in the area of self-contained single-binary/single-file executables or libraries, such as Lua. Lua is the primary motivation for this project, as it is itself a compact library for building flexible and extensible prototypes and tools. ris
can act as a bootstrapping component to embed resources for building specialized shell-scripting replacements, i.e. for massive scripted file operations.
Source
https://github.com/d-led/ris
There is a number of paths this project can take from here. Features, such as robustness, performance or flexibility could all be addressed, but most probably ris will be shaped by its usage or absence of such.