• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_unit_test/test.gni")
34import("backend.gni")
35import("freertos_backends.gni")
36import("stl_backends.gni")
37
38# This scope is essentially an enum for pw_system_target's `cpu` selection.
39PW_SYSTEM_CPU = {
40  CORTEX_M4F = "cortex-m4f"
41  CORTEX_M3 = "cortex-m3"
42  CORTEX_M7F = "cortex-m7f"
43
44  # Native builds for the host CPU.
45  NATIVE = "native"
46}
47
48# This scope is essentially an enum for pw_system_target's `scheduler`
49# selection.
50PW_SYSTEM_SCHEDULER = {
51  FREERTOS = "freertos"
52
53  # Native uses the host OS's native scheduler and OS primitives as provided
54  # through the Standard Template Library.
55  NATIVE = "native"
56}
57
58# Defines a target toolchain, automatically setting many required build
59# arguments to simplify instantiation of a target.
60#
61# Args:
62#  cpu: (required) The architecture to target.
63#    Supported choices: PW_SYSTEM_CPU.CORTEX_M7F, PW_SYSTEM_CPU.CORTEX_M4F, PW_SYSTEM_CPU.CORTEX_M3, PW_SYSTEM_CPU.NATIVE
64#  scheduler: (required) The scheduler implementation and API to use for this
65#    target.
66#    Supported choices: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE
67#  use_pw_malloc: Whether or not to replace the default malloc implementation
68#    with pw_malloc. Defaults enabled for supported targets.
69#  link_deps: Additional link-time dependencies required for all executables.
70#    This is a list of source sets.
71#  build_args: Additional overrides for GN build arguments.
72#  global_configs: Configs that will be globally applied to all pw_source_set,
73#    pw_static_library, and pw_executable targets.
74template("pw_system_target") {
75  _OPTIMIZATION_LEVELS = {
76    SIZE_OPTIMIZED = "size_optimized"
77    SPEED_OPTIMIZED = "speed_optimized"
78    DEBUG = "debug"
79  }
80
81  # Generic defaults.
82  _default_configs = [ "$dir_pw_build:extra_strict_warnings" ]
83  if (defined(invoker.global_configs)) {
84    foreach(cfg, invoker.global_configs) {
85      _default_configs += [ get_path_info(cfg, "abspath") ]
86    }
87  }
88
89  _link_deps = [
90    "$dir_pw_assert:impl",
91    "$dir_pw_log:impl",
92  ]
93  if (defined(invoker.link_deps)) {
94    _link_deps += invoker.link_deps
95  }
96  _final_binary_extension = ""
97
98  _default_build_args = {
99    pw_system_RPC_SERVER_BACKEND = "$dir_pw_system:hdlc_rpc_server"
100    pw_system_IO_BACKEND = "$dir_pw_system:sys_io_target_io"
101
102    # TODO(amontanez): This should be set to pw_assert_log ASAP.
103    pw_assert_BACKEND = dir_pw_assert_basic
104
105    # TODO(amontanez): This should be set to pw_log_tokenized when support
106    # is added.
107    pw_log_BACKEND = dir_pw_log_basic
108
109    pw_rpc_CONFIG = "$dir_pw_rpc:use_global_mutex"
110
111    # TODO(amontanez): This should be set to a "$dir_pw_unit_test:rpc_main"
112    # when RPC is working.
113    pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main"
114  }
115
116  # Populate architecture-specific build args.
117  assert(
118      defined(invoker.cpu),
119      "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.NATIVE")
120  if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M7F) {
121    _current_cpu = "arm"
122    _default_configs += [ "$dir_pw_toolchain/arm_gcc:enable_float_printf" ]
123    _arch_build_args = {
124      pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
125      pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
126      pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
127    }
128
129    _final_binary_extension = ".elf"
130
131    _toolchains = [
132      {
133        toolchain_base = pw_toolchain_arm_gcc.cortex_m7f_debug
134        level_name = _OPTIMIZATION_LEVELS.DEBUG
135      },
136      {
137        toolchain_base = pw_toolchain_arm_gcc.cortex_m7f_size_optimized
138        level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
139      },
140      {
141        toolchain_base = pw_toolchain_arm_gcc.cortex_m7f_speed_optimized
142        level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
143      },
144    ]
145  } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M4F) {
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:armv7m"
151      pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
152    }
153
154    _final_binary_extension = ".elf"
155
156    _toolchains = [
157      {
158        toolchain_base = pw_toolchain_arm_gcc.cortex_m4f_debug
159        level_name = _OPTIMIZATION_LEVELS.DEBUG
160      },
161      {
162        toolchain_base = pw_toolchain_arm_gcc.cortex_m4f_size_optimized
163        level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
164      },
165      {
166        toolchain_base = pw_toolchain_arm_gcc.cortex_m4f_speed_optimized
167        level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
168      },
169    ]
170  } else if (invoker.cpu == PW_SYSTEM_CPU.CORTEX_M3) {
171    _current_cpu = "arm"
172    _arch_build_args = {
173      pw_bloat_BLOATY_CONFIG = "$dir_pw_boot_cortex_m/bloaty_config.bloaty"
174      pw_boot_BACKEND = "$dir_pw_boot_cortex_m:armv7m"
175      pw_interrupt_CONTEXT_BACKEND = "$dir_pw_interrupt_cortex_m:context_armv7m"
176    }
177
178    _final_binary_extension = ".elf"
179
180    _toolchains = [
181      {
182        toolchain_base = pw_toolchain_arm_gcc.cortex_m3_debug
183        level_name = _OPTIMIZATION_LEVELS.DEBUG
184      },
185      {
186        toolchain_base = pw_toolchain_arm_gcc.cortex_m3_size_optimized
187        level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
188      },
189      {
190        toolchain_base = pw_toolchain_arm_gcc.cortex_m3_speed_optimized
191        level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
192      },
193    ]
194  } else if (invoker.cpu == PW_SYSTEM_CPU.NATIVE) {
195    _current_cpu = host_cpu
196    _arch_build_args = {
197      pw_log_BACKEND = dir_pw_log_string
198      pw_log_string_HANDLER_BACKEND = "$dir_pw_system:log_backend"
199      pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio"
200      pw_system_IO_BACKEND = "$dir_pw_system:socket_target_io"
201    }
202    _link_deps += [ "$dir_pw_log_string:handler.impl" ]
203
204    if (host_os != "win") {
205      _toolchains = [
206        {
207          toolchain_base = pw_toolchain_host_clang.debug
208          level_name = _OPTIMIZATION_LEVELS.DEBUG
209        },
210        {
211          toolchain_base = pw_toolchain_host_clang.size_optimized
212          level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
213        },
214        {
215          toolchain_base = pw_toolchain_host_clang.speed_optimized
216          level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
217        },
218      ]
219    } else {
220      _toolchains = [
221        {
222          toolchain_base = pw_toolchain_host_gcc.debug
223          level_name = _OPTIMIZATION_LEVELS.DEBUG
224        },
225        {
226          toolchain_base = pw_toolchain_host_gcc.size_optimized
227          level_name = _OPTIMIZATION_LEVELS.SIZE_OPTIMIZED
228        },
229        {
230          toolchain_base = pw_toolchain_host_gcc.speed_optimized
231          level_name = _OPTIMIZATION_LEVELS.SPEED_OPTIMIZED
232        },
233      ]
234    }
235  }
236  assert(defined(_arch_build_args),
237         "Unknown cpu choice for $target_name: `${invoker.cpu}`")
238
239  # Populate OS-specific build args.
240  assert(
241      defined(invoker.scheduler),
242      "Please select an `scheduler` for $target_name. Options: PW_SYSTEM_SCHEDULER.FREERTOS, PW_SYSTEM_SCHEDULER.NATIVE")
243  if (invoker.scheduler == PW_SYSTEM_SCHEDULER.FREERTOS) {
244    _current_os = "freertos"
245    _os_build_args = PW_SYSTEM_FREERTOS_BACKENDS
246  } else if (invoker.scheduler == PW_SYSTEM_SCHEDULER.NATIVE) {
247    _current_os = host_os
248    _os_build_args = PW_SYSTEM_STL_BACKENDS
249  }
250  assert(defined(_os_build_args),
251         "Unknown scheduler choice for $target_name: `${invoker.scheduler}`")
252
253  # Configure malloc defaults.
254  _use_pw_malloc = false
255  if (defined(invoker.use_pw_malloc)) {
256    _use_pw_malloc = invoker.use_pw_malloc
257  } else if (invoker.cpu != PW_SYSTEM_CPU.NATIVE) {
258    _use_pw_malloc = true
259  }
260
261  if (_use_pw_malloc) {
262    _default_configs += [ "$dir_pw_malloc:pw_malloc_wrapper_config" ]
263    _link_deps += [ dir_pw_malloc ]
264    _malloc_build_args = {
265      pw_malloc_BACKEND = dir_pw_malloc_freelist
266    }
267  } else {
268    _malloc_build_args = {
269    }
270  }
271
272  foreach(toolchain_and_level, _toolchains) {
273    # Clear from previous iteration.
274    _base = {
275    }
276    _base = toolchain_and_level.toolchain_base
277
278    generate_toolchain("${target_name}.${toolchain_and_level.level_name}") {
279      forward_variables_from(_base,
280                             "*",
281                             [
282                               "defaults",
283                               "name",
284                             ])
285      final_binary_extension = _final_binary_extension
286      defaults = {
287        current_os = _current_os
288        current_cpu = _current_cpu
289        forward_variables_from(_base.defaults, "*")
290        forward_variables_from(_default_build_args, "*")
291        forward_variables_from(_arch_build_args, "*")
292        forward_variables_from(_os_build_args, "*")
293        forward_variables_from(_malloc_build_args, "*")
294        default_configs += _default_configs
295        if (!defined(pw_build_LINK_DEPS)) {
296          pw_build_LINK_DEPS = []
297        }
298        pw_build_LINK_DEPS += _link_deps
299
300        if (defined(invoker.build_args)) {
301          forward_variables_from(invoker.build_args, "*")
302        }
303      }
304    }
305  }
306}
307