1+ #!/usr/bin/env python3
12"""
23Copyright (c) 2017-2019 ARM Limited. All rights reserved.
34
1516See the License for the specific language governing permissions and
1617limitations
1718"""
19+ import json
1820import os
1921from os .path import dirname , abspath , basename , join , normpath
2022import os .path
3032
3133 """
3234
35+
36+ EXECUTABLE_ANALYSIS_TOOLS_PATH = join (
37+ os .path .dirname (__file__ ),
38+ "../../executable_analysis_tools/" ,
39+ )
40+ sys .path .append (EXECUTABLE_ANALYSIS_TOOLS_PATH )
41+ import elf_float_checker
42+
3343ROOT = abspath (dirname (dirname (dirname (dirname (__file__ )))))
34- sys .path .insert ( 0 , ROOT )
44+ sys .path .append ( ROOT )
3545
3646from tools .build_api import get_mbed_official_release
3747from tools .targets import TARGET_MAP
@@ -349,7 +359,15 @@ def status(message):
349359 return results
350360
351361
352- def compile_repos (config , toolchains , targets , profile , verbose , examples ):
362+ def compile_repos (
363+ config ,
364+ toolchains ,
365+ targets ,
366+ profiles ,
367+ verbose ,
368+ examples ,
369+ post_checks ,
370+ ):
353371 """Compiles combinations of example programs, targets and compile chains.
354372
355373 The results are returned in a [key: value] dictionary format:
@@ -388,6 +406,7 @@ def compile_repos(config, toolchains, targets, profile, verbose, examples):
388406 test_example = True
389407 else :
390408 test_example = False
409+
391410 if example ['compile' ]:
392411 for repo_info in get_repo_list (example ):
393412 name = basename (repo_info ['repo' ])
@@ -399,28 +418,54 @@ def compile_repos(config, toolchains, targets, profile, verbose, examples):
399418 example ['features' ]):
400419
401420 build_command = ["mbed-cli" , "compile" , "-t" , toolchain , "-m" , target ] + (['-v' ] if verbose else [])
402- if profile :
403- build_command . append ( "-- profile" )
404- build_command .append ( profile )
421+ if profiles :
422+ for profile in profiles :
423+ build_command .extend ([ "-- profile" , profile ] )
405424
406425 print ("Compiling [%s] for [%s] with toolchain [%s]\n \n > %s" % (name , target , toolchain , " " .join (build_command )))
407426
408- proc = subprocess .Popen (build_command , stdout = subprocess .PIPE , stderr = subprocess .PIPE )
427+ if (
428+ post_checks
429+ and POST_BUILD_CHECK_FLOATS in post_checks
430+ and name not in POST_BUILD_CHECK_FLOATS_EXCLUDED_EXAMPLES
431+ ):
432+ # Disable floating point support for minimal-printf if
433+ # a post build check for minimal-printf is specified.
434+ has_float_support = "false"
435+ else :
436+ has_float_support = "true"
437+
438+ _set_minimal_printf_floats_status (has_float_support )
439+
440+ proc = subprocess .run (
441+ build_command ,
442+ stdin = None ,
443+ stdout = subprocess .PIPE ,
444+ stderr = subprocess .PIPE ,
445+ )
446+
447+ std_out = proc .stdout .decode ()
448+ std_err = proc .stderr .decode ()
409449
410- std_out , std_err = proc .communicate ()
411- std_out = std_out .decode ('utf-8' )
412450 print ("\n #### STDOUT ####\n %s\n #### STDERR ####\n %s\n #### End of STDOUT/STDERR ####\n " % (std_out ,std_err ))
413-
451+
414452 if test_example :
415453 log = example ['compare_log' ].pop (0 )
416454 # example['compare_log'] is a list of log file/files, which matches each examples/sub-examples from same repo.
417455 # pop the log file out of list regardless the compilation for each example pass of fail
418456 image = fetch_output_image (std_out )
419457 if image :
420458 image_info = [{"binary_type" : "bootable" ,"path" : normpath (join (name ,image )),"compare_log" :log }]
459+ if post_checks :
460+ try :
461+ _perform_post_build_checks (
462+ name , post_checks , dirname (image )
463+ )
464+ except PostBuildCheckFailureError as error :
465+ failures .append (str (error ))
421466 else :
422467 print ("Warning: could not find built image for example %s" % name )
423-
468+
424469 example_summary = "{} {} {}" .format (name , target , toolchain )
425470 if proc .returncode :
426471 failures .append (example_summary )
@@ -494,4 +539,81 @@ def fetch_output_image(output):
494539 image = lines [index ][7 :]
495540 if os .path .isfile (image ):
496541 return image
497- return False
542+ return False
543+
544+
545+ def _perform_post_build_checks (example_name , checks , elf_dir_path ):
546+ """
547+ Perform post build checks.
548+
549+ Returns a tuple (str, bool) where str is a message and
550+ bool indicating if the check failed.
551+ """
552+ if not checks :
553+ raise PostBuildCheckFailureError ("No post build check specified" )
554+
555+ # Find the elf file
556+ elf_file = None
557+ for dirpath , _ , filenames in os .walk (elf_dir_path ):
558+ for filename in filenames :
559+ if filename .endswith (".elf" ):
560+ elf_file = os .path .join (dirpath , filename )
561+
562+ if not elf_file :
563+ raise PostBuildCheckFailureError (
564+ "Cannot find ELF file in {}" .format (elf_dir_path )
565+ )
566+
567+ for check in set (checks ):
568+ SUPPORTED_POST_BUILD_CHECKS [check ](example_name , elf_file )
569+
570+
571+ def _set_minimal_printf_floats_status (status ):
572+ """
573+ Enable or disable floating point support in minimal-printf.
574+
575+ Pass the string `true` or `false` to enable or disable floating point.
576+ """
577+ with open (
578+ os .path .join (ROOT , "platform" , "mbed_lib.json" ), "r"
579+ ) as platform_lib_file :
580+ data = json .load (platform_lib_file )
581+
582+ data ["config" ]["minimal-printf-enable-floating-point" ]["value" ] = status
583+
584+ with open (
585+ os .path .join (ROOT , "platform" , "mbed_lib.json" ), "w"
586+ ) as platform_lib_file :
587+ json .dump (data , platform_lib_file , indent = 4 )
588+
589+
590+ # Post-build check functions should be listed below and must raise a
591+ # a PostBuildCheckFailureError in case of failure
592+
593+ def _post_build_check_floating_point (example_name , elf_file ):
594+ """Check if there are floating points in the executable."""
595+
596+ if example_name in POST_BUILD_CHECK_FLOATS_EXCLUDED_EXAMPLES :
597+ return
598+
599+ float_symbols = elf_float_checker .check_float_symbols (elf_file )
600+
601+ if float_symbols :
602+ raise PostBuildCheckFailureError (
603+ "Floating point symbols found in executable: {}" .format (
604+ float_symbols
605+ )
606+ )
607+
608+
609+ POST_BUILD_CHECK_FLOATS_EXCLUDED_EXAMPLES = [
610+ "mbed-os-example-lorawan" ,
611+ "nanostack-border-router" ,
612+ ]
613+ POST_BUILD_CHECK_FLOATS = "FLOATS"
614+ SUPPORTED_POST_BUILD_CHECKS = {
615+ POST_BUILD_CHECK_FLOATS : _post_build_check_floating_point
616+ }
617+
618+ class PostBuildCheckFailureError (Exception ):
619+ """An exception to indicate that a post build check failed."""
0 commit comments