• 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_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