Published:

Jarle Aase

Compiling and using a code-generator with CMake

bookmark 1 min read

Using code-generators is quite common for C++ developers. As part of the preparations for releasing stbl, the program that converts this site from a handful of text files to a modern, reponsive website, I wanted to embed some html template files in the binary itself. One simple way to do that is to create a header file and a source file that creates a std::map with the file name as the key and a pointer to a const char * as the value. Since these templates are files that change rapidly as the project matures, I wanted to generate the code that embeds the files when the project is built. The code-generator is just a few lines of C++ code. But that also need to be built as part of the build process. So what I needed to happen was:

The CMakeLists.txt file to build the code generator looks like:

project (mkres)
add_executable(mkres main.cpp)
target_link_libraries(mkres ${DEFAULT_LIBRARIES})

The CMakeLists.txt file that use the tool and build the library looks like:

project(libstbl)
add_custom_command(
    COMMAND mkres stbl embedded_templates_ templates_res.cpp templates_res.h ${STBL_ROOT_DIR}/examples/default/templates/*.html
    DEPENDS ${STBL_ROOT_DIR}/examples/default/templates/*.html mkres
    OUTPUT templates_res.cpp templates_res.h
    COMMENT "Embedding templates..."
    )

set(SOURCES
    ...
    templates_res.cpp
    )

add_library(libstbl ${SOURCES})
target_include_directories(libstbl PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

The add_custom_command function DEPENDS on mkres, which makes CMake build it before it is used. The OUTPUT tells CMake what files are built, and when one of those files are specified as a source for the library, it calls the code generator prior to building the library.

The generated files ends up in a directory created by cmake. In order to #include the header-file from the source code of the library I am building, I needed to call the target_include_directories function to add it's path to the list of paths to scan for included files.

I have not done this (built the required tool as part of the build-process) with CMake before. However, it was easy and CMake takes care of the paths to the tool and the generated source code itself. Basically, I just state my intentions to CMake - and it just works.

Nice!