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:
agrieve 2015-08-10 14:17:56 -07:00 коммит произвёл Commit bot
Родитель faced743d1
Коммит e8e1d878ba
8 изменённых файлов: 100 добавлений и 55 удалений

Просмотреть файл

@ -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 ]
}
}

40
toolchain/toolchain.gni Normal file
Просмотреть файл

@ -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"