VTK  9.1.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  [BINARY] [NUL_TERMINATE])
28 ~~~
29 
30 The only required variable is `INPUT`, however, it is likely that at least one
31 of `HEADER_OUTPUT` or `SOURCE_OUTPUT` will be required to add them to a
32 library.
33 
34  * `INPUT`: (Required) The path to the file to be embedded. If a relative path
35  is given, it will be interpreted as being relative to
36  `CMAKE_CURRENT_SOURCE_DIR`.
37  * `NAME`: This is the base name of the files that will be generated as well
38  as the variable name for the C string. It defaults to the basename of the
39  input without extensions.
40  * `EXPORT_SYMBOL`: The symbol to use for exporting the variable. By default,
41  it will not be exported. If set, `EXPORT_HEADER` must also be set.
42  * `EXPORT_HEADER`: The header to include for providing the given export
43  symbol. If set, `EXPORT_SYMBOL` should also be set.
44  * `HEADER_OUTPUT`: The variable to store the generated header path.
45  * `SOURCE_OUTPUT`: The variable to store the generated source path.
46  * `BINARY`: If given, the data will be written as an array of `unsigned char`
47  bytes.
48  * `NUL_TERMINATE`: If given, the binary data will be `NUL`-terminated. Only
49  makes sense with the `BINARY` flag. This is intended to be used if
50  embedding a file as a C string exceeds compiler limits on string literals
51  in various compilers.
52 #]==]
54  cmake_parse_arguments(PARSE_ARGV 0 _vtk_encode_string
55  "BINARY;NUL_TERMINATE"
56  "INPUT;NAME;EXPORT_SYMBOL;EXPORT_HEADER;HEADER_OUTPUT;SOURCE_OUTPUT"
57  "")
58 
59  if (_vtk_encode_string_UNPARSED_ARGUMENTS)
60  message(FATAL_ERROR
61  "Unrecognized arguments to vtk_encode_string: "
62  "${_vtk_encode_string_UNPARSED_ARGUMENTS}")
63  endif ()
64 
65  if (NOT DEFINED _vtk_encode_string_INPUT)
66  message(FATAL_ERROR
67  "Missing `INPUT` for vtk_encode_string.")
68  endif ()
69 
70  if (NOT DEFINED _vtk_encode_string_NAME)
71  get_filename_component(_vtk_encode_string_NAME
72  "${_vtk_encode_string_INPUT}" NAME_WE)
73  endif ()
74 
75  if (DEFINED _vtk_encode_string_EXPORT_SYMBOL AND
76  NOT DEFINED _vtk_encode_string_EXPORT_HEADER)
77  message(FATAL_ERROR
78  "Missing `EXPORT_HEADER` when using `EXPORT_SYMBOL`.")
79  endif ()
80 
81  if (DEFINED _vtk_encode_string_EXPORT_HEADER AND
82  NOT DEFINED _vtk_encode_string_EXPORT_SYMBOL)
83  message(WARNING
84  "Missing `EXPORT_SYMBOL` when using `EXPORT_HEADER`.")
85  endif ()
86 
87  if (NOT _vtk_encode_string_BINARY AND _vtk_encode_string_NUL_TERMINATE)
88  message(FATAL_ERROR
89  "The `NUL_TERMINATE` flag only makes sense with the `BINARY` flag.")
90  endif ()
91 
92  set(_vtk_encode_string_header
93  "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.h")
94  set(_vtk_encode_string_source
95  "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.cxx")
96 
97  if (IS_ABSOLUTE "${_vtk_encode_string_INPUT}")
98  set(_vtk_encode_string_input
99  "${_vtk_encode_string_INPUT}")
100  else ()
101  set(_vtk_encode_string_input
102  "${CMAKE_CURRENT_SOURCE_DIR}/${_vtk_encode_string_INPUT}")
103  endif ()
104 
105  add_custom_command(
106  OUTPUT ${_vtk_encode_string_header}
107  ${_vtk_encode_string_source}
108  DEPENDS "${_vtkEncodeString_script_file}"
109  "${_vtk_encode_string_input}"
110  COMMAND "${CMAKE_COMMAND}"
111  "-Dsource_dir=${CMAKE_CURRENT_SOURCE_DIR}"
112  "-Dbinary_dir=${CMAKE_CURRENT_BINARY_DIR}"
113  "-Dsource_file=${_vtk_encode_string_input}"
114  "-Doutput_name=${_vtk_encode_string_NAME}"
115  "-Dexport_symbol=${_vtk_encode_string_EXPORT_SYMBOL}"
116  "-Dexport_header=${_vtk_encode_string_EXPORT_HEADER}"
117  "-Dbinary=${_vtk_encode_string_BINARY}"
118  "-Dnul_terminate=${_vtk_encode_string_NUL_TERMINATE}"
119  "-D_vtk_encode_string_run=ON"
120  -P "${_vtkEncodeString_script_file}")
121 
122  if (DEFINED _vtk_encode_string_SOURCE_OUTPUT)
123  set("${_vtk_encode_string_SOURCE_OUTPUT}"
124  "${_vtk_encode_string_source}"
125  PARENT_SCOPE)
126  endif ()
127 
128  if (DEFINED _vtk_encode_string_HEADER_OUTPUT)
129  set("${_vtk_encode_string_HEADER_OUTPUT}"
130  "${_vtk_encode_string_header}"
131  PARENT_SCOPE)
132  endif ()
133 endfunction ()
134 
135 if (_vtk_encode_string_run AND CMAKE_SCRIPT_MODE_FILE)
136  set(output_header "${binary_dir}/${output_name}.h")
137  set(output_source "${binary_dir}/${output_name}.cxx")
138 
139  file(WRITE "${output_header}" "")
140  file(WRITE "${output_source}" "")
141 
142  file(APPEND "${output_header}"
143  "#ifndef ${output_name}_h\n#define ${output_name}_h\n\n")
144  if (export_symbol)
145  file(APPEND "${output_header}"
146  "#include \"${export_header}\"\n\n${export_symbol} ")
147  endif ()
148 
149  if (IS_ABSOLUTE "${source_file}")
150  set(source_file_full "${source_file}")
151  else ()
152  set(source_file_full "${source_dir}/${source_file}")
153  endif ()
154  set(hex_arg)
155  if (binary)
156  set(hex_arg HEX)
157  endif ()
158  file(READ "${source_file_full}" original_content ${hex_arg})
159 
160  if (binary)
161  if (nul_terminate)
162  string(APPEND original_content "00")
163  endif ()
164  string(LENGTH "${original_content}" output_size)
165  math(EXPR output_size "${output_size} / 2")
166  file(APPEND "${output_header}"
167  "extern const unsigned char ${output_name}[${output_size}];\n\n#endif\n")
168 
169  file(APPEND "${output_source}"
170  "#include \"${output_name}.h\"\n\nconst unsigned char ${output_name}[${output_size}] = {\n")
171  string(REGEX REPLACE "\‍([0-9a-f][0-9a-f]\‍)" ",0x\\1" escaped_content "${original_content}")
172  # Hard line wrap the file.
173  string(REGEX REPLACE "\‍(..........................................................................,\‍)" "\\1\n" escaped_content "${escaped_content}")
174  # Remove the leading comma.
175  string(REGEX REPLACE "^," "" escaped_content "${escaped_content}")
176  file(APPEND "${output_source}"
177  "${escaped_content}\n")
178  file(APPEND "${output_source}"
179  "};\n")
180  else ()
181  file(APPEND "${output_header}"
182  "extern const char *${output_name};\n\n#endif\n")
183 
184  # Escape literal backslashes.
185  string(REPLACE "\\" "\\\\" escaped_content "${original_content}")
186  # Escape literal double quotes.
187  string(REPLACE "\"" "\\\"" escaped_content "${escaped_content}")
188  # Turn newlines into newlines in the C string.
189  string(REPLACE "\n" "\\n\"\n\"" escaped_content "${escaped_content}")
190 
191  file(APPEND "${output_source}"
192  "#include \"${output_name}.h\"\n\nconst char *${output_name} =\n")
193  file(APPEND "${output_source}"
194  "\"${escaped_content}\";\n")
195  endif ()
196 endif ()
@ on
Definition: vtkX3D.h:445
@ time
Definition: vtkX3D.h:503
@ content
Definition: vtkX3D.h:308
@ name
Definition: vtkX3D.h:225
@ data
Definition: vtkX3D.h:321
@ string
Definition: vtkX3D.h:496
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.