@@ -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)' )
@@ -898,11 +919,11 @@ class MakefileMaker:
898
919
executable = program + self .executable_extension
899
920
self .target (program + '.run' ,
900
921
[executable ],
901
- ['$(RUN) ' + executable + ' $(RUNS)' ],
922
+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ],
902
923
phony = True )
903
924
self .target (program + '.gmon' ,
904
925
[executable ],
905
- ['$(RUN) ' + executable + ' $(RUNS)' ,
926
+ ['$(SETENV)$( RUN) ' + executable + ' $(RUNS)' ,
906
927
'mv gmon.out $@' ])
907
928
908
929
def program_subsection (self , src , executables ):
@@ -1057,12 +1078,12 @@ class MakefileMaker:
1057
1078
# so is the .datax file.
1058
1079
self .target ('tests/' + base + '.run' ,
1059
1080
[exe_file , 'tests/seedfile' ],
1060
- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1081
+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ],
1061
1082
short = 'RUN tests/' + exe_basename ,
1062
1083
phony = True )
1063
1084
self .target ('tests/' + base + '.gmon' ,
1064
1085
[exe_file , 'tests/seedfile' ],
1065
- ['cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1086
+ ['$(SETENV) cd tests && $(RUN) ./' + exe_basename + ' $(RUNS)' ,
1066
1087
'mv tests/gmon.out $@' ],
1067
1088
short = 'RUN tests/' + exe_basename )
1068
1089
valgrind_log_basename = 'MemoryChecker.{}.log' .format (base )
@@ -1111,7 +1132,7 @@ class MakefileMaker:
1111
1132
self .target ('tests/seedfile' , [],
1112
1133
['dd bs=64 count=1 </dev/urandom >$@' ])
1113
1134
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)' ],
1115
1136
help = 'Run all the test suites.' ,
1116
1137
short = '' ,
1117
1138
phony = True )
@@ -1550,6 +1571,16 @@ def set_default_option(options, attr, value):
1550
1571
elif isinstance (value , list ):
1551
1572
setattr (options , attr , value + getattr (options , attr ))
1552
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
+
1553
1584
def set_default_options (options ):
1554
1585
"""Apply the preset if any and set default for remaining options.
1555
1586
@@ -1571,7 +1602,9 @@ def set_default_options(options):
1571
1602
continue
1572
1603
set_default_option (options , attr , value )
1573
1604
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.
1575
1608
for attr , value in _default_options .items ():
1576
1609
set_default_option (options , attr , value )
1577
1610
for envopt in _environment_options :
@@ -1621,6 +1654,8 @@ def main():
1621
1654
parser .add_argument ('--config-unset' ,
1622
1655
action = 'append' , default = [],
1623
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.' )
1624
1659
parser .add_argument ('--default-target' ,
1625
1660
help = 'Default makefile target (default: all)' )
1626
1661
parser .add_argument ('--dir' , '-d' ,
0 commit comments