1# Copyright 2021 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 15import("//build_overrides/pigweed.gni") 16 17import("$dir_pw_assert/backend.gni") 18import("$dir_pw_bloat/bloat.gni") 19import("$dir_pw_boot/backend.gni") 20import("$dir_pw_build/cc_library.gni") 21import("$dir_pw_chrono/backend.gni") 22import("$dir_pw_interrupt/backend.gni") 23import("$dir_pw_log/backend.gni") 24import("$dir_pw_log_string/backend.gni") 25import("$dir_pw_malloc/backend.gni") 26import("$dir_pw_sync/backend.gni") 27import("$dir_pw_sys_io/backend.gni") 28import("$dir_pw_thread/backend.gni") 29import("$dir_pw_toolchain/arm_gcc/toolchains.gni") 30import("$dir_pw_toolchain/generate_toolchain.gni") 31import("$dir_pw_toolchain/host_clang/toolchains.gni") 32import("$dir_pw_toolchain/host_gcc/toolchains.gni") 33import("$dir_pw_trace/backend.gni") 34import("$dir_pw_trace_tokenized/config.gni") 35import("$dir_pw_unit_test/test.gni") 36import("backend.gni") 37import("freertos_backends.gni") 38import("stl_backends.gni") 39 40# This scope is essentially an enum for pw_system_target's `cpu` selection. 41PW_SYSTEM_CPU = { 42 CORTEX_M0PLUS = "cortex-m0plus" 43 CORTEX_M4F = "cortex-m4f" 44 CORTEX_M3 = "cortex-m3" 45 CORTEX_M7F = "cortex-m7f" 46 CORTEX_M33 = "cortex-m33" 47 48 # Native builds for the host CPU. 49 NATIVE = "native" 50} 51 52# This scope is essentially an enum for pw_system_target's `scheduler` 53# selection. 54PW_SYSTEM_SCHEDULER = { 55 FREERTOS = "freertos" 56 57 # Native uses the host OS's native scheduler and OS primitives as provided 58 # through the Standard Template Library. 59 NATIVE = "native" 60} 61 62declare_args() { 63 # This argument is intended to be user-facing and should NOT be set by a 64 # toolchain. This switches ALL pw_system_target toolchains to use the 65 # multi_endpoint_rpc_config config to illustrate a multi-endpoint mode that 66 # isolates logging and RPC traffic via HDLC multiplexing. 67 # 68 # If you would like to use this in production, it is strongly recommended that 69 # you instead just add the appropriate defines to your target's toolchain 70 # definition. 71 pw_system_USE_MULTI_ENDPOINT_CONFIG = false 72} 73 74# Defines a target toolchain, automatically setting many required build 75# arguments to simplify instantiation of a target. 76# 77# Args: 78# cpu: (required) The architecture to target. 79# Supported choices: PW_SYSTEM_CPU.CORTEX_M7F, PW_SYSTEM_CPU.CORTEX_M4F, PW_SYSTEM_CPU.CORTEX_M3, 80# PW_SYSTEM_CPU.CORTEX_M33, PW_SYSTEM_CPU.NATIVE 81# scheduler: (required) The scheduler implementation and API to use for this 82# target. 83# Supported choices: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE 84# system_toolchain: Override the default toolchain selection. 85# use_pw_malloc: Whether or not to replace the default malloc implementation 86# with pw_malloc. Defaults enabled for supported targets. 87# link_deps: Additional link-time dependencies required for all executables. 88# This is a list of source sets. 89# build_args: Additional overrides for GN build arguments. 90# global_configs: Configs that will be globally applied to all pw_source_set, 91# pw_static_library, and pw_executable targets. 92template("pw_system_target") { 93 _OPTIMIZATION_LEVELS = { 94 SIZE_OPTIMIZED = "size_optimized" 95 SPEED_OPTIMIZED = "speed_optimized" 96 DEBUG = "debug" 97 } 98 99 # Generic defaults. 100 _default_configs = [ "$dir_pw_build:extra_strict_warnings" ] 101 if (defined(invoker.global_configs)) { 102 foreach(cfg, invoker.global_configs) { 103 _default_configs += [ get_path_info(cfg, "abspath") ] 104 } 105 } 106 107 _link_deps = [ 108 "$dir_pw_assert:impl", 109 "$dir_pw_log:impl", 110 ] 111 if (defined(invoker.link_deps)) { 112 _link_deps += invoker.link_deps 113 } 114 _final_binary_extension = "" 115 116 _default_build_args = { 117 pw_system_RPC_SERVER_BACKEND = "$dir_pw_system:hdlc_rpc_server" 118 pw_system_IO_BACKEND = "$dir_pw_system:sys_io_target_io" 119 120 # TODO(amontanez): This should be set to pw_assert_log ASAP. 121 pw_assert_BACKEND = dir_pw_assert_basic 122 123 # TODO(amontanez): This should be set to pw_log_tokenized when support 124 # is added. 125 pw_log_BACKEND = dir_pw_log_basic 126 127 # TODO(amontanez): This should be set to a "$dir_pw_unit_test:rpc_main" 128 # when RPC is working. 129 pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" 130 131 pw_trace_BACKEND = "$dir_pw_trace_tokenized" 132 133 if (pw_system_USE_MULTI_ENDPOINT_CONFIG) { 134 pw_system_CONFIG = "$dir_pw_system:multi_endpoint_rpc_config" 135 } 136 } 137 138 # Populate architecture-specific build args. 139 assert( 140 defined(invoker.cpu), 141 "Please select a `cpu` for $target_name. Options: PW_SYSTEM_CPU.CORTEX_M7, PW_SYSTEM_CPU.CORTEX_M4F, PW_SYSTEM_CPU.CORTEX_M3, PW_SYSTEM_CPU.CORTEX_M33, PW_SYSTEM_CPU.NATIVE") 142 if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M33) { 143 _current_cpu = "arm" 144 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 145 _arch_build_args = { 146 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 147 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:pw_boot_cortex_m" 148 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context" 149 } 150 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 151 152 if (defined(invoker.system_toolchain)) { 153 _system_toolchain = invoker.system_toolchain 154 } else { 155 _system_toolchain = pw_toolchain_arm_gcc 156 } 157 158 _final_binary_extension = ".elf" 159 160 _toolchains = [ 161 { 162 toolchain_base = _system_toolchain.cortex_m33_debug 163 level_name = _OPTIMIZATION_LEVELS.DEBUG 164 }, 165 { 166 toolchain_base = _system_toolchain.cortex_m33_size_optimized 167 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 168 }, 169 { 170 toolchain_base = _system_toolchain.cortex_m33_speed_optimized 171 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 172 }, 173 ] 174 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M7F) { 175 _current_cpu = "arm" 176 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 177 _arch_build_args = { 178 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 179 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 180 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 181 } 182 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 183 184 if (defined(invoker.system_toolchain)) { 185 _system_toolchain = invoker.system_toolchain 186 } else { 187 _system_toolchain = pw_toolchain_arm_gcc 188 } 189 190 _final_binary_extension = ".elf" 191 192 _toolchains = [ 193 { 194 toolchain_base = _system_toolchain.cortex_m7f_debug 195 level_name = _OPTIMIZATION_LEVELS.DEBUG 196 }, 197 { 198 toolchain_base = _system_toolchain.cortex_m7f_size_optimized 199 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 200 }, 201 { 202 toolchain_base = _system_toolchain.cortex_m7f_speed_optimized 203 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 204 }, 205 ] 206 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M4F) { 207 _current_cpu = "arm" 208 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 209 _arch_build_args = { 210 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 211 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 212 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 213 } 214 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 215 216 if (defined(invoker.system_toolchain)) { 217 _system_toolchain = invoker.system_toolchain 218 } else { 219 _system_toolchain = pw_toolchain_arm_gcc 220 } 221 222 _final_binary_extension = ".elf" 223 224 _toolchains = [ 225 { 226 toolchain_base = _system_toolchain.cortex_m4f_debug 227 level_name = _OPTIMIZATION_LEVELS.DEBUG 228 }, 229 { 230 toolchain_base = _system_toolchain.cortex_m4f_size_optimized 231 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 232 }, 233 { 234 toolchain_base = _system_toolchain.cortex_m4f_speed_optimized 235 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 236 }, 237 ] 238 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M3) { 239 _current_cpu = "arm" 240 _arch_build_args = { 241 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 242 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 243 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 244 } 245 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 246 247 if (defined(invoker.system_toolchain)) { 248 _system_toolchain = invoker.system_toolchain 249 } else { 250 _system_toolchain = pw_toolchain_arm_gcc 251 } 252 253 _final_binary_extension = ".elf" 254 255 _toolchains = [ 256 { 257 toolchain_base = _system_toolchain.cortex_m3_debug 258 level_name = _OPTIMIZATION_LEVELS.DEBUG 259 }, 260 { 261 toolchain_base = _system_toolchain.cortex_m3_size_optimized 262 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 263 }, 264 { 265 toolchain_base = _system_toolchain.cortex_m3_speed_optimized 266 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 267 }, 268 ] 269 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M0PLUS) { 270 _current_cpu = "arm" 271 _arch_build_args = { 272 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 273 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 274 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 275 } 276 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 277 278 if (defined(invoker.system_toolchain)) { 279 _system_toolchain = invoker.system_toolchain 280 } else { 281 _system_toolchain = pw_toolchain_arm_gcc 282 } 283 284 # This creates a double .elf.elf extension for the rp2040 target. 285 # _final_binary_extension = ".elf" 286 287 _toolchains = [ 288 { 289 toolchain_base = _system_toolchain.cortex_m0plus_debug 290 level_name = _OPTIMIZATION_LEVELS.DEBUG 291 }, 292 { 293 toolchain_base = _system_toolchain.cortex_m0plus_size_optimized 294 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 295 }, 296 { 297 toolchain_base = _system_toolchain.cortex_m0plus_speed_optimized 298 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 299 }, 300 ] 301 } else if (invoker.cpu == PW_SYSTEM_CPU.NATIVE) { 302 _current_cpu = host_cpu 303 _arch_build_args = { 304 pw_log_BACKEND = dir_pw_log_string 305 pw_log_string_HANDLER_BACKEND = "$dir_pw_system:log_backend" 306 pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" 307 pw_system_IO_BACKEND = "$dir_pw_system:socket_target_io" 308 } 309 _link_deps += [ "$dir_pw_log_string:handler.impl" ] 310 311 if (defined(invoker.system_toolchain)) { 312 _system_toolchain = invoker.system_toolchain 313 } else if (host_os == "win") { 314 _system_toolchain = pw_toolchain_host_gcc 315 } else { 316 _system_toolchain = pw_toolchain_host_clang 317 } 318 319 _toolchains = [ 320 { 321 toolchain_base = _system_toolchain.debug 322 level_name = _OPTIMIZATION_LEVELS.DEBUG 323 }, 324 { 325 toolchain_base = _system_toolchain.size_optimized 326 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 327 }, 328 { 329 toolchain_base = _system_toolchain.speed_optimized 330 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 331 }, 332 ] 333 } 334 assert(defined(_arch_build_args), 335 "Unknown cpu choice for $target_name: `${invoker.cpu}`") 336 337 # Populate OS-specific build args. 338 assert( 339 defined(invoker.scheduler), 340 "Please select an `scheduler` for $target_name. Options: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE") 341 if (invoker.scheduler == PW_SYSTEM_SCHEDULER.FREERTOS) { 342 _current_os = "freertos" 343 _os_build_args = PW_SYSTEM_FREERTOS_BACKENDS 344 } else if (invoker.scheduler == PW_SYSTEM_SCHEDULER.NATIVE) { 345 _current_os = host_os 346 _os_build_args = PW_SYSTEM_STL_BACKENDS 347 } 348 assert(defined(_os_build_args), 349 "Unknown scheduler choice for $target_name: `${invoker.scheduler}`") 350 351 # Configure malloc defaults. 352 _use_pw_malloc = false 353 if (defined(invoker.use_pw_malloc)) { 354 _use_pw_malloc = invoker.use_pw_malloc 355 } else if (invoker.cpu != PW_SYSTEM_CPU.NATIVE) { 356 _use_pw_malloc = true 357 } 358 359 if (_use_pw_malloc) { 360 _default_configs += [ "$dir_pw_malloc:wrap_functions" ] 361 _link_deps += [ dir_pw_malloc ] 362 _malloc_build_args = { 363 pw_malloc_BACKEND = "$dir_pw_malloc:bucket_block_allocator" 364 } 365 } else { 366 _malloc_build_args = { 367 } 368 } 369 370 foreach(toolchain_and_level, _toolchains) { 371 # Clear from previous iteration. 372 _base = { 373 } 374 _base = toolchain_and_level.toolchain_base 375 376 generate_toolchain("${target_name}.${toolchain_and_level.level_name}") { 377 forward_variables_from(_base, 378 "*", 379 [ 380 "defaults", 381 "name", 382 ]) 383 final_binary_extension = _final_binary_extension 384 defaults = { 385 current_os = _current_os 386 current_cpu = _current_cpu 387 forward_variables_from(_base.defaults, "*") 388 forward_variables_from(_default_build_args, "*") 389 forward_variables_from(_arch_build_args, "*") 390 forward_variables_from(_os_build_args, "*") 391 forward_variables_from(_malloc_build_args, "*") 392 default_configs += _default_configs 393 if (!defined(pw_build_LINK_DEPS)) { 394 pw_build_LINK_DEPS = [] 395 } 396 pw_build_LINK_DEPS += _link_deps 397 398 if (defined(invoker.build_args)) { 399 forward_variables_from(invoker.build_args, "*") 400 } 401 } 402 } 403 } 404} 405