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