@@ -70,10 +70,8 @@ _environment_options = [
7070 'Options to always pass to ${CC} when compiling or linking' ),
7171 EnvironmentOption ('DLLFLAGS' , '-shared' ,
7272 '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' ),
7775 EnvironmentOption ('LDFLAGS' , '' ,
7876 'Options to always pass to ${CC} when linking' ),
7977 EnvironmentOption ('LIBRARY_EXTRA_CFLAGS' , '' ,
@@ -465,7 +463,7 @@ class MakefileMaker:
465463 for com in commands :
466464 self .format ('\t {}{}' ,
467465 ('' if short is None else '$(Q)' ),
468- com .replace ('\n ' , ' \\ \n \t ' ))
466+ com .strip ( ' \n ' ). replace ('\n ' , ' \\ \n \t ' ))
469467 if help is not None :
470468 self .help [name ] = help
471469 if phony :
@@ -779,7 +777,7 @@ class MakefileMaker:
779777 """
780778 self .comment ('Library targets' )
781779 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
783781 '-I include' ,
784782 self .include_path_options ('library/*' ),
785783 '$(LIBRARY_EXTRA_CFLAGS)' )
@@ -972,6 +970,7 @@ class MakefileMaker:
972970 '$(LDFLAGS)' ,
973971 '$(PROGRAMS_LDFLAGS)' ,
974972 sjoin (* (dash_l_libs + self .extra_link_flags (base ))),
973+ '$(EXTRA_LIBS)' ,
975974 '-o $@' )],
976975 clean = False ,
977976 short = 'LD $@' )
@@ -1026,17 +1025,24 @@ class MakefileMaker:
10261025 tests_common_objects .append (object_file )
10271026 self .assign ('test_common_objects' , * tests_common_objects )
10281027
1029- def test_subsection (self , src , executables ):
1028+ def test_subsection (self , src , executables , groups ):
10301029 """Emit the makefile rules to build one test suite.
10311030
10321031 src is a SourceFile object for a .data file.
10331032
10341033 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+ """
10361041 base = os .path .basename (src .base ())
10371042 source_dir = src .source_dir ()
10381043 try :
10391044 function_base = base [:base .index ('.' )]
1045+ groups .setdefault (function_base , [])
10401046 except ValueError :
10411047 function_base = base
10421048 data_file = src .relative_path ()
@@ -1045,6 +1051,8 @@ class MakefileMaker:
10451051 c_file = os .path .join ('tests' , base + '.c' )
10461052 exe_basename = base + self .executable_extension
10471053 exe_file = os .path .join ('tests' , exe_basename )
1054+ if function_base in groups :
1055+ groups [function_base ].append (exe_file )
10481056 generate_command = self .test_generator .command (function_file , data_file )
10491057 self .target (self .test_generator .target (c_file ),
10501058 ['$(SOURCE_DIR)/' + base
@@ -1098,6 +1106,28 @@ class MakefileMaker:
10981106 short = 'VALGRIND tests/' + exe_basename ,
10991107 phony = True )
11001108
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+
11011131 def tests_section (self ):
11021132 """Emit makefile rules to build and run test suites."""
11031133 self .comment ('Test targets' )
@@ -1111,7 +1141,8 @@ class MakefileMaker:
11111141 '$(TESTS_EXTRA_LDFLAGS)' )
11121142 self .assign ('TESTS_EXTRA_OBJECTS' )
11131143 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)' )
11151146 self .assign ('test_build_deps' ,
11161147 '$(test_common_objects)' , * self .static_libraries )
11171148 self .add_clean (* ['tests' + sub + '/*' + ext
@@ -1122,9 +1153,11 @@ class MakefileMaker:
11221153 data_files = self .list_source_files (self .options .source ,
11231154 'tests/suites/*.data' )
11241155 executables = []
1156+ groups = {}
11251157 for src in data_files :
1126- self .test_subsection (src , executables )
1158+ self .test_subsection (src , executables , groups )
11271159 self .assign ('test_apps' , * executables )
1160+ self .test_group_targets (groups )
11281161 self .target ('tests' , ['$(test_apps)' ],
11291162 [],
11301163 help = 'Build the host tests.' ,
@@ -1147,7 +1180,7 @@ class MakefileMaker:
11471180 [],
11481181 help = 'Run all the test suites with Valgrind.' ,
11491182 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) .'
11511184 self .help ['tests/test_suite_%.valgrind' ] = 'Run one test suite with valgrind.'
11521185 self .add_clean ('$(test_apps)' )
11531186 # TODO: test_psa_constant_names.py
@@ -1224,25 +1257,31 @@ class MakefileMaker:
12241257 os .replace (temp_file , destination )
12251258
12261259class ConfigMaker :
1227- """Parent class for config.h builders.
1260+ """Parent class for config.h or mbedtls_config.h builders.
12281261
12291262 Typical usage: ChildClass(options).run()
12301263 """
12311264
12321265 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."""
12341267 self .options = options
12351268 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'
12361276 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
12401279 if not options .in_tree_build :
12411280 self .source_file_path = 'source/' + self .source_file_path
12421281 else :
12431282 self .source_file_path = os .path .abspath (self .source_file )
12441283 self .target_file = os .path .join (options .dir ,
1245- 'include' , 'mbedtls' , 'config.h' )
1284+ 'include' , 'mbedtls' , basename )
12461285
12471286 def start (self ):
12481287 """Builder-specific method which is called first."""
@@ -1268,7 +1307,7 @@ class ConfigMaker:
12681307 raise NotImplementedError
12691308
12701309 def run (self ):
1271- """Go ahead and generate config.h ."""
1310+ """Go ahead and generate the config header ."""
12721311 self .start ()
12731312 if self .options .config_name is not None :
12741313 self .batch (self .options .config_name )
@@ -1293,16 +1332,20 @@ class ConfigMaker:
12931332_config_classes = {}
12941333
12951334class 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 ."""
12971336
12981337 def start (self ):
12991338 if not are_same_existing_files (self .source_file , self .target_file ):
13001339 shutil .copyfile (self .source_file , self .target_file )
13011340
13021341 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 )
13061349
13071350 def set (self , name , value = None ):
13081351 if value is None :
@@ -1321,7 +1364,7 @@ class ConfigCopy(ConfigMaker):
13211364_config_classes ['copy' ] = ConfigCopy
13221365
13231366class 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."""
13251368
13261369 def __init__ (self , * args ):
13271370 super ().__init__ (* args )
@@ -1345,12 +1388,13 @@ class ConfigInclude(ConfigMaker):
13451388 self .lines .append ('#undef ' + name )
13461389
13471390 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' )
13541398 self .lines .append ('#endif' )
13551399 with open (self .target_file , 'w' ) as out :
13561400 for line in self .lines :
@@ -1362,7 +1406,7 @@ class BuildTreeMaker:
13621406
13631407 * Create a directory structure.
13641408 * 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 .
13661410 * Create a Makefile.
13671411
13681412 Typical usage: BuildTreeMaker(options).run()
@@ -1440,6 +1484,29 @@ class BuildTreeMaker:
14401484 # in a submodule.
14411485 self .make_link ('source/tests/suites' , 'suites' )
14421486
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+
14431510 def run (self ):
14441511 """Go ahead and prepate the build tree."""
14451512 for subdir in ([['include' , 'mbedtls' ],
@@ -1459,6 +1526,7 @@ class BuildTreeMaker:
14591526 ['tests' , 'ssl-opt.sh' ]]:
14601527 self .link_to_source_maybe (link )
14611528 self .link_test_suites ()
1529+ self .prepare_source ()
14621530 self .makefile .generate ()
14631531 self .config .run ()
14641532
@@ -1526,6 +1594,13 @@ _preset_options = {
15261594 CFLAGS = '-Os' ,
15271595 COMMON_FLAGS = '-mthumb -mcpu=cortex-m0plus' ,
15281596 ),
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+ ),
15291604 'msan' : argparse .Namespace (
15301605 _help = 'Clang Memory sanitizer (MSan), current configuration' ,
15311606 config_unset = ['MBEDTLS_AESNI_C' ,
@@ -1642,18 +1717,18 @@ def main():
16421717 parser .add_argument ('--assembly-extension' ,
16431718 help = 'File extension for assembly files' )
16441719 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' )
16461721 parser .add_argument ('--config-mode' ,
16471722 choices = _config_classes .keys (),
1648- help = 'What to do with config.h ' )
1723+ help = 'What to do with the config header ' )
16491724 parser .add_argument ('--config-name' ,
1650- help = 'Configuration to set with scripts/config.pl ' )
1725+ help = 'Configuration to set with scripts/config.{pl,py} ' )
16511726 parser .add_argument ('--config-set' ,
16521727 action = 'append' , default = [],
1653- help = 'Additional symbol to set in config.h ' )
1728+ help = 'Additional symbol to set in the config header ' )
16541729 parser .add_argument ('--config-unset' ,
16551730 action = 'append' , default = [],
1656- help = 'Symbol to unset in config.h ' )
1731+ help = 'Symbol to unset in the config header ' )
16571732 parser .add_argument ('--cross' ,
16581733 help = 'Run tests on a different architecture with Qemu. Forces an out-of-tree build.' )
16591734 parser .add_argument ('--default-target' ,
0 commit comments