blob: 669da6a3edba36006635a8a43bbe3b9ba009c074 [file] [log] [blame]
# Copyright 2021 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
import("//build_overrides/pigweed.gni")
import("$dir_pw_assert/backend.gni")
import("$dir_pw_bloat/bloat.gni")
import("$dir_pw_boot/backend.gni")
import("$dir_pw_build/cc_library.gni")
import("$dir_pw_chrono/backend.gni")
import("$dir_pw_interrupt/backend.gni")
import("$dir_pw_log/backend.gni")
import("$dir_pw_log_string/backend.gni")
import("$dir_pw_malloc/backend.gni")
import("$dir_pw_sync/backend.gni")
import("$dir_pw_sys_io/backend.gni")
import("$dir_pw_thread/backend.gni")
import("$dir_pw_toolchain/arm_gcc/toolchains.gni")
import("$dir_pw_toolchain/generate_toolchain.gni")
import("$dir_pw_toolchain/host_clang/toolchains.gni")
import("$dir_pw_toolchain/host_gcc/toolchains.gni")
import("$dir_pw_trace/backend.gni")
import("$dir_pw_trace_tokenized/config.gni")
import("$dir_pw_unit_test/test.gni")
import("backend.gni")
import("freertos_backends.gni")
import("stl_backends.gni")
# This scope is essentially an enum for pw_system_target's `cpu` selection.
PW_SYSTEM_CPU = {
CORTEX_M0PLUS = "cortex-m0plus"
CORTEX_M4F = "cortex-m4f"
CORTEX_M3 = "cortex-m3"
CORTEX_M7F = "cortex-m7f"
CORTEX_M33 = "cortex-m33"
# Native builds for the host CPU.
NATIVE = "native"
}
# This scope is essentially an enum for pw_system_target's `scheduler`
# selection.
PW_SYSTEM_SCHEDULER = {
FREERTOS = "freertos"
# Native uses the host OS's native scheduler and OS primitives as provided
# through the Standard Template Library.
NATIVE = "native"
}
declare_args() {
# This argument is intended to be user-facing and should NOT be set by a
# toolchain. This switches ALL pw_system_target toolchains to use the
# multi_endpoint_rpc_config config to illustrate a multi-endpoint mode that
# isolates logging and RPC traffic via HDLC multiplexing.
#
# If you would like to use this in production, it is strongly recommended that
# you instead just add the appropriate defines to your target's toolchain
# definition.
pw_system_USE_MULTI_ENDPOINT_CONFIG = false
}
# Defines a target toolchain, automatically setting many required build
# arguments to simplify instantiation of a target.
#
# Args:
# cpu: (required) The architecture to target.
# Supported choices: PW_SYSTEM_CPU.CORTEX_M7F, PW_SYSTEM_CPU.CORTEX_M4F, PW_SYSTEM_CPU.CORTEX_M3,
# PW_SYSTEM_CPU.CORTEX_M33, PW_SYSTEM_CPU.NATIVE
# scheduler: (required) The scheduler implementation and API to use for this
# target.
# Supported choices: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE
# system_toolchain: Override the default toolchain selection.
# use_pw_malloc: Whether or not to replace the default malloc implementation
# with pw_malloc. Defaults enabled for supported targets.
# link_deps: Additional link-time dependencies required for all executables.
# This is a list of source sets.
# build_args: Additional overrides for GN build arguments.
# global_configs: Configs that will be globally applied to all pw_source_set,
# pw_static_library, and pw_executable targets.
template("pw_system_target") {
_OPTIMIZATION_LEVELS = {
SIZE_OPTIMIZED = "size_optimized"
SPEED_OPTIMIZED = "speed_optimized"
DEBUG = "debug"
}
# Generic defaults.
_default_configs = [ "$dir_pw_build:extra_strict_warnings" ]
if (defined(invoker.global_configs)) {
foreach(cfg, invoker.global_configs) {
_default_configs += [ get_path_info(cfg, "abspath") ]
}
}
_link_deps = [
"$dir_pw_assert:impl",
"$dir_pw_log:impl",
]
if (defined(invoker.link_deps)) {
_link_deps += invoker.link_deps
}
_final_binary_extension = ""
_default_build_args = {
pw_system_RPC_SERVER_BACKEND = "$dir_pw_system:hdlc_rpc_server"
pw_system_IO_BACKEND = "$dir_pw_system:sys_io_target_io"
# TODO(amontanez): This should be set to pw_assert_log ASAP.
pw_assert_BACKEND = dir_pw_assert_basic
# TODO(amontanez): This should be set to pw_log_tokenized when support
# is added.
pw_log_BACKEND = dir_pw_log_basic
# TODO(amontanez): This should be set to a "$dir_pw_unit_test:rpc_main"
# when RPC is working.
pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main"
pw_trace_BACKEND = "$dir_pw_trace_tokenized"
if (pw_system_USE_MULTI_ENDPOINT_CONFIG) {
pw_system_CONFIG = "$dir_pw_system:multi_endpoint_rpc_config"
}
}
# Populate architecture-specific build args.
assert(
defined(invoker.cpu),
"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")
if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M33) {
_current_cpu = "arm"
_default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ]
_arch_build_args = {
pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
pw_boot_BACKEND = "$dir_pw_boot_cortex_m:pw_boot_cortex_m"
pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context"
}
_link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else {
_system_toolchain = pw_toolchain_arm_gcc
}
_final_binary_extension = ".elf"
_toolchains = [
{
toolchain_base = _system_toolchain.cortex_m33_debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.cortex_m33_size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.cortex_m33_speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
} else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M7F) {
_current_cpu = "arm"
_default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ]
_arch_build_args = {
pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
}
_link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else {
_system_toolchain = pw_toolchain_arm_gcc
}
_final_binary_extension = ".elf"
_toolchains = [
{
toolchain_base = _system_toolchain.cortex_m7f_debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.cortex_m7f_size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.cortex_m7f_speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
} else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M4F) {
_current_cpu = "arm"
_default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ]
_arch_build_args = {
pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
}
_link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else {
_system_toolchain = pw_toolchain_arm_gcc
}
_final_binary_extension = ".elf"
_toolchains = [
{
toolchain_base = _system_toolchain.cortex_m4f_debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.cortex_m4f_size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.cortex_m4f_speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
} else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M3) {
_current_cpu = "arm"
_arch_build_args = {
pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
}
_link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else {
_system_toolchain = pw_toolchain_arm_gcc
}
_final_binary_extension = ".elf"
_toolchains = [
{
toolchain_base = _system_toolchain.cortex_m3_debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.cortex_m3_size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.cortex_m3_speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
} else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M0PLUS) {
_current_cpu = "arm"
_arch_build_args = {
pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
}
_link_deps += [ "$dir_pw_toolchain/arm_gcc:arm_none_eabi_gcc_support" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else {
_system_toolchain = pw_toolchain_arm_gcc
}
# This creates a double .elf.elf extension for the rp2040 target.
# _final_binary_extension = ".elf"
_toolchains = [
{
toolchain_base = _system_toolchain.cortex_m0plus_debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.cortex_m0plus_size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.cortex_m0plus_speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
} else if (invoker.cpu == PW_SYSTEM_CPU.NATIVE) {
_current_cpu = host_cpu
_arch_build_args = {
pw_log_BACKEND = dir_pw_log_string
pw_log_string_HANDLER_BACKEND = "$dir_pw_system:log_backend"
pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio"
pw_system_IO_BACKEND = "$dir_pw_system:socket_target_io"
}
_link_deps += [ "$dir_pw_log_string:handler.impl" ]
if (defined(invoker.system_toolchain)) {
_system_toolchain = invoker.system_toolchain
} else if (host_os == "win") {
_system_toolchain = pw_toolchain_host_gcc
} else {
_system_toolchain = pw_toolchain_host_clang
}
_toolchains = [
{
toolchain_base = _system_toolchain.debug
level_name = _OPTIMIZATION_LEVELS.DEBUG
},
{
toolchain_base = _system_toolchain.size_optimized
level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
},
{
toolchain_base = _system_toolchain.speed_optimized
level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
},
]
}
assert(defined(_arch_build_args),
"Unknown cpu choice for $target_name: `${invoker.cpu}`")
# Populate OS-specific build args.
assert(
defined(invoker.scheduler),
"Please select an `scheduler` for $target_name. Options: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE")
if (invoker.scheduler == PW_SYSTEM_SCHEDULER.FREERTOS) {
_current_os = "freertos"
_os_build_args = PW_SYSTEM_FREERTOS_BACKENDS
} else if (invoker.scheduler == PW_SYSTEM_SCHEDULER.NATIVE) {
_current_os = host_os
_os_build_args = PW_SYSTEM_STL_BACKENDS
}
assert(defined(_os_build_args),
"Unknown scheduler choice for $target_name: `${invoker.scheduler}`")
# Configure malloc defaults.
_use_pw_malloc = false
if (defined(invoker.use_pw_malloc)) {
_use_pw_malloc = invoker.use_pw_malloc
} else if (invoker.cpu != PW_SYSTEM_CPU.NATIVE) {
_use_pw_malloc = true
}
if (_use_pw_malloc) {
_default_configs += [ "$dir_pw_malloc:wrap_functions" ]
_link_deps += [ dir_pw_malloc ]
_malloc_build_args = {
pw_malloc_BACKEND = "$dir_pw_malloc:bucket_block_allocator"
}
} else {
_malloc_build_args = {
}
}
foreach(toolchain_and_level, _toolchains) {
# Clear from previous iteration.
_base = {
}
_base = toolchain_and_level.toolchain_base
generate_toolchain("${target_name}.${toolchain_and_level.level_name}") {
forward_variables_from(_base,
"*",
[
"defaults",
"name",
])
final_binary_extension = _final_binary_extension
defaults = {
current_os = _current_os
current_cpu = _current_cpu
forward_variables_from(_base.defaults, "*")
forward_variables_from(_default_build_args, "*")
forward_variables_from(_arch_build_args, "*")
forward_variables_from(_os_build_args, "*")
forward_variables_from(_malloc_build_args, "*")
default_configs += _default_configs
if (!defined(pw_build_LINK_DEPS)) {
pw_build_LINK_DEPS = []
}
pw_build_LINK_DEPS += _link_deps
if (defined(invoker.build_args)) {
forward_variables_from(invoker.build_args, "*")
}
}
}
}
}