Skip to content

Commit d9becd4

Browse files
authored
Merge pull request #11856 from fkjagodzinski/gcc_build-enable_lto_for_release
GCC: Add a build profile extension with the link-time optimizer enabled
2 parents c12b433 + 56255ad commit d9becd4

File tree

5 files changed

+57
-16
lines changed

5 files changed

+57
-16
lines changed

tools/profiles/debug.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"GCC_ARM": {
3-
"common": ["-c", "-Wall", "-Wextra",
3+
"common": ["-Wall", "-Wextra",
44
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
55
"-fmessage-length=0", "-fno-exceptions",
66
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
77
"-MMD",
8-
"-fomit-frame-pointer", "-Og", "-g3", "-DMBED_DEBUG",
8+
"-fomit-frame-pointer", "-Og", "-DMBED_DEBUG",
99
"-DMBED_TRAP_ERRORS_ENABLED=1"],
10-
"asm": ["-x", "assembler-with-cpp"],
11-
"c": ["-std=gnu11"],
12-
"cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"],
10+
"asm": ["-c", "-g3", "-x", "assembler-with-cpp"],
11+
"c": ["-c", "-g3", "-std=gnu11"],
12+
"cxx": ["-c", "-g3", "-std=gnu++14", "-fno-rtti", "-Wvla"],
1313
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
1414
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
1515
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",

tools/profiles/develop.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"GCC_ARM": {
3-
"common": ["-c", "-Wall", "-Wextra",
3+
"common": ["-Wall", "-Wextra",
44
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
55
"-fmessage-length=0", "-fno-exceptions",
66
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
77
"-MMD",
88
"-fomit-frame-pointer", "-Os", "-g", "-DMBED_TRAP_ERRORS_ENABLED=1"],
9-
"asm": ["-x", "assembler-with-cpp"],
10-
"c": ["-std=gnu11"],
11-
"cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"],
9+
"asm": ["-c", "-x", "assembler-with-cpp"],
10+
"c": ["-c", "-std=gnu11"],
11+
"cxx": ["-c", "-std=gnu++14", "-fno-rtti", "-Wvla"],
1212
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
1313
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
1414
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",

tools/profiles/extensions/lto.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"ARMC6": {
33
"common": ["-flto"],
44
"ld": ["--lto", "--lto_level=Oz"]
5+
},
6+
"GCC_ARM": {
7+
"common": ["-flto"],
8+
"ld": ["-u main"]
59
}
610
}

tools/profiles/release.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"GCC_ARM": {
3-
"common": ["-c", "-Wall", "-Wextra",
3+
"common": ["-Wall", "-Wextra",
44
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
55
"-fmessage-length=0", "-fno-exceptions",
66
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
77
"-MMD",
88
"-fomit-frame-pointer", "-Os", "-DNDEBUG", "-g"],
9-
"asm": ["-x", "assembler-with-cpp"],
10-
"c": ["-std=gnu11"],
11-
"cxx": ["-std=gnu++14", "-fno-rtti", "-Wvla"],
9+
"asm": ["-c", "-x", "assembler-with-cpp"],
10+
"c": ["-c", "-std=gnu11"],
11+
"cxx": ["-c", "-std=gnu++14", "-fno-rtti", "-Wvla"],
1212
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
1313
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_memalign_r",
1414
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit",

tools/toolchains/gcc.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import re
1818
import fnmatch
1919
from os.path import join, basename, splitext, dirname, exists
20-
from os import getenv
20+
from os import getcwd, getenv
2121
from distutils.spawn import find_executable
2222
from distutils.version import LooseVersion
2323

@@ -35,6 +35,7 @@ class GCC(mbedToolchain):
3535

3636
GCC_RANGE = (LooseVersion("9.0.0"), LooseVersion("10.0.0"))
3737
GCC_VERSION_RE = re.compile(b"\d+\.\d+\.\d+")
38+
DWARF_PRODUCER_RE = re.compile(r'(DW_AT_producer)(.*:\s*)(?P<producer>.*)')
3839

3940
def __init__(self, target, notify=None, macros=None, build_profile=None,
4041
build_dir=None, coverage_patterns=None):
@@ -149,12 +150,14 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
149150
self.cppc += self.flags['cxx'] + self.flags['common']
150151

151152
self.flags['ld'] += self.cpu
152-
self.ld = [join(tool_path, "arm-none-eabi-gcc")] + self.flags['ld']
153+
self.ld = [join(tool_path, "arm-none-eabi-gcc")]
154+
self.ld += self.flags['ld'] + self.flags['common']
153155
self.sys_libs = ["stdc++", "supc++", "m", "c", "gcc", "nosys"]
154156
self.preproc = [join(tool_path, "arm-none-eabi-cpp"), "-E", "-P"]
155157

156158
self.ar = join(tool_path, "arm-none-eabi-ar")
157159
self.elf2bin = join(tool_path, "arm-none-eabi-objcopy")
160+
self.objdump = join(tool_path, "arm-none-eabi-objdump")
158161

159162
self.use_distcc = (bool(getenv("DISTCC_POTENTIAL_HOSTS", False))
160163
and not getenv("MBED_DISABLE_DISTCC", False))
@@ -305,12 +308,31 @@ def link(self, output, objects, libraries, lib_dirs, mem_map):
305308
self.default_cmd(cmd)
306309
mem_map = preproc_output
307310

311+
# NOTE: GCC_ARM_LTO_WORKAROUND
312+
# This is a workaround for the GCC not using the strong symbols from
313+
# C files to override the weak symbols from ASM files. This GCC bug is only
314+
# present when building with the link-time optimizer (LTO) enabled. For
315+
# more details please see:
316+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967
317+
#
318+
# This can be fixed by changing the order of object files in the linker
319+
# command; objects providing the weak symbols and compiled from assembly
320+
# must be listed before the objects providing the strong symbols.
321+
# To keep things simple, ALL object files from ASM are listed before
322+
# other object files.
323+
asm_objects = []
324+
if '-flto' in self.ld:
325+
asm_objects = self.get_asm_objects(objects)
326+
reorg_objects = (
327+
[o for o in objects if o in asm_objects] +
328+
[o for o in objects if o not in asm_objects]
329+
)
308330
# Build linker command
309331
map_file = splitext(output)[0] + ".map"
310332
cmd = (
311333
(self.coverage_ld if self.coverage_patterns else self.ld) +
312334
["-o", output, "-Wl,-Map=%s" % map_file] +
313-
objects +
335+
reorg_objects +
314336
["-Wl,--start-group"] +
315337
libs +
316338
["-Wl,--end-group"]
@@ -382,6 +404,21 @@ def check_executable():
382404
exec_name = join(TOOLCHAIN_PATHS['GCC_ARM'], 'arm-none-eabi-gcc')
383405
return exists(exec_name) or exists(exec_name + '.exe')
384406

407+
def check_if_obj_from_asm(self, obj_file):
408+
"""Check if obj_file was build by the GNU Assembler."""
409+
dw_producer = ''
410+
cmd = [self.objdump, '--dwarf=info', obj_file]
411+
stdout, stderr, rc = run_cmd(cmd, work_dir=getcwd(), chroot=self.CHROOT)
412+
if rc != 0:
413+
return False
414+
match = self.DWARF_PRODUCER_RE.search(stdout.encode('utf-8'))
415+
if match:
416+
dw_producer = match.group('producer')
417+
return 'GNU AS' in dw_producer
418+
419+
def get_asm_objects(self, objects):
420+
"""Return a list of object files built from ASM."""
421+
return [o for o in objects if self.check_if_obj_from_asm(o)]
385422

386423
class GCC_ARM(GCC):
387424
pass

0 commit comments

Comments
 (0)