Investigation of a tech stack for a future project
1# GenerateWebAssets.cmake
2# Uses xxd -i to convert web assets to C byte arrays - generates both .h and .cpp
3
4cmake_minimum_required(VERSION 3.28)
5
6if(NOT INPUT_DIR OR NOT OUTPUT_CPP OR NOT OUTPUT_HEADER)
7 message(FATAL_ERROR "Usage: cmake -DINPUT_DIR=<dir> -DOUTPUT_CPP=<cpp> -DOUTPUT_HEADER=<h> -P GenerateWebAssets.cmake")
8endif()
9
10if(NOT EXISTS ${INPUT_DIR})
11 message(FATAL_ERROR "Input directory does not exist: ${INPUT_DIR}")
12endif()
13
14file(GLOB_RECURSE ASSETS "${INPUT_DIR}/*")
15list(FILTER ASSETS EXCLUDE REGEX ".*/$")
16
17set(HEADER_CONTENT "")
18set(CPP_CONTENT "")
19set(MAP_ENTRIES "")
20
21foreach(ASSET ${ASSETS})
22 file(RELATIVE_PATH REL_PATH ${INPUT_DIR} ${ASSET})
23
24 set(NAME ${REL_PATH})
25 string(REPLACE "-" "_" NAME ${NAME})
26 string(REPLACE "." "_" NAME ${NAME})
27 string(REPLACE "/" "_" NAME ${NAME})
28 string(REPLACE "\\" "_" NAME ${NAME})
29
30 # Use xxd -i via stdin to get plain byte array
31 execute_process(
32 COMMAND sh -c "cat \"${ASSET}\" | xxd -i"
33 OUTPUT_VARIABLE XXD_OUTPUT
34 RESULT_VARIABLE XXD_RESULT
35 )
36
37 if(NOT XXD_RESULT EQUAL 0)
38 message(ERROR "xxd failed for ${ASSET}")
39 continue()
40 endif()
41
42
43 string(APPEND CPP_CONTENT "static constexpr unsigned char asset_${NAME}[] = {${XXD_OUTPUT}};\n\n")
44
45 if(REL_PATH MATCHES "\\.html$")
46 set(MIME_TYPE "text/html")
47 elseif(REL_PATH MATCHES "\\.js$")
48 set(MIME_TYPE "application/javascript")
49 elseif(REL_PATH MATCHES "\\.wasm$")
50 set(MIME_TYPE "application/wasm")
51 elseif(REL_PATH MATCHES "\\.css$")
52 set(MIME_TYPE "text/css")
53 else()
54 set(MIME_TYPE "application/octet-stream")
55 endif()
56
57 string(APPEND MAP_ENTRIES " {\"${REL_PATH}\", {asset_${NAME}, sizeof(asset_${NAME}), \"${MIME_TYPE}\"}},\n")
58endforeach()
59
60# Generate header
61set(HEADER "// Auto-generated header with embedded web assets
62// Generated from ${INPUT_DIR}
63
64#pragma once
65#include <cstddef>
66#include <string_view>
67#include <unordered_map>
68
69namespace web_assets {
70
71struct AssetInfo {
72 unsigned char const* data;
73 std::size_t size;
74 std::string_view mime_type;
75};
76
77extern std::unordered_map<std::string_view, AssetInfo> asset_map;
78
79} // namespace web_assets
80")
81
82# Generate cpp
83set(CPP "// Auto-generated source with embedded web assets
84// Generated from ${INPUT_DIR}
85
86#include \"web_assets.h\"
87
88namespace web_assets {
89
90${CPP_CONTENT}std::unordered_map<std::string_view, AssetInfo> asset_map = {
91${MAP_ENTRIES}};
92
93} // namespace web_assets
94")
95
96file(WRITE "${OUTPUT_HEADER}" "${HEADER}")
97file(WRITE "${OUTPUT_CPP}" "${CPP}")
98
99message(STATUS "Generated ${OUTPUT_HEADER} and ${OUTPUT_CPP}")