Skip to content

Commit c03fb23

Browse files
committed
Handle missing tools better
Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
1 parent 5d3c541 commit c03fb23

File tree

1 file changed

+154
-84
lines changed

1 file changed

+154
-84
lines changed

tools/bin/mtest

Lines changed: 154 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,100 @@ def clean():
130130
subrun(["make", "clean"], silent=True)
131131

132132

133-
def toolchain(target):
133+
def toolchain_exes(target):
134+
compiler_exe = target.compiler
135+
136+
# construct triple needed in gcc and objdump executable name
137+
triple_abi = "gnu"
138+
triple_arch = target.arch
139+
if target.arch == "x86":
140+
triple_arch = "i686"
141+
elif target.isa == "aarch64":
142+
triple_arch = "aarch64"
143+
elif target.arch.startswith("armv"):
144+
triple_arch = "arm"
145+
triple_abi = "gnueabi"
146+
if target.arch in ["mips64", "mips64el"]:
147+
triple_abi = "gnuabi64"
148+
triple = f"{triple_arch}-linux-{triple_abi}"
149+
150+
if target.compiler == "gcc":
151+
if not target.is_native:
152+
# see https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
153+
if "-march" in target.cflags or "-mcpu" in target.cflags:
154+
# user-specified arch/isa/cpu
155+
triple = "aarch64-linux-gnu"
156+
for v in range(1,7):
157+
if f"-march=armv{v}" in target.cflags: triple = "arm-linux-gnueabi"
158+
if "-mthumb" in target.cflags: triple = "arm-linux-gnueabi"
159+
m = re.search(r"-mcpu=cortex-(\S+)", target.cflags)
160+
if m:
161+
v = m.group(1)
162+
if (v[0] == 'a' and int(v[1:]) < 34): triple = "arm-linux-gnueabi"
163+
if (v[0] == 'm'): triple = "arm-linux-gnueabi"
164+
if "-mcpu=arm" in target.cflags: triple = "arm-linux-gnueabi"
165+
166+
compiler_exe = f"{triple}-gcc"
167+
for i in range(25, 1, -1):
168+
if shutil.which(compiler_exe) is not None: break
169+
compiler_exe = f"{triple}-gcc-{i}"
170+
171+
if shutil.which(compiler_exe) is None:
172+
compiler_exe = None
173+
if target.compiler == "gcc":
174+
compiler_error = f"could not locate gcc executable {triple}-gcc or {triple}-gcc-<majorversion>"
175+
else:
176+
compiler_error = f"could not locate {target.compiler} executable"
177+
178+
# non-arch-specific size should work in all cases, but may as well prefer <triple>-size
179+
if args.size:
180+
size_exe = triple + "-size"
181+
if shutil.which(size_exe) is None:
182+
size_exe = "size"
183+
if shutil.which(size_exe) is None:
184+
size_exe = None
185+
else:
186+
size_exe = None
187+
size_error = f"could not locate size executable {triple}-size or size"
188+
189+
# we need an architecture-specific obj-dump for disassembly (unless it's a native build)
190+
if args.disassemble:
191+
objdump_exe = triple + "-objdump"
192+
if shutil.which(objdump_exe) is None:
193+
if target.is_native:
194+
objdump_exe = "objdump"
195+
if shutil.which(objdump_exe) is None:
196+
objdump_exe = None
197+
else:
198+
objdump_exe = None
199+
if target.is_native:
200+
objdump_error = f"could not locate size executable {triple}-objdump or objdump"
201+
else:
202+
objdump_error = f"could not locate size executable {triple}-objdump"
203+
204+
if target.arch.startswith("armv"):
205+
qemu_arch = "arm"
206+
else:
207+
qemu_arch = QEMU_NAME_MAP.get(target.arch, target.arch)
208+
qemu_exe = f"qemu-{qemu_arch}-static"
209+
qemu_error = f"could not locate qemu executable {qemu_exe}"
210+
if shutil.which(qemu_exe) is None:
211+
qemu_exe = None
212+
213+
return {
214+
"compiler": compiler_exe,
215+
"objdump": objdump_exe,
216+
"size": size_exe,
217+
"triple": triple,
218+
"qemu": qemu_exe,
219+
"compiler_error": compiler_error,
220+
"size_error": size_error,
221+
"objdump_error": objdump_error,
222+
"qemu_error": qemu_error
223+
}
224+
225+
226+
def toolchain(target, exit_on_failure=True):
134227
# basic CFLAGS setup
135228
c_flags = f"-I{ROOT}/include"
136229
if "-O" not in target.cflags:
@@ -147,21 +240,10 @@ def toolchain(target):
147240
c_flags += " " + target.cflags.strip()
148241
c_flags = c_flags.strip()
149242

150-
compiler_exe = target.compiler
151-
152-
# construct triple needed in gcc and objdump executable name
153-
triple_abi = "gnu"
154-
triple_arch = target.arch
155-
if target.arch == "x86":
156-
triple_arch = "i686"
157-
elif target.isa == "aarch64":
158-
triple_arch = "aarch64"
159-
elif target.arch.startswith("armv"):
160-
triple_arch = "arm"
161-
triple_abi = "gnueabi"
162-
if target.arch in ["mips64", "mips64el"]:
163-
triple_abi = "gnuabi64"
164-
triple = f"{triple_arch}-linux-{triple_abi}"
243+
if args.memsan:
244+
c_flags += " " + MEMSAN_CFLAGS
245+
elif args.asan:
246+
c_flags += " " + ASAN_CFLAGS
165247

166248
if target.compiler == "armclang":
167249
if target.isa == "thumb1":
@@ -174,24 +256,13 @@ def toolchain(target):
174256
elif target.isa == "aarch64":
175257
c_flags += " --target=aarch64-arm-none-eabi -mcpu=cortex-a78"
176258
else:
177-
error(f"unsupported ISA {target.isa} for armclang")
259+
if exit_on_failure: error(f"unsupported ISA {target.isa} for armclang")
178260

179261
elif target.compiler == "gcc":
180262
if not target.is_native:
181263
# see https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html
182-
if "-march" in c_flags or "-mcpu" in c_flags:
183-
# user-specified arch/isa/cpu
184-
triple = "aarch64-linux-gnu"
185-
for v in range(1,7):
186-
if f"-march=armv{v}" in c_flags: triple = "arm-linux-gnueabi"
187-
if "-mthumb" in c_flags: triple = "arm-linux-gnueabi"
188-
m = re.search(r"-mcpu=cortex-(\S+)", c_flags)
189-
if m:
190-
v = m.group(1)
191-
if (v[0] == 'a' and int(v[1:]) < 34): triple = "arm-linux-gnueabi"
192-
if (v[0] == 'm'): triple = "arm-linux-gnueabi"
193-
if "-mcpu=arm" in c_flags: triple = "arm-linux-gnueabi"
194-
else:
264+
if not ("-march" in c_flags or "-mcpu" in c_flags):
265+
# not user-specified arch/isa/cpu
195266
if target.arch == "armv5" and target.isa == "thumb1":
196267
c_flags += " -mcpu=arm926ej-s -mthumb"
197268
elif target.arch == "armv5" and target.isa == "arm":
@@ -217,13 +288,6 @@ def toolchain(target):
217288
if target.arch == "x86_64":
218289
# Support AESNI intrinsics
219290
c_flags += " -mpclmul -msse2 -maes"
220-
# search for compiler exe (highest version available)
221-
compiler_exe = f"{triple}-gcc"
222-
for i in range(25, 1, -1):
223-
if shutil.which(compiler_exe) is not None: break
224-
compiler_exe = f"{triple}-gcc-{i}"
225-
else:
226-
error(f"could not locate gcc executable {triple}-gcc or {triple}-gcc-<majorversion>")
227291

228292
elif target.compiler == "clang":
229293
if not target.is_native:
@@ -257,44 +321,20 @@ def toolchain(target):
257321
else:
258322
error(f"unsupported target {target.arch} {target.isa} for clang")
259323

260-
if args.memsan:
261-
c_flags += " " + MEMSAN_CFLAGS
262-
ld_flags = target.ldflags
263-
elif args.asan:
264-
c_flags += " " + ASAN_CFLAGS
265-
ld_flags = target.ldflags + " " + ASAN_LDFLAGS
266-
else:
267-
ld_flags = target.ldflags
268-
324+
ld_flags = target.ldflags
325+
if args.asan:
326+
ld_flags += " " + ASAN_LDFLAGS
269327
if not target.is_native:
270328
ld_flags += " --static"
271329

272-
# non-arch-specific size should work in all cases, but may as well prefer <triple>-size
273-
size_exe = triple + "-size"
274-
if args.size:
275-
if shutil.which(size_exe) is None:
276-
size_exe = "size"
277-
if shutil.which(size_exe) is None:
278-
error(f"could not locate size executable {triple}-size or size")
279-
280-
# we need an architecture-specific obj-dump for disassembly (unless it's a native build)
281-
objdump_exe = triple + "-objdump"
282-
if args.disassemble and shutil.which(objdump_exe) is None:
283-
if target.is_native:
284-
objdump_exe = "objdump"
285-
if shutil.which(objdump_exe) is None:
286-
error(f"could not locate objdump executable {objdump_exe}")
287-
288-
# check for compiler exe
289-
if shutil.which(compiler_exe) is None:
290-
error(f"could not locate compiler executable {compiler_exe}")
330+
exes = toolchain_exes(target)
291331

292332
return {
293333
"CFLAGS": c_flags.strip(),
294334
"LDFLAGS": ld_flags.strip(),
295-
"CC": compiler_exe,
296-
"OBJDUMP": objdump_exe,
297-
"SIZE": size_exe
335+
"CC": exes["compiler"],
336+
"OBJDUMP": exes["objdump"],
337+
"SIZE": exes["size"]
298338
}
299339

300340

@@ -373,6 +413,10 @@ def flags_to_hr_str(flags):
373413
return hrs.strip()
374414

375415

416+
def can_disassemble(target):
417+
return toolchain_exes(target)["objdump"] is not None
418+
419+
376420
def disassemble(target):
377421
# note: clang seems to want "-gdwarf-4" passed to CFLAGS to show source with --source properly
378422
# run objdump -d to disassemble
@@ -401,6 +445,10 @@ def disassemble(target):
401445
return "\n".join(diss)
402446

403447

448+
def can_build(target):
449+
return toolchain_exes(target)["compiler"] is not None
450+
451+
404452
def build(target, tests):
405453
log("building")
406454
try:
@@ -438,6 +486,10 @@ def build(target, tests):
438486
log(indent_adjust=-4)
439487

440488

489+
def can_size(target):
490+
return toolchain_exes(target)["size"] is not None
491+
492+
441493
def size(target):
442494
log("size")
443495
try:
@@ -465,6 +517,13 @@ def size(target):
465517
log(indent_adjust=-4)
466518

467519

520+
def can_run(target):
521+
if target.is_native:
522+
return True
523+
else:
524+
return toolchain_exes(target)["qemu"] is not None
525+
526+
468527
def run(target, tests, quiet=False):
469528
if target.baremetal or not tests: return
470529

@@ -476,11 +535,8 @@ def run(target, tests, quiet=False):
476535
if target.is_native:
477536
output, _ = subrun(f"{TEST_DIR}/" + t, test_dir=True, silent=quiet)
478537
else:
479-
if target.arch.startswith("armv"):
480-
qemu_arch = "arm"
481-
else:
482-
qemu_arch = QEMU_NAME_MAP.get(target.arch, target.arch)
483-
output, _ = subrun([f"qemu-{qemu_arch}-static", t], test_dir=True, silent=quiet)
538+
qemu_exe = toolchain_exes(target)["qemu"]
539+
output, _ = subrun([qemu_exe, t], test_dir=True, silent=quiet)
484540
if quiet and output:
485541
log(output.splitlines()[-1])
486542
finally:
@@ -526,15 +582,15 @@ mtest -k alignment
526582
527583
Report library size, as built by armclang -Oz with TF-M configuration for armv8 thumb2:
528584
mtest -S
529-
mtest -S clang # as above, but use clang instead of the default armclang
585+
mtest -S clang # as above, but use clang instead of the default armclang
530586
531587
Build aes.o multiple times, with every combination of the given options:
532588
mtest aes.o MBEDTLS_AES_SETKEY_ENC_ALT,MBEDTLS_AES_DECRYPT_ALT,MBEDTLS_AES_ROM_TABLES,MBEDTLS_AES_ENCRYPT_ALT,MBEDTLS_AES_SETKEY_DEC_ALT,MBEDTLS_AES_FEWER_TABLES,MBEDTLS_PADLOCK_C
533589
534590
Disassemble cmac.o
535591
mtest cmac.o -d
536592
537-
Disassemble mbedtls_xor, built with clang -Os for arm
593+
Disassemble mbedtls_xor for arm, built with clang -Os
538594
mtest -d mbedtls_xor -Os clang arm
539595
'''
540596

@@ -770,16 +826,30 @@ def main():
770826
try:
771827
log(indent_adjust=4)
772828
backup_config_options(restore=True, delete_backup=False)
773-
build(target, args.tests)
829+
if can_build(target):
830+
build(target, args.tests)
831+
else:
832+
log("skipping target: " + toolchain_exes(target)["compiler_error"])
833+
continue
774834
if args.size:
775-
size(target)
776-
if (args.disassemble):
777-
d = disassemble(target)
778-
log(f"Disassembly for {args.disassemble}:")
779-
print(d)
780-
print()
781-
run(target, args.tests, quiet=quiet)
782-
first = False
835+
if can_size(target):
836+
size(target)
837+
else:
838+
log("skipping size: " + toolchain_exes(target)["size_error"])
839+
if args.disassemble:
840+
if can_disassemble(target):
841+
d = disassemble(target)
842+
distgt = '' if args.disassemble == True else ' for ' + args.disassemble
843+
log(f"Disassembly{distgt}:")
844+
print(d)
845+
print()
846+
else:
847+
log("skipping disassemble: " + toolchain_exes(target)["objdump_error"])
848+
if args.tests:
849+
if can_run(target):
850+
run(target, args.tests, quiet=quiet)
851+
else:
852+
log("skipping running tests: " + toolchain_exes(target)["qemu_error"])
783853
finally:
784854
log(indent_adjust=-4)
785855
finally:

0 commit comments

Comments
 (0)