Use source_sets in component builds and static_library in release builds.
Static libraries don't guarantee that an exported symbol gets linked
into a shared library (and in order to support Chromium's component
build mode, WebRTC needs to be linked as a shared library).
Source sets always pass all the object files to the linker.
On the flip side, source_sets link more object files in release builds
and to avoid this, this CL introduces a the GN template "rtc_library" that
expands to static_library during release builds and to source_set during
component builds.
See: https://gn.googlesource.com/gn/+/master/docs/reference.md#func_source_set
Bug: webrtc:9419
Change-Id: I4667e820c2b3fcec417becbd2034acc13e4f04fe
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157168
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Nico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#29525}
diff --git a/webrtc.gni b/webrtc.gni
index 2e6ccc8..6033764 100644
--- a/webrtc.gni
+++ b/webrtc.gni
@@ -300,17 +300,22 @@
suppressed_configs = []
}
+set_defaults("rtc_library") {
+ configs = rtc_add_configs
+ suppressed_configs = []
+}
+
set_defaults("rtc_source_set") {
configs = rtc_add_configs
suppressed_configs = []
}
-set_defaults("rtc_executable") {
+set_defaults("rtc_static_library") {
configs = rtc_add_configs
suppressed_configs = []
}
-set_defaults("rtc_static_library") {
+set_defaults("rtc_executable") {
configs = rtc_add_configs
suppressed_configs = []
}
@@ -485,46 +490,6 @@
}
}
-template("rtc_executable") {
- executable(target_name) {
- forward_variables_from(invoker,
- "*",
- [
- "deps",
- "configs",
- "public_configs",
- "suppressed_configs",
- "visibility",
- ])
- forward_variables_from(invoker, [ "visibility" ])
- if (!defined(visibility)) {
- visibility = webrtc_default_visibility
- }
- configs += invoker.configs
- configs -= rtc_remove_configs
- configs -= invoker.suppressed_configs
- deps = invoker.deps
-
- public_configs = [
- rtc_common_inherited_config,
- absl_include_config,
- absl_define_config,
- ]
- if (defined(testonly) && testonly) {
- public_configs += [ absl_flags_config ]
- }
- if (defined(invoker.public_configs)) {
- public_configs += invoker.public_configs
- }
- if (is_win) {
- deps += [
- # Give executables the default manifest on Windows (a no-op elsewhere).
- "//build/win:default_exe_manifest",
- ]
- }
- }
-}
-
template("rtc_static_library") {
static_library(target_name) {
forward_variables_from(invoker,
@@ -600,6 +565,143 @@
}
}
+# This template automatically switches the target type between source_set
+# and static_library.
+#
+# This should be the default target type for all the WebRTC targets with
+# one exception. Do not use this template for header only targets, in that case
+# rtc_source_set must be used in order to avoid build errors (e.g. libtool
+# complains if the output .a file is empty).
+#
+# How does it work:
+# Since all files in a source_set are linked into a final binary, while files
+# in a static library are only linked in if at least one symbol in them is
+# referenced, in component builds source_sets are easy to deal with because
+# all their object files are passed to the linker to create a shared library.
+# In release builds instead, static_libraries are preferred since they allow
+# the linker to discard dead code.
+# For the same reason, testonly targets will always be expanded to
+# source_set in order to be sure that tests are present in the test binary.
+template("rtc_library") {
+ if (is_component_build || (defined(invoker.testonly) && invoker.testonly)) {
+ target_type = "source_set"
+ } else {
+ target_type = "static_library"
+ }
+ target(target_type, target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "configs",
+ "public_configs",
+ "suppressed_configs",
+ "visibility",
+ ])
+ forward_variables_from(invoker, [ "visibility" ])
+ if (!defined(visibility)) {
+ visibility = webrtc_default_visibility
+ }
+
+ # What's your poison?
+ if (defined(testonly) && testonly) {
+ assert(!defined(poisonous))
+ assert(!defined(allow_poison))
+ } else {
+ if (!defined(poisonous)) {
+ poisonous = []
+ }
+ if (!defined(allow_poison)) {
+ allow_poison = []
+ }
+ if (!defined(assert_no_deps)) {
+ assert_no_deps = []
+ }
+ if (!defined(deps)) {
+ deps = []
+ }
+ foreach(p, poisonous) {
+ deps += [ webrtc_root + ":poison_" + p ]
+ }
+ foreach(poison_type, all_poison_types) {
+ allow_dep = true
+ foreach(v, visibility) {
+ if (v == "*") {
+ allow_dep = false
+ }
+ }
+ foreach(p, allow_poison + poisonous) {
+ if (p == poison_type) {
+ allow_dep = true
+ }
+ }
+ if (!allow_dep) {
+ assert_no_deps += [ webrtc_root + ":poison_" + poison_type ]
+ }
+ }
+ }
+
+ if (!defined(testonly) || !testonly) {
+ configs += rtc_prod_configs
+ }
+
+ configs += invoker.configs
+ configs += rtc_library_impl_config
+ configs -= rtc_remove_configs
+ configs -= invoker.suppressed_configs
+ public_configs = [
+ rtc_common_inherited_config,
+ absl_include_config,
+ absl_define_config,
+ ]
+ if (defined(testonly) && testonly) {
+ public_configs += [ absl_flags_config ]
+ }
+ if (defined(invoker.public_configs)) {
+ public_configs += invoker.public_configs
+ }
+ }
+}
+
+template("rtc_executable") {
+ executable(target_name) {
+ forward_variables_from(invoker,
+ "*",
+ [
+ "deps",
+ "configs",
+ "public_configs",
+ "suppressed_configs",
+ "visibility",
+ ])
+ forward_variables_from(invoker, [ "visibility" ])
+ if (!defined(visibility)) {
+ visibility = webrtc_default_visibility
+ }
+ configs += invoker.configs
+ configs -= rtc_remove_configs
+ configs -= invoker.suppressed_configs
+ deps = invoker.deps
+
+ public_configs = [
+ rtc_common_inherited_config,
+ absl_include_config,
+ absl_define_config,
+ ]
+ if (defined(testonly) && testonly) {
+ public_configs += [ absl_flags_config ]
+ }
+ if (defined(invoker.public_configs)) {
+ public_configs += invoker.public_configs
+ }
+ if (is_win) {
+ deps += [
+ # Give executables the default manifest on Windows (a no-op elsewhere).
+ "//build/win:default_exe_manifest",
+ ]
+ }
+ }
+}
+
template("rtc_shared_library") {
shared_library(target_name) {
forward_variables_from(invoker,