# Copyright 2022 The Pigweed Authors # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. include_guard(GLOBAL) cmake_minimum_required(VERSION 3.20) # string(JSON) include("$ENV{PW_ROOT}/pw_build/pigweed.cmake") # Turns binary blobs into a C++ library of hard-coded byte arrays. The byte # arrays are constant initialized and are safe to access at any time, including # before main(). # # Args: # # HEADER # # The header file to generate. Users will include this file exactly as it is # written here to reference the byte arrays. # # NAMESPACE # # The C++ namespace in which to place the generated blobs. # # BLOB # # A blob to be transformed from file to byte array. Multiple blobs may be # specified. # # Blob args: # # SYMBOL_NAME # # The C++ symbol name for the byte array. # # PATH # # The file path for the binary blob. # # LINKER_SECTION [optional] # # If present, places the byte array in the specified linker section. # # ALIGNAS [optional] # # If present, the byte array is aligned as specified. The value of this # argument is used verbatim in an alignas() specifier for the blob # byte array. # function(pw_cc_blob_library NAME) cmake_parse_arguments(PARSE_ARGV 1 arg "" "HEADER;NAMESPACE" "") set(blobs ${arg_UNPARSED_ARGUMENTS}) set(blob_files "") set(blob_index 0) set(json_blobs "[]") # Create a JSON list of blobs pw_require_args("" arg_ HEADER NAMESPACE) while(NOT "${blobs}" STREQUAL "") list(POP_FRONT blobs first_arg) if(NOT "${first_arg}" STREQUAL BLOB) message(FATAL_ERROR "Invalid syntax in pw_cc_blob_library: " "Expected 'BLOB', found '${first_arg}'.") endif() list(FIND blobs BLOB blob_end) list(SUBLIST blobs 0 "${blob_end}" current_blob) cmake_parse_arguments( blob_arg "" "SYMBOL_NAME;PATH;LINKER_SECTION;ALIGNAS" "" "${current_blob}" ) if(NOT "${blob_arg_UNPARSED_ARGUMENTS}" STREQUAL "") message(FATAL_ERROR "Unexpected BLOB arguments in pw_cc_blob_library: " "${blob_arg_UNPARSED_ARGUMENTS}") endif() pw_require_args("BLOB args for ${CMAKE_CURRENT_FUNCTION}" blob_arg_ PATH SYMBOL_NAME) cmake_path(ABSOLUTE_PATH blob_arg_PATH) list(APPEND blob_files "${blob_arg_PATH}") set(json_blob "{}") _pw_json_set_string_key(json_blob file_path "${blob_arg_PATH}") _pw_json_set_string_key(json_blob symbol_name "${blob_arg_SYMBOL_NAME}") if(NOT "${blob_arg_ALIGNAS}" STREQUAL "") _pw_json_set_string_key(json_blob alignas "${blob_arg_ALIGNAS}") endif() if(NOT "${blob_arg_LINKER_SECTION}" STREQUAL "") _pw_json_set_string_key( json_blob linker_section "${blob_arg_LINKER_SECTION}") endif() string(JSON json_blobs SET "${json_blobs}" "${blob_index}" "${json_blob}") if("${blob_end}" EQUAL -1) break() endif() list(SUBLIST blobs "${blob_end}" -1 blobs) math(EXPR blob_index "${blob_index}+1") endwhile() set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/${NAME}") set(blob_json_file "${out_dir}/blobs.json") file(WRITE "${blob_json_file}" "${json_blobs}") set_property( # Ensure the file is regenerated by CMake if it is deleted. DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${blob_json_file}") set(generated_header "${out_dir}/public/${arg_HEADER}") cmake_path(GET arg_HEADER STEM filename) set(generated_source "${out_dir}/${filename}.cc") add_custom_command( COMMAND python3 "$ENV{PW_ROOT}/pw_build/py/pw_build/generate_cc_blob_library.py" --blob-file "${blob_json_file}" --header-include "${arg_HEADER}" --out-header "${generated_header}" --out-source "${generated_source}" --namespace "${arg_NAMESPACE}" DEPENDS "$ENV{PW_ROOT}/pw_build/py/pw_build/generate_cc_blob_library.py" "${blob_json_file}" ${blob_files} OUTPUT "${generated_header}" "${generated_source}" ) add_custom_target("${NAME}._gen" DEPENDS "${generated_header}" "${generated_source}" ) pw_add_library_generic("${NAME}" OBJECT SOURCES "${generated_source}" PUBLIC_INCLUDES "${out_dir}/public" PUBLIC_DEPS pw_polyfill pw_preprocessor ) add_dependencies("${NAME}" "${NAME}._gen") endfunction(pw_cc_blob_library) # Sets a key with a string value in a JSON object. macro(_pw_json_set_string_key json_var key value) string(JSON "${json_var}" SET "${${json_var}}" "${key}" "\"${value}\"") endmacro()