1# This is an example script for use with CMake projects for locating and configuring 2# the nanopb library. 3# 4# The following variables can be set and are optional: 5# 6# 7# PROTOBUF_SRC_ROOT_FOLDER - When compiling with MSVC, if this cache variable is set 8# the protobuf-default VS project build locations 9# (vsprojects/Debug & vsprojects/Release) will be searched 10# for libraries and binaries. 11# 12# NANOPB_IMPORT_DIRS - List of additional directories to be searched for 13# imported .proto files. 14# 15# NANOPB_OPTIONS - List of options passed to nanopb. 16# 17# NANOPB_DEPENDS - List of files to be used as dependencies 18# for the generated source and header files. These 19# files are not directly passed as options to 20# nanopb but rather their directories. 21# 22# NANOPB_GENERATE_CPP_APPEND_PATH - By default -I will be passed to protoc 23# for each directory where a proto file is referenced. 24# This causes all output files to go directly 25# under build directory, instead of mirroring 26# relative paths of source directories. 27# Set to FALSE if you want to disable this behaviour. 28# PROTOC_OPTIONS - Pass options to protoc executable 29# 30# Defines the following variables: 31# 32# NANOPB_FOUND - Found the nanopb library (source&header files, generator tool, protoc compiler tool) 33# NANOPB_INCLUDE_DIRS - Include directories for Google Protocol Buffers 34# 35# The following cache variables are also available to set or use: 36# PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler 37# NANOPB_GENERATOR_SOURCE_DIR - The nanopb generator source 38# 39# ==================================================================== 40# 41# NANOPB_GENERATE_CPP (public function) 42# NANOPB_GENERATE_CPP(SRCS HDRS [RELPATH <root-path-of-proto-files>] 43# <proto-files>...) 44# SRCS = Variable to define with autogenerated source files 45# HDRS = Variable to define with autogenerated header files 46# If you want to use relative paths in your import statements use the RELPATH 47# option. The argument to RELPATH should be the directory that all the 48# imports will be relative to. 49# When RELPATH is not specified then all proto files can be imported without 50# a path. 51# 52# 53# ==================================================================== 54# Example: 55# 56# set(NANOPB_SRC_ROOT_FOLDER "/path/to/nanopb") 57# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_SRC_ROOT_FOLDER}/extra) 58# find_package( Nanopb REQUIRED ) 59# include_directories(${NANOPB_INCLUDE_DIRS}) 60# 61# NANOPB_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto) 62# 63# include_directories(${CMAKE_CURRENT_BINARY_DIR}) 64# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS}) 65# 66# Example with RELPATH: 67# Assume we have a layout like: 68# .../CMakeLists.txt 69# .../bar.cc 70# .../proto/ 71# .../proto/foo.proto (Which contains: import "sub/bar.proto"; ) 72# .../proto/sub/bar.proto 73# Everything would be the same as the previous example, but the call to 74# NANOPB_GENERATE_CPP would change to: 75# 76# NANOPB_GENERATE_CPP(PROTO_SRCS PROTO_HDRS RELPATH proto 77# proto/foo.proto proto/sub/bar.proto) 78# 79# ==================================================================== 80 81#============================================================================= 82# Copyright 2009 Kitware, Inc. 83# Copyright 2009-2011 Philip Lowman <philip@yhbt.com> 84# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS 85# 86# Redistribution and use in source and binary forms, with or without 87# modification, are permitted provided that the following conditions 88# are met: 89# 90# * Redistributions of source code must retain the above copyright 91# notice, this list of conditions and the following disclaimer. 92# 93# * Redistributions in binary form must reproduce the above copyright 94# notice, this list of conditions and the following disclaimer in the 95# documentation and/or other materials provided with the distribution. 96# 97# * Neither the names of Kitware, Inc., the Insight Software Consortium, 98# nor the names of their contributors may be used to endorse or promote 99# products derived from this software without specific prior written 100# permission. 101# 102# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 103# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 104# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 105# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 106# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 107# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 108# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 109# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 110# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 111# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 112# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 113# 114#============================================================================= 115# 116# Changes 117# 2013.01.31 - Pavlo Ilin - used Modules/FindProtobuf.cmake from cmake 2.8.10 to 118# write FindNanopb.cmake 119# 120#============================================================================= 121 122 123function(NANOPB_GENERATE_CPP SRCS HDRS) 124 cmake_parse_arguments(NANOPB_GENERATE_CPP "" "RELPATH" "" ${ARGN}) 125 if(NOT NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS) 126 return() 127 endif() 128 set(NANOPB_OPTIONS_DIRS) 129 130 if(NANOPB_GENERATE_CPP_RELPATH) 131 list(APPEND _nanopb_include_path "-I${NANOPB_GENERATE_CPP_RELPATH}") 132 list(APPEND NANOPB_OPTIONS_DIRS ${NANOPB_GENERATE_CPP_RELPATH}) 133 endif() 134 135 if(NANOPB_GENERATE_CPP_APPEND_PATH) 136 # Create an include path for each file specified 137 foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS}) 138 get_filename_component(ABS_FIL ${FIL} ABSOLUTE) 139 get_filename_component(ABS_PATH ${ABS_FIL} PATH) 140 list(APPEND _nanopb_include_path "-I${ABS_PATH}") 141 endforeach() 142 else() 143 set(_nanopb_include_path "-I${CMAKE_CURRENT_SOURCE_DIR}") 144 endif() 145 146 if(DEFINED NANOPB_IMPORT_DIRS) 147 foreach(DIR ${NANOPB_IMPORT_DIRS}) 148 get_filename_component(ABS_PATH ${DIR} ABSOLUTE) 149 list(APPEND _nanopb_include_path "-I${ABS_PATH}") 150 endforeach() 151 endif() 152 153 list(REMOVE_DUPLICATES _nanopb_include_path) 154 155 set(GENERATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/nanopb/generator) 156 157 set(NANOPB_GENERATOR_EXECUTABLE ${GENERATOR_PATH}/nanopb_generator.py) 158 if (CMAKE_HOST_WIN32) 159 set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb.bat) 160 else() 161 set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb) 162 endif() 163 164 set(GENERATOR_CORE_DIR ${GENERATOR_PATH}/proto) 165 set(GENERATOR_CORE_SRC 166 ${GENERATOR_CORE_DIR}/nanopb.proto) 167 168 # Treat the source directory as immutable. 169 # 170 # Copy the generator directory to the build directory before 171 # compiling python and proto files. Fixes issues when using the 172 # same build directory with different python/protobuf versions 173 # as the binary build directory is discarded across builds. 174 # 175 add_custom_command( 176 OUTPUT ${NANOPB_GENERATOR_EXECUTABLE} ${GENERATOR_CORE_SRC} 177 COMMAND ${CMAKE_COMMAND} -E copy_directory 178 ARGS ${NANOPB_GENERATOR_SOURCE_DIR} ${GENERATOR_PATH} 179 VERBATIM) 180 181 set(GENERATOR_CORE_PYTHON_SRC) 182 foreach(FIL ${GENERATOR_CORE_SRC}) 183 get_filename_component(ABS_FIL ${FIL} ABSOLUTE) 184 get_filename_component(FIL_WE ${FIL} NAME_WE) 185 186 set(output "${GENERATOR_CORE_DIR}/${FIL_WE}_pb2.py") 187 set(GENERATOR_CORE_PYTHON_SRC ${GENERATOR_CORE_PYTHON_SRC} ${output}) 188 add_custom_command( 189 OUTPUT ${output} 190 COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} 191 ARGS -I${GENERATOR_PATH}/proto 192 --python_out=${GENERATOR_CORE_DIR} ${ABS_FIL} 193 DEPENDS ${ABS_FIL} 194 VERBATIM) 195 endforeach() 196 197 if(NANOPB_GENERATE_CPP_RELPATH) 198 get_filename_component(ABS_ROOT ${NANOPB_GENERATE_CPP_RELPATH} ABSOLUTE) 199 endif() 200 foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS}) 201 get_filename_component(ABS_FIL ${FIL} ABSOLUTE) 202 get_filename_component(FIL_WE ${FIL} NAME_WLE) 203 get_filename_component(FIL_DIR ${ABS_FIL} PATH) 204 set(FIL_PATH_REL) 205 if(ABS_ROOT) 206 # Check that the file is under the given "RELPATH" 207 string(FIND ${ABS_FIL} ${ABS_ROOT} LOC) 208 if (${LOC} EQUAL 0) 209 string(REPLACE "${ABS_ROOT}/" "" FIL_REL ${ABS_FIL}) 210 get_filename_component(FIL_PATH_REL ${FIL_REL} PATH) 211 file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}) 212 endif() 213 endif() 214 if(NOT FIL_PATH_REL) 215 set(FIL_PATH_REL ".") 216 endif() 217 218 list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c") 219 list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h") 220 221 # If there an options file in the same working directory, set it as a dependency 222 get_filename_component(ABS_OPT_FIL ${FIL_DIR}/${FIL_WE}.options ABSOLUTE) 223 if(EXISTS ${ABS_OPT_FIL}) 224 # Get directory as lookups for dependency options fail if an options 225 # file is used. The options is still set as a dependency of the 226 # generated source and header. 227 get_filename_component(options_dir ${ABS_OPT_FIL} DIRECTORY) 228 list(APPEND NANOPB_OPTIONS_DIRS ${options_dir}) 229 else() 230 set(ABS_OPT_FIL) 231 endif() 232 233 # If the dependencies are options files, we need to pass the directories 234 # as arguments to nanopb 235 foreach(depends_file ${NANOPB_DEPENDS}) 236 get_filename_component(ext ${depends_file} EXT) 237 if(ext STREQUAL ".options") 238 get_filename_component(depends_dir ${depends_file} DIRECTORY) 239 list(APPEND NANOPB_OPTIONS_DIRS ${depends_dir}) 240 endif() 241 endforeach() 242 243 if(NANOPB_OPTIONS_DIRS) 244 list(REMOVE_DUPLICATES NANOPB_OPTIONS_DIRS) 245 endif() 246 247 set(NANOPB_PLUGIN_OPTIONS) 248 foreach(options_path ${NANOPB_OPTIONS_DIRS}) 249 set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} -I${options_path}") 250 endforeach() 251 252 if(NANOPB_OPTIONS) 253 set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} ${NANOPB_OPTIONS}") 254 endif() 255 256 # based on the version of protoc it might be necessary to add "/${FIL_PATH_REL}" currently dealt with in #516 257 set(NANOPB_OUT "${CMAKE_CURRENT_BINARY_DIR}") 258 259 # We need to pass the path to the option files to the nanopb plugin. There are two ways to do it. 260 # - An older hacky one using ':' as option separator in protoc args preventing the ':' to be used in path. 261 # - Or a newer one, using --nanopb_opt which requires a version of protoc >= 3.6 262 # Since nanopb 0.4.6, --nanopb_opt is the default. 263 if(DEFINED NANOPB_PROTOC_OLDER_THAN_3_6_0) 264 set(NANOPB_OPT_STRING "--nanopb_out=${NANOPB_PLUGIN_OPTIONS}:${NANOPB_OUT}") 265 else() 266 set(NANOPB_OPT_STRING "--nanopb_opt=${NANOPB_PLUGIN_OPTIONS}" "--nanopb_out=${NANOPB_OUT}") 267 endif() 268 269 add_custom_command( 270 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c" 271 "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h" 272 COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} 273 ARGS ${_nanopb_include_path} -I${GENERATOR_PATH} 274 -I${GENERATOR_CORE_DIR} -I${CMAKE_CURRENT_BINARY_DIR} 275 --plugin=protoc-gen-nanopb=${NANOPB_GENERATOR_PLUGIN} 276 ${NANOPB_OPT_STRING} 277 ${PROTOC_OPTIONS} 278 ${ABS_FIL} 279 DEPENDS ${ABS_FIL} ${GENERATOR_CORE_PYTHON_SRC} 280 ${ABS_OPT_FIL} ${NANOPB_DEPENDS} 281 COMMENT "Running C++ protocol buffer compiler using nanopb plugin on ${FIL}" 282 VERBATIM ) 283 284 endforeach() 285 286 set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE) 287 288 if(NOT DEFINED NANOPB_GENERATE_CPP_STANDALONE) 289 set(NANOPB_GENERATE_CPP_STANDALONE TRUE) 290 endif() 291 292 if (NANOPB_GENERATE_CPP_STANDALONE) 293 set(${SRCS} ${${SRCS}} ${NANOPB_SRCS} PARENT_SCOPE) 294 set(${HDRS} ${${HDRS}} ${NANOPB_HDRS} PARENT_SCOPE) 295 else() 296 set(${SRCS} ${${SRCS}} PARENT_SCOPE) 297 set(${HDRS} ${${HDRS}} PARENT_SCOPE) 298 endif() 299endfunction() 300 301 302 303# 304# Main. 305# 306 307# By default have NANOPB_GENERATE_CPP macro pass -I to protoc 308# for each directory where a proto file is referenced. 309if(NOT DEFINED NANOPB_GENERATE_CPP_APPEND_PATH) 310 set(NANOPB_GENERATE_CPP_APPEND_PATH TRUE) 311endif() 312 313# Make a really good guess regarding location of NANOPB_SRC_ROOT_FOLDER 314if(NOT DEFINED NANOPB_SRC_ROOT_FOLDER) 315 get_filename_component(NANOPB_SRC_ROOT_FOLDER 316 ${CMAKE_CURRENT_LIST_DIR}/.. ABSOLUTE) 317endif() 318 319# Find the include directory 320find_path(NANOPB_INCLUDE_DIRS 321 pb.h 322 PATHS ${NANOPB_SRC_ROOT_FOLDER} 323 NO_CMAKE_FIND_ROOT_PATH 324) 325mark_as_advanced(NANOPB_INCLUDE_DIRS) 326 327# Find nanopb source files 328set(NANOPB_SRCS) 329set(NANOPB_HDRS) 330list(APPEND _nanopb_srcs pb_decode.c pb_encode.c pb_common.c) 331list(APPEND _nanopb_hdrs pb_decode.h pb_encode.h pb_common.h pb.h) 332 333foreach(FIL ${_nanopb_srcs}) 334 find_file(${FIL}__nano_pb_file NAMES ${FIL} PATHS ${NANOPB_SRC_ROOT_FOLDER} ${NANOPB_INCLUDE_DIRS} NO_CMAKE_FIND_ROOT_PATH) 335 list(APPEND NANOPB_SRCS "${${FIL}__nano_pb_file}") 336 mark_as_advanced(${FIL}__nano_pb_file) 337endforeach() 338 339foreach(FIL ${_nanopb_hdrs}) 340 find_file(${FIL}__nano_pb_file NAMES ${FIL} PATHS ${NANOPB_INCLUDE_DIRS} NO_CMAKE_FIND_ROOT_PATH) 341 mark_as_advanced(${FIL}__nano_pb_file) 342 list(APPEND NANOPB_HDRS "${${FIL}__nano_pb_file}") 343endforeach() 344 345# Find the protoc Executable 346find_program(PROTOBUF_PROTOC_EXECUTABLE 347 NAMES protoc 348 DOC "The Google Protocol Buffers Compiler" 349 PATHS 350 ${PROTOBUF_SRC_ROOT_FOLDER}/vsprojects/Release 351 ${PROTOBUF_SRC_ROOT_FOLDER}/vsprojects/Debug 352 ${NANOPB_SRC_ROOT_FOLDER}/generator-bin 353 ${NANOPB_SRC_ROOT_FOLDER}/generator 354) 355mark_as_advanced(PROTOBUF_PROTOC_EXECUTABLE) 356 357# Find nanopb generator source dir 358find_path(NANOPB_GENERATOR_SOURCE_DIR 359 NAMES nanopb_generator.py 360 DOC "nanopb generator source" 361 PATHS 362 ${NANOPB_SRC_ROOT_FOLDER}/generator 363 NO_CMAKE_FIND_ROOT_PATH 364) 365mark_as_advanced(NANOPB_GENERATOR_SOURCE_DIR) 366 367include(FindPackageHandleStandardArgs) 368find_package_handle_standard_args(Nanopb DEFAULT_MSG 369 NANOPB_INCLUDE_DIRS 370 NANOPB_SRCS NANOPB_HDRS 371 NANOPB_GENERATOR_SOURCE_DIR 372 PROTOBUF_PROTOC_EXECUTABLE 373 ) 374