Skip to content

Commit

Permalink
Separate toolchains for shared libraries
Browse files Browse the repository at this point in the history
1. Added `toolchain_suite` template and switched toolchain definitions
to it, so now each toolchain definition defines a regular and
`_shared` toolchain, with different values for `is_shared_library`
argument.
2. Changed the logic of choosing between `fPIC` and `fPIE` based on
`is_shared_library` arg.
3. Changed `shared_library` template to define a group, depending on
the same target in a shared toolchain, and a copy of an output
artifact.
4. Made a copy of `runtime:dart_shared_lib` config and add it
automatically to all shared libraries.
5. Removed `runtime:dart_shared_lib` config and `DART_SHARED_LIB`
define from existing `shared_library` targets.

This CL should be a no-op refactoring to enable
https://dart-review.googlesource.com/c/sdk/+/394102.

TEST=ci

Change-Id: I6c044254d8e74b6b3ddadbf784e58d5f641fbcf3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392661
Commit-Queue: Ivan Inozemtsev <[email protected]>
Reviewed-by: Ryan Macnak <[email protected]>
  • Loading branch information
iinozemtsev authored and Commit Queue committed Nov 26, 2024
1 parent 3f8255d commit a999cec
Show file tree
Hide file tree
Showing 16 changed files with 1,061 additions and 824 deletions.
134 changes: 132 additions & 2 deletions build/config/BUILDCONFIG.gn
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ declare_args() {
# protobuf-gn fails to build if this argument isn't defined. This should never
# be set to true, becuase we never build within the Fuchsia tree.
is_fuchsia_tree = false

# Set to true when compiling in a _shared toolchain, used for
# building shared libraries.
is_shared_library = false
}

# =============================================================================
Expand Down Expand Up @@ -258,6 +262,11 @@ if (use_flutter_cxx) {
]
}

if (is_shared_library) {
# Always enable DART_EXPORT in shared toolchain.
_native_compiler_configs += [ "//build/config/compiler:dart_shared_lib" ]
}

if (is_win) {
_native_compiler_configs += [
"//build/config/win:lean_and_mean",
Expand Down Expand Up @@ -456,15 +465,14 @@ if (is_win) {
}
}

# Sets default dependencies for executable and shared_library targets.
# Sets default dependencies for executable and loadable_module targets.
#
# Variables
# no_default_deps: If true, no standard dependencies will be added.
foreach(_target_type,
[
"executable",
"loadable_module",
"shared_library",
]) {
template(_target_type) {
target(_target_type, target_name) {
Expand All @@ -487,6 +495,128 @@ foreach(_target_type,
}
}

if (!is_shared_library) {
# In the main toolchain, shared_library defined as a group with two targets:
#
# - same library in the _shared toolcahin
# - copy of the built library from a toolchain output folder into
# the main output folder
template("shared_library") {
original_target_name = target_name
copy_target_name = "${target_name}_copy"
shared_toolchain_target_name =
"${original_target_name}(${current_toolchain}_shared)"

copy(copy_target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
if (defined(visibility)) {
visibility += [ ":$original_target_name" ]
}

deps = [ ":$shared_toolchain_target_name" ]

# Calculate an output file name produced by an shared library.
# Inspired by Fuchsia build config
# https://cs.opensource.google/fuchsia/fuchsia/+/main:build/config/BUILDCONFIG.gn;l=3183;drc=86dcff138700c76441db8592b39de7b3997a0050
output_name = original_target_name
if (defined(invoker.output_name)) {
output_name = invoker.output_name
}

output_prefix = "lib"
if (!defined(output_extension)) {
if (current_os == "mac" || current_os == "ios") {
output_extension = "dylib"
} else if (current_os == "win") {
output_extension = "dll"
output_prefix = ""
} else if (current_os == "unknown" && current_cpu == "wasm32") {
output_extension = "wasm"
} else {
output_extension = "so"
}
}

output_file_name = "$output_prefix$output_name"
if (output_extension != "") {
output_file_name += ".$output_extension"
}

local_out_dir = root_out_dir
shared_out_dir = get_label_info(deps[0], "root_out_dir")
if (defined(invoker.output_dir)) {
local_out_dir = invoker.output_dir

# If invoker.output_dir is not root_build_dir, assume it is a
# sub-directory of root_out_dir, and adjust the source path accordingly
# (e.g. "<toolchain>/foo" -> "<toolchain>-<variant>/foo").
if (local_out_dir != root_build_dir) {
relative_dir =
rebase_path(local_out_dir, root_out_dir, root_build_dir)
shared_out_dir = "$shared_out_dir/$relative_dir"
}
}

sources = [ "$shared_out_dir/$output_file_name" ]
outputs = [ "$local_out_dir/$output_file_name" ]
}

group(target_name) {
public_deps = [
":$copy_target_name",
":$shared_toolchain_target_name",
]
}
not_needed(invoker, "*")
}
} else {
# In the -shared toolchain, shared_library is just its normal self,
# but if the invoker constrained the visibility, we must make sure
# the dependency from the main toolchain is still allowed.
template("shared_library") {
shared_library(target_name) {
# original_target_name = target_name
forward_variables_from(invoker, [ "visibility" ])
forward_variables_from(invoker,
"*",
[
"no_default_deps",
"visibility",
])
if (!defined(output_dir)) {
output_dir = root_out_dir
}
if (!defined(output_name)) {
output_name = target_name
}

# target_name = original_target_name
if (defined(visibility)) {
visibility += [ ":$target_name" ]
}
if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) {
if (!defined(deps)) {
deps = []
}

if (use_flutter_cxx) {
deps += [ "//third_party/libcxx" ]
}
if (is_fuchsia) {
deps += [
"//build/fuchsia/config/clang:c++-runtime-deps",
"//third_party/fuchsia/gn-sdk/src/config:runtime_library_group",
]
}
}
}
}
}

# ==============================================================================
# COMPONENT SETUP
# ==============================================================================
Expand Down
12 changes: 5 additions & 7 deletions build/config/compiler/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,7 @@ config("compiler") {
}

if (is_android || is_linux || is_mac || is_ios || is_fuchsia) {
if (use_flutter_cxx) {
# shared_library_config isn't transitive, so we don't automatically get
# another versions of libcxx with and without -fPIC. Properly setting this
# up so only shard libraries pay the extra cost fPIC over fPIE means
# something like separate GN toolchains like in the Fuchsia GN build. For
# now, globally enabling fPIC is okay because it is limited to test-only
# builds.
if (is_shared_library) {
cflags += [ "-fPIC" ]
ldflags += [ "-fPIC" ]
} else {
Expand Down Expand Up @@ -916,3 +910,7 @@ config("symbols") {
]
}
}

config("dart_shared_lib") {
defines = [ "DART_SHARED_LIB" ]
}
8 changes: 5 additions & 3 deletions build/config/sysroot.gni
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ if (is_linux) {
target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-x86_64",
root_build_dir)
} else if (current_cpu == "arm") {
target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-armv7",
root_build_dir)
target_sysroot =
rebase_path("//buildtools/sysroot/alpine-linux-armv7", root_build_dir)
} else if (current_cpu == "arm64") {
target_sysroot = rebase_path("//buildtools/sysroot/alpine-linux-aarch64",
root_build_dir)
Expand All @@ -50,7 +50,9 @@ if (is_linux) {
}

if ((current_toolchain == host_toolchain ||
current_toolchain == default_toolchain) && target_sysroot != "") {
current_toolchain == default_toolchain ||
current_toolchain == "${default_toolchain}_shared") &&
target_sysroot != "") {
sysroot = target_sysroot
} else if (is_android) {
import("//build/config/android/config.gni")
Expand Down
92 changes: 10 additions & 82 deletions build/toolchain/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,31 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/config/sysroot.gni") # Imports android/config.gni.
import("//build/toolchain/ccache.gni")
import("//build/toolchain/gcc_toolchain.gni")
import("//build/toolchain/rbe.gni")
import("//build/toolchain/toolchain_suite.gni")

# The Android GCC toolchains share most of the same parameters, so we have this
# wrapper around gcc_toolchain to avoid duplication of logic.
#
# Parameters:
# - android_ndk_lib_dir
# Libraries for this architecture
# - tool_prefix
# Prefix to be added to the tool names.
# - toolchain_cpu
# Same as gcc_toolchain
template("android_toolchain") {
gcc_toolchain(target_name) {
if (use_rbe) {
compiler_args =
rewrapper_args + [ "--labels=type=compile,compiler=clang,lang=cpp" ]

# TODO: Unfortunately I see no way to get build_arch reliably.
if (rbe_os != host_os) {
compiler_args += [
"--inputs=build/rbe,buildtools/$rbe_os-$rbe_cpu/clang/bin/llvm",
"--remote_wrapper=../../build/rbe/llvm.sh",
]
}
assembler_prefix = ""
compiler_prefix = string_join(" ", compiler_args) + " "
link_prefix = ""
} else if (use_ccache) {
assembler_prefix = "ccache "
compiler_prefix = "ccache "
link_prefix = "ccache "
} else {
assembler_prefix = ""
compiler_prefix = ""
link_prefix = ""
}

is_clang = true
prefix = rebase_path(
"${android_ndk_root}/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}/bin",
root_build_dir)

cc = "${compiler_prefix}${prefix}/clang"
cxx = "${compiler_prefix}${prefix}/clang++"
asm = "${assembler_prefix}${prefix}/clang"
ar = prefix + "/llvm-ar"
ld = "${link_prefix}${prefix}/clang++"
readelf = prefix + "/llvm-readelf"
nm = prefix + "/llvm-nm"
android_strip = prefix + "/llvm-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"

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 ]
template("android_toolchain_suite") {
toolchain_suite(target_name) {
toolchain_template = "android_toolchain"
forward_variables_from(invoker, "*")
}
}

android_toolchain("clang_x86") {
android_toolchain_suite("clang_x86") {
toolchain_cpu = "x86"
}

android_toolchain("clang_arm") {
android_toolchain_suite("clang_arm") {
toolchain_cpu = "arm"
}

android_toolchain("clang_x64") {
android_toolchain_suite("clang_x64") {
toolchain_cpu = "x86_64"
}

android_toolchain("clang_arm64") {
android_toolchain_suite("clang_arm64") {
toolchain_cpu = "arm64"
}

android_toolchain("clang_riscv64") {
android_toolchain_suite("clang_riscv64") {
toolchain_cpu = "riscv64"
}
Loading

0 comments on commit a999cec

Please sign in to comment.