1818from builtins import str # noqa: F401
1919
2020import re
21+ import os
2122from copy import copy
22- from os .path import join , dirname , splitext , basename , exists , isfile
23+ from os .path import join , dirname , splitext , basename , exists , isfile , split
2324from os import makedirs , write , remove
2425from tempfile import mkstemp
2526from shutil import rmtree
2627from distutils .version import LooseVersion
2728
2829from tools .targets import CORE_ARCH
2930from tools .toolchains .mbed_toolchain import mbedToolchain , TOOLCHAIN_PATHS
30- from tools .utils import mkdir , NotSupportedException , run_cmd
31+ from tools .utils import mkdir , NotSupportedException , ToolException , run_cmd
3132
3233
3334class ARM (mbedToolchain ):
@@ -44,6 +45,7 @@ class ARM(mbedToolchain):
4445 "Cortex-M7" , "Cortex-M7F" , "Cortex-M7FD" , "Cortex-A9"
4546 ]
4647 ARMCC_RANGE = (LooseVersion ("5.06" ), LooseVersion ("5.07" ))
48+ ARMCC_PRODUCT_RE = re .compile (b"Product: (.*)" )
4749 ARMCC_VERSION_RE = re .compile (b"Component: ARM Compiler (\d+\.\d+)" )
4850
4951 @staticmethod
@@ -103,11 +105,20 @@ def __init__(self, target, notify=None, macros=None,
103105
104106 self .SHEBANG += " --cpu=%s" % cpu
105107
108+ self .product_name = None
109+
106110 def version_check (self ):
107- stdout , _ , retcode = run_cmd ([self .cc [0 ], "--vsn" ], redirect = True )
111+ # The --ide=mbed removes an instability with checking the version of
112+ # the ARMC6 binary that comes with Mbed Studio.
113+ # NOTE: the --ide=mbed argument is only for use with Mbed OS
114+ stdout , _ , retcode = run_cmd (
115+ [self .cc [0 ], "--vsn" , "--ide=mbed" ],
116+ redirect = True
117+ )
108118 msg = None
109119 min_ver , max_ver = self .ARMCC_RANGE
110- match = self .ARMCC_VERSION_RE .search (stdout .encode ("utf-8" ))
120+ output = stdout .encode ("utf-8" )
121+ match = self .ARMCC_VERSION_RE .search (output )
111122 if match :
112123 found_version = LooseVersion (match .group (1 ).decode ("utf-8" ))
113124 else :
@@ -132,6 +143,19 @@ def version_check(self):
132143 "severity" : "WARNING" ,
133144 })
134145
146+ msg = None
147+ match = self .ARMCC_PRODUCT_RE .search (output )
148+ if match :
149+ self .product_name = match .group (1 ).decode ("utf-8" )
150+ else :
151+ self .product_name = None
152+
153+ if not match or len (match .groups ()) != 1 :
154+ msg = (
155+ "Could not detect product name: defaulting to professional "
156+ "version of ARMC6"
157+ )
158+
135159 def _get_toolchain_labels (self ):
136160 if getattr (self .target , "default_toolchain" , "ARM" ) == "uARM" :
137161 return ["ARM" , "ARM_MICRO" ]
@@ -275,7 +299,7 @@ def correct_scatter_shebang(self, scatter_file, cur_dir_name=None):
275299
276300 return new_scatter
277301
278- def link (self , output , objects , libraries , lib_dirs , scatter_file ):
302+ def get_link_command (self , output , objects , libraries , lib_dirs , scatter_file ):
279303 base , _ = splitext (output )
280304 map_file = base + ".map"
281305 args = ["-o" , output , "--info=totals" , "--map" , "--list=%s" % map_file ]
@@ -294,6 +318,13 @@ def link(self, output, objects, libraries, lib_dirs, scatter_file):
294318 link_files = self .get_link_file (cmd [1 :])
295319 cmd = [cmd_linker , '--via' , link_files ]
296320
321+ return cmd
322+
323+ def link (self , output , objects , libraries , lib_dirs , scatter_file ):
324+ cmd = self .get_link_command (
325+ output , objects , libraries , lib_dirs , scatter_file
326+ )
327+
297328 self .notify .cc_verbose ("Link: %s" % ' ' .join (cmd ))
298329 self .default_cmd (cmd )
299330
@@ -304,12 +335,15 @@ def archive(self, objects, lib_path):
304335 param = objects
305336 self .default_cmd ([self .ar , '-r' , lib_path ] + param )
306337
338+ def get_binary_commands (self , bin_arg , bin , elf ):
339+ return [self .elf2bin , bin_arg , '-o' , bin , elf ]
340+
307341 def binary (self , resources , elf , bin ):
308342 _ , fmt = splitext (bin )
309343 # On .hex format, combine multiple .hex files (for multiple load
310344 # regions) into one
311345 bin_arg = {".bin" : "--bin" , ".hex" : "--i32combined" }[fmt ]
312- cmd = [ self .elf2bin , bin_arg , '-o' , bin , elf ]
346+ cmd = self .get_binary_commands ( bin_arg , bin , elf )
313347
314348 # remove target binary file/path
315349 if exists (bin ):
@@ -337,7 +371,6 @@ def redirect_symbol(source, sync, build_dir):
337371 write (handle , "RESOLVE %s AS %s\n " % (source , sync ))
338372 return "--edit=%s" % filename
339373
340-
341374class ARM_STD (ARM ):
342375
343376 OFFICIALLY_SUPPORTED = True
@@ -359,7 +392,7 @@ def __init__(
359392 build_profile = build_profile
360393 )
361394 if int (target .build_tools_metadata ["version" ]) > 0 :
362- #check only for ARMC5 because ARM_STD means using ARMC5, and thus
395+ #check only for ARMC5 because ARM_STD means using ARMC5, and thus
363396 # supported_toolchains must include ARMC5
364397 if "ARMC5" not in target .supported_toolchains :
365398 raise NotSupportedException (
@@ -546,12 +579,21 @@ def __init__(self, target, *args, **kwargs):
546579 self .ar = join (TOOLCHAIN_PATHS ["ARMC6" ], "armar" )
547580 self .elf2bin = join (TOOLCHAIN_PATHS ["ARMC6" ], "fromelf" )
548581
582+ # Adding this for safety since this inherits the `version_check` function
583+ # but does not call the constructor of ARM_STD, so the `product_name` variable
584+ # is not initialized.
585+ self .product_name = None
586+
549587 def _get_toolchain_labels (self ):
550588 if getattr (self .target , "default_toolchain" , "ARM" ) == "uARM" :
551589 return ["ARM" , "ARM_MICRO" , "ARMC6" ]
552590 else :
553591 return ["ARM" , "ARM_STD" , "ARMC6" ]
554592
593+ @property
594+ def is_mbed_studio_armc6 (self ):
595+ return self .product_name and "Mbed Studio" in self .product_name
596+
555597 def parse_dependencies (self , dep_path ):
556598 return mbedToolchain .parse_dependencies (self , dep_path )
557599
@@ -565,21 +607,27 @@ def get_config_option(self, config_header):
565607 return ["-include" , config_header ]
566608
567609 def get_compile_options (self , defines , includes , for_asm = False ):
568-
610+
569611 opts = ['-D%s' % d for d in defines ]
612+
570613 if self .RESPONSE_FILES :
571614 opts += ['@{}' .format (self .get_inc_file (includes ))]
572615 else :
573616 opts += ["-I%s" % i for i in includes if i ]
574-
617+
575618 config_header = self .get_config_header ()
576619 if config_header :
577620 opts .extend (self .get_config_option (config_header ))
578621 if for_asm :
579- return [
622+ opts = [
580623 "--cpreproc" ,
581624 "--cpreproc_opts=%s" % "," .join (self .flags ['common' ] + opts )
582625 ]
626+
627+ if self .is_mbed_studio_armc6 :
628+ # NOTE: the --ide=mbed argument is only for use with Mbed OS
629+ opts .insert (0 , "--ide=mbed" )
630+
583631 return opts
584632
585633 def assemble (self , source , object , includes ):
@@ -594,3 +642,23 @@ def compile(self, cc, source, object, includes):
594642 cmd .extend (self .get_compile_options (self .get_symbols (), includes ))
595643 cmd .extend (["-o" , object , source ])
596644 return [cmd ]
645+
646+ def get_link_command (self , output , objects , libraries , lib_dirs , scatter_file ):
647+ cmd = ARM .get_link_command (
648+ self , output , objects , libraries , lib_dirs , scatter_file
649+ )
650+
651+ if self .is_mbed_studio_armc6 :
652+ # NOTE: the --ide=mbed argument is only for use with Mbed OS
653+ cmd .insert (1 , "--ide=mbed" )
654+
655+ return cmd
656+
657+ def get_binary_commands (self , bin_arg , bin , elf ):
658+ cmd = ARM .get_binary_commands (self , bin_arg , bin , elf )
659+
660+ if self .is_mbed_studio_armc6 :
661+ # NOTE: the --ide=mbed argument is only for use with Mbed OS
662+ cmd .insert (1 , "--ide=mbed" )
663+
664+ return cmd
0 commit comments