blob: c805829b09f2393816b5b4e167e2be460094ec38 [file] [log] [blame]
Julian Halldf86fce2020-11-23 18:09:55 +01001#-------------------------------------------------------------------------------
Gyorgy Szing96669942021-12-08 04:19:50 +01002# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
Julian Halldf86fce2020-11-23 18:09:55 +01003#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8#[===[.rst:
Gyorgy Szing2247d242021-09-03 16:17:25 +02009NanoPB integration for cmake
Julian Halldf86fce2020-11-23 18:09:55 +010010----------------------------
11
12This module will:
13 - download nanopb if not available locally
14 - build the runtime static library and the generator
15 - import the static library to the build
16 - define a function to provide access to the generator
17
18Note: the python module created by the generator build will be installed under
19Python_SITELIB ("Third-party platform independent installation directory.")
20This means the build may alter the state of your system. Please use virtualenv.
21
Gyorgy Szing2247d242021-09-03 16:17:25 +020022Note: see requirements.txt for dependencies which need to be installed before
Julian Halldf86fce2020-11-23 18:09:55 +010023running this module.
24
25#]===]
26
27#### Get the dependency
28
Gyorgy Szing96669942021-12-08 04:19:50 +010029set(NANOPB_URL "https://github.com/nanopb/nanopb.git"
30 CACHE STRING "nanopb repository URL")
31set(NANOPB_REFSPEC "nanopb-0.4.2"
32 CACHE STRING "nanopb git refspec")
33set(NANOPB_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/nanopb-src"
34 CACHE PATH "nanopb source-code")
35set(NANOPB_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/nanopb_install"
36 CACHE PATH "nanopb installation directory")
Julian Halldf86fce2020-11-23 18:09:55 +010037
38# Checking git
39find_program(GIT_COMMAND "git")
40if (NOT GIT_COMMAND)
41 message(FATAL_ERROR "Please install git")
42endif()
43
Gyorgy Szing96669942021-12-08 04:19:50 +010044set(GIT_OPTIONS
Julian Halldf86fce2020-11-23 18:09:55 +010045 GIT_REPOSITORY ${NANOPB_URL}
46 GIT_TAG ${NANOPB_REFSPEC}
Julian Halla628af32022-04-01 10:08:18 +010047 GIT_SHALLOW FALSE
Julian Halldf86fce2020-11-23 18:09:55 +010048 #See the .patch file for details on why it is needed.
49 PATCH_COMMAND git stash
50 COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/fix-pyhon-name.patch
Gyorgy Szing96669942021-12-08 04:19:50 +010051 )
Julian Halldf86fce2020-11-23 18:09:55 +010052
Andrew Beggs97a00d42021-06-15 15:45:46 +000053if (NOT "${NANOPB_EXTERNAL_INCLUDE_PATHS}" STREQUAL "")
Gyorgy Szing96669942021-12-08 04:19:50 +010054 string(REPLACE ";" " " NANOPB_EXTERNAL_INCLUDE_PATHS "${NANOPB_EXTERNAL_INCLUDE_PATHS}")
Andrew Beggs97a00d42021-06-15 15:45:46 +000055endif()
56
Gyorgy Szing96669942021-12-08 04:19:50 +010057include(${TS_ROOT}/tools/cmake/common/LazyFetch.cmake REQUIRED)
58LazyFetch_MakeAvailable(DEP_NAME nanopb
59 FETCH_OPTIONS ${GIT_OPTIONS}
60 INSTALL_DIR ${NANOPB_INSTALL_DIR}
61 PACKAGE_DIR ${NANOPB_INSTALL_DIR}
62 CACHE_FILE "${TS_ROOT}/external/nanopb/nanopb-init-cache.cmake.in"
63 SOURCE_DIR "${NANOPB_SOURCE_DIR}"
64 )
Julian Halldf86fce2020-11-23 18:09:55 +010065
Gyorgy Szing96669942021-12-08 04:19:50 +010066#set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${NANOPB_INSTALL_DIR}/)
Julian Halldf86fce2020-11-23 18:09:55 +010067
68#### Build access to the protobuf compiler
69#TODO: verify protoc dependencies: python3-protobuf
Gyorgy Szing96669942021-12-08 04:19:50 +010070find_package(Python3 REQUIRED COMPONENTS Interpreter)
Julian Halldf86fce2020-11-23 18:09:55 +010071
72find_file(NANOPB_GENERATOR_PATH
73 NAMES nanopb_generator.py
74 PATHS ${nanopb_SOURCE_DIR}/generator
75 DOC "nanopb protobuf compiler"
76 NO_DEFAULT_PATH
77 )
78
79if (NOT NANOPB_GENERATOR_PATH)
80 message(FATAL_ERROR "Nanopb generator was not found!")
81endif()
82
83#[===[.rst:
84.. cmake:command:: protobuf_generate
85
86 .. code-block:: cmake
87
88 protobuf_generate(SRC file.proto
89 TGT foo
90 NAMESPACE bar
91 BASE_DIR "proto/definitions")
92
93 Run the ``nanopb_generator`` to compile a protobuf definition file into C source.
94 Generated source file will be added to the source list of ``TGT``. Protobuf
95 compilation will take part before TGT+NAMESPACE is built.
96
97 Protobuf file names added to the same TGT must not collide.
98
99 Inputs:
100
101 ``SRC``
Gyorgy Szing2247d242021-09-03 16:17:25 +0200102 Path to of the protobuf file to process. Either absolute or relative to the
Julian Halldf86fce2020-11-23 18:09:55 +0100103 callers location.
104
105 ``TGT``
106 Name of target to compile generated source files.
107
108 ``NAMESPACE``
109 Namespace to put generated files under. Specifies include path and allows
110 separating colliding protobuf files.
111
112 ``BASE_DIR``
Gyorgy Szing2247d242021-09-03 16:17:25 +0200113 Base directory. Generated files are located relative to this base.
Julian Halldf86fce2020-11-23 18:09:55 +0100114
115#]===]
116function(protobuf_generate)
117 set(_options )
118 set(_oneValueArgs SRC TGT NAMESPACE BASE_DIR)
119 set(_multiValueArgs )
120
121 cmake_parse_arguments(PARAMS "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
122
123 #Verify mandatory parameters
124 if (NOT DEFINED PARAMS_SRC)
125 message(FATAL_ERROR "nanopb_generate(): mandatory parameter SRC missing.")
126 endif()
127 if (NOT DEFINED PARAMS_TGT)
128 message(FATAL_ERROR "nanopb_generate(): mandatory parameter TGT missing.")
129 endif()
130 if (NOT DEFINED PARAMS_NAMESPACE)
131 message(FATAL_ERROR "nanopb_generate(): mandatory parameter NAMESPACE missing.")
132 endif()
133 if (NOT DEFINED PARAMS_BASE_DIR)
134 message(FATAL_ERROR "nanopb_generate(): mandatory parameter BASE_DIR missing.")
135 endif()
136
Gyorgy Szing2247d242021-09-03 16:17:25 +0200137 #If SRC is not absolute make it relative to the callers location.
Julian Halldf86fce2020-11-23 18:09:55 +0100138 if (NOT IS_ABSOLUTE ${PARAMS_SRC})
139 set(PARAMS_SRC "${CMAKE_CURRENT_LIST_DIR}/${PARAMS_SRC}")
140 endif()
141
142 #Calculate the output directory
143 set(_OUT_DIR_BASE ${CMAKE_BINARY_DIR}/src/${PARAMS_NAMESPACE})
144 #Calculate output file names
145 get_filename_component(_BASENAME ${PARAMS_SRC} NAME_WE)
146
147 #Get relative path or SRC to BASE_DIR
148 file(RELATIVE_PATH _SRC_REL ${PARAMS_BASE_DIR} ${PARAMS_SRC})
149 get_filename_component(_OUT_DIR_REL ${_SRC_REL} DIRECTORY )
150
151 #Calculate output file paths
152 set(_OUT_C "${_OUT_DIR_BASE}/${_OUT_DIR_REL}/${_BASENAME}.pb.c")
153 set(_OUT_H "${_OUT_DIR_BASE}/${_OUT_DIR_REL}/${_BASENAME}.pb.h")
154
155 #some helper variables for the purpose of readability
156 set(_nanopb_target "nanopb_generate_${PARAMS_TGT}_${PARAMS_NAMESPACE}")
157 set(_nanopb_fake_file "nanopb_generate_ff_${PARAMS_TGT}")
158
159 if (NOT TARGET "${_nanopb_target}")
Gyorgy Szingcd3241a2021-06-30 22:41:11 +0000160 #Tell cmake the dependency (source) file is fake.
161 set_source_files_properties("${_nanopb_fake_file}" PROPERTIES SYMBOLIC "true")
Julian Halldf86fce2020-11-23 18:09:55 +0100162 #Create a custom target which depends on a "fake" file.
163 add_custom_target("${_nanopb_target}"
164 DEPENDS "${_nanopb_fake_file}")
Gyorgy Szing2247d242021-09-03 16:17:25 +0200165 #Add a custom command to the target to create output directory.
Julian Halldf86fce2020-11-23 18:09:55 +0100166 add_custom_command(OUTPUT "${_nanopb_fake_file}"
167 COMMAND ${CMAKE_COMMAND} -E make_directory ${_OUT_DIR_BASE}
168 COMMENT "Generating source from protobuf definitions for target ${PARAMS_TGT}")
169 #Ensure protobuf build happens before test target.
170 add_dependencies(${PARAMS_TGT} ${_nanopb_target})
171 #Add include path to protobuf output.
172 target_include_directories(${PARAMS_TGT} PRIVATE ${_OUT_DIR_BASE})
173 endif()
174
Gyorgy Szing0358e082022-05-10 09:09:37 +0200175 get_filename_component(NANOPB_GENERATOR_DIR "${NANOPB_GENERATOR_PATH}" DIRECTORY CACHE "Location of nanopb generator.")
Julian Halldf86fce2020-11-23 18:09:55 +0100176 #Append a protobuf generator command to the nanopb_generate target.
Gyorgy Szingcd3241a2021-06-30 22:41:11 +0000177 add_custom_command(OUTPUT "${_OUT_C}" "${_OUT_H}"
Gyorgy Szing0358e082022-05-10 09:09:37 +0200178 COMMAND
179 ${CMAKE_COMMAND} -E env PYTHONPATH=${NANOPB_GENERATOR_DIR}
180 ${Python3_EXECUTABLE} ${NANOPB_GENERATOR_PATH}
Julian Halldf86fce2020-11-23 18:09:55 +0100181 -I ${PARAMS_BASE_DIR}
182 -D ${_OUT_DIR_BASE}
183 ${_SRC_REL}
184 DEPENDS "${PARAMS_SRC}")
185
186 #Add generated file to the target
187 set_property(SOURCE "${_OUT_C}" PROPERTY GENERATED TRUE)
188 target_sources(${PARAMS_TGT} PRIVATE "${_OUT_C}")
189endfunction()
190
191#[===[.rst:
192.. cmake:command:: protobuf_generate_all
193
194 .. code-block:: cmake
195
196 protobuf_generate_all(TGT foo
197 NAMESPACE bar
198 BASE_DIR "proto/definitions")
199
200 Generates C code from all .proto files listed in the target
201 property PROTOBUF_FILES.
202
203 Inputs:
204
205 ``TGT``
206 Name of target to compile generated source files.
207
208 ``NAMESPACE``
209 Namespace to put generated files under. Specifies include path and allows
210 separating colliding protobuf files.
211
212 ``BASE_DIR``
Gyorgy Szing2247d242021-09-03 16:17:25 +0200213 Base directory. Generated files are located relative to this base.
Julian Halldf86fce2020-11-23 18:09:55 +0100214
215#]===]
216function(protobuf_generate_all)
217 set(_options )
218 set(_oneValueArgs TGT NAMESPACE BASE_DIR)
219 set(_multiValueArgs )
220
221 cmake_parse_arguments(PARAMS "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
222
223 #Verify mandatory parameters
224 if (NOT DEFINED PARAMS_TGT)
225 message(FATAL_ERROR "nanopb_generate_all(): mandatory parameter TGT missing.")
226 endif()
227 if (NOT DEFINED PARAMS_NAMESPACE)
228 message(FATAL_ERROR "nanopb_generate_all(): mandatory parameter NAMESPACE missing.")
229 endif()
230 if (NOT DEFINED PARAMS_BASE_DIR)
231 message(FATAL_ERROR "nanopb_generate_all(): mandatory parameter BASE_DIR missing.")
232 endif()
233
234 get_property(_protolist TARGET ${PARAMS_TGT} PROPERTY PROTOBUF_FILES)
235
236 #Build of each .proto file
237 foreach(_file IN LISTS _protolist)
238 protobuf_generate(
239 TGT ${PARAMS_TGT}
240 SRC "${_file}"
241 NAMESPACE ${PARAMS_NAMESPACE}
242 BASE_DIR ${PARAMS_BASE_DIR})
243 endforeach()
Gyorgy Szing96669942021-12-08 04:19:50 +0100244endfunction()