blob: 60b146ba708306ccad82599dcfff7d3fea7ba8e8 [file] [log] [blame]
Wyatt Heplerc9e51d22020-10-29 09:12:37 -07001# Copyright 2020 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14include_guard(GLOBAL)
15
16# Declares a protocol buffers library. This function creates a library for each
17# supported protocol buffer implementation:
18#
19# ${NAME}.pwpb - pw_protobuf generated code
20# ${NAME}.nanopb - Nanopb generated code (requires Nanopb)
21#
22# This function also creates libraries for generating pw_rpc code:
23#
24# ${NAME}.nanopb_rpc - generates Nanopb pw_rpc code
25# ${NAME}.raw_rpc - generates raw pw_rpc (no protobuf library) code
26# ${NAME}.pwpb_rpc - (Not implemented) generates pw_protobuf pw_rpc code
27#
28# Args:
29#
30# NAME - the base name of the libraries to create
31# SOURCES - .proto source files
32# DEPS - dependencies on other pw_proto_library targets
Wyatt Hepler752d7d32021-03-02 09:02:23 -080033# PREFIX - prefix add to the proto files
34# STRIP_PREFIX - prefix to remove from the proto files
35# INPUTS - files to include along with the .proto files (such as Nanopb
36# .options files
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070037#
38function(pw_proto_library NAME)
Wyatt Hepler752d7d32021-03-02 09:02:23 -080039 cmake_parse_arguments(PARSE_ARGV 1 arg "" "STRIP_PREFIX;PREFIX"
40 "SOURCES;INPUTS;DEPS")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070041
Wyatt Hepler1573b822021-03-11 17:32:26 -080042 if("${arg_SOURCES}" STREQUAL "")
43 message(FATAL_ERROR
44 "pw_proto_library requires at least one .proto file in SOURCES. No "
45 "SOURCES were listed for ${NAME}.")
46 endif()
47
Wyatt Hepler752d7d32021-03-02 09:02:23 -080048 set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/${NAME}")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070049
50 # Use INTERFACE libraries to track the proto include paths that are passed to
51 # protoc.
52 set(include_deps "${arg_DEPS}")
53 list(TRANSFORM include_deps APPEND ._includes)
54
55 add_library("${NAME}._includes" INTERFACE)
56 target_include_directories("${NAME}._includes" INTERFACE ".")
57 target_link_libraries("${NAME}._includes" INTERFACE ${include_deps})
58
59 # Generate a file with all include paths needed by protoc.
Wyatt Hepler752d7d32021-03-02 09:02:23 -080060 set(include_file "${out_dir}/include_paths.txt")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070061 file(GENERATE OUTPUT "${include_file}"
62 CONTENT
63 "$<TARGET_PROPERTY:${NAME}._includes,INTERFACE_INCLUDE_DIRECTORIES>")
64
Wyatt Hepler752d7d32021-03-02 09:02:23 -080065 if("${arg_STRIP_PREFIX}" STREQUAL "")
66 set(arg_STRIP_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}")
67 endif()
68
69 foreach(path IN LISTS arg_SOURCES arg_INPUTS)
70 get_filename_component(abspath "${path}" ABSOLUTE)
71 list(APPEND files_to_mirror "${abspath}")
72 endforeach()
73
74 # Mirror the sources to the output directory with the specified prefix.
75 _pw_rebase_paths(
76 sources "${out_dir}/sources/${arg_PREFIX}" "${arg_STRIP_PREFIX}" "${arg_SOURCES}" "")
77 _pw_rebase_paths(
78 inputs "${out_dir}/sources/${arg_PREFIX}" "${arg_STRIP_PREFIX}" "${arg_INPUTS}" "")
79
80 add_custom_command(
81 COMMAND
82 python
83 "$ENV{PW_ROOT}/pw_build/py/pw_build/mirror_tree.py"
84 --source-root "${arg_STRIP_PREFIX}"
85 --directory "${out_dir}/sources/${arg_PREFIX}"
86 ${files_to_mirror}
87 DEPENDS
88 "$ENV{PW_ROOT}/pw_build/py/pw_build/mirror_tree.py"
89 ${files_to_mirror}
90 ${arg_DEPS}
91 OUTPUT
92 ${sources} ${inputs}
93 )
94
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070095 # Create a protobuf target for each supported protobuf library.
96 _pw_pwpb_library(
Wyatt Hepler752d7d32021-03-02 09:02:23 -080097 "${NAME}" "${sources}" "${inputs}" "${arg_DEPS}" "${include_file}" "${out_dir}")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070098 _pw_raw_rpc_library(
Wyatt Hepler752d7d32021-03-02 09:02:23 -080099 "${NAME}" "${sources}" "${inputs}" "${arg_DEPS}" "${include_file}" "${out_dir}")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700100 _pw_nanopb_library(
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800101 "${NAME}" "${sources}" "${inputs}" "${arg_DEPS}" "${include_file}" "${out_dir}")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700102 _pw_nanopb_rpc_library(
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800103 "${NAME}" "${sources}" "${inputs}" "${arg_DEPS}" "${include_file}" "${out_dir}")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700104endfunction(pw_proto_library)
105
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800106function(_pw_rebase_paths VAR OUT_DIR ROOT FILES EXTENSIONS)
107 foreach(file IN LISTS FILES)
108 get_filename_component(file "${file}" ABSOLUTE)
109 file(RELATIVE_PATH file "${ROOT}" "${file}")
110
111 if ("${EXTENSIONS}" STREQUAL "")
112 list(APPEND mirrored_files "${OUT_DIR}/${file}")
113 else()
114 foreach(ext IN LISTS EXTENSIONS)
115 get_filename_component(dir "${file}" DIRECTORY)
116 get_filename_component(name "${file}" NAME_WE)
117 list(APPEND mirrored_files "${OUT_DIR}/${dir}/${name}${ext}")
118 endforeach()
119 endif()
120 endforeach()
121
122 set("${VAR}" "${mirrored_files}" PARENT_SCOPE)
123endfunction(_pw_rebase_paths)
124
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700125# Internal function that invokes protoc through generate_protos.py.
126function(_pw_generate_protos
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800127 TARGET LANGUAGE PLUGIN OUTPUT_EXTS INCLUDE_FILE OUT_DIR SOURCES INPUTS DEPS)
128 # Determine the names of the compiled output files.
129 _pw_rebase_paths(outputs
130 "${OUT_DIR}/${LANGUAGE}" "${OUT_DIR}/sources" "${SOURCES}" "${OUTPUT_EXTS}")
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800131
132 # Export the output files to the caller's scope so it can use them if needed.
133 set(generated_outputs "${outputs}" PARENT_SCOPE)
134
135 if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
136 get_filename_component(dir "${source_file}" DIRECTORY)
137 get_filename_component(name "${source_file}" NAME_WE)
138 set(PLUGIN "${dir}/${name}.bat")
139 endif()
140
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700141 set(script "$ENV{PW_ROOT}/pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py")
142 add_custom_command(
143 COMMAND
144 python
145 "${script}"
146 --language "${LANGUAGE}"
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800147 --plugin-path "${PLUGIN}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700148 --include-file "${INCLUDE_FILE}"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800149 --compile-dir "${OUT_DIR}/sources"
150 --out-dir "${OUT_DIR}/${LANGUAGE}"
151 --sources ${SOURCES}
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700152 DEPENDS
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700153 ${script}
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800154 ${SOURCES}
155 ${INPUTS}
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700156 ${DEPS}
157 OUTPUT
158 ${outputs}
159 )
160 add_custom_target("${TARGET}" DEPENDS ${outputs})
161endfunction(_pw_generate_protos)
162
163# Internal function that creates a pwpb proto library.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800164function(_pw_pwpb_library NAME SOURCES INPUTS DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700165 list(TRANSFORM DEPS APPEND .pwpb)
166
167 _pw_generate_protos("${NAME}.generate.pwpb"
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800168 pwpb
169 "$ENV{PW_ROOT}/pw_protobuf/py/pw_protobuf/plugin.py"
170 ".pwpb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700171 "${INCLUDE_FILE}"
172 "${OUT_DIR}"
173 "${SOURCES}"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800174 "${INPUTS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700175 "${DEPS}"
176 )
177
178 # Create the library with the generated source files.
179 add_library("${NAME}.pwpb" INTERFACE)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800180 target_include_directories("${NAME}.pwpb" INTERFACE "${OUT_DIR}/pwpb")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700181 target_link_libraries("${NAME}.pwpb" INTERFACE pw_protobuf ${DEPS})
182 add_dependencies("${NAME}.pwpb" "${NAME}.generate.pwpb")
183endfunction(_pw_pwpb_library)
184
185# Internal function that creates a raw_rpc proto library.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800186function(_pw_raw_rpc_library NAME SOURCES INPUTS DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700187 list(TRANSFORM DEPS APPEND .raw_rpc)
188
189 _pw_generate_protos("${NAME}.generate.raw_rpc"
190 raw_rpc
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800191 "$ENV{PW_ROOT}/pw_rpc/py/pw_rpc/plugin_raw.py"
192 ".raw_rpc.pb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700193 "${INCLUDE_FILE}"
194 "${OUT_DIR}"
195 "${SOURCES}"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800196 "${INPUTS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700197 "${DEPS}"
198 )
199
200 # Create the library with the generated source files.
201 add_library("${NAME}.raw_rpc" INTERFACE)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800202 target_include_directories("${NAME}.raw_rpc" INTERFACE "${OUT_DIR}/raw_rpc")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700203 target_link_libraries("${NAME}.raw_rpc"
204 INTERFACE
205 pw_rpc.raw
206 pw_rpc.server
207 ${DEPS}
208 )
209 add_dependencies("${NAME}.raw_rpc" "${NAME}.generate.raw_rpc")
210endfunction(_pw_raw_rpc_library)
211
212# Internal function that creates a nanopb proto library.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800213function(_pw_nanopb_library NAME SOURCES INPUTS DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700214 list(TRANSFORM DEPS APPEND .nanopb)
215
216 set(nanopb_dir "$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,protobuf-nanopb-static,pw_build.empty>,SOURCE_DIR>")
217 set(nanopb_plugin
218 "$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,${nanopb_dir}/generator/protoc-gen-nanopb,COULD_NOT_FIND_protobuf-nanopb-static_TARGET_PLEASE_SET_UP_NANOPB>")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700219
220 _pw_generate_protos("${NAME}.generate.nanopb"
221 nanopb
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800222 "${nanopb_plugin}"
223 ".pb.h;.pb.c"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700224 "${INCLUDE_FILE}"
225 "${OUT_DIR}"
226 "${SOURCES}"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800227 "${INPUTS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700228 "${DEPS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700229 )
230
231 # Create the library with the generated source files.
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800232 add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${generated_outputs})
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800233 target_include_directories("${NAME}.nanopb" PUBLIC "${OUT_DIR}/nanopb")
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700234 target_link_libraries("${NAME}.nanopb" PUBLIC pw_third_party.nanopb ${DEPS})
235 add_dependencies("${NAME}.nanopb" "${NAME}.generate.nanopb")
236endfunction(_pw_nanopb_library)
237
238# Internal function that creates a nanopb_rpc library.
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800239function(_pw_nanopb_rpc_library NAME SOURCES INPUTS DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700240 # Determine the names of the output files.
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700241 list(TRANSFORM DEPS APPEND .nanopb_rpc)
242
243 _pw_generate_protos("${NAME}.generate.nanopb_rpc"
244 nanopb_rpc
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800245 "$ENV{PW_ROOT}/pw_rpc/py/pw_rpc/plugin_nanopb.py"
246 ".rpc.pb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700247 "${INCLUDE_FILE}"
248 "${OUT_DIR}"
249 "${SOURCES}"
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800250 "${INPUTS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700251 "${DEPS}"
252 )
253
254 # Create the library with the generated source files.
255 add_library("${NAME}.nanopb_rpc" INTERFACE)
Wyatt Hepler752d7d32021-03-02 09:02:23 -0800256 target_include_directories("${NAME}.nanopb_rpc"
257 INTERFACE
258 "${OUT_DIR}/nanopb_rpc"
259 )
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700260 target_link_libraries("${NAME}.nanopb_rpc"
261 INTERFACE
262 "${NAME}.nanopb"
Wyatt Heplerdcfa92b2020-11-10 09:47:30 -0800263 pw_rpc.nanopb.method_union
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700264 pw_rpc.server
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700265 ${DEPS}
266 )
267 add_dependencies("${NAME}.nanopb_rpc" "${NAME}.generate.nanopb_rpc")
268endfunction(_pw_nanopb_rpc_library)