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