Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/ardupilotwaf/boards.py
9779 views
1
# encoding: utf-8
2
3
# flake8: noqa
4
5
from collections import OrderedDict
6
import re
7
import sys, os
8
import fnmatch
9
import platform
10
import glob
11
12
import waflib
13
from waflib import Utils, Context
14
from waflib.Configure import conf
15
import json
16
_board_classes = {}
17
_board = None
18
19
# modify our search path:
20
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../libraries/AP_HAL_ChibiOS/hwdef/scripts'))
21
import chibios_hwdef
22
import build_options
23
24
class BoardMeta(type):
25
def __init__(cls, name, bases, dct):
26
super(BoardMeta, cls).__init__(name, bases, dct)
27
28
if 'abstract' not in cls.__dict__:
29
cls.abstract = False
30
if cls.abstract:
31
return
32
33
if not hasattr(cls, 'toolchain'):
34
cls.toolchain = 'native'
35
36
board_name = getattr(cls, 'name', name)
37
if board_name in _board_classes:
38
raise Exception('board named %s already exists' % board_name)
39
_board_classes[board_name] = cls
40
41
class Board:
42
abstract = True
43
44
def __init__(self):
45
self.with_can = False
46
self.with_littlefs = False
47
48
def configure(self, cfg):
49
cfg.env.TOOLCHAIN = cfg.options.toolchain or self.toolchain
50
if hasattr(self,'configure_toolchain'):
51
self.configure_toolchain(cfg)
52
else:
53
cfg.load('toolchain')
54
cfg.load('cxx_checks')
55
56
# don't check elf symbols by default
57
cfg.env.CHECK_SYMBOLS = False
58
59
env = waflib.ConfigSet.ConfigSet()
60
def srcpath(path):
61
return cfg.srcnode.make_node(path).abspath()
62
env.SRCROOT = srcpath('')
63
64
self.configure_env(cfg, env)
65
66
# Setup scripting:
67
env.DEFINES.update(
68
LUA_32BITS = 1,
69
)
70
71
env.AP_LIBRARIES += [
72
'AP_Scripting',
73
'AP_Scripting/lua/src',
74
]
75
76
if cfg.options.enable_scripting:
77
env.DEFINES.update(
78
AP_SCRIPTING_ENABLED = 1,
79
)
80
elif cfg.options.disable_scripting:
81
env.DEFINES.update(
82
AP_SCRIPTING_ENABLED = 0,
83
)
84
85
# embed any scripts from ROMFS/scripts
86
if os.path.exists('ROMFS/scripts'):
87
for f in os.listdir('ROMFS/scripts'):
88
if fnmatch.fnmatch(f, "*.lua"):
89
env.ROMFS_FILES += [('scripts/'+f,'ROMFS/scripts/'+f)]
90
91
# allow GCS disable for AP_DAL example
92
if cfg.options.no_gcs:
93
env.CXXFLAGS += ['-DHAL_GCS_ENABLED=0']
94
95
# Setup DDS
96
if env.BOARD_CLASS == "ChibiOS" or env.BOARD_CLASS == "Linux":
97
# need to check the hwdef.h file for the board to see if dds is enabled
98
# the issue here is that we need to configure the env properly to include
99
# the DDS library, but the definition is the the hwdef file
100
# and can be overridden by the commandline options
101
with open(env.BUILDROOT + "/hwdef.h", 'r', encoding="utf8") as file:
102
if "#define AP_DDS_ENABLED 1" in file.read():
103
# Enable DDS if the hwdef file has it enabled
104
cfg.env.OPTIONS['enable_DDS'] = True
105
elif cfg.env.OPTIONS.get('enable_DDS', False):
106
# Add the define enabled if the hwdef file does not have it and the commandline option is set
107
env.DEFINES.update(
108
AP_DDS_ENABLED=1,
109
)
110
else:
111
# Add the define disabled if the hwdef file does not have it and the commandline option is not set
112
env.DEFINES.update(
113
AP_DDS_ENABLED=0,
114
)
115
else:
116
if cfg.options.enable_DDS:
117
env.DEFINES.update(
118
AP_DDS_ENABLED=1,
119
)
120
else:
121
env.DEFINES.update(
122
AP_DDS_ENABLED=0,
123
)
124
125
# setup for supporting onvif cam control
126
if cfg.options.enable_onvif:
127
cfg.recurse('libraries/AP_ONVIF')
128
env.ENABLE_ONVIF = True
129
env.ROMFS_FILES += [('scripts/ONVIF_Camera_Control.lua',
130
'libraries/AP_Scripting/applets/ONVIF_Camera_Control.lua')]
131
env.DEFINES.update(
132
ENABLE_ONVIF=1,
133
SCRIPTING_ENABLE_DEFAULT=1,
134
)
135
env.AP_LIBRARIES += [
136
'AP_ONVIF'
137
]
138
else:
139
env.ENABLE_ONVIF = False
140
env.DEFINES.update(
141
ENABLE_ONVIF=0,
142
)
143
144
# allow enable of OpenDroneID for any board
145
if cfg.options.enable_opendroneid:
146
env.ENABLE_OPENDRONEID = True
147
env.DEFINES.update(
148
AP_OPENDRONEID_ENABLED=1,
149
)
150
cfg.msg("Enabled OpenDroneID", 'yes')
151
else:
152
cfg.msg("Enabled OpenDroneID", 'no', color='YELLOW')
153
154
# allow enable of firmware ID checking for any board
155
if cfg.options.enable_check_firmware:
156
env.CHECK_FIRMWARE_ENABLED = True
157
env.DEFINES.update(
158
AP_CHECK_FIRMWARE_ENABLED=1,
159
)
160
cfg.msg("Enabled firmware ID checking", 'yes')
161
else:
162
cfg.msg("Enabled firmware ID checking", 'no', color='YELLOW')
163
164
if cfg.options.enable_gps_logging:
165
env.DEFINES.update(
166
AP_GPS_DEBUG_LOGGING_ENABLED=1,
167
)
168
cfg.msg("GPS Debug Logging", 'yes')
169
else:
170
cfg.msg("GPS Debug Logging", 'no', color='YELLOW')
171
172
# allow enable of custom controller for any board
173
# enabled on sitl by default
174
if (cfg.options.enable_custom_controller or self.get_name() == "sitl") and not cfg.options.no_gcs:
175
env.ENABLE_CUSTOM_CONTROLLER = True
176
env.DEFINES.update(
177
AP_CUSTOMCONTROL_ENABLED=1,
178
)
179
env.AP_LIBRARIES += [
180
'AC_CustomControl'
181
]
182
cfg.msg("Enabled custom controller", 'yes')
183
else:
184
env.DEFINES.update(
185
AP_CUSTOMCONTROL_ENABLED=0,
186
)
187
cfg.msg("Enabled custom controller", 'no', color='YELLOW')
188
189
# support enabling any option in build_options.py
190
for opt in build_options.BUILD_OPTIONS:
191
enable_option = opt.config_option().replace("-","_")
192
disable_option = "disable_" + enable_option[len("enable-"):]
193
lower_disable_option = disable_option.lower().replace("_", "-")
194
lower_enable_option = enable_option.lower().replace("_", "-")
195
if getattr(cfg.options, enable_option, False) or getattr(cfg.options, lower_enable_option, False):
196
env.CXXFLAGS += ['-D%s=1' % opt.define]
197
cfg.msg("Enabled %s" % opt.label, 'yes', color='GREEN')
198
elif getattr(cfg.options, disable_option, False) or getattr(cfg.options, lower_disable_option, False):
199
env.CXXFLAGS += ['-D%s=0' % opt.define]
200
cfg.msg("Enabled %s" % opt.label, 'no', color='YELLOW')
201
202
# support embedding lua drivers and applets
203
driver_list = glob.glob(os.path.join(Context.run_dir, "libraries/AP_Scripting/drivers/*.lua"))
204
applet_list = glob.glob(os.path.join(Context.run_dir, "libraries/AP_Scripting/applets/*.lua"))
205
for d in driver_list + applet_list:
206
bname = os.path.basename(d)
207
embed_name = bname[:-4]
208
embed_option = f"embed-{embed_name}".replace("-","_")
209
if getattr(cfg.options, embed_option, False):
210
env.ROMFS_FILES += [(f'scripts/{bname}', d)]
211
cfg.msg(f"Embedded {bname}", 'yes', color='GREEN')
212
213
if cfg.options.disable_networking:
214
env.CXXFLAGS += ['-DAP_NETWORKING_ENABLED=0']
215
216
if cfg.options.enable_networking_tests:
217
env.CXXFLAGS += ['-DAP_NETWORKING_TESTS_ENABLED=1']
218
219
if cfg.options.enable_iomcu_profiled_support:
220
env.CXXFLAGS += ['-DAP_IOMCU_PROFILED_SUPPORT_ENABLED=1']
221
222
d = env.get_merged_dict()
223
# Always prepend so that arguments passed in the command line get
224
# the priority.
225
for k, val in d.items():
226
# Dictionaries (like 'DEFINES') are converted to lists to
227
# conform to waf conventions.
228
if isinstance(val, dict):
229
keys = list(val.keys())
230
if not isinstance(val, OrderedDict):
231
keys.sort()
232
val = ['%s=%s' % (vk, val[vk]) for vk in keys]
233
234
if k in cfg.env and isinstance(cfg.env[k], list):
235
cfg.env.prepend_value(k, val)
236
else:
237
cfg.env[k] = val
238
239
cfg.ap_common_checks()
240
241
cfg.env.prepend_value('INCLUDES', [
242
cfg.srcnode.find_dir('libraries/AP_Common/missing').abspath()
243
])
244
if os.path.exists(os.path.join(env.SRCROOT, '.vscode/c_cpp_properties.json')) and 'AP_NO_COMPILE_COMMANDS' not in os.environ:
245
# change c_cpp_properties.json configure the VSCode Intellisense env
246
c_cpp_properties = json.load(open(os.path.join(env.SRCROOT, '.vscode/c_cpp_properties.json')))
247
for config in c_cpp_properties['configurations']:
248
config['compileCommands'] = "${workspaceFolder}/build/%s/compile_commands.json" % self.get_name()
249
json.dump(c_cpp_properties, open(os.path.join(env.SRCROOT, './.vscode/c_cpp_properties.json'), 'w'), indent=4)
250
cfg.msg("Configured VSCode Intellisense", 'yes')
251
else:
252
cfg.msg("Configured VSCode Intellisense:", 'no', color='YELLOW')
253
254
def cc_version_gte(self, cfg, want_major, want_minor):
255
if cfg.env.TOOLCHAIN == "custom":
256
return True
257
(major, minor, patchlevel) = cfg.env.CC_VERSION
258
return (int(major) > want_major or
259
(int(major) == want_major and int(minor) >= want_minor))
260
261
def configure_env(self, cfg, env):
262
# Use a dictionary instead of the conventional list for definitions to
263
# make easy to override them. Convert back to list before consumption.
264
env.DEFINES = {}
265
266
env.with_can = self.with_can
267
268
# potentially set extra defines from an environment variable:
269
if cfg.options.define is not None:
270
for (n, v) in [d.split("=") for d in cfg.options.define]:
271
cfg.msg("Defining: %s" % (n, ), v)
272
env.CFLAGS += ['-D%s=%s' % (n, v)]
273
env.CXXFLAGS += ['-D%s=%s' % (n, v)]
274
275
env.CFLAGS += [
276
'-ffunction-sections',
277
'-fdata-sections',
278
'-fsigned-char',
279
280
'-Wall',
281
'-Wextra',
282
'-Werror=format',
283
'-Wpointer-arith',
284
'-Wcast-align',
285
'-Wno-missing-field-initializers',
286
'-Wno-unused-parameter',
287
'-Wno-redundant-decls',
288
'-Wno-unknown-pragmas',
289
'-Wno-trigraphs',
290
'-Werror=shadow',
291
'-Werror=return-type',
292
'-Werror=unused-result',
293
'-Werror=unused-variable',
294
'-Werror=narrowing',
295
'-Werror=attributes',
296
'-Werror=overflow',
297
'-Werror=parentheses',
298
'-Werror=format-extra-args',
299
'-Werror=ignored-qualifiers',
300
'-Werror=undef',
301
'-DARDUPILOT_BUILD',
302
]
303
304
if cfg.options.scripting_checks:
305
env.DEFINES.update(
306
AP_SCRIPTING_CHECKS = 1,
307
)
308
309
cfg.msg("CXX Compiler", "%s %s" % (cfg.env.COMPILER_CXX, ".".join(cfg.env.CC_VERSION)))
310
311
if cfg.options.assert_cc_version:
312
cfg.msg("Checking compiler", "%s %s" % (cfg.options.assert_cc_version, ".".join(cfg.env.CC_VERSION)))
313
have_version = cfg.env.COMPILER_CXX+"-"+'.'.join(list(cfg.env.CC_VERSION))
314
want_version = cfg.options.assert_cc_version
315
if have_version != want_version:
316
cfg.fatal("cc version mismatch: %s should be %s" % (have_version, want_version))
317
318
# ensure that if you are using clang you're using it for both
319
# C and C++!
320
if (("clang" in cfg.env.COMPILER_CC and "clang" not in cfg.env.COMPILER_CXX) or
321
("clang" not in cfg.env.COMPILER_CC and "clang" in cfg.env.COMPILER_CXX)):
322
cfg.fatal("Compiler mismatch; set CC and CXX to matching compilers (eg. CXX=clang++-19 CC=clang-19")
323
324
if 'clang' in cfg.env.COMPILER_CC:
325
env.CFLAGS += [
326
'-fcolor-diagnostics',
327
'-Wno-gnu-designator',
328
'-Wno-inconsistent-missing-override',
329
'-Wno-mismatched-tags',
330
'-Wno-gnu-variable-sized-type-not-at-end',
331
'-Werror=implicit-fallthrough',
332
'-cl-single-precision-constant',
333
'-Wno-vla-extension',
334
'-ftrapping-math', # prevent re-ordering of sanity checks
335
]
336
else:
337
env.CFLAGS += [
338
'-Wno-format-contains-nul',
339
'-fsingle-precision-constant', # force const vals to be float , not double. so 100.0 means 100.0f
340
]
341
342
if cfg.env.DEBUG:
343
env.CFLAGS += [
344
'-g',
345
'-O0',
346
]
347
env.DEFINES.update(
348
HAL_DEBUG_BUILD = 1,
349
)
350
elif cfg.options.debug_symbols:
351
env.CFLAGS += [
352
'-g',
353
]
354
if cfg.env.COVERAGE:
355
env.CFLAGS += [
356
'-fprofile-arcs',
357
'-ftest-coverage',
358
]
359
env.CXXFLAGS += [
360
'-fprofile-arcs',
361
'-ftest-coverage',
362
]
363
env.LINKFLAGS += [
364
'-lgcov',
365
'-coverage',
366
]
367
env.DEFINES.update(
368
HAL_COVERAGE_BUILD = 1,
369
)
370
371
if cfg.options.bootloader:
372
# don't let bootloaders try and pull scripting in
373
cfg.options.disable_scripting = True
374
375
if cfg.options.enable_math_check_indexes:
376
env.CXXFLAGS += ['-DMATH_CHECK_INDEXES']
377
378
if cfg.options.private_key:
379
env.PRIVATE_KEY = cfg.options.private_key
380
381
env.CXXFLAGS += [
382
'-std=gnu++11',
383
384
'-fdata-sections',
385
'-ffunction-sections',
386
'-fno-exceptions',
387
'-fsigned-char',
388
389
'-Wall',
390
'-Wextra',
391
'-Wpointer-arith',
392
'-Wno-unused-parameter',
393
'-Wno-missing-field-initializers',
394
'-Wno-redundant-decls',
395
'-Wno-unknown-pragmas',
396
'-Wno-expansion-to-defined',
397
'-Wno-invalid-offsetof',
398
'-Werror=reorder',
399
'-Werror=cast-align',
400
'-Werror=attributes',
401
'-Werror=format-security',
402
'-Werror=format-extra-args',
403
'-Werror=enum-compare',
404
'-Werror=format',
405
'-Werror=array-bounds',
406
'-Werror=uninitialized',
407
'-Werror=init-self',
408
'-Werror=narrowing',
409
'-Werror=return-type',
410
'-Werror=switch',
411
'-Werror=sign-compare',
412
'-Werror=type-limits',
413
'-Werror=undef',
414
'-Werror=unused-result',
415
'-Werror=shadow',
416
'-Werror=unused-value',
417
'-Werror=unused-variable',
418
'-Werror=delete-non-virtual-dtor',
419
'-Wfatal-errors',
420
'-Wno-trigraphs',
421
'-Werror=parentheses',
422
'-DARDUPILOT_BUILD',
423
'-Wuninitialized',
424
'-Warray-bounds',
425
]
426
427
use_prefix_map = False
428
if 'clang++' in cfg.env.COMPILER_CXX:
429
env.CXXFLAGS += [
430
'-fcolor-diagnostics',
431
432
'-Werror=address-of-packed-member',
433
434
'-Werror=inconsistent-missing-override',
435
'-Werror=overloaded-virtual',
436
437
# catch conversion issues:
438
'-Werror=bitfield-enum-conversion',
439
'-Werror=bool-conversion',
440
'-Werror=constant-conversion',
441
'-Werror=enum-conversion',
442
'-Werror=int-conversion',
443
'-Werror=literal-conversion',
444
'-Werror=non-literal-null-conversion',
445
'-Werror=null-conversion',
446
'-Werror=objc-literal-conversion',
447
# '-Werror=shorten-64-to-32', # ARRAY_SIZE() creates this all over the place as the caller typically takes a uint32_t not a size_t
448
'-Werror=string-conversion',
449
# '-Werror=sign-conversion', # can't use as we assign into AP_Int8 from uint8_ts
450
451
'-Wno-gnu-designator',
452
'-Wno-mismatched-tags',
453
'-Wno-vla-extension',
454
'-Wno-gnu-variable-sized-type-not-at-end',
455
'-Werror=implicit-fallthrough',
456
'-cl-single-precision-constant',
457
'-ftrapping-math', # prevent re-ordering of sanity checks
458
]
459
if self.cc_version_gte(cfg, 10, 0):
460
use_prefix_map = True
461
else:
462
env.CXXFLAGS += [
463
'-Wno-format-contains-nul',
464
'-Werror=unused-but-set-variable',
465
'-fsingle-precision-constant',
466
'-Wno-psabi',
467
]
468
if self.cc_version_gte(cfg, 5, 2):
469
env.CXXFLAGS += [
470
'-Werror=suggest-override',
471
]
472
if self.cc_version_gte(cfg, 7, 4):
473
env.CXXFLAGS += [
474
'-Werror=implicit-fallthrough',
475
'-Werror=maybe-uninitialized',
476
'-Werror=duplicated-cond',
477
]
478
if self.cc_version_gte(cfg, 8, 0):
479
use_prefix_map = True
480
if self.cc_version_gte(cfg, 8, 4):
481
env.CXXFLAGS += [
482
'-Werror=sizeof-pointer-div',
483
]
484
if self.cc_version_gte(cfg, 13, 2):
485
env.CXXFLAGS += [
486
'-Werror=use-after-free',
487
]
488
env.CFLAGS += [
489
'-Werror=use-after-free',
490
]
491
492
if cfg.env.TOOLCHAIN == "custom":
493
# the QURT board stuff should be extracting the compiler
494
# version properly. In the meantime, here's a really
495
# awesome thing:
496
use_prefix_map = False
497
498
if use_prefix_map:
499
# fixes to make __FILE__ and debug paths repeatable in .elf/.bin
500
501
# build root including variant (e.g. by default build/sitl)
502
bldnode = cfg.bldnode.make_node(cfg.variant)
503
# compute source root path from the perspective of the exact build
504
# root above. this path is (as far as we can tell) what waf
505
# prefixes source files with when passing them to the compiler
506
file_prefix = str(cfg.srcnode.path_from(bldnode))
507
508
# now tell the compiler to remap that prefix to `../..` (the prefix
509
# by default) so any stored source paths are independent of
510
# wherever the build dir is and the debugger can find the source
511
cfg.env.CFLAGS += [f"-ffile-prefix-map={file_prefix}=../.."]
512
cfg.env.CXXFLAGS += [f"-ffile-prefix-map={file_prefix}=../.."]
513
514
if cfg.options.Werror:
515
errors = ['-Werror',
516
'-Werror=missing-declarations',
517
'-Werror=float-equal',
518
'-Werror=undef',
519
]
520
env.CFLAGS += errors
521
env.CXXFLAGS += errors
522
523
if cfg.env.DEBUG:
524
env.CXXFLAGS += [
525
'-g',
526
'-O0',
527
]
528
529
if cfg.env.DEST_OS == 'darwin':
530
if self.cc_version_gte(cfg, 15, 0):
531
env.LINKFLAGS += [
532
'-Wl,-dead_strip,-ld_classic',
533
]
534
else:
535
env.LINKFLAGS += [
536
'-Wl,-dead_strip',
537
]
538
else:
539
env.LINKFLAGS += [
540
'-fno-exceptions',
541
'-Wl,--gc-sections',
542
]
543
544
if self.with_can:
545
# for both AP_Perip and main fw enable deadlines
546
env.DEFINES.update(CANARD_ENABLE_DEADLINE = 1)
547
548
if not cfg.env.AP_PERIPH:
549
env.AP_LIBRARIES += [
550
'AP_DroneCAN',
551
'modules/DroneCAN/libcanard/*.c',
552
]
553
if cfg.options.enable_dronecan_tests:
554
env.DEFINES.update(AP_TEST_DRONECAN_DRIVERS = 1)
555
556
env.DEFINES.update(
557
DRONECAN_CXX_WRAPPERS = 1,
558
USE_USER_HELPERS = 1,
559
CANARD_ALLOCATE_SEM=1
560
)
561
562
563
564
if cfg.options.build_dates:
565
env.build_dates = True
566
567
# We always want to use PRI format macros
568
cfg.define('__STDC_FORMAT_MACROS', 1)
569
570
if cfg.options.postype_single:
571
env.CXXFLAGS += ['-DHAL_WITH_POSTYPE_DOUBLE=0']
572
573
if cfg.options.osd or cfg.options.osd_fonts:
574
env.CXXFLAGS += ['-DOSD_ENABLED=1', '-DHAL_MSP_ENABLED=1']
575
576
if cfg.options.osd_fonts:
577
for f in os.listdir('libraries/AP_OSD/fonts'):
578
if fnmatch.fnmatch(f, "font*bin"):
579
env.ROMFS_FILES += [(f,'libraries/AP_OSD/fonts/'+f)]
580
581
if cfg.options.ekf_double:
582
env.CXXFLAGS += ['-DHAL_WITH_EKF_DOUBLE=1']
583
584
if cfg.options.ekf_single:
585
env.CXXFLAGS += ['-DHAL_WITH_EKF_DOUBLE=0']
586
587
if cfg.env.CONSISTENT_BUILDS:
588
# if symbols are renamed we don't want them to affect the output:
589
env.CXXFLAGS += ['-fno-rtti']
590
# avoid different filenames for the same source file
591
# affecting the compiler output:
592
env.CXXFLAGS += ['-frandom-seed=4'] # ob. xkcd
593
594
# disable setting build ID in the ELF header. though if two binaries
595
# are identical they will have the same build ID, setting it avoids
596
# creating a difference if they are not in a way we care about.
597
env.LDFLAGS += ['-Wl,--build-id=none']
598
# squash all line numbers to be the number 17
599
env.CXXFLAGS += [
600
"-D__AP_LINE__=17",
601
]
602
else:
603
env.CXXFLAGS += [
604
"-D__AP_LINE__=__LINE__",
605
]
606
607
# add files from ROMFS_custom
608
custom_dir = 'ROMFS_custom'
609
if os.path.exists(custom_dir):
610
for root, subdirs, files in os.walk(custom_dir):
611
for f in files:
612
if fnmatch.fnmatch(f,"*~"):
613
# exclude emacs tmp files
614
continue
615
fname = root[len(custom_dir)+1:]+"/"+f
616
if fname.startswith("/"):
617
fname = fname[1:]
618
env.ROMFS_FILES += [(fname,root+"/"+f)]
619
620
def pre_build(self, bld):
621
'''pre-build hook that gets called before dynamic sources'''
622
if bld.env.ROMFS_FILES:
623
self.embed_ROMFS_files(bld)
624
625
def build(self, bld):
626
git_hash_ext = bld.git_head_hash(short=True, hash_abbrev=16)
627
bld.ap_version_append_str('GIT_VERSION', bld.git_head_hash(short=True), "abcdef")
628
bld.ap_version_append_str('GIT_VERSION_EXTENDED', git_hash_ext, "0123456789abcdef")
629
bld.ap_version_append_int('GIT_VERSION_INT', int("0x" + bld.git_head_hash(short=True), base=16), 15)
630
# this build root is mostly used as a temporary directory by SIM_JSBSim and probably needs to go
631
bld.ap_version_append_str('AP_BUILD_ROOT', bld.srcnode.abspath(), "/tmp")
632
633
if bld.env.build_dates:
634
if bld.options.consistent_builds:
635
raise ValueError("can't enable consistent builds and build dates")
636
637
import time
638
ltime = time.localtime()
639
bld.ap_version_append_int('BUILD_DATE_YEAR', ltime.tm_year)
640
bld.ap_version_append_int('BUILD_DATE_MONTH', ltime.tm_mon)
641
bld.ap_version_append_int('BUILD_DATE_DAY', ltime.tm_mday)
642
643
def embed_ROMFS_files(self, ctx):
644
'''embed some files using AP_ROMFS'''
645
import embed
646
header = ctx.bldnode.make_node('ap_romfs_embedded.h').abspath()
647
if not embed.create_embedded_h(header, ctx.env.ROMFS_FILES, ctx.env.ROMFS_UNCOMPRESSED):
648
ctx.fatal("Failed to created ap_romfs_embedded.h")
649
650
ctx.env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_H']
651
652
# Allow lua to load from ROMFS if any lua files are added
653
for file in ctx.env.ROMFS_FILES:
654
if file[0].startswith("scripts") and file[0].endswith(".lua"):
655
ctx.env.CXXFLAGS += ['-DHAL_HAVE_AP_ROMFS_EMBEDDED_LUA']
656
break
657
658
Board = BoardMeta('Board', Board.__bases__, dict(Board.__dict__))
659
660
def add_dynamic_boards_chibios():
661
'''add boards based on existence of hwdef.dat in subdirectories for ChibiOS'''
662
add_dynamic_boards_from_hwdef_dir(chibios, 'libraries/AP_HAL_ChibiOS/hwdef')
663
664
def add_dynamic_boards_linux():
665
'''add boards based on existence of hwdef.dat in subdirectories for '''
666
add_dynamic_boards_from_hwdef_dir(LinuxBoard, 'libraries/AP_HAL_Linux/hwdef')
667
668
def add_dynamic_boards_sitl():
669
'''add boards based on existence of hwdef.dat in subdirectories for '''
670
add_dynamic_boards_from_hwdef_dir(SITLBoard, 'libraries/AP_HAL_SITL/hwdef')
671
672
def add_dynamic_boards_from_hwdef_dir(base_type, hwdef_dir):
673
'''add boards based on existence of hwdef.dat in subdirectory'''
674
dirname, dirlist, filenames = next(os.walk(hwdef_dir))
675
for d in dirlist:
676
if d in _board_classes.keys():
677
continue
678
hwdef = os.path.join(dirname, d, 'hwdef.dat')
679
hwdef_bl = os.path.join(dirname, d, 'hwdef-bl.dat')
680
if os.path.exists(hwdef) or os.path.exists(hwdef_bl):
681
newclass = type(d, (base_type,), {'name': d})
682
683
def add_dynamic_boards_esp32():
684
'''add boards based on existence of hwdef.dat in subdirectories for ESP32'''
685
dirname, dirlist, filenames = next(os.walk('libraries/AP_HAL_ESP32/hwdef'))
686
for d in dirlist:
687
if d in _board_classes.keys():
688
continue
689
hwdef = os.path.join(dirname, d, 'hwdef.dat')
690
if os.path.exists(hwdef):
691
mcu_esp32s3 = True if (d[0:7] == "esp32s3") else False
692
if mcu_esp32s3:
693
newclass = type(d, (esp32s3,), {'name': d})
694
else:
695
newclass = type(d, (esp32,), {'name': d})
696
697
def get_boards_names():
698
add_dynamic_boards_chibios()
699
add_dynamic_boards_esp32()
700
add_dynamic_boards_linux()
701
add_dynamic_boards_sitl()
702
703
return sorted(list(_board_classes.keys()), key=str.lower)
704
705
def is_board_based(board, cls):
706
return issubclass(_board_classes[board], cls)
707
708
def get_ap_periph_boards():
709
'''Add AP_Periph boards based on existence of periph keyword in hwdef.dat or board name'''
710
list_ap = [s for s in list(_board_classes.keys()) if "periph" in s]
711
dirname, dirlist, filenames = next(os.walk('libraries/AP_HAL_ChibiOS/hwdef'))
712
for d in dirlist:
713
if d in list_ap:
714
continue
715
hwdef = os.path.join(dirname, d, 'hwdef.dat')
716
if os.path.exists(hwdef):
717
ch = chibios_hwdef.ChibiOSHWDef(hwdef=[hwdef], quiet=True)
718
try:
719
if ch.is_periph_fw_unprocessed():
720
list_ap.append(d)
721
except chibios_hwdef.ChibiOSHWDefIncludeNotFoundException as e:
722
print(f"{e.includer} includes {e.hwdef} which does not exist")
723
sys.exit(1)
724
725
list_ap = list(set(list_ap))
726
return list_ap
727
728
def get_removed_boards():
729
'''list of boards which have been removed'''
730
return sorted(['px4-v1', 'px4-v2', 'px4-v3', 'px4-v4', 'px4-v4pro'])
731
732
@conf
733
def get_board(ctx):
734
global _board
735
if not _board:
736
if not ctx.env.BOARD:
737
ctx.fatal('BOARD environment variable must be set before first call to get_board()')
738
if ctx.env.BOARD in get_removed_boards():
739
ctx.fatal('''
740
The board target %s has been removed from ArduPilot with the removal of NuttX support and HAL_PX4.
741
742
Please use a replacement build as follows:
743
744
px4-v2 Use Pixhawk1 build
745
px4-v3 Use Pixhawk1 or CubeBlack builds
746
px4-v4 Use Pixracer build
747
px4-v4pro Use DrotekP3Pro build
748
''' % ctx.env.BOARD)
749
750
boards = _board_classes.keys()
751
if ctx.env.BOARD not in boards:
752
ctx.fatal("Invalid board '%s': choices are %s" % (ctx.env.BOARD, ', '.join(sorted(boards, key=str.lower))))
753
_board = _board_classes[ctx.env.BOARD]()
754
return _board
755
756
# NOTE: Keeping all the board definitions together so we can easily
757
# identify opportunities to simplify common flags. In the future might
758
# be worthy to keep board definitions in files of their own.
759
760
class SITLBoard(Board):
761
abstract = True
762
763
def __init__(self):
764
super().__init__()
765
766
self.with_can = True
767
self.with_littlefs = True
768
769
def configure(self, cfg):
770
if hasattr(self, 'hwdef'):
771
cfg.env.HWDEF = self.hwdef
772
773
# load hwdef, extract toolchain from cfg.env:
774
cfg.load('sitl')
775
if cfg.env.TOOLCHAIN:
776
self.toolchain = cfg.env.TOOLCHAIN
777
else:
778
# default tool-chain for SITL-based boards:
779
self.toolchain = 'native'
780
781
super().configure(cfg)
782
783
def configure_env(self, cfg, env):
784
super().configure_env(cfg, env)
785
env.DEFINES.update(
786
CONFIG_HAL_BOARD = 'HAL_BOARD_SITL',
787
CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_NONE',
788
AP_SCRIPTING_CHECKS = 1, # SITL should always do runtime scripting checks
789
AP_BARO_PROBE_EXTERNAL_I2C_BUSES = 1,
790
)
791
792
env.BOARD_CLASS = "SITL"
793
794
cfg.define('AP_SIM_ENABLED', 1)
795
cfg.define('HAL_WITH_SPI', 1)
796
cfg.define('HAL_WITH_RAMTRON', 1)
797
cfg.define('AP_OPENDRONEID_ENABLED', 1)
798
cfg.define('AP_SIGNED_FIRMWARE', 0)
799
800
cfg.define('AP_NOTIFY_LP5562_BUS', 2)
801
cfg.define('AP_NOTIFY_LP5562_ADDR', 0x30)
802
803
# turn on fencepoint and rallypoint protocols so they're still tested:
804
env.CXXFLAGS.extend([
805
'-DAP_MAVLINK_RALLY_POINT_PROTOCOL_ENABLED=HAL_GCS_ENABLED&&HAL_RALLY_ENABLED',
806
'-DAC_POLYFENCE_FENCE_POINT_PROTOCOL_SUPPORT=HAL_GCS_ENABLED&&AP_FENCE_ENABLED'
807
])
808
809
if not cfg.env.AP_PERIPH:
810
try:
811
env.CXXFLAGS.remove('-DHAL_NAVEKF2_AVAILABLE=0')
812
except ValueError:
813
pass
814
env.CXXFLAGS += ['-DHAL_NAVEKF2_AVAILABLE=1']
815
816
if self.with_can:
817
cfg.define('HAL_NUM_CAN_IFACES', 2)
818
env.DEFINES.update(CANARD_MULTI_IFACE=1,
819
CANARD_IFACE_ALL = 0x3,
820
CANARD_ENABLE_CANFD = 1,
821
CANARD_ENABLE_ASSERTS = 1)
822
if not cfg.options.force_32bit:
823
# needed for cygwin
824
env.CXXFLAGS += [ '-DCANARD_64_BIT=1' ]
825
env.CFLAGS += [ '-DCANARD_64_BIT=1' ]
826
if Utils.unversioned_sys_platform().startswith("linux"):
827
cfg.define('HAL_CAN_WITH_SOCKETCAN', 1)
828
else:
829
cfg.define('HAL_CAN_WITH_SOCKETCAN', 0)
830
831
env.CXXFLAGS += [
832
'-Werror=float-equal',
833
'-Werror=missing-declarations',
834
]
835
836
if not cfg.options.disable_networking and not 'clang' in cfg.env.COMPILER_CC:
837
# lwip doesn't build with clang
838
env.CXXFLAGS += ['-DAP_NETWORKING_ENABLED=1']
839
840
if cfg.options.ubsan or cfg.options.ubsan_abort:
841
env.CXXFLAGS += [
842
"-fsanitize=undefined",
843
"-fsanitize=float-cast-overflow",
844
"-DUBSAN_ENABLED",
845
]
846
env.LINKFLAGS += [
847
"-fsanitize=undefined",
848
"-lubsan",
849
]
850
851
if cfg.options.ubsan_abort:
852
env.CXXFLAGS += [
853
"-fno-sanitize-recover"
854
]
855
856
if not cfg.env.DEBUG:
857
env.CXXFLAGS += [
858
'-O3',
859
]
860
861
if 'clang++' in cfg.env.COMPILER_CXX and cfg.options.asan:
862
env.CXXFLAGS += [
863
'-fsanitize=address',
864
'-fno-omit-frame-pointer',
865
]
866
867
env.LIB += [
868
'm',
869
]
870
871
cfg.check_librt(env)
872
cfg.check_feenableexcept()
873
874
env.LINKFLAGS += ['-pthread',]
875
876
if cfg.env.DEBUG and 'clang++' in cfg.env.COMPILER_CXX and cfg.options.asan:
877
env.LINKFLAGS += ['-fsanitize=address']
878
879
env.AP_LIBRARIES += [
880
'AP_HAL_SITL',
881
'AP_CSVReader',
882
]
883
884
env.AP_LIBRARIES += [
885
'SITL',
886
]
887
888
# wrap malloc to ensure memory is zeroed
889
if cfg.env.DEST_OS == 'cygwin':
890
pass # handled at runtime in libraries/AP_Common/c++.cpp
891
elif platform.system() != 'Darwin':
892
env.LINKFLAGS += ['-Wl,--wrap,malloc']
893
894
if cfg.options.enable_sfml:
895
if not cfg.check_SFML(env):
896
cfg.fatal("Failed to find SFML libraries")
897
898
if cfg.options.enable_sfml_joystick:
899
if not cfg.check_SFML(env):
900
cfg.fatal("Failed to find SFML libraries")
901
env.CXXFLAGS += ['-DSFML_JOYSTICK']
902
903
if cfg.options.sitl_osd:
904
env.CXXFLAGS += ['-DWITH_SITL_OSD','-DOSD_ENABLED=1']
905
for f in os.listdir('libraries/AP_OSD/fonts'):
906
if fnmatch.fnmatch(f, "font*bin"):
907
env.ROMFS_FILES += [(f,'libraries/AP_OSD/fonts/'+f)]
908
909
for f in os.listdir('Tools/autotest/models'):
910
if fnmatch.fnmatch(f, "*.json") or fnmatch.fnmatch(f, "*.parm"):
911
env.ROMFS_FILES += [('models/'+f,'Tools/autotest/models/'+f)]
912
913
# include locations.txt so SITL on windows can lookup by name
914
env.ROMFS_FILES += [('locations.txt','Tools/autotest/locations.txt')]
915
916
if cfg.options.sitl_rgbled:
917
env.CXXFLAGS += ['-DWITH_SITL_RGBLED']
918
919
if cfg.options.enable_sfml_audio:
920
if not cfg.check_SFML_Audio(env):
921
cfg.fatal("Failed to find SFML Audio libraries")
922
env.CXXFLAGS += ['-DWITH_SITL_TONEALARM']
923
924
if cfg.options.sitl_littlefs:
925
env.CXXFLAGS += ['-DHAL_OS_LITTLEFS_IO=1']
926
927
if cfg.env.DEST_OS == 'cygwin':
928
env.LIB += [
929
'winmm',
930
]
931
932
if Utils.unversioned_sys_platform() == 'cygwin':
933
env.CXXFLAGS += ['-DCYGWIN_BUILD']
934
935
if 'clang++' in cfg.env.COMPILER_CXX:
936
print("Disabling SLP for clang++")
937
env.CXXFLAGS += [
938
'-fno-slp-vectorize' # compiler bug when trying to use SLP
939
]
940
941
if cfg.options.force_32bit:
942
# 32bit platform flags
943
env.CXXFLAGS += [
944
'-m32',
945
]
946
env.CFLAGS += [
947
'-m32',
948
]
949
env.LDFLAGS += [
950
'-m32',
951
]
952
953
# whitelist of compilers which we should build with -Werror
954
gcc_whitelist = frozenset([
955
('11','3','0'),
956
('11','4','0'),
957
('12','1','0'),
958
])
959
960
# initialise werr_enabled from defaults:
961
werr_enabled = bool('g++' in cfg.env.COMPILER_CXX and cfg.env.CC_VERSION in gcc_whitelist)
962
963
# now process overrides to that default:
964
if (cfg.options.Werror is not None and
965
cfg.options.Werror == cfg.options.disable_Werror):
966
cfg.fatal("Asked to both enable and disable Werror")
967
968
if cfg.options.Werror is not None:
969
werr_enabled = cfg.options.Werror
970
elif cfg.options.disable_Werror is not None:
971
werr_enabled = not cfg.options.disable_Werror
972
973
if werr_enabled:
974
cfg.msg("Enabling -Werror", "yes")
975
if '-Werror' not in env.CXXFLAGS:
976
env.CXXFLAGS += [ '-Werror' ]
977
else:
978
cfg.msg("Enabling -Werror", "no")
979
if '-Werror' in env.CXXFLAGS:
980
env.CXXFLAGS.remove('-Werror')
981
982
def get_name(self):
983
return self.__class__.__name__
984
985
def pre_build(self, bld):
986
'''pre-build hook that gets called before dynamic sources'''
987
from waflib.Context import load_tool
988
module = load_tool('sitl', [], with_sys_path=True)
989
fun = getattr(module, 'pre_build', None)
990
if fun:
991
fun(bld)
992
super().pre_build(bld)
993
994
class esp32(Board):
995
abstract = True
996
toolchain = 'xtensa-esp32-elf'
997
998
def configure(self, cfg):
999
super(esp32, self).configure(cfg)
1000
if cfg.env.TOOLCHAIN:
1001
self.toolchain = cfg.env.TOOLCHAIN
1002
else:
1003
# default tool-chain for esp32-based boards:
1004
self.toolchain = 'xtensa-esp32-elf'
1005
1006
def configure_env(self, cfg, env):
1007
env.BOARD_CLASS = "ESP32"
1008
1009
def expand_path(p):
1010
print("USING EXPRESSIF IDF:"+str(env.idf))
1011
return cfg.root.find_dir(env.IDF+p).abspath()
1012
try:
1013
env.IDF = os.environ['IDF_PATH']
1014
except:
1015
env.IDF = cfg.srcnode.abspath()+"/modules/esp_idf"
1016
1017
super(esp32, self).configure_env(cfg, env)
1018
cfg.load('esp32')
1019
env.DEFINES.update(
1020
CONFIG_HAL_BOARD = 'HAL_BOARD_ESP32',
1021
)
1022
1023
tt = self.name[5:] #leave off 'esp32' so we just get 'buzz','diy','icarus, etc
1024
1025
# this makes sure we get the correct subtype
1026
env.DEFINES.update(
1027
CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_NONE',
1028
)
1029
1030
if self.name.endswith("empty"):
1031
# for empty targets build as SIM-on-HW
1032
env.DEFINES.update(AP_SIM_ENABLED = 1)
1033
env.AP_LIBRARIES += [
1034
'SITL',
1035
]
1036
else:
1037
env.DEFINES.update(AP_SIM_ENABLED = 0)
1038
1039
# FreeRTOS component from esp-idf expects this define
1040
env.DEFINES.update(ESP_PLATFORM = 1)
1041
1042
env.AP_LIBRARIES += [
1043
'AP_HAL_ESP32',
1044
]
1045
1046
env.CFLAGS += [
1047
'-fno-inline-functions',
1048
'-mlongcalls',
1049
'-fsingle-precision-constant',
1050
]
1051
env.CFLAGS.remove('-Werror=undef')
1052
1053
env.CXXFLAGS += ['-mlongcalls',
1054
'-Os',
1055
'-g',
1056
'-ffunction-sections',
1057
'-fdata-sections',
1058
'-fno-exceptions',
1059
'-fno-rtti',
1060
'-nostdlib',
1061
'-fstrict-volatile-bitfields',
1062
'-Wno-sign-compare',
1063
'-fno-inline-functions',
1064
'-mlongcalls',
1065
'-fsingle-precision-constant', # force const vals to be float , not double. so 100.0 means 100.0f
1066
'-fno-threadsafe-statics']
1067
env.CXXFLAGS.remove('-Werror=undef')
1068
env.CXXFLAGS.remove('-Werror=shadow')
1069
1070
# wrap malloc to ensure memory is zeroed
1071
# note that this also needs to be done in the CMakeLists.txt files
1072
env.LINKFLAGS += ['-Wl,--wrap,malloc']
1073
1074
# TODO: remove once hwdef.dat support is in place
1075
defaults_file = 'libraries/AP_HAL_ESP32/hwdef/%s/defaults.parm' % self.get_name()
1076
if os.path.exists(defaults_file):
1077
env.ROMFS_FILES += [('defaults.parm', defaults_file)]
1078
env.DEFINES.update(
1079
HAL_PARAM_DEFAULTS_PATH='"@ROMFS/defaults.parm"',
1080
)
1081
1082
env.AP_PROGRAM_AS_STLIB = True
1083
#if cfg.options.enable_profile:
1084
# env.CXXFLAGS += ['-pg',
1085
# '-DENABLE_PROFILE=1']
1086
def pre_build(self, bld):
1087
'''pre-build hook that gets called before dynamic sources'''
1088
from waflib.Context import load_tool
1089
module = load_tool('esp32', [], with_sys_path=True)
1090
fun = getattr(module, 'pre_build', None)
1091
if fun:
1092
fun(bld)
1093
super(esp32, self).pre_build(bld)
1094
1095
1096
def build(self, bld):
1097
super(esp32, self).build(bld)
1098
bld.load('esp32')
1099
1100
def get_name(self):
1101
return self.__class__.__name__
1102
1103
class esp32s3(esp32):
1104
abstract = True
1105
toolchain = 'xtensa-esp32s3-elf'
1106
1107
def configure_env(self, cfg, env):
1108
if cfg.env.TOOLCHAIN:
1109
self.toolchain = cfg.env.TOOLCHAIN
1110
else:
1111
# default tool-chain for esp32-based boards:
1112
self.toolchain = 'xtensa-esp32s3-elf'
1113
1114
if hasattr(self, 'hwdef'):
1115
cfg.env.HWDEF = self.hwdef
1116
super(esp32s3, self).configure_env(cfg, env)
1117
1118
class chibios(Board):
1119
abstract = True
1120
toolchain = 'arm-none-eabi'
1121
1122
def configure_env(self, cfg, env):
1123
if hasattr(self, 'hwdef'):
1124
cfg.env.HWDEF = self.hwdef
1125
super(chibios, self).configure_env(cfg, env)
1126
1127
cfg.load('chibios')
1128
env.BOARD = self.name
1129
env.BOARD_CLASS = "ChibiOS"
1130
1131
env.DEFINES.update(
1132
CONFIG_HAL_BOARD = 'HAL_BOARD_CHIBIOS',
1133
HAVE_STD_NULLPTR_T = 0,
1134
)
1135
1136
env.AP_LIBRARIES += [
1137
'AP_HAL_ChibiOS',
1138
]
1139
1140
# make board name available for USB IDs
1141
env.CHIBIOS_BOARD_NAME = 'HAL_BOARD_NAME="%s"' % self.name
1142
env.HAL_MAX_STACK_FRAME_SIZE = 'HAL_MAX_STACK_FRAME_SIZE=%d' % 1300 # set per Wframe-larger-than, ensure its same
1143
env.CFLAGS += cfg.env.CPU_FLAGS + [
1144
'-Wlogical-op',
1145
'-Wframe-larger-than=1300',
1146
'-Wno-attributes',
1147
'-fno-exceptions',
1148
'-Wall',
1149
'-Wextra',
1150
'-Wno-sign-compare',
1151
'-Wfloat-equal',
1152
'-Wpointer-arith',
1153
'-Wmissing-declarations',
1154
'-Wno-unused-parameter',
1155
'-Werror=array-bounds',
1156
'-Wfatal-errors',
1157
'-Werror=uninitialized',
1158
'-Werror=init-self',
1159
'-Werror=unused-but-set-variable',
1160
'-Wno-missing-field-initializers',
1161
'-Wno-trigraphs',
1162
'-fno-strict-aliasing',
1163
'-fomit-frame-pointer',
1164
'-falign-functions=16',
1165
'-ffunction-sections',
1166
'-fdata-sections',
1167
'-fno-strength-reduce',
1168
'-fno-builtin-printf',
1169
'-fno-builtin-fprintf',
1170
'-fno-builtin-vprintf',
1171
'-fno-builtin-vfprintf',
1172
'-fno-builtin-puts',
1173
'-fno-math-errno',
1174
'-mno-thumb-interwork',
1175
'-mthumb',
1176
'--specs=nano.specs',
1177
'--specs=nosys.specs',
1178
'-D__USE_CMSIS',
1179
'-Werror=deprecated-declarations',
1180
'-DNDEBUG=1'
1181
]
1182
if not cfg.options.Werror:
1183
env.CFLAGS += [
1184
'-Wno-error=double-promotion',
1185
'-Wno-error=missing-declarations',
1186
'-Wno-error=float-equal',
1187
'-Wno-error=cpp',
1188
]
1189
1190
env.CXXFLAGS += env.CFLAGS + [
1191
'-fno-rtti',
1192
'-fno-threadsafe-statics',
1193
]
1194
env.CFLAGS += [
1195
'-std=c11'
1196
]
1197
1198
if Utils.unversioned_sys_platform() == 'cygwin':
1199
env.CXXFLAGS += ['-DCYGWIN_BUILD']
1200
1201
bldnode = cfg.bldnode.make_node(self.name)
1202
env.BUILDROOT = bldnode.make_node('').abspath()
1203
1204
env.LINKFLAGS = cfg.env.CPU_FLAGS + [
1205
'-fomit-frame-pointer',
1206
'-falign-functions=16',
1207
'-ffunction-sections',
1208
'-fdata-sections',
1209
'-u_port_lock',
1210
'-u_port_unlock',
1211
'-u_exit',
1212
'-u_kill',
1213
'-u_getpid',
1214
'-u_errno',
1215
'-uchThdExit',
1216
'-fno-common',
1217
'-nostartfiles',
1218
'-mno-thumb-interwork',
1219
'-mthumb',
1220
'--specs=nano.specs',
1221
'--specs=nosys.specs',
1222
'-L%s' % env.BUILDROOT,
1223
'-L%s' % cfg.srcnode.make_node('modules/ChibiOS/os/common/startup/ARMCMx/compilers/GCC/ld/').abspath(),
1224
'-L%s' % cfg.srcnode.make_node('libraries/AP_HAL_ChibiOS/hwdef/common/').abspath(),
1225
'-Wl,-Map,Linker.map,%s--cref,--gc-sections,--no-warn-mismatch,--library-path=/ld,--script=ldscript.ld,--defsym=__process_stack_size__=%s,--defsym=__main_stack_size__=%s' % ("--print-memory-usage," if cfg.env.EXT_FLASH_SIZE_MB > 0 and cfg.env.INT_FLASH_PRIMARY == 0 else "", cfg.env.PROCESS_STACK, cfg.env.MAIN_STACK)
1226
]
1227
1228
if cfg.env.DEBUG:
1229
env.CFLAGS += [
1230
'-gdwarf-4',
1231
'-g3',
1232
]
1233
env.LINKFLAGS += [
1234
'-gdwarf-4',
1235
'-g3',
1236
]
1237
1238
if cfg.env.COMPILER_CXX == "g++":
1239
if not self.cc_version_gte(cfg, 10, 2):
1240
# require at least 10.2 compiler
1241
cfg.fatal("ChibiOS build requires g++ version 10.2.1 or later, found %s" % '.'.join(cfg.env.CC_VERSION))
1242
1243
if cfg.env.ENABLE_ASSERTS:
1244
cfg.msg("Enabling ChibiOS asserts", "yes")
1245
env.CFLAGS += [ '-DHAL_CHIBIOS_ENABLE_ASSERTS' ]
1246
env.CXXFLAGS += [ '-DHAL_CHIBIOS_ENABLE_ASSERTS' ]
1247
else:
1248
cfg.msg("Enabling ChibiOS asserts", "no")
1249
1250
1251
if cfg.env.SAVE_TEMPS:
1252
env.CXXFLAGS += [ '-S', '-save-temps=obj' ]
1253
1254
if cfg.options.disable_watchdog:
1255
cfg.msg("Disabling Watchdog", "yes")
1256
env.CFLAGS += [ '-DDISABLE_WATCHDOG' ]
1257
env.CXXFLAGS += [ '-DDISABLE_WATCHDOG' ]
1258
else:
1259
cfg.msg("Disabling Watchdog", "no")
1260
1261
if cfg.env.ENABLE_MALLOC_GUARD:
1262
cfg.msg("Enabling malloc guard", "yes")
1263
env.CFLAGS += [ '-DHAL_CHIBIOS_ENABLE_MALLOC_GUARD' ]
1264
env.CXXFLAGS += [ '-DHAL_CHIBIOS_ENABLE_MALLOC_GUARD' ]
1265
else:
1266
cfg.msg("Enabling malloc guard", "no")
1267
1268
if cfg.env.ENABLE_STATS:
1269
cfg.msg("Enabling ChibiOS thread statistics", "yes")
1270
env.CFLAGS += [ '-DHAL_ENABLE_THREAD_STATISTICS' ]
1271
env.CXXFLAGS += [ '-DHAL_ENABLE_THREAD_STATISTICS' ]
1272
else:
1273
cfg.msg("Enabling ChibiOS thread statistics", "no")
1274
1275
if cfg.env.SIM_ENABLED:
1276
env.DEFINES.update(
1277
AP_SIM_ENABLED = 1,
1278
)
1279
env.AP_LIBRARIES += [
1280
'SITL',
1281
]
1282
else:
1283
env.DEFINES.update(
1284
AP_SIM_ENABLED = 0,
1285
)
1286
1287
env.LIB += ['gcc', 'm']
1288
1289
env.GIT_SUBMODULES += [
1290
'ChibiOS',
1291
]
1292
1293
env.INCLUDES += [
1294
cfg.srcnode.find_dir('libraries/AP_GyroFFT/CMSIS_5/include').abspath(),
1295
cfg.srcnode.find_dir('modules/lwip/src/include/compat/posix').abspath()
1296
]
1297
1298
# whitelist of compilers which we should build with -Werror
1299
gcc_whitelist = frozenset([
1300
('4','9','3'),
1301
('6','3','1'),
1302
('9','2','1'),
1303
('9','3','1'),
1304
('10','2','1'),
1305
('11','3','0'),
1306
('11','4','0'),
1307
])
1308
1309
if cfg.env.HAL_CANFD_SUPPORTED:
1310
env.DEFINES.update(CANARD_ENABLE_CANFD=1)
1311
else:
1312
env.DEFINES.update(CANARD_ENABLE_TAO_OPTION=1)
1313
if not cfg.options.bootloader and cfg.env.HAL_NUM_CAN_IFACES:
1314
if int(cfg.env.HAL_NUM_CAN_IFACES) >= 1:
1315
env.DEFINES.update(CANARD_IFACE_ALL=(1<<int(cfg.env.HAL_NUM_CAN_IFACES))-1)
1316
if cfg.options.Werror or cfg.env.CC_VERSION in gcc_whitelist:
1317
cfg.msg("Enabling -Werror", "yes")
1318
if '-Werror' not in env.CXXFLAGS:
1319
env.CXXFLAGS += [ '-Werror' ]
1320
else:
1321
cfg.msg("Enabling -Werror", "no")
1322
1323
if cfg.options.signed_fw:
1324
cfg.define('AP_SIGNED_FIRMWARE', 1)
1325
env.CFLAGS += [
1326
'-DAP_SIGNED_FIRMWARE=1',
1327
]
1328
else:
1329
cfg.define('AP_SIGNED_FIRMWARE', 0)
1330
env.CFLAGS += [
1331
'-DAP_SIGNED_FIRMWARE=0',
1332
]
1333
1334
try:
1335
import intelhex
1336
env.HAVE_INTEL_HEX = True
1337
cfg.msg("Checking for intelhex module:", 'OK')
1338
except Exception:
1339
cfg.msg("Checking for intelhex module:", 'disabled', color='YELLOW')
1340
env.HAVE_INTEL_HEX = False
1341
1342
if cfg.options.enable_new_checking:
1343
env.CHECK_SYMBOLS = True
1344
else:
1345
# disable new checking on ChibiOS by default to save flash
1346
# we enable it in a CI test to catch incorrect usage
1347
env.CXXFLAGS += [
1348
"-DNEW_NOTHROW=new",
1349
"-fcheck-new", # rely on -fcheck-new ensuring nullptr checks
1350
]
1351
1352
def build(self, bld):
1353
super(chibios, self).build(bld)
1354
bld.ap_version_append_str('CHIBIOS_GIT_VERSION', bld.git_submodule_head_hash('ChibiOS', short=True), "12345678")
1355
bld.load('chibios')
1356
1357
def pre_build(self, bld):
1358
'''pre-build hook that gets called before dynamic sources'''
1359
from waflib.Context import load_tool
1360
module = load_tool('chibios', [], with_sys_path=True)
1361
fun = getattr(module, 'pre_build', None)
1362
if fun:
1363
fun(bld)
1364
super(chibios, self).pre_build(bld)
1365
1366
def get_name(self):
1367
return self.name
1368
1369
class LinuxBoard(Board):
1370
'''an abstract base class for Linux boards to inherit from'''
1371
abstract = True
1372
1373
def __init__(self):
1374
super().__init__()
1375
1376
self.with_can = True
1377
1378
def configure(self, cfg):
1379
if hasattr(self, 'hwdef'):
1380
cfg.env.HWDEF = self.hwdef
1381
1382
# load hwdef, extract toolchain from cfg.env:
1383
cfg.load('linux')
1384
if cfg.env.TOOLCHAIN:
1385
self.toolchain = cfg.env.TOOLCHAIN
1386
else:
1387
# default tool-chain for Linux-based boards:
1388
self.toolchain = 'arm-linux-gnueabihf'
1389
1390
# we should be able to do better here:
1391
if cfg.env.WITH_CAN:
1392
self.with_can = True
1393
1394
super().configure(cfg)
1395
1396
def configure_env(self, cfg, env):
1397
super().configure_env(cfg, env)
1398
1399
env.BOARD_CLASS = "LINUX"
1400
1401
env.DEFINES.update(
1402
CONFIG_HAL_BOARD = 'HAL_BOARD_LINUX',
1403
AP_SIM_ENABLED = 0,
1404
)
1405
1406
if not cfg.env.DEBUG:
1407
env.CXXFLAGS += [
1408
'-O3',
1409
]
1410
1411
env.LIB += [
1412
'm',
1413
]
1414
1415
cfg.check_librt(env)
1416
cfg.check_lttng(env)
1417
cfg.check_libdl(env)
1418
cfg.check_libiio(env)
1419
1420
env.LINKFLAGS += ['-pthread',]
1421
env.AP_LIBRARIES += [
1422
'AP_HAL_Linux',
1423
]
1424
1425
# wrap malloc to ensure memory is zeroed
1426
env.LINKFLAGS += ['-Wl,--wrap,malloc']
1427
1428
if cfg.options.force_32bit:
1429
env.DEFINES.update(
1430
HAL_FORCE_32BIT = 1,
1431
)
1432
# 32bit platform flags
1433
cfg.env.CXXFLAGS += [
1434
'-m32',
1435
]
1436
cfg.env.CFLAGS += [
1437
'-m32',
1438
]
1439
cfg.env.LDFLAGS += [
1440
'-m32',
1441
]
1442
else:
1443
env.DEFINES.update(
1444
HAL_FORCE_32BIT = 0,
1445
)
1446
1447
if self.with_can:
1448
env.DEFINES.update(CANARD_MULTI_IFACE=1,
1449
CANARD_IFACE_ALL = 0x3)
1450
1451
if cfg.options.apstatedir:
1452
cfg.define('AP_STATEDIR', cfg.options.apstatedir)
1453
1454
defaults_file = 'libraries/AP_HAL_Linux/boards/%s/defaults.parm' % self.get_name()
1455
if os.path.exists(defaults_file):
1456
env.ROMFS_FILES += [('defaults.parm', defaults_file)]
1457
env.DEFINES.update(
1458
HAL_PARAM_DEFAULTS_PATH='"@ROMFS/defaults.parm"',
1459
)
1460
1461
def pre_build(self, bld):
1462
'''pre-build hook that gets called before dynamic sources'''
1463
from waflib.Context import load_tool
1464
module = load_tool('linux', [], with_sys_path=True)
1465
fun = getattr(module, 'pre_build', None)
1466
if fun:
1467
fun(bld)
1468
super().pre_build(bld)
1469
1470
def build(self, bld):
1471
super().build(bld)
1472
bld.load('linux')
1473
if bld.options.upload:
1474
waflib.Options.commands.append('rsync')
1475
# Avoid infinite recursion
1476
bld.options.upload = False
1477
1478
def get_name(self):
1479
# get name of class
1480
return self.__class__.__name__
1481
1482
class QURT(Board):
1483
'''support for QURT based boards'''
1484
toolchain = 'custom'
1485
1486
def __init__(self):
1487
super().__init__()
1488
1489
self.with_can = False
1490
1491
def configure_toolchain(self, cfg):
1492
cfg.env.CXX_NAME = 'gcc'
1493
cfg.env.HEXAGON_SDK_DIR = "/opt/hexagon-sdk/4.1.0.4-lite"
1494
cfg.env.CC_VERSION = ('4','1','0')
1495
cfg.env.TOOLCHAIN_DIR = cfg.env.HEXAGON_SDK_DIR + "/tools/HEXAGON_Tools/8.4.05/Tools"
1496
cfg.env.COMPILER_CC = cfg.env.TOOLCHAIN_DIR + "/bin/hexagon-clang"
1497
cfg.env.COMPILER_CXX = cfg.env.TOOLCHAIN_DIR + "/bin/hexagon-clang++"
1498
cfg.env.LINK_CXX = cfg.env.HEXAGON_SDK_DIR + "/tools/HEXAGON_Tools/8.4.05/Tools/bin/hexagon-link"
1499
cfg.env.CXX = ["ccache", cfg.env.COMPILER_CXX]
1500
cfg.env.CC = ["ccache", cfg.env.COMPILER_CC]
1501
cfg.env.CXX_TGT_F = ['-c', '-o']
1502
cfg.env.CC_TGT_F = ['-c', '-o']
1503
cfg.env.CCLNK_SRC_F = []
1504
cfg.env.CXXLNK_SRC_F = []
1505
cfg.env.CXXLNK_TGT_F = ['-o']
1506
cfg.env.CCLNK_TGT_F = ['-o']
1507
cfg.env.CPPPATH_ST = '-I%s'
1508
cfg.env.DEFINES_ST = '-D%s'
1509
cfg.env.AR = cfg.env.HEXAGON_SDK_DIR + "/tools/HEXAGON_Tools/8.4.05/Tools/bin/hexagon-ar"
1510
cfg.env.ARFLAGS = 'rcs'
1511
cfg.env.cxxstlib_PATTERN = 'lib%s.a'
1512
cfg.env.cstlib_PATTERN = 'lib%s.a'
1513
cfg.env.LIBPATH_ST = '-L%s'
1514
cfg.env.LIB_ST = '-l%s'
1515
cfg.env.SHLIB_MARKER = ''
1516
cfg.env.STLIBPATH_ST = '-L%s'
1517
cfg.env.STLIB_MARKER = ''
1518
cfg.env.STLIB_ST = '-l%s'
1519
cfg.env.LDFLAGS = [
1520
'-lgcc',
1521
cfg.env.TOOLCHAIN_DIR + '/target/hexagon/lib/v66/G0/pic/finiS.o'
1522
]
1523
1524
def configure_env(self, cfg, env):
1525
super(QURT, self).configure_env(cfg, env)
1526
1527
env.BOARD_CLASS = "QURT"
1528
env.HEXAGON_APP = "libardupilot.so"
1529
env.INCLUDES += [cfg.env.HEXAGON_SDK_DIR + "/rtos/qurt/computev66/include/qurt"]
1530
env.INCLUDES += [cfg.env.HEXAGON_SDK_DIR + "/rtos/qurt/computev66/include/posix"]
1531
1532
CFLAGS = "-MD -mv66 -fPIC -mcpu=hexagonv66 -G0 -fdata-sections -ffunction-sections -fomit-frame-pointer -fmerge-all-constants -fno-signed-zeros -fno-trapping-math -freciprocal-math -fno-math-errno -fno-strict-aliasing -fvisibility=hidden -fno-rtti -fmath-errno"
1533
env.CXXFLAGS += CFLAGS.split()
1534
env.CFLAGS += CFLAGS.split()
1535
1536
env.DEFINES.update(
1537
CONFIG_HAL_BOARD = 'HAL_BOARD_QURT',
1538
CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_NONE',
1539
AP_SIM_ENABLED = 0,
1540
)
1541
1542
env.LINKFLAGS = [
1543
"-march=hexagon",
1544
"-mcpu=hexagonv66",
1545
"-shared",
1546
"-call_shared",
1547
"-G0",
1548
cfg.env.TOOLCHAIN_DIR + "/target/hexagon/lib/v66/G0/pic/initS.o",
1549
f"-L{cfg.env.TOOLCHAIN_DIR}/target/hexagon/lib/v66/G0/pic",
1550
"-Bsymbolic",
1551
cfg.env.TOOLCHAIN_DIR + "/target/hexagon/lib/v66/G0/pic/libgcc.a",
1552
"--wrap=malloc",
1553
"--wrap=calloc",
1554
"--wrap=free",
1555
"--wrap=printf",
1556
"--wrap=strdup",
1557
"--wrap=__stack_chk_fail",
1558
"-lc"
1559
]
1560
1561
if not cfg.env.DEBUG:
1562
env.CXXFLAGS += [
1563
'-O3',
1564
]
1565
1566
env.AP_LIBRARIES += [
1567
'AP_HAL_QURT',
1568
]
1569
1570
def build(self, bld):
1571
super(QURT, self).build(bld)
1572
bld.load('qurt')
1573
1574
def get_name(self):
1575
# get name of class
1576
return self.__class__.__name__
1577
1578
1579