aboutsummaryrefslogtreecommitdiff
path: root/extra/FindNanopb.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'extra/FindNanopb.cmake')
-rw-r--r--extra/FindNanopb.cmake211
1 files changed, 163 insertions, 48 deletions
diff --git a/extra/FindNanopb.cmake b/extra/FindNanopb.cmake
index c804e70..bba341d 100644
--- a/extra/FindNanopb.cmake
+++ b/extra/FindNanopb.cmake
@@ -1,10 +1,6 @@
# This is an example script for use with CMake projects for locating and configuring
# the nanopb library.
#
-# The following varialbes have to be set:
-#
-# NANOPB_SRC_ROOT_FOLDER - Path to nanopb source folder
-#
# The following variables can be set and are optional:
#
#
@@ -16,6 +12,13 @@
# NANOPB_IMPORT_DIRS - List of additional directories to be searched for
# imported .proto files.
#
+# NANOPB_OPTIONS - List of options passed to nanopb.
+#
+# NANOPB_DEPENDS - List of files to be used as dependencies
+# for the generated source and header files. These
+# files are not directly passed as options to
+# nanopb but rather their directories.
+#
# NANOPB_GENERATE_CPP_APPEND_PATH - By default -I will be passed to protoc
# for each directory where a proto file is referenced.
# Set to FALSE if you want to disable this behaviour.
@@ -26,23 +29,28 @@
# NANOPB_INCLUDE_DIRS - Include directories for Google Protocol Buffers
#
# The following cache variables are also available to set or use:
-# NANOPB_GENERATOR_EXECUTABLE - The nanopb generator
# PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler
+# NANOPB_GENERATOR_SOURCE_DIR - The nanopb generator source
#
# ====================================================================
#
# NANOPB_GENERATE_CPP (public function)
-# SRCS = Variable to define with autogenerated
-# source files
-# HDRS = Variable to define with autogenerated
-# header files
-# ARGN = proto files
+# NANOPB_GENERATE_CPP(SRCS HDRS [RELPATH <root-path-of-proto-files>]
+# <proto-files>...)
+# SRCS = Variable to define with autogenerated source files
+# HDRS = Variable to define with autogenerated header files
+# If you want to use relative paths in your import statements use the RELPATH
+# option. The argument to RELPATH should be the directory that all the
+# imports will be relative to.
+# When RELPATH is not specified then all proto files can be imported without
+# a path.
+#
#
# ====================================================================
# Example:
#
# set(NANOPB_SRC_ROOT_FOLDER "/path/to/nanopb")
-# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_SRC_ROOT_FOLDER}/cmake)
+# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_SRC_ROOT_FOLDER}/extra)
# find_package( Nanopb REQUIRED )
# include_directories(${NANOPB_INCLUDE_DIRS})
#
@@ -51,6 +59,19 @@
# include_directories(${CMAKE_CURRENT_BINARY_DIR})
# add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
#
+# Example with RELPATH:
+# Assume we have a layout like:
+# .../CMakeLists.txt
+# .../bar.cc
+# .../proto/
+# .../proto/foo.proto (Which contains: import "sub/bar.proto"; )
+# .../proto/sub/bar.proto
+# Everything would be the same as the previous example, but the call to
+# NANOPB_GENERATE_CPP would change to:
+#
+# NANOPB_GENERATE_CPP(PROTO_SRCS PROTO_HDRS RELPATH proto
+# proto/foo.proto proto/sub/bar.proto)
+#
# ====================================================================
#=============================================================================
@@ -96,62 +117,148 @@
function(NANOPB_GENERATE_CPP SRCS HDRS)
- if(NOT ARGN)
+ cmake_parse_arguments(NANOPB_GENERATE_CPP "" "RELPATH" "" ${ARGN})
+ if(NOT NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS)
return()
endif()
if(NANOPB_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
- foreach(FIL ${ARGN})
+ foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
-
- list(FIND _nanobp_include_path ${ABS_PATH} _contains_already)
- if(${_contains_already} EQUAL -1)
- list(APPEND _nanobp_include_path -I ${ABS_PATH})
- endif()
+ list(APPEND _nanopb_include_path "-I${ABS_PATH}")
endforeach()
else()
- set(_nanobp_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+ set(_nanopb_include_path "-I${CMAKE_CURRENT_SOURCE_DIR}")
+ endif()
+
+ if(NANOPB_GENERATE_CPP_RELPATH)
+ list(APPEND _nanopb_include_path "-I${NANOPB_GENERATE_CPP_RELPATH}")
endif()
if(DEFINED NANOPB_IMPORT_DIRS)
foreach(DIR ${NANOPB_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
- list(FIND _nanobp_include_path ${ABS_PATH} _contains_already)
- if(${_contains_already} EQUAL -1)
- list(APPEND _nanobp_include_path -I ${ABS_PATH})
- endif()
+ list(APPEND _nanopb_include_path "-I${ABS_PATH}")
endforeach()
endif()
- set(${SRCS})
- set(${HDRS})
- get_filename_component(GENERATOR_PATH ${NANOPB_GENERATOR_EXECUTABLE} PATH)
+ list(REMOVE_DUPLICATES _nanopb_include_path)
+
+ set(GENERATOR_PATH ${CMAKE_BINARY_DIR}/nanopb/generator)
+
+ set(NANOPB_GENERATOR_EXECUTABLE ${GENERATOR_PATH}/nanopb_generator.py)
+ set(NANOPB_GENERATOR_PLUGIN ${GENERATOR_PATH}/protoc-gen-nanopb)
+
+ set(GENERATOR_CORE_DIR ${GENERATOR_PATH}/proto)
+ set(GENERATOR_CORE_SRC
+ ${GENERATOR_CORE_DIR}/nanopb.proto
+ ${GENERATOR_CORE_DIR}/plugin.proto)
+
+ # Treat the source diretory as immutable.
+ #
+ # Copy the generator directory to the build directory before
+ # compiling python and proto files. Fixes issues when using the
+ # same build directory with different python/protobuf versions
+ # as the binary build directory is discarded across builds.
+ #
+ add_custom_command(
+ OUTPUT ${NANOPB_GENERATOR_EXECUTABLE} ${GENERATOR_CORE_SRC}
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ ARGS ${NANOPB_GENERATOR_SOURCE_DIR} ${GENERATOR_PATH}
+ VERBATIM)
+
+ set(GENERATOR_CORE_PYTHON_SRC)
+ foreach(FIL ${GENERATOR_CORE_SRC})
+ get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+ get_filename_component(FIL_WE ${FIL} NAME_WE)
- foreach(FIL ${ARGN})
+ set(output "${GENERATOR_CORE_DIR}/${FIL_WE}_pb2.py")
+ set(GENERATOR_CORE_PYTHON_SRC ${GENERATOR_CORE_PYTHON_SRC} ${output})
+ add_custom_command(
+ OUTPUT ${output}
+ COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+ ARGS -I${GENERATOR_PATH}/proto
+ --python_out=${GENERATOR_CORE_DIR} ${ABS_FIL}
+ DEPENDS ${ABS_FIL}
+ VERBATIM)
+ endforeach()
+
+ if(NANOPB_GENERATE_CPP_RELPATH)
+ get_filename_component(ABS_ROOT ${NANOPB_GENERATE_CPP_RELPATH} ABSOLUTE)
+ endif()
+ foreach(FIL ${NANOPB_GENERATE_CPP_UNPARSED_ARGUMENTS})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
+ get_filename_component(FIL_DIR ${FIL} PATH)
+ set(FIL_PATH_REL)
+ if(ABS_ROOT)
+ # Check that the file is under the given "RELPATH"
+ string(FIND ${ABS_FIL} ${ABS_ROOT} LOC)
+ if (${LOC} EQUAL 0)
+ string(REPLACE "${ABS_ROOT}/" "" FIL_REL ${ABS_FIL})
+ get_filename_component(FIL_PATH_REL ${FIL_REL} PATH)
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL})
+ endif()
+ endif()
+ if(NOT FIL_PATH_REL)
+ set(FIL_PATH_REL ".")
+ endif()
+
+ list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c")
+ list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h")
+
+ set(NANOPB_PLUGIN_OPTIONS)
+ set(NANOPB_OPTIONS_DIRS)
+
+ # If there an options file in the same working directory, set it as a dependency
+ set(NANOPB_OPTIONS_FILE ${FIL_DIR}/${FIL_WE}.options)
+ if(EXISTS ${NANOPB_OPTIONS_FILE})
+ # Get directory as lookups for dependency options fail if an options
+ # file is used. The options is still set as a dependency of the
+ # generated source and header.
+ get_filename_component(options_dir ${NANOPB_OPTIONS_FILE} DIRECTORY)
+ list(APPEND NANOPB_OPTIONS_DIRS ${options_dir})
+ else()
+ set(NANOPB_OPTIONS_FILE)
+ endif()
+
+ # If the dependencies are options files, we need to pass the directories
+ # as arguments to nanopb
+ foreach(depends_file ${NANOPB_DEPENDS})
+ get_filename_component(ext ${depends_file} EXT)
+ if(ext STREQUAL ".options")
+ get_filename_component(depends_dir ${depends_file} DIRECTORY)
+ list(APPEND NANOPB_OPTIONS_DIRS ${depends_dir})
+ endif()
+ endforeach()
- list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.c")
- list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
+ if(NANOPB_OPTIONS_DIRS)
+ list(REMOVE_DUPLICATES NANOPB_OPTIONS_DIRS)
+ endif()
+
+ foreach(options_path ${NANOPB_OPTIONS_DIRS})
+ set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} -I${options_path}")
+ endforeach()
+
+ if(NANOPB_OPTIONS)
+ set(NANOPB_PLUGIN_OPTIONS "${NANOPB_PLUGIN_OPTIONS} ${NANOPB_OPTIONS}")
+ endif()
add_custom_command(
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb"
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.c"
+ "${CMAKE_CURRENT_BINARY_DIR}/${FIL_PATH_REL}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
- ARGS -I${GENERATOR_PATH} -I${CMAKE_CURRENT_BINARY_DIR} ${_nanobp_include_path} -o${FIL_WE}.pb ${ABS_FIL}
- DEPENDS ${ABS_FIL}
- COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+ ARGS -I${GENERATOR_PATH} -I${GENERATOR_CORE_DIR}
+ -I${CMAKE_CURRENT_BINARY_DIR} ${_nanopb_include_path}
+ --plugin=protoc-gen-nanopb=${NANOPB_GENERATOR_PLUGIN}
+ "--nanopb_out=${NANOPB_PLUGIN_OPTIONS}:${CMAKE_CURRENT_BINARY_DIR}" ${ABS_FIL}
+ DEPENDS ${ABS_FIL} ${GENERATOR_CORE_PYTHON_SRC}
+ ${NANOPB_OPTIONS_FILE} ${NANOPB_DEPENDS}
+ COMMENT "Running C++ protocol buffer compiler using nanopb plugin on ${FIL}"
VERBATIM )
- add_custom_command(
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.c"
- "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
- COMMAND python
- ARGS ${NANOPB_GENERATOR_EXECUTABLE} ${FIL_WE}.pb
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb"
- COMMENT "Running nanopb generator on ${FIL_WE}.pb"
- VERBATIM )
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
@@ -172,6 +279,12 @@ if(NOT DEFINED NANOPB_GENERATE_CPP_APPEND_PATH)
set(NANOPB_GENERATE_CPP_APPEND_PATH TRUE)
endif()
+# Make a really good guess regarding location of NANOPB_SRC_ROOT_FOLDER
+if(NOT DEFINED NANOPB_SRC_ROOT_FOLDER)
+ get_filename_component(NANOPB_SRC_ROOT_FOLDER
+ ${CMAKE_CURRENT_LIST_DIR}/.. ABSOLUTE)
+endif()
+
# Find the include directory
find_path(NANOPB_INCLUDE_DIRS
pb.h
@@ -182,8 +295,8 @@ mark_as_advanced(NANOPB_INCLUDE_DIRS)
# Find nanopb source files
set(NANOPB_SRCS)
set(NANOPB_HDRS)
-list(APPEND _nanopb_srcs pb_decode.c pb_encode.c)
-list(APPEND _nanopb_hdrs pb_decode.h pb_encode.h pb.h)
+list(APPEND _nanopb_srcs pb_decode.c pb_encode.c pb_common.c)
+list(APPEND _nanopb_hdrs pb_decode.h pb_encode.h pb_common.h pb.h)
foreach(FIL ${_nanopb_srcs})
find_file(${FIL}__nano_pb_file NAMES ${FIL} PATHS ${NANOPB_SRC_ROOT_FOLDER} ${NANOPB_INCLUDE_DIRS})
@@ -207,19 +320,21 @@ find_program(PROTOBUF_PROTOC_EXECUTABLE
)
mark_as_advanced(PROTOBUF_PROTOC_EXECUTABLE)
-# Find nanopb generator
-find_file(NANOPB_GENERATOR_EXECUTABLE
+# Find nanopb generator source dir
+find_path(NANOPB_GENERATOR_SOURCE_DIR
NAMES nanopb_generator.py
- DOC "nanopb generator"
+ DOC "nanopb generator source"
PATHS
${NANOPB_SRC_ROOT_FOLDER}/generator
)
-mark_as_advanced(NANOPB_GENERATOR_EXECUTABLE)
+mark_as_advanced(NANOPB_GENERATOR_SOURCE_DIR)
+
+find_package(PythonInterp REQUIRED)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(NANOPB DEFAULT_MSG
NANOPB_INCLUDE_DIRS
NANOPB_SRCS NANOPB_HDRS
- NANOPB_GENERATOR_EXECUTABLE
+ NANOPB_GENERATOR_SOURCE_DIR
PROTOBUF_PROTOC_EXECUTABLE
)