Wyatt Hepler | c9e51d2 | 2020-10-29 09:12:37 -0700 | [diff] [blame^] | 1 | # 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. |
| 14 | include_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 | # |
| 34 | function(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}") |
| 63 | endfunction(pw_proto_library) |
| 64 | |
| 65 | # Internal function that invokes protoc through generate_protos.py. |
| 66 | function(_pw_generate_protos |
| 67 | TARGET LANGUAGE INCLUDE_FILE OUT_DIR SOURCES OUTPUTS DEPS) |
| 68 | set(script "$ENV{PW_ROOT}/pw_protobuf_compiler/py/pw_protobuf_compiler/generate_protos.py") |
| 69 | add_custom_command( |
| 70 | COMMAND |
| 71 | python |
| 72 | "${script}" |
| 73 | --language "${LANGUAGE}" |
| 74 | --module-path "${CMAKE_CURRENT_SOURCE_DIR}" |
| 75 | --include-file "${INCLUDE_FILE}" |
| 76 | --out-dir "${OUT_DIR}" |
| 77 | ${ARGN} |
| 78 | ${SOURCES} |
| 79 | DEPENDS |
| 80 | ${SOURCES} |
| 81 | ${script} |
| 82 | ${DEPS} |
| 83 | OUTPUT |
| 84 | ${outputs} |
| 85 | ) |
| 86 | add_custom_target("${TARGET}" DEPENDS ${outputs}) |
| 87 | endfunction(_pw_generate_protos) |
| 88 | |
| 89 | # Internal function that creates a pwpb proto library. |
| 90 | function(_pw_pwpb_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR) |
| 91 | # Determine the names of the output files. |
| 92 | set(outputs "${SOURCES}") |
| 93 | list(TRANSFORM outputs REPLACE "\.proto$" ".pwpb.h") |
| 94 | list(TRANSFORM outputs PREPEND "${OUT_DIR}/") |
| 95 | |
| 96 | # Make the source paths absolute since they are passed to a script. |
| 97 | list(TRANSFORM SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") |
| 98 | |
| 99 | list(TRANSFORM DEPS APPEND .pwpb) |
| 100 | |
| 101 | _pw_generate_protos("${NAME}.generate.pwpb" |
| 102 | cc |
| 103 | "${INCLUDE_FILE}" |
| 104 | "${OUT_DIR}" |
| 105 | "${SOURCES}" |
| 106 | "${outputs}" |
| 107 | "${DEPS}" |
| 108 | ) |
| 109 | |
| 110 | # Create the library with the generated source files. |
| 111 | add_library("${NAME}.pwpb" INTERFACE) |
| 112 | target_include_directories("${NAME}.pwpb" INTERFACE "${OUT_DIR}") |
| 113 | target_link_libraries("${NAME}.pwpb" INTERFACE pw_protobuf ${DEPS}) |
| 114 | add_dependencies("${NAME}.pwpb" "${NAME}.generate.pwpb") |
| 115 | endfunction(_pw_pwpb_library) |
| 116 | |
| 117 | # Internal function that creates a raw_rpc proto library. |
| 118 | function(_pw_raw_rpc_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR) |
| 119 | # Determine the names of the output files. |
| 120 | set(outputs "${SOURCES}") |
| 121 | list(TRANSFORM outputs REPLACE "\.proto$" ".raw_rpc.pb.h") |
| 122 | list(TRANSFORM outputs PREPEND "${OUT_DIR}/") |
| 123 | |
| 124 | # Make the source paths absolute since they are passed to a script. |
| 125 | list(TRANSFORM SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") |
| 126 | |
| 127 | list(TRANSFORM DEPS APPEND .raw_rpc) |
| 128 | |
| 129 | _pw_generate_protos("${NAME}.generate.raw_rpc" |
| 130 | raw_rpc |
| 131 | "${INCLUDE_FILE}" |
| 132 | "${OUT_DIR}" |
| 133 | "${SOURCES}" |
| 134 | "${outputs}" |
| 135 | "${DEPS}" |
| 136 | ) |
| 137 | |
| 138 | # Create the library with the generated source files. |
| 139 | add_library("${NAME}.raw_rpc" INTERFACE) |
| 140 | target_include_directories("${NAME}.raw_rpc" INTERFACE "${OUT_DIR}") |
| 141 | target_link_libraries("${NAME}.raw_rpc" |
| 142 | INTERFACE |
| 143 | pw_rpc.raw |
| 144 | pw_rpc.server |
| 145 | ${DEPS} |
| 146 | ) |
| 147 | add_dependencies("${NAME}.raw_rpc" "${NAME}.generate.raw_rpc") |
| 148 | endfunction(_pw_raw_rpc_library) |
| 149 | |
| 150 | # Internal function that creates a nanopb proto library. |
| 151 | function(_pw_nanopb_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR) |
| 152 | # Determine the names of the output files. |
| 153 | set(outputs_h "${SOURCES}") |
| 154 | list(TRANSFORM outputs_h REPLACE "\.proto$" ".pb.h") |
| 155 | list(TRANSFORM outputs_h PREPEND "${OUT_DIR}/") |
| 156 | |
| 157 | set(outputs_c "${SOURCES}") |
| 158 | list(TRANSFORM outputs_c REPLACE "\.proto$" ".pb.c") |
| 159 | list(TRANSFORM outputs_c PREPEND "${OUT_DIR}/") |
| 160 | |
| 161 | set(outputs ${outputs_c} ${outputs_h}) |
| 162 | |
| 163 | # Make the source paths absolute since they are passed to a script. |
| 164 | list(TRANSFORM SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") |
| 165 | |
| 166 | list(TRANSFORM DEPS APPEND .nanopb) |
| 167 | |
| 168 | set(nanopb_dir "$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,protobuf-nanopb-static,pw_build.empty>,SOURCE_DIR>") |
| 169 | set(nanopb_plugin |
| 170 | "$<IF:$<TARGET_EXISTS:protobuf-nanopb-static>,${nanopb_dir}/generator/protoc-gen-nanopb,COULD_NOT_FIND_protobuf-nanopb-static_TARGET_PLEASE_SET_UP_NANOPB>") |
| 171 | if(WIN32) |
| 172 | set(nanopb_plugin "${nanopb_plugin}.bat") |
| 173 | endif() |
| 174 | |
| 175 | _pw_generate_protos("${NAME}.generate.nanopb" |
| 176 | nanopb |
| 177 | "${INCLUDE_FILE}" |
| 178 | "${OUT_DIR}" |
| 179 | "${SOURCES}" |
| 180 | "${outputs}" |
| 181 | "${DEPS}" |
| 182 | --custom-plugin "${nanopb_plugin}" |
| 183 | --include-paths "${nanopb_dir}/generator/proto" |
| 184 | ) |
| 185 | |
| 186 | # Create the library with the generated source files. |
| 187 | add_library("${NAME}.nanopb" EXCLUDE_FROM_ALL ${outputs}) |
| 188 | target_include_directories("${NAME}.nanopb" PUBLIC "${OUT_DIR}") |
| 189 | target_link_libraries("${NAME}.nanopb" PUBLIC pw_third_party.nanopb ${DEPS}) |
| 190 | add_dependencies("${NAME}.nanopb" "${NAME}.generate.nanopb") |
| 191 | endfunction(_pw_nanopb_library) |
| 192 | |
| 193 | # Internal function that creates a nanopb_rpc library. |
| 194 | function(_pw_nanopb_rpc_library NAME SOURCES DEPS INCLUDE_FILE OUT_DIR) |
| 195 | # Determine the names of the output files. |
| 196 | set(outputs "${SOURCES}") |
| 197 | list(TRANSFORM outputs REPLACE "\.proto$" ".rpc.pb.h") |
| 198 | list(TRANSFORM outputs PREPEND "${OUT_DIR}/") |
| 199 | |
| 200 | # Make the source paths absolute since they are passed to a script. |
| 201 | list(TRANSFORM SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/") |
| 202 | |
| 203 | list(TRANSFORM DEPS APPEND .nanopb_rpc) |
| 204 | |
| 205 | _pw_generate_protos("${NAME}.generate.nanopb_rpc" |
| 206 | nanopb_rpc |
| 207 | "${INCLUDE_FILE}" |
| 208 | "${OUT_DIR}" |
| 209 | "${SOURCES}" |
| 210 | "${outputs}" |
| 211 | "${DEPS}" |
| 212 | ) |
| 213 | |
| 214 | # Create the library with the generated source files. |
| 215 | add_library("${NAME}.nanopb_rpc" INTERFACE) |
| 216 | target_include_directories("${NAME}.nanopb_rpc" INTERFACE "${OUT_DIR}") |
| 217 | target_link_libraries("${NAME}.nanopb_rpc" |
| 218 | INTERFACE |
| 219 | "${NAME}.nanopb" |
| 220 | pw_rpc.server |
| 221 | pw_rpc.nanopb |
| 222 | ${DEPS} |
| 223 | ) |
| 224 | add_dependencies("${NAME}.nanopb_rpc" "${NAME}.generate.nanopb_rpc") |
| 225 | endfunction(_pw_nanopb_rpc_library) |