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 pw_compilation_testing_NEGATIVE_COMPILATION_ENABLED = host_os != "win" 141 } 142 143 # Populate architecture-specific build args. 144 assert( 145 defined(invoker.cpu), 146 "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") 147 if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M33) { 148 _current_cpu = "arm" 149 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 150 _arch_build_args = { 151 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 152 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:pw_boot_cortex_m" 153 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context" 154 } 155 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 156 157 if (defined(invoker.system_toolchain)) { 158 _system_toolchain = invoker.system_toolchain 159 } else { 160 _system_toolchain = pw_toolchain_arm_gcc 161 } 162 163 _final_binary_extension = ".elf" 164 165 _toolchains = [ 166 { 167 toolchain_base = _system_toolchain.cortex_m33_debug 168 level_name = _OPTIMIZATION_LEVELS.DEBUG 169 }, 170 { 171 toolchain_base = _system_toolchain.cortex_m33_size_optimized 172 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 173 }, 174 { 175 toolchain_base = _system_toolchain.cortex_m33_speed_optimized 176 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 177 }, 178 ] 179 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M55) { 180 _current_cpu = "arm" 181 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 182 _arch_build_args = { 183 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 184 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:pw_boot_cortex_m" 185 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context" 186 } 187 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 188 189 if (defined(invoker.system_toolchain)) { 190 _system_toolchain = invoker.system_toolchain 191 } else { 192 _system_toolchain = pw_toolchain_arm_gcc 193 } 194 195 _final_binary_extension = ".elf" 196 197 _toolchains = [ 198 { 199 toolchain_base = _system_toolchain.cortex_m55_debug 200 level_name = _OPTIMIZATION_LEVELS.DEBUG 201 }, 202 { 203 toolchain_base = _system_toolchain.cortex_m55_size_optimized 204 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 205 }, 206 { 207 toolchain_base = _system_toolchain.cortex_m55_speed_optimized 208 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 209 }, 210 ] 211 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M7F) { 212 _current_cpu = "arm" 213 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 214 _arch_build_args = { 215 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 216 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 217 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 218 } 219 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 220 221 if (defined(invoker.system_toolchain)) { 222 _system_toolchain = invoker.system_toolchain 223 } else { 224 _system_toolchain = pw_toolchain_arm_gcc 225 } 226 227 _final_binary_extension = ".elf" 228 229 _toolchains = [ 230 { 231 toolchain_base = _system_toolchain.cortex_m7f_debug 232 level_name = _OPTIMIZATION_LEVELS.DEBUG 233 }, 234 { 235 toolchain_base = _system_toolchain.cortex_m7f_size_optimized 236 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 237 }, 238 { 239 toolchain_base = _system_toolchain.cortex_m7f_speed_optimized 240 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 241 }, 242 ] 243 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M4F) { 244 _current_cpu = "arm" 245 _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ] 246 _arch_build_args = { 247 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 248 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 249 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 250 } 251 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 252 253 if (defined(invoker.system_toolchain)) { 254 _system_toolchain = invoker.system_toolchain 255 } else { 256 _system_toolchain = pw_toolchain_arm_gcc 257 } 258 259 _final_binary_extension = ".elf" 260 261 _toolchains = [ 262 { 263 toolchain_base = _system_toolchain.cortex_m4f_debug 264 level_name = _OPTIMIZATION_LEVELS.DEBUG 265 }, 266 { 267 toolchain_base = _system_toolchain.cortex_m4f_size_optimized 268 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 269 }, 270 { 271 toolchain_base = _system_toolchain.cortex_m4f_speed_optimized 272 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 273 }, 274 ] 275 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M3) { 276 _current_cpu = "arm" 277 _arch_build_args = { 278 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 279 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 280 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 281 } 282 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 283 284 if (defined(invoker.system_toolchain)) { 285 _system_toolchain = invoker.system_toolchain 286 } else { 287 _system_toolchain = pw_toolchain_arm_gcc 288 } 289 290 _final_binary_extension = ".elf" 291 292 _toolchains = [ 293 { 294 toolchain_base = _system_toolchain.cortex_m3_debug 295 level_name = _OPTIMIZATION_LEVELS.DEBUG 296 }, 297 { 298 toolchain_base = _system_toolchain.cortex_m3_size_optimized 299 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 300 }, 301 { 302 toolchain_base = _system_toolchain.cortex_m3_speed_optimized 303 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 304 }, 305 ] 306 } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M0PLUS) { 307 _current_cpu = "arm" 308 _arch_build_args = { 309 pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty" 310 pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m" 311 pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m" 312 } 313 _link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ] 314 315 if (defined(invoker.system_toolchain)) { 316 _system_toolchain = invoker.system_toolchain 317 } else { 318 _system_toolchain = pw_toolchain_arm_gcc 319 } 320 321 # This creates a double .elf.elf extension for the rp2040 target. 322 # _final_binary_extension = ".elf" 323 324 _toolchains = [ 325 { 326 toolchain_base = _system_toolchain.cortex_m0plus_debug 327 level_name = _OPTIMIZATION_LEVELS.DEBUG 328 }, 329 { 330 toolchain_base = _system_toolchain.cortex_m0plus_size_optimized 331 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 332 }, 333 { 334 toolchain_base = _system_toolchain.cortex_m0plus_speed_optimized 335 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 336 }, 337 ] 338 } else if (invoker.cpu == PW_SYSTEM_CPU.NATIVE) { 339 _current_cpu = host_cpu 340 _arch_build_args = { 341 pw_log_BACKEND = dir_pw_log_string 342 pw_log_string_HANDLER_BACKEND = "$dir_pw_system:log_backend" 343 pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" 344 pw_system_IO_BACKEND = "$dir_pw_system:socket_target_io" 345 } 346 _link_deps += [ "$dir_pw_log_string:handler.impl" ] 347 348 if (defined(invoker.system_toolchain)) { 349 _system_toolchain = invoker.system_toolchain 350 } else if (host_os == "win") { 351 _system_toolchain = pw_toolchain_host_gcc 352 } else { 353 _system_toolchain = pw_toolchain_host_clang 354 } 355 356 _toolchains = [ 357 { 358 toolchain_base = _system_toolchain.debug 359 level_name = _OPTIMIZATION_LEVELS.DEBUG 360 }, 361 { 362 toolchain_base = _system_toolchain.size_optimized 363 level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED 364 }, 365 { 366 toolchain_base = _system_toolchain.speed_optimized 367 level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED 368 }, 369 ] 370 } 371 assert(defined(_arch_build_args), 372 "Unknown cpu choice for $target_name: `${invoker.cpu}`") 373 374 # Populate OS-specific build args. 375 assert( 376 defined(invoker.scheduler), 377 "Please select an `scheduler` for $target_name. Options: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE") 378 if (invoker.scheduler == PW_SYSTEM_SCHEDULER.FREERTOS) { 379 _current_os = "freertos" 380 _os_build_args = PW_SYSTEM_FREERTOS_BACKENDS 381 } else if (invoker.scheduler == PW_SYSTEM_SCHEDULER.NATIVE) { 382 _current_os = host_os 383 _os_build_args = PW_SYSTEM_STL_BACKENDS 384 } 385 assert(defined(_os_build_args), 386 "Unknown scheduler choice for $target_name: `${invoker.scheduler}`") 387 388 # Configure malloc defaults. 389 _use_pw_malloc = false 390 if (defined(invoker.use_pw_malloc)) { 391 _use_pw_malloc = invoker.use_pw_malloc 392 } else if (invoker.cpu != PW_SYSTEM_CPU.NATIVE) { 393 _use_pw_malloc = true 394 } 395 396 if (_use_pw_malloc) { 397 _default_configs += [ "$dir_pw_malloc:wrap_functions" ] 398 _link_deps += [ dir_pw_malloc ] 399 _malloc_build_args = { 400 pw_malloc_BACKEND = "$dir_pw_malloc:bucket_block_allocator" 401 } 402 } else { 403 _malloc_build_args = { 404 } 405 } 406 407 foreach(toolchain_and_level, _toolchains) { 408 # Clear from previous iteration. 409 _base = { 410 } 411 _base = toolchain_and_level.toolchain_base 412 413 generate_toolchain("${target_name}.${toolchain_and_level.level_name}") { 414 forward_variables_from(_base, 415 "*", 416 [ 417 "defaults", 418 "name", 419 ]) 420 final_binary_extension = _final_binary_extension 421 defaults = { 422 current_os = _current_os 423 current_cpu = _current_cpu 424 forward_variables_from(_base.defaults, "*") 425 forward_variables_from(_default_build_args, "*") 426 forward_variables_from(_arch_build_args, "*") 427 forward_variables_from(_os_build_args, "*") 428 forward_variables_from(_malloc_build_args, "*") 429 default_configs += _default_configs 430 if (!defined(pw_build_LINK_DEPS)) { 431 pw_build_LINK_DEPS = [] 432 } 433 pw_build_LINK_DEPS += _link_deps 434 435 if (defined(invoker.build_args)) { 436 forward_variables_from(invoker.build_args, "*") 437 } 438 } 439 } 440 } 441} 442