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