2@file vtkEncodeString.cmake
4This
module contains the @ref vtk_encode_string function which may be used to
5turn a file into a C string. This is primarily used within a program so that
6the content does not need to be retrieved from the filesystem at runtime, but
7can still be developed as a standalone file.
10set(_vtkEncodeString_script_file "${CMAKE_CURRENT_LIST_FILE}")
13@brief Encode a file as a C string at build time
15Adds a rule to turn a file into a C string. Note that any Unicode characters
16will not be replaced with escaping, so it is recommended to avoid their usage
23 [EXPORT_SYMBOL <symbol>]
24 [EXPORT_HEADER <header>]
25 [HEADER_OUTPUT <variable>]
26 [SOURCE_OUTPUT <variable>]
28 [ABI_MANGLE_SYMBOL_BEGIN <being>]
29 [ABI_MANGLE_SYMBOL_END <end>]
30 [ABI_MANGLE_HEADER <header>]
32 [BINARY] [NUL_TERMINATE])
35The only required variable is `INPUT`, however, it is likely that at least one
36of `HEADER_OUTPUT` or `SOURCE_OUTPUT` will be required to add them to a
39 * `INPUT`: (Required) The path to the file to be embedded. If a relative path
40 is given, it will be interpreted as being relative to
41 `CMAKE_CURRENT_SOURCE_DIR`.
42 * `NAME`: This is the base name of the files that will be generated as well
43 as the variable name for the C string. It defaults to the basename of the
44 input without extensions.
45 * `EXPORT_SYMBOL`: The symbol to use for exporting the variable. By default,
46 it will not be exported. If set, `EXPORT_HEADER` must also be set.
47 * `EXPORT_HEADER`: The header to include for providing the given export
48 symbol. If set, `EXPORT_SYMBOL` should also be set.
49 * `HEADER_OUTPUT`: The variable to store the generated header path.
50 * `SOURCE_OUTPUT`: The variable to store the generated source path.
51 * `BINARY`: If given, the data will be written as an array of `unsigned char`
53 * `NUL_TERMINATE`: If given, the binary data will be `NUL`-terminated. Only
54 makes sense with the `BINARY` flag. This is intended to be used if
55 embedding a file as a C string exceeds compiler limits on string literals
57 * `ABI_MANGLE_SYMBOL_BEGIN`: Open a mangling namespace with the given symbol.
58 If given, `ABI_MANGLE_SYMBOL_END` and `ABI_MANGLE_HEADER` must also be set.
59 * `ABI_MANGLE_SYMBOL_END`: Close a mangling namespace with the given symbol.
60 If given, `ABI_MANGLE_SYMBOL_BEGIN` and `ABI_MANGLE_HEADER` must also be set.
61 * `ABI_MANGLE_HEADER`: The header which provides the ABI mangling symbols.
62 If given, `ABI_MANGLE_SYMBOL_BEGIN` and `ABI_MANGLE_SYMBOL_END` must also
65function (vtk_encode_string)
66 cmake_parse_arguments(PARSE_ARGV 0 _vtk_encode_string
67 "BINARY;NUL_TERMINATE
"
68 "INPUT;NAME;EXPORT_SYMBOL;EXPORT_HEADER;HEADER_OUTPUT;SOURCE_OUTPUT;ABI_MANGLE_SYMBOL_BEGIN;ABI_MANGLE_SYMBOL_END;ABI_MANGLE_HEADER
"
71 if (_vtk_encode_string_UNPARSED_ARGUMENTS)
74 "${_vtk_encode_string_UNPARSED_ARGUMENTS}
")
77 if (NOT DEFINED _vtk_encode_string_INPUT)
82 if (NOT DEFINED _vtk_encode_string_NAME)
83 get_filename_component(_vtk_encode_string_NAME
84 "${_vtk_encode_string_INPUT}
" NAME_WE)
87 if (DEFINED _vtk_encode_string_EXPORT_SYMBOL AND
88 NOT DEFINED _vtk_encode_string_EXPORT_HEADER)
90 "Missing `EXPORT_HEADER` when
using `EXPORT_SYMBOL`.
")
93 if (DEFINED _vtk_encode_string_EXPORT_HEADER AND
94 NOT DEFINED _vtk_encode_string_EXPORT_SYMBOL)
96 "Missing `EXPORT_SYMBOL` when
using `EXPORT_HEADER`.
")
99 if (DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN AND
100 (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END OR
101 NOT DEFINED _vtk_encode_string_ABI_MANGLE_HEADER))
103 "Missing `ABI_MANGLE_SYMBOL_END` or `ABI_MANGLE_HEADER` when
using "
104 "`ABI_MANGLE_SYMBOL_BEGIN`.")
107 if (DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END AND
108 (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN OR
109 NOT DEFINED _vtk_encode_string_ABI_MANGLE_HEADER))
111 "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_HEADER` when using "
112 "`ABI_MANGLE_SYMBOL_END`.")
115 if (DEFINED _vtk_encode_string_ABI_MANGLE_HEADER AND
116 (NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN OR
117 NOT DEFINED _vtk_encode_string_ABI_MANGLE_SYMBOL_END))
119 "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_SYMBOL_END` when "
120 "using `ABI_MANGLE_HEADER`.")
123 if (NOT _vtk_encode_string_BINARY AND _vtk_encode_string_NUL_TERMINATE)
125 "The `NUL_TERMINATE` flag only makes sense with the `BINARY` flag.")
128 set(_vtk_encode_string_header
129 "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.h
")
130 set(_vtk_encode_string_source
131 "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.cxx
")
133 if (IS_ABSOLUTE "${_vtk_encode_string_INPUT}
")
134 set(_vtk_encode_string_input
135 "${_vtk_encode_string_INPUT}
")
137 set(_vtk_encode_string_input
138 "${CMAKE_CURRENT_SOURCE_DIR}/${_vtk_encode_string_INPUT}
")
142 OUTPUT ${_vtk_encode_string_header}
143 ${_vtk_encode_string_source}
144 DEPENDS "${_vtkEncodeString_script_file}
"
145 "${_vtk_encode_string_input}
"
146 COMMAND "${CMAKE_COMMAND}
"
147 "-Dsource_dir=${CMAKE_CURRENT_SOURCE_DIR}
"
148 "-Dbinary_dir=${CMAKE_CURRENT_BINARY_DIR}
"
149 "-Dsource_file=${_vtk_encode_string_input}
"
150 "-Doutput_name=${_vtk_encode_string_NAME}
"
151 "-Dexport_symbol=${_vtk_encode_string_EXPORT_SYMBOL}
"
152 "-Dexport_header=${_vtk_encode_string_EXPORT_HEADER}
"
153 "-Dabi_mangle_symbol_begin=${_vtk_encode_string_ABI_MANGLE_SYMBOL_BEGIN}
"
154 "-Dabi_mangle_symbol_end=${_vtk_encode_string_ABI_MANGLE_SYMBOL_END}
"
155 "-Dabi_mangle_header=${_vtk_encode_string_ABI_MANGLE_HEADER}
"
156 "-Dbinary=${_vtk_encode_string_BINARY}
"
157 "-Dnul_terminate=${_vtk_encode_string_NUL_TERMINATE}
"
158 "-D_vtk_encode_string_run=ON
"
159 -P "${_vtkEncodeString_script_file}
")
161 if (DEFINED _vtk_encode_string_SOURCE_OUTPUT)
162 set("${_vtk_encode_string_SOURCE_OUTPUT}
"
163 "${_vtk_encode_string_source}
"
167 if (DEFINED _vtk_encode_string_HEADER_OUTPUT)
168 set("${_vtk_encode_string_HEADER_OUTPUT}
"
169 "${_vtk_encode_string_header}
"
174if (_vtk_encode_string_run AND CMAKE_SCRIPT_MODE_FILE)
175 set(output_header "${binary_dir}/${output_name}.h
")
176 set(output_source "${binary_dir}/${output_name}.cxx
")
178 set(license_topfile "
179 file(WRITE
"${output_header}" ${license_topfile})
180 file(WRITE
"${output_source}" ${license_topfile})
182 file(APPEND
"${output_header}"
183 "#ifndef ${output_name}_h\n#define ${output_name}_h\n\n")
185 file(APPEND
"${output_header}"
186 "#include \"${export_header}\"\n")
188 if (abi_mangle_header AND abi_mangle_symbol_begin)
189 file(APPEND "${output_header}
"
190 "#include \
"${abi_mangle_header}\"\n\n${abi_mangle_symbol_begin}\n\n")
193 file(APPEND "${output_header}
"
197 if (IS_ABSOLUTE "${source_file}
")
198 set(source_file_full "${source_file}
")
200 set(source_file_full "${source_dir}/${source_file}
")
206 file(READ "${source_file_full}
" original_content ${hex_arg})
210 string(APPEND original_content "00
")
212 string(LENGTH "${original_content}
" output_size)
213 math(EXPR output_size "${output_size} / 2
")
214 file(APPEND "${output_header}
"
215 "extern const unsigned char ${output_name}[${output_size}];\n\n
")
216 if (abi_mangle_symbol_end)
217 file(APPEND "${output_header}
"
218 "${abi_mangle_symbol_end}\n
")
220 file(APPEND "${output_header}
"
223 file(APPEND "${output_source}
"
224 "#include \
"${output_name}.h\"\n\n")
225 if (abi_mangle_symbol_begin)
226 file(APPEND
"${output_source}"
227 "${abi_mangle_symbol_begin}\n\n")
229 file(APPEND "${output_source}
"
230 "const unsigned char ${output_name}[${output_size}] = {\n
")
231 string(REGEX REPLACE "\([0-9a-f][0-9a-f]\)
" ",0x\\1
" escaped_content "${original_content}
")
232 # Hard line wrap the file.
233 string(REGEX REPLACE "\(..........................................................................,\)
" "\\1\n
" escaped_content "${escaped_content}
")
234 # Remove the leading comma.
235 string(REGEX REPLACE "^,
" "" escaped_content "${escaped_content}
")
236 file(APPEND "${output_source}
"
237 "${escaped_content}\n
")
238 file(APPEND "${output_source}
"
240 if (abi_mangle_symbol_end)
241 file(APPEND "${output_source}
"
242 "${abi_mangle_symbol_end}\n
")
245 file(APPEND "${output_header}
"
246 "extern const char *${output_name};\n\n
")
247 if (abi_mangle_symbol_end)
248 file(APPEND "${output_header}
"
249 "${abi_mangle_symbol_end}\n\n
")
251 file(APPEND "${output_header}
"
254 # Escape literal backslashes.
255 string(REPLACE "\\
" "\\\\
" escaped_content "${original_content}
")
256 # Escape literal double quotes.
257 string(REPLACE "\
"" "\\\"" escaped_content
"${escaped_content}")
258 # Turn newlines into newlines in the C
string.
259 string(REPLACE
"\n" "\\n\"\n\"" escaped_content
"${escaped_content}")
261 file(APPEND
"${output_source}"
262 "#include \"${output_name}.h\"\n\n")
263 if (abi_mangle_symbol_begin)
264 file(APPEND
"${output_source}"
265 "${abi_mangle_symbol_begin}\n\n")
267 file(APPEND "${output_source}
"
268 "const char *${output_name} =\n
")
269 file(APPEND "${output_source}
"
270 "\
"${escaped_content}\";\n")
271 if (abi_mangle_symbol_end)
272 file(APPEND
"${output_source}"
273 "\n${abi_mangle_symbol_end}\n")
function vtk_encode_string()
Encode a file as a C string at build time.