@@ -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)' )
@@ -898,11 +919,11 @@ class MakefileMaker:
898919 executable = program + self .executable_extension
899920 self .target (program + '.run' ,
900921 [executable ],
901- ['$(RUN) ' + executable + ' $(RUNS)' ],
922+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ],
902923 phony = True )
903924 self .target (program + '.gmon' ,
904925 [executable ],
905- ['$(RUN) ' + executable + ' $(RUNS)' ,
926+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ,
906927 'mv gmon.out $@' ])
907928
908929 def program_subsection (self , src , executables ):
@@ -1057,12 +1078,12 @@ class MakefileMaker:
10571078 # so is the .datax file.
10581079 self .target ('tests/' + base + '.run' ,
10591080 [exe_file , 'tests/seedfile' ],
1060- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1081+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
10611082 short = 'RUN tests/' + exe_basename ,
10621083 phony = True )
10631084 self .target ('tests/' + base + '.gmon' ,
10641085 [exe_file , 'tests/seedfile' ],
1065- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1086+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
10661087 'mv tests/gmon.out $@' ],
10671088 short = 'RUN tests/' + exe_basename )
10681089 valgrind_log_basename = 'MemoryChecker.{}.log' .format (base )
@@ -1111,7 +1132,7 @@ class MakefileMaker:
11111132 self .target ('tests/seedfile' , [],
11121133 ['dd bs=64 count=1 </dev/urandom >$@' ])
11131134 self .target ('check' , ['$(test_apps)' , 'tests/seedfile' ],
1114- ['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)' ],
11151136 help = 'Run all the test suites.' ,
11161137 short = '' ,
11171138 phony = True )
@@ -1550,6 +1571,16 @@ def set_default_option(options, attr, value):
15501571 elif isinstance (value , list ):
15511572 setattr (options , attr , value + getattr (options , attr ))
15521573
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+
15531584def set_default_options (options ):
15541585 """Apply the preset if any and set default for remaining options.
15551586
@@ -1571,7 +1602,9 @@ def set_default_options(options):
15711602 continue
15721603 set_default_option (options , attr , value )
15731604 set_default_option (options , 'dir' , 'build-' + options .preset )
1574- # Step 2: set remaining defaults.
1605+ # Step 2: handle multi-effect options
1606+ handle_cross (options )
1607+ # Step 3: set remaining defaults.
15751608 for attr , value in _default_options .items ():
15761609 set_default_option (options , attr , value )
15771610 for envopt in _environment_options :
@@ -1621,6 +1654,8 @@ def main():
16211654 parser .add_argument ('--config-unset' ,
16221655 action = 'append' , default = [],
16231656 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.' )
16241659 parser .add_argument ('--default-target' ,
16251660 help = 'Default makefile target (default: all)' )
16261661 parser .add_argument ('--dir' , '-d' ,
0 commit comments