@@ -70,10 +70,8 @@ _environment_options = [
70
70
'Options to always pass to ${CC} when compiling or linking' ),
71
71
EnvironmentOption ('DLLFLAGS' , '-shared' ,
72
72
'Options to pass to ${CC} when building a shared library' ),
73
- # TODO: allow linking extra libraries. This requires passing -l options
74
- # _after_ the objects to link. But LDFLAGS and xxx_EXTRA_LDFLAGS are
75
- # currently passed before. Should they be moved after? Or should there be
76
- # different variables?
73
+ EnvironmentOption ('EXTRA_LIBS' , '' ,
74
+ 'Extra libraries to link programs (including tests) with' ),
77
75
EnvironmentOption ('LDFLAGS' , '' ,
78
76
'Options to always pass to ${CC} when linking' ),
79
77
EnvironmentOption ('LIBRARY_EXTRA_CFLAGS' , '' ,
@@ -465,7 +463,7 @@ class MakefileMaker:
465
463
for com in commands :
466
464
self .format ('\t {}{}' ,
467
465
('' if short is None else '$(Q)' ),
468
- com .replace ('\n ' , ' \\ \n \t ' ))
466
+ com .strip ( ' \n ' ). replace ('\n ' , ' \\ \n \t ' ))
469
467
if help is not None :
470
468
self .help [name ] = help
471
469
if phony :
@@ -779,7 +777,7 @@ class MakefileMaker:
779
777
"""
780
778
self .comment ('Library targets' )
781
779
self .assign ('LIBRARY_CFLAGS' ,
782
- '-I include/mbedtls' , # must come first, for " config.h"
780
+ '-I include/mbedtls' , # must come first, for the config header
783
781
'-I include' ,
784
782
self .include_path_options ('library/*' ),
785
783
'$(LIBRARY_EXTRA_CFLAGS)' )
@@ -972,6 +970,7 @@ class MakefileMaker:
972
970
'$(LDFLAGS)' ,
973
971
'$(PROGRAMS_LDFLAGS)' ,
974
972
sjoin (* (dash_l_libs + self .extra_link_flags (base ))),
973
+ '$(EXTRA_LIBS)' ,
975
974
'-o $@' )],
976
975
clean = False ,
977
976
short = 'LD $@' )
@@ -1026,17 +1025,24 @@ class MakefileMaker:
1026
1025
tests_common_objects .append (object_file )
1027
1026
self .assign ('test_common_objects' , * tests_common_objects )
1028
1027
1029
- def test_subsection (self , src , executables ):
1028
+ def test_subsection (self , src , executables , groups ):
1030
1029
"""Emit the makefile rules to build one test suite.
1031
1030
1032
1031
src is a SourceFile object for a .data file.
1033
1032
1034
1033
This function appens the path to the test executable to the list
1035
- executables.)"""
1034
+ executables.
1035
+
1036
+ If the .data file is part of a group (*.*.data where the part before the
1037
+ first '.' identifies a group), add it to the groups dictionary. The
1038
+ keys in this dictionary are group names (base names of .function files)
1039
+ and the values are lists of dependencies.
1040
+ """
1036
1041
base = os .path .basename (src .base ())
1037
1042
source_dir = src .source_dir ()
1038
1043
try :
1039
1044
function_base = base [:base .index ('.' )]
1045
+ groups .setdefault (function_base , [])
1040
1046
except ValueError :
1041
1047
function_base = base
1042
1048
data_file = src .relative_path ()
@@ -1045,6 +1051,8 @@ class MakefileMaker:
1045
1051
c_file = os .path .join ('tests' , base + '.c' )
1046
1052
exe_basename = base + self .executable_extension
1047
1053
exe_file = os .path .join ('tests' , exe_basename )
1054
+ if function_base in groups :
1055
+ groups [function_base ].append (exe_file )
1048
1056
generate_command = self .test_generator .command (function_file , data_file )
1049
1057
self .target (self .test_generator .target (c_file ),
1050
1058
['$(SOURCE_DIR)/' + base
@@ -1098,6 +1106,28 @@ class MakefileMaker:
1098
1106
short = 'VALGRIND tests/' + exe_basename ,
1099
1107
phony = True )
1100
1108
1109
+ def test_group_targets (self , groups ):
1110
+ """Emit run targets for test groups.
1111
+
1112
+ A test group is a group of test executables that share the same
1113
+ .function file. The groups parameter is a dictionary mapping group
1114
+ names to the list of executables that they contain.
1115
+ """
1116
+ use_run_test_suites = False
1117
+ for base , executables in groups .items ():
1118
+ shell_code = '''
1119
+ failures=;
1120
+ for x in {}; do
1121
+ ./$$x || failures="$$failures $$x";
1122
+ done;
1123
+ if [ -n "$$failures" ]; then echo; echo "Failures:$$failures"; false; fi
1124
+ ''' .format (' ' .join ([re .sub (r'.*/' , r'' , exe ) for exe in executables ]))
1125
+ self .target ('tests/' + base + '.run' ,
1126
+ groups [base ] + ['tests/seedfile' ],
1127
+ ['$(SETENV)cd tests && ' + shell_code ],
1128
+ short = '' ,
1129
+ phony = True )
1130
+
1101
1131
def tests_section (self ):
1102
1132
"""Emit makefile rules to build and run test suites."""
1103
1133
self .comment ('Test targets' )
@@ -1111,7 +1141,8 @@ class MakefileMaker:
1111
1141
'$(TESTS_EXTRA_LDFLAGS)' )
1112
1142
self .assign ('TESTS_EXTRA_OBJECTS' )
1113
1143
self .assign ('test_libs' ,
1114
- * [self .dash_l_lib (lib ) for lib in reversed (self .static_libraries )])
1144
+ * [self .dash_l_lib (lib ) for lib in reversed (self .static_libraries )],
1145
+ '$(EXTRA_LIBS)' )
1115
1146
self .assign ('test_build_deps' ,
1116
1147
'$(test_common_objects)' , * self .static_libraries )
1117
1148
self .add_clean (* ['tests' + sub + '/*' + ext
@@ -1122,9 +1153,11 @@ class MakefileMaker:
1122
1153
data_files = self .list_source_files (self .options .source ,
1123
1154
'tests/suites/*.data' )
1124
1155
executables = []
1156
+ groups = {}
1125
1157
for src in data_files :
1126
- self .test_subsection (src , executables )
1158
+ self .test_subsection (src , executables , groups )
1127
1159
self .assign ('test_apps' , * executables )
1160
+ self .test_group_targets (groups )
1128
1161
self .target ('tests' , ['$(test_apps)' ],
1129
1162
[],
1130
1163
help = 'Build the host tests.' ,
@@ -1147,7 +1180,7 @@ class MakefileMaker:
1147
1180
[],
1148
1181
help = 'Run all the test suites with Valgrind.' ,
1149
1182
phony = True )
1150
- self .help ['tests/test_suite_%.run' ] = 'Run one test suite.'
1183
+ self .help ['tests/test_suite_%.run' ] = 'Run one test suite (or a group) .'
1151
1184
self .help ['tests/test_suite_%.valgrind' ] = 'Run one test suite with valgrind.'
1152
1185
self .add_clean ('$(test_apps)' )
1153
1186
# TODO: test_psa_constant_names.py
@@ -1224,25 +1257,31 @@ class MakefileMaker:
1224
1257
os .replace (temp_file , destination )
1225
1258
1226
1259
class ConfigMaker :
1227
- """Parent class for config.h builders.
1260
+ """Parent class for config.h or mbedtls_config.h builders.
1228
1261
1229
1262
Typical usage: ChildClass(options).run()
1230
1263
"""
1231
1264
1232
1265
def __init__ (self , options ):
1233
- """Initialize a config.h builder with the given command line options."""
1266
+ """Initialize a config header builder with the given command line options."""
1234
1267
self .options = options
1235
1268
self .source_file = options .config_file
1269
+ include_dir = os .path .join (options .source , 'include' , 'mbedtls' )
1270
+ if os .path .exists (os .path .join (include_dir , 'build_info.h' )):
1271
+ self .version = 3
1272
+ basename = 'mbedtls_config.h'
1273
+ else :
1274
+ self .version = 2
1275
+ basename = 'config.h'
1236
1276
if self .source_file is None :
1237
- self .source_file = os .path .join (options .source ,
1238
- 'include' , 'mbedtls' , 'config.h' )
1239
- self .source_file_path = 'include/mbedtls/config.h'
1277
+ self .source_file = os .path .join (include_dir , basename )
1278
+ self .source_file_path = 'include/mbedtls/' + basename
1240
1279
if not options .in_tree_build :
1241
1280
self .source_file_path = 'source/' + self .source_file_path
1242
1281
else :
1243
1282
self .source_file_path = os .path .abspath (self .source_file )
1244
1283
self .target_file = os .path .join (options .dir ,
1245
- 'include' , 'mbedtls' , 'config.h' )
1284
+ 'include' , 'mbedtls' , basename )
1246
1285
1247
1286
def start (self ):
1248
1287
"""Builder-specific method which is called first."""
@@ -1268,7 +1307,7 @@ class ConfigMaker:
1268
1307
raise NotImplementedError
1269
1308
1270
1309
def run (self ):
1271
- """Go ahead and generate config.h ."""
1310
+ """Go ahead and generate the config header ."""
1272
1311
self .start ()
1273
1312
if self .options .config_name is not None :
1274
1313
self .batch (self .options .config_name )
@@ -1293,16 +1332,20 @@ class ConfigMaker:
1293
1332
_config_classes = {}
1294
1333
1295
1334
class ConfigCopy (ConfigMaker ):
1296
- """ConfigMaker implementation that copies config.h and runs config.pl ."""
1335
+ """ConfigMaker implementation that copies the config header and runs the config script ."""
1297
1336
1298
1337
def start (self ):
1299
1338
if not are_same_existing_files (self .source_file , self .target_file ):
1300
1339
shutil .copyfile (self .source_file , self .target_file )
1301
1340
1302
1341
def run_config_script (self , * args ):
1303
- cmd = ['perl' , 'scripts/config.pl' ,
1304
- '-f' , os .path .abspath (self .target_file )] + list (args )
1305
- subprocess .check_call (cmd , cwd = self .options .dir )
1342
+ if os .path .exists (os .path .join (self .options .source ,
1343
+ 'scripts' , 'config.py' )):
1344
+ cmd = [sys .executable , 'scripts/config.py' ]
1345
+ else :
1346
+ cmd = ['perl' , 'scripts/config.pl' ]
1347
+ cmd += ['-f' , os .path .abspath (self .target_file )] + list (args )
1348
+ subprocess .check_call (cmd , cwd = self .options .source )
1306
1349
1307
1350
def set (self , name , value = None ):
1308
1351
if value is None :
@@ -1321,7 +1364,7 @@ class ConfigCopy(ConfigMaker):
1321
1364
_config_classes ['copy' ] = ConfigCopy
1322
1365
1323
1366
class ConfigInclude (ConfigMaker ):
1324
- """ConfigMaker implementation that makes a config.h that #includes the base one."""
1367
+ """ConfigMaker implementation that makes a config script that #includes the base one."""
1325
1368
1326
1369
def __init__ (self , * args ):
1327
1370
super ().__init__ (* args )
@@ -1345,12 +1388,13 @@ class ConfigInclude(ConfigMaker):
1345
1388
self .lines .append ('#undef ' + name )
1346
1389
1347
1390
def finish (self ):
1348
- self .lines .append ('' )
1349
- self .lines .append ('#undef MBEDTLS_CHECK_CONFIG_H' )
1350
- # Avoid a redefinition of this typedef
1351
- self .lines .append ('#define mbedtls_iso_c_forbids_empty_translation_units mbedtls_iso_c_forbids_empty_translation_units2' )
1352
- self .lines .append ('#include "mbedtls/check_config.h"' )
1353
- self .lines .append ('#undef mbedtls_iso_c_forbids_empty_translation_units' )
1391
+ if self .version < 3 :
1392
+ self .lines .append ('' )
1393
+ self .lines .append ('#undef MBEDTLS_CHECK_CONFIG_H' )
1394
+ # Avoid a redefinition of this typedef
1395
+ self .lines .append ('#define mbedtls_iso_c_forbids_empty_translation_units mbedtls_iso_c_forbids_empty_translation_units2' )
1396
+ self .lines .append ('#include "mbedtls/check_config.h"' )
1397
+ self .lines .append ('#undef mbedtls_iso_c_forbids_empty_translation_units' )
1354
1398
self .lines .append ('#endif' )
1355
1399
with open (self .target_file , 'w' ) as out :
1356
1400
for line in self .lines :
@@ -1362,7 +1406,7 @@ class BuildTreeMaker:
1362
1406
1363
1407
* Create a directory structure.
1364
1408
* Create symbolic links to some files and directories from the source.
1365
- * Create a config.h.
1409
+ * Create a config.h or mbedtls_config.h .
1366
1410
* Create a Makefile.
1367
1411
1368
1412
Typical usage: BuildTreeMaker(options).run()
@@ -1440,6 +1484,29 @@ class BuildTreeMaker:
1440
1484
# in a submodule.
1441
1485
self .make_link ('source/tests/suites' , 'suites' )
1442
1486
1487
+ def prepare_source (self ):
1488
+ """Generate extra source files in the source tree.
1489
+
1490
+ This is necessary in the Mbed TLS development branch since before 3.0:
1491
+ some source files are not checked into version control. Ideally this
1492
+ script would know how to generate them in the target directory, but
1493
+ this is not implemented yet. As an easier-to-implement stopgap measure,
1494
+ generate the files in the source tree.
1495
+
1496
+ This implementation relies on the official Makefile, so it won't work
1497
+ when re-running mbedtls-prepare-build for an in-tree build.
1498
+ """
1499
+ if not os .path .exists (os .path .join (self .source_path ,
1500
+ 'library' , 'error.c' )):
1501
+ for name in ('gnumake' , 'gmake' , 'make' ):
1502
+ make_command = shutil .which (name )
1503
+ if make_command is not None :
1504
+ break
1505
+ else :
1506
+ raise Exception ('No "make" command found to run "make generated_files"' )
1507
+ subprocess .check_call ([make_command , 'generated_files' ],
1508
+ cwd = self .source_path )
1509
+
1443
1510
def run (self ):
1444
1511
"""Go ahead and prepate the build tree."""
1445
1512
for subdir in ([['include' , 'mbedtls' ],
@@ -1459,6 +1526,7 @@ class BuildTreeMaker:
1459
1526
['tests' , 'ssl-opt.sh' ]]:
1460
1527
self .link_to_source_maybe (link )
1461
1528
self .link_test_suites ()
1529
+ self .prepare_source ()
1462
1530
self .makefile .generate ()
1463
1531
self .config .run ()
1464
1532
@@ -1526,6 +1594,13 @@ _preset_options = {
1526
1594
CFLAGS = '-Os' ,
1527
1595
COMMON_FLAGS = '-mthumb -mcpu=cortex-m0plus' ,
1528
1596
),
1597
+ 'mingw' : argparse .Namespace (
1598
+ _help = 'MinGW-w64' ,
1599
+ AR = 'x86_64-w64-mingw32-ar' ,
1600
+ CC = 'x86_64-w64-mingw32-gcc' ,
1601
+ EXTRA_LIBS = '-lws2_32' ,
1602
+ CFLAGS = '-O1' ,
1603
+ ),
1529
1604
'msan' : argparse .Namespace (
1530
1605
_help = 'Clang Memory sanitizer (MSan), current configuration' ,
1531
1606
config_unset = ['MBEDTLS_AESNI_C' ,
@@ -1642,18 +1717,18 @@ def main():
1642
1717
parser .add_argument ('--assembly-extension' ,
1643
1718
help = 'File extension for assembly files' )
1644
1719
parser .add_argument ('--config-file' ,
1645
- help = 'Base config.h to use' )
1720
+ help = 'Base config header (config.h or mbedtls_config.h) to use' )
1646
1721
parser .add_argument ('--config-mode' ,
1647
1722
choices = _config_classes .keys (),
1648
- help = 'What to do with config.h ' )
1723
+ help = 'What to do with the config header ' )
1649
1724
parser .add_argument ('--config-name' ,
1650
- help = 'Configuration to set with scripts/config.pl ' )
1725
+ help = 'Configuration to set with scripts/config.{pl,py} ' )
1651
1726
parser .add_argument ('--config-set' ,
1652
1727
action = 'append' , default = [],
1653
- help = 'Additional symbol to set in config.h ' )
1728
+ help = 'Additional symbol to set in the config header ' )
1654
1729
parser .add_argument ('--config-unset' ,
1655
1730
action = 'append' , default = [],
1656
- help = 'Symbol to unset in config.h ' )
1731
+ help = 'Symbol to unset in the config header ' )
1657
1732
parser .add_argument ('--cross' ,
1658
1733
help = 'Run tests on a different architecture with Qemu. Forces an out-of-tree build.' )
1659
1734
parser .add_argument ('--default-target' ,
0 commit comments