Skip to content

About

Easy-to-use CMake utility to generate C/C++ code containing binary data from files

Resources

Stars

6 stars

Watchers

1 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

embed-binaries

Easy-to-use CMake utility to generate C/C++ code containing binary data from files. Useful when you want to avoid shipping extra files, but you want to still have them separately during development.

IMPORTANT NOTE

If you are using either C++26 or newer, or C23 or newer, I strongly suggest you try using #embed:

It has compiler support, so it's fast and it even has more features. Go upgrade your compiler. Enjoy (no need to thank me, thank compiler writers as well as the C and C++ standards committees).

Features

  • Generates C/C++ source files with arrays containing binary data
  • Single CMake file with no dependencies except CMake >=3.17.5. Copy the file to your project and start using it!
  • Generated source files are updated at build-time whenever the original assets get modified (CMake's add_custom_command is used)
  • Platform-independent, since all of the implementation is written in CMake
  • Can optionally generate a constexpr array for compile-time manipulation in C++

Reference

embed_binaries(<generated-target-name>
  [ASSET
    NAME <name>
    PATH <path>
    [BYTE_TYPE <c-cpp-type>]
    [CONSTEXPR]
    [NULL_TERMINATE]
  ]...)
  • NAME: name of the asset (the name of the generated file and variable)
  • PATH: path to the asset file (absolute of relative to CMAKE_CURRENT_SOURCE_DIR)
  • BYTE_TYPE: type of the elements of the generated array. Defaults to: "unsigned char". Useful when embedding ascii string data (use BYTE_TYPE "char")
  • CONSTEXPR: by default, an extern const array will be declared in the header, with the contents in a corresponding .c file, which makes the header as short as possible, improving compile time, especially when embedding larger assets. If you specify this option, a constexpr array will be generated instead (which must go in the header)
  • NULL_TERMINATE: append a null-terminator (0 byte) at the end of the embedded data. Useful when embedding string data that will be used with APIs expecting null-terminated strings

Disclaimer

Having the implementation written in CMake makes this utility easy-to-use and portable, but that also makes it rather slow. This is not really noticeable for small assets (<1MB), but you will notice it as you have more and more data. During my tests, generating the code for an ~8MB big file took ~17 seconds in my machine (and generated a ~40MB big .c file!). Therefore, this utility is intended for projects where ease of use is important (e.g. personal projects) or for projects that will only have a few assets to embed. If you have different plans, I would suggest investing some time on a different solution

Example

NOTE: see the example/ directory for a full example project

include("path/to/embed-binaries.cmake")

embed_binaries(my-embedded-binaries
    ASSET
        NAME "application_logo"
        PATH "assets/application_logo.png"
    ASSET
        NAME "vertex_shader"
        PATH "shaders/dummy_shader.vert"
        BYTE_TYPE "char"
    
        CONSTEXPR # The data will be placed in the header
        
        # OpenGL does not require null-terminated strings for shaders, this is not a good example
        NULL_TERMINATE
    # ASSET ...
)

add_executable(my-executable
    # files...
)
target_link_libraries(my-executable PRIVATE my-embedded-binaries)

Sample generated code

With CONSTEXPR and DATA_TYPE "char":
fragment_shader.h

#pragma once

#ifndef __cplusplus
#error "'constexpr' is a C++ feature"
#endif

constexpr char embedded_fragment_shader[226] = {
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x33,0x30,0x0d,0x0a,0x0d,0x0a,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x5f,
0x63,0x6f,0x6f,0x72,0x64,0x69,0x6e,0x61,0x74,0x65,0x73,0x3b,0x0d,0x0a,0x0d,0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x6d,0x6f,0x64,
0x75,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0d,0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,
0x44,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
0x72,0x3b,0x0d,0x0a,0x0d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0d,0x0a,0x7b,0x0d,0x0a,0x09,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x2c,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x5f,0x63,0x6f,0x6f,
0x72,0x64,0x69,0x6e,0x61,0x74,0x65,0x73,0x29,0x20,0x2a,0x20,0x6d,0x6f,0x64,0x75,0x6c,0x61,0x74,0x69,0x6f,0x6e,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0d,0x0a,0x7d,
0x0d,0x0a,
};

Normal mode:
application_logo.h

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

extern const unsigned char embedded_application_logo[212253];

#ifdef __cplusplus
}
#endif

application_logo.c

#include "application_logo.h"

#ifdef __cplusplus
extern "C" {
#endif

const unsigned char embedded_application_logo[212253] = {
0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,0x00,0x00,0x02,0x64,0x00,0x00,0x01,0x99,0x08,0x02,0x00,0x00,0x00,0xa8,0x97,0xba,
/* 6632 more lines... */
};

#ifdef __cplusplus
}
#endif

About

Easy-to-use CMake utility to generate C/C++ code containing binary data from files

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages