@@ -86,6 +86,8 @@ _environment_options = [
8686 'Options to pass to ${CC} when linking sample programs' ),
8787 EnvironmentOption ('PYTHON' , 'python3' ,
8888 'Python3 interpreter' ),
89+ EnvironmentOption ('QEMU_LD_PREFIX' , '' ,
90+ 'Path to a runtime for Qemu' ),
8991 EnvironmentOption ('RM' , 'rm -f' ,
9092 'Program to remove files (e.g. "rm -f")' ),
9193 EnvironmentOption ('RUN' , '' ,
@@ -308,6 +310,9 @@ class MakefileMaker:
308310 self .static_libraries = None
309311 self .help = {}
310312 self .clean = []
313+ self .variables_to_export = set ()
314+ if options .QEMU_LD_PREFIX :
315+ self .variables_to_export .add ('QEMU_LD_PREFIX' )
311316 self .dependency_cache = {
312317 # TODO: arrange to find dependencies of this generated file.
313318 # They're hard-coded for now, but that won't work if the
@@ -478,6 +483,21 @@ class MakefileMaker:
478483 if clean :
479484 self .add_clean (name )
480485
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+
481501 def environment_option_subsection (self ):
482502 """Generate the assignments to customizable options."""
483503 self .comment ('Tool settings' )
@@ -524,6 +544,7 @@ class MakefileMaker:
524544 self .line ('AUX_Q_$(V) = @' )
525545 self .line ('ECHO_IF_QUIET = $(AUX_ECHO_IF_QUIET_)' )
526546 self .line ('Q = $(AUX_Q_)' )
547+ self .assign ('SETENV' , self .setenv_command ())
527548 self .line ('' )
528549 self .comment ('Auxiliary paths' )
529550 self .assign ('SOURCE_DIR_FROM_TESTS' , '../$(SOURCE_DIR)' )
@@ -717,8 +738,8 @@ class MakefileMaker:
717738 [sjoin (script_path , '-o $@' , * sources )])
718739 self .object_target ('LIBRARY' , GeneratedFile (generated ), [])
719740
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 .
722743
723744 Look for the specified wildcard pattern under all submodules, including
724745 the root tree. If a given file name is present in multiple submodules,
@@ -734,8 +755,10 @@ class MakefileMaker:
734755 start = len (submodule_root )
735756 if submodule :
736757 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 )]
739762 for source_name in sources :
740763 src = SourceFile (root , submodule , source_name )
741764 base = src .base ()
@@ -896,11 +919,11 @@ class MakefileMaker:
896919 executable = program + self .executable_extension
897920 self .target (program + '.run' ,
898921 [executable ],
899- ['$(RUN) ' + executable + ' $(RUNS)' ],
922+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ],
900923 phony = True )
901924 self .target (program + '.gmon' ,
902925 [executable ],
903- ['$(RUN) ' + executable + ' $(RUNS)' ,
926+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ,
904927 'mv gmon.out $@' ])
905928
906929 def program_subsection (self , src , executables ):
@@ -994,7 +1017,8 @@ class MakefileMaker:
9941017 definition must come before both targets for programs and tests.
9951018 """
9961019 tests_common_sources = self .list_source_files (self .options .source ,
997- 'tests/src/*.c' )
1020+ 'tests/src/*.c' ,
1021+ 'tests/src/drivers/*.c' )
9981022 tests_common_objects = []
9991023 for src in tests_common_sources :
10001024 self .object_target ('TESTS' , src , [])
@@ -1054,12 +1078,12 @@ class MakefileMaker:
10541078 # so is the .datax file.
10551079 self .target ('tests/' + base + '.run' ,
10561080 [exe_file , 'tests/seedfile' ],
1057- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1081+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
10581082 short = 'RUN tests/' + exe_basename ,
10591083 phony = True )
10601084 self .target ('tests/' + base + '.gmon' ,
10611085 [exe_file , 'tests/seedfile' ],
1062- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1086+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
10631087 'mv tests/gmon.out $@' ],
10641088 short = 'RUN tests/' + exe_basename )
10651089 valgrind_log_basename = 'MemoryChecker.{}.log' .format (base )
@@ -1108,7 +1132,7 @@ class MakefileMaker:
11081132 self .target ('tests/seedfile' , [],
11091133 ['dd bs=64 count=1 </dev/urandom >$@' ])
11101134 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)' ],
11121136 help = 'Run all the test suites.' ,
11131137 short = '' ,
11141138 phony = True )
@@ -1420,7 +1444,7 @@ class BuildTreeMaker:
14201444 """Go ahead and prepate the build tree."""
14211445 for subdir in ([['include' , 'mbedtls' ],
14221446 ['library' ],
1423- ['tests' , 'src' ]] +
1447+ ['tests' , 'src' , 'drivers' ]] +
14241448 [['programs' , d ] for d in self .programs_subdirs ()]):
14251449 self .make_subdir (subdir )
14261450 source_link = os .path .join (self .options .dir , 'source' )
@@ -1547,6 +1571,16 @@ def set_default_option(options, attr, value):
15471571 elif isinstance (value , list ):
15481572 setattr (options , attr , value + getattr (options , attr ))
15491573
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+
15501584def set_default_options (options ):
15511585 """Apply the preset if any and set default for remaining options.
15521586
@@ -1568,7 +1602,9 @@ def set_default_options(options):
15681602 continue
15691603 set_default_option (options , attr , value )
15701604 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.
15721608 for attr , value in _default_options .items ():
15731609 set_default_option (options , attr , value )
15741610 for envopt in _environment_options :
@@ -1618,6 +1654,8 @@ def main():
16181654 parser .add_argument ('--config-unset' ,
16191655 action = 'append' , default = [],
16201656 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.' )
16211659 parser .add_argument ('--default-target' ,
16221660 help = 'Default makefile target (default: all)' )
16231661 parser .add_argument ('--dir' , '-d' ,
0 commit comments