#[==[ @file vtkEncodeString.cmake This module contains the @ref vtk_encode_string function which may be used to turn a file into a C string. This is primarily used within a program so that the content does not need to be retrieved from the filesystem at runtime, but can still be developed as a standalone file. #]==] set(_vtkEncodeString_script_file "${CMAKE_CURRENT_LIST_FILE}") include(CMakeParseArguments) #[==[ @brief Encode a file as a C string at build time Adds a rule to turn a file into a C string. Note that any Unicode characters will not be replaced with escaping, so it is recommended to avoid their usage in the input. ~~~ vtk_encode_string INPUT [NAME ] [EXPORT_SYMBOL ] [EXPORT_HEADER
] [HEADER_OUTPUT ] [SOURCE_OUTPUT ] [BINARY] [NUL_TERMINATE]) ~~~ The only required variable is `INPUT`, however, it is likely that at least one of `HEADER_OUTPUT` or `SOURCE_OUTPUT` will be required to add them to a library. * `INPUT`: (Required) The path to the file to be embedded. If a relative path is given, it will be interpreted as being relative to `CMAKE_CURRENT_SOURCE_DIR`. * `NAME`: This is the base name of the files that will be generated as well as the variable name for the C string. It defaults to the basename of the input without extensions. * `EXPORT_SYMBOL`: The symbol to use for exporting the variable. By default, it will not be exported. If set, `EXPORT_HEADER` must also be set. * `EXPORT_HEADER`: The header to include for providing the given export symbol. If set, `EXPORT_SYMBOL` should also be set. * `HEADER_OUTPUT`: The variable to store the generated header path. * `SOURCE_OUTPUT`: The variable to store the generated source path. * `BINARY`: If given, the data will be written as an array of `unsigned char` bytes. * `NUL_TERMINATE`: If given, the binary data will be `NUL`-terminated. Only makes sense with the `BINARY` flag. This is intended to be used if embedding a file as a C string exceeds compiler limits on string literals in various compilers. #]==] function (vtk_encode_string) cmake_parse_arguments(_vtk_encode_string "BINARY;NUL_TERMINATE" "INPUT;NAME;EXPORT_SYMBOL;EXPORT_HEADER;HEADER_OUTPUT;SOURCE_OUTPUT" "" ${ARGN}) if (_vtk_encode_string_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unrecognized arguments to vtk_encode_string: " "${_vtk_encode_string_UNPARSED_ARGUMENTS}") endif () if (NOT DEFINED _vtk_encode_string_INPUT) message(FATAL_ERROR "Missing `INPUT` for vtk_encode_string.") endif () if (NOT DEFINED _vtk_encode_string_NAME) get_filename_component(_vtk_encode_string_NAME "${_vtk_encode_string_INPUT}" NAME_WE) endif () if (DEFINED _vtk_encode_string_EXPORT_SYMBOL AND NOT DEFINED _vtk_encode_string_EXPORT_HEADER) message(FATAL_ERROR "Missing `EXPORT_HEADER` when using `EXPORT_SYMBOL`.") endif () if (DEFINED _vtk_encode_string_EXPORT_HEADER AND NOT DEFINED _vtk_encode_string_EXPORT_SYMBOL) message(WARNING "Missing `EXPORT_SYMBOL` when using `EXPORT_HEADER`.") endif () if (NOT _vtk_encode_string_BINARY AND _vtk_encode_string_NUL_TERMINATE) message(FATAL_ERROR "The `NUL_TERMINATE` flag only makes sense with the `BINARY` flag.") endif () set(_vtk_encode_string_header "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.h") set(_vtk_encode_string_source "${CMAKE_CURRENT_BINARY_DIR}/${_vtk_encode_string_NAME}.cxx") if (IS_ABSOLUTE "${_vtk_encode_string_INPUT}") set(_vtk_encode_string_input "${_vtk_encode_string_INPUT}") else () set(_vtk_encode_string_input "${CMAKE_CURRENT_SOURCE_DIR}/${_vtk_encode_string_INPUT}") endif () add_custom_command( OUTPUT ${_vtk_encode_string_header} ${_vtk_encode_string_source} DEPENDS "${_vtkEncodeString_script_file}" "${_vtk_encode_string_input}" COMMAND "${CMAKE_COMMAND}" "-Dsource_dir=${CMAKE_CURRENT_SOURCE_DIR}" "-Dbinary_dir=${CMAKE_CURRENT_BINARY_DIR}" "-Dsource_file=${_vtk_encode_string_input}" "-Doutput_name=${_vtk_encode_string_NAME}" "-Dexport_symbol=${_vtk_encode_string_EXPORT_SYMBOL}" "-Dexport_header=${_vtk_encode_string_EXPORT_HEADER}" "-Dbinary=${_vtk_encode_string_BINARY}" "-Dnul_terminate=${_vtk_encode_string_NUL_TERMINATE}" "-D_vtk_encode_string_run=ON" -P "${_vtkEncodeString_script_file}") if (DEFINED _vtk_encode_string_SOURCE_OUTPUT) set("${_vtk_encode_string_SOURCE_OUTPUT}" "${_vtk_encode_string_source}" PARENT_SCOPE) endif () if (DEFINED _vtk_encode_string_HEADER_OUTPUT) set("${_vtk_encode_string_HEADER_OUTPUT}" "${_vtk_encode_string_header}" PARENT_SCOPE) endif () endfunction () if (_vtk_encode_string_run AND CMAKE_SCRIPT_MODE_FILE) set(output_header "${binary_dir}/${output_name}.h") set(output_source "${binary_dir}/${output_name}.cxx") file(WRITE "${output_header}" "") file(WRITE "${output_source}" "") file(APPEND "${output_header}" "#ifndef ${output_name}_h\n#define ${output_name}_h\n\n") if (export_symbol) file(APPEND "${output_header}" "#include \"${export_header}\"\n\n${export_symbol} ") endif () if (IS_ABSOLUTE "${source_file}") set(source_file_full "${source_file}") else () set(source_file_full "${source_dir}/${source_file}") endif () set(hex_arg) if (binary) set(hex_arg HEX) endif () file(READ "${source_file_full}" original_content ${hex_arg}) if (binary) if (nul_terminate) string(APPEND original_content "00") endif () string(LENGTH "${original_content}" output_size) math(EXPR output_size "${output_size} / 2") file(APPEND "${output_header}" "extern const unsigned char ${output_name}[${output_size}];\n\n#endif\n") file(APPEND "${output_source}" "#include \"${output_name}.h\"\n\nconst unsigned char ${output_name}[${output_size}] = {\n") string(REGEX REPLACE "\([0-9a-f][0-9a-f]\)" ",0x\\1" escaped_content "${original_content}") # Hard line wrap the file. string(REGEX REPLACE "\(..........................................................................,\)" "\\1\n" escaped_content "${escaped_content}") # Remove the leading comma. string(REGEX REPLACE "^," "" escaped_content "${escaped_content}") file(APPEND "${output_source}" "${escaped_content}\n") file(APPEND "${output_source}" "};\n") else () file(APPEND "${output_header}" "extern const char *${output_name};\n\n#endif\n") # Escape literal backslashes. string(REPLACE "\\" "\\\\" escaped_content "${original_content}") # Escape literal double quotes. string(REPLACE "\"" "\\\"" escaped_content "${escaped_content}") # Turn newlines into newlines in the C string. string(REPLACE "\n" "\\n\"\n\"" escaped_content "${escaped_content}") file(APPEND "${output_source}" "#include \"${output_name}.h\"\n\nconst char *${output_name} =\n") file(APPEND "${output_source}" "\"${escaped_content}\";\n") endif () endif ()