Skip to content

Commit a6f4b58

Browse files
authored
Merge pull request #2675 from sarahmarshy/toolchain_path_check
Revise checking toolchain path
2 parents 054f232 + 8670598 commit a6f4b58

File tree

7 files changed

+99
-49
lines changed

7 files changed

+99
-49
lines changed

tools/build.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
sys.path.insert(0, ROOT)
2828

2929

30-
from tools.toolchains import TOOLCHAINS
30+
from tools.toolchains import TOOLCHAINS, TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
3131
from tools.toolchains import mbedToolchain
3232
from tools.targets import TARGET_NAMES, TARGET_MAP
3333
from tools.options import get_default_options_parser
@@ -161,6 +161,7 @@
161161
print mcu_toolchain_matrix(platform_filter=options.general_filter_regex)
162162
exit(0)
163163

164+
164165
# Get target list
165166
targets = options.mcu if options.mcu else TARGET_NAMES
166167

@@ -212,6 +213,11 @@
212213
# CPPCHECK code validation
213214
if options.cppcheck_validation:
214215
for toolchain in toolchains:
216+
if not TOOLCHAIN_CLASSES[toolchain].check_executable():
217+
search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
218+
args_error(parser, "Could not find executable for %s.\n"
219+
"Currently set search path: %s"
220+
% (toolchain, search_path))
215221
for target in targets:
216222
try:
217223
mcu = TARGET_MAP[target]

tools/make.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import sys
2222
from time import sleep
2323
from shutil import copy
24-
from os.path import join, abspath, dirname, isfile, isdir
24+
from os.path import join, abspath, dirname
2525

2626
# Be sure that the tools directory is in the search path
2727
ROOT = abspath(join(dirname(__file__), ".."))
@@ -46,8 +46,7 @@
4646
from utils import argparse_filestring_type
4747
from utils import argparse_many
4848
from utils import argparse_dir_not_parent
49-
from argparse import ArgumentTypeError
50-
from tools.toolchains import mbedToolchain
49+
from tools.toolchains import mbedToolchain, TOOLCHAIN_CLASSES, TOOLCHAIN_PATHS
5150
from tools.settings import CLI_COLOR_MAP
5251

5352
if __name__ == '__main__':
@@ -232,6 +231,12 @@
232231
else:
233232
notify = None
234233

234+
if not TOOLCHAIN_CLASSES[toolchain].check_executable():
235+
search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
236+
args_error(parser, "Could not find executable for %s.\n"
237+
"Currently set search path: %s"
238+
%(toolchain,search_path))
239+
235240
# Test
236241
for test_no in p:
237242
test = Test(test_no)

tools/test.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from tools.test_exporters import ReportExporter, ResultExporterType
3636
from utils import argparse_filestring_type, argparse_lowercase_type, argparse_many
3737
from utils import argparse_dir_not_parent
38-
from tools.toolchains import mbedToolchain
38+
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS, TOOLCHAIN_CLASSES
3939
from tools.settings import CLI_COLOR_MAP
4040

4141
if __name__ == '__main__':
@@ -115,6 +115,12 @@
115115
args_error(parser, "argument -t/--tool is required")
116116
toolchain = options.tool[0]
117117

118+
if not TOOLCHAIN_CLASSES[toolchain].check_executable():
119+
search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
120+
args_error(parser, "Could not find executable for %s.\n"
121+
"Currently set search path: %s"
122+
% (toolchain, search_path))
123+
118124
# Find all tests in the relevant paths
119125
for path in all_paths:
120126
all_tests.update(find_tests(path, mcu, toolchain, options.options,
@@ -196,6 +202,7 @@
196202
print "Failed to build library"
197203
else:
198204
# Build all the tests
205+
199206
test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, mcu, toolchain,
200207
options=options.options,
201208
clean=options.clean,

tools/toolchains/__init__.py

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from copy import deepcopy
2828
from tools.config import Config
2929
from abc import ABCMeta, abstractmethod
30+
from distutils.spawn import find_executable
3031

3132
from multiprocessing import Pool, cpu_count
3233
from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path, compile_worker
@@ -188,23 +189,6 @@ def __str__(self):
188189
}
189190

190191

191-
def check_toolchain_path(function):
192-
"""Check if the path to toolchain is valid. Exit if not.
193-
Use this function as a decorator. Causes a system exit if the path does
194-
not exist. Execute the function as normal if the path does exist.
195-
196-
Positional arguments:
197-
function -- the function to decorate
198-
"""
199-
def perform_check(self, *args, **kwargs):
200-
if not exists(self.toolchain_path) and not exists(self.toolchain_path+'.exe'):
201-
error_string = 'Could not find executable for %s.\n Currently ' \
202-
'set search path: %s'% (self.name, self.toolchain_path)
203-
raise Exception(error_string)
204-
return function(self, *args, **kwargs)
205-
return perform_check
206-
207-
208192
class mbedToolchain:
209193
# Verbose logging
210194
VERBOSE = True
@@ -723,7 +707,6 @@ def get_arch_file(self, objects):
723707

724708
# THIS METHOD IS BEING CALLED BY THE MBED ONLINE BUILD SYSTEM
725709
# ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
726-
@check_toolchain_path
727710
def compile_sources(self, resources, build_path, inc_dirs=None):
728711
# Web IDE progress bar for project build
729712
files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources
@@ -922,7 +905,6 @@ def compile_output(self, output=[]):
922905
else:
923906
raise ToolException(_stderr)
924907

925-
@check_toolchain_path
926908
def build_library(self, objects, dir, name):
927909
needed_update = False
928910
lib = self.STD_LIB_NAME % name
@@ -934,7 +916,6 @@ def build_library(self, objects, dir, name):
934916

935917
return needed_update
936918

937-
@check_toolchain_path
938919
def link_program(self, r, tmp_path, name):
939920
needed_update = False
940921
ext = 'bin'
@@ -1114,6 +1095,51 @@ def get_config_header(self):
11141095
self.config_processed = True
11151096
return self.config_file
11161097

1098+
@staticmethod
1099+
def generic_check_executable(tool_key, executable_name, levels_up,
1100+
nested_dir=None):
1101+
"""
1102+
Positional args:
1103+
tool_key: the key to index TOOLCHAIN_PATHS
1104+
executable_name: the toolchain's named executable (ex. armcc)
1105+
levels_up: each toolchain joins the toolchain_path, some
1106+
variable directories (bin, include), and the executable name,
1107+
so the TOOLCHAIN_PATH value must be appropriately distanced
1108+
1109+
Keyword args:
1110+
nested_dir: the directory within TOOLCHAIN_PATHS where the executable
1111+
is found (ex: 'bin' for ARM\bin\armcc (necessary to check for path
1112+
that will be used by toolchain's compile)
1113+
1114+
Returns True if the executable location specified by the user
1115+
exists and is valid OR the executable can be found on the PATH.
1116+
Returns False otherwise.
1117+
"""
1118+
# Search PATH if user did not specify a path or specified path doesn't
1119+
# exist.
1120+
if not TOOLCHAIN_PATHS[tool_key] or not exists(TOOLCHAIN_PATHS[tool_key]):
1121+
exe = find_executable(executable_name)
1122+
if not exe:
1123+
return False
1124+
for level in range(levels_up):
1125+
# move up the specified number of directories
1126+
exe = dirname(exe)
1127+
TOOLCHAIN_PATHS[tool_key] = exe
1128+
if nested_dir:
1129+
subdir = join(TOOLCHAIN_PATHS[tool_key], nested_dir,
1130+
executable_name)
1131+
else:
1132+
subdir = join(TOOLCHAIN_PATHS[tool_key],executable_name)
1133+
# User could have specified a path that exists but does not contain exe
1134+
return exists(subdir) or exists(subdir +'.exe')
1135+
1136+
@abstractmethod
1137+
def check_executable(self):
1138+
"""Returns True if the executable (armcc) location specified by the
1139+
user exists OR the executable can be found on the PATH.
1140+
Returns False otherwise."""
1141+
raise NotImplemented
1142+
11171143
@abstractmethod
11181144
def get_config_option(self, config_header):
11191145
"""Generate the compiler option that forces the inclusion of the configuration

tools/toolchains/arm.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"""
1717
import re
1818
from os.path import join, dirname, splitext, basename
19-
from distutils.spawn import find_executable
2019

2120
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
2221
from tools.hooks import hook_tool
@@ -42,6 +41,13 @@ class ARM(mbedToolchain):
4241
'ld': [],
4342
}
4443

44+
@staticmethod
45+
def check_executable():
46+
"""Returns True if the executable (armcc) location specified by the
47+
user exists OR the executable can be found on the PATH.
48+
Returns False otherwise."""
49+
return mbedToolchain.generic_check_executable("ARM", 'armcc', 2, 'bin')
50+
4551
def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
4652
mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose)
4753

@@ -56,11 +62,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
5662
else:
5763
cpu = target.core
5864

59-
if not TOOLCHAIN_PATHS['ARM']:
60-
exe = find_executable('armcc')
61-
if exe:
62-
TOOLCHAIN_PATHS['ARM'] = dirname(dirname(exe))
63-
6465
ARM_BIN = join(TOOLCHAIN_PATHS['ARM'], "bin")
6566
ARM_INC = join(TOOLCHAIN_PATHS['ARM'], "include")
6667

@@ -86,8 +87,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
8687
self.ar = join(ARM_BIN, "armar")
8788
self.elf2bin = join(ARM_BIN, "fromelf")
8889

89-
self.toolchain_path = TOOLCHAIN_PATHS['ARM']
90-
9190
def parse_dependencies(self, dep_path):
9291
dependencies = []
9392
for line in open(dep_path).readlines():

tools/toolchains/gcc.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
limitations under the License.
1616
"""
1717
import re
18-
from os.path import join, basename, splitext, dirname, exists
19-
from distutils.spawn import find_executable
18+
from os.path import join, basename, splitext
2019

2120
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
2221
from tools.hooks import hook_tool
@@ -111,11 +110,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
111110
self.ar = join(tool_path, "arm-none-eabi-ar")
112111
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
113112

114-
if tool_path:
115-
self.toolchain_path = main_cc
116-
else:
117-
self.toolchain_path = find_executable("arm-none-eabi-gcc") or ''
118-
119113
def parse_dependencies(self, dep_path):
120114
dependencies = []
121115
buff = open(dep_path).readlines()
@@ -275,6 +269,13 @@ def binary(self, resources, elf, bin):
275269

276270

277271
class GCC_ARM(GCC):
272+
@staticmethod
273+
def check_executable():
274+
"""Returns True if the executable (arm-none-eabi-gcc) location
275+
specified by the user exists OR the executable can be found on the PATH.
276+
Returns False otherwise."""
277+
return mbedToolchain.generic_check_executable("GCC_ARM", 'arm-none-eabi-gcc', 1)
278+
278279
def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
279280
GCC.__init__(self, target, options, notify, macros, silent, TOOLCHAIN_PATHS['GCC_ARM'], extra_verbose=extra_verbose)
280281

@@ -300,6 +301,13 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
300301

301302

302303
class GCC_CR(GCC):
304+
@staticmethod
305+
def check_executable():
306+
"""Returns True if the executable (arm-none-eabi-gcc) location
307+
specified by the user exists OR the executable can be found on the PATH.
308+
Returns False otherwise."""
309+
return mbedToolchain.generic_check_executable("GCC_CR", 'arm-none-eabi-gcc', 1)
310+
303311
def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
304312
GCC.__init__(self, target, options, notify, macros, silent, TOOLCHAIN_PATHS['GCC_CR'], extra_verbose=extra_verbose)
305313

tools/toolchains/iar.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
"""
1717
import re
1818
from os import remove
19-
from os.path import join, exists, dirname, splitext, exists
20-
from distutils.spawn import find_executable
19+
from os.path import join, splitext
2120

2221
from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS
2322
from tools.hooks import hook_tool
@@ -45,18 +44,20 @@ class IAR(mbedToolchain):
4544
'ld': ["--skip_dynamic_initialization", "--threaded_lib"],
4645
}
4746

47+
@staticmethod
48+
def check_executable():
49+
"""Returns True if the executable (arm-none-eabi-gcc) location
50+
specified by the user exists OR the executable can be found on the PATH.
51+
Returns False otherwise."""
52+
return mbedToolchain.generic_check_executable("IAR", 'iccarm', 2, "bin")
53+
4854
def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False):
4955
mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose)
5056
if target.core == "Cortex-M7F" or target.core == "Cortex-M7FD":
5157
cpuchoice = "Cortex-M7"
5258
else:
5359
cpuchoice = target.core
5460

55-
if not TOOLCHAIN_PATHS['IAR']:
56-
exe = find_executable('iccarm')
57-
if exe:
58-
TOOLCHAIN_PATHS['IAR'] = dirname(dirname(exe))
59-
6061
# flags_cmd are used only by our scripts, the project files have them already defined,
6162
# using this flags results in the errors (duplication)
6263
# asm accepts --cpu Core or --fpu FPU, not like c/c++ --cpu=Core
@@ -108,8 +109,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False,
108109
self.ar = join(IAR_BIN, "iarchive")
109110
self.elf2bin = join(IAR_BIN, "ielftool")
110111

111-
self.toolchain_path = TOOLCHAIN_PATHS['IAR']
112-
113112
def parse_dependencies(self, dep_path):
114113
return [(self.CHROOT if self.CHROOT else '')+path.strip() for path in open(dep_path).readlines()
115114
if (path and not path.isspace())]

0 commit comments

Comments
 (0)