@@ -86,6 +86,8 @@ _environment_options = [
86
86
'Options to pass to ${CC} when linking sample programs' ),
87
87
EnvironmentOption ('PYTHON' , 'python3' ,
88
88
'Python3 interpreter' ),
89
+ EnvironmentOption ('QEMU_LD_PREFIX' , '' ,
90
+ 'Path to a runtime for Qemu' ),
89
91
EnvironmentOption ('RM' , 'rm -f' ,
90
92
'Program to remove files (e.g. "rm -f")' ),
91
93
EnvironmentOption ('RUN' , '' ,
@@ -308,6 +310,9 @@ class MakefileMaker:
308
310
self .static_libraries = None
309
311
self .help = {}
310
312
self .clean = []
313
+ self .variables_to_export = set ()
314
+ if options .QEMU_LD_PREFIX :
315
+ self .variables_to_export .add ('QEMU_LD_PREFIX' )
311
316
self .dependency_cache = {
312
317
# TODO: arrange to find dependencies of this generated file.
313
318
# They're hard-coded for now, but that won't work if the
@@ -478,6 +483,21 @@ class MakefileMaker:
478
483
if clean :
479
484
self .add_clean (name )
480
485
486
+ def setenv_command (self ):
487
+ """Generate a shell command to export some environment variables.
488
+
489
+ The values of these variables must not contain the character ``'``
490
+ (single quote).
491
+
492
+ Return an empty string if there are no variables to export.
493
+ """
494
+ if not self .variables_to_export :
495
+ return ''
496
+ return (' export ' +
497
+ ' ' .join (['{}=\' $({})\' ' .format (name , name )
498
+ for name in sorted (self .variables_to_export )]) +
499
+ '; ' )
500
+
481
501
def environment_option_subsection (self ):
482
502
"""Generate the assignments to customizable options."""
483
503
self .comment ('Tool settings' )
@@ -524,6 +544,7 @@ class MakefileMaker:
524
544
self .line ('AUX_Q_$(V) = @' )
525
545
self .line ('ECHO_IF_QUIET = $(AUX_ECHO_IF_QUIET_)' )
526
546
self .line ('Q = $(AUX_Q_)' )
547
+ self .assign ('SETENV' , self .setenv_command ())
527
548
self .line ('' )
528
549
self .comment ('Auxiliary paths' )
529
550
self .assign ('SOURCE_DIR_FROM_TESTS' , '../$(SOURCE_DIR)' )
@@ -717,8 +738,8 @@ class MakefileMaker:
717
738
[sjoin (script_path , '-o $@' , * sources )])
718
739
self .object_target ('LIBRARY' , GeneratedFile (generated ), [])
719
740
720
- def list_source_files (self , root , pattern ):
721
- """List the source files matching the specified pattern .
741
+ def list_source_files (self , root , * patterns ):
742
+ """List the source files matching any of the specified patterns .
722
743
723
744
Look for the specified wildcard pattern under all submodules, including
724
745
the root tree. If a given file name is present in multiple submodules,
@@ -734,8 +755,10 @@ class MakefileMaker:
734
755
start = len (submodule_root )
735
756
if submodule :
736
757
start += 1
737
- abs_pattern = os .path .join (submodule_root , pattern )
738
- sources = [src [start :] for src in glob .glob (abs_pattern )]
758
+ sources = []
759
+ for pattern in patterns :
760
+ abs_pattern = os .path .join (submodule_root , pattern )
761
+ sources += [src [start :] for src in glob .glob (abs_pattern )]
739
762
for source_name in sources :
740
763
src = SourceFile (root , submodule , source_name )
741
764
base = src .base ()
@@ -896,11 +919,11 @@ class MakefileMaker:
896
919
executable = program + self .executable_extension
897
920
self .target (program + '.run' ,
898
921
[executable ],
899
- ['$(RUN) ' + executable + ' $(RUNS)' ],
922
+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ],
900
923
phony = True )
901
924
self .target (program + '.gmon' ,
902
925
[executable ],
903
- ['$(RUN) ' + executable + ' $(RUNS)' ,
926
+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ,
904
927
'mv gmon.out $@' ])
905
928
906
929
def program_subsection (self , src , executables ):
@@ -994,7 +1017,8 @@ class MakefileMaker:
994
1017
definition must come before both targets for programs and tests.
995
1018
"""
996
1019
tests_common_sources = self .list_source_files (self .options .source ,
997
- 'tests/src/*.c' )
1020
+ 'tests/src/*.c' ,
1021
+ 'tests/src/drivers/*.c' )
998
1022
tests_common_objects = []
999
1023
for src in tests_common_sources :
1000
1024
self .object_target ('TESTS' , src , [])
@@ -1054,12 +1078,12 @@ class MakefileMaker:
1054
1078
# so is the .datax file.
1055
1079
self .target ('tests/' + base + '.run' ,
1056
1080
[exe_file , 'tests/seedfile' ],
1057
- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1081
+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1058
1082
short = 'RUN tests/' + exe_basename ,
1059
1083
phony = True )
1060
1084
self .target ('tests/' + base + '.gmon' ,
1061
1085
[exe_file , 'tests/seedfile' ],
1062
- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1086
+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1063
1087
'mv tests/gmon.out $@' ],
1064
1088
short = 'RUN tests/' + exe_basename )
1065
1089
valgrind_log_basename = 'MemoryChecker.{}.log' .format (base )
@@ -1108,7 +1132,7 @@ class MakefileMaker:
1108
1132
self .target ('tests/seedfile' , [],
1109
1133
['dd bs=64 count=1 </dev/urandom >$@' ])
1110
1134
self .target ('check' , ['$(test_apps)' , 'tests/seedfile' ],
1111
- ['cd tests && $(PERL) scripts/run-test-suites.pl --skip=$(SKIP_TEST_SUITES)' ],
1135
+ ['$(SETENV) cd tests && $(PERL) scripts/run-test-suites.pl --skip=$(SKIP_TEST_SUITES)' ],
1112
1136
help = 'Run all the test suites.' ,
1113
1137
short = '' ,
1114
1138
phony = True )
@@ -1420,7 +1444,7 @@ class BuildTreeMaker:
1420
1444
"""Go ahead and prepate the build tree."""
1421
1445
for subdir in ([['include' , 'mbedtls' ],
1422
1446
['library' ],
1423
- ['tests' , 'src' ]] +
1447
+ ['tests' , 'src' , 'drivers' ]] +
1424
1448
[['programs' , d ] for d in self .programs_subdirs ()]):
1425
1449
self .make_subdir (subdir )
1426
1450
source_link = os .path .join (self .options .dir , 'source' )
@@ -1547,6 +1571,16 @@ def set_default_option(options, attr, value):
1547
1571
elif isinstance (value , list ):
1548
1572
setattr (options , attr , value + getattr (options , attr ))
1549
1573
1574
+ def handle_cross (options ):
1575
+ """Update settings to handle --cross."""
1576
+ if options .cross is None :
1577
+ return
1578
+ # Paths for Ubuntu 18.04 with the packages qemu-user and either
1579
+ # gcc-multilib-<ARCH> or gcc-<ARCH> installed.
1580
+ set_default_option (options , 'QEMU_LD_PREFIX' , '/usr/' + options .cross )
1581
+ set_default_option (options , 'CC' , options .cross + '-gcc' )
1582
+ set_default_option (options , 'dir' , 'build-' + options .cross )
1583
+
1550
1584
def set_default_options (options ):
1551
1585
"""Apply the preset if any and set default for remaining options.
1552
1586
@@ -1568,7 +1602,9 @@ def set_default_options(options):
1568
1602
continue
1569
1603
set_default_option (options , attr , value )
1570
1604
set_default_option (options , 'dir' , 'build-' + options .preset )
1571
- # Step 2: set remaining defaults.
1605
+ # Step 2: handle multi-effect options
1606
+ handle_cross (options )
1607
+ # Step 3: set remaining defaults.
1572
1608
for attr , value in _default_options .items ():
1573
1609
set_default_option (options , attr , value )
1574
1610
for envopt in _environment_options :
@@ -1618,6 +1654,8 @@ def main():
1618
1654
parser .add_argument ('--config-unset' ,
1619
1655
action = 'append' , default = [],
1620
1656
help = 'Symbol to unset in config.h' )
1657
+ parser .add_argument ('--cross' ,
1658
+ help = 'Run tests on a different architecture with Qemu. Forces an out-of-tree build.' )
1621
1659
parser .add_argument ('--default-target' ,
1622
1660
help = 'Default makefile target (default: all)' )
1623
1661
parser .add_argument ('--dir' , '-d' ,
0 commit comments