blob: f34cb646fef2804f7bce2ab2df6de5da916c7233 [file] [log] [blame]
# 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("${NAME}" STATIC
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()