DEV Community

Addy
Addy

Posted on

Simple CMake to Compile Resources

Recently I have been working on a project that has a Simple Web Server, so I needed a way to serve HTML files. I didn't want to distribute the files as part of a "package" and instead wanted them compiled into the distributed binary.

I went to Google and searched c++ cmake compile resources. The first project I found was this. However this project was much more involved than I needed, going so far as to implement a mini-filesystem, much like Qt's resource system.

I wanted something more simple. I wanted to take a resource, compile it into a header as a char array.

This was my solution:

function(generate_header INPUTFILE OUTPUTFILE VARNAME) set(DONE FALSE) set(CURRENTPOS 0) file(READ ${INPUTFILE} FILEDATA HEX) string(LENGTH "${FILEDATA}" DATALEN) set(OUTPUT_DATA "") file(WRITE ${OUTPUTFILE} "#pragma once\n\nstatic const char ${VARNAME}[] = { ") foreach(BYTE_OFFSET RANGE 0 "${DATALEN}" 2) string(SUBSTRING "${FILEDATA}" "${BYTE_OFFSET}" 2 HEX_STRING) string(LENGTH "${HEX_STRING}" TEMPLEN) if ("${TEMPLEN}" GREATER 0) set(OUTPUT_DATA "${OUTPUT_DATA}0x${HEX_STRING}, ") endif() endforeach() file(APPEND ${OUTPUTFILE} "${OUTPUT_DATA}0") file(APPEND ${OUTPUTFILE} " };\n") endfunction() function(z_compile_resources RESOURCE_LIST) foreach(RESOURCE_NAME ${ARGN}) set(RESOURCE_FILENAME "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_NAME}") get_filename_component(FILENAME ${RESOURCE_NAME} NAME_WE) get_filename_component(EXT ${RESOURCE_NAME} EXT) string(SUBSTRING ${EXT} 1 -1 EXT) set(OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}_${EXT}.h") set(VARIABLE_NAME "${FILENAME}_${EXT}") generate_header(${RESOURCE_FILENAME} ${OUTPUT_FILE} ${VARIABLE_NAME}) endforeach() endfunction() 
Enter fullscreen mode Exit fullscreen mode

Now I can compile resources in my CMake file like so:

z_compile_resources(RESOURCE_FILES html/index.html ) 
Enter fullscreen mode Exit fullscreen mode

And now CMake will generate a header file that looks like this:

#pragma once  static const char index_html[] = { 0x3c, 0x68, ... , 0 }; 
Enter fullscreen mode Exit fullscreen mode

This is awesome! And now in my source file I can use it like so:

#include "index_html.h"  /* lots of code here */ std::cout << index_html << '\n'; 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)