GN: Use lib.unstripped rather than lib.stripped. Add a toolchain.gni
toolchain.gni introduces: root_shlib_dir, shlib_prefix, and shlib_extension The original goal of this change was to put shlibs under lib/ for Linux / Android, since that's where GYP puts them. However, the lack of support for loadable_module (or more specifically - per target output directory) in GN makes this infeasible at the moment. This change also mitigates a subtle bug where on Android the unstripped .so is used mistakenly instead of the lib.stripped/ version. It also fixes shlib's link_output being set to the unstripped .so rather than the stripped .so (on Android). BUG=509771 Review URL: https://codereview.chromium.org/1236503002 Cr-Original-Commit-Position: refs/heads/master@{#342697} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: c3cd5e6fe977af4a3c8b20ccb332896b2c888354
This commit is contained in:
Родитель
faced743d1
Коммит
e8e1d878ba
|
@ -30,7 +30,7 @@ action("cpplib_stripped") {
|
|||
_strip_bin = "${android_tool_prefix}strip"
|
||||
_soname = "libc++_shared.so"
|
||||
_input_so = "${android_libcpp_root}/libs/${android_app_abi}/${_soname}"
|
||||
_output_so = "${root_out_dir}/lib.stripped/${_soname}"
|
||||
_output_so = "${root_shlib_dir}/${_soname}"
|
||||
|
||||
script = "//build/gn_run_binary.py"
|
||||
inputs = [
|
||||
|
|
|
@ -167,12 +167,8 @@ if (is_android) {
|
|||
android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++"
|
||||
if (is_component_build) {
|
||||
android_libcpp_library = "c++_shared"
|
||||
# By appending .cr, we prevent name collisions with libraries already
|
||||
# loaded by the Android zygote.
|
||||
android_product_extension = ".cr.so"
|
||||
} else {
|
||||
android_libcpp_library = "c++_static"
|
||||
android_product_extension = ".so"
|
||||
}
|
||||
|
||||
# ABI ------------------------------------------------------------------------
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import("//base/android/linker/config.gni")
|
||||
import("//build/config/android/config.gni")
|
||||
import("//build/config/android/internal_rules.gni")
|
||||
import("//build/toolchain/toolchain.gni")
|
||||
import("//third_party/android_platform/config.gni")
|
||||
import("//tools/grit/grit_rule.gni")
|
||||
|
||||
|
@ -1438,7 +1439,7 @@ template("android_apk") {
|
|||
}
|
||||
|
||||
if (is_component_build) {
|
||||
_native_libs += [ "$root_out_dir/lib.stripped/libc++_shared.so" ]
|
||||
_native_libs += [ "$root_shlib_dir/libc++_shared.so" ]
|
||||
_chromium_linker_dep += [ "//build/android:cpplib_stripped" ]
|
||||
}
|
||||
|
||||
|
@ -1447,12 +1448,13 @@ template("android_apk") {
|
|||
process_file_template(invoker.native_libs, "{{source_name_part}}")
|
||||
_native_libs += process_file_template(
|
||||
_first_ext_removed,
|
||||
"$root_build_dir/lib.stripped/{{source_name_part}}$android_product_extension")
|
||||
"$root_shlib_dir/{{source_name_part}}$shlib_extension")
|
||||
|
||||
_native_libs_dir = base_path + "/libs"
|
||||
|
||||
if (_use_chromium_linker) {
|
||||
_native_libs += [ "$root_build_dir/lib.stripped/libchromium_android_linker$android_product_extension" ]
|
||||
_native_libs +=
|
||||
[ "$root_shlib_dir/libchromium_android_linker$shlib_extension" ]
|
||||
}
|
||||
|
||||
_enable_relocation_packing = false
|
||||
|
@ -1663,7 +1665,7 @@ template("android_apk") {
|
|||
|
||||
skip_packing_list = [
|
||||
"gdbserver",
|
||||
"libchromium_android_linker$android_product_extension",
|
||||
"libchromium_android_linker$shlib_extension",
|
||||
]
|
||||
|
||||
enable_packing_arg = 0
|
||||
|
@ -1947,7 +1949,7 @@ template("unittest_apk") {
|
|||
if (defined(invoker.unittests_binary)) {
|
||||
unittests_binary = invoker.unittests_binary
|
||||
} else {
|
||||
unittests_binary = "lib${test_suite_name}${android_product_extension}"
|
||||
unittests_binary = "lib${test_suite_name}${shlib_extension}"
|
||||
}
|
||||
|
||||
if (defined(invoker.apk_name)) {
|
||||
|
@ -2081,7 +2083,7 @@ template("android_aidl") {
|
|||
# Example
|
||||
# create_native_executable_dist("foo_dist") {
|
||||
# dist_dir = "$root_build_dir/foo_dist"
|
||||
# binary = "$root_build_dir/exe.stripped/foo"
|
||||
# binary = "$root_build_dir/foo"
|
||||
# deps = [ ":the_thing_that_makes_foo" ]
|
||||
# }
|
||||
template("create_native_executable_dist") {
|
||||
|
@ -2100,7 +2102,6 @@ template("create_native_executable_dist") {
|
|||
find_deps_target_name = "${template_name}__find_library_dependencies"
|
||||
copy_target_name = "${template_name}__copy_libraries_and_exe"
|
||||
|
||||
stripped_libraries_dir = "$root_build_dir/lib.stripped"
|
||||
action(find_deps_target_name) {
|
||||
visibility = [ ":$copy_target_name" ]
|
||||
|
||||
|
@ -2120,7 +2121,7 @@ template("create_native_executable_dist") {
|
|||
rebase_path(depfile, root_build_dir),
|
||||
"--input-libraries=$rebased_binaries",
|
||||
"--libraries-dir",
|
||||
rebase_path(stripped_libraries_dir, root_build_dir),
|
||||
rebase_path(root_shlib_dir, root_build_dir),
|
||||
"--output",
|
||||
rebase_path(libraries_list, root_build_dir),
|
||||
"--readelf",
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/toolchain/toolchain.gni")
|
||||
|
||||
# This config causes functions not to be automatically exported from shared
|
||||
# libraries. By default, all symbols are exported but this means there are
|
||||
# lots of exports that slow everything down. In general we explicitly mark
|
||||
|
@ -26,11 +28,15 @@ config("executable_ldconfig") {
|
|||
"-Wl,-z,nocopyreloc",
|
||||
]
|
||||
} else {
|
||||
# Android doesn't support rpath.
|
||||
# Note: Android doesn't support rpath.
|
||||
rpath_link = ""
|
||||
if (shlib_subdir != ".") {
|
||||
rpath_link = "${shlib_subdir}/"
|
||||
}
|
||||
ldflags = [
|
||||
# Want to pass "\$". GN will re-escape as required for ninja.
|
||||
"-Wl,-rpath=\$ORIGIN/",
|
||||
"-Wl,-rpath-link=",
|
||||
"-Wl,-rpath=\$ORIGIN/${rpath_link}",
|
||||
"-Wl,-rpath-link=${rpath_link}",
|
||||
|
||||
# Newer binutils don't set DT_RPATH unless you disable "new" dtags
|
||||
# and the new DT_RUNPATH doesn't work without --no-as-needed flag.
|
||||
|
|
|
@ -64,32 +64,10 @@ template("android_gcc_toolchain") {
|
|||
ld = cxx
|
||||
readelf = compiler_prefix + tool_prefix + "readelf"
|
||||
nm = compiler_prefix + tool_prefix + "nm"
|
||||
strip = "${tool_prefix}strip"
|
||||
|
||||
toolchain_os = "android"
|
||||
toolchain_cpu = invoker.toolchain_cpu
|
||||
|
||||
# We make the assumption that the gcc_toolchain will produce a soname with
|
||||
# the following definition.
|
||||
soname = "{{target_output_name}}{{output_extension}}"
|
||||
|
||||
stripped_soname = "lib.stripped/${soname}"
|
||||
temp_stripped_soname = "${stripped_soname}.tmp"
|
||||
|
||||
android_strip = "${tool_prefix}strip"
|
||||
|
||||
strip_command =
|
||||
"$android_strip --strip-unneeded -o $temp_stripped_soname $soname"
|
||||
replace_command = "if ! cmp -s $temp_stripped_soname $stripped_soname; then mv $temp_stripped_soname $stripped_soname; fi"
|
||||
postsolink = "$strip_command && $replace_command"
|
||||
solink_outputs = [ stripped_soname ]
|
||||
default_output_extension = android_product_extension
|
||||
|
||||
# We make the assumption that the gcc_toolchain will produce an exe with
|
||||
# the following definition.
|
||||
exe = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
|
||||
stripped_exe = "exe.stripped/$exe"
|
||||
postlink = "$android_strip --strip-unneeded -o $stripped_exe $exe"
|
||||
link_outputs = [ stripped_exe ]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/toolchain/toolchain.gni")
|
||||
|
||||
# This value will be inherited in the toolchain below.
|
||||
concurrent_links = exec_script("get_concurrent_links.py", [], "value")
|
||||
|
||||
|
@ -34,6 +36,11 @@ concurrent_links = exec_script("get_concurrent_links.py", [], "value")
|
|||
# - deps
|
||||
# Just forwarded to the toolchain definition.
|
||||
# - is_clang
|
||||
# Whether to use clang instead of gcc.
|
||||
# - strip
|
||||
# Location of the strip executable. When specified, strip will be run on
|
||||
# all shared libraries and executables as they are built. The pre-stripped
|
||||
# artifacts will be put in lib.stripped/ and exe.stripped/.
|
||||
template("gcc_toolchain") {
|
||||
toolchain(target_name) {
|
||||
assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value")
|
||||
|
@ -138,24 +145,34 @@ template("gcc_toolchain") {
|
|||
tool("solink") {
|
||||
soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
|
||||
sofile = "{{root_out_dir}}/$soname" # Possibly including toolchain dir.
|
||||
if (shlib_subdir != ".") {
|
||||
sofile = "{{root_out_dir}}/$shlib_subdir/$soname"
|
||||
}
|
||||
rspfile = sofile + ".rsp"
|
||||
|
||||
unstripped_sofile = sofile
|
||||
if (defined(invoker.strip)) {
|
||||
unstripped_sofile = "{{root_out_dir}}/lib.unstripped/$soname"
|
||||
}
|
||||
|
||||
# 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"
|
||||
|
||||
link_command = "$ld -shared {{ldflags}} -o $unstripped_sofile -Wl,-soname=$soname @$rspfile"
|
||||
assert(defined(readelf), "to solink you must have a readelf")
|
||||
assert(defined(nm), "to solink you must have an nm")
|
||||
toc_command = "{ $readelf -d $sofile | grep SONAME ; $nm -gD -f p $sofile | cut -f1-2 -d' '; } > $temporary_tocname"
|
||||
toc_command = "{ $readelf -d $unstripped_sofile | grep SONAME ; $nm -gD -f p $unstripped_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
|
||||
if (defined(invoker.strip)) {
|
||||
strip_command =
|
||||
"${invoker.strip} --strip-unneeded -o $sofile $unstripped_sofile"
|
||||
command += " && " + strip_command
|
||||
}
|
||||
rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive $solink_libs_section_prefix {{libs}} $solink_libs_section_postfix"
|
||||
|
||||
|
@ -164,7 +181,7 @@ template("gcc_toolchain") {
|
|||
# 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"
|
||||
default_output_extension = shlib_extension
|
||||
if (defined(invoker.default_output_extension)) {
|
||||
default_output_extension = invoker.default_output_extension
|
||||
}
|
||||
|
@ -182,27 +199,35 @@ template("gcc_toolchain") {
|
|||
sofile,
|
||||
tocfile,
|
||||
]
|
||||
if (defined(invoker.solink_outputs)) {
|
||||
outputs += invoker.solink_outputs
|
||||
if (sofile != unstripped_sofile) {
|
||||
outputs += [ unstripped_sofile ]
|
||||
}
|
||||
link_output = sofile
|
||||
depend_output = tocfile
|
||||
}
|
||||
|
||||
tool("link") {
|
||||
outfile = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
|
||||
exename = "{{target_output_name}}{{output_extension}}"
|
||||
outfile = "{{root_out_dir}}/$exename"
|
||||
rspfile = "$outfile.rsp"
|
||||
command = "$ld {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postfix"
|
||||
if (defined(invoker.postlink)) {
|
||||
command += " && " + invoker.postlink
|
||||
unstripped_outfile = outfile
|
||||
if (defined(invoker.strip)) {
|
||||
unstripped_outfile = "{{root_out_dir}}/exe.unstripped/$exename"
|
||||
}
|
||||
|
||||
command = "$ld {{ldflags}} -o $unstripped_outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group $libs_section_prefix {{libs}} $libs_section_postfix"
|
||||
if (defined(invoker.strip)) {
|
||||
strip_command =
|
||||
"${invoker.strip} --strip-unneeded -o $outfile $unstripped_outfile"
|
||||
command += " && " + strip_command
|
||||
}
|
||||
description = "LINK $outfile"
|
||||
rspfile_content = "{{inputs}}"
|
||||
outputs = [
|
||||
outfile,
|
||||
]
|
||||
if (defined(invoker.link_outputs)) {
|
||||
outputs += invoker.link_outputs
|
||||
if (outfile != unstripped_outfile) {
|
||||
outputs += [ unstripped_outfile ]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2015 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.
|
||||
|
||||
# Toolchain-related configuration that may be needed outside the context of the
|
||||
# toolchain() rules themselves.
|
||||
|
||||
# Subdirectory within root_out_dir for shared library files.
|
||||
# TODO(agrieve): GYP sets this to "lib" for Linux & Android, but this won't work
|
||||
# in GN until support for loadable_module() is added.
|
||||
# See: https://codereview.chromium.org/1236503002/
|
||||
shlib_subdir = "."
|
||||
|
||||
# Root out dir for shared library files.
|
||||
root_shlib_dir = root_out_dir
|
||||
if (shlib_subdir != ".") {
|
||||
root_shlib_dir += "/$shlib_subdir"
|
||||
}
|
||||
|
||||
# Extension for shared library files (including leading dot).
|
||||
if (is_mac || is_ios) {
|
||||
shlib_extension = ".dylib"
|
||||
} else if (is_android && is_component_build) {
|
||||
# By appending .cr, we prevent name collisions with libraries already
|
||||
# loaded by the Android zygote.
|
||||
shlib_extension = ".cr.so"
|
||||
} else if (is_posix) {
|
||||
shlib_extension = ".so"
|
||||
} else if (is_win) {
|
||||
shlib_extension = ".dll"
|
||||
} else {
|
||||
assert(false, "Platform not supported")
|
||||
}
|
||||
|
||||
# Prefix for shared library files.
|
||||
if (is_posix) {
|
||||
shlib_prefix = "lib"
|
||||
} else {
|
||||
shlib_prefix = ""
|
||||
}
|
|
@ -147,8 +147,7 @@ template("msvc_toolchain") {
|
|||
|
||||
tool("solink") {
|
||||
dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g. foo.dll
|
||||
libname =
|
||||
"{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g. foo.dll.lib
|
||||
libname = "${dllname}.lib" # e.g. foo.dll.lib
|
||||
rspfile = "${dllname}.rsp"
|
||||
|
||||
link_command = "$python_path gyp-win-tool link-wrapper $env False link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile"
|
||||
|
|
Загрузка…
Ссылка в новой задаче