blob: bd8584e4b6a0d8e48239eeb8be36b36739573ebc [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
33#
34function(pw_proto_library NAME)
35 cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "SOURCES;DEPS")
36
37 set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/protos")
38
39 # Use INTERFACE libraries to track the proto include paths that are passed to
40 # protoc.
41 set(include_deps "${arg_DEPS}")
42 list(TRANSFORM include_deps APPEND ._includes)
43
44 add_library("${NAME}._includes" INTERFACE)
45 target_include_directories("${NAME}._includes" INTERFACE ".")
46 target_link_libraries("${NAME}._includes" INTERFACE ${include_deps})
47
48 # Generate a file with all include paths needed by protoc.
49 set(include_file "${out_dir}/${NAME}.include_paths.txt")
50 file(GENERATE OUTPUT "${include_file}"
51 CONTENT
52 "$<TARGET_PROPERTY:${NAME}._includes,INTERFACE_INCLUDE_DIRECTORIES>")
53
54 # Create a protobuf target for each supported protobuf library.
55 _pw_pwpb_library(
56 "${NAME}" "${arg_SOURCES}" "${arg_DEPS}" "${include_file}" "${out_dir}")
57 _pw_raw_rpc_library(
58 "${NAME}" "${arg_SOURCES}" "${arg_DEPS}" "${include_file}" "${out_dir}")
59 _pw_nanopb_library(
60 "${NAME}" "${arg_SOURCES}" "${arg_DEPS}" "${include_file}" "${out_dir}")
61 _pw_nanopb_rpc_library(
62 "${NAME}" "${arg_SOURCES}" "${arg_DEPS}" "${include_file}" "${out_dir}")
63endfunction(pw_proto_library)
64
65# Internal function that invokes protoc through generate_protos.py.
66function(_pw_generate_protos
Wyatt Heplerd9336a42020-11-10 09:47:30 -080067 TARGET LANGUAGE PLUGIN OUTPUT_EXTS INCLUDE_FILE OUT_DIR SOURCES DEPS)
68 # Determine the names of the output files.
69 foreach(extension IN LISTS OUTPUT_EXTS)
70 foreach(source_file IN LISTS SOURCES)
71 get_filename_component(dir "${source_file}" DIRECTORY)
72 get_filename_component(name "${source_file}" NAME_WE)
73 list(APPEND outputs "${OUT_DIR}/${dir}/${name}${extension}")
74 endforeach()
75 endforeach()
76
77 # Export the output files to the caller's scope so it can use them if needed.
78 set(generated_outputs "${outputs}" PARENT_SCOPE)
79
80 if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
81 get_filename_component(dir "${source_file}" DIRECTORY)
82 get_filename_component(name "${source_file}" NAME_WE)
83 set(PLUGIN "${dir}/${name}.bat")
84 endif()
85
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070086 set(script "$ENV{PW_ROOT}/pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py")
87 add_custom_command(
88 COMMAND
89 python
90 "${script}"
91 --language "${LANGUAGE}"
Wyatt Heplerd9336a42020-11-10 09:47:30 -080092 --plugin-path "${PLUGIN}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -070093 --module-path "${CMAKE_CURRENT_SOURCE_DIR}"
94 --include-file "${INCLUDE_FILE}"
95 --out-dir "${OUT_DIR}"
96 ${ARGN}
97 ${SOURCES}
98 DEPENDS
99 ${SOURCES}
100 ${script}
101 ${DEPS}
102 OUTPUT
103 ${outputs}
104 )
105 add_custom_target("${TARGET}" DEPENDS ${outputs})
106endfunction(_pw_generate_protos)
107
108# Internal function that creates a pwpb proto library.
109function(_pw_pwpb_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700110 list(TRANSFORM DEPS APPEND .pwpb)
111
112 _pw_generate_protos("${NAME}.generate.pwpb"
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800113 pwpb
114 "$ENV{PW_ROOT}/pw_protobuf/py/pw_protobuf/plugin.py"
115 ".pwpb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700116 "${INCLUDE_FILE}"
117 "${OUT_DIR}"
118 "${SOURCES}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700119 "${DEPS}"
120 )
121
122 # Create the library with the generated source files.
123 add_library("${NAME}.pwpb" INTERFACE)
124 target_include_directories("${NAME}.pwpb" INTERFACE "${OUT_DIR}")
125 target_link_libraries("${NAME}.pwpb" INTERFACE pw_protobuf ${DEPS})
126 add_dependencies("${NAME}.pwpb" "${NAME}.generate.pwpb")
127endfunction(_pw_pwpb_library)
128
129# Internal function that creates a raw_rpc proto library.
130function(_pw_raw_rpc_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700131 list(TRANSFORM DEPS APPEND .raw_rpc)
132
133 _pw_generate_protos("${NAME}.generate.raw_rpc"
134 raw_rpc
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800135 "$ENV{PW_ROOT}/pw_rpc/py/pw_rpc/plugin_raw.py"
136 ".raw_rpc.pb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700137 "${INCLUDE_FILE}"
138 "${OUT_DIR}"
139 "${SOURCES}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700140 "${DEPS}"
141 )
142
143 # Create the library with the generated source files.
144 add_library("${NAME}.raw_rpc" INTERFACE)
145 target_include_directories("${NAME}.raw_rpc" INTERFACE "${OUT_DIR}")
146 target_link_libraries("${NAME}.raw_rpc"
147 INTERFACE
148 pw_rpc.raw
149 pw_rpc.server
150 ${DEPS}
151 )
152 add_dependencies("${NAME}.raw_rpc" "${NAME}.generate.raw_rpc")
153endfunction(_pw_raw_rpc_library)
154
155# Internal function that creates a nanopb proto library.
156function(_pw_nanopb_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR)
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700157 list(TRANSFORM DEPS APPEND .nanopb)
158
159 set(nanopb_dir "$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,protobuf-nanopb-static,pw_build.empty>,SOURCE_DIR>")
160 set(nanopb_plugin
161 "$<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 -0700162
163 _pw_generate_protos("${NAME}.generate.nanopb"
164 nanopb
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800165 "${nanopb_plugin}"
166 ".pb.h;.pb.c"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700167 "${INCLUDE_FILE}"
168 "${OUT_DIR}"
169 "${SOURCES}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700170 "${DEPS}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700171 --include-paths "${nanopb_dir}/generator/proto"
172 )
173
174 # Create the library with the generated source files.
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800175 add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${generated_outputs})
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700176 target_include_directories("${NAME}.nanopb" PUBLIC "${OUT_DIR}")
177 target_link_libraries("${NAME}.nanopb" PUBLIC pw_third_party.nanopb ${DEPS})
178 add_dependencies("${NAME}.nanopb" "${NAME}.generate.nanopb")
179endfunction(_pw_nanopb_library)
180
181# Internal function that creates a nanopb_rpc library.
182function(_pw_nanopb_rpc_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR)
183 # Determine the names of the output files.
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700184 list(TRANSFORM DEPS APPEND .nanopb_rpc)
185
186 _pw_generate_protos("${NAME}.generate.nanopb_rpc"
187 nanopb_rpc
Wyatt Heplerd9336a42020-11-10 09:47:30 -0800188 "$ENV{PW_ROOT}/pw_rpc/py/pw_rpc/plugin_nanopb.py"
189 ".rpc.pb.h"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700190 "${INCLUDE_FILE}"
191 "${OUT_DIR}"
192 "${SOURCES}"
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700193 "${DEPS}"
194 )
195
196 # Create the library with the generated source files.
197 add_library("${NAME}.nanopb_rpc" INTERFACE)
198 target_include_directories("${NAME}.nanopb_rpc" INTERFACE "${OUT_DIR}")
199 target_link_libraries("${NAME}.nanopb_rpc"
200 INTERFACE
201 "${NAME}.nanopb"
Wyatt Heplerdcfa92b2020-11-10 09:47:30 -0800202 pw_rpc.nanopb.method_union
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700203 pw_rpc.server
Wyatt Heplerc9e51d22020-10-29 09:12:37 -0700204 ${DEPS}
205 )
206 add_dependencies("${NAME}.nanopb_rpc" "${NAME}.generate.nanopb_rpc")
207endfunction(_pw_nanopb_rpc_library)