summaryrefslogtreecommitdiff
path: root/res/Embed.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'res/Embed.cmake')
-rw-r--r--res/Embed.cmake162
1 files changed, 162 insertions, 0 deletions
diff --git a/res/Embed.cmake b/res/Embed.cmake
new file mode 100644
index 00000000..8da9e1d6
--- /dev/null
+++ b/res/Embed.cmake
@@ -0,0 +1,162 @@
1# CMake Helper for Binary Resources
2# Copyright: 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
3# License: BSD 2-Clause
4
5option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF)
6
7# Build "bincat" for concatenating files.
8if (NOT ENABLE_RESOURCE_EMBED)
9 message (STATUS "Compiling bincat for merging resource files...")
10 set (_catDir ${CMAKE_BINARY_DIR}/res)
11 execute_process (COMMAND ${CMAKE_COMMAND} -E make_directory ${_catDir})
12 execute_process (COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/res WORKING_DIRECTORY ${_catDir})
13 execute_process (COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${_catDir})
14 set (BINCAT_COMMAND ${_catDir}/bincat)
15endif ()
16
17function (embed_getname output fn)
18 get_filename_component (name ${fn} NAME_WE)
19 string (REPLACE "-" "" name ${name})
20 string (REPLACE "=" "" name ${name})
21 string (SUBSTRING ${name} 0 1 first)
22 string (TOUPPER ${first} first)
23 string (SUBSTRING ${name} 1 -1 remainder)
24 set (name "${first}${remainder}")
25 get_filename_component (ext ${fn} EXT)
26 if (ext STREQUAL .ttf)
27 set (resName "font")
28 elseif (ext STREQUAL .png)
29 set (resName "image")
30 else ()
31 set (resName "blob")
32 endif ()
33 set (resName "${resName}${name}_Embedded" PARENT_SCOPE)
34endfunction (embed_getname)
35
36function (embed_write path name fnSource fnHeader)
37 message (STATUS "${path}")
38 file (READ ${path} fileData HEX)
39 string (REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," cList ${fileData})
40 string (REGEX REPLACE
41 "(0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],0x[0-9a-f][0-9a-f],)"
42 "\\1\n " cList ${cList})
43 string (LENGTH ${fileData} len)
44 math (EXPR alen "${len} / 2")
45 set (src "static const uint8_t bytes_${name}_[] = {\n")
46 string (APPEND src " ${cList}\n")
47 string (APPEND src "};
48static iBlockData data_${name}_ = {
49 .refCount = 2, .data = iConstCast(char *, bytes_${name}_), .size = ${alen}, .allocSize = ${alen}
50};
51const iBlock ${name} = { &data_${name}_ };
52")
53 set (header "extern const iBlock ${name};\n")
54 # Output the results.
55 file (APPEND ${fnSource} "${src}")
56 file (APPEND ${fnHeader} "${header}")
57endfunction (embed_write)
58
59function (embed_make)
60 set (EMB_H ${CMAKE_CURRENT_BINARY_DIR}/embedded.h)
61 set (EMB_C ${CMAKE_CURRENT_BINARY_DIR}/embedded.c)
62 if (ENABLE_RESOURCE_EMBED)
63 set (needGen NO)
64 if (NOT EXISTS ${EMB_H} OR NOT EXISTS ${EMB_C})
65 set (needGen YES)
66 else ()
67 file (TIMESTAMP ${EMB_H} genTime %s)
68 foreach (resPath ${ARGV})
69 set (fn "${CMAKE_CURRENT_LIST_DIR}/${resPath}")
70 file (TIMESTAMP ${fn} resTime %s)
71 if (${resTime} GREATER ${genTime})
72 set (needGen YES)
73 endif ()
74 endforeach (resPath)
75 endif ()
76 else ()
77 set (needGen YES)
78 endif ()
79 if (needGen)
80 if (ENABLE_RESOURCE_EMBED)
81 # Compose a source file with the resource data in an array.
82 file (WRITE ${EMB_H} "#include <the_Foundation/block.h>\n")
83 file (WRITE ${EMB_C} "#include \"embedded.h\"\n")
84 foreach (fn ${ARGV})
85 embed_getname (resName ${fn})
86 embed_write (${fn} ${resName} ${EMB_C} ${EMB_H})
87 endforeach (fn)
88 else ()
89 # Collect resources in a single binary file.
90 set (EMB_BIN ${CMAKE_CURRENT_BINARY_DIR}/resources.binary)
91 file (REMOVE ${EMB_BIN})
92 list (LENGTH ARGV fileCount)
93 execute_process (COMMAND ${BINCAT_COMMAND} ${EMB_BIN} ${ARGV}
94 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
95 OUTPUT_VARIABLE fileSizes
96 )
97 set (offsets)
98 set (fpos 0)
99 foreach (fileSize ${fileSizes})
100 list (APPEND offsets "${fpos}")
101 math (EXPR fpos "${fpos} + ${fileSize}")
102 endforeach (fileSize)
103 file (WRITE ${EMB_H} "#include <the_Foundation/block.h>\n
104#define iHaveLoadEmbed 1
105iBool load_Embed(const char *path);\n\n")
106 file (WRITE ${EMB_C} [[
107#include "embedded.h"
108#include <the_Foundation/file.h>
109#include <the_Foundation/fileinfo.h>
110
111iDeclareType(EmbedChunk)
112
113struct Impl_EmbedChunk {
114 size_t pos;
115 size_t size;
116};
117
118static const iEmbedChunk chunks_Embed_[] = {
119]])
120 set (index 0)
121 foreach (fn ${ARGV})
122 list (GET fileSizes ${index} fileSize)
123 list (GET offsets ${index} fpos)
124 file (APPEND ${EMB_C} " { ${fpos}, ${fileSize} },\n")
125 math (EXPR index "${index} + 1")
126 endforeach (fn)
127 file (APPEND ${EMB_C} "};\n\n")
128 foreach (fn ${ARGV})
129 embed_getname (resName ${fn})
130 file (APPEND ${EMB_H} "extern iBlock ${resName};\n")
131 file (APPEND ${EMB_C} "iBlock ${resName};\n")
132 endforeach (fn)
133 file (APPEND ${EMB_C} "\nstatic iBlock *blocks_Embed_[] = {\n")
134 foreach (fn ${ARGV})
135 embed_getname (resName ${fn})
136 file (APPEND ${EMB_C} " &${resName},\n")
137 endforeach (fn)
138 file (APPEND ${EMB_C} [[
139};
140
141iBool load_Embed(const char *path) {
142 const size_t fileSize = (size_t) fileSizeCStr_FileInfo(path);
143 iFile *f = iClob(newCStr_File(path));
144 if (open_File(f, readOnly_FileMode)) {
145 iForIndices(i, blocks_Embed_) {
146 const iEmbedChunk *chunk = &chunks_Embed_[i];
147 iBlock *data = blocks_Embed_[i];
148 if (chunk->pos + chunk->size > fileSize) {
149 return iFalse;
150 }
151 init_Block(data, chunk->size);
152 seek_File(f, chunk->pos);
153 readData_File(f, chunk->size, data_Block(data));
154 }
155 return iTrue;
156 }
157 return iFalse;
158}
159]])
160 endif ()
161 endif ()
162endfunction (embed_make)