VTK  9.3.0
vtkEncodeString.cmake
Go to the documentation of this file.
1 #[==[
2 @file vtkEncodeString.cmake
3 
4 This module contains the @ref vtk_encode_string function which may be used to
5 turn a file into a C string. This is primarily used within a program so that
6 the content does not need to be retrieved from the filesystem at runtime, but
7 can still be developed as a standalone file.
8 #]==]
9 
10 set(_vtkEncodeString_script_file "${CMAKE_CURRENT_LIST_FILE}")
11 
12 #[==[
13 @brief Encode a file as a C string at build time
14 
15 Adds a rule to turn a file into a C string. Note that any Unicode characters
16 will not be replaced with escaping, so it is recommended to avoid their usage
17 in the input.
18 
19 ~~~
21  INPUT <input>
22  [NAME <name>]
23  [EXPORT_SYMBOL <symbol>]
24  [EXPORT_HEADER <header>]
25  [HEADER_OUTPUT <variable>]
26  [SOURCE_OUTPUT <variable>]
27 
28  [ABI_MANGLE_SYMBOL_BEGIN <being>]
29  [ABI_MANGLE_SYMBOL_END <end>]
30  [ABI_MANGLE_HEADER <header>]
31 
32  [BINARY] [NUL_TERMINATE])
33 ~~~
34 
35 The only required variable is `INPUT`, however, it is likely that at least one
36 of `HEADER_OUTPUT` or `SOURCE_OUTPUT` will be required to add them to a
37 library.
38 
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`
52  bytes.
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
56  in various compilers.
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
63  be set.
64 #]==]
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"
69  "")
70 
71  if (_vtk_encode_string_UNPARSED_ARGUMENTS)
72  message(FATAL_ERROR
73  "Unrecognized arguments to vtk_encode_string: "
74  "${_vtk_encode_string_UNPARSED_ARGUMENTS}")
75  endif ()
76 
77  if (NOT DEFINED _vtk_encode_string_INPUT)
78  message(FATAL_ERROR
79  "Missing `INPUT` for vtk_encode_string.")
80  endif ()
81 
82  if (NOT DEFINED _vtk_encode_string_NAME)
83  get_filename_component(_vtk_encode_string_NAME
84  "${_vtk_encode_string_INPUT}" NAME_WE)
85  endif ()
86 
87  if (DEFINED _vtk_encode_string_EXPORT_SYMBOL AND
88  NOT DEFINED _vtk_encode_string_EXPORT_HEADER)
89  message(FATAL_ERROR
90  "Missing `EXPORT_HEADER` when using `EXPORT_SYMBOL`.")
91  endif ()
92 
93  if (DEFINED _vtk_encode_string_EXPORT_HEADER AND
94  NOT DEFINED _vtk_encode_string_EXPORT_SYMBOL)
95  message(WARNING
96  "Missing `EXPORT_SYMBOL` when using `EXPORT_HEADER`.")
97  endif ()
98 
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))
102  message(WARNING
103  "Missing `ABI_MANGLE_SYMBOL_END` or `ABI_MANGLE_HEADER` when using "
104  "`ABI_MANGLE_SYMBOL_BEGIN`.")
105  endif ()
106 
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))
110  message(WARNING
111  "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_HEADER` when using "
112  "`ABI_MANGLE_SYMBOL_END`.")
113  endif ()
114 
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))
118  message(WARNING
119  "Missing `ABI_MANGLE_SYMBOL_BEGIN` or `ABI_MANGLE_SYMBOL_END` when "
120  "using `ABI_MANGLE_HEADER`.")
121  endif ()
122 
123  if (NOT _vtk_encode_string_BINARY AND _vtk_encode_string_NUL_TERMINATE)
124  message(FATAL_ERROR
125  "The `NUL_TERMINATE` flag only makes sense with the `BINARY` flag.")
126  endif ()
127 
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")
132 
133  if (IS_ABSOLUTE "${_vtk_encode_string_INPUT}")
134  set(_vtk_encode_string_input
135  "${_vtk_encode_string_INPUT}")
136  else ()
137  set(_vtk_encode_string_input
138  "${CMAKE_CURRENT_SOURCE_DIR}/${_vtk_encode_string_INPUT}")
139  endif ()
140 
141  add_custom_command(
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}")
160 
161  if (DEFINED _vtk_encode_string_SOURCE_OUTPUT)
162  set("${_vtk_encode_string_SOURCE_OUTPUT}"
163  "${_vtk_encode_string_source}"
164  PARENT_SCOPE)
165  endif ()
166 
167  if (DEFINED _vtk_encode_string_HEADER_OUTPUT)
168  set("${_vtk_encode_string_HEADER_OUTPUT}"
169  "${_vtk_encode_string_header}"
170  PARENT_SCOPE)
171  endif ()
172 endfunction ()
173 
174 if (_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")
177 
178  set(license_topfile "// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen\n// SPDX-License-Identifier: BSD-3-Clause\n")
179  file(WRITE "${output_header}" ${license_topfile})
180  file(WRITE "${output_source}" ${license_topfile})
181 
182  file(APPEND "${output_header}"
183  "#ifndef ${output_name}_h\n#define ${output_name}_h\n\n")
184  if (export_header)
185  file(APPEND "${output_header}"
186  "#include \"${export_header}\"\n")
187  endif ()
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")
191  endif ()
192  if (export_symbol)
193  file(APPEND "${output_header}"
194  "${export_symbol} ")
195  endif ()
196 
197  if (IS_ABSOLUTE "${source_file}")
198  set(source_file_full "${source_file}")
199  else ()
200  set(source_file_full "${source_dir}/${source_file}")
201  endif ()
202  set(hex_arg)
203  if (binary)
204  set(hex_arg HEX)
205  endif ()
206  file(READ "${source_file_full}" original_content ${hex_arg})
207 
208  if (binary)
209  if (nul_terminate)
210  string(APPEND original_content "00")
211  endif ()
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")
219  endif ()
220  file(APPEND "${output_header}"
221  "#endif\n")
222 
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")
228  endif ()
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}"
239  "};\n")
240  if (abi_mangle_symbol_end)
241  file(APPEND "${output_source}"
242  "${abi_mangle_symbol_end}\n")
243  endif ()
244  else ()
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")
250  endif ()
251  file(APPEND "${output_header}"
252  "#endif\n")
253 
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}")
260 
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")
266  endif ()
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")
274  endif ()
275  endif ()
276 endif ()
@ on
Definition: vtkX3D.h:439
@ function
Definition: vtkX3D.h:249
@ time
Definition: vtkX3D.h:497
@ content
Definition: vtkX3D.h:302
@ name
Definition: vtkX3D.h:219
@ data
Definition: vtkX3D.h:315
boost::graph_traits< vtkGraph * >::vertex_descriptor source(boost::graph_traits< vtkGraph * >::edge_descriptor e, vtkGraph *)
function vtk_encode_string()
Encode a file as a C string at build time.