xref: /aosp_15_r20/external/pigweed/pw_build/cc_blob_library.cmake (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker# Copyright 2022 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker#
3*61c4878aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker# use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker# the License at
6*61c4878aSAndroid Build Coastguard Worker#
7*61c4878aSAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker#
9*61c4878aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker# License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker# the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Workerinclude_guard(GLOBAL)
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Workercmake_minimum_required(VERSION 3.20)  # string(JSON)
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Workerinclude("$ENV{PW_ROOT}/pw_build/pigweed.cmake")
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker# Turns binary blobs into a C++ library of hard-coded byte arrays. The byte
22*61c4878aSAndroid Build Coastguard Worker# arrays are constant initialized and are safe to access at any time, including
23*61c4878aSAndroid Build Coastguard Worker# before main().
24*61c4878aSAndroid Build Coastguard Worker#
25*61c4878aSAndroid Build Coastguard Worker# Args:
26*61c4878aSAndroid Build Coastguard Worker#
27*61c4878aSAndroid Build Coastguard Worker#   HEADER
28*61c4878aSAndroid Build Coastguard Worker#
29*61c4878aSAndroid Build Coastguard Worker#     The header file to generate. Users will include this file exactly as it is
30*61c4878aSAndroid Build Coastguard Worker#     written here to reference the byte arrays.
31*61c4878aSAndroid Build Coastguard Worker#
32*61c4878aSAndroid Build Coastguard Worker#   NAMESPACE
33*61c4878aSAndroid Build Coastguard Worker#
34*61c4878aSAndroid Build Coastguard Worker#     The C++ namespace in which to place the generated blobs.
35*61c4878aSAndroid Build Coastguard Worker#
36*61c4878aSAndroid Build Coastguard Worker#   BLOB
37*61c4878aSAndroid Build Coastguard Worker#
38*61c4878aSAndroid Build Coastguard Worker#     A blob to be transformed from file to byte array. Multiple blobs may be
39*61c4878aSAndroid Build Coastguard Worker#     specified.
40*61c4878aSAndroid Build Coastguard Worker#
41*61c4878aSAndroid Build Coastguard Worker#     Blob args:
42*61c4878aSAndroid Build Coastguard Worker#
43*61c4878aSAndroid Build Coastguard Worker#       SYMBOL_NAME
44*61c4878aSAndroid Build Coastguard Worker#
45*61c4878aSAndroid Build Coastguard Worker#         The C++ symbol name for the byte array.
46*61c4878aSAndroid Build Coastguard Worker#
47*61c4878aSAndroid Build Coastguard Worker#       PATH
48*61c4878aSAndroid Build Coastguard Worker#
49*61c4878aSAndroid Build Coastguard Worker#         The file path for the binary blob.
50*61c4878aSAndroid Build Coastguard Worker#
51*61c4878aSAndroid Build Coastguard Worker#       LINKER_SECTION [optional]
52*61c4878aSAndroid Build Coastguard Worker#
53*61c4878aSAndroid Build Coastguard Worker#         If present, places the byte array in the specified linker section.
54*61c4878aSAndroid Build Coastguard Worker#
55*61c4878aSAndroid Build Coastguard Worker#       ALIGNAS [optional]
56*61c4878aSAndroid Build Coastguard Worker#
57*61c4878aSAndroid Build Coastguard Worker#         If present, the byte array is aligned as specified. The value of this
58*61c4878aSAndroid Build Coastguard Worker#         argument is used verbatim in an alignas() specifier for the blob
59*61c4878aSAndroid Build Coastguard Worker#         byte array.
60*61c4878aSAndroid Build Coastguard Worker#
61*61c4878aSAndroid Build Coastguard Workerfunction(pw_cc_blob_library NAME)
62*61c4878aSAndroid Build Coastguard Worker  cmake_parse_arguments(PARSE_ARGV 1 arg "" "HEADER;NAMESPACE" "")
63*61c4878aSAndroid Build Coastguard Worker
64*61c4878aSAndroid Build Coastguard Worker  set(blobs ${arg_UNPARSED_ARGUMENTS})
65*61c4878aSAndroid Build Coastguard Worker  set(blob_files "")
66*61c4878aSAndroid Build Coastguard Worker  set(blob_index 0)
67*61c4878aSAndroid Build Coastguard Worker  set(json_blobs "[]")  # Create a JSON list of blobs
68*61c4878aSAndroid Build Coastguard Worker
69*61c4878aSAndroid Build Coastguard Worker  pw_require_args("" arg_ HEADER NAMESPACE)
70*61c4878aSAndroid Build Coastguard Worker
71*61c4878aSAndroid Build Coastguard Worker  while(NOT "${blobs}" STREQUAL "")
72*61c4878aSAndroid Build Coastguard Worker    list(POP_FRONT blobs first_arg)
73*61c4878aSAndroid Build Coastguard Worker
74*61c4878aSAndroid Build Coastguard Worker    if(NOT "${first_arg}" STREQUAL BLOB)
75*61c4878aSAndroid Build Coastguard Worker      message(FATAL_ERROR "Invalid syntax in pw_cc_blob_library: "
76*61c4878aSAndroid Build Coastguard Worker        "Expected 'BLOB', found '${first_arg}'.")
77*61c4878aSAndroid Build Coastguard Worker    endif()
78*61c4878aSAndroid Build Coastguard Worker
79*61c4878aSAndroid Build Coastguard Worker    list(FIND blobs BLOB blob_end)
80*61c4878aSAndroid Build Coastguard Worker    list(SUBLIST blobs 0 "${blob_end}" current_blob)
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker    cmake_parse_arguments(
83*61c4878aSAndroid Build Coastguard Worker      blob_arg "" "SYMBOL_NAME;PATH;LINKER_SECTION;ALIGNAS" "" "${current_blob}"
84*61c4878aSAndroid Build Coastguard Worker    )
85*61c4878aSAndroid Build Coastguard Worker
86*61c4878aSAndroid Build Coastguard Worker    if(NOT "${blob_arg_UNPARSED_ARGUMENTS}" STREQUAL "")
87*61c4878aSAndroid Build Coastguard Worker      message(FATAL_ERROR "Unexpected BLOB arguments in pw_cc_blob_library: "
88*61c4878aSAndroid Build Coastguard Worker          "${blob_arg_UNPARSED_ARGUMENTS}")
89*61c4878aSAndroid Build Coastguard Worker    endif()
90*61c4878aSAndroid Build Coastguard Worker
91*61c4878aSAndroid Build Coastguard Worker    pw_require_args("BLOB args for ${CMAKE_CURRENT_FUNCTION}"
92*61c4878aSAndroid Build Coastguard Worker         blob_arg_ PATH SYMBOL_NAME)
93*61c4878aSAndroid Build Coastguard Worker
94*61c4878aSAndroid Build Coastguard Worker    cmake_path(ABSOLUTE_PATH blob_arg_PATH)
95*61c4878aSAndroid Build Coastguard Worker    list(APPEND blob_files "${blob_arg_PATH}")
96*61c4878aSAndroid Build Coastguard Worker
97*61c4878aSAndroid Build Coastguard Worker    set(json_blob "{}")
98*61c4878aSAndroid Build Coastguard Worker    _pw_json_set_string_key(json_blob file_path "${blob_arg_PATH}")
99*61c4878aSAndroid Build Coastguard Worker    _pw_json_set_string_key(json_blob symbol_name "${blob_arg_SYMBOL_NAME}")
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker    if(NOT "${blob_arg_ALIGNAS}" STREQUAL "")
102*61c4878aSAndroid Build Coastguard Worker      _pw_json_set_string_key(json_blob alignas "${blob_arg_ALIGNAS}")
103*61c4878aSAndroid Build Coastguard Worker    endif()
104*61c4878aSAndroid Build Coastguard Worker
105*61c4878aSAndroid Build Coastguard Worker    if(NOT "${blob_arg_LINKER_SECTION}" STREQUAL "")
106*61c4878aSAndroid Build Coastguard Worker      _pw_json_set_string_key(
107*61c4878aSAndroid Build Coastguard Worker          json_blob linker_section "${blob_arg_LINKER_SECTION}")
108*61c4878aSAndroid Build Coastguard Worker    endif()
109*61c4878aSAndroid Build Coastguard Worker
110*61c4878aSAndroid Build Coastguard Worker    string(JSON json_blobs SET "${json_blobs}" "${blob_index}" "${json_blob}")
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard Worker    if("${blob_end}" EQUAL -1)
113*61c4878aSAndroid Build Coastguard Worker      break()
114*61c4878aSAndroid Build Coastguard Worker    endif()
115*61c4878aSAndroid Build Coastguard Worker
116*61c4878aSAndroid Build Coastguard Worker    list(SUBLIST blobs "${blob_end}" -1 blobs)
117*61c4878aSAndroid Build Coastguard Worker    math(EXPR blob_index "${blob_index}+1")
118*61c4878aSAndroid Build Coastguard Worker  endwhile()
119*61c4878aSAndroid Build Coastguard Worker
120*61c4878aSAndroid Build Coastguard Worker  set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/${NAME}")
121*61c4878aSAndroid Build Coastguard Worker  set(blob_json_file "${out_dir}/blobs.json")
122*61c4878aSAndroid Build Coastguard Worker
123*61c4878aSAndroid Build Coastguard Worker  file(WRITE "${blob_json_file}" "${json_blobs}")
124*61c4878aSAndroid Build Coastguard Worker  set_property(  # Ensure the file is regenerated by CMake if it is deleted.
125*61c4878aSAndroid Build Coastguard Worker      DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${blob_json_file}")
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard Worker  set(generated_header "${out_dir}/public/${arg_HEADER}")
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker  cmake_path(GET arg_HEADER STEM filename)
130*61c4878aSAndroid Build Coastguard Worker  set(generated_source "${out_dir}/${filename}.cc")
131*61c4878aSAndroid Build Coastguard Worker
132*61c4878aSAndroid Build Coastguard Worker  add_custom_command(
133*61c4878aSAndroid Build Coastguard Worker    COMMAND
134*61c4878aSAndroid Build Coastguard Worker      python3
135*61c4878aSAndroid Build Coastguard Worker      "$ENV{PW_ROOT}/pw_build/py/pw_build/generate_cc_blob_library.py"
136*61c4878aSAndroid Build Coastguard Worker      --blob-file "${blob_json_file}"
137*61c4878aSAndroid Build Coastguard Worker      --header-include "${arg_HEADER}"
138*61c4878aSAndroid Build Coastguard Worker      --out-header "${generated_header}"
139*61c4878aSAndroid Build Coastguard Worker      --out-source "${generated_source}"
140*61c4878aSAndroid Build Coastguard Worker      --namespace "${arg_NAMESPACE}"
141*61c4878aSAndroid Build Coastguard Worker    DEPENDS
142*61c4878aSAndroid Build Coastguard Worker      "$ENV{PW_ROOT}/pw_build/py/pw_build/generate_cc_blob_library.py"
143*61c4878aSAndroid Build Coastguard Worker      "${blob_json_file}"
144*61c4878aSAndroid Build Coastguard Worker      ${blob_files}
145*61c4878aSAndroid Build Coastguard Worker    OUTPUT
146*61c4878aSAndroid Build Coastguard Worker      "${generated_header}"
147*61c4878aSAndroid Build Coastguard Worker      "${generated_source}"
148*61c4878aSAndroid Build Coastguard Worker  )
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker  add_custom_target("${NAME}._gen"
151*61c4878aSAndroid Build Coastguard Worker    DEPENDS
152*61c4878aSAndroid Build Coastguard Worker      "${generated_header}"
153*61c4878aSAndroid Build Coastguard Worker      "${generated_source}"
154*61c4878aSAndroid Build Coastguard Worker  )
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard Worker  pw_add_library_generic("${NAME}" OBJECT
157*61c4878aSAndroid Build Coastguard Worker    SOURCES
158*61c4878aSAndroid Build Coastguard Worker      "${generated_source}"
159*61c4878aSAndroid Build Coastguard Worker    PUBLIC_INCLUDES
160*61c4878aSAndroid Build Coastguard Worker      "${out_dir}/public"
161*61c4878aSAndroid Build Coastguard Worker    PUBLIC_DEPS
162*61c4878aSAndroid Build Coastguard Worker      pw_polyfill
163*61c4878aSAndroid Build Coastguard Worker      pw_preprocessor
164*61c4878aSAndroid Build Coastguard Worker  )
165*61c4878aSAndroid Build Coastguard Worker  add_dependencies("${NAME}" "${NAME}._gen")
166*61c4878aSAndroid Build Coastguard Workerendfunction(pw_cc_blob_library)
167*61c4878aSAndroid Build Coastguard Worker
168*61c4878aSAndroid Build Coastguard Worker# Sets a key with a string value in a JSON object.
169*61c4878aSAndroid Build Coastguard Workermacro(_pw_json_set_string_key json_var key value)
170*61c4878aSAndroid Build Coastguard Worker  string(JSON "${json_var}" SET "${${json_var}}" "${key}" "\"${value}\"")
171*61c4878aSAndroid Build Coastguard Workerendmacro()
172