mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:03:19 +00:00
e961aa565e
When producing ARM builds instruct llvm-objcopy to drop .ARM.exidx/extab sections. These sections don't contain any useful information (we don't use exceptions or unwind C++ frames and most of the dart binary is in fact not covered by them), however they have been seen to break dynamic linker in older glibc versions (pre 2.23) because .ARM.exidx ends up being positioned between .rel.dyn and .rel.plt sections while older versions of dynamic linker expect these two sections to appear one after another in the ELF file. Closes https://github.com/dart-lang/sdk/issues/41644. Change-Id: I0ceebb63105591f132f3764180ae041366cbcade Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/175723 Reviewed-by: Alexander Markov <alexmarkov@google.com> Commit-Queue: Vyacheslav Egorov <vegorov@google.com>
260 lines
9.4 KiB
Plaintext
260 lines
9.4 KiB
Plaintext
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
# This value will be inherited in the toolchain below.
|
|
concurrent_links = exec_script("get_concurrent_links.py", [], "value")
|
|
|
|
# This template defines a toolchain for something that works like gcc
|
|
# (including clang).
|
|
#
|
|
# It requires the following variables specifying the executables to run:
|
|
# - cc
|
|
# - cxx
|
|
# - ar
|
|
# - ld
|
|
# - readelf
|
|
# - nm
|
|
# and the following which is used in the toolchain_args
|
|
# - toolchain_cpu (What "current_cpu" should be set to when invoking a
|
|
# build using this toolchain.)
|
|
# - toolchain_os (What "current_os" should be set to when invoking a
|
|
# build using this toolchain.)
|
|
#
|
|
# Optional parameters:
|
|
# - libs_section_prefix
|
|
# - libs_section_postfix
|
|
# The contents of these strings, if specified, will be placed around
|
|
# the libs section of the linker line. It allows one to inject libraries
|
|
# at the beginning and end for all targets in a toolchain.
|
|
# - solink_libs_section_prefix
|
|
# - solink_libs_section_postfix
|
|
# Same as libs_section_{pre,post}fix except used for solink instead of link.
|
|
# - post_solink
|
|
# The content of this string, if specified, will be appended to the solink
|
|
# command.
|
|
# - deps
|
|
# Just forwarded to the toolchain definition.
|
|
# - is_clang
|
|
# - strip
|
|
# Location of the strip executable. When specified, strip will be run on
|
|
# all executables as they are built. The stripped artifacts will be put in
|
|
# exe.stripped/.
|
|
# - llvm_objcopy
|
|
# Location of the llvm-objcopy executable. Used as strip instead of strip
|
|
# when specified.
|
|
template("gcc_toolchain") {
|
|
toolchain(target_name) {
|
|
assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value")
|
|
assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value")
|
|
assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value")
|
|
assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value")
|
|
assert(defined(invoker.readelf),
|
|
"gcc_toolchain() must specify a \"readelf\" value")
|
|
assert(defined(invoker.nm), "gcc_toolchain() must specify a \"nm\" value")
|
|
assert(defined(invoker.toolchain_cpu),
|
|
"gcc_toolchain() must specify a \"toolchain_cpu\"")
|
|
assert(defined(invoker.toolchain_os),
|
|
"gcc_toolchain() must specify a \"toolchain_os\"")
|
|
|
|
# We can't do string interpolation ($ in strings) on things with dots in
|
|
# them. To allow us to use $cc below, for example, we create copies of
|
|
# these values in our scope.
|
|
cc = invoker.cc
|
|
cxx = invoker.cxx
|
|
ar = invoker.ar
|
|
ld = invoker.ld
|
|
readelf = invoker.readelf
|
|
nm = invoker.nm
|
|
|
|
# Bring these into our scope for string interpolation with default values.
|
|
if (defined(invoker.libs_section_prefix)) {
|
|
libs_section_prefix = invoker.libs_section_prefix
|
|
} else {
|
|
libs_section_prefix = ""
|
|
}
|
|
|
|
if (defined(invoker.libs_section_postfix)) {
|
|
libs_section_postfix = invoker.libs_section_postfix
|
|
} else {
|
|
libs_section_postfix = ""
|
|
}
|
|
|
|
if (defined(invoker.solink_libs_section_prefix)) {
|
|
solink_libs_section_prefix = invoker.solink_libs_section_prefix
|
|
} else {
|
|
solink_libs_section_prefix = ""
|
|
}
|
|
|
|
if (defined(invoker.solink_libs_section_postfix)) {
|
|
solink_libs_section_postfix = invoker.solink_libs_section_postfix
|
|
} else {
|
|
solink_libs_section_postfix = ""
|
|
}
|
|
|
|
# These library switches can apply to all tools below.
|
|
lib_switch = "-l"
|
|
lib_dir_switch = "-L"
|
|
|
|
tool("cc") {
|
|
depfile = "{{output}}.d"
|
|
command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
|
|
depsformat = "gcc"
|
|
description = "CC {{output}}"
|
|
outputs =
|
|
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
|
|
}
|
|
|
|
tool("cxx") {
|
|
depfile = "{{output}}.d"
|
|
command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
|
|
depsformat = "gcc"
|
|
description = "CXX {{output}}"
|
|
outputs =
|
|
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
|
|
}
|
|
|
|
tool("asm") {
|
|
# For GCC we can just use the C compiler to compile assembly.
|
|
depfile = "{{output}}.d"
|
|
command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
|
|
depsformat = "gcc"
|
|
description = "ASM {{output}}"
|
|
outputs =
|
|
[ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
|
|
}
|
|
|
|
tool("alink") {
|
|
rspfile = "{{output}}.rsp"
|
|
command = "rm -f {{output}} && $ar rcs {{output}} @$rspfile"
|
|
description = "AR {{output}}"
|
|
rspfile_content = "{{inputs}}"
|
|
outputs =
|
|
[ "{{target_out_dir}}/{{target_output_name}}{{output_extension}}" ]
|
|
default_output_extension = ".a"
|
|
output_prefix = "lib"
|
|
}
|
|
|
|
tool("solink") {
|
|
soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
|
|
sofile = "{{root_out_dir}}/$soname" # Possibly including toolchain dir.
|
|
rspfile = sofile + ".rsp"
|
|
|
|
# These variables are not built into GN but are helpers that implement
|
|
# (1) linking to produce a .so, (2) extracting the symbols from that file
|
|
# to a temporary file, (3) if the temporary file has differences from the
|
|
# existing .TOC file, overwrite it, otherwise, don't change it.
|
|
tocfile = sofile + ".TOC"
|
|
temporary_tocname = sofile + ".tmp"
|
|
link_command =
|
|
"$ld -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
|
|
toc_command = "{ $readelf -d $sofile | grep SONAME ; $nm -gD -f posix $sofile | cut -f1-2 -d' '; } > $temporary_tocname"
|
|
replace_command = "if ! cmp -s $temporary_tocname $tocfile; then mv $temporary_tocname $tocfile; fi"
|
|
|
|
command = "$link_command && $toc_command && $replace_command"
|
|
if (defined(invoker.postsolink)) {
|
|
command += " && " + invoker.postsolink
|
|
}
|
|
rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix"
|
|
|
|
description = "SOLINK $sofile"
|
|
|
|
# Use this for {{output_extension}} expansions unless a target manually
|
|
# overrides it (in which case {{output_extension}} will be what the target
|
|
# specifies).
|
|
default_output_extension = ".so"
|
|
if (defined(invoker.default_output_extension)) {
|
|
default_output_extension = invoker.default_output_extension
|
|
}
|
|
|
|
output_prefix = "lib"
|
|
|
|
# Since the above commands only updates the .TOC file when it changes, ask
|
|
# Ninja to check if the timestamp actually changed to know if downstream
|
|
# dependencies should be recompiled.
|
|
restat = true
|
|
|
|
# Tell GN about the output files. It will link to the sofile but use the
|
|
# tocfile for dependency management.
|
|
outputs = [
|
|
sofile,
|
|
tocfile,
|
|
]
|
|
if (defined(invoker.solink_outputs)) {
|
|
outputs += invoker.solink_outputs
|
|
}
|
|
link_output = sofile
|
|
depend_output = tocfile
|
|
}
|
|
|
|
tool("link") {
|
|
exename = "{{target_output_name}}{{output_extension}}"
|
|
outfile = "{{root_out_dir}}/$exename"
|
|
rspfile = "$outfile.rsp"
|
|
|
|
if (defined(invoker.strip) || defined(invoker.llvm_objcopy)) {
|
|
stripped_outfile = "{{root_out_dir}}/exe.stripped/$exename"
|
|
}
|
|
|
|
command = "$ld {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postfix"
|
|
if (defined(invoker.strip)) {
|
|
strip = invoker.strip
|
|
strip_command =
|
|
"${strip} --strip-unneeded -o $stripped_outfile $outfile"
|
|
command += " && " + strip_command
|
|
} else if (defined(invoker.llvm_objcopy)) {
|
|
strip = invoker.llvm_objcopy
|
|
if (defined(invoker.llvm_objcopy_extra_args)) {
|
|
extra_args = invoker.llvm_objcopy_extra_args
|
|
} else {
|
|
extra_args = ""
|
|
}
|
|
strip_command =
|
|
"${strip} --strip-all ${extra_args} $outfile $stripped_outfile"
|
|
command += " && " + strip_command
|
|
}
|
|
if (defined(invoker.postlink)) {
|
|
command += " && " + invoker.postlink
|
|
}
|
|
description = "LINK $outfile"
|
|
rspfile_content = "{{inputs}}"
|
|
outputs = [ outfile ]
|
|
if (defined(invoker.strip) || defined(invoker.llvm_objcopy)) {
|
|
outputs += [ stripped_outfile ]
|
|
}
|
|
if (defined(invoker.link_outputs)) {
|
|
outputs += invoker.link_outputs
|
|
}
|
|
}
|
|
|
|
tool("stamp") {
|
|
command = "touch {{output}}"
|
|
description = "STAMP {{output}}"
|
|
}
|
|
|
|
tool("copy") {
|
|
command = "ln -f {{source}} {{output}} 2>/dev/null || (rm -rf {{output}} && cp -af {{source}} {{output}})"
|
|
description = "COPY {{source}} {{output}}"
|
|
}
|
|
|
|
# When invoking this toolchain not as the default one, these args will be
|
|
# passed to the build. They are ignored when this is the default toolchain.
|
|
toolchain_args = {
|
|
current_cpu = invoker.toolchain_cpu
|
|
current_os = invoker.toolchain_os
|
|
|
|
# These values need to be passed through unchanged.
|
|
target_os = target_os
|
|
target_cpu = target_cpu
|
|
|
|
if (defined(invoker.is_clang)) {
|
|
is_clang = invoker.is_clang
|
|
}
|
|
}
|
|
|
|
if (defined(invoker.deps)) {
|
|
deps = invoker.deps
|
|
}
|
|
}
|
|
}
|