diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/libwebrtc/build/config | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
169 files changed, 27997 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/config/BUILD.gn b/third_party/libwebrtc/build/config/BUILD.gn new file mode 100644 index 0000000000..05ae8a8c99 --- /dev/null +++ b/third_party/libwebrtc/build/config/BUILD.gn @@ -0,0 +1,391 @@ +# 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. + +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") +import("//build/config/crypto.gni") +import("//build/config/dcheck_always_on.gni") +import("//build/config/features.gni") + +# Subprojects need to override arguments in {mac,ios}_sdk_overrides.gni in their +# .gn config, but those arguments are only used on macOS. Including +# mac_sdk_overrides.gni insures that this doesn't trigger an unused argument +# warning. +import("//build/config/ios/ios_sdk_overrides.gni") +import("//build/config/mac/mac_sdk_overrides.gni") + +import("//build/config/pch.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/config/ui.gni") +import("//build/toolchain/goma.gni") +if (is_android) { + import("//build/config/android/abi.gni") +} + +# ============================================== +# PLEASE DO NOT ADD MORE THINGS TO THIS LIST +# ============================================== +# +# Legacy feature defines applied to all targets. +# +# These are applied to every single compile in the build and most of them are +# only relevant to a few files. This bloats command lines and causes +# unnecessary recompiles when flags are flipped. +# +# To pass defines to source code from the build, use the buildflag system which +# will write headers containing the defines you need. This isolates the define +# and means its definition can participate in the build graph, only recompiling +# things when it actually changes. +# +# See //build/buildflag_header.gni for instructions on generating headers. +# +# This will also allow you to scope your build flag to a BUILD.gn file (or a +# .gni file if you need it from more than one place) rather than making global +# flags. See //build/config/BUILDCONFIG.gn for advice on where to define +# build flags. +config("feature_flags") { + defines = [] + if (dcheck_always_on) { + defines += [ "DCHECK_ALWAYS_ON=1" ] + if (dcheck_is_configurable) { + defines += [ "DCHECK_IS_CONFIGURABLE" ] + } + } + if (use_udev) { + # TODO(brettw) should probably be "=1". + defines += [ "USE_UDEV" ] + } + if (use_aura) { + defines += [ "USE_AURA=1" ] + } + if (use_glib) { + defines += [ "USE_GLIB=1" ] + } + if (use_nss_certs) { + defines += [ "USE_NSS_CERTS=1" ] + } + if (use_ozone && !is_android) { + # Note that some Chrome OS builds unconditionally set |use_ozone| to true, + # but they also build some targets with the Android toolchain. This ensures + # that Android targets still build with USE_OZONE=0 in such cases. + # + # TODO(crbug.com/837032): Maybe this can be cleaned up if we can avoid + # setting use_ozone globally. + defines += [ "USE_OZONE=1" ] + } + if (use_x11) { + defines += [ "USE_X11=1" ] + } + if (is_asan || is_hwasan || is_lsan || is_tsan || is_msan) { + defines += [ "MEMORY_TOOL_REPLACES_ALLOCATOR" ] + } + if (is_asan) { + defines += [ "ADDRESS_SANITIZER" ] + } + if (is_lsan) { + defines += [ "LEAK_SANITIZER" ] + } + if (is_tsan) { + defines += [ + "THREAD_SANITIZER", + "DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1", + ] + } + if (is_msan) { + defines += [ "MEMORY_SANITIZER" ] + } + if (is_ubsan || is_ubsan_null || is_ubsan_vptr || is_ubsan_security) { + defines += [ "UNDEFINED_SANITIZER" ] + } + if (is_official_build) { + defines += [ "OFFICIAL_BUILD" ] + } + + # ============================================== + # PLEASE DO NOT ADD MORE THINGS TO THIS LIST + # ============================================== + # + # See the comment at the top. +} + +# Debug/release ---------------------------------------------------------------- + +config("debug") { + defines = [ + "DYNAMIC_ANNOTATIONS_ENABLED=1", + ] + if (!is_win) { + defines += [ "_DEBUG" ] + } + if (is_nacl) { + defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ] + } + + if (is_win) { + if (!enable_iterator_debugging && !use_custom_libcxx) { + # Iterator debugging is enabled by default by the compiler on debug + # builds, and we have to tell it to turn it off. + defines += [ "_HAS_ITERATOR_DEBUGGING=0" ] + } + } else if ((is_linux || is_chromeos) && target_cpu == "x64" && + enable_iterator_debugging) { + # Enable libstdc++ debugging facilities to help catch problems early, see + # http://crbug.com/65151 . + # TODO(phajdan.jr): Should we enable this for all of POSIX? + #defines += [ "_GLIBCXX_DEBUG=1" ] + } +} + +config("release") { + defines = [ "NDEBUG" ] + + # Sanitizers. + if (is_tsan) { + defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=1" ] + } else { + defines += [ "NVALGRIND" ] + if (!is_nacl) { + # NaCl always enables dynamic annotations. Currently this value is set to + # 1 for all .nexes. + defines += [ "DYNAMIC_ANNOTATIONS_ENABLED=0" ] + } + } + + if (is_ios) { + # Disable NSAssert and GTMDevAssert (from Google Toolbox for Mac). This + # follows XCode's default behavior for Release builds. + defines += [ "NS_BLOCK_ASSERTIONS=1" ] + } +} + +# Default libraries ------------------------------------------------------------ + +# This config defines the default libraries applied to all targets. +config("default_libs") { + if (is_win) { + # TODO(brettw) this list of defaults should probably be smaller, and + # instead the targets that use the less common ones (e.g. wininet or + # winspool) should include those explicitly. + libs = [ + "advapi32.lib", + "comdlg32.lib", + "dbghelp.lib", + "dnsapi.lib", + "gdi32.lib", + "msimg32.lib", + "odbc32.lib", + "odbccp32.lib", + "oleaut32.lib", + "shell32.lib", + "shlwapi.lib", + "user32.lib", + "usp10.lib", + "uuid.lib", + "version.lib", + "wininet.lib", + "winmm.lib", + "winspool.lib", + "ws2_32.lib", + + # Please don't add more stuff here. We should actually be making this + # list smaller, since all common things should be covered. If you need + # some extra libraries, please just add a libs = [ "foo.lib" ] to your + # target that needs it. + ] + if (current_os == "winuwp") { + # These libraries are needed for Windows UWP (i.e. store apps). + libs += [ + "dloadhelper.lib", + "WindowsApp.lib", + ] + } else { + # These libraries are not compatible with Windows UWP (i.e. store apps.) + libs += [ + "delayimp.lib", + "kernel32.lib", + "ole32.lib", + ] + } + } else if (is_android) { + libs = [ + "dl", + "m", + ] + } else if (is_mac) { + # Targets should choose to explicitly link frameworks they require. Since + # linking can have run-time side effects, nothing should be listed here. + libs = [] + } else if (is_ios) { + # The libraries listed here will be specified for both the target and the + # host. Only the common ones should be listed here. + frameworks = [ + "CoreFoundation.framework", + "CoreGraphics.framework", + "CoreText.framework", + "Foundation.framework", + ] + } else if (is_linux || is_chromeos) { + libs = [ + "dl", + "pthread", + "rt", + ] + } +} + +group("common_deps") { + visibility = [ + ":executable_deps", + ":loadable_module_deps", + ":shared_library_deps", + ] + + # WARNING: This group is a dependency of **every executable and shared + # library**. Please be careful adding new dependencies here. + public_deps = [] + + if (using_sanitizer) { + public_deps += [ "//build/config/sanitizers:deps" ] + } + + #if (use_custom_libcxx) { + # public_deps += [ "//buildtools/third_party/libc++" ] + #} + + if (use_afl) { + public_deps += [ "//third_party/afl" ] + } + + if (is_android && use_order_profiling) { + public_deps += [ "//base/android/orderfile:orderfile_instrumentation" ] + } + + if (is_fuchsia) { + public_deps += + [ "//third_party/fuchsia-sdk/sdk/build/config:runtime_library_group" ] + } +} + +# Only the executable template in BUILDCONFIG.gn should reference this. +group("executable_deps") { + public_deps = [ ":common_deps" ] + if (export_libcxxabi_from_executables) { + public_deps += [ "//buildtools/third_party/libc++abi" ] + } +} + +# Only the loadable_module template in BUILDCONFIG.gn should reference this. +group("loadable_module_deps") { + public_deps = [ ":common_deps" ] +} + +# Only the shared_library template in BUILDCONFIG.gn should reference this. +group("shared_library_deps") { + public_deps = [ ":common_deps" ] +} + +# Executable configs ----------------------------------------------------------- + +# Windows linker setup for EXEs and DLLs. +if (is_win) { + _windows_linker_configs = [ + "//build/config/win:sdk_link", + "//build/config/win:common_linker_setup", + ] +} + +# This config defines the configs applied to all executables. +config("executable_config") { + configs = [] + + if (is_win) { + configs += _windows_linker_configs + } else if (is_mac) { + configs += [ "//build/config/mac:mac_dynamic_flags" ] + } else if (is_ios) { + configs += [ + "//build/config/ios:ios_dynamic_flags", + "//build/config/ios:ios_executable_flags", + ] + } else if (is_linux || is_chromeos || is_android || current_os == "aix") { + configs += [ "//build/config/gcc:executable_config" ] + if (is_chromecast) { + configs += [ "//build/config/chromecast:executable_config" ] + } else if (is_fuchsia) { + configs += [ "//build/config/fuchsia:executable_config" ] + } + } + + # If we're using the prebuilt instrumented libraries with the sanitizers, we + # need to add ldflags to every binary to make sure they are picked up. + if (prebuilt_instrumented_libraries_available) { + configs += [ "//third_party/instrumented_libraries:prebuilt_ldflags" ] + } + if (use_locally_built_instrumented_libraries) { + configs += [ "//third_party/instrumented_libraries:locally_built_ldflags" ] + } + configs += [ "//build/config/sanitizers:link_executable" ] +} + +# Shared library configs ------------------------------------------------------- + +# This config defines the configs applied to all shared libraries. +config("shared_library_config") { + configs = [] + + if (is_win) { + configs += _windows_linker_configs + } else if (is_mac) { + configs += [ "//build/config/mac:mac_dynamic_flags" ] + } else if (is_ios) { + configs += [ + "//build/config/ios:ios_dynamic_flags", + "//build/config/ios:ios_shared_library_flags", + ] + } else if (is_chromecast) { + configs += [ "//build/config/chromecast:shared_library_config" ] + } else if (is_linux || is_chromeos || current_os == "aix") { + configs += [ "//build/config/gcc:shared_library_config" ] + } + + # If we're using the prebuilt instrumented libraries with the sanitizers, we + # need to add ldflags to every binary to make sure they are picked up. + if (prebuilt_instrumented_libraries_available) { + configs += [ "//third_party/instrumented_libraries:prebuilt_ldflags" ] + } + if (use_locally_built_instrumented_libraries) { + configs += [ "//third_party/instrumented_libraries:locally_built_ldflags" ] + } + configs += [ "//build/config/sanitizers:link_shared_library" ] +} + +# Add this config to your target to enable precompiled headers. +# +# Precompiled headers are done on a per-target basis. If you have just a couple +# of files, the time it takes to precompile (~2 seconds) can actually be longer +# than the time saved. On a Z620, a 100 file target compiles about 2 seconds +# faster with precompiled headers, with greater savings for larger targets. +# +# Recommend precompiled headers for targets with more than 50 .cc files. +config("precompiled_headers") { + if (enable_precompiled_headers) { + if (is_win) { + # This is a string rather than a file GN knows about. It has to match + # exactly what's in the /FI flag below, and what might appear in the + # source code in quotes for an #include directive. + precompiled_header = "build/precompile.h" + + # This is a file that GN will compile with the above header. It will be + # implicitly added to the sources (potentially multiple times, with one + # variant for each language used in the target). + precompiled_source = "//build/precompile.cc" + + # Force include the header. + cflags = [ "/FI$precompiled_header" ] + } else if (is_mac || is_linux) { + precompiled_source = "//build/precompile.h" + } + } +} diff --git a/third_party/libwebrtc/build/config/BUILDCONFIG.gn b/third_party/libwebrtc/build/config/BUILDCONFIG.gn new file mode 100644 index 0000000000..571ae5f0d6 --- /dev/null +++ b/third_party/libwebrtc/build/config/BUILDCONFIG.gn @@ -0,0 +1,588 @@ +# 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. + +# ============================================================================= +# WHAT IS THIS FILE? +# ============================================================================= +# +# This is the master GN build configuration. This file is loaded after the +# build args (args.gn) for the build directory and after the toplevel ".gn" +# file (which points to this file as the build configuration). +# +# This file will be executed and the resulting context will be used to execute +# every other file in the build. So variables declared here (that don't start +# with an underscore) will be implicitly global. + +# ============================================================================= +# PLATFORM SELECTION +# ============================================================================= +# +# There are two main things to set: "os" and "cpu". The "toolchain" is the name +# of the GN thing that encodes combinations of these things. +# +# Users typically only set the variables "target_os" and "target_cpu" in "gn +# args", the rest are set up by our build and internal to GN. +# +# There are three different types of each of these things: The "host" +# represents the computer doing the compile and never changes. The "target" +# represents the main thing we're trying to build. The "current" represents +# which configuration is currently being defined, which can be either the +# host, the target, or something completely different (like nacl). GN will +# run the same build file multiple times for the different required +# configuration in the same build. +# +# This gives the following variables: +# - host_os, host_cpu, host_toolchain +# - target_os, target_cpu, default_toolchain +# - current_os, current_cpu, current_toolchain. +# +# Note the default_toolchain isn't symmetrical (you would expect +# target_toolchain). This is because the "default" toolchain is a GN built-in +# concept, and "target" is something our build sets up that's symmetrical with +# its GYP counterpart. Potentially the built-in default_toolchain variable +# could be renamed in the future. +# +# When writing build files, to do something only for the host: +# if (current_toolchain == host_toolchain) { ... + +if (target_os == "") { + target_os = host_os +} + +if (target_cpu == "") { + if (target_os == "android") { + # If we're building for Android, we should assume that we want to + # build for ARM by default, not the host_cpu (which is likely x64). + # This allows us to not have to specify both target_os and target_cpu + # on the command line. + target_cpu = "arm" + } else { + target_cpu = host_cpu + } +} + +if (current_cpu == "") { + current_cpu = target_cpu +} +if (current_os == "") { + current_os = target_os +} + +# ============================================================================= +# BUILD FLAGS +# ============================================================================= +# +# This block lists input arguments to the build, along with their default +# values. +# +# If a value is specified on the command line, it will overwrite the defaults +# given in a declare_args block, otherwise the default will be used. +# +# YOU SHOULD ALMOST NEVER NEED TO ADD FLAGS TO THIS FILE. GN allows any file in +# the build to declare build flags. If you need a flag for a single component, +# you can just declare it in the corresponding BUILD.gn file. +# +# - If your feature is a single target, say //components/foo, you can put +# a declare_args() block in //components/foo/BUILD.gn and use it there. +# Nobody else in the build needs to see the flag. +# +# - Defines based on build variables should be implemented via the generated +# build flag header system. See //build/buildflag_header.gni. You can put +# the buildflag_header target in the same file as the build flag itself. You +# should almost never set "defines" directly. +# +# - If your flag toggles a target on and off or toggles between different +# versions of similar things, write a "group" target that forwards to the +# right target (or no target) depending on the value of the build flag. This +# group can be in the same BUILD.gn file as the build flag, and targets can +# depend unconditionally on the group rather than duplicating flag checks +# across many targets. +# +# - If a semi-random set of build files REALLY needs to know about a define and +# the above pattern for isolating the build logic in a forwarding group +# doesn't work, you can put the argument in a .gni file. This should be put +# in the lowest level of the build that knows about this feature (which should +# almost always be outside of the //build directory!). +# +# Other flag advice: +# +# - Use boolean values when possible. If you need a default value that expands +# to some complex thing in the default case (like the location of the +# compiler which would be computed by a script), use a default value of -1 or +# the empty string. Outside of the declare_args block, conditionally expand +# the default value as necessary. +# +# - Use a name like "use_foo" or "is_foo" (whatever is more appropriate for +# your feature) rather than just "foo". +# +# - Write good comments directly above the declaration with no blank line. +# These comments will appear as documentation in "gn args --list". +# +# - Don't call exec_script inside declare_args. This will execute the script +# even if the value is overridden, which is wasteful. See first bullet. + +declare_args() { + # Set to enable the official build level of optimization. This has nothing + # to do with branding, but enables an additional level of optimization above + # release (!is_debug). This might be better expressed as a tri-state + # (debug, release, official) but for historical reasons there are two + # separate flags. + is_official_build = false + + # Set to true when compiling with the Clang compiler. + is_clang = current_os != "linux" || current_os == "openbsd" || + (current_cpu != "s390x" && current_cpu != "s390" && + current_cpu != "ppc64" && current_cpu != "ppc" && + current_cpu != "mips" && current_cpu != "mips64" && + current_cpu != "riscv64") + + # Allows the path to a custom target toolchain to be injected as a single + # argument, and set as the default toolchain. + custom_toolchain = "" + + # This should not normally be set as a build argument. It's here so that + # every toolchain can pass through the "global" value via toolchain_args(). + host_toolchain = "" + + # DON'T ADD MORE FLAGS HERE. Read the comment above. +} + +declare_args() { + # Debug build. Enabling official builds automatically sets is_debug to false. + is_debug = !is_official_build +} + +declare_args() { + # Component build. Setting to true compiles targets declared as "components" + # as shared libraries loaded dynamically. This speeds up development time. + # When false, components will be linked statically. + # + # For more information see + # https://chromium.googlesource.com/chromium/src/+/main/docs/component_build.md + is_component_build = is_debug && current_os != "ios" +} + +assert(!(is_debug && is_official_build), "Can't do official debug builds") + +# ============================================================================== +# TOOLCHAIN SETUP +# ============================================================================== +# +# Here we set the default toolchain, as well as the variable host_toolchain +# which will identify the toolchain corresponding to the local system when +# doing cross-compiles. When not cross-compiling, this will be the same as the +# default toolchain. +# +# We do this before anything else to make sure we complain about any +# unsupported os/cpu combinations as early as possible. + +if (host_toolchain == "") { + # This should only happen in the top-level context. + # In a specific toolchain context, the toolchain_args() + # block should have propagated a value down. + # TODO(dpranke): Add some sort of assert here that verifies that + # no toolchain omitted host_toolchain from its toolchain_args(). + + if (host_os == "linux" || host_os == "openbsd") { + if (target_os != "linux") { + host_toolchain = "//build/toolchain/linux:clang_$host_cpu" + } else if (is_clang) { + host_toolchain = "//build/toolchain/linux:clang_$host_cpu" + } else { + host_toolchain = "//build/toolchain/linux:$host_cpu" + } + } else if (host_os == "mac") { + host_toolchain = "//build/toolchain/mac:clang_$host_cpu" + } else if (host_os == "win") { + # On Windows always use the target CPU for host builds for x86/x64. On the + # configurations we support this will always work and it saves build steps. + # Windows ARM64 targets require an x64 host for cross build. + if (target_cpu == "x86" || target_cpu == "x64") { + if (is_clang) { + host_toolchain = "//build/toolchain/win:win_clang_$target_cpu" + } else { + host_toolchain = "//build/toolchain/win:$target_cpu" + } + } else if (is_clang) { + host_toolchain = "//build/toolchain/win:win_clang_$host_cpu" + } else { + host_toolchain = "//build/toolchain/win:$host_cpu" + } + } else if (host_os == "aix") { + host_toolchain = "//build/toolchain/aix:$host_cpu" + } else { + assert(false, "Unsupported host_os: $host_os") + } +} + +_default_toolchain = "" + +if (target_os == "android") { + assert(host_os == "linux" || host_os == "mac", + "Android builds are only supported on Linux and Mac hosts.") + _default_toolchain = "//build/toolchain/android:android_clang_$target_cpu" +} else if (target_os == "chromeos" || target_os == "linux" || target_os == "openbsd") { + # See comments in build/toolchain/cros/BUILD.gn about board compiles. + if (is_clang) { + _default_toolchain = "//build/toolchain/linux:clang_$target_cpu" + } else { + _default_toolchain = "//build/toolchain/linux:$target_cpu" + } +} else if (target_os == "fuchsia") { + _default_toolchain = "//build/toolchain/fuchsia:$target_cpu" +} else if (target_os == "ios") { + _default_toolchain = "//build/toolchain/ios:ios_clang_$target_cpu" +} else if (target_os == "mac") { + #assert(host_os == "mac" || host_os == "linux", + # "Mac cross-compiles are unsupported.") + _default_toolchain = "//build/toolchain/mac:clang_$target_cpu" +} else if (target_os == "win") { + # On Windows, we use the same toolchain for host and target by default. + # Beware, win cross builds have some caveats, see docs/win_cross.md + if (is_clang) { + _default_toolchain = "//build/toolchain/win:win_clang_$target_cpu" + } else { + _default_toolchain = "//build/toolchain/win:$target_cpu" + } +} else if (target_os == "winuwp") { + # Only target WinUWP on for a Windows store application and only + # x86, x64 and arm are supported target CPUs. + assert(target_cpu == "x86" || target_cpu == "x64" || target_cpu == "arm" || + target_cpu == "arm64") + _default_toolchain = "//build/toolchain/win:uwp_$target_cpu" +} else if (target_os == "aix") { + _default_toolchain = "//build/toolchain/aix:$target_cpu" +} else { + assert(false, "Unsupported target_os: $target_os") +} + +# If a custom toolchain has been set in the args, set it as default. Otherwise, +# set the default toolchain for the platform (if any). +if (custom_toolchain != "") { + set_default_toolchain(custom_toolchain) +} else if (_default_toolchain != "") { + set_default_toolchain(_default_toolchain) +} + +# ============================================================================= +# OS DEFINITIONS +# ============================================================================= +# +# We set these various is_FOO booleans for convenience in writing OS-based +# conditions. +# +# - is_android, is_chromeos, is_ios, and is_win should be obvious. +# - is_mac is set only for desktop Mac. It is not set on iOS. +# - is_posix is true for mac and any Unix-like system (basically everything +# except Fuchsia and Windows). +# - is_linux is true for desktop Linux, but not for ChromeOS nor Android (which +# is generally too different despite being based on the Linux kernel). +# +# Do not add more is_* variants here for random lesser-used Unix systems like +# aix or one of the BSDs. If you need to check these, just check the +# current_os value directly. + +is_android = current_os == "android" +is_chromeos = current_os == "chromeos" +is_fuchsia = current_os == "fuchsia" +is_ios = current_os == "ios" +is_linux = current_os == "linux" +is_bsd = current_os == "openbsd" +is_mac = current_os == "mac" +is_nacl = current_os == "nacl" +is_win = current_os == "win" || current_os == "winuwp" + +is_apple = is_ios || is_mac +is_posix = !is_win && !is_fuchsia + +# ============================================================================= +# TARGET DEFAULTS +# ============================================================================= +# +# Set up the default configuration for every build target of the given type. +# The values configured here will be automatically set on the scope of the +# corresponding target. Target definitions can add or remove to the settings +# here as needed. +# +# WHAT GOES HERE? +# +# Other than the main compiler and linker configs, the only reason for a config +# to be in this list is if some targets need to explicitly override that config +# by removing it. This is how targets opt-out of flags. If you don't have that +# requirement and just need to add a config everywhere, reference it as a +# sub-config of an existing one, most commonly the main "compiler" one. + +# Holds all configs used for running the compiler. +default_compiler_configs = [ + "//build/config:feature_flags", + "//build/config/compiler:afdo", + "//build/config/compiler:afdo_optimize_size", + "//build/config/compiler:cet_shadow_stack", + "//build/config/compiler:compiler", + "//build/config/compiler:compiler_arm_fpu", + "//build/config/compiler:compiler_arm_thumb", + "//build/config/compiler:chromium_code", + "//build/config/compiler:default_include_dirs", + "//build/config/compiler:default_optimization", + "//build/config/compiler:default_stack_frames", + "//build/config/compiler:default_symbols", + "//build/config/compiler:export_dynamic", + "//build/config/compiler:no_exceptions", + "//build/config/compiler:no_rtti", + "//build/config/compiler:runtime_library", + "//build/config/compiler:thin_archive", + "//build/config/compiler:thinlto_optimize_default", + "//build/config/compiler:default_init_stack_vars", + "//build/config/compiler:no_unresolved_symbols", + "//build/config/compiler/pgo:default_pgo_flags", + "//build/config/coverage:default_coverage", + "//build/config/sanitizers:default_sanitizer_flags", +] + +if (is_win) { + default_compiler_configs += [ + "//build/config/win:default_cfg_compiler", + "//build/config/win:default_crt", + "//build/config/win:lean_and_mean", + "//build/config/win:nominmax", + "//build/config/win:unicode", + "//build/config/win:winver", + ] +} + +if (is_posix) { + if (current_os != "aix") { + default_compiler_configs += + [ "//build/config/gcc:symbol_visibility_hidden" ] + } +} + +if (is_fuchsia) { + default_compiler_configs += [ "//build/config/gcc:symbol_visibility_hidden" ] +} + +if (is_android) { + default_compiler_configs += + [ "//build/config/android:default_orderfile_instrumentation" ] +} + +if (is_clang && !is_nacl) { + default_compiler_configs += [ + "//build/config/clang:find_bad_constructs", + "//build/config/clang:extra_warnings", + ] +} + +# Debug/release-related defines. +if (is_debug) { + default_compiler_configs += [ "//build/config:debug" ] +} else { + default_compiler_configs += [ "//build/config:release" ] +} + +# Static libraries and source sets use only the compiler ones. +set_defaults("static_library") { + configs = default_compiler_configs +} +set_defaults("source_set") { + configs = default_compiler_configs +} +set_defaults("rust_library") { + configs = default_compiler_configs +} +set_defaults("rust_proc_macro") { + configs = default_compiler_configs +} + +# Compute the set of configs common to all linked targets (shared libraries, +# loadable modules, executables) to avoid duplication below. +if (is_win) { + # Many targets remove these configs, so they are not contained within + # //build/config:executable_config for easy removal. + _linker_configs = [ + "//build/config/win:default_incremental_linking", + + # Default to console-mode apps. Most of our targets are tests and such + # that shouldn't use the windows subsystem. + "//build/config/win:console", + ] +} else if (is_mac) { + _linker_configs = [ "//build/config/mac:strip_all" ] +} else { + _linker_configs = [] +} + +# Executable defaults. +default_executable_configs = default_compiler_configs + [ + "//build/config:default_libs", + "//build/config:executable_config", + ] + _linker_configs + +if (is_win) { + # Turn on linker CFI for executables, and position it so it can be removed + # if needed. + default_executable_configs += [ "//build/config/win:cfi_linker" ] +} + +set_defaults("executable") { + configs = default_executable_configs +} + +# Shared library and loadable module defaults (also for components in component +# mode). +default_shared_library_configs = default_compiler_configs + [ + "//build/config:default_libs", + "//build/config:shared_library_config", + ] + _linker_configs +if (is_win) { + # Turn on linker CFI for DLLs, and position it so it can be removed if needed. + default_shared_library_configs += [ "//build/config/win:cfi_linker" ] +} + +if (is_android) { + # Strip native JNI exports from shared libraries by default. Binaries that + # want this can remove this config. + default_shared_library_configs += + [ "//build/config/android:hide_all_but_jni_onload" ] +} +set_defaults("shared_library") { + configs = default_shared_library_configs +} +set_defaults("loadable_module") { + configs = default_shared_library_configs + + # loadable_modules are generally used by other libs, not just via JNI. + if (is_android) { + configs -= [ "//build/config/android:hide_all_but_jni_onload" ] + } +} + +# A helper for forwarding testonly and visibility. +# Forwarding "*" does not include variables from outer scopes (to avoid copying +# all globals into each template invocation), so it will not pick up +# file-scoped or outer-template-scoped variables. Normally this behavior is +# desired, but "visibility" and "testonly" are commonly defined in outer scopes. +# Explicitly forwarding them in forward_variables_from() works around this +# nuance. See //build/docs/writing_gn_templates.md#using-forward_variables_from +TESTONLY_AND_VISIBILITY = [ + "testonly", + "visibility", +] + +# Sets default dependencies for executable and shared_library targets. +# +# Variables +# no_default_deps: If true, no standard dependencies will be added. +# Targets that set this usually also want to remove +# "//build/config/compiler:runtime_library" from configs (to remove +# its subconfig "//build/config/c++:runtime_library"). +foreach(_target_type, + [ + "executable", + "loadable_module", + "shared_library", + ]) { + template(_target_type) { + # Alias "target_name" because it is clobbered by forward_variables_from(). + _target_name = target_name + target(_target_type, _target_name) { + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ "no_default_deps" ]) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + if (!defined(deps)) { + deps = [] + } + if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) { + # This pulls in one of: + # //build/config:executable_deps + # //build/config:loadable_module_deps + # //build/config:shared_library_deps + # (This explicit list is so that grepping for these configs finds where + # they are used.) + deps += [ "//build/config:${_target_type}_deps" ] + } + + # On Android, write shared library output file to metadata. We will use + # this information to, for instance, collect all shared libraries that + # should be packaged into an APK. + if (!defined(invoker.metadata) && is_android && + (_target_type == "shared_library" || + _target_type == "loadable_module")) { + _output_name = _target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + # Remove 'lib' prefix from output name if it exists. + _magic_prefix = "$0x01$0x01" + _output_name = string_replace("${_magic_prefix}${_output_name}", + "${_magic_prefix}lib", + _magic_prefix, + 1) + _output_name = string_replace(_output_name, _magic_prefix, "", 1) + + if (defined(output_extension)) { + _shlib_extension = ".$output_extension" + } else if (is_component_build && _target_type != "loadable_module") { + _shlib_extension = ".cr.so" + } else { + _shlib_extension = ".so" + } + + metadata = { + shared_libraries = + [ "$root_out_dir/lib${_output_name}${_shlib_extension}" ] + } + } + } + } +} + +# ============================================================================== +# COMPONENT SETUP +# ============================================================================== + +# Defines a component, which equates to a shared_library when +# is_component_build == true and a static_library otherwise. +# +# Use static libraries for the static build rather than source sets because +# many of of our test binaries link many large dependencies but often don't +# use large portions of them. The static libraries are much more efficient to +# link in this situation since only the necessary object files are linked. +# +# The invoker can override the type of the target in the non-component-build +# case by setting static_component_type to either "source_set" or +# "static_library". If unset, the default will be used. +template("component") { + if (is_component_build) { + _component_mode = "shared_library" + } else if (defined(invoker.static_component_type)) { + assert(invoker.static_component_type == "static_library" || + invoker.static_component_type == "source_set") + _component_mode = invoker.static_component_type + } else if (!defined(invoker.sources) || invoker.sources == []) { + # When there are no sources defined, use a source set to avoid creating + # an empty static library (which generally don't work). + _component_mode = "source_set" + } else { + _component_mode = "static_library" + } + target(_component_mode, target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } +} + +# Component defaults +set_defaults("component") { + if (is_component_build) { + configs = default_shared_library_configs + if (is_android) { + configs -= [ "//build/config/android:hide_all_but_jni_onload" ] + } + } else { + configs = default_compiler_configs + } +} diff --git a/third_party/libwebrtc/build/config/OWNERS b/third_party/libwebrtc/build/config/OWNERS new file mode 100644 index 0000000000..eeb67065c2 --- /dev/null +++ b/third_party/libwebrtc/build/config/OWNERS @@ -0,0 +1,5 @@ +dpranke@google.com +scottmg@chromium.org + +per-file ozone.gni=file://ui/ozone/OWNERS +per-file ozone_extra.gni=file://ui/ozone/OWNERS diff --git a/third_party/libwebrtc/build/config/aix/BUILD.gn b/third_party/libwebrtc/build/config/aix/BUILD.gn new file mode 100644 index 0000000000..9079f6f53e --- /dev/null +++ b/third_party/libwebrtc/build/config/aix/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright 2017 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. + +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/toolchain.gni") + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic. + +config("compiler") { + # These flags are shared between the C compiler and linker. + defines = [ + "_LINUX_SOURCE_COMPAT=1", + "__STDC_FORMAT_MACROS", + "_ALL_SOURCE=1", + ] + + cflags = [ + "-Wall", + "-Wno-unused-parameter", + "-pthread", + "-Wmissing-field-initializers", + "-Wno-uninitialized", + "-mcpu=power5+", + "-mfprnd", + "-mno-popcntb", + "-maix64", + "-fdata-sections", + "-ffunction-sections", + "-O3", + + # "-Werror" + # We need to find a way to fix the TOC warnings if we want to enable this. + ] + + cflags_cc = [ + "-fno-rtti", + "-fno-exceptions", + "-Wno-narrowing", + "-Wno-non-virtual-dtor", + ] + + ldflags = [ + "-pthread", + "-maix64", + "-Wl,-bbigtoc", + ] + + if (is_component_build) { + cflags += [ + "-fpic", + ] + ldflags += [ + "-Wl,-brtl", + # -bnoipath so that only names of .so objects are stored in loader + # section, excluding leading "./" + "-Wl,-bnoipath", + ] + } +} diff --git a/third_party/libwebrtc/build/config/android/BUILD.gn b/third_party/libwebrtc/build/config/android/BUILD.gn new file mode 100644 index 0000000000..a77a628be4 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/BUILD.gn @@ -0,0 +1,161 @@ +# Copyright 2014 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. + +import("//build/config/android/config.gni") +import("//build/config/c++/c++.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/sanitizers/sanitizers.gni") + +if (current_toolchain == default_toolchain) { + import("//build/toolchain/concurrent_links.gni") +} + +assert(is_android) + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic that is +# Android-only. +config("compiler") { + cflags = [ + "-ffunction-sections", + "-fno-short-enums", + ] + defines = [ + "ANDROID", + + # The NDK has these things, but doesn't define the constants to say that it + # does. Define them here instead. + "HAVE_SYS_UIO_H", + + # Forces full rebuilds on NDK rolls. To rebuild everything when NDK version + # stays the same, increment the suffix number. + "ANDROID_NDK_VERSION_ROLL=${android_ndk_version}_1", + ] + + if (target_cpu == "mips64el") { + cflags += [ + # Have to force IAS for mips64. + "-fintegrated-as", + ] + } + + ldflags = [ + # Don't allow visible symbols from libgcc or libc++ to be + # re-exported. + "-Wl,--exclude-libs=libgcc.a", + + # Don't allow visible symbols from libraries that contain + # assembly code with symbols that aren't hidden properly. + # http://crbug.com/448386 + "-Wl,--exclude-libs=libvpx_assembly_arm.a", + ] + + # TODO(crbug.com/1184398): Move to compiler-rt when we are ready. + ldflags += [ "--rtlib=libgcc" ] + if (target_cpu == "arm64") { + # For outline atomics on AArch64 (can't pass this unconditionally + # due to unused flag warning on other targets). + cflags += [ "--rtlib=libgcc" ] + if (arm_control_flow_integrity == "standard") { + cflags += [ "-mbranch-protection=standard" ] + } + } + + # $compile_api_level corresponds to the API level used for the sysroot path + # calculation in //build/config/android/config.gni + if (android_64bit_target_cpu) { + compile_api_level = android64_ndk_api_level + } else { + compile_api_level = android32_ndk_api_level + } + + cflags += [ "--target=$android_abi_target$compile_api_level" ] + ldflags += [ "--target=$android_abi_target$compile_api_level" ] + + # Assign any flags set for the C compiler to asmflags so that they are sent + # to the assembler. + asmflags = cflags +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Android-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + # Let the linker find libgcc.a. + ldflags = [ "--gcc-toolchain=" + + rebase_path(android_toolchain_root, root_build_dir) ] + + libs = [] + + # On 64-bit platforms, the only symbols provided by libandroid_support.a are + # strto{d,f,l,ul}_l. These symbols are not used by our libc++, and newer NDKs + # don't provide a libandroid_support.a on 64-bit platforms, so we only depend + # on this library on 32-bit platforms. + if (target_cpu == "arm" || target_cpu == "x86") { + libs += [ "android_support" ] + } + + # arm builds of libc++ starting in NDK r12 depend on unwind. + if (target_cpu == "arm") { + libs += [ "unwind" ] + } + + if (target_cpu == "arm" && arm_version == 6) { + libs += [ "atomic" ] + } + + if (target_cpu == "mipsel") { + libs += [ "atomic" ] + } + + # TODO(jdduke) Re-enable on mips after resolving linking + # issues with libc++ (crbug.com/456380). + if (target_cpu != "mipsel" && target_cpu != "mips64el") { + ldflags += [ "-Wl,--warn-shared-textrel" ] + } +} + +config("hide_all_but_jni_onload") { + ldflags = [ "-Wl,--version-script=" + rebase_path( + "//build/android/android_only_explicit_jni_exports.lst", + root_build_dir) ] +} + +config("hide_all_but_jni") { + ldflags = [ "-Wl,--version-script=" + + rebase_path("//build/android/android_only_jni_exports.lst", + root_build_dir) ] +} + +config("lld_pack_relocations") { + ldflags = [ "-Wl,--pack-dyn-relocs=android" ] +} + +# Used for instrumented build to generate the orderfile. +config("default_orderfile_instrumentation") { + if (use_order_profiling) { + cflags = [ "-finstrument-function-entry-bare" ] + if (use_thin_lto) { + # TODO(pcc): This should not be necessary. Remove once + # https://reviews.llvm.org/D50016 lands and gets rolled in. + ldflags = [ "-Wl,-u,__cyg_profile_func_enter_bare" ] + } + } +} + +if (current_toolchain == default_toolchain) { + pool("goma_javac_pool") { + # Override action_pool when goma is enabled for javac. + depth = 10000 + } + + # When defined, this pool should be used instead of link_pool for command + # that need 1-2GB of RAM. https://crbug.com/1078460 + if (defined(java_cmd_pool_size)) { + pool("java_cmd_pool") { + depth = java_cmd_pool_size + } + } +} diff --git a/third_party/libwebrtc/build/config/android/OWNERS b/third_party/libwebrtc/build/config/android/OWNERS new file mode 100644 index 0000000000..a74cfbe228 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/OWNERS @@ -0,0 +1 @@ +file://build/android/OWNERS diff --git a/third_party/libwebrtc/build/config/android/abi.gni b/third_party/libwebrtc/build/config/android/abi.gni new file mode 100644 index 0000000000..1dbbf0cd61 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/abi.gni @@ -0,0 +1,101 @@ +# Copyright 2017 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. + +# Logic separated out from config.gni so that it can be used by compiler.gni +# without introducing a circular dependency. + +# NOTE: Because Chrome OS builds may depend on targets built with the Android +# toolchain, this GNI file may be read and processed from within Chrome OS +# toolchains. Checking |is_android| here would therefore be too restrictive. +assert(is_android || is_chromeos) + +declare_args() { + # Adds intrumentation to each function. Writes a file with the order that + # functions are called at startup. + use_order_profiling = false + + # Only effective if use_order_profiling = true. When this is true, + # instrumentation switches from startup profiling after a delay, and + # then waits for a devtools memory dump request to dump all + # profiling information. When false, the same delay is used to switch from + # startup, and then after a second delay all profiling information is dumped. + # See base::android::orderfile::StartDelayedDump for more information. + devtools_instrumentation_dumping = false + + # Only effective if use_order_profiling = true. When this is true the call + # graph based instrumentation is used. + use_call_graph = false + + # Build additional browser splits with HWASAN instrumentation enabled. + build_hwasan_splits = false + + # *For CQ puposes only* Leads to non-working APKs. + # Forces all APKs/bundles to be 64-bit only to improve build speed in the CQ + # (no need to also build 32-bit library). + skip_secondary_abi_for_cq = false +} + +assert(!devtools_instrumentation_dumping || use_order_profiling, + "devtools_instrumentation_dumping requires use_order_profiling") +assert(!use_call_graph || use_order_profiling, + "use_call_graph requires use_order_profiling") + +if (target_cpu == "x86") { + android_app_abi = "x86" + android_abi_target = "i686-linux-android" +} else if (target_cpu == "arm") { + import("//build/config/arm.gni") + if (arm_version < 7) { + android_app_abi = "armeabi" + } else { + android_app_abi = "armeabi-v7a" + } + android_abi_target = "arm-linux-androideabi" +} else if (target_cpu == "mipsel") { + android_app_abi = "mips" + android_abi_target = "mipsel-linux-android" +} else if (target_cpu == "x64") { + android_app_abi = "x86_64" + + # Place holder for x64 support, not tested. + # TODO: Enable clang support for Android x64. http://crbug.com/539781 + android_abi_target = "x86_64-linux-android" +} else if (target_cpu == "arm64") { + android_app_abi = "arm64-v8a" + android_abi_target = "aarch64-linux-android" +} else if (target_cpu == "mips64el") { + android_app_abi = "mips64" + + # Place holder for mips64 support, not tested. + android_abi_target = "mips64el-linux-android" +} else { + assert(false, "Unknown Android ABI: " + target_cpu) +} + +if (target_cpu == "arm64" || target_cpu == "x64" || target_cpu == "mips64el") { + android_64bit_target_cpu = true +} else if (target_cpu == "arm" || target_cpu == "x86" || + target_cpu == "mipsel") { + android_64bit_target_cpu = false +} else { + assert(false, "Unknown target CPU: $target_cpu") +} + +# Intentionally do not define android_app_secondary_abi_cpu and +# android_app_secondary_abi for 32-bit target_cpu, since they are not used. +if (target_cpu == "arm64") { + android_secondary_abi_cpu = "arm" + android_app_secondary_abi = "armeabi-v7a" +} else if (target_cpu == "x64") { + android_secondary_abi_cpu = "x86" + android_app_secondary_abi = "x86" +} else if (target_cpu == "mips64el") { + android_secondary_abi_cpu = "mipsel" + android_app_secondary_abi = "mips" +} + +if (defined(android_secondary_abi_cpu)) { + android_secondary_abi_toolchain = + "//build/toolchain/android:android_clang_${android_secondary_abi_cpu}" +} diff --git a/third_party/libwebrtc/build/config/android/android_nocompile.gni b/third_party/libwebrtc/build/config/android/android_nocompile.gni new file mode 100644 index 0000000000..8ffca0e138 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/android_nocompile.gni @@ -0,0 +1,113 @@ +# Copyright 2020 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. + +import("//build/config/android/rules.gni") + +declare_args() { + # Used by tests to enable generating build files for GN targets which should + # not compile. + enable_android_nocompile_tests = false +} + +# Defines a test suite which checks that the 'test targets' fail to compile. The +# test suite runs 'gn gen' with a custom output directory and attempts to compile +# each test target. +# +# All of the tests should be defined in the same dedicated BUILD.gn file in order +# to minimize the number of targets that are processed by 'gn gen'. +# +# Variables +# tests: List of test configurations. A test configuration has the following +# keys: +# 'target': The GN target which should not compile when +# enable_android_nocompile_tests=true The target should compile when +# enable_android_nocompile_tests=false. +# 'expected_compile_output_regex': Error message regex to search for when compile fails. +# 'nocompile_sources': Source files which do not compile. This ensures that +# the test suite is re-run when one of these files change (as the test +# targets might not depend of the files when +# enable_android_nocompile_tests=false). +template("android_nocompile_test_suite") { + assert(!enable_android_nocompile_tests) + + action(target_name) { + testonly = true + script = "//build/android/gyp/nocompile_test.py" + + _tests = invoker.tests + _test0 = _tests[0] + _test0_dir = get_label_info(_test0["target"], "dir") + _test0_target_out_dir = get_label_info(_test0["target"], "target_out_dir") + foreach(_test_config, _tests) { + assert( + _test0_dir == get_label_info(_test_config["target"], "dir"), + "To avoid running 'gn gen' for each test, all tests in an android_nocompile_test_suite() should be declared in same BUILD.gn file") + } + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + + # Depend on compile_java Python scripts so that the action is re-run whenever the script is + # modified. + _pydeps = [ "//build/android/gyp/compile_java.pydeps" ] + if (defined(invoker.pydeps)) { + _pydeps += invoker.pydeps + } + + inputs = [] + foreach(_pydeps_file, _pydeps) { + _pydeps_file_lines = [] + _pydeps_file_lines = read_file(_pydeps_file, "list lines") + _pydeps_entries = [] + _pydeps_entries = filter_exclude(_pydeps_file_lines, [ "#*" ]) + _pydeps_file_dir = get_path_info(_pydeps_file, "dir") + inputs += rebase_path(_pydeps_entries, ".", _pydeps_file_dir) + } + + _json_test_configs = [] + foreach(_test_config, _tests) { + _test = _test_config["target"] + deps += [ _test ] + sources += _test_config["nocompile_sources"] + _dep_dir = get_label_info(_test, "dir") + _dep_name = get_label_info(_test, "name") + _json_test_configs += [ + { + target = "${_dep_dir}:${_dep_name}" + expect_regex = _test_config["expected_compile_output_regex"] + }, + ] + } + + _config_path = "$target_gen_dir/${target_name}.nocompile_config" + write_file(_config_path, _json_test_configs, "json") + + # Compute output directory for no-compile tests based on the directory containing test + # targets instead of based on the test suite target name. This avoids calling 'gn gen' for each + # android_nocompile_test_suite() for test suites whose tests are declared in the same BUILD.gn + # file. + _out_dir = "${_test0_target_out_dir}/nocompile_out" + + _stamp_path = "${target_gen_dir}/${target_name}.stamp" + args = [ + "--gn-args-path", + "args.gn", + "--out-dir", + rebase_path(_out_dir, root_build_dir), + "--test-configs-path", + rebase_path(_config_path, root_build_dir), + "--stamp", + rebase_path(_stamp_path, root_build_dir), + ] + inputs += [ _config_path ] + outputs = [ _stamp_path ] + } +} diff --git a/third_party/libwebrtc/build/config/android/build_vars.gni b/third_party/libwebrtc/build/config/android/build_vars.gni new file mode 100644 index 0000000000..a47607dc7c --- /dev/null +++ b/third_party/libwebrtc/build/config/android/build_vars.gni @@ -0,0 +1,29 @@ +# Copyright 2020 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. + +import("//build/config/android/config.gni") + +# Contains useful GN variables that may be used by scripts that take +# --output-directory as an arg. +build_vars_file = "$root_build_dir/build_vars.json" + +android_build_vars_json = { + if (enable_java_templates) { + android_ndk_root = rebase_path(android_ndk_root, root_build_dir) + android_sdk_build_tools = + rebase_path(android_sdk_build_tools, root_build_dir) + android_sdk_build_tools_version = android_sdk_build_tools_version + android_sdk_root = rebase_path(android_sdk_root, root_build_dir) + android_sdk_version = android_sdk_version + android_tool_prefix = rebase_path(android_tool_prefix, root_build_dir) + final_android_sdk = final_android_sdk + + if (defined(android_secondary_abi_cpu)) { + android_secondary_abi_toolchain = + rebase_path(get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir"), + root_build_dir) + } + } +} diff --git a/third_party/libwebrtc/build/config/android/channel.gni b/third_party/libwebrtc/build/config/android/channel.gni new file mode 100644 index 0000000000..6348bb996e --- /dev/null +++ b/third_party/libwebrtc/build/config/android/channel.gni @@ -0,0 +1,14 @@ +# Copyright 2014 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. + +declare_args() { + # The channel to build on Android: stable, beta, dev, canary, work, or + # default. "default" should be used on non-official builds. + android_channel = "default" +} + +assert(android_channel == "default" || android_channel == "canary" || + android_channel == "dev" || android_channel == "beta" || + android_channel == "stable", + "Invalid channel: " + android_channel) diff --git a/third_party/libwebrtc/build/config/android/config.gni b/third_party/libwebrtc/build/config/android/config.gni new file mode 100644 index 0000000000..13418299e6 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/config.gni @@ -0,0 +1,353 @@ +# Copyright 2014 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 file contains common system config stuff for the Android build. + +# NOTE: Because Chrome OS builds may depend on targets built with the Android +# toolchain, this GNI file may be read and processed from within Chrome OS +# toolchains. Checking |is_android| here would therefore be too restrictive. +if (is_android || is_chromeos) { + import("//build/config/chromecast_build.gni") + import("//build/config/dcheck_always_on.gni") + import("//build_overrides/build.gni") + import("abi.gni") + + if (build_with_chromium) { + # Some non-chromium projects (e.g. WebRTC) use our build configs + # heavily but don't write gclient args files. + + import("//build/config/gclient_args.gni") + if (defined(checkout_android_native_support)) { + n = "$0x0A" # Newline + assert(checkout_android_native_support, + "Missing native Android toolchain support. |target_os| in your " + + ".gclient configuration file (in the parent directory of " + + "src) must include \"android\" and/or \"chromeos\". For " + + "example:${n}${n}solutions = [${n}...${n}]${n}" + + "target_os=[\"chromeos\"]${n}${n}" + + "After adding |target_os| please re-run \"gclient sync\".${n}") + } + } + + has_chrome_android_internal = + exec_script("//build/dir_exists.py", + [ rebase_path("//clank", root_build_dir) ], + "string") == "True" + + # We are using a separate declare_args block for only this argument so that + # we can decide if we have to pull in definitions from the internal config + # early. + declare_args() { + # Enables using the internal Chrome for Android repository. The default + # value depends on whether the repository is available, and if it's not but + # this argument is manually set to True, the generation will fail. + # The main purpose of this argument is to avoid having to maintain 2 + # repositories to support both public only and internal builds. + enable_chrome_android_internal = has_chrome_android_internal + + # The default to use for android:minSdkVersion for targets that do + # not explicitly set it. + default_min_sdk_version = 21 + + # [WIP] Allows devs to achieve much faster edit-build-install cycles. + # Currently only works for ChromeModern apks due to incremental install. + # This needs to be in a separate declare_args as it determines some of the + # args in the main declare_args block below. + android_fast_local_dev = false + } + + declare_args() { + # Android API level for 32 bits platforms + android32_ndk_api_level = default_min_sdk_version + + # Android API level for 64 bits platforms + if (default_min_sdk_version < 21) { + android64_ndk_api_level = 21 + } else { + android64_ndk_api_level = default_min_sdk_version + } + } + + if (enable_chrome_android_internal) { + import("//clank/config.gni") + } else { + import("//build/config/android/sdk.gni") + declare_args() { + # Which Android SDK to use. + android_sdk_release = default_android_sdk_release + } + } + + if (!defined(default_android_ndk_root)) { + default_android_ndk_root = "//third_party/android_ndk" + default_android_ndk_version = "r22" + default_android_ndk_major_version = 22 + } else { + assert(defined(default_android_ndk_version)) + assert(defined(default_android_ndk_major_version)) + } + + public_android_sdk_root = "//third_party/android_sdk/public" + if (android_sdk_release == "s") { + default_android_sdk_root = public_android_sdk_root + default_android_sdk_version = "31" + default_android_sdk_build_tools_version = "31.0.0" + public_android_sdk = true + } + + # For use downstream when we are building with preview Android SDK + if (!defined(final_android_sdk)) { + final_android_sdk = public_android_sdk + } + + if (!defined(default_lint_android_sdk_root)) { + # Purposefully repeated so that downstream can change + # default_android_sdk_root without changing lint version. + default_lint_android_sdk_root = public_android_sdk_root + default_lint_android_sdk_version = 31 + } + + if (!defined(default_extras_android_sdk_root)) { + # Purposefully repeated so that downstream can change + # default_android_sdk_root without changing where we load the SDK extras + # from. (Google Play services, etc.) + default_extras_android_sdk_root = public_android_sdk_root + } + + if (!defined(default_android_keystore_path)) { + default_android_keystore_path = "//build/android/chromium-debug.keystore" + default_android_keystore_name = "chromiumdebugkey" + default_android_keystore_password = "chromium" + } + + # google_play_services_package contains the path where individual client + # targets (e.g. google_play_services_base_java) are located. + if (!defined(google_play_services_package)) { + if (is_chromecast && chromecast_branding != "public") { + google_play_services_package = "//chromecast/internal/android/prebuilt/google-play-services-first-party" + } else { + google_play_services_package = "//third_party/android_deps" + } + } + + if (!defined(dagger_java_target)) { + dagger_java_target = + "//third_party/android_deps:com_google_dagger_dagger_java" + } + + if (!defined(dagger_annotation_processor_target)) { + dagger_annotation_processor_target = + "//third_party/android_deps:com_google_dagger_dagger_compiler_java" + } + + if (!defined(guava_android_target)) { + guava_android_target = + "//third_party/android_deps:com_google_guava_guava_android_java" + } + + if (!defined(material_design_target)) { + material_design_target = + "//third_party/android_deps:com_google_android_material_material_java" + } + + if (!defined(android_protoc_bin)) { + android_protoc_bin = "//third_party/android_protoc/protoc" + android_proto_runtime = + "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java" + } + + webview_public_framework_dep = + "//third_party/android_sdk:public_framework_system_java" + if (!defined(webview_framework_dep)) { + webview_framework_dep = webview_public_framework_dep + } + + assert(defined(default_android_sdk_root), + "SDK release " + android_sdk_release + " not recognized.") + + declare_args() { + android_ndk_root = default_android_ndk_root + android_ndk_version = default_android_ndk_version + android_ndk_major_version = default_android_ndk_major_version + + android_sdk_root = default_android_sdk_root + android_sdk_version = default_android_sdk_version + android_sdk_build_tools_version = default_android_sdk_build_tools_version + + lint_android_sdk_root = default_lint_android_sdk_root + lint_android_sdk_version = default_lint_android_sdk_version + + # Libc++ library directory. Override to use a custom libc++ binary. + android_libcpp_lib_dir = "" + + # Android versionCode for android_apk()s that don't explicitly set one. + android_default_version_code = "1" + + # Android versionName for android_apk()s that don't explicitly set one. + android_default_version_name = "Developer Build" + + # Forced Android versionCode + android_override_version_code = "" + + # Forced Android versionName + android_override_version_name = "" + + # The path to the keystore to use for signing builds. + android_keystore_path = default_android_keystore_path + + # The name of the keystore to use for signing builds. + android_keystore_name = default_android_keystore_name + + # The password for the keystore to use for signing builds. + android_keystore_password = default_android_keystore_password + + # Java debug on Android. Having this on enables multidexing, and turning it + # off will enable proguard. + is_java_debug = is_debug + + # Mark APKs as android:debuggable="true". + debuggable_apks = !is_official_build + + # Set to false to disable the Errorprone compiler. + # Defaults to false for official builds to reduce build times. + # Static analysis failures should have been already caught by normal bots. + # Disabled when fast_local_dev is turned on. + use_errorprone_java_compiler = !is_official_build && !android_fast_local_dev + + # Build incremental targets whenever possible. + # See //build/android/incremental_install/README.md for more details. + incremental_install = android_fast_local_dev + + # When true, updates all android_aar_prebuilt() .info files during gn gen. + # Refer to android_aar_prebuilt() for more details. + update_android_aar_prebuilts = false + + # Turns off android lint. Useful for prototyping or for faster local builds. + # Defaults to true for official builds to reduce build times. + # Static analysis failures should have been already caught by normal bots. + # Disabled when fast_local_dev is turned on. + disable_android_lint = is_official_build || android_fast_local_dev + + # Location of aapt2 used for app bundles. For now, a more recent version + # than the one distributed with the Android SDK is required. + android_sdk_tools_bundle_aapt2_dir = + "//third_party/android_build_tools/aapt2" + + # Causes expectation failures to break the build, otherwise, just warns on + # stderr and writes a failure file to $android_configuration_failure_dir: + fail_on_android_expectations = false + + # Controls whether proguard obfuscation is enabled for targets + # configured to use it. + enable_proguard_obfuscation = true + + # Controls whether |short_resource_paths| and |strip_resource_names| are + # respected. Useful when trying to analyze APKs using tools that do not + # support mapping these names. + enable_arsc_obfuscation = true + + # The target to use as the system WebView implementation. + if (android_64bit_target_cpu && skip_secondary_abi_for_cq) { + system_webview_apk_target = "//android_webview:system_webview_64_apk" + } else { + system_webview_apk_target = "//android_webview:system_webview_apk" + } + + # Where to write failed expectations for bots to read. + expectations_failure_dir = "$root_build_dir/failed_expectations" + } + + # We need a second declare_args block to make sure we are using the overridden + # value of the arguments set above. + declare_args() { + if (defined(default_android_sdk_platform_version)) { + android_sdk_platform_version = default_android_sdk_platform_version + } else { + android_sdk_platform_version = android_sdk_version + } + + # Whether java assertions and Preconditions checks are enabled. + enable_java_asserts = is_java_debug || dcheck_always_on + + # Reduce build time by using d8 incremental build. + enable_incremental_d8 = true + + # Use hashed symbol names to reduce JNI symbol overhead. + use_hashed_jni_names = !is_java_debug + + # Enables Java library desugaring. + # This will cause an extra classes.dex file to appear in every apk. + enable_jdk_library_desugaring = true + } + + # Host stuff ----------------------------------------------------------------- + + # Defines the name the Android build gives to the current host CPU + # architecture, which is different than the names GN uses. + if (host_cpu == "x64") { + android_host_arch = "x86_64" + } else if (host_cpu == "x86") { + android_host_arch = "x86" + } else { + assert(false, "Need Android toolchain support for your build CPU arch.") + } + + # Defines the name the Android build gives to the current host CPU + # architecture, which is different than the names GN uses. + if (host_os == "linux") { + android_host_os = "linux" + } else if (host_os == "mac") { + android_host_os = "darwin" + } else { + assert(false, "Need Android toolchain support for your build OS.") + } + + # Directories and files ------------------------------------------------------ + # + # We define may of the dirs strings here for each output architecture (rather + # than just the current one) since these are needed by the Android toolchain + # file to define toolchains for all possible targets in one pass. + + android_sdk = + "${android_sdk_root}/platforms/android-${android_sdk_platform_version}" + android_sdk_build_tools = + "${android_sdk_root}/build-tools/$android_sdk_build_tools_version" + + # Path to the SDK's android.jar + android_sdk_jar = "$android_sdk/android.jar" + + # Location of libgcc. This is only needed for the current GN toolchain, so we + # only need to define the current one, rather than one for every platform + # like the toolchain roots. + if (target_cpu == "x86") { + android_prebuilt_arch = "android-x86" + _binary_prefix = "i686-linux-android" + } else if (target_cpu == "arm") { + android_prebuilt_arch = "android-arm" + _binary_prefix = "arm-linux-androideabi" + } else if (target_cpu == "mipsel") { + android_prebuilt_arch = "android-mips" + _binary_prefix = "mipsel-linux-android" + } else if (target_cpu == "x64") { + android_prebuilt_arch = "android-x86_64" + _binary_prefix = "x86_64-linux-android" + } else if (target_cpu == "arm64") { + android_prebuilt_arch = "android-arm64" + _binary_prefix = "aarch64-linux-android" + } else if (target_cpu == "mips64el") { + android_prebuilt_arch = "android-mips64" + _binary_prefix = "mips64el-linux-android" + } else { + assert(false, "Need android libgcc support for your target arch.") + } + + android_toolchain_root = "$android_ndk_root/toolchains/llvm/prebuilt/${android_host_os}-${android_host_arch}" + android_tool_prefix = "$android_toolchain_root/bin/$_binary_prefix-" + android_readelf = "${android_tool_prefix}readelf" + android_objcopy = "${android_tool_prefix}objcopy" + android_gdbserver = + "$android_ndk_root/prebuilt/$android_prebuilt_arch/gdbserver/gdbserver" + + android_sdk_tools_bundle_aapt2 = "${android_sdk_tools_bundle_aapt2_dir}/aapt2" +} diff --git a/third_party/libwebrtc/build/config/android/copy_ex.gni b/third_party/libwebrtc/build/config/android/copy_ex.gni new file mode 100644 index 0000000000..d3705dd7ef --- /dev/null +++ b/third_party/libwebrtc/build/config/android/copy_ex.gni @@ -0,0 +1,72 @@ +# Copyright 2019 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. +# +# Copy a list of file into a destination directory. Potentially renaming +# files are they are copied. This also ensures that symlinks are followed +# during the copy (i.e. the symlinks are never copied, only their content). +# +# Variables: +# dest: Destination directory path. +# sources: List of source files or directories to copy to dest. +# renaming_sources: Optional list of source file paths that will be renamed +# during the copy operation. If provided, renaming_destinations is required. +# renaming_destinations: Optional list of destination file paths, required +# when renaming_sources is provided. Both lists should have the same size +# and matching entries. +# args: Optional. Additionnal arguments to the copy_ex.py script. +# +# The following variables have the usual GN meaning: data, deps, inputs, +# outputs, testonly, visibility. + +import("//build/config/python.gni") + +template("copy_ex") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + outputs = [] + if (defined(invoker.outputs)) { + outputs += invoker.outputs + } + if (defined(invoker.inputs)) { + inputs = invoker.inputs + } + + script = "//build/android/gyp/copy_ex.py" + + args = [ + "--dest", + rebase_path(invoker.dest, root_build_dir), + ] + rebased_sources = rebase_path(sources, root_build_dir) + args += [ "--files=$rebased_sources" ] + + if (defined(invoker.args)) { + args += invoker.args + } + + if (defined(invoker.renaming_sources) && + defined(invoker.renaming_destinations)) { + sources += invoker.renaming_sources + renaming_destinations = invoker.renaming_destinations + outputs += + get_path_info(rebase_path(renaming_destinations, ".", invoker.dest), + "abspath") + rebased_renaming_sources = + rebase_path(invoker.renaming_sources, root_build_dir) + args += [ "--renaming-sources=$rebased_renaming_sources" ] + args += [ "--renaming-destinations=$renaming_destinations" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni b/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni new file mode 100644 index 0000000000..5444c5b972 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/extract_unwind_tables.gni @@ -0,0 +1,44 @@ +# Copyright 2018 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. + +import("//build/config/android/rules.gni") + +template("unwind_table_asset") { + # Note: This file name is used in multiple monochrome build scripts. + _asset_path = "${target_gen_dir}/${target_name}/unwind_cfi_32" + _unwind_action = "${target_name}__extract" + + action(_unwind_action) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _root_dir = "$root_out_dir" + if (defined(android_secondary_abi_cpu)) { + _root_dir = get_label_info(":foo($android_secondary_abi_toolchain)", + "root_out_dir") + } + + script = "//build/android/gyp/extract_unwind_tables.py" + outputs = [ _asset_path ] + inputs = [ "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension" ] + + args = [ + "--input_path", + rebase_path( + "${_root_dir}/lib.unstripped/$shlib_prefix${invoker.library_target}$shlib_extension", + root_build_dir), + "--output_path", + rebase_path(_asset_path, root_build_dir), + "--dump_syms_path", + rebase_path("$root_out_dir/dump_syms", root_build_dir), + ] + deps = invoker.deps + deps += [ "//third_party/breakpad:dump_syms" ] + } + android_assets(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + sources = [ _asset_path ] + disable_compression = true + deps = [ ":$_unwind_action" ] + } +} diff --git a/third_party/libwebrtc/build/config/android/internal_rules.gni b/third_party/libwebrtc/build/config/android/internal_rules.gni new file mode 100644 index 0000000000..3ed306a9e7 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/internal_rules.gni @@ -0,0 +1,4368 @@ +# Copyright 2014 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. + +# Do not add any imports to non-//build directories here. +# Some projects (e.g. V8) do not have non-build directories DEPS'ed in. +import("//build/config/android/config.gni") +import("//build/config/android/copy_ex.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/compute_inputs_for_analyze.gni") +import("//build/config/coverage/coverage.gni") +import("//build/config/python.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/kythe.gni") +import("//build/util/generate_wrapper.gni") +import("//build_overrides/build.gni") +if (current_toolchain == default_toolchain) { + import("//build/toolchain/concurrent_links.gni") +} +assert(is_android) + +# The following _java_*_types variables capture all the existing target types. +# If a new type is introduced, please add it to one of these categories, +# preferring the more specific resource/library types. +_java_resource_types = [ + "android_assets", + "android_resources", +] + +_java_library_types = [ + "java_library", + "system_java_library", + "android_app_bundle_module", +] + +# These are leaf java target types. They cannot be passed as deps to other +# targets. Thus their naming schemes are not enforced. +_java_leaf_types = [ + "android_apk", + "android_app_bundle", + "dist_aar", + "dist_jar", + "java_annotation_processor", + "java_binary", + "junit_binary", +] + +# All _java_resource_types targets must conform to these patterns. +_java_resource_patterns = [ + "*:*_assets", + "*android*:assets", + "*:*_apk_*resources", + "*android*:resources", + "*:*_resources", + "*:*_grd", + "*:*locale_paks", + "*:*_java_strings", + "*:*strings_java", +] + +# All _java_library_types targets must conform to these patterns. This includes +# all non-leaf targets that use java_library_impl. +_java_library_patterns = [ + "*:*_java", + "*:*_javalib", + "*:*_java_*", # e.g. chrome_java_test_support + "*:java", + "*:junit", + "*:junit_*", + "*:*_junit_*", + "*:*javatests", + "*:*_bundle_module", + + # TODO(agrieve): Rename targets below to match above patterns. + "//android_webview/glue:glue", +] + +# These identify all non-leaf targets that have .build_config.json files. This is the +# set of patterns that other targets can use to filter out java targets. +java_target_patterns = _java_library_patterns + _java_resource_patterns + +_r8_path = "//third_party/r8/lib/r8.jar" +_custom_d8_path = "//third_party/r8/custom_d8.jar" +_desugar_jdk_libs_json = "//third_party/r8/desugar_jdk_libs.json" +_desugar_jdk_libs_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/desugar_jdk_libs-1.1.1.jar" +_desugar_jdk_libs_configuration_jar = "//third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/desugar_jdk_libs_configuration-1.1.1.jar" +_desugar_runtime_jar = "$root_build_dir/obj/third_party/bazel/desugar/Desugar_runtime.processed.jar" + +_dexdump_path = "$android_sdk_build_tools/dexdump" +_dexlayout_path = "//third_party/android_build_tools/art/dexlayout" +_profman_path = "//third_party/android_build_tools/art/profman" +_art_lib_file_names = [ + "libartbase.so", + "libart-compiler.so", + "libart-dexlayout.so", + "libart-disassembler.so", + "libart-gtest.so", + "libart.so", + "libbacktrace.so", + "libbase.so", + "libcrypto-host.so", + "libc++.so", + "libcutils.so", + "libdexfile.so", + "libexpat-host.so", + "libicui18n-host.so", + "libicuuc-host.so", + "libjavacore.so", + "libjavacrypto.so", + "liblog.so", + "liblz4.so", + "liblzma.so", + "libnativebridge.so", + "libnativehelper.so", + "libnativeloader.so", + "libopenjdkjvm.so", + "libopenjdkjvmti.so", + "libopenjdk.so", + "libprofile.so", + "libsigchain.so", + "libssl-host.so", + "libunwindstack.so", + "libvixl-arm64.so", + "libvixl-arm.so", + "libvixld-arm64.so", + "libvixld-arm.so", + "libz-host.so", + "libziparchive.so", + "slicer.so", +] +_default_art_libs = [] +foreach(lib, _art_lib_file_names) { + _default_art_libs += [ "//third_party/android_build_tools/art/lib/$lib" ] +} + +# Put the bug number in the target name so that false-positives have a hint in +# the error message about why non-existent dependencies are there. +build_config_target_suffix = "__build_config_crbug_908819" + +# Write the target's .build_config.json file. This is a json file that contains a +# dictionary of information about how to build this target (things that +# require knowledge about this target's dependencies and cannot be calculated +# at gn-time). There is a special syntax to add a value in that dictionary to +# an action/action_foreachs args: +# --python-arg=@FileArg($rebased_build_config_path:key0:key1) +# At runtime, such an arg will be replaced by the value in the build_config. +# See build/android/gyp/write_build_config.py and +# build/android/gyp/util/build_utils.py:ExpandFileArgs +template("write_build_config") { + _type = invoker.type + _parent_invoker = invoker.invoker + _target_label = + get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain") + + # Ensure targets match naming patterns so that __assetres, __header, __impl + # targets work properly. Those generated targets allow for effective deps + # filtering. + if (filter_exclude([ _type ], _java_resource_types) == []) { + if (filter_exclude([ _target_label ], _java_resource_patterns) != []) { + assert(false, "Invalid java resource target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_library_types) == []) { + if (filter_exclude([ _target_label ], _java_library_patterns) != [] || + filter_exclude([ _target_label ], _java_resource_patterns) == []) { + assert(false, "Invalid java library target name: $_target_label") + } + } else if (_type == "group") { + if (filter_exclude([ _target_label ], java_target_patterns) != []) { + assert(false, "Invalid java target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_leaf_types) != []) { + assert(false, "This java type needs a category: $_type") + } + + if (defined(invoker.public_target_label)) { + _target_label = invoker.public_target_label + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + if (defined(invoker.android_manifest_dep)) { + deps += [ invoker.android_manifest_dep ] + } + + script = "//build/android/gyp/write_build_config.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [] + outputs = [ invoker.build_config ] + + _deps_configs = [] + _public_deps_configs = [] + if (defined(invoker.possible_config_deps)) { + foreach(_possible_dep, invoker.possible_config_deps) { + _dep_label = get_label_info(_possible_dep, "label_no_toolchain") + if (filter_exclude([ _dep_label ], java_target_patterns) == []) { + # Put the bug number in the target name so that false-positives + # have a hint in the error message about non-existent dependencies. + deps += [ "$_dep_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir") + _dep_name = get_label_info(_possible_dep, "name") + _dep_config = "$_dep_gen_dir/$_dep_name.build_config.json" + + _deps_configs += [ _dep_config ] + if (defined(invoker.possible_config_public_deps)) { + if (filter_include([ _possible_dep ], + invoker.possible_config_public_deps) != []) { + _public_deps_configs += [ _dep_config ] + } + } + } + } + } + _rebased_deps_configs = rebase_path(_deps_configs, root_build_dir) + _rebased_public_deps_configs = + rebase_path(_public_deps_configs, root_build_dir) + + args = [ + "--type=$_type", + "--depfile", + rebase_path(depfile, root_build_dir), + "--deps-configs=$_rebased_deps_configs", + "--public-deps-configs=$_rebased_public_deps_configs", + "--build-config", + rebase_path(invoker.build_config, root_build_dir), + "--gn-target", + _target_label, + ] + + if (defined(invoker.ignore_dependency_public_deps) && + invoker.ignore_dependency_public_deps) { + args += [ "--ignore-dependency-public-deps" ] + } + + if (defined(invoker.aar_path)) { + args += [ + "--aar-path", + rebase_path(invoker.aar_path, root_build_dir), + ] + } + + if (defined(invoker.chromium_code) && !invoker.chromium_code) { + # Default to chromium code if invoker did not pass anything. + args += [ "--non-chromium-code" ] + } + + if (defined(invoker.device_jar_path)) { + args += [ + "--device-jar-path", + rebase_path(invoker.device_jar_path, root_build_dir), + ] + } + if (defined(invoker.host_jar_path)) { + args += [ + "--host-jar-path", + rebase_path(invoker.host_jar_path, root_build_dir), + ] + } + if (defined(invoker.unprocessed_jar_path)) { + args += [ + "--unprocessed-jar-path", + rebase_path(invoker.unprocessed_jar_path, root_build_dir), + ] + } + if (defined(invoker.ijar_path)) { + args += [ + "--interface-jar-path", + rebase_path(invoker.ijar_path, root_build_dir), + ] + } + if (defined(invoker.java_resources_jar)) { + args += [ + "--java-resources-jar-path", + rebase_path(invoker.java_resources_jar, root_build_dir), + ] + } + if (defined(invoker.annotation_processor_deps) && + invoker.annotation_processor_deps != []) { + _processor_configs = [] + foreach(_processor_dep, invoker.annotation_processor_deps) { + _dep_label = get_label_info(_processor_dep, "label_no_toolchain") + _dep_gen_dir = get_label_info(_processor_dep, "target_gen_dir") + _dep_name = get_label_info(_processor_dep, "name") + deps += [ "$_dep_label$build_config_target_suffix" ] + _processor_configs += [ "$_dep_gen_dir/$_dep_name.build_config.json" ] + } + _rebased_processor_configs = + rebase_path(_processor_configs, root_build_dir) + args += [ "--annotation-processor-configs=$_rebased_processor_configs" ] + } + + # Dex path for library targets, or the the intermediate library for apks. + if (defined(invoker.dex_path)) { + args += [ + "--dex-path", + rebase_path(invoker.dex_path, root_build_dir), + ] + } + + # Dex path for the final apk. + if (defined(invoker.final_dex_path)) { + args += [ + "--final-dex-path", + rebase_path(invoker.final_dex_path, root_build_dir), + ] + } + if (defined(invoker.supports_android) && invoker.supports_android) { + args += [ "--supports-android" ] + } + if (defined(invoker.requires_android) && invoker.requires_android) { + args += [ "--requires-android" ] + } + if (defined(invoker.is_prebuilt) && invoker.is_prebuilt) { + args += [ "--is-prebuilt" ] + } + if (defined(invoker.bypass_platform_checks) && + invoker.bypass_platform_checks) { + args += [ "--bypass-platform-checks" ] + } + + if (defined(invoker.apk_under_test)) { + deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ] + apk_under_test_gen_dir = + get_label_info(invoker.apk_under_test, "target_gen_dir") + apk_under_test_name = get_label_info(invoker.apk_under_test, "name") + apk_under_test_config = + "$apk_under_test_gen_dir/$apk_under_test_name.build_config.json" + args += [ + "--tested-apk-config", + rebase_path(apk_under_test_config, root_build_dir), + ] + } + + if (defined(invoker.asset_sources)) { + _rebased_asset_sources = + rebase_path(invoker.asset_sources, root_build_dir) + args += [ "--asset-sources=$_rebased_asset_sources" ] + } + if (defined(invoker.asset_renaming_sources)) { + _rebased_asset_renaming_sources = + rebase_path(invoker.asset_renaming_sources, root_build_dir) + args += [ "--asset-renaming-sources=$_rebased_asset_renaming_sources" ] + + # These are zip paths, so no need to rebase. + args += [ + "--asset-renaming-destinations=${invoker.asset_renaming_destinations}", + ] + } + if (defined(invoker.disable_compression) && invoker.disable_compression) { + args += [ "--disable-asset-compression" ] + } + if (defined(invoker.treat_as_locale_paks) && invoker.treat_as_locale_paks) { + args += [ "--treat-as-locale-paks" ] + } + + if (defined(invoker.merged_android_manifest)) { + args += [ + "--merged-android-manifest", + rebase_path(invoker.merged_android_manifest, root_build_dir), + ] + } + if (defined(invoker.android_manifest)) { + inputs += [ invoker.android_manifest ] + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + if (defined(invoker.resources_zip)) { + args += [ + "--resources-zip", + rebase_path(invoker.resources_zip, root_build_dir), + ] + } + + if (defined(invoker.resource_overlay) && invoker.resource_overlay) { + args += [ "--resource-overlay" ] + } + + if (defined(invoker.custom_package)) { + args += [ + "--package-name", + invoker.custom_package, + ] + } + if (defined(invoker.r_text)) { + args += [ + "--r-text-path", + rebase_path(invoker.r_text, root_build_dir), + ] + } + if (defined(invoker.res_size_info_path)) { + args += [ + "--res-size-info", + rebase_path(invoker.res_size_info_path, root_build_dir), + ] + } + if (defined(invoker.res_sources_path)) { + _res_sources_path = rebase_path(invoker.res_sources_path, root_build_dir) + args += [ "--res-sources-path=$_res_sources_path" ] + } + if (defined(invoker.proto_resources_path)) { + _rebased_proto_resources = + rebase_path(invoker.proto_resources_path, root_build_dir) + args += [ "--apk-proto-resources=$_rebased_proto_resources" ] + } + if (defined(invoker.r_text_path)) { + _rebased_rtxt_path = rebase_path(invoker.r_text_path, root_build_dir) + args += [ "--r-text-path=$_rebased_rtxt_path" ] + } + if (defined(invoker.module_pathmap_path)) { + _rebased_pathmap_path = + rebase_path(invoker.module_pathmap_path, root_build_dir) + args += [ "--module-pathmap-path=$_rebased_pathmap_path" ] + } + + if (defined(invoker.shared_libraries_runtime_deps_file)) { + # Don't list shared_libraries_runtime_deps_file as an input in order to + # avoid having to depend on the runtime_deps target. See comment in + # rules.gni for why we do this. + args += [ + "--shared-libraries-runtime-deps", + rebase_path(invoker.shared_libraries_runtime_deps_file, root_build_dir), + ] + } + + if (defined(invoker.base_allowlist_rtxt_path)) { + args += [ + "--base-allowlist-rtxt-path", + rebase_path(invoker.base_allowlist_rtxt_path, root_build_dir), + ] + } + + if (defined(invoker.is_base_module) && invoker.is_base_module) { + args += [ "--is-base-module" ] + } + + if (defined(invoker.loadable_modules)) { + _rebased_loadable_modules = + rebase_path(invoker.loadable_modules, root_build_dir) + args += [ "--loadable-modules=$_rebased_loadable_modules" ] + } + + if (defined(invoker.secondary_abi_shared_libraries_runtime_deps_file)) { + # Don't list secondary_abi_shared_libraries_runtime_deps_file as an + # input in order to avoid having to depend on the runtime_deps target. + # See comment in rules.gni for why we do this. + args += [ + "--secondary-abi-shared-libraries-runtime-deps", + rebase_path(invoker.secondary_abi_shared_libraries_runtime_deps_file, + root_build_dir), + ] + } + + if (defined(invoker.secondary_abi_loadable_modules) && + invoker.secondary_abi_loadable_modules != []) { + _rebased_secondary_abi_loadable_modules = + rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) + args += [ "--secondary-abi-loadable-modules=$_rebased_secondary_abi_loadable_modules" ] + } + + if (defined(invoker.native_lib_placeholders) && + invoker.native_lib_placeholders != []) { + args += [ "--native-lib-placeholders=${invoker.native_lib_placeholders}" ] + } + + if (defined(invoker.secondary_native_lib_placeholders) && + invoker.secondary_native_lib_placeholders != []) { + args += [ "--secondary-native-lib-placeholders=${invoker.secondary_native_lib_placeholders}" ] + } + + if (defined(invoker.uncompress_shared_libraries) && + invoker.uncompress_shared_libraries) { + args += [ "--uncompress-shared-libraries" ] + } + + if (defined(invoker.library_always_compress)) { + args += [ "--library-always-compress=${invoker.library_always_compress}" ] + } + + if (defined(invoker.library_renames)) { + args += [ "--library-renames=${invoker.library_renames}" ] + } + + if (defined(invoker.apk_path)) { + # TODO(tiborg): Remove APK path from build config and use + # install_artifacts from metadata instead. + _rebased_apk_path = rebase_path(invoker.apk_path, root_build_dir) + args += [ "--apk-path=$_rebased_apk_path" ] + if (defined(invoker.incremental_apk_path)) { + _rebased_incremental_apk_path = + rebase_path(invoker.incremental_apk_path, root_build_dir) + _rebased_incremental_install_json_path = + rebase_path(invoker.incremental_install_json_path, root_build_dir) + args += [ + "--incremental-install-json-path=$_rebased_incremental_install_json_path", + "--incremental-apk-path=$_rebased_incremental_apk_path", + ] + } + } + + if (defined(invoker.java_sources_file)) { + args += [ + "--java-sources-file", + rebase_path(invoker.java_sources_file, root_build_dir), + ] + } + if (defined(invoker.srcjar)) { + args += [ + "--srcjar", + rebase_path(invoker.srcjar, root_build_dir), + ] + } + if (defined(invoker.bundled_srcjars)) { + _rebased_bundled_srcjars = + rebase_path(invoker.bundled_srcjars, root_build_dir) + args += [ "--bundled-srcjars=$_rebased_bundled_srcjars" ] + } + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) { + args += [ "--proguard-enabled" ] + } + if (defined(invoker.proguard_mapping_path)) { + _rebased_proguard_mapping_path = + rebase_path(invoker.proguard_mapping_path, root_build_dir) + args += [ "--proguard-mapping-path=$_rebased_proguard_mapping_path" ] + } + if (defined(invoker.input_jars_paths)) { + _rebased_input_jars_paths = + rebase_path(invoker.input_jars_paths, root_build_dir) + args += [ "--extra-classpath-jars=$_rebased_input_jars_paths" ] + } + if (defined(invoker.low_classpath_priority) && + invoker.low_classpath_priority) { + args += [ "--low-classpath-priority" ] + } + if (defined(invoker.mergeable_android_manifests)) { + _rebased_mergeable_android_manifests = + rebase_path(invoker.mergeable_android_manifests, root_build_dir) + args += [ + "--mergeable-android-manifests=$_rebased_mergeable_android_manifests", + ] + } + if (defined(invoker.proguard_configs)) { + _rebased_proguard_configs = + rebase_path(invoker.proguard_configs, root_build_dir) + args += [ "--proguard-configs=$_rebased_proguard_configs" ] + } + if (defined(invoker.static_library_dependent_targets)) { + _dependent_configs = [] + foreach(_dep, invoker.static_library_dependent_targets) { + _dep_name = _dep.name + _dep_label = get_label_info(_dep_name, "label_no_toolchain") + deps += [ "$_dep_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(_dep_name, "target_gen_dir") + _dep_name = get_label_info(_dep_name, "name") + _config = rebase_path("$_dep_gen_dir/$_dep_name.build_config.json", + root_build_dir) + _dependent_configs += [ _config ] + } + args += [ "--static-library-dependent-configs=$_dependent_configs" ] + } + if (defined(invoker.gradle_treat_as_prebuilt) && + invoker.gradle_treat_as_prebuilt) { + args += [ "--gradle-treat-as-prebuilt" ] + } + if (defined(invoker.main_class)) { + args += [ + "--main-class", + invoker.main_class, + ] + } + if (defined(invoker.base_module_target)) { + _base_label = + get_label_info(invoker.base_module_target, "label_no_toolchain") + _dep_gen_dir = get_label_info(_base_label, "target_gen_dir") + _dep_name = get_label_info(_base_label, "name") + deps += [ "$_base_label$build_config_target_suffix" ] + _base_module_build_config = "$_dep_gen_dir/$_dep_name.build_config.json" + inputs += [ _base_module_build_config ] + args += [ + "--base-module-build-config", + rebase_path(_base_module_build_config, root_build_dir), + ] + } + if (defined(invoker.module_build_configs)) { + inputs += invoker.module_build_configs + _rebased_configs = + rebase_path(invoker.module_build_configs, root_build_dir) + args += [ "--module-build-configs=$_rebased_configs" ] + } + if (defined(invoker.version_name)) { + args += [ + "--version-name", + invoker.version_name, + ] + } + if (defined(invoker.version_code)) { + args += [ + "--version-code", + invoker.version_code, + ] + } + if (defined(invoker.recursive_resource_deps) && + invoker.recursive_resource_deps) { + args += [ "--recursive-resource-deps" ] + } + if (current_toolchain != default_toolchain) { + # This has to be a built-time error rather than a GN assert because many + # packages have a mix of java and non-java targets. For example, the + # following would fail even though nothing depends on :bar(//baz): + # + # shared_library("foo") { + # } + # + # android_library("bar") { + # deps = [ ":foo(//baz)" ] + # assert(current_toolchain == default_toolchain) + # } + _msg = [ + "Tried to build an Android target in a non-default toolchain.", + "target: $_target_label", + "current_toolchain: $current_toolchain", + "default_toolchain: $default_toolchain", + ] + args += [ "--fail=$_msg" ] + } + } +} + +template("generate_android_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + generator_script = "//build/android/gyp/generate_android_wrapper.py" + sources = [ + "//build/android/gyp/util/build_utils.py", + "//build/gn_helpers.py", + "//build/util/generate_wrapper.py", + ] + } +} + +template("generate_r_java") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + if (!defined(deps)) { + deps = [] + } + if (defined(invoker.possible_resource_deps)) { + foreach(_dep, invoker.possible_resource_deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != []) { + # Depend on the java libraries' transitive __assetres target instead. + # This is required to ensure depending on java_groups works. + deps += [ "${_target_label}__assetres" ] + } else { + deps += [ _dep ] + } + } + } + depfile = "$target_gen_dir/${invoker.target_name}.d" + inputs = [ invoker.build_config ] + outputs = [ invoker.srcjar_path ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + script = "//build/android/gyp/create_r_java.py" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--srcjar-out", + rebase_path(invoker.srcjar_path, root_build_dir), + "--deps-rtxts=@FileArg($_rebased_build_config:deps_info:dependency_r_txt_files)", + "--r-package=${invoker.package}", + ] + } +} + +# Generates a script in the build bin directory which runs the test +# target using the test runner script in build/android/test_runner.py. +template("test_runner_script") { + testonly = true + _test_name = invoker.test_name + _test_type = invoker.test_type + _incremental_apk = defined(invoker.incremental_apk) && invoker.incremental_apk + + _runtime_deps = + !defined(invoker.ignore_all_data_deps) || !invoker.ignore_all_data_deps + + if (_runtime_deps) { + # This runtime_deps file is used at runtime and thus cannot go in + # target_gen_dir. + _target_dir_name = get_label_info(":$target_name", "dir") + _runtime_deps_file = + "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.runtime_deps" + _runtime_deps_target = "${target_name}__write_deps" + group(_runtime_deps_target) { + forward_variables_from(invoker, + [ + "data", + "deps", + "public_deps", + ]) + data_deps = [] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + if (defined(invoker.additional_apks)) { + data_deps += invoker.additional_apks + } + write_runtime_deps = _runtime_deps_file + } + } + + if (defined(invoker.apk_under_test)) { + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file("${target_name}__install_artifacts") { + deps = [ invoker.apk_under_test ] + output_conversion = "json" + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + walk_keys = [ "install_artifacts_barrier" ] + rebase = root_build_dir + } + } + + generate_android_wrapper(target_name) { + wrapper_script = "$root_build_dir/bin/run_${_test_name}" + + executable = "//testing/test_env.py" + + if (defined(android_test_runner_script)) { + _runner_script = android_test_runner_script + } else { + _runner_script = "//build/android/test_runner.py" + } + + deps = [] + if (defined(invoker.deps)) { + deps = invoker.deps + } + data_deps = [ + "//build/android:test_runner_py", + "//testing:test_scripts_shared", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + data = [] + if (defined(invoker.data)) { + data += invoker.data + } + + executable_args = [ + "@WrappedPath(" + rebase_path(_runner_script, root_build_dir) + ")", + _test_type, + "--output-directory", + "@WrappedPath(.)", + ] + + if (_runtime_deps) { + deps += [ ":$_runtime_deps_target" ] + data += [ _runtime_deps_file ] + _rebased_runtime_deps_file = + rebase_path(_runtime_deps_file, root_build_dir) + executable_args += [ + "--runtime-deps-path", + "@WrappedPath(${_rebased_runtime_deps_file})", + ] + } + + # apk_target is not used for native executable tests + # (e.g. breakpad_unittests). + if (defined(invoker.apk_target)) { + assert(!defined(invoker.executable_dist_dir)) + deps += [ "${invoker.apk_target}$build_config_target_suffix" ] + _apk_build_config = + get_label_info(invoker.apk_target, "target_gen_dir") + "/" + + get_label_info(invoker.apk_target, "name") + ".build_config.json" + _rebased_apk_build_config = rebase_path(_apk_build_config, root_build_dir) + not_needed([ "_rebased_apk_build_config" ]) + } else if (_test_type == "gtest") { + assert( + defined(invoker.executable_dist_dir), + "Must define either apk_target or executable_dist_dir for test_runner_script()") + _rebased_executable_dist_dir = + rebase_path(invoker.executable_dist_dir, root_build_dir) + executable_args += [ + "--executable-dist-dir", + "@WrappedPath(${_rebased_executable_dist_dir})", + ] + } + + _device_test = true + if (_test_type == "gtest") { + assert(defined(invoker.test_suite)) + executable_args += [ + "--suite", + invoker.test_suite, + ] + if (use_clang_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "instrumentation") { + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))" + if (_incremental_apk) { + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_apk_path))" + } + _rebased_test_jar = rebase_path(invoker.test_jar, root_build_dir) + executable_args += [ + "--test-apk", + _test_apk, + "--test-jar", + "@WrappedPath(${_rebased_test_jar})", + ] + if (defined(invoker.apk_under_test)) { + if (_incremental_apk) { + deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ] + _apk_under_test_build_config = + get_label_info(invoker.apk_under_test, "target_gen_dir") + "/" + + get_label_info(invoker.apk_under_test, "name") + + ".build_config.json" + _rebased_apk_under_test_build_config = + rebase_path(_apk_under_test_build_config, root_build_dir) + _apk_under_test = "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path))" + } else { + deps += [ ":${target_name}__install_artifacts" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _apk_under_test = + "@WrappedPath(@FileArg($_rebased_install_artifacts_json[]))" + } + executable_args += [ + "--apk-under-test", + _apk_under_test, + ] + } + if (defined(invoker.use_webview_provider)) { + deps += [ "${invoker.use_webview_provider}$build_config_target_suffix" ] + _build_config = + get_label_info(invoker.use_webview_provider, "target_gen_dir") + + "/" + get_label_info(invoker.use_webview_provider, "name") + + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + executable_args += [ + "--use-webview-provider", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", + ] + } + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled && + !_incremental_apk) { + executable_args += [ "--enable-java-deobfuscation" ] + } + if (use_jacoco_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "junit") { + assert(defined(invoker.test_suite)) + _device_test = false + executable_args += [ + "--test-suite", + invoker.test_suite, + ] + + deps += [ ":${invoker.test_suite}$build_config_target_suffix" ] + _junit_binary_build_config = + "${target_gen_dir}/${invoker.test_suite}.build_config.json" + + _rebased_robolectric_runtime_deps_dir = + rebase_path("$root_build_dir/lib.java/third_party/robolectric", + root_build_dir) + _rebased_resource_apk = rebase_path(invoker.resource_apk, root_build_dir) + executable_args += [ + "--resource-apk", + "@WrappedPath(${_rebased_resource_apk})", + "--robolectric-runtime-deps-dir", + "@WrappedPath(${_rebased_robolectric_runtime_deps_dir})", + ] + if (use_jacoco_coverage) { + # Set a default coverage output directory (can be overridden by user + # passing the same flag). + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ + "--coverage-dir", + "@WrappedPath(${_rebased_coverage_dir})", + ] + } + } else if (_test_type == "linker") { + executable_args += [ + "--test-apk", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))", + ] + } else { + assert(false, "Invalid test type: $_test_type.") + } + + if (defined(invoker.additional_apks)) { + foreach(additional_apk, invoker.additional_apks) { + deps += [ "$additional_apk$build_config_target_suffix" ] + _build_config = + get_label_info(additional_apk, "target_gen_dir") + "/" + + get_label_info(additional_apk, "name") + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + executable_args += [ + "--additional-apk", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", + ] + } + } + if (defined(invoker.shard_timeout)) { + executable_args += [ "--shard-timeout=${invoker.shard_timeout}" ] + } + if (_incremental_apk) { + executable_args += [ + "--test-apk-incremental-install-json", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_install_json_path))", + ] + if (defined(invoker.apk_under_test)) { + executable_args += [ + "--apk-under-test-incremental-install-json", + "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_install_json_path))", + ] + } + executable_args += [ "--fast-local-dev" ] + } + if (_device_test && is_asan) { + executable_args += [ "--tool=asan" ] + } + + if (defined(invoker.modules)) { + foreach(module, invoker.modules) { + executable_args += [ + "--module", + module, + ] + } + } + + if (defined(invoker.fake_modules)) { + foreach(fake_module, invoker.fake_modules) { + executable_args += [ + "--fake-module", + fake_module, + ] + } + } + + if (defined(invoker.additional_locales)) { + foreach(locale, invoker.additional_locales) { + executable_args += [ + "--additional-locale", + locale, + ] + } + } + + if (defined(invoker.extra_args)) { + executable_args += invoker.extra_args + } + } +} + +if (enable_java_templates) { + template("android_lint") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + if (!defined(deps)) { + deps = [] + } + + # https://crbug.com/1098752 Fix for bot OOM (https://crbug.com/1098333). + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + + # Lint requires generated sources and generated resources from the build. + # Turbine __header targets depend on all generated sources, and the + # __assetres targets depend on all generated resources. + if (defined(invoker.deps)) { + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != + []) { + deps += [ + "${_target_label}__assetres", + "${_target_label}__header", + ] + } else { + # Keep non-java deps as they may generate files used only by lint. + # e.g. generated suppressions.xml files. + deps += [ _dep ] + } + } + } + + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } else { + _min_sdk_version = default_min_sdk_version + } + + _lint_binary_path = "$lint_android_sdk_root/cmdline-tools/latest/bin/lint" + _cache_dir = "$root_build_dir/android_lint_cache" + + # Save generated xml files in a consistent location for debugging. + _lint_gen_dir = "$target_gen_dir/$target_name" + _backported_methods = "//third_party/r8/backported_methods.txt" + + script = "//build/android/gyp/lint.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [ + _lint_binary_path, + _backported_methods, + ] + + args = [ + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + "--depfile", + rebase_path(depfile, root_build_dir), + "--lint-binary-path", + rebase_path(_lint_binary_path, root_build_dir), + "--cache-dir", + rebase_path(_cache_dir, root_build_dir), + "--lint-gen-dir", + rebase_path(_lint_gen_dir, root_build_dir), + "--android-sdk-version=${lint_android_sdk_version}", + "--min-sdk-version=$_min_sdk_version", + "--android-sdk-root", + rebase_path(lint_android_sdk_root, root_build_dir), + "--backported-methods", + rebase_path(_backported_methods, root_build_dir), + ] + + if (defined(invoker.skip_build_server) && invoker.skip_build_server) { + # Nocompile tests need lint to fail through ninja. + args += [ "--skip-build-server" ] + } + + if (defined(invoker.lint_suppressions_file)) { + inputs += [ invoker.lint_suppressions_file ] + + args += [ + "--config-path", + rebase_path(invoker.lint_suppressions_file, root_build_dir), + ] + } + + if (defined(testonly) && testonly) { + # Allows us to ignore unnecessary checks when linting test targets. + args += [ "--testonly" ] + } + + if (defined(invoker.manifest_package)) { + args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.lint_baseline_file)) { + if (compute_inputs_for_analyze) { + # The baseline file is included in lint.py as a depfile dep. Since + # removing it regenerates the file, it is useful to not have this as + # a gn input during local development. Add it only for bots' analyze. + inputs += [ invoker.lint_baseline_file ] + } + args += [ + # Baseline allows us to turn on lint warnings without fixing all the + # pre-existing issues. This stops the flood of new issues while the + # existing ones are being fixed. + "--baseline", + rebase_path(invoker.lint_baseline_file, root_build_dir), + ] + } + + if (defined(invoker.create_cache) && invoker.create_cache) { + # Putting the stamp file in the cache dir allows us to depend on ninja + # to create the cache dir for us. + _stamp_path = "$_cache_dir/build.lint.stamp" + args += [ "--create-cache" ] + } else { + _stamp_path = "$target_out_dir/$target_name/build.lint.stamp" + deps += [ + "//build/android:prepare_android_lint_cache", + invoker.build_config_dep, + ] + inputs += [ invoker.build_config ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + + args += [ + "--manifest-path=@FileArg($_rebased_build_config:deps_info:lint_android_manifest)", + "--extra-manifest-paths=@FileArg($_rebased_build_config:deps_info:lint_extra_android_manifests)", + + # Lint requires all source and all resource files to be passed in the + # same invocation for checks like UnusedResources. + "--java-sources=@FileArg($_rebased_build_config:deps_info:lint_java_sources)", + "--aars=@FileArg($_rebased_build_config:deps_info:lint_aars)", + "--srcjars=@FileArg($_rebased_build_config:deps_info:lint_srcjars)", + "--resource-sources=@FileArg($_rebased_build_config:deps_info:lint_resource_sources)", + "--resource-zips=@FileArg($_rebased_build_config:deps_info:lint_resource_zips)", + + # The full classpath is required for annotation checks like @IntDef. + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + ] + } + + outputs = [ _stamp_path ] + args += [ + "--stamp", + rebase_path(_stamp_path, root_build_dir), + ] + } + } + + template("proguard") { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "public_deps", + ]) + _script = "//build/android/gyp/proguard.py" + _deps = invoker.deps + + _inputs = [ + invoker.build_config, + _r8_path, + ] + if (defined(invoker.inputs)) { + _inputs += invoker.inputs + } + if (defined(invoker.proguard_mapping_path)) { + _mapping_path = invoker.proguard_mapping_path + } else { + _mapping_path = "${invoker.output_path}.mapping" + } + + _enable_jdk_library_desugaring = enable_jdk_library_desugaring + if (defined(invoker.supports_jdk_library_desugaring) && + !invoker.supports_jdk_library_desugaring) { + _enable_jdk_library_desugaring = false + } + + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _args = [ + "--mapping-output", + rebase_path(_mapping_path, root_build_dir), + "--classpath", + "@FileArg($_rebased_build_config:deps_info:proguard_classpath_jars)", + "--classpath", + "@FileArg($_rebased_build_config:android:sdk_jars)", + "--r8-path", + rebase_path(_r8_path, root_build_dir), + ] + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + + if ((!defined(invoker.proguard_enable_obfuscation) || + invoker.proguard_enable_obfuscation) && enable_proguard_obfuscation) { + _proguard_sourcefile_suffix = "" + if (defined(invoker.proguard_sourcefile_suffix)) { + _proguard_sourcefile_suffix = "-${invoker.proguard_sourcefile_suffix}" + } + + # This is generally the apk name, and serves to identify the mapping + # file that would be required to deobfuscate a stacktrace. + _mapping_id = get_path_info(_mapping_path, "name") + _args += [ + "--enable-obfuscation", + "--sourcefile", + "chromium-${_mapping_id}${_proguard_sourcefile_suffix}", + ] + } else if (defined(invoker.proguard_sourcefile_suffix)) { + not_needed(invoker, [ "proguard_sourcefile_suffix" ]) + } + + if (defined(invoker.modules)) { + foreach(_feature_module, invoker.modules) { + _rebased_module_build_config = + rebase_path(_feature_module.build_config, root_build_dir) + _args += [ + "--feature-name=${_feature_module.name}", + "--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)", + "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:device_classpath)", + ] + if (defined(_feature_module.uses_split)) { + _args += [ "--uses-split=${_feature_module.name}:${_feature_module.uses_split}" ] + } + _deps += [ _feature_module.build_config_target ] + } + _stamp = "${target_gen_dir}/${target_name}.r8.stamp" + _outputs = [ _stamp ] + _output_arg = [ + "--stamp", + rebase_path(_stamp, root_build_dir), + ] + } else { + # We don't directly set the output arg on the _args variable since it is + # shared with the expectation target that uses its own stamp file and + # does not take an --output-path. + _output_arg = [ + "--output-path", + rebase_path(invoker.output_path, root_build_dir), + ] + _outputs = [ invoker.output_path ] + } + _outputs += [ _mapping_path ] + + if (defined(invoker.disable_r8_outlining) && invoker.disable_r8_outlining) { + _args += [ "--disable-outlining" ] + } + + if (defined(invoker.enable_proguard_checks) && + !invoker.enable_proguard_checks) { + _args += [ "--disable-checks" ] + } + + if (defined(invoker.is_static_library) && invoker.is_static_library) { + _args += [ + "--extra-mapping-output-paths", + "@FileArg($_rebased_build_config:deps_info:static_library_proguard_mapping_output_paths)", + ] + } + + if (_enable_jdk_library_desugaring) { + _args += [ + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + ] + _inputs += [ _desugar_jdk_libs_json ] + + _args += [ + "--desugar-jdk-libs-jar", + rebase_path(_desugar_jdk_libs_jar, root_build_dir), + "--desugar-jdk-libs-configuration-jar", + rebase_path(_desugar_jdk_libs_configuration_jar, root_build_dir), + ] + _inputs += [ + _desugar_jdk_libs_jar, + _desugar_jdk_libs_configuration_jar, + ] + + _desugared_library_keep_rule_output_path = + "$target_gen_dir/$target_name.desugared_library_keep_rules.flags" + _args += [ + "--desugared-library-keep-rule-output", + rebase_path(_desugared_library_keep_rule_output_path, root_build_dir), + ] + } + _ignore_desugar_missing_deps = + defined(invoker.ignore_desugar_missing_deps) && + invoker.ignore_desugar_missing_deps + if (!_ignore_desugar_missing_deps) { + _args += [ "--show-desugar-default-interface-warnings" ] + } + + if (enable_java_asserts) { + # The default for generating dex file format is + # --force-disable-assertions. + _args += [ "--force-enable-assertions" ] + } + + if (defined(invoker.args)) { + _args += invoker.args + } + + if (defined(invoker.expected_proguard_config)) { + _expectations_target = + "${invoker.top_target_name}_validate_proguard_config" + action_with_pydeps(_expectations_target) { + script = _script + + # Need to depend on all deps so that proguard.txt within .aar files get + # extracted. + deps = _deps + depfile = "${target_gen_dir}/${target_name}.d" + inputs = [ + invoker.build_config, + invoker.expected_proguard_config, + ] + _actual_file = "$target_gen_dir/$target_name.proguard_configs" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_proguard_config, "/", "_") + outputs = [ + _actual_file, + _failure_file, + ] + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--expected-file", + rebase_path(invoker.expected_proguard_config, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_proguard_config_base)) { + inputs += [ invoker.expected_proguard_config_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_proguard_config_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + action_with_pydeps(target_name) { + script = _script + deps = _deps + inputs = _inputs + outputs = _outputs + depfile = "${target_gen_dir}/${target_name}.d" + args = _args + _output_arg + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + } + + # Generates a script in the build bin directory to run a java binary. + # + # Variables + # main_class: The class containing the program entry point. + # build_config: Path to .build_config.json for the jar (contains classpath). + # script_name: Name of the script to generate. + # wrapper_script_args: List of extra arguments to pass to the executable. + # tiered_stop_at_level_one: Whether to pass --tiered-stop-at-level-one + # + template("java_binary_script") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + + _main_class = invoker.main_class + _build_config = invoker.build_config + _script_name = invoker.script_name + + script = "//build/android/gyp/create_java_binary_script.py" + inputs = [ _build_config ] + _java_script = "$root_build_dir/bin/$_script_name" + outputs = [ _java_script ] + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args = [ + "--output", + rebase_path(_java_script, root_build_dir), + "--main-class", + _main_class, + ] + args += [ + "--classpath=@FileArg($_rebased_build_config:deps_info:host_classpath)", + ] + + if (use_jacoco_coverage) { + args += [ + "--classpath", + rebase_path("//third_party/jacoco/lib/jacocoagent.jar", + root_build_dir), + ] + } + if (use_jacoco_coverage || !treat_warnings_as_errors) { + args += [ "--noverify" ] + } + if (defined(invoker.tiered_stop_at_level_one) && + invoker.tiered_stop_at_level_one) { + args += [ "--tiered-stop-at-level-one" ] + } + if (defined(invoker.wrapper_script_args)) { + args += [ "--" ] + invoker.wrapper_script_args + } + } + } + + # Variables + # apply_mapping: The path to the ProGuard mapping file to apply. + # disable_incremental: Disable incremental dexing. + template("dex") { + _min_sdk_version = default_min_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + _is_dex_merging = defined(invoker.input_dex_filearg) + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21 + _enable_desugar = !defined(invoker.enable_desugar) || invoker.enable_desugar + _use_classic_desugar = + defined(invoker.use_classic_desugar) && invoker.use_classic_desugar + _desugar_needs_classpath = _enable_desugar && !_use_classic_desugar + + # It's not safe to dex merge with libraries dex'ed at higher api versions. + assert(!_is_dex_merging || _min_sdk_version >= default_min_sdk_version) + + # For D8's backported method desugaring to work properly, the dex merge step + # must not be set to a higher minSdkVersion than it was for the libraries. + if (_enable_desugar && _is_dex_merging) { + _min_sdk_version = default_min_sdk_version + } + + assert(defined(invoker.output) || + (_proguard_enabled && defined(invoker.modules))) + assert(!_proguard_enabled || !(defined(invoker.input_dex_filearg) || + defined(invoker.input_classes_filearg) || + defined(invoker.input_class_jars)), + "Cannot explicitly set inputs when proguarding a dex.") + + # Dex merging should not also be dexing. + assert(!(_is_dex_merging && defined(invoker.input_classes_filearg))) + assert(!(_is_dex_merging && defined(invoker.input_class_jars))) + + assert(!(defined(invoker.apply_mapping) && !_proguard_enabled), + "apply_mapping can only be specified if proguard is enabled.") + + if (_enable_main_dex_list) { + _main_dex_rules = "//build/android/main_dex_classes.flags" + } + + if (_desugar_needs_classpath || _proguard_enabled) { + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + } + + if (_proguard_enabled) { + _proguard_target_name = target_name + + proguard(_proguard_target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "build_config", + "data", + "data_deps", + "deps", + "desugar_jars_paths", + "disable_r8_outlining", + "enable_proguard_checks", + "expected_proguard_config", + "expected_proguard_config_base", + "ignore_desugar_missing_deps", + "is_static_library", + "modules", + "proguard_enable_obfuscation", + "proguard_mapping_path", + "proguard_sourcefile_suffix", + "supports_jdk_library_desugaring", + "top_target_name", + ]) + inputs = [] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + if (defined(invoker.proguard_configs)) { + inputs += invoker.proguard_configs + } + + args = [ + "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", + "--min-api=$_min_sdk_version", + ] + if (defined(invoker.has_apk_under_test) && invoker.has_apk_under_test) { + args += [ "--input-paths=@FileArg($_rebased_build_config:deps_info:device_classpath_extended)" ] + } else { + args += [ "--input-paths=@FileArg($_rebased_build_config:deps_info:device_classpath)" ] + } + if (_use_classic_desugar) { + deps += [ "//third_party/bazel/desugar:desugar_runtime_java" ] + inputs += [ _desugar_runtime_jar ] + args += [ + "--input-paths", + rebase_path(_desugar_runtime_jar, root_build_dir), + ] + } + if (defined(invoker.proguard_args)) { + args += invoker.proguard_args + } + + if (defined(invoker.apply_mapping)) { + _rebased_apply_mapping_path = + rebase_path(invoker.apply_mapping, root_build_dir) + args += [ "--apply-mapping=$_rebased_apply_mapping_path" ] + } + + if (_enable_main_dex_list) { + if (defined(invoker.extra_main_dex_proguard_config)) { + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + inputs += [ invoker.extra_main_dex_proguard_config ] + } + args += [ + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + ] + inputs += [ _main_dex_rules ] + } + + if (defined(invoker.output)) { + output_path = invoker.output + } else if (!defined(proguard_mapping_path)) { + proguard_mapping_path = "$target_out_dir/$target_name.mapping" + } + } + } else { # !_proguard_enabled + _is_library = defined(invoker.is_library) && invoker.is_library + _input_class_jars = [] + if (defined(invoker.input_class_jars)) { + _input_class_jars = invoker.input_class_jars + } + _deps = invoker.deps + + if (!_is_library && _use_classic_desugar) { + # It would be more efficient to use the pre-dex'ed copy of the runtime, + # but it's easier to add it in this way. + _deps += [ "//third_party/bazel/desugar:desugar_runtime_java" ] + _input_class_jars += [ _desugar_runtime_jar ] + } + if (_input_class_jars != []) { + _rebased_input_class_jars = + rebase_path(_input_class_jars, root_build_dir) + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + ]) + script = "//build/android/gyp/dex.py" + deps = _deps + depfile = "$target_gen_dir/$target_name.d" + outputs = [ invoker.output ] + inputs = [ + _r8_path, + _custom_d8_path, + ] + + if (!_is_library) { + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(outputs[0], root_build_dir), + "--min-api=$_min_sdk_version", + "--r8-jar-path", + rebase_path(_r8_path, root_build_dir), + "--custom-d8-jar-path", + rebase_path(_custom_d8_path, root_build_dir), + + # Uncomment when rebuilding custom_d8.jar. + #"--skip-custom-d8", + ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (enable_incremental_d8 && !(defined(invoker.disable_incremental) && + invoker.disable_incremental)) { + # Don't use incremental dexing for ProGuarded inputs as a precaution. + args += [ + "--incremental-dir", + rebase_path("$target_out_dir/$target_name", root_build_dir), + ] + } + + if (_enable_multidex) { + args += [ "--multi-dex" ] + if (_enable_main_dex_list) { + if (defined(invoker.extra_main_dex_proguard_config)) { + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + inputs += [ invoker.extra_main_dex_proguard_config ] + } + args += [ + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + ] + inputs += [ _main_dex_rules ] + } + } + if (_is_library) { + args += [ "--library" ] + } + if (defined(invoker.input_dex_filearg)) { + inputs += [ invoker.build_config ] + args += [ "--dex-inputs-filearg=${invoker.input_dex_filearg}" ] + } + if (defined(invoker.input_classes_filearg)) { + inputs += [ invoker.build_config ] + args += [ "--class-inputs-filearg=${invoker.input_classes_filearg}" ] + } + if (_input_class_jars != []) { + inputs += _input_class_jars + args += [ "--class-inputs=${_rebased_input_class_jars}" ] + } + + if (defined(invoker.dexlayout_profile)) { + args += [ + "--dexlayout-profile", + rebase_path(invoker.dexlayout_profile, root_build_dir), + "--dexlayout-path", + rebase_path(_dexlayout_path, root_build_dir), + "--profman-path", + rebase_path(_profman_path, root_build_dir), + "--dexdump-path", + rebase_path(_dexdump_path, root_build_dir), + ] + inputs += [ + _dexlayout_path, + _profman_path, + _dexdump_path, + invoker.dexlayout_profile, + ] + inputs += _default_art_libs + } + + # Never compile intemediates with --release in order to: + # 1) not require recompiles when toggling is_java_debug, + # 2) allow incremental_install=1 to still have local variable + # information even when is_java_debug=false. + if (!is_java_debug && !_is_library) { + args += [ "--release" ] + } + + if (_enable_desugar) { + args += [ "--desugar" ] + + # Passing the flag for dex merging causes invalid dex files to be created. + if (enable_jdk_library_desugaring && !_is_dex_merging) { + inputs += [ _desugar_jdk_libs_json ] + args += [ + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + ] + } + _ignore_desugar_missing_deps = + defined(invoker.ignore_desugar_missing_deps) && + invoker.ignore_desugar_missing_deps + if (!_ignore_desugar_missing_deps && !_use_classic_desugar) { + args += [ "--show-desugar-default-interface-warnings" ] + } + } + if (_desugar_needs_classpath) { + _desugar_dependencies_path = + "$target_gen_dir/$target_name.desugardeps" + args += [ + "--desugar-dependencies", + rebase_path(_desugar_dependencies_path, root_build_dir), + "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_jars)", + + # Pass the full classpath to find new dependencies that are not in + # the .desugardeps file. + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + ] + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + if (defined(invoker.final_ijar_path)) { + # Need to include the input .interface.jar on the classpath in order to make + # jar_excluded_patterns classes visible to desugar. + args += [ + "--classpath", + rebase_path(invoker.final_ijar_path, root_build_dir), + ] + inputs += [ invoker.final_ijar_path ] + } + } else { + not_needed(invoker, [ "desugar_jars_paths" ]) + } + + if (enable_java_asserts) { + # The default for generating dex file format is + # --force-disable-assertions. + args += [ "--force-enable-assertions" ] + } + } + } + } + + # Variables + # output: Path to output ".l8.dex". + # min_sdk_version: The minimum Android SDK version this target supports. + template("dex_jdk_libs") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/dex_jdk_libs.py" + inputs = [ + _r8_path, + _desugar_jdk_libs_json, + _desugar_jdk_libs_jar, + _desugar_jdk_libs_configuration_jar, + ] + outputs = [ invoker.output ] + args = [ + "--r8-path", + rebase_path(_r8_path, root_build_dir), + "--desugar-jdk-libs-json", + rebase_path(_desugar_jdk_libs_json, root_build_dir), + "--desugar-jdk-libs-jar", + rebase_path(_desugar_jdk_libs_jar, root_build_dir), + "--desugar-jdk-libs-configuration-jar", + rebase_path(_desugar_jdk_libs_configuration_jar, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--min-api=${invoker.min_sdk_version}", + ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + } + + template("jacoco_instr") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "public_deps", + ]) + + # The name needs to match the SOURCES_JSON_FILES_SUFFIX in + # generate_coverage_metadata_for_java.py. + _sources_json_file = "$target_out_dir/${target_name}__jacoco_sources.json" + _jacococli_jar = "//third_party/jacoco/lib/jacococli.jar" + + script = "//build/android/gyp/jacoco_instr.py" + inputs = invoker.java_files + [ + _jacococli_jar, + invoker.input_jar_path, + ] + outputs = [ + _sources_json_file, + invoker.output_jar_path, + ] + args = [ + "--input-path", + rebase_path(invoker.input_jar_path, root_build_dir), + "--output-path", + rebase_path(invoker.output_jar_path, root_build_dir), + "--sources-json-file", + rebase_path(_sources_json_file, root_build_dir), + "--java-sources-file", + rebase_path(invoker.java_sources_file, root_build_dir), + "--jacococli-jar", + rebase_path(_jacococli_jar, root_build_dir), + ] + if (coverage_instrumentation_input_file != "") { + args += [ + "--files-to-instrument", + rebase_path(coverage_instrumentation_input_file, root_build_dir), + ] + } + } + } + + template("filter_jar") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/filter_zip.py" + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = [ invoker.input_jar ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + outputs = [ invoker.output_jar ] + + _jar_excluded_patterns = [] + if (defined(invoker.jar_excluded_patterns)) { + _jar_excluded_patterns = invoker.jar_excluded_patterns + } + _jar_included_patterns = [] + if (defined(invoker.jar_included_patterns)) { + _jar_included_patterns = invoker.jar_included_patterns + } + args = [ + "--input", + rebase_path(invoker.input_jar, root_build_dir), + "--output", + rebase_path(invoker.output_jar, root_build_dir), + "--exclude-globs=${_jar_excluded_patterns}", + "--include-globs=${_jar_included_patterns}", + ] + } + } + + template("process_java_library") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = invoker.jar_deps + _previous_output_jar = invoker.input_jar_path + + if (invoker.is_device_jar && invoker.enable_desugar) { + _desugar_target = "${target_name}_device__desugar" + _desugar_output_jar = "$target_out_dir/$target_name.desugar.jar" + + action_with_pydeps(_desugar_target) { + script = "//build/android/gyp/desugar.py" + deps = _deps + invoker.classpath_deps + depfile = "$target_gen_dir/$target_name.d" + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + _desugar_jar = "//third_party/bazel/desugar/Desugar.jar" + + inputs = [ + invoker.build_config, + _previous_output_jar, + _desugar_jar, + ] + outputs = [ _desugar_output_jar ] + args = [ + "--desugar-jar", + rebase_path(_desugar_jar, root_build_dir), + "--input-jar", + rebase_path(_previous_output_jar, root_build_dir), + "--output-jar", + rebase_path(_desugar_output_jar, root_build_dir), + + # Temporarily using java_full_interface_classpath until classpath validation of targets + # is implemented, see http://crbug.com/885273 + "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)", + "--depfile", + rebase_path(depfile, root_build_dir), + ] + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + + _deps = [] + _deps = [ ":$_desugar_target" ] + _previous_output_jar = _desugar_output_jar + } + + if (invoker.jacoco_instrument) { + _filter_jar_target_name = "${target_name}__filter_jar" + _filter_jar_output_jar = "$target_out_dir/$target_name.filter.jar" + } else { + _filter_jar_target_name = target_name + _filter_jar_output_jar = invoker.output_jar_path + } + + filter_jar(_filter_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + deps = _deps + input_jar = _previous_output_jar + output_jar = _filter_jar_output_jar + } + + if (invoker.jacoco_instrument) { + # Jacoco must run after desugar (or else desugar sometimes fails). + # It must run after filtering to avoid the same (filtered) class mapping + # to multiple .jar files. + # We run offline code coverage processing here rather than with a + # javaagent as the desired coverage data was not being generated. + # See crbug.com/1097815. + jacoco_instr(target_name) { + deps = [ ":$_filter_jar_target_name" ] + invoker.jar_deps + forward_variables_from(invoker, + [ + "java_files", + "java_sources_file", + ]) + + input_jar_path = _filter_jar_output_jar + output_jar_path = invoker.output_jar_path + } + } + } + + template("bytecode_processor") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _bytecode_checker_script = "$root_build_dir/bin/helper/bytecode_processor" + script = "//build/android/gyp/bytecode_processor.py" + inputs = [ + invoker.build_config, + invoker.input_jar, + _bytecode_checker_script, + ] + outputs = [ "$target_out_dir/$target_name.bytecode.stamp" ] + deps = + invoker.deps + + [ "//build/android/bytecode:bytecode_processor($default_toolchain)" ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + args = [ + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + "--script", + rebase_path(_bytecode_checker_script, root_build_dir), + "--gn-target=${invoker.target_label}", + "--input-jar", + rebase_path(invoker.input_jar, root_build_dir), + "--stamp", + rebase_path(outputs[0], root_build_dir), + "--direct-classpath-jars=@FileArg($_rebased_build_config:javac:classpath)", + "--full-classpath-jars=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--full-classpath-gn-targets=@FileArg($_rebased_build_config:deps_info:javac_full_classpath_targets)", + ] + if (invoker.requires_android) { + args += [ "--sdk-classpath-jars=@FileArg($_rebased_build_config:android:sdk_jars)" ] + } + if (invoker.is_prebuilt) { + args += [ "--is-prebuilt" ] + } + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + if (defined(invoker.missing_classes_allowlist)) { + args += [ + "--missing-classes-allowlist=${invoker.missing_classes_allowlist}", + ] + } + } + } + + template("merge_manifests") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/merge_manifest.py" + depfile = "$target_gen_dir/$target_name.d" + + inputs = [ + invoker.build_config, + invoker.input_manifest, + ] + + outputs = [ invoker.output_manifest ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--android-sdk-cmdline-tools", + rebase_path("${public_android_sdk_root}/cmdline-tools/latest", + root_build_dir), + "--root-manifest", + rebase_path(invoker.input_manifest, root_build_dir), + "--output", + rebase_path(invoker.output_manifest, root_build_dir), + "--extras", + "@FileArg($_rebased_build_config:extra_android_manifests)", + "--min-sdk-version=${invoker.min_sdk_version}", + "--target-sdk-version=${invoker.target_sdk_version}", + ] + + if (defined(invoker.manifest_package)) { + args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (defined(invoker.max_sdk_version)) { + args += [ "--max-sdk-version=${invoker.max_sdk_version}" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + } + + # This template is used to parse a set of resource directories and + # create the R.txt, .srcjar and .resources.zip for it. + # + # Input variables: + # deps: Specifies the input dependencies for this target. + # + # build_config: Path to the .build_config.json file corresponding to the target. + # + # sources: + # List of input resource files. + # + # custom_package: (optional) + # Package name for the generated R.java source file. Optional if + # android_manifest is not provided. + # + # android_manifest: (optional) + # If custom_package is not provided, path to an AndroidManifest.xml file + # that is only used to extract a package name out of it. + # + # r_text_in_path: (optional) + # Path to an input R.txt file to use to generate the R.java file. + # The default is to use 'aapt' to generate the file from the content + # of the resource directories. + # + # Output variables: + # resources_zip: + # Path to a .resources.zip that will simply contain all the + # input resources, collected in a single archive. + # + # r_text_out_path: Path for the generated R.txt file. + # + template("prepare_resources") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "sources", + ]) + script = "//build/android/gyp/prepare_resources.py" + + depfile = "$target_gen_dir/${invoker.target_name}.d" + outputs = [ + invoker.resources_zip, + invoker.resources_zip + ".info", + invoker.r_text_out_path, + ] + + inputs = [ invoker.res_sources_path ] + + _rebased_res_sources_path = + rebase_path(invoker.res_sources_path, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--res-sources-path=$_rebased_res_sources_path", + "--resource-zip-out", + rebase_path(invoker.resources_zip, root_build_dir), + "--r-text-out", + rebase_path(invoker.r_text_out_path, root_build_dir), + ] + + if (defined(invoker.r_text_in_path)) { + _r_text_in_path = invoker.r_text_in_path + inputs += [ _r_text_in_path ] + args += [ + "--r-text-in", + rebase_path(_r_text_in_path, root_build_dir), + ] + } + + if (defined(invoker.strip_drawables) && invoker.strip_drawables) { + args += [ "--strip-drawables" ] + } + if (defined(invoker.allow_missing_resources) && + invoker.allow_missing_resources) { + args += [ "--allow-missing-resources" ] + } + } + } + + # A template that is used to compile all resources needed by a binary + # (e.g. an android_apk or a junit_binary) into an intermediate .ar_ + # archive. It can also generate an associated .srcjar that contains the + # final R.java sources for all resource packages the binary depends on. + # + # Input variables: + # android_sdk_dep: The sdk dep that these resources should compile against. + # + # deps: Specifies the input dependencies for this target. + # + # build_config: Path to the .build_config.json file corresponding to the target. + # + # build_config_dep: Dep target to generate the .build_config.json file. + # + # android_manifest: Path to root manifest for the binary. + # + # version_code: (optional) + # + # version_name: (optional) + # + # shared_resources: (optional) + # If true, make all variables in each generated R.java file non-final, + # and provide an onResourcesLoaded() method that can be used to reset + # their package index at load time. Useful when the APK corresponds to + # a library that is loaded at runtime, like system_webview_apk or + # monochrome_apk. + # + # app_as_shared_lib: (optional) + # If true, same effect as shared_resources, but also ensures that the + # resources can be used by the APK when it is loaded as a regular + # application as well. Useful for the monochrome_public_apk target + # which is both an application and a shared runtime library that + # implements the system webview feature. + # + # shared_resources_allowlist: (optional) + # Path to an R.txt file. If provided, acts similar to shared_resources + # except that it restricts the list of non-final resource variables + # to the list from the input R.txt file. Overrides shared_resources + # when both are specified. + # + # shared_resources_allowlist_locales: (optional) + # If shared_resources_allowlist is used, provide an optional list of + # Chromium locale names to determine which localized shared string + # resources to put in the final output, even if aapt_locale_allowlist + # is defined to a smaller subset. + # + # aapt_locale_allowlist: (optional) + # Restrict compiled locale-dependent resources to a specific allowlist. + # NOTE: This is a list of Chromium locale names, not Android ones. + # + # r_java_root_package_name: (optional) + # Short package name for this target's root R java file (ex. input of + # "base" would become "gen.base_module" for the root R java package name). + # Optional as defaults to "base". + # + # resource_exclusion_regex: (optional) + # + # resource_exclusion_exceptions: (optional) + # + # resource_values_filter_rules: (optional) + # + # no_xml_namespaces: (optional) + # + # png_to_webp: (optional) + # If true, convert all PNG resources (except 9-patch files) to WebP. + # + # post_process_script: (optional) + # + # package_name: (optional) + # Name of the package for the purpose of creating R class. + # + # package_id: (optional) + # Use a custom package ID in resource IDs. + # + # arsc_package_name: (optional) + # Use this package name in the arsc file rather than the package name + # found in the AndroidManifest.xml. Does not affect the package name + # used in AndroidManifest.xml. + # + # resource_ids_provider_dep: (optional) + # Use resource IDs provided by another APK target when compiling resources + # (via. "aapt2 link --stable-ids") + # + # + # Output variables: + # arsc_output: Path to output .ap_ file (optional). + # + # proto_output: Path to output .proto.ap_ file (optional). + # + # r_text_out_path: (optional): + # Path for the corresponding generated R.txt file. + # + # proguard_file: (optional) + # Path to proguard configuration file for this apk target. + # + # proguard_file_main_dex: (optional) + # + template("compile_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = [ + invoker.android_sdk_dep, + invoker.build_config_dep, + ] + if (defined(invoker.android_manifest_dep)) { + _deps += [ invoker.android_manifest_dep ] + } + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != []) { + # Depend on the java libraries' transitive __assetres target instead. + _deps += [ "${_target_label}__assetres" ] + } else { + _deps += [ _dep ] + } + } + + if (defined(invoker.arsc_output)) { + _arsc_output = invoker.arsc_output + } + _final_srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + + _script = "//build/android/gyp/compile_resources.py" + + _inputs = [ + invoker.build_config, + android_sdk_tools_bundle_aapt2, + ] + + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + _args = [ + "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)", + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", + "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)", + "--extra-main-r-text-files=@FileArg($_rebased_build_config:deps_info:extra_main_r_text_files)", + "--min-sdk-version=${invoker.min_sdk_version}", + "--target-sdk-version=${invoker.target_sdk_version}", + "--webp-cache-dir=obj/android-webp-cache", + ] + + _inputs += [ invoker.android_manifest ] + _outputs = [ _final_srcjar_path ] + _args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + "--srcjar-out", + rebase_path(_final_srcjar_path, root_build_dir), + ] + if (defined(invoker.no_xml_namespaces) && invoker.no_xml_namespaces) { + _args += [ "--no-xml-namespaces" ] + } + if (defined(invoker.version_code)) { + _args += [ + "--version-code", + invoker.version_code, + ] + } + if (defined(invoker.version_name)) { + _args += [ + "--version-name", + invoker.version_name, + ] + } + if (defined(_arsc_output)) { + _outputs += [ _arsc_output ] + _args += [ + "--arsc-path", + rebase_path(_arsc_output, root_build_dir), + ] + } + if (defined(invoker.proto_output)) { + _outputs += [ invoker.proto_output ] + _args += [ + "--proto-path", + rebase_path(invoker.proto_output, root_build_dir), + ] + } + if (defined(invoker.size_info_path)) { + _outputs += [ invoker.size_info_path ] + _args += [ + "--info-path", + rebase_path(invoker.size_info_path, root_build_dir), + ] + } + + if (defined(invoker.r_java_root_package_name)) { + _args += [ + "--r-java-root-package-name", + invoker.r_java_root_package_name, + ] + } + + # Useful to have android:debuggable in the manifest even for Release + # builds. Just omit it for officai + if (debuggable_apks) { + _args += [ "--debuggable" ] + } + + if (defined(invoker.r_text_out_path)) { + _outputs += [ invoker.r_text_out_path ] + _args += [ + "--r-text-out", + rebase_path(invoker.r_text_out_path, root_build_dir), + ] + } + + if (defined(invoker.rename_manifest_package)) { + _args += [ + "--rename-manifest-package", + invoker.rename_manifest_package, + ] + } + + # Define the flags related to shared resources. + # + # Note the small sanity check to ensure that the package ID of the + # generated resources table is correct. It should be 0x02 for runtime + # shared libraries, and 0x7f otherwise. + + if (defined(invoker.shared_resources) && invoker.shared_resources) { + _args += [ "--shared-resources" ] + } + if (defined(invoker.app_as_shared_lib) && invoker.app_as_shared_lib) { + _args += [ "--app-as-shared-lib" ] + } + if (defined(invoker.package_id)) { + _args += [ "--package-id=${invoker.package_id}" ] + } + if (defined(invoker.package_name)) { + _args += [ + "--package-name", + invoker.package_name, + ] + } + if (defined(invoker.arsc_package_name)) { + _args += [ + "--arsc-package-name", + invoker.arsc_package_name, + ] + } + + if (defined(invoker.shared_resources_allowlist)) { + _inputs += [ invoker.shared_resources_allowlist ] + _args += [ + "--shared-resources-allowlist", + rebase_path(invoker.shared_resources_allowlist, root_build_dir), + ] + } + if (defined(invoker.shared_resources_allowlist_locales)) { + _args += [ "--shared-resources-allowlist-locales=" + + "${invoker.shared_resources_allowlist_locales}" ] + } + + if (!defined(testonly) || !testonly || + (defined(invoker.enforce_resource_overlays_in_tests) && + invoker.enforce_resource_overlays_in_tests)) { + _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:deps_info:dependency_zip_overlays)" ] + } else { + _args += [ "--dependencies-res-zip-overlays=@FileArg($_rebased_build_config:deps_info:dependency_zips)" ] + } + + if (defined(invoker.proguard_file)) { + _outputs += [ invoker.proguard_file ] + _args += [ + "--proguard-file", + rebase_path(invoker.proguard_file, root_build_dir), + ] + } + + if (defined(invoker.proguard_file_main_dex)) { + _outputs += [ invoker.proguard_file_main_dex ] + _args += [ + "--proguard-file-main-dex", + rebase_path(invoker.proguard_file_main_dex, root_build_dir), + ] + } + + if (defined(invoker.aapt_locale_allowlist)) { + _args += [ "--locale-allowlist=${invoker.aapt_locale_allowlist}" ] + } + if (defined(invoker.png_to_webp) && invoker.png_to_webp) { + _webp_target = "//third_party/libwebp:cwebp($host_toolchain)" + _webp_binary = get_label_info(_webp_target, "root_out_dir") + "/cwebp" + _deps += [ _webp_target ] + _inputs += [ _webp_binary ] + _args += [ + "--png-to-webp", + "--webp-binary", + rebase_path(_webp_binary, root_build_dir), + ] + } + if (defined(invoker.resource_exclusion_regex)) { + _args += + [ "--resource-exclusion-regex=${invoker.resource_exclusion_regex}" ] + if (defined(invoker.resource_exclusion_exceptions)) { + _args += [ "--resource-exclusion-exceptions=${invoker.resource_exclusion_exceptions}" ] + } + } + if (defined(invoker.resource_values_filter_rules)) { + _args += + [ "--values-filter-rules=${invoker.resource_values_filter_rules}" ] + } + + if (defined(invoker.include_resource)) { + _rebased_include_resources = + rebase_path(invoker.include_resource, root_build_dir) + _args += [ "--include-resources=$_rebased_include_resources" ] + } + + if (defined(invoker._args)) { + _args += invoker._args + } + + if (defined(invoker.emit_ids_out_path)) { + _outputs += [ invoker.emit_ids_out_path ] + _rebased_emit_ids_path = + rebase_path(invoker.emit_ids_out_path, root_out_dir) + _args += [ "--emit-ids-out=$_rebased_emit_ids_path" ] + } + + if (defined(invoker.resource_ids_provider_dep)) { + _compile_res_dep = + "${invoker.resource_ids_provider_dep}__compile_resources" + _gen_dir = get_label_info(_compile_res_dep, "target_gen_dir") + _name = get_label_info(_compile_res_dep, "name") + _resource_ids_path = "$_gen_dir/$_name.resource_ids" + _inputs += [ _resource_ids_path ] + _rebased_ids_path = rebase_path(_resource_ids_path, root_out_dir) + _args += [ "--use-resource-ids-path=$_rebased_ids_path" ] + _deps += [ _compile_res_dep ] + } + + if (defined(invoker.max_sdk_version)) { + _max_sdk_version = invoker.max_sdk_version + _args += [ "--max-sdk-version=$_max_sdk_version" ] + } + + if (defined(invoker.manifest_package)) { + _args += [ "--manifest-package=${invoker.manifest_package}" ] + } + + if (defined(invoker.is_bundle_module) && invoker.is_bundle_module) { + _args += [ "--is-bundle-module" ] + } + + if (defined(invoker.uses_split)) { + assert(invoker.is_bundle_module) + _args += [ "--uses-split=${invoker.uses_split}" ] + } + + if (defined(invoker.expected_android_manifest)) { + _expectations_target = + "${invoker.top_target_name}_validate_android_manifest" + action_with_pydeps(_expectations_target) { + _actual_file = "${invoker.android_manifest}.normalized" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_android_manifest, "/", "_") + inputs = [ + invoker.android_manifest, + invoker.build_config, + invoker.expected_android_manifest, + ] + outputs = [ + _actual_file, + _failure_file, + ] + deps = [ + invoker.android_manifest_dep, + invoker.build_config_dep, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_android_manifest, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_android_manifest_base)) { + args += [ + "--expected-file-base", + rebase_path(invoker.expected_android_manifest_base, root_build_dir), + ] + inputs += [ invoker.expected_android_manifest_base ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + if (defined(invoker.extra_verification_manifest)) { + inputs += [ invoker.extra_verification_manifest ] + args += [ + "--extra-verification-manifest", + rebase_path(invoker.extra_verification_manifest, root_build_dir), + ] + if (defined(invoker.extra_verification_manifest_dep)) { + deps += [ invoker.extra_verification_manifest_dep ] + } + } + } + _deps += [ ":$_expectations_target" ] + } + + action_with_pydeps(target_name) { + script = _script + depfile = "$target_gen_dir/${target_name}.d" + inputs = _inputs + outputs = _outputs + deps = _deps + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } + } + + # A template that is used to optimize compiled resources using aapt2 optimize. + # + # proto_input_path: + # Path to input compiled .proto.ap_ file. + # + # short_resource_paths: (optional) + # Rename the paths within a the apk to be randomly generated short + # strings to reduce binary size. + # + # strip_resource_names: (optional) + # Strip resource names from the resources table of the apk. + # + # resources_configs_paths: (optional) + # List of resource configs to use for optimization. + # + # optimized_proto_output: + # Path to output optimized .proto.ap_ file. + # + # resources_path_map_out_path: (optional): + # Path for the generated map between original resource paths and + # shortened resource paths. + template("optimize_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "deps" ]) + script = "//build/android/gyp/optimize_resources.py" + outputs = [ invoker.optimized_proto_output ] + inputs = [ + android_sdk_tools_bundle_aapt2, + invoker.r_text_path, + invoker.proto_input_path, + ] + args = [ + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--r-text-in", + rebase_path(invoker.r_text_path, root_build_dir), + "--proto-path", + rebase_path(invoker.proto_input_path, root_build_dir), + "--optimized-proto-path", + rebase_path(invoker.optimized_proto_output, root_build_dir), + ] + + if (defined(invoker.resources_config_paths)) { + inputs += invoker.resources_config_paths + _rebased_resource_configs = + rebase_path(invoker.resources_config_paths, root_build_dir) + args += [ "--resources-config-paths=${_rebased_resource_configs}" ] + } + + if (defined(invoker.short_resource_paths) && + invoker.short_resource_paths) { + args += [ "--short-resource-paths" ] + if (defined(invoker.resources_path_map_out_path)) { + outputs += [ invoker.resources_path_map_out_path ] + args += [ + "--resources-path-map-out-path", + rebase_path(invoker.resources_path_map_out_path, root_build_dir), + ] + } + } + + if (defined(invoker.strip_resource_names) && + invoker.strip_resource_names) { + args += [ "--strip-resource-names" ] + } + } + } + + # A template that is used to find unused resources. + template("unused_resources") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/unused_resources.py" + depfile = "$target_gen_dir/${target_name}.d" + _unused_resources_script = "$root_build_dir/bin/helper/unused_resources" + inputs = [ _unused_resources_script ] + outputs = [ invoker.output_config ] + if (!defined(deps)) { + deps = [] + } + deps += [ "//build/android/unused_resources:unused_resources" ] + _rebased_module_build_config = + rebase_path(invoker.build_config, root_build_dir) + args = [ + "--script", + rebase_path(_unused_resources_script, root_build_dir), + "--output-config", + rebase_path(invoker.output_config, root_build_dir), + "--r-text=@FileArg($_rebased_module_build_config:deps_info:r_text_path)", + "--dependencies-res-zips=@FileArg($_rebased_module_build_config:deps_info:dependency_zips)", + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + if (defined(invoker.proguard_mapping_path)) { + inputs += [ invoker.proguard_mapping_path ] + args += [ + "--proguard-mapping", + rebase_path(invoker.proguard_mapping_path, root_build_dir), + ] + } + + foreach(_build_config, invoker.all_module_build_configs) { + inputs += [ _build_config ] + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args += [ + "--dexes=@FileArg($_rebased_build_config:final_dex:path)", + "--android-manifests=@FileArg($_rebased_build_config:deps_info:merged_android_manifest)", + ] + } + } + } + + # Create an .jar.info file by merging several .jar.info files into one. + # + # Variables: + # build_config: Path to APK's build config file. Used to extract the + # list of input .jar files from its dependencies. + # name: Name of the apk or app bundle (e.g. "Foo.apk"). + # res_size_info_path: Path to input .ap_.info file (for apks). + # + template("create_size_info_files") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/create_size_info_files.py" + _jar_info_path = "$root_build_dir/size-info/${invoker.name}.jar.info" + _pak_info_path = "$root_build_dir/size-info/${invoker.name}.pak.info" + _res_info_path = "$root_build_dir/size-info/${invoker.name}.res.info" + outputs = [ + _jar_info_path, + _pak_info_path, + _res_info_path, + ] + depfile = "$target_gen_dir/$target_name.d" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--jar-info-path", + rebase_path(_jar_info_path, root_build_dir), + "--pak-info-path", + rebase_path(_pak_info_path, root_build_dir), + "--res-info-path", + rebase_path(_res_info_path, root_build_dir), + ] + _is_bundle = defined(invoker.module_build_configs) + if (_is_bundle) { + inputs = invoker.module_build_configs + foreach(_build_config, invoker.module_build_configs) { + _rebased_build_config = rebase_path(_build_config, root_build_dir) + args += [ + "--jar-files=@FileArg($_rebased_build_config:deps_info:unprocessed_jar_path)", + "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--in-res-info-path=@FileArg($_rebased_build_config:deps_info:res_size_info)", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + ] + } + } else { + inputs = [ + invoker.build_config, + invoker.res_size_info_path, + ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + args += [ + "--jar-files=@FileArg($_rebased_build_config:deps_info:unprocessed_jar_path)", + "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--in-res-info-path", + rebase_path(invoker.res_size_info_path, root_build_dir), + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + ] + } + } + } + + # Creates a signed and aligned .apk. + # + # Variables + # apk_name: (optional) APK name (without .apk suffix). If provided, will + # be used to generate .info files later used by the supersize tool. + # assets_build_config: Path to android_apk .build_config.json containing merged + # asset information. + # deps: Specifies the dependencies of this target. + # dex_path: Path to classes.dex file to include (optional). + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # jdk_libs_dex: Path to classes.dex for desugar_jdk_libs. + # packaged_resources_path: Path to .ap_ to use. + # output_apk_path: Output path for the generated .apk. + # min_sdk_version: The minimum Android SDK version this target supports. + # native_lib_placeholders: List of placeholder filenames to add to the apk + # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). + # loadable_modules: List of native libraries. + # native_libs_filearg: @FileArg() of additionally native libraries. + # secondary_abi_loadable_modules: (optional) List of native libraries for + # secondary ABI. + # secondary_abi_native_libs_filearg: (optional). @FileArg() of additional + # secondary ABI native libs. + # keystore_path: Path to keystore to use for signing. + # keystore_name: Key alias to use. + # keystore_password: Keystore password. + # uncompress_shared_libraries: (optional, default false) Whether to store + # native libraries inside the APK uncompressed and page-aligned. + template("package_apk") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "public_deps" ]) + _deps = invoker.deps + _native_lib_placeholders = [] + if (defined(invoker.native_lib_placeholders)) { + _native_lib_placeholders = invoker.native_lib_placeholders + } + _secondary_native_lib_placeholders = [] + if (defined(invoker.secondary_native_lib_placeholders)) { + _secondary_native_lib_placeholders = + invoker.secondary_native_lib_placeholders + } + + _script = "//build/android/gyp/apkbuilder.py" + _apksigner = "$android_sdk_build_tools/lib/apksigner.jar" + _zipalign = "$android_sdk_build_tools/zipalign" + + _inputs = [ + invoker.build_config, + invoker.keystore_path, + invoker.packaged_resources_path, + _apksigner, + _zipalign, + ] + + _outputs = [ invoker.output_apk_path ] + _data = [ invoker.output_apk_path ] + + _rebased_compiled_resources_path = + rebase_path(invoker.packaged_resources_path, root_build_dir) + _rebased_packaged_apk_path = + rebase_path(invoker.output_apk_path, root_build_dir) + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _args = [ + "--resource-apk=$_rebased_compiled_resources_path", + "--output-apk=$_rebased_packaged_apk_path", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + "--apksigner-jar", + rebase_path(_apksigner, root_build_dir), + "--zipalign-path", + rebase_path(_zipalign, root_build_dir), + "--key-path", + rebase_path(invoker.keystore_path, root_build_dir), + "--key-name", + invoker.keystore_name, + "--key-passwd", + invoker.keystore_password, + "--min-sdk-version=${invoker.min_sdk_version}", + + # TODO(mlopatkin) We are relying on the fact that build_config is an APK + # build_config. + "--java-resources=@FileArg($_rebased_build_config:java_resources_jars)", + ] + if (is_official_build) { + _args += [ "--best-compression" ] + } + if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { + _args += [ "--uncompress-dex" ] + } + if (defined(invoker.uncompress_shared_libraries) && + invoker.uncompress_shared_libraries) { + _args += [ "--uncompress-shared-libraries=True" ] + } + if (defined(invoker.library_always_compress)) { + _args += + [ "--library-always-compress=${invoker.library_always_compress}" ] + } + if (defined(invoker.library_renames)) { + _args += [ "--library-renames=${invoker.library_renames}" ] + } + if (defined(invoker.dex_path)) { + _inputs += [ invoker.dex_path ] + _args += [ + "--dex-file", + rebase_path(invoker.dex_path, root_build_dir), + ] + } + if (defined(invoker.jdk_libs_dex)) { + _inputs += [ invoker.jdk_libs_dex ] + _args += [ + "--jdk-libs-dex-file", + rebase_path(invoker.jdk_libs_dex, root_build_dir), + ] + } + if ((defined(invoker.loadable_modules) && invoker.loadable_modules != []) || + defined(invoker.native_libs_filearg) || + _native_lib_placeholders != []) { + _args += [ "--android-abi=$android_app_abi" ] + } + if (defined(android_app_secondary_abi)) { + _args += [ "--secondary-android-abi=$android_app_secondary_abi" ] + } + if (defined(invoker.loadable_modules) && invoker.loadable_modules != []) { + _inputs += invoker.loadable_modules + _rebased_loadable_modules = + rebase_path(invoker.loadable_modules, root_build_dir) + _args += [ "--native-libs=$_rebased_loadable_modules" ] + } + if (defined(invoker.native_libs_filearg)) { + _args += [ "--native-libs=${invoker.native_libs_filearg}" ] + } + if (_native_lib_placeholders != []) { + _args += [ "--native-lib-placeholders=$_native_lib_placeholders" ] + } + + if (defined(invoker.secondary_abi_native_libs_filearg)) { + _args += [ + "--secondary-native-libs=${invoker.secondary_abi_native_libs_filearg}", + ] + } + if (defined(invoker.secondary_abi_loadable_modules)) { + _rebased_secondary_abi_loadable_modules = + rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) + _args += + [ "--secondary-native-libs=$_rebased_secondary_abi_loadable_modules" ] + } + if (_secondary_native_lib_placeholders != []) { + _args += [ "--secondary-native-lib-placeholders=$_secondary_native_lib_placeholders" ] + } + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.expected_libs_and_assets)) { + _expectations_target = + "${invoker.top_target_name}_validate_libs_and_assets" + action_with_pydeps(_expectations_target) { + _actual_file = "$target_gen_dir/$target_name.libs_and_assets" + _failure_file = + "$expectations_failure_dir/" + + string_replace(invoker.expected_libs_and_assets, "/", "_") + inputs = [ + invoker.build_config, + invoker.expected_libs_and_assets, + ] + deps = [ invoker.build_config_dep ] + outputs = [ + _actual_file, + _failure_file, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_libs_and_assets, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_libs_and_assets_base)) { + inputs += [ invoker.expected_libs_and_assets_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_libs_and_assets_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + action_with_pydeps(target_name) { + depfile = "$target_gen_dir/$target_name.d" + inputs = _inputs + deps = _deps + data = _data + outputs = _outputs + script = _script + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } + } + + # Compile Java source files into a .jar file, potentially using an + # annotation processor, and/or the errorprone compiler. + # + # Note that the only way to specify custom annotation processors is + # by using build_config to point to a file that corresponds to a java-related + # target that includes javac:processor_classes entries (i.e. there is no + # variable here that can be used for this purpose). + # + # Note also the peculiar use of java_files / java_sources_file. The content + # of the java_files list and the java_sources_file file must match exactly. + # This rule uses java_files only to list the inputs to the action that + # calls compile_java.py, but will pass the list of Java source files + # with the '@${java_sources_file}" command-line syntax. Not a problem in + # practice since this is only called from java_library_impl() that sets up + # the variables properly. + # + # Variables: + # main_target_name: Used when extracting srcjars for codesearch. + # java_files: Optional list of Java source file paths. + # srcjar_deps: Optional list of .srcjar dependencies (not file paths). + # The corresponding source files they contain will be compiled too. + # java_sources_file: Optional path to file containing list of Java source + # file paths. This must always be provided if java_files is not empty + # and must match it exactly. + # build_config: Path to the .build_config.json file of the corresponding + # java_library_impl() target. The following entries will be used by this + # template: javac:srcjars, deps_info:javac_full_classpath, + # deps_info:javac_full_interface_classpath, javac:processor_classpath, + # javac:processor_classes + # javac_jar_path: Path to the final output .jar file. + # javac_args: Optional list of extra arguments to pass to javac. + # chromium_code: Whether this corresponds to Chromium-specific sources. + # requires_android: True if these sources can only run on Android. + # additional_jar_files: Optional list of files to copy into the resulting + # .jar file (by default, only .class files are put there). Each entry + # has the 'srcPath:dstPath' format. + # enable_errorprone: If True, use the errorprone compiler to check for + # error-prone constructs in the language. If not provided, whether this is + # enabled depends on chromium_code and the global + # use_errorprone_java_compiler variable. + # use_turbine: If True, compile headers using turbine.py. + # apk_name: Optional APK name. If provided, will tell compile_java.py to also + # generate an .apk.jar.info file under size-info/${apk_name}.apk.jar.info + # processor_args_javac: List of annotation processor arguments, each one + # will be passed to javac as -A<entry>. + # deps: Dependencies for the corresponding target. + # testonly: Usual meaning (should be True for test-only targets) + # + # [1] https://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html + # + template("compile_java") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _build_config = invoker.build_config + _chromium_code = invoker.chromium_code + + _processor_args = [] + if (defined(invoker.processor_args_javac)) { + _processor_args = invoker.processor_args_javac + } + + _additional_jar_files = [] + if (defined(invoker.additional_jar_files)) { + _additional_jar_files = invoker.additional_jar_files + } + + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps += invoker.srcjar_deps + } + + _java_srcjars = [] + foreach(dep, _srcjar_deps) { + _dep_gen_dir = get_label_info(dep, "target_gen_dir") + _dep_name = get_label_info(dep, "name") + _java_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ] + } + + # generated_jar_path is an output when use_turbine and an input otherwise. + if (!invoker.use_turbine) { + _java_srcjars += [ invoker.generated_jar_path ] + } + + _javac_args = [] + if (defined(invoker.javac_args)) { + _javac_args = invoker.javac_args + } + + action_with_pydeps(target_name) { + if (invoker.use_turbine) { + script = "//build/android/gyp/turbine.py" + } else { + script = "//build/android/gyp/compile_java.py" + } + + if (target_name == "chrome_java__header") { + # Regression test for: https://crbug.com/1154302 + assert_no_deps = [ "//base:base_java__impl" ] + } + + depfile = "$target_gen_dir/$target_name.d" + deps = _srcjar_deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + + outputs = [ invoker.output_jar_path ] + if (!invoker.enable_errorprone && !invoker.use_turbine) { + outputs += [ invoker.output_jar_path + ".info" ] + } + inputs = invoker.java_files + _java_srcjars + [ _build_config ] + if (invoker.java_files != []) { + inputs += [ invoker.java_sources_file ] + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _rebased_output_jar_path = + rebase_path(invoker.output_jar_path, root_build_dir) + _rebased_java_srcjars = rebase_path(_java_srcjars, root_build_dir) + _rebased_depfile = rebase_path(depfile, root_build_dir) + _rebased_generated_dir = rebase_path( + "$target_gen_dir/${invoker.main_target_name}/generated_java", + root_build_dir) + args = [ + "--depfile=$_rebased_depfile", + "--generated-dir=$_rebased_generated_dir", + "--jar-path=$_rebased_output_jar_path", + "--java-srcjars=$_rebased_java_srcjars", + "--target-name", + get_label_info(":${target_name}", "label_no_toolchain"), + ] + + if (defined(invoker.header_jar_path)) { + inputs += [ invoker.header_jar_path ] + args += [ + "--header-jar", + rebase_path(invoker.header_jar_path, root_build_dir), + ] + _header_jar_classpath = + [ rebase_path(invoker.header_jar_path, root_build_dir) ] + args += [ "--classpath=$_header_jar_classpath" ] + } + + if (invoker.use_turbine) { + # Prefer direct deps for turbine as much as possible. + args += [ "--classpath=@FileArg($_rebased_build_config:javac:interface_classpath)" ] + } else { + args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)" ] + } + + if (invoker.use_turbine) { + args += [ + "--processorpath=@FileArg($_rebased_build_config:javac:processor_classpath)", + "--processors=@FileArg($_rebased_build_config:javac:processor_classes)", + ] + } + + if (invoker.use_turbine) { + _turbine_jar_path = "//third_party/turbine/turbine.jar" + inputs += [ _turbine_jar_path ] + outputs += [ invoker.generated_jar_path ] + args += [ + "--turbine-jar-path", + rebase_path(_turbine_jar_path, root_build_dir), + "--generated-jar-path", + rebase_path(invoker.generated_jar_path, root_build_dir), + ] + } + + # Currently turbine does not support JDK11. + if (invoker.supports_android || invoker.use_turbine) { + args += [ "--java-version=1.8" ] + } + if (use_java_goma) { + args += [ "--gomacc-path=$goma_dir/gomacc" ] + + # Override the default action_pool when goma is enabled. + pool = "//build/config/android:goma_javac_pool" + } + + # Flag enable_kythe_annotations requires + # checkout_android_prebuilts_build_tools=True in .gclient. + if (enable_kythe_annotations && !invoker.enable_errorprone) { + args += [ "--enable-kythe-annotations" ] + } + if (invoker.requires_android) { + args += [ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)" ] + } + if (_chromium_code) { + args += [ "--chromium-code=1" ] + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + } + if (defined(invoker.jar_excluded_patterns)) { + args += [ "--jar-info-exclude-globs=${invoker.jar_excluded_patterns}" ] + } + + if (invoker.enable_errorprone) { + # Our custom plugin pulls in the main errorprone dep transitively. + _errorprone_dep = "//tools/android/errorprone_plugin:errorprone_plugin" + deps += [ _errorprone_dep ] + _dep_gen_dir = get_label_info(_errorprone_dep, "target_gen_dir") + _dep_name = get_label_info(_errorprone_dep, "name") + _rebased_errorprone_buildconfig = + rebase_path("$_dep_gen_dir/$_dep_name.build_config.json", + root_build_dir) + args += [ + "--processorpath=@FileArg($_rebased_errorprone_buildconfig:deps_info:host_classpath)", + "--enable-errorprone", + ] + } + if (defined(invoker.skip_build_server) && invoker.skip_build_server) { + # Nocompile tests need lint to fail through ninja. + args += [ "--skip-build-server" ] + } + + foreach(e, _processor_args) { + args += [ "--processor-arg=" + e ] + } + + foreach(file_tuple, _additional_jar_files) { + # Each element is of length two, [ path_to_file, path_to_put_in_jar ] + inputs += [ file_tuple[0] ] + args += + [ "--additional-jar-file=" + + rebase_path(file_tuple[0], root_build_dir) + ":" + file_tuple[1] ] + } + if (invoker.java_files != []) { + args += [ "@" + rebase_path(invoker.java_sources_file, root_build_dir) ] + } + foreach(e, _javac_args) { + args += [ "--javac-arg=" + e ] + } + } + } + + template("java_lib_group") { + forward_variables_from(invoker, [ "testonly" ]) + _group_name = invoker.group_name + not_needed([ "_group_name" ]) + group(target_name) { + if (defined(invoker.deps)) { + deps = [] + foreach(_dep, invoker.deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_library_patterns) == [] && + filter_exclude([ _target_label ], _java_resource_patterns) != + []) { + # This is a java library dep, so replace it. + deps += [ "${_target_label}__${_group_name}" ] + } else { + # Transitive java group targets should also include direct deps. + deps += [ _dep ] + } + } + } + } + } + + # Create an interface jar from a normal jar. + # + # Variables + # input_jar: Path to input .jar. + # output_jar: Path to output .ijar. + # + template("generate_interface_jar") { + action_with_pydeps(target_name) { + _ijar_target = "//third_party/ijar:ijar($host_toolchain)" + _ijar_executable = get_label_info(_ijar_target, "root_out_dir") + "/ijar" + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "public_deps", + ]) + script = "//build/android/gyp/ijar.py" + deps = [ _ijar_target ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [ + invoker.input_jar, + _ijar_executable, + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + outputs = [ invoker.output_jar ] + args = [ + rebase_path(_ijar_executable, root_build_dir), + rebase_path(invoker.input_jar, root_build_dir), + rebase_path(invoker.output_jar, root_build_dir), + ] + } + } + + # A rule that will handle multiple Java-related targets. + # + # The caller can provide a list of source files with 'java_files' + # and 'srcjar_deps', or a prebuilt .jar file through 'jar_path'. + # + # In the case of a 'java_binary' target type, it can even provide none of + # that (and the rule will just generate its wrapper script). + # + # The template will process the input .jar file (either the prebuilt one, + # or the result of compiling the sources), for example to apply Proguard, + # but also other ranges of bytecode-level rewriting schemes. + # + # Variables: + # type: type of Java target, valid values: 'java_library', 'java_binary', + # 'junit_binary', 'java_annotation_processor', and 'android_apk' + # main_target_name: optional. If provided, overrides target_name when + # creating sub-targets (e.g. "${main_target_name}__dex") and + # some output files (e.g. "${main_target_name}.sources"). Only used + # for 'android_apk' types at the moment, where main_target_name will + # be the name of the main APK target. + # supports_android: Optional. True if target can run on Android. + # requires_android: Optional. True if target can only run on Android. + # java_files: Optional list of Java source file paths for this target. + # javac_args: Optional list of extra arguments to pass to javac. + # errorprone_args: Optional list of extra arguments to pass to. + # srcjar_deps: Optional list of .srcjar targets (not file paths). The Java + # source files they contain will also be compiled for this target. + # java_sources_file: Optional path to a file which will be written with + # the content of java_files. If not provided, the file will be written + # under $target_gen_dir/$main_target_name.sources. Ignored if + # java_files is empty. If not + # jar_path: Optional path to a prebuilt .jar file for this target. + # Mutually exclusive with java_files and srcjar_deps. + # output_name: Optional output name for the final jar path. Used to + # determine the name of the final jar. Default is to use the same + # name as jar_path, if provided, or main_target_name. + # main_class: Main Java class name for 'java_binary', 'junit_binary' and + # 'java_annotation_processor' target types. Should not be set for other + # ones. + # deps: Dependencies for this target. + # public_deps: Dependencies that this target exposes as part of its public API. + # public_deps do not need to be listed in both the 'deps' and 'public_deps' lists. + # testonly: True iff target should only be used for tests. + # chromium_code: Optional. Whether this is Chromium-specific code. If not + # provided, this is determined automatically, based on the location of + # the source files (i.e. anything under third_party/ is not + # Chromium-specific unless it is in a 'chromium' sub-directory). + # jacoco_never_instrument: Optional. If provided, whether to forbid + # instrumentation with the Jacoco coverage processor. If not provided, + # this is controlled by the global use_jacoco_coverage build arg variable + # and only used for non-test Chromium code. + # include_android_sdk: Optional. Whether or not the android SDK dep + # should be added to deps. Defaults to true for non-system libraries + # that support android. + # alternative_android_sdk_dep: Optional. Alternative Android system + # android java target to use. + # annotation_processor_deps: Optional list of dependencies corresponding + # to annotation processors used to compile these sources. + # input_jars_paths: Optional list of additional .jar file paths, which will + # be added to the compile-time classpath when building this target (but + # not to the runtime classpath). + # desugar_jars_paths: Optional list of additional .jar file paths, which will + # be added to the desugar classpath when building this target (but not to + # any other classpath). This is only used to break dependency cycles. + # gradle_treat_as_prebuilt: Cause generate_gradle.py to reference this + # library via its built .jar rather than including its .java sources. + # proguard_enabled: Optional. True to enable ProGuard obfuscation. + # proguard_configs: Optional list of additional proguard config file paths. + # bypass_platform_checks: Optional. If True, platform checks will not + # be performed. They are used to verify that every target with + # requires_android only depends on targets that, at least supports_android. + # Similarly, if a target has !supports_android, then it cannot depend on + # any other target that has requires_android. + # include_java_resources: Optional. If True, include Java (not Android) + # resources into final .jar file. + # jar_excluded_patterns: Optional list of .class file patterns to exclude + # from the final .jar file. + # jar_included_patterns: Optional list of .class file patterns to include + # in the final .jar file. jar_excluded_patterns take precedence over this. + # low_classpath_priority: Indicates that the library should be placed at the + # end of the classpath. The default classpath order has libraries ordered + # before the libraries that they depend on. 'low_classpath_priority' is + # useful when one java_library() overrides another via + # 'jar_excluded_patterns' and the overriding library does not depend on the + # overridee. + # + # For 'android_apk' and 'android_app_bundle_module' targets only: + # + # apk_path: Path to the final APK file. + # android_manifest: Path to AndroidManifest.xml file for the APK. + # android_manifest_dep: Optional. Dependency target that generates + # android_manifest. + # apk_under_test: For 'android_apk' targets used to test other APKs, + # this is the target name of APK being tested. + # incremental_apk_path: Path to the incremental APK. + # incremental_install_json_path: Path to the incremental install json. + # native_lib_placeholders: Optional. List of placeholder filenames to add to + # the APK. + # proguard_mapping_path: Path to .mapping file produced from ProGuard step. + # shared_libraries_runtime_deps_file: Optional. Path to a file listing the + # native shared libraries required at runtime by the APK. + # secondary_abi_shared_libraries_runtime_deps_file: + # secondary_native_lib_placeholders: Optional. List of placeholder filenames + # to add to the APK for the secondary ABI. + # loadable_modules: Optional list of extra native libraries to + # be stored in the APK. + # secondary_abi_loadable_modules: Optional list of native libraries for + # secondary ABI. + # uncompress_shared_libraries: Optional. True to store native shared + # libraries uncompressed and page-aligned. + # proto_resources_path: The path of an zip archive containing the APK's + # resources compiled to the protocol buffer format (instead of regular + # binary xml + resources.arsc). + # r_text_path: The path of the R.txt file generated when compiling the + # resources for this target. + # module_pathmap_path: The path of the pathmap file generated when compiling + # the resources for the bundle module, if path shortening is enabled. + # base_allowlist_rtxt_path: The path of the R.txt file containing the + # list of string resources to keep in the base split APK for any bundle + # that uses this target. + # + # For 'java_binary' and 'junit_binary' targets only. Ignored by others: + # + # wrapper_script_name: Optional name for the generated wrapper script. + # Default is main target name. + # wrapper_script_args: Optional list of extra arguments used by the + # generated wrapper script. + # + template("java_library_impl") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + + forward_variables_from(invoker, [ "testonly" ]) + _is_prebuilt = defined(invoker.jar_path) + _is_annotation_processor = invoker.type == "java_annotation_processor" + _is_java_binary = + invoker.type == "java_binary" || invoker.type == "junit_binary" + _supports_android = + defined(invoker.supports_android) && invoker.supports_android + _requires_android = + defined(invoker.requires_android) && invoker.requires_android + + _invoker_deps = [] + if (defined(invoker.deps)) { + _invoker_deps += invoker.deps + } + if (defined(invoker.public_deps)) { + foreach(_public_dep, invoker.public_deps) { + if (filter_include([ _public_dep ], _invoker_deps) != []) { + assert(false, "'public_deps' and 'deps' overlap: $_public_dep") + } + } + _invoker_deps += invoker.public_deps + } + + _main_target_name = target_name + if (defined(invoker.main_target_name)) { + _main_target_name = invoker.main_target_name + } + + if (defined(invoker.resources_package)) { + _resources_package = invoker.resources_package + } + + _java_files = [] + if (defined(invoker.sources)) { + _java_files = invoker.sources + } + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps = invoker.srcjar_deps + } + _has_sources = _java_files != [] || _srcjar_deps != [] + + if (_is_prebuilt) { + assert(!_has_sources) + } else { + # Allow java_binary to not specify any sources. This is needed when a prebuilt + # is needed as a library as well as a binary. + assert(_is_annotation_processor || _is_java_binary || _has_sources) + } + + if (_is_java_binary) { + assert(defined(invoker.main_class), + "${invoker.type}() must set main_class") + } else if (_is_annotation_processor) { + assert(defined(invoker.main_class), + "java_annotation_processor() must set main_class") + } else { + assert(!defined(invoker.main_class), + "main_class cannot be used for target of type ${invoker.type}") + } + + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } else { + # Default based on whether target is in third_party. + _chromium_code = + filter_exclude([ get_label_info(":$_main_target_name", "dir") ], + [ "*\bthird_party\b*" ]) != [] + if (!_chromium_code && !_is_prebuilt && _java_files != []) { + # Unless third_party code has an org.chromium file in it. + _chromium_code = + filter_exclude(_java_files, [ "*\bchromium\b*" ]) != _java_files + } + } + + # Define build_config_deps which will be a list of targets required to + # build the _build_config. + _build_config = "$target_gen_dir/$_main_target_name.build_config.json" + _build_config_target_name = + "${_main_target_name}$build_config_target_suffix" + + # The only target that might have no prebuilt and no sources is a java_binary. + _build_host_jar = false + _build_device_jar = false + if (_is_prebuilt || _has_sources) { + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } else if (_is_prebuilt) { + _output_name = get_path_info(invoker.jar_path, "name") + } else { + _output_name = _main_target_name + } + + _build_host_jar = _is_java_binary || _is_annotation_processor || + invoker.type == "java_library" + _build_device_jar = + invoker.type != "system_java_library" && _supports_android + + _jacoco_instrument = + use_jacoco_coverage && _chromium_code && _java_files != [] && + _build_device_jar && (!defined(invoker.testonly) || !invoker.testonly) + if (defined(invoker.jacoco_never_instrument)) { + _jacoco_instrument = + !invoker.jacoco_never_instrument && _jacoco_instrument + } + + if (_build_host_jar) { + # Jar files can be needed at runtime (by Robolectric tests or java binaries), + # so do not put them under obj/. + # TODO(agrieve): I suspect it would be better to use dist_jar for java_binary + # rather than archiving unnecessary .jar files within lib.java. + _target_dir_name = get_label_info(":$_main_target_name", "dir") + _host_processed_jar_path = + "$root_out_dir/lib.java$_target_dir_name/$_output_name.jar" + } + if (_build_device_jar) { + _dex_path = "$target_out_dir/$_main_target_name.dex.jar" + _enable_desugar = + !defined(invoker.enable_desugar) || invoker.enable_desugar + _use_classic_desugar = + defined(invoker.use_classic_desugar) && invoker.use_classic_desugar + + # Build speed optimization: Skip "process device" step if the step + # would be just a copy and avoid the copy. + _process_device_jar = + defined(invoker.bytecode_rewriter_target) || _jacoco_instrument || + (_enable_desugar && _use_classic_desugar) || + defined(invoker.jar_excluded_patterns) || + defined(invoker.jar_included_patterns) + if (!_process_device_jar && _is_prebuilt) { + _device_processed_jar_path = invoker.jar_path + } else { + _device_processed_jar_path = + "$target_out_dir/$_output_name.processed.jar" + } + } + + # For static libraries, the javac jar output is created at the intermediate + # path so that it can be processed by another target and moved to the final + # spot that the .build_config.json knows about. Technically this should be done + # for the ijar as well, but this is only used for APK targets where + # the ijar path isn't actually used. + if (_has_sources) { + _final_ijar_path = "$target_out_dir/$_output_name.turbine.jar" + } else { + _final_ijar_path = "$target_out_dir/$_output_name.ijar.jar" + } + + if (_has_sources) { + if (_build_device_jar && !_process_device_jar) { + _javac_jar_path = _device_processed_jar_path + } else { + _javac_jar_path = "$target_out_dir/$_main_target_name.javac.jar" + } + _generated_jar_path = + "$target_gen_dir/$_main_target_name.generated.srcjar" + } + + if (_is_prebuilt) { + _unprocessed_jar_path = invoker.jar_path + } else { + _unprocessed_jar_path = _javac_jar_path + } + } + + if (_is_prebuilt || _has_sources) { + _java_res_deps = [] + _java_header_deps = [] + _java_impl_deps = [] + _non_java_deps = [] + foreach(_dep, _invoker_deps) { + _target_label = get_label_info(_dep, "label_no_toolchain") + if (filter_exclude([ _target_label ], _java_resource_patterns) == []) { + _java_res_deps += [ _dep ] + } else if (filter_exclude([ _target_label ], _java_library_patterns) == + []) { + # This is a java library dep, so it has header and impl targets. + _java_header_deps += [ "${_target_label}__header" ] + _java_impl_deps += [ "${_target_label}__impl" ] + } else { + _non_java_deps += [ _dep ] + } + } + + # Don't need to depend on the apk-under-test to be packaged. + if (defined(invoker.apk_under_test)) { + _java_header_deps += [ "${invoker.apk_under_test}__java__header" ] + _java_impl_deps += [ "${invoker.apk_under_test}__java__impl" ] + } + + # These deps cannot be passed via invoker.deps since bundle_module targets + # have bundle_module.build_config without the __java suffix, so they are + # special and cannot be passed as regular deps to write_build_config. + if (defined(invoker.base_module_target)) { + _java_header_deps += [ "${invoker.base_module_target}__java__header" ] + _java_impl_deps += [ "${invoker.base_module_target}__java__impl" ] + } + + _extra_java_deps = [] + if (_jacoco_instrument) { + _extra_java_deps += [ "//third_party/jacoco:jacocoagent_java" ] + } + + _include_android_sdk = _build_device_jar + if (defined(invoker.include_android_sdk)) { + _include_android_sdk = invoker.include_android_sdk + } + if (_include_android_sdk) { + _sdk_java_dep = "//third_party/android_sdk:android_sdk_java" + if (defined(invoker.alternative_android_sdk_dep)) { + _sdk_java_dep = invoker.alternative_android_sdk_dep + } + + # This is an android_system_java_prebuilt target, so no headers. + _extra_java_deps += [ _sdk_java_dep ] + } + + # Classpath deps is used for header and dex targets, they do not need + # resource deps. + _classpath_deps = _java_header_deps + _non_java_deps + _extra_java_deps + + [ ":$_build_config_target_name" ] + + _full_classpath_deps = + _java_impl_deps + _java_res_deps + _non_java_deps + _extra_java_deps + + [ ":$_build_config_target_name" ] + } + + # Often needed, but too hard to figure out when ahead of time. + not_needed([ + "_classpath_deps", + "_full_classpath_deps", + ]) + + if (_java_files != []) { + _java_sources_file = "$target_gen_dir/$_main_target_name.sources" + if (defined(invoker.java_sources_file)) { + _java_sources_file = invoker.java_sources_file + } + write_file(_java_sources_file, rebase_path(_java_files, root_build_dir)) + } + + write_build_config(_build_config_target_name) { + forward_variables_from(invoker, + [ + "aar_path", + "annotation_processor_deps", + "base_allowlist_rtxt_path", + "gradle_treat_as_prebuilt", + "input_jars_paths", + "low_classpath_priority", + "main_class", + "proguard_configs", + "proguard_enabled", + "proguard_mapping_path", + "public_target_label", + "r_text_path", + "type", + ]) + if (type == "android_apk" || type == "android_app_bundle_module") { + forward_variables_from( + invoker, + [ + "android_manifest", + "android_manifest_dep", + "merged_android_manifest", + "final_dex_path", + "loadable_modules", + "native_lib_placeholders", + "res_size_info_path", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries_runtime_deps_file", + "secondary_native_lib_placeholders", + "shared_libraries_runtime_deps_file", + "static_library_dependent_targets", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + ]) + } + if (type == "android_apk") { + forward_variables_from(invoker, + [ + "apk_path", + "apk_under_test", + "incremental_apk_path", + "incremental_install_json_path", + ]) + } + if (type == "android_app_bundle_module") { + forward_variables_from(invoker, + [ + "base_module_target", + "is_base_module", + "module_pathmap_path", + "proto_resources_path", + "version_name", + "version_code", + ]) + } + chromium_code = _chromium_code + build_config = _build_config + is_prebuilt = _is_prebuilt + + # Specifically avoid passing in invoker.base_module_target as one of the + # possible_config_deps. + possible_config_deps = _invoker_deps + if (defined(_extra_java_deps)) { + possible_config_deps += _extra_java_deps + } + if (defined(apk_under_test)) { + possible_config_deps += [ apk_under_test ] + } + + if (defined(invoker.public_deps)) { + possible_config_public_deps = invoker.public_deps + } + + supports_android = _supports_android + requires_android = _requires_android + bypass_platform_checks = defined(invoker.bypass_platform_checks) && + invoker.bypass_platform_checks + + if (defined(_resources_package)) { + custom_package = _resources_package + } + if (_is_prebuilt || _has_sources) { + ijar_path = _final_ijar_path + unprocessed_jar_path = _unprocessed_jar_path + } + if (_build_host_jar) { + host_jar_path = _host_processed_jar_path + } + if (_build_device_jar) { + device_jar_path = _device_processed_jar_path + dex_path = _dex_path + } + if (_java_files != []) { + java_sources_file = _java_sources_file + } + + bundled_srcjars = [] + foreach(d, _srcjar_deps) { + _dep_gen_dir = get_label_info(d, "target_gen_dir") + _dep_name = get_label_info(d, "name") + bundled_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ] + } + if (defined(invoker.include_java_resources) && + invoker.include_java_resources) { + java_resources_jar = _unprocessed_jar_path + if (defined(invoker.jar_path)) { + # Use original jar_path because _jar_path points to a library without + # resources. + } else { + java_resources_jar = _device_processed_jar_path + } + } + } + + if (_is_prebuilt || _has_sources) { + _header_target_name = "${target_name}__header" + } + + _public_deps = [] + _analysis_public_deps = [] + _analysis_files = [] + + if (defined(invoker.proguard_configs)) { + assert(_build_host_jar || _build_device_jar) + + # proguard_configs listed on java_library targets need to be marked + # as inputs to at least one action so that "gn analyze" will know + # about them. Although this target doesn't use them, it's a convenient spot + # to list them. + # https://crbug.com/827197 + _analysis_files = invoker.proguard_configs + _analysis_public_deps = + _non_java_deps + _srcjar_deps # For the aapt-generated + # proguard rules. + } + + if (_has_sources) { + if (defined(invoker.enable_errorprone)) { + _enable_errorprone = invoker.enable_errorprone + } else { + _enable_errorprone = + _java_files != [] && _chromium_code && use_errorprone_java_compiler + } + + _type = invoker.type + + _uses_fake_rjava = _type == "java_library" && _requires_android + + if (_uses_fake_rjava && defined(_resources_package)) { + # has _resources at the end so it looks like a resources pattern, since + # it does act like one (and other resources patterns need to depend on + # this before they can read its output R.txt). + _fake_rjava_target = "${target_name}__rjava_resources" + _possible_resource_deps = _invoker_deps + generate_r_java(_fake_rjava_target) { + deps = [ ":$_build_config_target_name" ] + if (defined(_possible_resource_deps)) { + possible_resource_deps = _possible_resource_deps + } + build_config = _build_config + + # Filepath has to be exactly this because compile_java looks for the + # srcjar of srcjar_deps at this location $gen_dir/$target_name.srcjar + srcjar_path = "$target_gen_dir/$target_name.srcjar" + package = _resources_package + } + _srcjar_deps += [ ":$_fake_rjava_target" ] + } + + template("compile_java_helper") { + _enable_errorprone = + defined(invoker.enable_errorprone) && invoker.enable_errorprone + if (_enable_errorprone) { + # Rely on the header jar to provide all .class files so that it is + # safe to omit generated files entirely for errorprone. + _filtered_java_files = + filter_exclude(_java_files, [ "$root_gen_dir*" ]) + } + if (_enable_errorprone && _filtered_java_files == []) { + # Filtering out generated files resulted in no files left. + group(target_name) { + not_needed(invoker, "*") + } + } else { + compile_java(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + output_jar_path = invoker.output_jar_path + enable_errorprone = _enable_errorprone + use_turbine = defined(invoker.use_turbine) && invoker.use_turbine + + main_target_name = _main_target_name + build_config = _build_config + + if (_enable_errorprone) { + java_files = _filtered_java_files + } else { + java_files = _java_files + srcjar_deps = _srcjar_deps + } + + if (java_files != []) { + java_sources_file = _java_sources_file + } + chromium_code = _chromium_code + supports_android = _supports_android + requires_android = _requires_android + if (!defined(deps)) { + deps = [] + } + deps += _classpath_deps + } + } + } + _compile_java_forward_variables = [ + "additional_jar_files", + "apk_name", + "jar_excluded_patterns", + "javac_args", + "processor_args_javac", + "skip_build_server", + ] + _annotation_processor_deps = [] + if (defined(invoker.annotation_processor_deps)) { + _annotation_processor_deps = invoker.annotation_processor_deps + } + + compile_java_helper(_header_target_name) { + forward_variables_from(invoker, _compile_java_forward_variables) + use_turbine = true + output_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + deps = _annotation_processor_deps + } + _public_deps += [ ":$_header_target_name" ] + + _compile_java_target = "${_main_target_name}__compile_java" + compile_java_helper(_compile_java_target) { + forward_variables_from(invoker, _compile_java_forward_variables) + output_jar_path = _javac_jar_path + deps = [ ":$_header_target_name" ] + header_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + } + if (_enable_errorprone) { + _compile_java_errorprone_target = "${_main_target_name}__errorprone" + compile_java_helper(_compile_java_errorprone_target) { + forward_variables_from(invoker, _compile_java_forward_variables) + enable_errorprone = true + if (defined(invoker.errorprone_args)) { + if (!defined(javac_args)) { + javac_args = [] + } + javac_args += invoker.errorprone_args + } + deps = [ ":$_header_target_name" ] + header_jar_path = _final_ijar_path + generated_jar_path = _generated_jar_path + output_jar_path = "$target_out_dir/$target_name.errorprone.stamp" + } + _analysis_public_deps += [ ":$_compile_java_errorprone_target" ] + } + } # _has_sources + + if (_is_prebuilt || _build_device_jar || _build_host_jar) { + _unprocessed_jar_deps = [] + if (_has_sources) { + _unprocessed_jar_deps += [ ":$_compile_java_target" ] + } + } + + if (defined(invoker.bytecode_rewriter_target)) { + assert(_build_host_jar || _build_device_jar, + "A host or device jar must be created to use bytecode rewriting") + + _rewritten_jar = "$target_out_dir/${target_name}_rewritten.jar" + _rewritten_jar_target_name = "${target_name}__rewritten" + _rewriter_path = root_build_dir + "/bin/helper/" + + get_label_info(invoker.bytecode_rewriter_target, "name") + _rebased_build_config = rebase_path(_build_config, root_build_dir) + action_with_pydeps(_rewritten_jar_target_name) { + script = "//build/android/gyp/bytecode_rewriter.py" + inputs = [ + _rewriter_path, + _build_config, + _unprocessed_jar_path, + ] + outputs = [ _rewritten_jar ] + depfile = "$target_gen_dir/$target_name.d" + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--script", + rebase_path(_rewriter_path, root_build_dir), + "--classpath", + "@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--classpath", + "@FileArg($_rebased_build_config:android:sdk_jars)", + "--input-jar", + rebase_path(_unprocessed_jar_path, root_build_dir), + "--output-jar", + rebase_path(_rewritten_jar, root_build_dir), + ] + deps = _unprocessed_jar_deps + _full_classpath_deps + + [ invoker.bytecode_rewriter_target ] + } + + _unprocessed_jar_deps = [] + _unprocessed_jar_deps = [ ":$_rewritten_jar_target_name" ] + _unprocessed_jar_path = _rewritten_jar + } + + if (_is_prebuilt) { + generate_interface_jar(_header_target_name) { + # Always used the unfiltered .jar to create the interface jar so that + # other targets will resolve filtered classes when depending on + # BuildConfig, NativeLibraries, etc. + input_jar = _unprocessed_jar_path + output_jar = _final_ijar_path + + # Normally ijar does not require any deps, but: + # 1 - Some jars are bytecode rewritten by _unprocessed_jar_deps. + # 2 - Other jars need to be unzipped by _non_java_deps. + # 3 - It is expected that depending on a header target implies depending + # on its transitive header target deps via _java_header_deps. + deps = _unprocessed_jar_deps + _non_java_deps + _java_header_deps + } + _public_deps += [ ":$_header_target_name" ] + } + + if (_build_host_jar || _build_device_jar) { + _enable_bytecode_checks = !defined(invoker.enable_bytecode_checks) || + invoker.enable_bytecode_checks + if (_enable_bytecode_checks) { + _bytecode_checks_target = "${target_name}__validate_classpath" + bytecode_processor(_bytecode_checks_target) { + forward_variables_from(invoker, [ "missing_classes_allowlist" ]) + deps = _unprocessed_jar_deps + _full_classpath_deps + + [ ":$_build_config_target_name" ] + requires_android = _requires_android + target_label = + get_label_info(":${invoker.target_name}", "label_no_toolchain") + input_jar = _unprocessed_jar_path + build_config = _build_config + is_prebuilt = _is_prebuilt + } + _analysis_public_deps += [ ":$_bytecode_checks_target" ] + } + + if (_build_host_jar) { + _process_host_jar_target_name = "${target_name}__process_host" + process_java_library(_process_host_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + input_jar_path = _unprocessed_jar_path + jar_deps = _unprocessed_jar_deps + _full_classpath_deps + is_device_jar = false + output_jar_path = _host_processed_jar_path + jacoco_instrument = _jacoco_instrument + if (_jacoco_instrument) { + java_files = _java_files + java_sources_file = _java_sources_file + } + } + _public_deps += [ ":${_process_host_jar_target_name}" ] + } + + if (_build_device_jar) { + if (_process_device_jar) { + _process_device_jar_target_name = "${target_name}__process_device" + process_java_library(_process_device_jar_target_name) { + forward_variables_from(invoker, + [ + "jar_excluded_patterns", + "jar_included_patterns", + ]) + input_jar_path = _unprocessed_jar_path + jar_deps = _unprocessed_jar_deps + _full_classpath_deps + is_device_jar = true + output_jar_path = _device_processed_jar_path + jacoco_instrument = _jacoco_instrument + if (_jacoco_instrument) { + java_files = _java_files + java_sources_file = _java_sources_file + } + enable_desugar = _enable_desugar && _use_classic_desugar + if (enable_desugar) { + build_config = _build_config + classpath_deps = _classpath_deps + forward_variables_from(invoker, [ "desugar_jars_paths" ]) + } + } + _process_device_jar_deps = [ ":${_process_device_jar_target_name}" ] + _public_deps += _process_device_jar_deps + } else { + assert(_unprocessed_jar_path == _device_processed_jar_path) + _process_device_jar_deps = + _unprocessed_jar_deps + _full_classpath_deps + } + + dex("${target_name}__dex") { + forward_variables_from(invoker, + [ + "desugar_jars_paths", + "proguard_enable_obfuscation", + "use_classic_desugar", + ]) + input_class_jars = [ _device_processed_jar_path ] + enable_desugar = _enable_desugar + ignore_desugar_missing_deps = !_enable_bytecode_checks + + # There's no value in per-class dexing prebuilts since they never + # change just one class at a time. + disable_incremental = _is_prebuilt + output = _dex_path + deps = _process_device_jar_deps + + if (enable_desugar && !_use_classic_desugar) { + # Desugaring with D8 requires full classpath. + build_config = _build_config + final_ijar_path = _final_ijar_path + deps += _classpath_deps + [ ":$_header_target_name" ] + } + + enable_multidex = false + is_library = true + } + _public_deps += [ ":${target_name}__dex" ] + } + } + + if (_is_java_binary) { + # Targets might use the generated script while building, so make it a dep + # rather than a data_dep. + java_binary_script("${target_name}__java_binary_script") { + forward_variables_from(invoker, + [ + "tiered_stop_at_level_one", + "main_class", + "wrapper_script_args", + ]) + build_config = _build_config + script_name = _main_target_name + if (defined(invoker.wrapper_script_name)) { + script_name = invoker.wrapper_script_name + } + deps = [ ":$_build_config_target_name" ] + } + _public_deps += [ ":${target_name}__java_binary_script" ] + } + + # The __impl target contains all non-analysis steps for this template. + # Having this separated out from the main target (which contains analysis + # steps) allows analysis steps for this target to be run concurrently with + # the non-analysis steps of other targets that depend on this one. + group("${target_name}__impl") { + public_deps = _public_deps + } + + java_lib_group("${target_name}__assetres") { + deps = _invoker_deps + group_name = "assetres" + + if (defined(_fake_rjava_target)) { + deps += [ ":$_fake_rjava_target" ] + } + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "data", + "data_deps", + "deps", + "public_deps", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":${target_name}__impl" ] + if (!defined(data)) { + data = [] + } + data += _analysis_files + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += _analysis_public_deps + } + } +} + +# Create a zip archive corresponding to an application bundle module. +# +# Compile all the components of a given android_apk_or_module() target into a +# zip archive suitable to later create an android_app_bundle() target. This +# archive's format is very similar to that on an APK, except for a few +# differences in internal directory layouts, and the fact that resources, as +# well as xml files, are compiled using a protocol-buffer based format (instead +# of the regular binary xml + resources.arsc). +# +# A final application bundle is built from one or more module bundle modules, +# plus some configuration file. +# +# Variables: +# module_zip_path: Output module path. +# build_config: Path to build_config of the android_apk_or_module() target. +# dex_path: If module is proguarded separately from the base module, dex_path +# is the path to its dex file and is passed directly to the creation script. +# Otherwise, dex_path is undefined and we retrieve the module's dex file +# using its build_config. +# expected_libs_and_assets: Verify the list of included native libraries +# and assets is consistent with the given expectation file. +# expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff +# with this file as the base. +# is_multi_abi: If true will add a library placeholder for the missing ABI if +# either the primary or the secondary ABI has no native libraries set. +# module_name: The module's name. +# native_libraries_config: Path to file listing native libraries to be +# packaged into each module. +# proguard_enabled: Optional. True if proguarding is enabled for this +# bundle. Default is to enable this only for release builds. Note that +# this will always perform synchronized proguarding. +template("create_android_app_bundle_module") { + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + _rebased_native_libraries_config = + rebase_path(invoker.native_libraries_config, root_build_dir) + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _deps = invoker.deps + _script = "//build/android/gyp/apkbuilder.py" + + # NOTE: Compared to the inputs of the "package_apk" template action, + # this list is much smaller, since finalize_apk is never called + # by apkbuild.py --format=bundle-module. This means not using + # apksigner and zipalign as well, nor the keystore. Other + # dependencies like extra native libraries are all pulled from the + # .build_config.json through @FileArg() references (see below) and + # will be listed in the generated depfile instead. + _inputs = [ + invoker.build_config, + invoker.native_libraries_config, + ] + _outputs = [ invoker.module_zip_path ] + _args = [ + "--format=bundle-module", + "--output-apk", + rebase_path(invoker.module_zip_path, root_build_dir), + "--resource-apk=@FileArg(" + + "$_rebased_build_config:deps_info:proto_resources_path)", + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg(" + + "$_rebased_build_config:uncompressed_assets)", + "--native-libs=@FileArg($_rebased_native_libraries_config" + + ":${invoker.module_name})", + "--native-lib-placeholders=@FileArg($_rebased_build_config" + + ":native:native_library_placeholders)", + "--secondary-native-lib-placeholders=@FileArg($_rebased_build_config" + + ":native:secondary_native_library_placeholders)", + "--android-abi=$android_app_abi", + "--min-sdk-version=${invoker.min_sdk_version}", + "--uncompress-shared-libraries=@FileArg(" + + "$_rebased_build_config:native:uncompress_shared_libraries)", + "--library-always-compress=@FileArg($_rebased_build_config:native:library_always_compress)", + "--library-renames=@FileArg($_rebased_build_config:native:library_renames)", + ] + if (defined(android_app_secondary_abi)) { + _rebased_secondary_abi_native_libraries_config = + rebase_path(invoker.secondary_abi_native_libraries_config, + root_build_dir) + _args += [ + "--secondary-native-libs", + "@FileArg($_rebased_secondary_abi_native_libraries_config" + + ":${invoker.module_name})", + "--secondary-android-abi=$android_app_secondary_abi", + ] + } + if (defined(invoker.is_multi_abi) && invoker.is_multi_abi) { + _args += [ "--is-multi-abi" ] + } + if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { + _args += [ "--uncompress-dex" ] + } + + # Use either provided dex path or build config path based on type of module. + if (defined(invoker.dex_path)) { + _inputs += [ invoker.dex_path ] + _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir) + _args += [ "--dex-file=$_rebased_dex_path" ] + } else { + _args += [ "--dex-file=@FileArg($_rebased_build_config:final_dex:path)" ] + } + + # The library is imported via proguard when proguard is enabled. + if (!_proguard_enabled && enable_jdk_library_desugaring && + invoker.module_name == "base") { + _all_jdk_libs = "//build/android:all_jdk_libs" + _deps += [ _all_jdk_libs ] + _jdk_libs_dex = + get_label_info(_all_jdk_libs, "target_out_dir") + "/all_jdk_libs.l8.dex" + _inputs += [ _jdk_libs_dex ] + _args += [ + "--jdk-libs-dex-file", + rebase_path(_jdk_libs_dex, root_build_dir), + ] + } + + if (treat_warnings_as_errors) { + _args += [ "--warnings-as-errors" ] + } + + if (defined(invoker.expected_libs_and_assets)) { + _expectations_target = "${invoker.top_target_name}_validate_libs_and_assets" + action_with_pydeps(_expectations_target) { + _actual_file = "$target_gen_dir/$target_name.libs_and_assets" + _failure_file = "$expectations_failure_dir/" + + string_replace(invoker.expected_libs_and_assets, "/", "_") + inputs = [ + invoker.expected_libs_and_assets, + invoker.build_config, + invoker.native_libraries_config, + ] + deps = [ + invoker.build_config_target, + invoker.native_libraries_config_target, + ] + if (defined(android_app_secondary_abi)) { + inputs += [ invoker.secondary_abi_native_libraries_config ] + deps += [ invoker.secondary_abi_native_libraries_config_target ] + } + outputs = [ + _actual_file, + _failure_file, + ] + script = _script + args = _args + [ + "--expected-file", + rebase_path(invoker.expected_libs_and_assets, root_build_dir), + "--actual-file", + rebase_path(_actual_file, root_build_dir), + "--failure-file", + rebase_path(_failure_file, root_build_dir), + "--only-verify-expectations", + ] + if (defined(invoker.expected_libs_and_assets_base)) { + inputs += [ invoker.expected_libs_and_assets_base ] + args += [ + "--expected-file-base", + rebase_path(invoker.expected_libs_and_assets_base, root_build_dir), + ] + } + if (fail_on_android_expectations) { + args += [ "--fail-on-expectations" ] + } + } + _deps += [ ":$_expectations_target" ] + } + + action_with_pydeps(target_name) { + deps = _deps + inputs = _inputs + outputs = _outputs + script = _script + depfile = "$target_gen_dir/$target_name.d" + args = _args + [ + "--depfile", + rebase_path(depfile, root_build_dir), + ] + } +} + +# Splits input dex file(s) based on given feature jars into seperate dex files +# for each feature. +# +# Variables: +# proguard_mapping: Path to input proguard mapping produced by synchronized +# proguarding. +# input_dex_zip: Path to zipped dex files to split. +# all_modules: Path to list of all modules. Each Module must have +# build_config, name, and build_config_target properties. +# feature_jars_args: Optional list of args to be passed to dexsplitter.py. +# If used should include the jars owned by each feature (in the same order +# as all_modules). Allows invoker to pull the list of jars from a different +# .build_config.json than the module's .build_config. +template("dexsplitter") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "deps" ]) + script = "//build/android/gyp/dexsplitter.py" + _stamp = "${target_gen_dir}/${target_name}.stamp" + outputs = [ _stamp ] + + depfile = "${target_gen_dir}/${target_name}.d" + args = [ + "--stamp", + rebase_path(_stamp, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + "--r8-path", + rebase_path(_r8_path, root_build_dir), + "--input-dex-zip", + rebase_path(invoker.input_dex_zip, root_build_dir), + "--proguard-mapping-file", + rebase_path(invoker.proguard_mapping, root_build_dir), + ] + + foreach(_feature_module, invoker.all_modules) { + _rebased_module_build_config = + rebase_path(_feature_module.build_config, root_build_dir) + args += [ + "--feature-name", + _feature_module.name, + "--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)", + ] + if (!defined(invoker.feature_jars_args)) { + args += [ "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:device_classpath)" ] + } + deps += [ _feature_module.build_config_target ] + } + if (defined(invoker.feature_jars_args)) { + args += invoker.feature_jars_args + } + } +} + +# Allots native libraries depended on by feature modules to the module the +# libraries should be packaged into. The packaging module may be different from +# the dependee module in case a library is depended on by multiple modules. In +# that case the library will be allotted to the closest ancestor given a module +# dependency tree (see |parent| below). +# +# Variables: +# modules: List of scopes with the following format: +# name: The module's name. +# parent: The module's parent's name. +# build_config: Path to the module's build config. +# build_config_target: Target creating |build_config|. +# native_libraries_filearg_keys: Keys to be used in +# @FileArg(|build_config|:<keys>) expressions pointing to a list of native +# libraries to consider in |build_config|. +# output: Path to native libraries config. +template("allot_native_libraries") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/allot_native_libraries.py" + args = [ + "--output", + rebase_path(invoker.output, root_build_dir), + ] + outputs = [ invoker.output ] + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [] + foreach(_module, invoker.modules) { + deps += [ _module.build_config_target ] + inputs += [ _module.build_config ] + _rebased_build_config = rebase_path(_module.build_config, root_out_dir) + foreach(_key, invoker.native_libraries_filearg_keys) { + args += [ + "--libraries", + "${_module.name},@FileArg($_rebased_build_config:$_key)", + ] + } + if (defined(_module.parent)) { + args += [ + "--dep", + "${_module.parent}:${_module.name}", + ] + } + } + } +} diff --git a/third_party/libwebrtc/build/config/android/linker_version_script.gni b/third_party/libwebrtc/build/config/android/linker_version_script.gni new file mode 100644 index 0000000000..96d8b665d1 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/linker_version_script.gni @@ -0,0 +1,43 @@ +# Copyright 2018 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. + +import("//build/config/python.gni") + +# Generate a custom linker version script that can later be used with +# "-Wl,--version-script=<path>" ldflags. +# +# Variables: +# export_java_symbols: Optional. If true, also export all Java_* symbols +# exported for JNI. +# export_symbol_allowlist_files: Optional. List of paths to input files containing +# lists of symbols to export. +# linker_script: Path to output linker version script. +# +template("generate_linker_version_script") { + action_with_pydeps(target_name) { + script = "//build/android/gyp/generate_linker_version_script.py" + outputs = [ invoker.linker_script ] + inputs = [] + args = [ "--output=" + rebase_path(invoker.linker_script, root_build_dir) ] + + if (defined(invoker.export_java_symbols) && invoker.export_java_symbols) { + args += [ "--export-java-symbols" ] + } + + if (defined(invoker.export_feature_registrations) && + invoker.export_feature_registrations) { + args += [ "--export-feature-registrations" ] + } + + if (defined(invoker.export_symbol_allowlist_files)) { + foreach(file_, invoker.export_symbol_allowlist_files) { + inputs += [ file_ ] + args += [ + "--export-symbol-allowlist-file", + rebase_path(file_, root_build_dir), + ] + } + } + } +} diff --git a/third_party/libwebrtc/build/config/android/rules.gni b/third_party/libwebrtc/build/config/android/rules.gni new file mode 100644 index 0000000000..45499a3781 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/rules.gni @@ -0,0 +1,5183 @@ +# Copyright 2014 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. + +# Do not add any imports to non-//build directories here. +# Some projects (e.g. V8) do not have non-build directories DEPS'ed in. + +import("//build/config/android/channel.gni") +import("//build/config/android/config.gni") +import("//build/config/android/internal_rules.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/coverage/coverage.gni") +import("//build/config/python.gni") +import("//build/config/rts.gni") +import("//build/config/zip.gni") +import("//build/toolchain/toolchain.gni") + +assert(is_android) + +declare_args() { + enable_jni_tracing = false +} + +if (target_cpu == "arm") { + _sanitizer_arch = "arm" +} else if (target_cpu == "arm64") { + _sanitizer_arch = "aarch64" +} else if (target_cpu == "x86") { + _sanitizer_arch = "i686" +} + +_sanitizer_runtimes = [] +if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) { + _sanitizer_runtimes = [ "$clang_base_path/lib/clang/$clang_version/lib/linux/libclang_rt.ubsan_standalone-$_sanitizer_arch-android.so" ] +} + +# Creates a dist directory for a native executable. +# +# Running a native executable on a device requires all the shared library +# dependencies of that executable. To make it easier to install and run such an +# executable, this will create a directory containing the native exe and all +# it's library dependencies. +# +# Note: It's usually better to package things as an APK than as a native +# executable. +# +# Variables +# dist_dir: Directory for the exe and libraries. Everything in this directory +# will be deleted before copying in the exe and libraries. +# binary: Path to (stripped) executable. +# extra_files: List of extra files to copy in (optional). +# +# Example +# create_native_executable_dist("foo_dist") { +# dist_dir = "$root_build_dir/foo_dist" +# binary = "$root_build_dir/foo" +# deps = [ ":the_thing_that_makes_foo" ] +# } +template("create_native_executable_dist") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _libraries_list = "${target_gen_dir}/${target_name}_library_dependencies.list" + + _sanitizer_runtimes_target_name = "${target_name}__sanitizer_runtimes" + group(_sanitizer_runtimes_target_name) { + metadata = { + shared_libraries = _sanitizer_runtimes + } + } + + generated_file("${target_name}__library_list") { + forward_variables_from(invoker, [ "deps" ]) + if (!defined(deps)) { + deps = [] + } + deps += [ ":${_sanitizer_runtimes_target_name}" ] + output_conversion = "json" + outputs = [ _libraries_list ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + + copy_ex(target_name) { + inputs = [ + _libraries_list, + invoker.binary, + ] + + dest = invoker.dist_dir + data = [ "${invoker.dist_dir}/" ] + + _rebased_libraries_list = rebase_path(_libraries_list, root_build_dir) + _rebased_binaries_list = rebase_path([ invoker.binary ], root_build_dir) + args = [ + "--clear", + "--files=@FileArg($_rebased_libraries_list)", + "--files=$_rebased_binaries_list", + ] + if (defined(invoker.extra_files)) { + _rebased_extra_files = rebase_path(invoker.extra_files, root_build_dir) + args += [ "--files=$_rebased_extra_files" ] + } + + _depfile = "$target_gen_dir/$target_name.d" + _stamp_file = "$target_gen_dir/$target_name.stamp" + outputs = [ _stamp_file ] + args += [ + "--depfile", + rebase_path(_depfile, root_build_dir), + "--stamp", + rebase_path(_stamp_file, root_build_dir), + ] + + deps = [ ":${target_name}__library_list" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } +} + +if (enable_java_templates) { + import("//build/config/sanitizers/sanitizers.gni") + + # JNI target implementation. See generate_jni or generate_jar_jni for usage. + template("generate_jni_impl") { + _jni_output_dir = "${target_gen_dir}/${target_name}" + if (defined(invoker.jni_generator_include)) { + _jni_generator_include = invoker.jni_generator_include + _jni_generator_include_deps = [] + } else { + _jni_generator_include = + "//base/android/jni_generator/jni_generator_helper.h" + _jni_generator_include_deps = [ + # Using //base/android/jni_generator/jni_generator_helper.h introduces + # a dependency on buildflags targets indirectly through + # base/android/jni_android.h, which is part of the //base target. + # This can't depend directly on //base without causing a dependency + # cycle, though. + "//base:debugging_buildflags", + "//base:logging_buildflags", + "//build:chromeos_buildflags", + ] + } + + action_with_pydeps(target_name) { + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//base/android/jni_generator/jni_generator.py" + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "public_deps", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += _jni_generator_include_deps + inputs = [] + args = [ + "--ptr_type=long", + "--includes", + rebase_path(_jni_generator_include, _jni_output_dir), + ] + + if (defined(invoker.classes)) { + if (defined(invoker.jar_file)) { + _jar_file = invoker.jar_file + } else { + _jar_file = android_sdk_jar + } + inputs += [ _jar_file ] + args += [ + "--jar_file", + rebase_path(_jar_file, root_build_dir), + ] + _input_args = invoker.classes + _input_names = invoker.classes + if (defined(invoker.always_mangle) && invoker.always_mangle) { + args += [ "--always_mangle" ] + } + } else { + assert(defined(invoker.sources)) + inputs += invoker.sources + _input_args = rebase_path(invoker.sources, root_build_dir) + _input_names = invoker.sources + if (use_hashed_jni_names) { + args += [ "--use_proxy_hash" ] + } + if (defined(invoker.namespace)) { + args += [ "-n ${invoker.namespace}" ] + } + } + if (defined(invoker.split_name)) { + args += [ "--split_name=${invoker.split_name}" ] + } + + outputs = [] + foreach(_name, _input_names) { + _name_part = get_path_info(_name, "name") + outputs += [ "${_jni_output_dir}/${_name_part}_jni.h" ] + } + + # Avoid passing GN lists because not all webrtc embedders use //build. + foreach(_output, outputs) { + args += [ + "--output_file", + rebase_path(_output, root_build_dir), + ] + } + foreach(_input, _input_args) { + args += [ "--input_file=$_input" ] + } + + if (enable_profiling) { + args += [ "--enable_profiling" ] + } + if (enable_jni_tracing) { + args += [ "--enable_tracing" ] + } + } + } + + # Declare a jni target + # + # This target generates the native jni bindings for a set of .java files. + # + # See base/android/jni_generator/jni_generator.py for more info about the + # format of generating JNI bindings. + # + # Variables + # sources: list of .java files to generate jni for + # namespace: Specify the namespace for the generated header file. + # deps, public_deps: As normal + # + # Example + # # Target located in base/BUILD.gn. + # generate_jni("foo_jni") { + # # Generates gen/base/foo_jni/Foo_jni.h + # # To use: #include "base/foo_jni/Foo_jni.h" + # sources = [ + # "android/java/src/org/chromium/foo/Foo.java", + # ..., + # ] + # } + template("generate_jni") { + generate_jni_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + # Declare a jni target for a prebuilt jar + # + # This target generates the native jni bindings for a set of classes in a .jar. + # + # See base/android/jni_generator/jni_generator.py for more info about the + # format of generating JNI bindings. + # + # Variables + # classes: list of .class files in the jar to generate jni for. These should + # include the full path to the .class file. + # jar_file: the path to the .jar. If not provided, will default to the sdk's + # android.jar + # always_mangle: Mangle all generated method names. By default, the script + # only mangles methods that cause ambiguity due to method overload. + # deps, public_deps: As normal + # + # Example + # # Target located in base/BUILD.gn. + # generate_jar_jni("foo_jni") { + # # Generates gen/base/foo_jni/Runnable_jni.h + # # To use: #include "base/foo_jni/Runnable_jni.h" + # classes = [ + # "android/view/Foo.class", + # ] + # } + template("generate_jar_jni") { + generate_jni_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + # Declare a jni registration target. + # + # This target generates a srcjar containing a copy of GEN_JNI.java, which has + # the native methods of all dependent java files. It can also create a .h file + # for use with manual JNI registration. + # + # The script does not scan any generated sources (those within .srcjars, or + # within root_build_dir). This could be fixed by adding deps & logic to scan + # .srcjars, but isn't currently needed. + # + # See base/android/jni_generator/jni_registration_generator.py for more info + # about the format of the header file. + # + # Variables + # targets: List of .build_config.json supported targets to provide java sources. + # header_output: Path to the generated .h file (optional). + # sources_exclusions: List of .java files that should be skipped. (optional) + # namespace: Registration functions will be wrapped into this. (optional) + # require_native_mocks: Enforce that any native calls using + # org.chromium.base.annotations.NativeMethods must have a mock set + # (optional). + # enable_native_mocks: Allow native calls using + # org.chromium.base.annotations.NativeMethods to be mocked in tests + # (optional). + # no_transitive_deps: Generate registration for only the Java source in the + # specified target(s). This is useful for generating registration for + # feature modules, without including base module dependencies. + # + # Example + # generate_jni_registration("chrome_jni_registration") { + # targets = [ ":chrome_public_apk" ] + # header_output = "$target_gen_dir/$target_name.h" + # sources_exclusions = [ + # "//path/to/Exception.java", + # ] + # } + template("generate_jni_registration") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + script = "//base/android/jni_generator/jni_registration_generator.py" + inputs = [] + deps = [] + _srcjar_output = "$target_gen_dir/$target_name.srcjar" + outputs = [ _srcjar_output ] + depfile = "$target_gen_dir/$target_name.d" + + args = [ + "--srcjar-path", + rebase_path(_srcjar_output, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + foreach(_target, invoker.targets) { + deps += [ "${_target}$build_config_target_suffix($default_toolchain)" ] + _build_config = + get_label_info("${_target}($default_toolchain)", "target_gen_dir") + + "/" + get_label_info("${_target}($default_toolchain)", "name") + + ".build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + inputs += [ _build_config ] + + if (defined(invoker.no_transitive_deps) && invoker.no_transitive_deps) { + args += [ "--sources-files=@FileArg($_rebased_build_config:deps_info:java_sources_file)" ] + } else { + args += [ + # This is a list of .sources files. + "--sources-files=@FileArg($_rebased_build_config:deps_info:jni:all_source)", + ] + } + } + + if (use_hashed_jni_names) { + args += [ "--use_proxy_hash" ] + } + + if (defined(invoker.enable_native_mocks) && invoker.enable_native_mocks) { + args += [ "--enable_proxy_mocks" ] + + if (defined(invoker.require_native_mocks) && + invoker.require_native_mocks) { + args += [ "--require_mocks" ] + } + } + + if (defined(invoker.header_output)) { + outputs += [ invoker.header_output ] + args += [ + "--header-path", + rebase_path(invoker.header_output, root_build_dir), + ] + } + + if (defined(invoker.sources_exclusions)) { + _rebase_sources_exclusions = + rebase_path(invoker.sources_exclusions, root_build_dir) + args += [ "--sources-exclusions=$_rebase_sources_exclusions" ] + } + + if (defined(invoker.namespace)) { + args += [ "--namespace=${invoker.namespace}" ] + } + } + } + + # Declare a target for c-preprocessor-generated java files + # + # NOTE: For generating Java conterparts to enums prefer using the java_cpp_enum + # rule instead. + # + # This target generates java files using the host C pre-processor. Each file in + # sources will be compiled using the C pre-processor. If include_path is + # specified, it will be passed (with --I) to the pre-processor. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the C pre-processor. For each + # file in sources, there will be one .java file in the final .srcjar. For a + # file named FooBar.template, a java file will be created with name + # FooBar.java. + # inputs: additional compile-time dependencies. Any files + # `#include`-ed in the templates should be listed here. + # defines: List of -D arguments for the preprocessor. + # + # Example + # java_cpp_template("foo_generated_enum") { + # sources = [ + # "android/java/templates/Foo.template", + # ] + # inputs = [ + # "android/java/templates/native_foo_header.h", + # ] + # } + template("java_cpp_template") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "inputs", + "public_deps", + "sources", + "testonly", + "visibility", + ]) + script = "//build/android/gyp/gcc_preprocess.py" + outputs = [ "$target_gen_dir/$target_name.srcjar" ] + + _include_dirs = [ + "//", + root_gen_dir, + ] + _rebased_include_dirs = rebase_path(_include_dirs, root_build_dir) + args = [ + "--include-dirs=$_rebased_include_dirs", + "--output", + rebase_path(outputs[0], root_build_dir), + ] + if (defined(invoker.defines)) { + foreach(_define, invoker.defines) { + args += [ + "--define", + _define, + ] + } + } + args += rebase_path(sources, root_build_dir) + } + } + + # Declare a target for generating Java classes from C++ enums. + # + # This target generates Java files from C++ enums using a script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each annotated + # enum contained in the sources files the script will generate a .java + # file with the same name as the name of the enum. + # + # Example + # java_cpp_enum("foo_generated_enum") { + # sources = [ + # "src/native_foo_header.h", + # ] + # } + template("java_cpp_enum") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_enum.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + + args = [ "--srcjar=$_rebased_srcjar_path" ] + _rebased_sources + outputs = [ _srcjar_path ] + } + } + + # Declare a target for generating Java classes with string constants matching + # those found in C++ files using a python script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each string + # constant in the source files, the script will add a corresponding + # Java string to the specified template file. + # Example + # java_cpp_strings("foo_switches") { + # sources = [ + # "src/foo_switches.cc", + # ] + # template = "src/templates/FooSwitches.java.tmpl + # } + # + # foo_switches.cc: + # + # // A switch. + # const char kASwitch = "a-switch"; + # + # FooSwitches.java.tmpl + # + # // Copyright {YEAR} 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 file is autogenerated by + # // {SCRIPT_NAME} + # // From + # // {SOURCE_PATH}, and + # // {TEMPLATE_PATH} + # + # package my.java.package; + # + # public abstract class FooSwitches {{ + # // ...snip... + # {NATIVE_STRINGS} + # // ...snip... + # }} + # + # result: + # A FooSwitches.java file, defining a class named FooSwitches in the package + # my.java.package. + template("java_cpp_strings") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_strings.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + _rebased_template = rebase_path(invoker.template, root_build_dir) + + args = [ + "--srcjar=$_rebased_srcjar_path", + "--template=$_rebased_template", + ] + args += _rebased_sources + sources += [ invoker.template ] + + outputs = [ _srcjar_path ] + } + } + + # Declare a target for generating Java classes with string constants matching + # those found in C++ base::Feature declarations, using a python script. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables + # sources: list of files to be processed by the script. For each + # base::Feature in the source files, the script will add a + # corresponding Java string for that feature's name to the + # specified template file. + # Example + # java_cpp_features("foo_features") { + # sources = [ + # "src/foo_features.cc", + # ] + # template = "src/templates/FooFeatures.java.tmpl + # } + # + # foo_features.cc: + # + # // A feature. + # const base::Feature kSomeFeature{"SomeFeature", + # base::FEATURE_DISABLED_BY_DEFAULT}; + # + # FooFeatures.java.tmpl + # + # // Copyright $YEAR 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. + # + # package my.java.package; + # + # public final class FooFeatures {{ + # // ...snip... + # {NATIVE_STRINGS} + # // ...snip... + # // Do not instantiate this class. + # private FooFeatures() {{}} + # }} + # + # result: + # A FooFeatures.java file, defining a class named FooFeatures in the package + # my.java.package. + template("java_cpp_features") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_features.py" + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _rebased_srcjar_path = rebase_path(_srcjar_path, root_build_dir) + _rebased_sources = rebase_path(invoker.sources, root_build_dir) + _rebased_template = rebase_path(invoker.template, root_build_dir) + + args = [ + "--srcjar=$_rebased_srcjar_path", + "--template=$_rebased_template", + ] + args += _rebased_sources + sources += [ invoker.template ] + + outputs = [ _srcjar_path ] + } + } + + # Declare a target for processing a Jinja template. + # + # Variables + # input: The template file to be processed. + # includes: List of files {% include %}'ed by input. + # output: Where to save the result. + # variables: (Optional) A list of variables to make available to the template + # processing environment, e.g. ["name=foo", "color=red"]. + # + # Example + # jinja_template("chrome_public_manifest") { + # input = "java/AndroidManifest.xml" + # output = "$target_gen_dir/AndroidManifest.xml" + # } + template("jinja_template") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = [ invoker.input ] + if (defined(invoker.includes)) { + inputs += invoker.includes + } + script = "//build/android/gyp/jinja_template.py" + + outputs = [ invoker.output ] + + args = [ + "--loader-base-dir", + rebase_path("//", root_build_dir), + "--inputs", + rebase_path(invoker.input, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--check-includes", + ] + if (defined(invoker.includes)) { + _rebased_includes = rebase_path(invoker.includes, root_build_dir) + args += [ "--includes=$_rebased_includes" ] + } + if (defined(invoker.variables)) { + args += [ "--variables=${invoker.variables}" ] + } + } + } + + # Writes native libraries to a NativeLibaries.java file. + # + # This target will create a single .srcjar. Adding this target to an + # android_library target's srcjar_deps will make the generated java files be + # included in that library's final outputs. + # + # Variables: + # native_libraries_list_file: (Optional) Path to file listing all native + # libraries to write. + # version_number: (Optional) String of expected version of 'main' native + # library. + # enable_chromium_linker: (Optional) Whether to use the Chromium linker. + # load_library_from_apk: (Optional) Whether libraries should be loaded from + # the APK without uncompressing. + # use_final_fields: True to use final fields. When false, all other + # variables must not be set. + template("write_native_libraries_java") { + _native_libraries_file = "$target_gen_dir/$target_name.srcjar" + if (target_cpu == "arm" || target_cpu == "arm64") { + _cpu_family = "CPU_FAMILY_ARM" + } else if (target_cpu == "x86" || target_cpu == "x64") { + _cpu_family = "CPU_FAMILY_X86" + } else if (target_cpu == "mipsel" || target_cpu == "mips64el") { + _cpu_family = "CPU_FAMILY_MIPS" + } else { + assert(false, "Unsupported CPU family") + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/write_native_libraries_java.py" + outputs = [ _native_libraries_file ] + args = [ + "--output", + rebase_path(_native_libraries_file, root_build_dir), + "--cpu-family", + _cpu_family, + ] + if (invoker.use_final_fields) { + # Write native_libraries_list_file via depfile rather than specifyin it + # as a dep in order allow R8 to run in parallel with native compilation. + depfile = "$target_gen_dir/$target_name.d" + args += [ + "--final", + "--depfile", + rebase_path(depfile, root_build_dir), + "--native-libraries-list", + rebase_path(invoker.native_libraries_list_file, root_build_dir), + ] + if (defined(invoker.main_component_library)) { + args += [ + "--main-component-library", + invoker.main_component_library, + ] + } + if (defined(invoker.enable_chromium_linker) && + invoker.enable_chromium_linker) { + args += [ "--enable-chromium-linker" ] + } + if (defined(invoker.load_library_from_apk) && + invoker.load_library_from_apk) { + args += [ "--load-library-from-apk" ] + } + if (defined(invoker.use_modern_linker) && invoker.use_modern_linker) { + args += [ "--use-modern-linker" ] + } + } + } + } + + # Declare a target for a set of Android resources generated at build + # time and stored in a single zip archive. The content of the archive + # should match the layout of a regular Android res/ folder (but the + # archive should not include a top-level res/ directory). + # + # Note that there is no associated .srcjar, R.txt or package name + # associated with this target. + # + # Variables: + # generated_resources_zip: Generated zip archive path. + # generating_target: Name of the target generating + # generated_resources_zip. This rule will check that it is part + # of its outputs. + # deps: Specifies the dependencies of this target. Any Android resources + # listed here will be also be included *after* this one when compiling + # all resources for a final apk or junit binary. This is useful to + # ensure that the resources of the current target override those of the + # dependency as well (and would not work if you have these deps to the + # generating target's dependencies). + # + # Example + # _zip_archive = "$target_gen_dir/${target_name}.resources_zip" + # + # action("my_resources__create_zip") { + # _depfile = "$target_gen_dir/${target_name}.d" + # script = "//build/path/to/create_my_resources_zip.py" + # args = [ + # "--depfile", rebase_path(_depfile, root_build_dir), + # "--output-zip", rebase_path(_zip_archive, root_build_dir), + # ] + # inputs = [] + # outputs = _zip_archive + # depfile = _depfile + # } + # + # android_generated_resources("my_resources") { + # generated_resources_zip = _zip_archive + # generating_target = ":my_resources__create_zip" + # } + # + template("android_generated_resources") { + forward_variables_from(invoker, [ "testonly" ]) + _build_config = "$target_gen_dir/${target_name}.build_config.json" + _rtxt_out_path = "$target_gen_dir/${target_name}.R.txt" + write_build_config("$target_name$build_config_target_suffix") { + forward_variables_from(invoker, [ "resource_overlay" ]) + + build_config = _build_config + resources_zip = invoker.generated_resources_zip + type = "android_resources" + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + r_text = _rtxt_out_path + } + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "visibility" ]) + public_deps = [ + ":$target_name$build_config_target_suffix", + invoker.generating_target, + ] + inputs = [ invoker.generated_resources_zip ] + outputs = [ _rtxt_out_path ] + script = "//build/android/gyp/create_r_txt.py" + args = [ + "--resources-zip-path", + rebase_path(invoker.generated_resources_zip, root_build_dir), + "--rtxt-path", + rebase_path(_rtxt_out_path, root_build_dir), + ] + } + } + + # Declare a target for processing Android resources as Jinja templates. + # + # This takes an Android resource directory where each resource is a Jinja + # template, processes each template, then packages the results in a zip file + # which can be consumed by an android resources, library, or apk target. + # + # If this target is included in the deps of an android resources/library/apk, + # the resources will be included with that target. + # + # Variables + # resources: The list of resources files to process. + # res_dir: The resource directory containing the resources. + # variables: (Optional) A list of variables to make available to the template + # processing environment, e.g. ["name=foo", "color=red"]. + # + # Example + # jinja_template_resources("chrome_public_template_resources") { + # res_dir = "res_template" + # resources = ["res_template/xml/syncable.xml"] + # variables = ["color=red"] + # } + template("jinja_template_resources") { + _resources_zip = "$target_out_dir/${target_name}.resources.zip" + _generating_target_name = "${target_name}__template" + + action_with_pydeps(_generating_target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + inputs = invoker.resources + script = "//build/android/gyp/jinja_template.py" + + outputs = [ _resources_zip ] + + _rebased_resources = rebase_path(invoker.resources, root_build_dir) + args = [ + "--inputs=${_rebased_resources}", + "--inputs-base-dir", + rebase_path(invoker.res_dir, root_build_dir), + "--outputs-zip", + rebase_path(_resources_zip, root_build_dir), + "--check-includes", + ] + if (defined(invoker.variables)) { + variables = invoker.variables + args += [ "--variables=${variables}" ] + } + } + + android_generated_resources(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "deps", + "resource_overlay", + ]) + generating_target = ":$_generating_target_name" + generated_resources_zip = _resources_zip + } + } + + # Declare a prebuilt android native library. + # + # This takes a base directory and library name and then looks for the library + # in <base dir>/$android_app_abi/<library name>. + # + # If you depend on this target, the library is stripped and output to the + # same locations non-prebuilt libraries are output. + # + # Variables + # base_dir: Directory where all ABIs of the library live. + # library_name: Name of the library .so file. + # + # Example + # android_native_prebuilt("elements_native") { + # base_dir = "//third_party/elements" + # lib_name = "elements.so" + # } + template("android_native_prebuilt") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + script = "//build/android/gyp/process_native_prebuilt.py" + _lib_path = "${invoker.base_dir}/$android_app_abi/${invoker.lib_name}" + _stripped_output_path = "$root_out_dir/${invoker.lib_name}" + _unstripped_output_path = + "$root_out_dir/lib.unstripped/${invoker.lib_name}" + inputs = [ _lib_path ] + outputs = [ + _stripped_output_path, + _unstripped_output_path, + ] + + # Add unstripped output to runtime deps for use by bots during stacktrace + # symbolization. + data = [ _unstripped_output_path ] + + _rebased_lib_path = rebase_path(_lib_path, root_build_dir) + _rebased_stripped_ouput_path = + rebase_path(_stripped_output_path, root_build_dir) + _rebased_unstripped_ouput_path = + rebase_path(_unstripped_output_path, root_build_dir) + _strip_tool_path = + rebase_path("//buildtools/third_party/eu-strip/bin/eu-strip", + root_build_dir) + + args = [ + "--strip-path=$_strip_tool_path", + "--input-path=$_rebased_lib_path", + "--stripped-output-path=$_rebased_stripped_ouput_path", + "--unstripped-output-path=$_rebased_unstripped_ouput_path", + ] + } + } + + # Declare an Android resources target + # + # This creates a resources zip file that will be used when building an Android + # library or apk and included into a final apk. + # + # To include these resources in a library/apk, this target should be listed in + # the library's deps. A library/apk will also include any resources used by its + # own dependencies. + # + # Variables + # sources: List of resource files for this target. + # deps: Specifies the dependencies of this target. Any Android resources + # listed in deps will be included by libraries/apks that depend on this + # target. + # alternative_android_sdk_dep: Optional. Alternative Android system + # android java target to use. + # android_manifest: AndroidManifest.xml for this target (optional). Will be + # merged into apks that directly or indirectly depend on this target. + # android_manifest_dep: Target that generates AndroidManifest (if applicable) + # custom_package: java package for generated .java files. + # allow_missing_resources: Do not fail if a resource exists in a directory + # but is not listed in sources. + # shared_resources: If true make a resource package that can be loaded by a + # different application at runtime to access the package's resources. + # resource_overlay: Whether the resources in 'sources' should override + # resources with the same name. Does not affect the behaviour of any + # android_resources() deps of this target. If a target with + # resource_overlay=true depends on another target with + # resource_overlay=true the target with the dependency overrides the + # other. + # r_text_file: (optional) path to pre-generated R.txt to be used when + # generating R.java instead of resource-based aapt-generated one. + # recursive_resource_deps: (optional) whether deps should be walked + # recursively to find resource deps. + # + # Example: + # android_resources("foo_resources") { + # deps = [":foo_strings_grd"] + # sources = [ + # "res/drawable/foo1.xml", + # "res/drawable/foo2.xml", + # ] + # custom_package = "org.chromium.foo" + # } + # + # android_resources("foo_resources_overrides") { + # deps = [":foo_resources"] + # sources = [ + # "res_overrides/drawable/foo1.xml", + # "res_overrides/drawable/foo2.xml", + # ] + # } + template("android_resources") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _base_path = "$target_gen_dir/$target_name" + if (defined(invoker.v14_skip)) { + not_needed(invoker, [ "v14_skip" ]) + } + + _res_sources_path = "$target_gen_dir/${invoker.target_name}.res.sources" + + _resources_zip = "$target_out_dir/$target_name.resources.zip" + _r_text_out_path = _base_path + "_R.txt" + _build_config = _base_path + ".build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + _deps = [] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + if (defined(invoker.alternative_android_sdk_dep)) { + _deps += [ invoker.alternative_android_sdk_dep ] + } else { + _deps += [ "//third_party/android_sdk:android_sdk_java" ] + } + + _resource_files = [] + if (defined(invoker.sources)) { + _resource_files += invoker.sources + } + + _rebased_resource_files = rebase_path(_resource_files, root_build_dir) + write_file(_res_sources_path, _rebased_resource_files) + + # This is necessary so we only lint chromium resources. + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } else { + # Default based on whether target is in third_party. + _chromium_code = + filter_exclude([ get_label_info(":$target_name", "dir") ], + [ "*\bthird_party\b*" ]) != [] + } + + write_build_config(_build_config_target_name) { + type = "android_resources" + build_config = _build_config + resources_zip = _resources_zip + res_sources_path = _res_sources_path + chromium_code = _chromium_code + + forward_variables_from(invoker, + [ + "android_manifest", + "android_manifest_dep", + "custom_package", + "mergeable_android_manifests", + "resource_overlay", + "recursive_resource_deps", + ]) + + r_text = _r_text_out_path + possible_config_deps = _deps + + # Always merge manifests from resources. + # * Might want to change this at some point for consistency and clarity, + # but keeping for backwards-compatibility. + if (!defined(mergeable_android_manifests) && defined(android_manifest)) { + mergeable_android_manifests = [ android_manifest ] + } + } + + prepare_resources(target_name) { + forward_variables_from(invoker, + [ + "strip_drawables", + "allow_missing_resources", + "visibility", + ]) + deps = _deps + + res_sources_path = _res_sources_path + sources = _resource_files + + resources_zip = _resources_zip + r_text_out_path = _r_text_out_path + + if (defined(invoker.r_text_file)) { + r_text_in_path = invoker.r_text_file + } + } + } + + # Declare an Android assets target. + # + # Defines a set of files to include as assets in a dependent apk. + # + # To include these assets in an apk, this target should be listed in + # the apk's deps, or in the deps of a library target used by an apk. + # + # Variables + # deps: Specifies the dependencies of this target. Any Android assets + # listed in deps will be included by libraries/apks that depend on this + # target. + # sources: List of files to include as assets. + # renaming_sources: List of files to include as assets and be renamed. + # renaming_destinations: List of asset paths for files in renaming_sources. + # disable_compression: Whether to disable compression for files that are + # known to be compressable (default: false). + # treat_as_locale_paks: Causes base's BuildConfig.java to consider these + # assets to be locale paks. + # + # Example: + # android_assets("content_shell_assets") { + # deps = [ + # ":generates_foo", + # ":other_assets", + # ] + # sources = [ + # "//path/asset1.png", + # "//path/asset2.png", + # "$target_gen_dir/foo.dat", + # ] + # } + # + # android_assets("overriding_content_shell_assets") { + # deps = [ ":content_shell_assets" ] + # # Override foo.dat from content_shell_assets. + # sources = [ "//custom/foo.dat" ] + # renaming_sources = [ "//path/asset2.png" ] + # renaming_destinations = [ "renamed/asset2.png" ] + # } + template("android_assets") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "android_assets" + build_config = _build_config + + forward_variables_from(invoker, + [ + "disable_compression", + "treat_as_locale_paks", + ]) + + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + + if (defined(invoker.sources)) { + asset_sources = invoker.sources + } + if (defined(invoker.renaming_sources)) { + assert(defined(invoker.renaming_destinations)) + _source_count = 0 + foreach(_, invoker.renaming_sources) { + _source_count += 1 + } + _dest_count = 0 + foreach(_, invoker.renaming_destinations) { + _dest_count += 1 + } + assert( + _source_count == _dest_count, + "android_assets() renaming_sources.length != renaming_destinations.length") + asset_renaming_sources = invoker.renaming_sources + asset_renaming_destinations = invoker.renaming_destinations + } + } + + group(target_name) { + forward_variables_from(invoker, [ "deps" ]) + public_deps = [ ":$_build_config_target_name" ] + } + } + + # Declare a group() that supports forwarding java dependency information. + # + # Example + # java_group("conditional_deps") { + # if (enable_foo) { + # deps = [":foo_java"] + # } + # } + template("java_group") { + _build_config_vars = [ + "input_jars_paths", + "mergeable_android_manifests", + "proguard_configs", + ] + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + write_build_config("$target_name$build_config_target_suffix") { + forward_variables_from(invoker, _build_config_vars) + type = "group" + build_config = "$target_gen_dir/${invoker.target_name}.build_config.json" + supports_android = true + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + } + foreach(_group_name, + [ + "header", + "impl", + "assetres", + ]) { + java_lib_group("${target_name}__${_group_name}") { + forward_variables_from(invoker, [ "deps" ]) + group_name = _group_name + } + } + group(target_name) { + forward_variables_from(invoker, + "*", + _build_config_vars + TESTONLY_AND_VISIBILITY) + if (!defined(deps)) { + deps = [] + } + deps += [ ":$target_name$build_config_target_suffix" ] + } + } + + # Declare a Java executable target + # + # Same as java_library, but also creates a wrapper script within + # $root_out_dir/bin. + # + # Supports all variables of java_library(), plus: + # main_class: When specified, a wrapper script is created within + # $root_build_dir/bin to launch the binary with the given class as the + # entrypoint. + # wrapper_script_name: Filename for the wrapper script (default=target_name) + # wrapper_script_args: List of additional arguments for the wrapper script. + # + # Example + # java_binary("foo") { + # sources = [ "org/chromium/foo/FooMain.java" ] + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooMain" + # } + # + # java_binary("foo") { + # jar_path = "lib/prebuilt.jar" + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooMain" + # } + template("java_binary") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_binary" + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//third_party/jdk:java_data" ] + } + } + + # Declare a Java Annotation Processor. + # + # Supports all variables of java_library(), plus: + # jar_path: Path to a prebuilt jar. Mutually exclusive with sources & + # srcjar_deps. + # main_class: The fully-quallified class name of the processor's entry + # point. + # + # Example + # java_annotation_processor("foo_processor") { + # sources = [ "org/chromium/foo/FooProcessor.java" ] + # deps = [ ":bar_java" ] + # main_class = "org.chromium.foo.FooProcessor" + # } + # + # java_annotation_processor("foo_processor") { + # jar_path = "lib/prebuilt.jar" + # main_class = "org.chromium.foo.FooMain" + # } + # + # java_library("...") { + # annotation_processor_deps = [":foo_processor"] + # } + # + template("java_annotation_processor") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_annotation_processor" + } + } + + # Declare a Junit executable target + # + # This target creates an executable from java code for running as a junit test + # suite. The executable will be in the output folder's /bin/ directory. + # + # Supports all variables of java_binary(). + # + # Example + # junit_binary("foo") { + # sources = [ "org/chromium/foo/FooTest.java" ] + # deps = [ ":bar_java" ] + # } + template("junit_binary") { + testonly = true + + _java_binary_target_name = "${target_name}__java_binary" + _test_runner_target_name = "${target_name}__test_runner_script" + _main_class = "org.chromium.testing.local.JunitTestMain" + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + _deps = [ + "//testing/android/junit:junit_test_support", + "//third_party/android_deps:robolectric_all_java", + "//third_party/junit", + "//third_party/mockito:mockito_java", + ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + if (defined(invoker.alternative_android_sdk_dep)) { + _android_sdk_dep = invoker.alternative_android_sdk_dep + } else { + _android_sdk_dep = "//third_party/android_sdk:android_sdk_java" + } + + # a package name or a manifest is required to have resources. This is + # added so that junit tests that do not care about the package name can + # still use resources without having to explicitly set one. + if (defined(invoker.package_name)) { + _package_name = invoker.package_name + } else if (!defined(invoker.android_manifest)) { + _package_name = "org.chromium.test" + } + + _resource_arsc_output = "${target_gen_dir}/${target_name}.ap_" + _compile_resources_target = "${target_name}__compile_resources" + compile_resources(_compile_resources_target) { + forward_variables_from(invoker, [ "android_manifest" ]) + deps = _deps + android_sdk_dep = _android_sdk_dep + build_config_dep = ":$_build_config_target_name" + build_config = _build_config + if (defined(_package_name)) { + rename_manifest_package = _package_name + } + if (!defined(android_manifest)) { + android_manifest = "//build/android/AndroidManifest.xml" + } + arsc_output = _resource_arsc_output + min_sdk_version = default_min_sdk_version + target_sdk_version = android_sdk_version + } + + _jni_srcjar_target = "${target_name}__final_jni" + _outer_target_name = target_name + generate_jni_registration(_jni_srcjar_target) { + enable_native_mocks = true + require_native_mocks = true + targets = [ ":$_outer_target_name" ] + } + + java_library_impl(_java_binary_target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY + [ "deps" ]) + type = "junit_binary" + main_target_name = invoker.target_name + + # Include the android SDK jar(s) for resource processing. + include_android_sdk = true + + # Robolectric can handle deps that set !supports_android as well those + # that set requires_android. + bypass_platform_checks = true + deps = _deps + testonly = true + main_class = _main_class + wrapper_script_name = "helper/$main_target_name" + + # As of April 2021, adding -XX:TieredStopAtLevel=1 does not affect the + # wall time of a single robolectric shard, but does reduce the CPU time by + # 66%, which makes sharding more effective. + tiered_stop_at_level_one = true + + if (!defined(srcjar_deps)) { + srcjar_deps = [] + } + srcjar_deps += [ + ":$_compile_resources_target", + ":$_jni_srcjar_target", + + # This dep is required for any targets that depend on //base:base_java. + "//build/android:build_config_gen", + ] + } + + test_runner_script(_test_runner_target_name) { + test_name = invoker.target_name + test_suite = invoker.target_name + test_type = "junit" + ignore_all_data_deps = true + resource_apk = _resource_arsc_output + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "visibility", + ]) + public_deps = [ + ":$_build_config_target_name", + ":$_java_binary_target_name", + ":$_test_runner_target_name", + ] + } + } + + # Declare a java library target + # + # Variables + # deps: Specifies the dependencies of this target. Java targets in this list + # will be added to the javac classpath. + # public_deps: Dependencies that this target exposes as part of its public API. + # public_deps do not need to be listed in both the 'deps' and 'public_deps' lists. + # annotation_processor_deps: List of java_annotation_processor targets to + # use when compiling. + # + # jar_path: Path to a prebuilt jar. Mutually exclusive with sources & + # srcjar_deps. + # sources: List of .java files included in this library. + # srcjar_deps: List of srcjar dependencies. The .java files in the srcjars + # will be added to sources and be included in this library. + # + # input_jars_paths: A list of paths to the jars that should be included + # in the compile-time classpath. These are in addition to library .jars + # that appear in deps. + # + # chromium_code: If true, extra analysis warning/errors will be enabled. + # enable_errorprone: If true, enables the errorprone compiler. + # skip_build_server: If true, avoids sending tasks to the build server. + # + # jar_excluded_patterns: List of patterns of .class files to exclude. + # jar_included_patterns: List of patterns of .class files to include. + # When omitted, all classes not matched by jar_excluded_patterns are + # included. When specified, all non-matching .class files are stripped. + # + # low_classpath_priority: Indicates that the library should be placed at the + # end of the classpath. The default classpath order has libraries ordered + # before the libraries that they depend on. 'low_classpath_priority' is + # useful when one java_library() overrides another via + # 'jar_excluded_patterns' and the overriding library does not depend on + # the overridee. + # + # output_name: File name for the output .jar (not including extension). + # Defaults to the input .jar file name. + # + # proguard_configs: List of proguard configs to use in final apk step for + # any apk that depends on this library. + # + # supports_android: If true, Android targets (android_library, android_apk) + # may depend on this target. Note: if true, this target must only use the + # subset of Java available on Android. + # bypass_platform_checks: Disables checks about cross-platform (Java/Android) + # dependencies for this target. This will allow depending on an + # android_library target, for example. + # enable_desugar: If false, disables desugaring of lambdas, etc. Use this + # only when you are sure the library does not require desugaring. E.g. + # to hide warnings shown from desugaring. + # + # additional_jar_files: Use to package additional files (Java resources) + # into the output jar. Pass a list of length-2 lists with format: + # [ [ path_to_file, path_to_put_in_jar ] ] + # + # javac_args: Additional arguments to pass to javac. + # errorprone_args: Additional arguments to pass to errorprone. + # + # data_deps, testonly + # + # Example + # java_library("foo_java") { + # sources = [ + # "org/chromium/foo/Foo.java", + # "org/chromium/foo/FooInterface.java", + # "org/chromium/foo/FooService.java", + # ] + # deps = [ + # ":bar_java" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # jar_excluded_patterns = [ + # "*/FooService.class", "org/chromium/FooService\$*.class" + # ] + # } + template("java_library") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_library" + } + } + + # Declare a java library target for a prebuilt jar + # + # Supports all variables of java_library(). + # + # Example + # java_prebuilt("foo_java") { + # jar_path = "foo.jar" + # deps = [ + # ":foo_resources", + # ":bar_java" + # ] + # } + template("java_prebuilt") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + type = "java_library" + } + } + + # Combines all dependent .jar files into a single .jar file. + # + # Variables: + # output: Path to the output jar. + # override_build_config: Use a pre-existing .build_config. Must be of type + # "apk". + # use_interface_jars: Use all dependent interface .jars rather than + # implementation .jars. + # use_unprocessed_jars: Use unprocessed / undesugared .jars. + # direct_deps_only: Do not recurse on deps. + # jar_excluded_patterns (optional) + # List of globs for paths to exclude. + # + # Example + # dist_jar("lib_fatjar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # } + template("dist_jar") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _supports_android = + !defined(invoker.supports_android) || invoker.supports_android + _use_interface_jars = + defined(invoker.use_interface_jars) && invoker.use_interface_jars + _use_unprocessed_jars = + defined(invoker.use_unprocessed_jars) && invoker.use_unprocessed_jars + _direct_deps_only = + defined(invoker.direct_deps_only) && invoker.direct_deps_only + assert(!(_use_unprocessed_jars && _use_interface_jars), + "Cannot set both use_interface_jars and use_unprocessed_jars") + + _jar_target_name = target_name + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + if (_supports_android) { + _deps += [ "//third_party/android_sdk:android_sdk_java" ] + } + + if (defined(invoker.override_build_config)) { + _build_config = invoker.override_build_config + } else { + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_jar" + supports_android = _supports_android + requires_android = + defined(invoker.requires_android) && invoker.requires_android + possible_config_deps = _deps + ignore_dependency_public_deps = _direct_deps_only + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + action_with_pydeps(_jar_target_name) { + forward_variables_from(invoker, [ "data" ]) + script = "//build/android/gyp/zip.py" + depfile = "$target_gen_dir/$target_name.d" + deps = _deps + + inputs = [ _build_config ] + + outputs = [ invoker.output ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--no-compress", + ] + + if (_direct_deps_only) { + if (_use_interface_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:javac:interface_classpath)" ] + } else if (_use_unprocessed_jars) { + args += [ + "--input-zips=@FileArg($_rebased_build_config:javac:classpath)", + ] + } else { + assert( + false, + "direct_deps_only does not work without use_interface_jars or use_unprocessed_jars") + } + } else { + if (_use_interface_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:dist_jar:all_interface_jars)" ] + } else if (_use_unprocessed_jars) { + args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ] + } else { + args += [ "--input-zips=@FileArg($_rebased_build_config:deps_info:device_classpath)" ] + } + } + _excludes = [] + if (defined(invoker.jar_excluded_patterns)) { + _excludes += invoker.jar_excluded_patterns + } + if (_use_interface_jars) { + # Turbine adds files like: META-INF/TRANSITIVE/.../Foo.class + # These confuse proguard: https://crbug.com/1081443 + _excludes += [ "META-INF/*" ] + } + if (_excludes != []) { + args += [ "--input-zips-excluded-globs=$_excludes" ] + } + } + } + + # Combines all dependent .jar files into a single proguarded .dex file. + # + # Variables: + # output: Path to the output dex. + # proguard_enabled: Whether to enable R8. + # proguard_configs: List of proguard configs. + # proguard_enable_obfuscation: Whether to enable obfuscation (default=true). + # + # Example + # dist_dex("lib_fatjar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # } + template("dist_dex") { + _deps = [ "//third_party/android_sdk:android_sdk_java" ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_jar" + forward_variables_from(invoker, + [ + "proguard_configs", + "proguard_enabled", + ]) + supports_android = true + requires_android = true + possible_config_deps = _deps + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + + dex(target_name) { + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "min_sdk_version", + ]) + deps = _deps + build_config = _build_config + enable_multidex = false + output = invoker.output + if (defined(proguard_enabled) && proguard_enabled) { + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this is using jar files + # rather than dex files. + ignore_desugar_missing_deps = true + + # When trying to build a stand-alone .dex, don't add in jdk_libs_dex. + supports_jdk_library_desugaring = false + } else { + _rebased_build_config = rebase_path(_build_config, root_build_dir) + input_dex_filearg = + "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)" + } + } + } + + # Creates an Android .aar library. + # + # Currently supports: + # * AndroidManifest.xml + # * classes.jar + # * jni/ + # * res/ + # * R.txt + # * proguard.txt + # Does not yet support: + # * public.txt + # * annotations.zip + # * assets/ + # See: https://developer.android.com/studio/projects/android-library.html#aar-contents + # + # Variables: + # output: Path to the output .aar. + # proguard_configs: List of proguard configs (optional). + # android_manifest: Path to AndroidManifest.xml (optional). + # native_libraries: list of native libraries (optional). + # direct_deps_only: Do not recurse on deps. (optional, defaults false). + # jar_excluded_patterns (optional): List of globs for paths to exclude. + # jar_included_patterns (optional): List of globs for paths to include. + # + # Example + # dist_aar("my_aar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.aar" + # } + template("dist_aar") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + + _direct_deps_only = + defined(invoker.direct_deps_only) && invoker.direct_deps_only + + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target_name = "$target_name$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + type = "dist_aar" + forward_variables_from(invoker, [ "proguard_configs" ]) + possible_config_deps = _deps + supports_android = true + requires_android = true + ignore_dependency_public_deps = _direct_deps_only + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "data" ]) + depfile = "$target_gen_dir/$target_name.d" + deps = _deps + script = "//build/android/gyp/dist_aar.py" + + inputs = [ _build_config ] + + # Although these will be listed as deps in the depfile, they must also + # appear here so that "gn analyze" knows about them. + # https://crbug.com/827197 + if (defined(invoker.proguard_configs)) { + inputs += invoker.proguard_configs + } + + outputs = [ invoker.output ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", + "--r-text-files=@FileArg($_rebased_build_config:deps_info:dependency_r_txt_files)", + "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", + ] + if (_direct_deps_only) { + args += [ "--jars=@FileArg($_rebased_build_config:javac:classpath)" ] + } else { + args += [ "--jars=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)" ] + } + if (defined(invoker.android_manifest)) { + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + if (defined(invoker.native_libraries) && invoker.native_libraries != []) { + inputs += invoker.native_libraries + _rebased_native_libraries = + rebase_path(invoker.native_libraries, root_build_dir) + + args += [ + "--native-libraries=$_rebased_native_libraries", + "--abi=$android_app_abi", + ] + } + if (defined(invoker.jar_excluded_patterns)) { + args += [ "--jar-excluded-globs=${invoker.jar_excluded_patterns}" ] + } + if (defined(invoker.jar_included_patterns)) { + args += [ "--jar-included-globs=${invoker.jar_included_patterns}" ] + } + if (defined(invoker.resource_included_patterns)) { + args += [ + "--resource-included-globs=${invoker.resource_included_patterns}", + ] + } + } + } + + # Declare an Android library target + # + # This target creates an Android library containing java code and Android + # resources. + # + # Supports all variables of java_library(), plus: + # deps: In addition to defining java deps, this can also include + # android_assets() and android_resources() targets. + # alternative_android_sdk_ijar: if set, the given android_sdk_ijar file + # replaces the default android_sdk_ijar. + # alternative_android_sdk_ijar_dep: the target that generates + # alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar + # is used. + # alternative_android_sdk_jar: actual jar corresponding to + # alternative_android_sdk_ijar, must be set if alternative_android_sdk_ijar + # is used. + # + # Example + # android_library("foo_java") { + # sources = [ + # "android/org/chromium/foo/Foo.java", + # "android/org/chromium/foo/FooInterface.java", + # "android/org/chromium/foo/FooService.java", + # ] + # deps = [ + # ":bar_java" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # jar_excluded_patterns = [ + # "*/FooService.class", "org/chromium/FooService\$*.class" + # ] + # } + template("android_library") { + java_library(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + supports_android = true + requires_android = true + + if (!defined(jar_excluded_patterns)) { + jar_excluded_patterns = [] + } + jar_excluded_patterns += [ + "*/R.class", + "*/R\$*.class", + "*/Manifest.class", + "*/Manifest\$*.class", + "*/GEN_JNI.class", + ] + } + } + + # Declare an Android library target for a prebuilt jar + # + # This target creates an Android library containing java code and Android + # resources. + # + # Supports all variables of android_library(). + # + # Example + # android_java_prebuilt("foo_java") { + # jar_path = "foo.jar" + # deps = [ + # ":foo_resources", + # ":bar_java" + # ] + # } + template("android_java_prebuilt") { + android_library(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + } + } + + template("android_system_java_prebuilt") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + supports_android = true + type = "system_java_library" + } + } + + # Creates org/chromium/build/BuildConfig.java + # This doesn't really belong in //build since it genates a file for //base. + # However, we don't currently have a better way to include this file in all + # apks that depend on //base:base_java. + # + # Variables: + # use_final_fields: True to use final fields. When false, all other + # variables must not be set. + # enable_multidex: Value for ENABLE_MULTIDEX. + # min_sdk_version: Value for MIN_SDK_VERSION. + # bundles_supported: Whether or not this target can be treated as a bundle. + # resources_version_variable: + # is_incremental_install: + # isolated_splits_enabled: Value for ISOLATED_SPLITS_ENABLED. + template("generate_build_config_srcjar") { + java_cpp_template(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + sources = [ "//build/android/java/templates/BuildConfig.template" ] + defines = [] + + # Set these even when !use_final_fields so that they have correct default + # values within junit_binary(), which ignores jar_excluded_patterns. + if (enable_java_asserts) { + defines += [ "_ENABLE_ASSERTS" ] + } + if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) { + defines += [ "_IS_UBSAN" ] + } + + if (is_chrome_branded) { + defines += [ "_IS_CHROME_BRANDED" ] + } + + if (is_chromecast && chromecast_branding == "internal") { + defines += [ "_IS_CHROMECAST_BRANDING_INTERNAL" ] + } + + if (defined(invoker.bundles_supported) && invoker.bundles_supported) { + defines += [ "_BUNDLES_SUPPORTED" ] + } + + if (defined(invoker.isolated_splits_enabled) && + invoker.isolated_splits_enabled) { + defines += [ "_ISOLATED_SPLITS_ENABLED" ] + } + + if (defined(invoker.is_incremental_install) && + invoker.is_incremental_install) { + defines += [ "_IS_INCREMENTAL_INSTALL" ] + } + + if (invoker.use_final_fields) { + forward_variables_from(invoker, [ "deps" ]) + defines += [ "USE_FINAL" ] + if (invoker.enable_multidex) { + defines += [ "ENABLE_MULTIDEX" ] + } + if (defined(invoker.min_sdk_version)) { + defines += [ "_MIN_SDK_VERSION=${invoker.min_sdk_version}" ] + } + if (defined(invoker.resources_version_variable)) { + defines += [ + "_RESOURCES_VERSION_VARIABLE=${invoker.resources_version_variable}", + ] + } + } + } + } + + # Creates ProductConfig.java, a file containing product-specific configuration. + # + # Currently, this includes the list of locales, both in their compressed and + # uncompressed format, as well as library loading + # + # Variables: + # build_config: Path to build_config used for locale lists. + # is_bundle_module: Whether or not this target is part of a bundle build. + # java_package: Java package for the generated class. + # use_chromium_linker: + # use_modern_linker: + template("generate_product_config_srcjar") { + java_cpp_template(target_name) { + defines = [] + _use_final = + defined(invoker.build_config) || + defined(invoker.use_chromium_linker) || + defined(invoker.use_modern_linker) || defined(invoker.is_bundle) + if (_use_final) { + defines += [ "USE_FINAL" ] + } + + sources = [ "//build/android/java/templates/ProductConfig.template" ] + defines += [ "PACKAGE=${invoker.java_package}" ] + + _use_chromium_linker = + defined(invoker.use_chromium_linker) && invoker.use_chromium_linker + _use_modern_linker = + defined(invoker.use_modern_linker) && invoker.use_modern_linker + _is_bundle = defined(invoker.is_bundle_module) && invoker.is_bundle_module + defines += [ + "USE_CHROMIUM_LINKER_VALUE=$_use_chromium_linker", + "USE_MODERN_LINKER_VALUE=$_use_modern_linker", + "IS_BUNDLE_VALUE=$_is_bundle", + ] + if (defined(invoker.build_config)) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + defines += [ "LOCALE_LIST=@FileArg($_rebased_build_config:deps_info:locales_java_list)" ] + } + } + } + + # Declare an Android app module target, which is used as the basis for an + # Android APK or an Android app bundle module. + # + # Supports all variables of android_library(), plus: + # android_manifest: Path to AndroidManifest.xml. NOTE: This manifest must + # not contain a <uses-sdk> element. Use [min|target|max]_sdk_version + # instead. + # android_manifest_dep: Target that generates AndroidManifest (if applicable) + # png_to_webp: If true, pngs (with the exception of 9-patch) are + # converted to webp during resource packaging. + # loadable_modules: List of paths to native libraries to include. Different + # from |shared_libraries| in that: + # * dependencies of this .so are not automatically included + # * ".cr.so" is never added + # * they are not side-loaded when incremental_install=true. + # * load_library_from_apk, use_chromium_linker, + # and enable_relocation_packing do not apply + # Use this instead of shared_libraries when you are going to load the library + # conditionally, and only when shared_libraries doesn't work for you. + # secondary_abi_loadable_modules: This is the loadable_modules analog to + # secondary_abi_shared_libraries. + # shared_libraries: List shared_library targets to bundle. If these + # libraries depend on other shared_library targets, those dependencies will + # also be included in the apk (e.g. for is_component_build). + # secondary_abi_shared_libraries: secondary abi shared_library targets to + # bundle. If these libraries depend on other shared_library targets, those + # dependencies will also be included in the apk (e.g. for is_component_build). + # native_lib_placeholders: List of placeholder filenames to add to the apk + # (optional). + # secondary_native_lib_placeholders: List of placeholder filenames to add to + # the apk for the secondary ABI (optional). + # generate_buildconfig_java: If defined and false, skip generating the + # BuildConfig java class describing the build configuration. The default + # is true when building with Chromium for non-test APKs. + # generate_final_jni: If defined and false, skip generating the + # GEN_JNI srcjar. + # jni_registration_header: If specified, causes the + # ${target_name}__final_jni target to additionally output a + # header file to this path for use with manual JNI registration. + # jni_sources_exclusions: List of source path to exclude from the + # final_jni step. + # aapt_locale_allowlist: If set, all locales not in this list will be + # stripped from resources.arsc. + # resource_exclusion_regex: Causes all drawable images matching the regex to + # be excluded (mipmaps are still included). + # resource_exclusion_exceptions: A list of globs used when + # resource_exclusion_regex is set. Files that match this list will + # still be included. + # resource_values_filter_rules: List of "source_path:name_regex" used to + # filter out unwanted values/ resources. + # shared_resources: True if this is a runtime shared library APK, like + # the system_webview_apk target. Ensures that its resources can be + # used by the loading application process. + # app_as_shared_lib: True if this is a regular application apk that can + # also serve as a runtime shared library, like the monochrome_public_apk + # target. Ensures that the resources are usable both by the APK running + # as an application, or by another process that loads it at runtime. + # shared_resources_allowlist_target: Optional name of a target specifying + # an input R.txt file that lists the resources that can be exported + # by the APK when shared_resources or app_as_shared_lib is defined. + # uncompress_shared_libraries: True if shared libraries should be stored + # uncompressed in the APK. Must be unset or true if load_library_from_apk + # is set to true. + # uncompress_dex: Store final .dex files uncompressed in the apk. + # strip_resource_names: True if resource names should be stripped from the + # resources.arsc file in the apk or module. + # strip_unused_resources: True if unused resources should be stripped from + # the apk or module. + # short_resource_paths: True if resource paths should be shortened in the + # apk or module. + # resources_config_paths: List of paths to the aapt2 optimize config files + # that tags resources with acceptable/non-acceptable optimizations. + # expected_android_manifest: Enables verification of expected merged + # manifest based on a golden file. + # resource_ids_provider_dep: If passed, this target will use the resource + # IDs generated by {resource_ids_provider_dep}__compile_res during + # resource compilation. + # enforce_resource_overlays_in_tests: Enables check for testonly targets that + # dependent resource targets which override another target set + # overlay_resources=true. This check is on for non-test targets and + # cannot be disabled. + # static_library_dependent_targets: A list of scopes describing targets that + # use this target as a static library. Common Java code from the targets + # listed in static_library_dependent_targets will be moved into this + # target. Scope members are name and is_resource_ids_provider. + # static_library_provider: Specifies a single target that this target will + # use as a static library APK. + # static_library_synchronized_proguard: When proguard is enabled, the + # static_library_provider target will provide the dex file(s) for this + # target. + # min_sdk_version: The minimum Android SDK version this target supports. + # Optional, default $default_min_sdk_version. + # target_sdk_version: The target Android SDK version for this target. + # Optional, default to android_sdk_version. + # max_sdk_version: The maximum Android SDK version this target supports. + # Optional, default not set. + # require_native_mocks: Enforce that any native calls using + # org.chromium.base.annotations.NativeMethods must have a mock set + # (optional). + # enable_native_mocks: Allow native calls using + # org.chromium.base.annotations.NativeMethods to be mocked in tests + # (optional). + # product_config_java_packages: Optional list of java packages. If given, a + # ProductConfig.java file will be generated for each package. + # enable_proguard_checks: Turns on -checkdiscard directives and missing + # symbols check in the proguard step (default=true). + # disable_r8_outlining: Turn off outlining during the proguard step. + # annotation_processor_deps: List of java_annotation_processor targets to + # use when compiling the sources given to this target (optional). + # processor_args_javac: List of args to pass to annotation processors when + # compiling sources given to this target (optional). + # bundles_supported: Enable Java code to treat this target as a bundle + # whether (by default determined by the target type). + # main_component_library: Specifies the name of the base component's library + # in a component build. If given, the system will find dependent native + # libraries at runtime by inspecting this library (optional). + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # expected_proguard_config: Checks that the merged set of proguard flags + # matches the given config. + # expected_proguard_config_base: Treat expected_proguard_config as a diff + # with this file as the base. + template("android_apk_or_module") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + assert(defined(invoker.android_manifest)) + _base_path = "$target_out_dir/$target_name/$target_name" + _build_config = "$target_gen_dir/$target_name.build_config.json" + _build_config_target = "$target_name$build_config_target_suffix" + + _min_sdk_version = default_min_sdk_version + _target_sdk_version = android_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + if (defined(invoker.target_sdk_version)) { + _target_sdk_version = invoker.target_sdk_version + } + + _template_name = target_name + + _is_bundle_module = + defined(invoker.is_bundle_module) && invoker.is_bundle_module + if (_is_bundle_module) { + _is_base_module = + defined(invoker.is_base_module) && invoker.is_base_module + } + + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + + if (!_is_bundle_module) { + _final_apk_path = invoker.final_apk_path + _final_rtxt_path = "${_final_apk_path}.R.txt" + } + + _res_size_info_path = "$target_out_dir/$target_name.ap_.info" + if (!_is_bundle_module) { + _final_apk_path_no_ext_list = + process_file_template([ _final_apk_path ], + "{{source_dir}}/{{source_name_part}}") + _final_apk_path_no_ext = _final_apk_path_no_ext_list[0] + not_needed([ "_final_apk_path_no_ext" ]) + } + + # Non-base bundle modules create only proto resources. + if (!_is_bundle_module || _is_base_module) { + _arsc_resources_path = "$target_out_dir/$target_name.ap_" + } + if (_is_bundle_module) { + # Path to the intermediate proto-format resources zip file. + _proto_resources_path = "$target_out_dir/$target_name.proto.ap_" + } else { + # resource_sizes.py needs to be able to find the unpacked resources.arsc + # file based on apk name to compute normatlized size. + _resource_sizes_arsc_path = + "$root_out_dir/arsc/" + + rebase_path(_final_apk_path_no_ext, root_build_dir) + ".ap_" + } + + if (defined(invoker.version_code)) { + _version_code = invoker.version_code + } else { + _version_code = android_default_version_code + } + + if (android_override_version_code != "") { + _version_code = android_override_version_code + } + + if (defined(invoker.version_name)) { + _version_name = invoker.version_name + } else { + _version_name = android_default_version_name + } + + if (android_override_version_name != "") { + _version_name = android_override_version_name + } + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + + _srcjar_deps = [] + if (defined(invoker.srcjar_deps)) { + _srcjar_deps = invoker.srcjar_deps + } + + _android_root_manifest_deps = [] + if (defined(invoker.android_manifest_dep)) { + _android_root_manifest_deps = [ invoker.android_manifest_dep ] + } + _android_root_manifest = invoker.android_manifest + + _use_chromium_linker = + defined(invoker.use_chromium_linker) && invoker.use_chromium_linker + _use_modern_linker = + defined(invoker.use_modern_linker) && invoker.use_modern_linker + + _load_library_from_apk = + defined(invoker.load_library_from_apk) && invoker.load_library_from_apk + + not_needed([ + "_use_chromium_linker", + "_use_modern_linker", + ]) + assert(!_load_library_from_apk || _use_chromium_linker, + "load_library_from_apk requires use_chromium_linker") + + # Make sure that uncompress_shared_libraries is set to true if + # load_library_from_apk is true. + if (defined(invoker.uncompress_shared_libraries)) { + _uncompress_shared_libraries = invoker.uncompress_shared_libraries + assert(!_load_library_from_apk || _uncompress_shared_libraries) + } else { + _uncompress_shared_libraries = _load_library_from_apk + } + + # The dependency that makes the chromium linker, if any is needed. + _native_libs_deps = [] + _shared_libraries_is_valid = + defined(invoker.shared_libraries) && invoker.shared_libraries != [] + + if (_shared_libraries_is_valid) { + _native_libs_deps += invoker.shared_libraries + + # Write shared library output files of all dependencies to a file. Those + # will be the shared libraries packaged into the APK. + _shared_library_list_file = + "$target_gen_dir/${_template_name}.native_libs" + generated_file("${_template_name}__shared_library_list") { + deps = _native_libs_deps + outputs = [ _shared_library_list_file ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__shared_library_list") { + } + } + + _secondary_abi_native_libs_deps = [] + + if (defined(invoker.secondary_abi_shared_libraries) && + invoker.secondary_abi_shared_libraries != []) { + _secondary_abi_native_libs_deps = invoker.secondary_abi_shared_libraries + + # Write shared library output files of all dependencies to a file. Those + # will be the shared libraries packaged into the APK. + _secondary_abi_shared_library_list_file = + "$target_gen_dir/${_template_name}.secondary_abi_native_libs" + generated_file("${_template_name}__secondary_abi_shared_library_list") { + deps = _secondary_abi_native_libs_deps + outputs = [ _secondary_abi_shared_library_list_file ] + data_keys = [ "shared_libraries" ] + walk_keys = [ "shared_libraries_barrier" ] + rebase = root_build_dir + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__secondary_abi_shared_library_list") { + } + } + + _rebased_build_config = rebase_path(_build_config, root_build_dir) + assert(_rebased_build_config != "") # Mark as used. + + _generate_buildconfig_java = !defined(invoker.apk_under_test) + if (defined(invoker.generate_buildconfig_java)) { + _generate_buildconfig_java = invoker.generate_buildconfig_java + } + + _generate_productconfig_java = defined(invoker.product_config_java_packages) + + # JNI generation usually goes hand-in-hand with buildconfig generation. + _generate_final_jni = _generate_buildconfig_java + if (defined(invoker.generate_final_jni)) { + _generate_final_jni = invoker.generate_final_jni + } + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + if (!_is_bundle_module && _proguard_enabled) { + _proguard_mapping_path = "$_final_apk_path.mapping" + } + + # TODO(http://crbug.com/901465): Move shared Java code to static libraries + # when !_proguard_enabled too. + _is_static_library_provider = + defined(invoker.static_library_dependent_targets) && _proguard_enabled + if (_is_static_library_provider) { + _static_library_sync_dex_path = "$_base_path.synchronized.r8dex.jar" + _resource_ids_provider_deps = [] + foreach(_target, invoker.static_library_dependent_targets) { + if (_target.is_resource_ids_provider) { + assert(_resource_ids_provider_deps == [], + "Can only have 1 resource_ids_provider_dep") + _resource_ids_provider_deps += [ _target.name ] + } + } + _resource_ids_provider_dep = _resource_ids_provider_deps[0] + } else if (defined(invoker.resource_ids_provider_dep)) { + _resource_ids_provider_dep = invoker.resource_ids_provider_dep + } + + if (_is_static_library_provider) { + _shared_resources_allowlist_target = _resource_ids_provider_dep + } else if (defined(invoker.shared_resources_allowlist_target)) { + _shared_resources_allowlist_target = + invoker.shared_resources_allowlist_target + } + + _uses_static_library = defined(invoker.static_library_provider) + _uses_static_library_synchronized_proguard = + defined(invoker.static_library_synchronized_proguard) && + invoker.static_library_synchronized_proguard + + if (_uses_static_library_synchronized_proguard) { + assert(_uses_static_library) + + # These will be provided by the static library APK. + _generate_buildconfig_java = false + _generate_final_jni = false + } + + # TODO(crbug.com/864142): Allow incremental installs of bundle modules. + _incremental_apk = !_is_bundle_module && + !(defined(invoker.never_incremental) && + invoker.never_incremental) && incremental_install + if (_incremental_apk) { + _target_dir_name = get_label_info(target_name, "dir") + _incremental_install_json_path = "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.incremental.json" + _incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" + } + + if (!_incremental_apk) { + # Bundle modules don't build the dex here, but need to write this path + # to their .build_config.json file. + if (_proguard_enabled) { + _final_dex_path = "$_base_path.r8dex.jar" + } else { + _final_dex_path = "$_base_path.mergeddex.jar" + } + } + + _android_manifest = + "$target_gen_dir/${_template_name}_manifest/AndroidManifest.xml" + _merge_manifest_target = "${_template_name}__merge_manifests" + merge_manifests(_merge_manifest_target) { + forward_variables_from(invoker, + [ + "manifest_package", + "max_sdk_version", + ]) + input_manifest = _android_root_manifest + output_manifest = _android_manifest + build_config = _build_config + min_sdk_version = _min_sdk_version + target_sdk_version = _target_sdk_version + deps = _android_root_manifest_deps + [ ":$_build_config_target" ] + } + + _final_deps = [] + + _enable_main_dex_list = _enable_multidex && _min_sdk_version < 21 + if (_enable_main_dex_list) { + _generated_proguard_main_dex_config = + "$_base_path.resources.main-dex-proguard.txt" + } + _generated_proguard_config = "$_base_path.resources.proguard.txt" + + if (_generate_buildconfig_java && + defined(invoker.product_version_resources_dep)) { + # Needs to be added as a .build_config.json dep to pick up resources. + _deps += [ invoker.product_version_resources_dep ] + } + + if (defined(invoker.alternative_android_sdk_dep)) { + _android_sdk_dep = invoker.alternative_android_sdk_dep + } else { + _android_sdk_dep = "//third_party/android_sdk:android_sdk_java" + } + + if (defined(_shared_resources_allowlist_target)) { + _allowlist_gen_dir = + get_label_info(_shared_resources_allowlist_target, "target_gen_dir") + _allowlist_target_name = + get_label_info(_shared_resources_allowlist_target, "name") + _allowlist_r_txt_path = + "${_allowlist_gen_dir}/${_allowlist_target_name}" + + "__compile_resources_R.txt" + _allowlist_deps = + "${_shared_resources_allowlist_target}__compile_resources" + } + + _compile_resources_target = "${_template_name}__compile_resources" + _compile_resources_rtxt_out = + "${target_gen_dir}/${_compile_resources_target}_R.txt" + _compile_resources_emit_ids_out = + "${target_gen_dir}/${_compile_resources_target}.resource_ids" + compile_resources(_compile_resources_target) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "app_as_shared_lib", + "enforce_resource_overlays_in_tests", + "expected_android_manifest", + "expected_android_manifest_base", + "extra_verification_manifest", + "extra_verification_manifest_dep", + "manifest_package", + "max_sdk_version", + "no_xml_namespaces", + "package_id", + "package_name", + "png_to_webp", + "r_java_root_package_name", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_values_filter_rules", + "shared_resources", + "shared_resources_allowlist_locales", + "uses_split", + ]) + android_manifest = _android_manifest + android_manifest_dep = ":$_merge_manifest_target" + version_code = _version_code + version_name = _version_name + min_sdk_version = _min_sdk_version + target_sdk_version = _target_sdk_version + + if (defined(expected_android_manifest)) { + top_target_name = _template_name + } + + if (defined(_resource_ids_provider_dep)) { + resource_ids_provider_dep = _resource_ids_provider_dep + } + + if (defined(invoker.post_process_package_resources_script)) { + post_process_script = invoker.post_process_package_resources_script + } + r_text_out_path = _compile_resources_rtxt_out + emit_ids_out_path = _compile_resources_emit_ids_out + size_info_path = _res_size_info_path + proguard_file = _generated_proguard_config + if (_enable_main_dex_list) { + proguard_file_main_dex = _generated_proguard_main_dex_config + } + + build_config = _build_config + build_config_dep = ":$_build_config_target" + android_sdk_dep = _android_sdk_dep + deps = _deps + + # The static library uses the R.txt files generated by the + # static_library_dependent_targets when generating the final R.java file. + if (_is_static_library_provider) { + foreach(_dep, invoker.static_library_dependent_targets) { + deps += [ "${_dep.name}__compile_resources" ] + } + } + + if (defined(invoker.apk_under_test)) { + # Set the arsc package name to match the apk_under_test package name + # So that test resources can references under_test resources via + # @type/name syntax. + r_java_root_package_name = "test" + arsc_package_name = + "@FileArg($_rebased_build_config:deps_info:arsc_package_name)" + + # Passing in the --emit-ids mapping will cause aapt2 to assign resources + # IDs that do not conflict with those from apk_under_test. + assert(!defined(resource_ids_provider_dep)) + resource_ids_provider_dep = invoker.apk_under_test + + include_resource = + get_label_info(invoker.apk_under_test, "target_out_dir") + "/" + + get_label_info(invoker.apk_under_test, "name") + ".ap_" + _link_against = invoker.apk_under_test + } + + if (_is_bundle_module) { + is_bundle_module = true + proto_output = _proto_resources_path + + if (defined(invoker.base_module_target)) { + include_resource = + get_label_info(invoker.base_module_target, "target_out_dir") + + "/" + get_label_info(invoker.base_module_target, "name") + ".ap_" + _link_against = invoker.base_module_target + } + } + + if (defined(_link_against)) { + deps += [ "${_link_against}__compile_resources" ] + include_resource = get_label_info(_link_against, "target_out_dir") + + "/" + get_label_info(_link_against, "name") + ".ap_" + } + + # Bundle modules have to reference resources from the base module. + if (!_is_bundle_module || _is_base_module) { + arsc_output = _arsc_resources_path + } + + if (defined(_shared_resources_allowlist_target)) { + # Used to ensure that the WebView resources are properly shared + # (i.e. are non-final and with package ID 0). + shared_resources_allowlist = _allowlist_r_txt_path + deps += [ _allowlist_deps ] + } + } + _srcjar_deps += [ ":$_compile_resources_target" ] + + # We don't ship apks anymore, only optimize bundle builds + if (_is_bundle_module) { + _short_resource_paths = + defined(invoker.short_resource_paths) && + invoker.short_resource_paths && enable_arsc_obfuscation + _strip_resource_names = + defined(invoker.strip_resource_names) && + invoker.strip_resource_names && enable_arsc_obfuscation + _strip_unused_resources = defined(invoker.strip_unused_resources) && + invoker.strip_unused_resources + _optimize_resources = _strip_resource_names || _short_resource_paths || + _strip_unused_resources + } + + if (_is_bundle_module && _optimize_resources) { + _optimized_proto_resources_path = + "$target_out_dir/$target_name.optimized.proto.ap_" + if (_short_resource_paths) { + _resources_path_map_out_path = + "${target_gen_dir}/${_template_name}_resources_path_map.txt" + } + _optimize_resources_target = "${_template_name}__optimize_resources" + optimize_resources(_optimize_resources_target) { + deps = _deps + [ ":$_compile_resources_target" ] + short_resource_paths = _short_resource_paths + strip_resource_names = _strip_resource_names + if (_short_resource_paths) { + resources_path_map_out_path = _resources_path_map_out_path + } + r_text_path = _compile_resources_rtxt_out + proto_input_path = _proto_resources_path + optimized_proto_output = _optimized_proto_resources_path + if (_strip_unused_resources) { + # These need to be kept in sync with the target names + output paths + # in the android_app_bundle template. + _unused_resources_target = "${_template_name}__unused_resources" + _unused_resources_config_path = + "$target_gen_dir/${_template_name}_unused_resources.config" + resources_config_paths = [ _unused_resources_config_path ] + deps += [ ":$_unused_resources_target" ] + } else { + resources_config_paths = [] + } + if (defined(invoker.resources_config_paths)) { + resources_config_paths += invoker.resources_config_paths + } + } + } + + if (!_is_bundle_module) { + # Output the R.txt file to a more easily discoverable location for + # archiving. This is necessary when stripping resource names so that we + # have an archive of resource names to ids for shipped apks (for + # debugging purposes). We copy the file rather than change the location + # of the original because other targets rely on the location of the R.txt + # file. + _copy_rtxt_target = "${_template_name}__copy_rtxt" + copy(_copy_rtxt_target) { + deps = [ ":$_compile_resources_target" ] + sources = [ _compile_resources_rtxt_out ] + outputs = [ _final_rtxt_path ] + } + _final_deps += [ ":$_copy_rtxt_target" ] + } + + if (defined(_resource_sizes_arsc_path)) { + _copy_arsc_target = "${_template_name}__copy_arsc" + copy(_copy_arsc_target) { + deps = [ ":$_compile_resources_target" ] + + # resource_sizes.py doesn't care if it gets the optimized .arsc. + sources = [ _arsc_resources_path ] + outputs = [ _resource_sizes_arsc_path ] + } + _final_deps += [ ":$_copy_arsc_target" ] + } + + _generate_native_libraries_java = + (!_is_bundle_module || _is_base_module) && + (_native_libs_deps != [] || _secondary_abi_native_libs_deps != []) && + !_uses_static_library_synchronized_proguard + if (_generate_native_libraries_java) { + write_native_libraries_java("${_template_name}__native_libraries") { + forward_variables_from(invoker, [ "main_component_library" ]) + + # Do not add a dep on the generated_file target in order to avoid having + # to build the native libraries before this target. The dependency is + # instead captured via a depfile. + if (_native_libs_deps != []) { + native_libraries_list_file = _shared_library_list_file + } else { + native_libraries_list_file = _secondary_abi_shared_library_list_file + } + enable_chromium_linker = _use_chromium_linker + load_library_from_apk = _load_library_from_apk + use_modern_linker = _use_modern_linker + use_final_fields = true + } + _srcjar_deps += [ ":${_template_name}__native_libraries" ] + } + + _loadable_modules = [] + if (defined(invoker.loadable_modules)) { + _loadable_modules = invoker.loadable_modules + } + + if (_native_libs_deps != []) { + _loadable_modules += _sanitizer_runtimes + } + + if (_generate_buildconfig_java) { + generate_build_config_srcjar("${_template_name}__build_config_srcjar") { + forward_variables_from(invoker, + [ + "min_sdk_version", + "isolated_splits_enabled", + ]) + _bundles_supported = _is_bundle_module || _is_static_library_provider + if (defined(invoker.bundles_supported)) { + _bundles_supported = invoker.bundles_supported + } + bundles_supported = _bundles_supported + use_final_fields = true + enable_multidex = _enable_multidex + is_incremental_install = _incremental_apk + if (defined(invoker.product_version_resources_dep)) { + resources_version_variable = + "org.chromium.base.R.string.product_version" + } + deps = [ ":$_build_config_target" ] + } + _srcjar_deps += [ ":${_template_name}__build_config_srcjar" ] + } + + if (_generate_productconfig_java) { + foreach(_package, invoker.product_config_java_packages) { + _locale_target_name = + "${_template_name}_${_package}__product_config_srcjar" + generate_product_config_srcjar("$_locale_target_name") { + forward_variables_from(invoker, [ "is_bundle_module" ]) + build_config = _build_config + java_package = _package + use_chromium_linker = _use_chromium_linker + use_modern_linker = _use_modern_linker + deps = [ ":$_build_config_target" ] + } + _srcjar_deps += [ ":$_locale_target_name" ] + } + } + + if (_generate_final_jni) { + generate_jni_registration("${_template_name}__final_jni") { + forward_variables_from(invoker, + [ + "enable_native_mocks", + "require_native_mocks", + ]) + if (defined(invoker.bundle_target)) { + targets = [ invoker.bundle_target ] + } else { + targets = [ ":$_template_name" ] + } + if (_is_static_library_provider) { + foreach(_target, invoker.static_library_dependent_targets) { + targets += [ _target.name ] + } + } + if (defined(invoker.jni_registration_header)) { + header_output = invoker.jni_registration_header + } + if (defined(invoker.jni_sources_exclusions)) { + sources_exclusions = invoker.jni_sources_exclusions + } + } + _srcjar_deps += [ ":${_template_name}__final_jni" ] + } else { + not_needed(invoker, + [ + "enable_native_mocks", + "jni_registration_header", + ]) + } + + _java_target = "${_template_name}__java" + + java_library_impl(_java_target) { + forward_variables_from(invoker, + [ + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "apk_under_test", + "base_module_target", + "chromium_code", + "jacoco_never_instrument", + "jar_excluded_patterns", + "javac_args", + "native_lib_placeholders", + "processor_args_javac", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + "sources", + "static_library_dependent_targets", + "use_classic_desugar", + "library_always_compress", + "library_renames", + ]) + deps = _deps + if (_uses_static_library_synchronized_proguard) { + if (!defined(jar_excluded_patterns)) { + jar_excluded_patterns = [] + } + + # The static library will provide all R.java files, but we still need to + # make the base module R.java files available at compile time since DFM + # R.java classes extend base module classes. + jar_excluded_patterns += [ + "*/R.class", + "*/R\$*.class", + ] + } + if (_is_bundle_module) { + type = "android_app_bundle_module" + res_size_info_path = _res_size_info_path + is_base_module = _is_base_module + forward_variables_from(invoker, + [ + "version_code", + "version_name", + ]) + } else { + type = "android_apk" + } + r_text_path = _compile_resources_rtxt_out + main_target_name = _template_name + supports_android = true + requires_android = true + srcjar_deps = _srcjar_deps + merged_android_manifest = _android_manifest + if (defined(_final_dex_path)) { + final_dex_path = _final_dex_path + } + + if (_is_bundle_module) { + proto_resources_path = _proto_resources_path + if (_optimize_resources) { + proto_resources_path = _optimized_proto_resources_path + if (_short_resource_paths) { + module_pathmap_path = _resources_path_map_out_path + } + } + } else { + apk_path = _final_apk_path + if (_incremental_apk) { + incremental_apk_path = _incremental_apk_path + incremental_install_json_path = _incremental_install_json_path + } + } + + proguard_enabled = _proguard_enabled + if (_proguard_enabled) { + proguard_configs = [ _generated_proguard_config ] + if (defined(invoker.proguard_configs)) { + proguard_configs += invoker.proguard_configs + } + if (!enable_java_asserts && (!defined(testonly) || !testonly) && + # Injected JaCoCo code causes -checkdiscards to fail. + !use_jacoco_coverage) { + proguard_configs += [ "//build/android/dcheck_is_off.flags" ] + } + if (!_is_bundle_module) { + proguard_mapping_path = _proguard_mapping_path + } + } + + # Do not add a dep on the generated_file target in order to avoid having + # to build the native libraries before this target. The dependency is + # instead captured via a depfile. + if (_native_libs_deps != []) { + shared_libraries_runtime_deps_file = _shared_library_list_file + } + if (defined(_secondary_abi_shared_library_list_file)) { + secondary_abi_shared_libraries_runtime_deps_file = + _secondary_abi_shared_library_list_file + } + + loadable_modules = _loadable_modules + + uncompress_shared_libraries = _uncompress_shared_libraries + + if (defined(_allowlist_r_txt_path) && _is_bundle_module) { + # Used to write the file path to the target's .build_config.json only. + base_allowlist_rtxt_path = _allowlist_r_txt_path + } + } + + # TODO(cjhopman): This is only ever needed to calculate the list of tests to + # run. See build/android/pylib/instrumentation/test_jar.py. We should be + # able to just do that calculation at build time instead. + if (defined(invoker.dist_ijar_path)) { + _dist_ijar_path = invoker.dist_ijar_path + dist_jar("${_template_name}_dist_ijar") { + override_build_config = _build_config + output = _dist_ijar_path + data = [ _dist_ijar_path ] + use_interface_jars = true + deps = [ + ":$_build_config_target", + ":$_java_target", + ] + } + } + + if (_uses_static_library_synchronized_proguard) { + _final_dex_target_dep = "${invoker.static_library_provider}__dexsplitter" + } else if (_is_bundle_module && _proguard_enabled) { + _final_deps += [ ":$_java_target" ] + } else if (_incremental_apk) { + if (defined(invoker.enable_proguard_checks)) { + not_needed(invoker, [ "enable_proguard_checks" ]) + } + if (defined(invoker.disable_r8_outlining)) { + not_needed(invoker, [ "disable_r8_outlining" ]) + } + if (defined(invoker.dexlayout_profile)) { + not_needed(invoker, [ "dexlayout_profile" ]) + } + } else { + # Dex generation for app bundle modules with proguarding enabled takes + # place later due to synchronized proguarding. + _final_dex_target_name = "${_template_name}__final_dex" + dex(_final_dex_target_name) { + forward_variables_from(invoker, + [ + "disable_r8_outlining", + "dexlayout_profile", + "enable_proguard_checks", + "proguard_enable_obfuscation", + ]) + min_sdk_version = _min_sdk_version + proguard_enabled = _proguard_enabled + build_config = _build_config + deps = [ + ":$_build_config_target", + ":$_java_target", + ] + if (_proguard_enabled) { + deps += _deps + [ ":$_compile_resources_target" ] + proguard_mapping_path = _proguard_mapping_path + proguard_sourcefile_suffix = "$android_channel-$_version_code" + has_apk_under_test = defined(invoker.apk_under_test) + } else if (_min_sdk_version >= default_min_sdk_version) { + # Enable dex merging only when min_sdk_version is >= what the library + # .dex files were created with. + input_dex_filearg = + "@FileArg(${_rebased_build_config}:final_dex:all_dex_files)" + } else { + input_classes_filearg = + "@FileArg($_rebased_build_config:deps_info:device_classpath)" + } + + if (_is_static_library_provider) { + # The list of input jars is already recorded in the .build_config.json, but + # we need to explicitly add the java deps here to ensure they're + # available to be used as inputs to the dex step. + foreach(_dep, invoker.static_library_dependent_targets) { + _target_label = get_label_info(_dep.name, "label_no_toolchain") + deps += [ "${_target_label}__java" ] + } + output = _static_library_sync_dex_path + is_static_library = true + } else { + output = _final_dex_path + } + enable_multidex = _enable_multidex + + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this may use jar files + # rather than dex files. + ignore_desugar_missing_deps = true + + if (_enable_main_dex_list) { + extra_main_dex_proguard_config = _generated_proguard_main_dex_config + deps += [ ":$_compile_resources_target" ] + } + } + + _final_dex_target_dep = ":$_final_dex_target_name" + + # For static libraries, a single Proguard run is performed that includes + # code from the static library APK and the APKs that use the static + # library (done via. classpath merging in write_build_config.py). + # This dexsplitter target splits the synchronized dex output into dex + # files for each APK/Bundle. In the Bundle case, another dexsplitter step + # is later performed to split the dex further for each feature module. + if (_is_static_library_provider && _proguard_enabled) { + _static_library_modules = [] + foreach(_target, invoker.static_library_dependent_targets) { + _apk_as_module = _target.name + _module_config_target = "${_apk_as_module}$build_config_target_suffix" + _module_gen_dir = get_label_info(_apk_as_module, "target_gen_dir") + _module_name = get_label_info(_apk_as_module, "name") + _module_config = "$_module_gen_dir/$_module_name.build_config.json" + _static_library_modules += [ + { + name = _module_name + build_config = _module_config + build_config_target = _module_config_target + }, + ] + } + + _static_library_dexsplitter_target = "${_template_name}__dexsplitter" + dexsplitter(_static_library_dexsplitter_target) { + input_dex_zip = _static_library_sync_dex_path + proguard_mapping = _proguard_mapping_path + deps = [ + ":$_build_config_target", + "$_final_dex_target_dep", + ] + all_modules = [ + { + name = "base" + build_config = _build_config + build_config_target = ":$_build_config_target" + }, + ] + _static_library_modules + feature_jars_args = [ + "--feature-jars", + "@FileArg($_rebased_build_config:deps_info:" + + "static_library_dependent_classpath_configs:" + + "$_rebased_build_config)", + ] + foreach(_module, _static_library_modules) { + _rebased_module_config = + rebase_path(_module.build_config, root_build_dir) + feature_jars_args += [ + "--feature-jars", + "@FileArg($_rebased_build_config:deps_info:" + + "static_library_dependent_classpath_configs:" + + "$_rebased_module_config)", + ] + } + } + _final_deps += [ ":$_static_library_dexsplitter_target" ] + _validate_dex_target = "${_template_name}__validate_dex" + action_with_pydeps(_validate_dex_target) { + depfile = "$target_gen_dir/$target_name.d" + script = + "//build/android/gyp/validate_static_library_dex_references.py" + inputs = [ _build_config ] + _stamp = "$target_gen_dir/$target_name.stamp" + outputs = [ _stamp ] + deps = [ + ":$_build_config_target", + ":$_static_library_dexsplitter_target", + ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--stamp", + rebase_path(_stamp, root_build_dir), + "--static-library-dex", + "@FileArg($_rebased_build_config:final_dex:path)", + ] + foreach(_module, _static_library_modules) { + inputs += [ _module.build_config ] + _rebased_config = rebase_path(_module.build_config, root_build_dir) + deps += [ _module.build_config_target ] + args += [ + "--static-library-dependent-dex", + "@FileArg($_rebased_config:final_dex:path)", + ] + } + } + + # TODO(crbug.com/1032609): Switch to using R8's support for feature + # aware ProGuard and get rid of "_validate_dex_target" or figure out + # why some classes aren't properly being kept. + # _final_deps += [ ":$_validate_dex_target" ] + _final_dex_target_dep = ":$_static_library_dexsplitter_target" + } + } + + _all_native_libs_deps = _native_libs_deps + _secondary_abi_native_libs_deps + if (_all_native_libs_deps != []) { + _native_libs_filearg_dep = ":$_build_config_target" + _all_native_libs_deps += [ _native_libs_filearg_dep ] + + if (!_is_bundle_module) { + _native_libs_filearg = + "@FileArg($_rebased_build_config:native:libraries)" + } + } + + if (_is_bundle_module) { + _final_deps += [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_compile_resources_target", + ] + _all_native_libs_deps + if (_optimize_resources) { + _final_deps += [ ":$_optimize_resources_target" ] + } + if (defined(_final_dex_target_dep)) { + not_needed([ "_final_dex_target_dep" ]) + } + } else { + # Generate size-info/*.jar.info files. + if (defined(invoker.name)) { + # Create size info files for targets that care about size + # (have proguard enabled). + _include_size_info = + defined(invoker.include_size_info) && invoker.include_size_info + if (_include_size_info || _proguard_enabled) { + _size_info_target = "${target_name}__size_info" + create_size_info_files(_size_info_target) { + name = "${invoker.name}.apk" + build_config = _build_config + res_size_info_path = _res_size_info_path + deps = _deps + [ + ":$_build_config_target", + ":$_compile_resources_target", + ":$_java_target", + ] + } + _final_deps += [ ":$_size_info_target" ] + } else { + not_needed(invoker, [ "name" ]) + } + } + + _keystore_path = android_keystore_path + _keystore_name = android_keystore_name + _keystore_password = android_keystore_password + + if (defined(invoker.keystore_path)) { + _keystore_path = invoker.keystore_path + _keystore_name = invoker.keystore_name + _keystore_password = invoker.keystore_password + } + + if (_incremental_apk) { + _incremental_compiled_resources_path = "${_base_path}_incremental.ap_" + _incremental_compile_resources_target_name = + "${target_name}__compile_incremental_resources" + + action_with_pydeps(_incremental_compile_resources_target_name) { + deps = [ + ":$_build_config_target", + ":$_compile_resources_target", + ":$_merge_manifest_target", + ] + script = + "//build/android/incremental_install/generate_android_manifest.py" + inputs = [ + _android_manifest, + _build_config, + _arsc_resources_path, + ] + outputs = [ _incremental_compiled_resources_path ] + + args = [ + "--disable-isolated-processes", + "--src-manifest", + rebase_path(_android_manifest, root_build_dir), + "--in-apk", + rebase_path(_arsc_resources_path, root_build_dir), + "--out-apk", + rebase_path(_incremental_compiled_resources_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--android-sdk-jars=@FileArg($_rebased_build_config:android:sdk_jars)", + ] + } + } + + _create_apk_target = "${_template_name}__create" + _final_deps += [ ":$_create_apk_target" ] + package_apk("$_create_apk_target") { + forward_variables_from(invoker, + [ + "expected_libs_and_assets", + "expected_libs_and_assets_base", + "native_lib_placeholders", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + "uncompress_dex", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + ]) + + if (defined(expected_libs_and_assets)) { + build_config_dep = ":$_build_config_target" + top_target_name = _template_name + } + + build_config = _build_config + keystore_name = _keystore_name + keystore_path = _keystore_path + keystore_password = _keystore_password + min_sdk_version = _min_sdk_version + uncompress_shared_libraries = _uncompress_shared_libraries + + deps = _deps + [ ":$_build_config_target" ] + + if ((!_proguard_enabled || _incremental_apk) && + enable_jdk_library_desugaring) { + _all_jdk_libs = "//build/android:all_jdk_libs" + deps += [ _all_jdk_libs ] + jdk_libs_dex = get_label_info(_all_jdk_libs, "target_out_dir") + + "/all_jdk_libs.l8.dex" + } + + if (_incremental_apk) { + _dex_target = "//build/android/incremental_install:apk_dex" + + deps += [ + ":${_incremental_compile_resources_target_name}", + _dex_target, + ] + + dex_path = get_label_info(_dex_target, "target_out_dir") + "/apk.dex" + + # All native libraries are side-loaded, so use a placeholder to force + # the proper bitness for the app. + _has_native_libs = + defined(_native_libs_filearg) || _loadable_modules != [] + if (_has_native_libs && !defined(native_lib_placeholders)) { + native_lib_placeholders = [ "libfix.crbug.384638.so" ] + } + + packaged_resources_path = _incremental_compiled_resources_path + output_apk_path = _incremental_apk_path + } else { + loadable_modules = _loadable_modules + deps += _all_native_libs_deps + [ + ":$_merge_manifest_target", + ":$_compile_resources_target", + ] + + if (defined(_final_dex_path)) { + dex_path = _final_dex_path + deps += [ _final_dex_target_dep ] + } + + packaged_resources_path = _arsc_resources_path + + if (defined(_native_libs_filearg)) { + native_libs_filearg = _native_libs_filearg + secondary_abi_native_libs_filearg = "@FileArg($_rebased_build_config:native:secondary_abi_libraries)" + } + output_apk_path = _final_apk_path + } + } + } + + if (_incremental_apk) { + _write_installer_json_rule_name = "${_template_name}__incremental_json" + action_with_pydeps(_write_installer_json_rule_name) { + script = "//build/android/incremental_install/write_installer_json.py" + deps = [ ":$_build_config_target" ] + _all_native_libs_deps + + data = [ _incremental_install_json_path ] + inputs = [ _build_config ] + outputs = [ _incremental_install_json_path ] + + _rebased_incremental_apk_path = + rebase_path(_incremental_apk_path, root_build_dir) + _rebased_incremental_install_json_path = + rebase_path(_incremental_install_json_path, root_build_dir) + args = [ + "--apk-path=$_rebased_incremental_apk_path", + "--output-path=$_rebased_incremental_install_json_path", + "--dex-file=@FileArg($_rebased_build_config:final_dex:all_dex_files)", + ] + if (_proguard_enabled) { + args += [ "--show-proguard-warning" ] + } + if (defined(_native_libs_filearg)) { + args += [ "--native-libs=$_native_libs_filearg" ] + deps += [ _native_libs_filearg_dep ] + } + if (_loadable_modules != []) { + _rebased_loadable_modules = + rebase_path(_loadable_modules, root_build_dir) + args += [ "--native-libs=$_rebased_loadable_modules" ] + } + } + _final_deps += [ + ":$_java_target", + ":$_write_installer_json_rule_name", + ] + } + + # Generate apk operation related script. + if (!_is_bundle_module && + (!defined(invoker.create_apk_script) || invoker.create_apk_script)) { + if (_uses_static_library) { + _install_artifacts_target = "${target_name}__install_artifacts" + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file(_install_artifacts_target) { + output_conversion = "json" + deps = [ invoker.static_library_provider ] + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + rebase = root_build_dir + } + } + _apk_operations_target_name = "${target_name}__apk_operations" + action_with_pydeps(_apk_operations_target_name) { + _generated_script = "$root_build_dir/bin/${invoker.target_name}" + script = "//build/android/gyp/create_apk_operations_script.py" + outputs = [ _generated_script ] + args = [ + "--script-output-path", + rebase_path(_generated_script, root_build_dir), + "--target-cpu=$target_cpu", + ] + if (defined(invoker.command_line_flags_file)) { + args += [ + "--command-line-flags-file", + invoker.command_line_flags_file, + ] + } + if (_incremental_apk) { + args += [ + "--incremental-install-json-path", + rebase_path(_incremental_install_json_path, root_build_dir), + ] + } else { + args += [ + "--apk-path", + rebase_path(_final_apk_path, root_build_dir), + ] + } + if (_uses_static_library) { + deps = [ ":$_install_artifacts_target" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _static_library_apk_path = + "@FileArg($_rebased_install_artifacts_json[])" + args += [ + "--additional-apk", + _static_library_apk_path, + ] + } + data = [] + data_deps = [ + "//build/android:apk_operations_py", + "//build/android:stack_tools", + ] + + if (_proguard_enabled && !_incremental_apk) { + # Required by logcat command. + data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] + data += [ "$_final_apk_path.mapping" ] + args += [ + "--proguard-mapping-path", + rebase_path("$_final_apk_path.mapping", root_build_dir), + ] + } + } + _final_deps += [ ":$_apk_operations_target_name" ] + } + + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + if (_enable_lint) { + android_lint("${target_name}__lint") { + forward_variables_from(invoker, + [ + "lint_baseline_file", + "lint_suppressions_file", + "min_sdk_version", + ]) + build_config = _build_config + build_config_dep = ":$_build_config_target" + deps = [ ":$_java_target" ] + if (defined(invoker.lint_suppressions_dep)) { + deps += [ invoker.lint_suppressions_dep ] + } + if (defined(invoker.lint_min_sdk_version)) { + min_sdk_version = invoker.lint_min_sdk_version + } + } + } else { + not_needed(invoker, + [ + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + ]) + } + + group(target_name) { + forward_variables_from(invoker, + [ + "assert_no_deps", + "data", + "data_deps", + "metadata", + ]) + + # Generate apk related operations at runtime. + public_deps = _final_deps + + if (!defined(data_deps)) { + data_deps = [] + } + + # Include unstripped native libraries so tests can symbolize stacks. + data_deps += _all_native_libs_deps + + if (_enable_lint) { + data_deps += [ ":${target_name}__lint" ] + } + + if (_uses_static_library) { + data_deps += [ invoker.static_library_provider ] + } + } + } + + # Declare an Android APK target + # + # This target creates an Android APK containing java code, resources, assets, + # and (possibly) native libraries. + # + # Supports all variables of android_apk_or_module(), plus: + # apk_name: Name for final apk. + # final_apk_path: (Optional) path to output APK. + # + # Example + # android_apk("foo_apk") { + # android_manifest = "AndroidManifest.xml" + # sources = [ + # "android/org/chromium/foo/FooApplication.java", + # "android/org/chromium/foo/FooActivity.java", + # ] + # deps = [ + # ":foo_support_java" + # ":foo_resources" + # ] + # srcjar_deps = [ + # ":foo_generated_enum" + # ] + # shared_libraries = [ + # ":my_shared_lib", + # ] + # } + template("android_apk") { + # TODO(crbug.com/1042017): Remove. + not_needed(invoker, [ "no_build_hooks" ]) + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "apk_under_test", + "app_as_shared_lib", + "assert_no_deps", + "bundles_supported", + "chromium_code", + "command_line_flags_file", + "create_apk_script", + "data", + "data_deps", + "deps", + "dexlayout_profile", + "disable_r8_outlining", + "dist_ijar_path", + "enable_lint", + "enable_multidex", + "enable_native_mocks", + "enable_proguard_checks", + "enforce_resource_overlays_in_tests", + "expected_android_manifest", + "expected_android_manifest_base", + "expected_libs_and_assets", + "expected_libs_and_assets_base", + "generate_buildconfig_java", + "generate_final_jni", + "include_size_info", + "input_jars_paths", + "use_modern_linker", + "jacoco_never_instrument", + "javac_args", + "jni_registration_header", + "jni_sources_exclusions", + "keystore_name", + "keystore_password", + "keystore_path", + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + "load_library_from_apk", + "loadable_modules", + "manifest_package", + "max_sdk_version", + "product_config_java_packages", + "main_component_library", + "min_sdk_version", + "native_lib_placeholders", + "never_incremental", + "no_xml_namespaces", + "png_to_webp", + "post_process_package_resources_script", + "processor_args_javac", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "r_java_root_package_name", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_ids_provider_dep", + "resource_values_filter_rules", + "require_native_mocks", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "shared_libraries", + "shared_resources", + "shared_resources_allowlist_locales", + "shared_resources_allowlist_target", + "sources", + "srcjar_deps", + "static_library_dependent_targets", + "static_library_provider", + "static_library_synchronized_proguard", + "target_sdk_version", + "testonly", + "uncompress_dex", + "uncompress_shared_libraries", + "use_classic_desugar", + "library_always_compress", + "library_renames", + "use_chromium_linker", + "version_code", + "version_name", + "visibility", + ]) + is_bundle_module = false + name = invoker.apk_name + if (defined(invoker.final_apk_path)) { + final_apk_path = invoker.final_apk_path + } else { + final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk" + } + metadata = { + install_artifacts = [ final_apk_path ] + } + if (defined(invoker.static_library_provider)) { + metadata.install_artifacts_barrier = [] + } + } + } + + # Declare an Android app bundle module target. + # + # The module can be used for an android_apk_or_module(). + # + # Supports all variables of android_library(), plus: + # module_name: Name of the module. + # is_base_module: If defined and true, indicates that this is the bundle's + # base module (optional). + # base_module_target: Base module target of the bundle this module will be + # added to (optional). Can only be specified for non-base modules. + # bundle_target: Bundle target that this module belongs to (optional). + # Can only be specified for base modules. + template("android_app_bundle_module") { + _is_base_module = defined(invoker.is_base_module) && invoker.is_base_module + + if (_is_base_module) { + assert(!defined(invoker.base_module_target)) + } else { + assert(!defined(invoker.app_as_shared_lib)) + assert(!defined(invoker.shared_resources)) + assert(!defined(invoker.shared_resources_allowlist_target)) + assert(!defined(invoker.shared_resources_allowlist_locales)) + assert(defined(invoker.base_module_target)) + assert(!defined(invoker.bundle_target)) + } + + # TODO(tiborg): We have several flags that are necessary for workarounds + # that come from the fact that the resources get compiled in the bundle + # module target, but bundle modules have to have certain flags in + # common or bundle modules have to know information about the base module. + # Those flags include version_code, version_name, and base_module_target. + # It would be better to move the resource compile target into the bundle + # target. Doing so would keep the bundle modules independent from the bundle + # and potentially reuse the same bundle modules for multiple bundles. + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_allowlist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "annotation_processor_deps", + "app_as_shared_lib", + "assert_no_deps", + "base_module_target", + "bundle_target", + "chromium_code", + "data", + "data_deps", + "deps", + "enable_multidex", + "expected_android_manifest", + "expected_android_manifest_base", + "extra_verification_manifest", + "extra_verification_manifest_dep", + "generate_buildconfig_java", + "generate_final_jni", + "input_jars_paths", + "isolated_splits_enabled", + "is_base_module", + "jacoco_never_instrument", + "jar_excluded_patterns", + "javac_args", + "jni_registration_header", + "jni_sources_exclusions", + "load_library_from_apk", + "loadable_modules", + "product_config_java_packages", + "manifest_package", + "max_sdk_version", + "min_sdk_version", + "native_lib_placeholders", + "no_xml_namespaces", + "package_id", + "package_name", + "png_to_webp", + "processor_args_javac", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_enable_obfuscation", + "resource_exclusion_exceptions", + "resource_exclusion_regex", + "resource_ids_provider_dep", + "resource_values_filter_rules", + "resources_config_paths", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "shared_libraries", + "shared_resources", + "shared_resources_allowlist_locales", + "shared_resources_allowlist_target", + "short_resource_paths", + "srcjar_deps", + "static_library_provider", + "static_library_synchronized_proguard", + "strip_resource_names", + "strip_unused_resources", + "target_sdk_version", + "testonly", + "uncompress_shared_libraries", + "library_always_compress", + "library_renames", + "use_chromium_linker", + "use_modern_linker", + "uses_split", + "version_code", + "version_name", + "visibility", + ]) + is_bundle_module = true + generate_buildconfig_java = _is_base_module + } + } + + # Declare an Android instrumentation test runner. + # + # This target creates a wrapper script to run Android instrumentation tests. + # + # Arguments: + # android_test_apk: The target containing the tests. + # android_test_apk_name: The apk_name in android_test_apk + # + # The following args are optional: + # apk_under_test: The target being tested. + # additional_apks: Additional targets to install on device. + # data: List of runtime data file dependencies. + # data_deps: List of non-linked dependencies. + # deps: List of private dependencies. + # extra_args: Extra arguments set for test runner. + # ignore_all_data_deps: Don't build data_deps and additional_apks. + # modules: Extra dynamic feature modules to install for test target. Can + # only be used if |apk_under_test| is an Android app bundle. + # fake_modules: Similar to |modules| but fake installed instead. + # never_incremental: Disable incremental builds. + # proguard_enabled: Enable proguard + # public_deps: List of public dependencies + # + # Example + # instrumentation_test_runner("foo_test_for_bar") { + # android_test_apk: ":foo" + # android_test_apk_name: "Foo" + # apk_under_test: ":bar" + # } + template("instrumentation_test_runner") { + if (use_rts) { + action("${invoker.target_name}__rts_filters") { + script = "//build/add_rts_filters.py" + rts_file = "${root_build_dir}/gen/rts/${invoker.target_name}.filter" + args = [ rebase_path(rts_file, root_build_dir) ] + outputs = [ rts_file ] + } + } + test_runner_script(target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "additional_locales", + "apk_under_test", + "data", + "data_deps", + "deps", + "extra_args", + "fake_modules", + "ignore_all_data_deps", + "modules", + "proguard_enabled", + "public_deps", + "use_webview_provider", + ]) + test_name = invoker.target_name + test_type = "instrumentation" + _apk_target_name = get_label_info(invoker.android_test_apk, "name") + apk_target = ":$_apk_target_name" + test_jar = "$root_build_dir/test.lib.java/" + + invoker.android_test_apk_name + ".jar" + incremental_apk = !(defined(invoker.never_incremental) && + invoker.never_incremental) && incremental_install + + public_deps = [ + ":$_apk_target_name", + + # Required by test runner to enumerate test list. + ":${_apk_target_name}_dist_ijar", + ] + if (defined(invoker.apk_under_test)) { + public_deps += [ invoker.apk_under_test ] + } + if (defined(invoker.additional_apks)) { + public_deps += invoker.additional_apks + } + if (use_rts) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${invoker.target_name}__rts_filters" ] + } + } + } + + # Declare an Android instrumentation test apk + # + # This target creates an Android instrumentation test apk. + # + # Supports all variables of android_apk(), plus: + # apk_under_test: The apk being tested (optional). + # + # Example + # android_test_apk("foo_test_apk") { + # android_manifest = "AndroidManifest.xml" + # apk_name = "FooTest" + # apk_under_test = "Foo" + # sources = [ + # "android/org/chromium/foo/FooTestCase.java", + # "android/org/chromium/foo/FooExampleTest.java", + # ] + # deps = [ + # ":foo_test_support_java" + # ] + # } + template("android_test_apk") { + android_apk(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + testonly = true + + # The size info enables the test_runner to find the source file location + # of a test after it is ran. + include_size_info = true + data = [ "$root_build_dir/size-info/${invoker.apk_name}.apk.jar.info" ] + if (defined(invoker.data)) { + data += invoker.data + } + + deps = [ "//testing/android/broker:broker_java" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + data_deps = [ + # Ensure unstripped libraries are included in runtime deps so that + # symbolization can be done. + ":${target_name}__secondary_abi_shared_library_list", + ":${target_name}__shared_library_list", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + if (defined(invoker.apk_under_test)) { + data_deps += [ invoker.apk_under_test ] + } else { + enable_native_mocks = true + } + + if (defined(invoker.apk_under_test)) { + _under_test_label = + get_label_info(invoker.apk_under_test, "label_no_toolchain") + data_deps += [ + "${_under_test_label}__secondary_abi_shared_library_list", + "${_under_test_label}__shared_library_list", + ] + } + + if (defined(invoker.additional_apks)) { + data_deps += invoker.additional_apks + } + if (defined(invoker.use_webview_provider)) { + data_deps += [ invoker.use_webview_provider ] + } + + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled && + !incremental_install) { + # When ProGuard is on, we use ProGuard to combine the under test java + # code and the test java code. This is to allow us to apply all ProGuard + # optimizations that we ship with, but not have them break tests. The + # apk under test will still have the same resources, assets, and + # manifest, all of which are the ones used in the tests. + proguard_configs = [ "//testing/android/proguard_for_test.flags" ] + if (defined(invoker.proguard_configs)) { + proguard_configs += invoker.proguard_configs + } + enable_proguard_checks = false + if (defined(invoker.final_apk_path)) { + _final_apk_path = final_apk_path + } else { + _final_apk_path = "$root_build_dir/apks/${invoker.apk_name}.apk" + } + data += [ "$_final_apk_path.mapping" ] + } + + dist_ijar_path = "$root_build_dir/test.lib.java/${invoker.apk_name}.jar" + create_apk_script = false + + forward_variables_from(invoker, + "*", + TESTONLY_AND_VISIBILITY + [ + "data", + "data_deps", + "deps", + "proguard_configs", + ]) + } + } + + # Declare an Android instrumentation test apk with wrapper script. + # + # This target creates an Android instrumentation test apk with wrapper script + # to run the test. + # + # Supports all variables of android_test_apk. + template("instrumentation_test_apk") { + assert(defined(invoker.apk_name)) + _apk_target_name = "${target_name}__test_apk" + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + android_test_apk(_apk_target_name) { + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + } + instrumentation_test_runner(target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "apk_under_test", + "data", + "data_deps", + "deps", + "extra_args", + "ignore_all_data_deps", + "modules", + "never_incremental", + "proguard_enabled", + "proguard_enable_obfuscation", + "public_deps", + "use_webview_provider", + ]) + android_test_apk = ":${_apk_target_name}" + android_test_apk_name = invoker.apk_name + } + } + + # Declare an Android gtest apk + # + # This target creates an Android apk for running gtest-based unittests. + # + # Variables + # deps: Specifies the dependencies of this target. These will be passed to + # the underlying android_apk invocation and should include the java and + # resource dependencies of the apk. + # shared_library: shared_library target that contains the unit tests. + # apk_name: The name of the produced apk. If unspecified, it uses the name + # of the shared_library target suffixed with "_apk". + # use_default_launcher: Whether the default activity (NativeUnitTestActivity) + # should be used for launching tests. + # allow_cleartext_traffic: (Optional) Whether to allow cleartext network + # requests during the test. + # use_native_activity: Test implements ANativeActivity_onCreate(). + # + # Example + # unittest_apk("foo_unittests_apk") { + # deps = [ ":foo_java", ":foo_resources" ] + # shared_library = ":foo_unittests" + # } + template("unittest_apk") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + _use_native_activity = + defined(invoker.use_native_activity) && invoker.use_native_activity + _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml" + assert(invoker.shared_library != "") + + # This trivial assert is needed in case android_manifest is defined, + # as otherwise _use_native_activity and _android_manifest would not be used. + assert(_use_native_activity != "" && _android_manifest != "") + + if (!defined(invoker.android_manifest)) { + _allow_cleartext_traffic = defined(invoker.allow_cleartext_traffic) && + invoker.allow_cleartext_traffic + jinja_template("${target_name}_manifest") { + _native_library_name = get_label_info(invoker.shared_library, "name") + if (defined(invoker.android_manifest_template)) { + input = invoker.android_manifest_template + } else { + input = + "//testing/android/native_test/java/AndroidManifest.xml.jinja2" + } + output = _android_manifest + variables = [ + "is_component_build=${is_component_build}", + "native_library_name=${_native_library_name}", + "use_native_activity=${_use_native_activity}", + "allow_cleartext_traffic=${_allow_cleartext_traffic}", + ] + } + } + + android_apk(target_name) { + data_deps = [] + forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) + testonly = true + create_apk_script = false + enable_native_mocks = true + + # TODO(crbug.com/1099849): Figure out why angle tests fail to launch + # with newer target_sdk_version. + if (!defined(invoker.target_sdk_version) && _use_native_activity) { + target_sdk_version = 24 + } + + assert(!defined(invoker.proguard_enabled) || !invoker.proguard_enabled || + invoker.proguard_configs != []) + + if (!defined(apk_name)) { + apk_name = get_label_info(invoker.shared_library, "name") + } + + if (!defined(android_manifest)) { + android_manifest_dep = ":${target_name}_manifest" + android_manifest = _android_manifest + } + + final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk" + + if (!defined(use_default_launcher) || use_default_launcher) { + deps += [ + "//base:base_java", + "//build/android/gtest_apk:native_test_instrumentation_test_runner_java", + "//testing/android/native_test:native_test_java", + ] + } + shared_libraries = [ invoker.shared_library ] + deps += [ + ":${target_name}__secondary_abi_shared_library_list", + ":${target_name}__shared_library_list", + ] + } + } + + # Generate .java files from .aidl files. + # + # This target will store the .java files in a srcjar and should be included in + # an android_library or android_apk's srcjar_deps. + # + # Variables + # sources: Paths to .aidl files to compile. + # import_include: Path to directory containing .java files imported by the + # .aidl files. + # interface_file: Preprocessed aidl file to import. + # + # Example + # android_aidl("foo_aidl") { + # import_include = "java/src" + # sources = [ + # "java/src/com/foo/bar/FooBarService.aidl", + # "java/src/com/foo/bar/FooBarServiceCallback.aidl", + # ] + # } + template("android_aidl") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + script = "//build/android/gyp/aidl.py" + depfile = "$target_gen_dir/$target_name.d" + sources = invoker.sources + + _srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + _aidl_path = "${android_sdk_build_tools}/aidl" + _framework_aidl = "$android_sdk/framework.aidl" + _imports = [ _framework_aidl ] + if (defined(invoker.interface_file)) { + assert(invoker.interface_file != "") + _imports += [ invoker.interface_file ] + } + + inputs = [ _aidl_path ] + _imports + + outputs = [ _srcjar_path ] + _rebased_imports = rebase_path(_imports, root_build_dir) + args = [ + "--aidl-path", + rebase_path(_aidl_path, root_build_dir), + "--imports=$_rebased_imports", + "--srcjar", + rebase_path(_srcjar_path, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + if (defined(invoker.import_include) && invoker.import_include != []) { + _rebased_import_paths = [] + foreach(_import_path, invoker.import_include) { + _rebased_import_path = [] + _rebased_import_path = [ rebase_path(_import_path, root_build_dir) ] + _rebased_import_paths += _rebased_import_path + } + args += [ "--includes=$_rebased_import_paths" ] + } + args += rebase_path(sources, root_build_dir) + } + } + + # Compile a protocol buffer to java. + # + # This generates java files from protocol buffers and creates an Android library + # containing the classes. + # + # Variables + # sources (required) + # Paths to .proto files to compile. + # + # proto_path (required) + # Root directory of .proto files. + # + # deps (optional) + # Additional dependencies. Passed through to both the action and the + # android_library targets. + # + # import_dirs (optional) + # A list of extra import directories to be passed to protoc compiler. + # WARNING: This circumvents proto checkdeps, and should only be used + # when needed, typically when proto files cannot cleanly import through + # absolute paths, such as for third_party or generated .proto files. + # http://crbug.com/691451 tracks fixing this. + # + # Example: + # proto_java_library("foo_proto_java") { + # proto_path = "src/foo" + # sources = [ "$proto_path/foo.proto" ] + # } + template("proto_java_library") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + + _template_name = target_name + + action_with_pydeps("${_template_name}__protoc_java") { + # The suffix "__protoc_java.srcjar" is used by SuperSize to identify + # protobuf symbols. + _srcjar_path = "$target_gen_dir/$target_name.srcjar" + script = "//build/protoc_java.py" + + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + sources = invoker.sources + depfile = "$target_gen_dir/$target_name.d" + outputs = [ _srcjar_path ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--protoc", + rebase_path(android_protoc_bin, root_build_dir), + "--proto-path", + rebase_path(invoker.proto_path, root_build_dir), + "--srcjar", + rebase_path(_srcjar_path, root_build_dir), + ] + rebase_path(sources, root_build_dir) + + if (defined(invoker.import_dirs)) { + foreach(_import_dir, invoker.import_dirs) { + args += [ + "--import-dir", + rebase_path(_import_dir, root_build_dir), + ] + } + } + } + + android_library(target_name) { + chromium_code = false + sources = [] + srcjar_deps = [ ":${_template_name}__protoc_java" ] + deps = [ "//third_party/android_deps:protobuf_lite_runtime_java" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } + } + + # Declare an Android library target for a prebuilt AAR. + # + # This target creates an Android library containing java code and Android + # resources. For libraries without resources, it will not generate + # corresponding android_resources targets. + # + # To avoid slowing down "gn gen", an associated .info file must be committed + # along with the .aar file. In order to create this file, define the target + # and then run once with the gn arg "update_android_aar_prebuilts = true". + # + # Variables + # aar_path: Path to the AAR. + # info_path: Path to the .aar.info file (generated via + # update_android_aar_prebuilts GN arg). + # proguard_configs: List of proguard configs to use in final apk step for + # any apk that depends on this library. + # ignore_aidl: Whether to ignore .aidl files found with the .aar. + # ignore_assets: Whether to ignore assets found in the .aar. + # ignore_manifest: Whether to ignore creating manifest. + # ignore_native_libraries: Whether to ignore .so files found in the .aar. + # See also extract_native_libraries. + # ignore_proguard_configs: Whether to ignore proguard configs. + # ignore_info_updates: Whether to ignore the info file when + # update_android_aar_prebuilts gn arg is true. However, the info file + # will still be verified regardless of the value of this flag. + # strip_resources: Whether to ignore android resources found in the .aar. + # custom_package: Java package for generated R.java files. + # extract_native_libraries: Whether to extract .so files found in the .aar. + # If the file contains .so, either extract_native_libraries or + # ignore_native_libraries must be set. + # TODO(jbudorick@): remove this arguments after crbug.com/522043 is fixed. + # requires_android: Whether this target can only be used for compiling + # Android related targets. + # + # Example + # android_aar_prebuilt("foo_java") { + # aar_path = "foo.aar" + # } + template("android_aar_prebuilt") { + _info_path = "$target_name.info" + if (defined(invoker.info_path)) { + _info_path = invoker.info_path + } + _output_path = "${target_out_dir}/${target_name}" + + # Some targets only differ by _java with other targets so _java and _junit + # need to be replaced by non-empty strings to avoid duplicate targets. (e.g. + # androidx_window_window_java vs androidx_window_window_java_java). + _target_name_without_java_or_junit = + string_replace(string_replace(target_name, "_java", "_J"), + "_junit", + "_U") + + # This unpack target is a python action, not a valid java target. Since the + # java targets below depend on it, its name must not match the java patterns + # in internal_rules.gni. + _unpack_target_name = "${_target_name_without_java_or_junit}__unpack_aar" + _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl + _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets + _ignore_manifest = + defined(invoker.ignore_manifest) && invoker.ignore_manifest + _ignore_native_libraries = defined(invoker.ignore_native_libraries) && + invoker.ignore_native_libraries + _ignore_proguard_configs = defined(invoker.ignore_proguard_configs) && + invoker.ignore_proguard_configs + _extract_native_libraries = defined(invoker.extract_native_libraries) && + invoker.extract_native_libraries + _strip_resources = + defined(invoker.strip_resources) && invoker.strip_resources + + # Allow 'resource_overlay' parameter even if there are no resources in order + # to keep the logic for generated 'android_aar_prebuilt' rules simple. + not_needed(invoker, [ "resource_overlay" ]) + + _ignore_info_updates = + defined(invoker.ignore_info_updates) && invoker.ignore_info_updates + + # Scan the AAR file and determine the resources and jar files. + # Some libraries might not have resources; others might have two jars. + if (!_ignore_info_updates && update_android_aar_prebuilts) { + print("Writing " + rebase_path(_info_path, "//")) + exec_script("//build/android/gyp/aar.py", + [ + "list", + rebase_path(invoker.aar_path, root_build_dir), + "--output", + rebase_path(_info_path, root_build_dir), + ]) + } + + # If "gn gen" is failing on the following line, you need to generate an + # .info file for your new target by running: + # gn gen --args='target_os="android" update_android_aar_prebuilts=true' out/tmp + # rm -r out/tmp + _scanned_files = read_file(_info_path, "scope") + + _use_scanned_assets = !_ignore_assets && _scanned_files.assets != [] + + assert(_ignore_aidl || _scanned_files.aidl == [], + "android_aar_prebuilt() aidl not yet supported." + + " Implement or use ignore_aidl = true." + + " http://crbug.com/644439") + assert( + !_scanned_files.has_native_libraries || + (_ignore_native_libraries || _extract_native_libraries), + "android_aar_prebuilt() contains .so files." + + " Please set ignore_native_libraries or extract_native_libraries.") + assert( + !(_ignore_native_libraries && _extract_native_libraries), + "ignore_native_libraries and extract_native_libraries cannot both be set.") + assert(!_scanned_files.has_native_libraries || + _scanned_files.native_libraries != []) + assert(_scanned_files.has_classes_jar || _scanned_files.subjars == []) + + action_with_pydeps(_unpack_target_name) { + script = "//build/android/gyp/aar.py" # Unzips the AAR + args = [ + "extract", + rebase_path(invoker.aar_path, root_build_dir), + "--output-dir", + rebase_path(_output_path, root_build_dir), + "--assert-info-file", + rebase_path(_info_path, root_build_dir), + ] + if (_strip_resources) { + args += [ "--ignore-resources" ] + } + inputs = [ invoker.aar_path ] + outputs = [ "${_output_path}/AndroidManifest.xml" ] + if (!_strip_resources && _scanned_files.has_r_text_file) { + # Certain packages, in particular Play Services have no R.txt even + # though its presence is mandated by AAR spec. Such packages cause + # spurious rebuilds if this output is specified unconditionally. + outputs += [ "${_output_path}/R.txt" ] + } + + if (!_strip_resources && _scanned_files.resources != []) { + outputs += get_path_info( + rebase_path(_scanned_files.resources, "", _output_path), + "abspath") + } + if (_scanned_files.has_classes_jar) { + outputs += [ "${_output_path}/classes.jar" ] + } + outputs += + get_path_info(rebase_path(_scanned_files.subjars, "", _output_path), + "abspath") + if (!_ignore_proguard_configs) { + if (_scanned_files.has_proguard_flags) { + outputs += [ "${_output_path}/proguard.txt" ] + } + } + + if (_extract_native_libraries && _scanned_files.has_native_libraries) { + outputs += get_path_info( + rebase_path(_scanned_files.native_libraries, "", _output_path), + "abspath") + } + if (_use_scanned_assets) { + outputs += + get_path_info(rebase_path(_scanned_files.assets, "", _output_path), + "abspath") + } + } + + _has_unignored_resources = + !_strip_resources && + (_scanned_files.resources != [] || _scanned_files.has_r_text_file) + + _should_process_manifest = + !_ignore_manifest && !_scanned_files.is_manifest_empty + + # Create the android_resources target for resources. + if (_has_unignored_resources || _should_process_manifest) { + _res_target_name = "${target_name}__resources" + android_resources(_res_target_name) { + forward_variables_from(invoker, + [ + "custom_package", + "resource_overlay", + "testonly", + "strip_drawables", + ]) + deps = [ ":$_unpack_target_name" ] + if (_should_process_manifest) { + android_manifest_dep = ":$_unpack_target_name" + android_manifest = "${_output_path}/AndroidManifest.xml" + } else if (defined(_scanned_files.manifest_package) && + !defined(custom_package)) { + custom_package = _scanned_files.manifest_package + } + + sources = [] + if (!_strip_resources) { + sources = rebase_path(_scanned_files.resources, "", _output_path) + } + if (!_strip_resources && _scanned_files.has_r_text_file) { + r_text_file = "${_output_path}/R.txt" + } + } + } else if (defined(invoker.strip_drawables)) { + not_needed(invoker, [ "strip_drawables" ]) + } + + if (_ignore_manifest) { + # Having this available can be useful for DFMs that depend on AARs. It + # provides a way to have manifest entries go into the base split while + # the code goes into a DFM. + java_group("${target_name}__ignored_manifest") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + deps = [ ":$_unpack_target_name" ] + mergeable_android_manifests = [ "${_output_path}/AndroidManifest.xml" ] + } + } + + # Create the android_assets target for assets + if (_use_scanned_assets) { + _assets_target_name = "${target_name}__assets" + android_assets(_assets_target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + renaming_sources = [] + renaming_destinations = [] + foreach(_asset_file, _scanned_files.assets) { + _original_path = + get_path_info(rebase_path(_asset_file, "", _output_path), + "abspath") + _updated_path = string_replace(_asset_file, "assets/", "", 1) + renaming_sources += [ _original_path ] + renaming_destinations += [ _updated_path ] + } + } + } + + # Create android_java_prebuilt target for classes.jar. + if (_scanned_files.has_classes_jar) { + _java_library_vars = [ + "bytecode_rewriter_target", + "enable_bytecode_checks", + "jar_excluded_patterns", + "jar_included_patterns", + "missing_classes_allowlist", + "requires_android", + "testonly", + "use_classic_desugar", + ] + + # Create android_java_prebuilt target for extra jars within jars/. + _subjar_targets = [] + foreach(_tuple, _scanned_files.subjar_tuples) { + _current_target = "${target_name}__subjar_${_tuple[0]}" + _subjar_targets += [ ":$_current_target" ] + java_prebuilt(_current_target) { + forward_variables_from(invoker, _java_library_vars) + deps = [ ":$_unpack_target_name" ] + if (!defined(requires_android)) { + requires_android = true + } + supports_android = true + jar_path = "$_output_path/${_tuple[1]}" + _base_output_name = get_path_info(jar_path, "name") + output_name = "${invoker.target_name}-$_base_output_name" + public_target_label = invoker.target_name + } + } + + _jar_target_name = "${target_name}__classes" + java_prebuilt(_jar_target_name) { + forward_variables_from(invoker, _java_library_vars) + forward_variables_from(invoker, + [ + "deps", + "input_jars_paths", + "proguard_configs", + ]) + if (!defined(deps)) { + deps = [] + } + deps += _subjar_targets + [ ":$_unpack_target_name" ] + if (defined(_res_target_name)) { + deps += [ ":$_res_target_name" ] + } + if (!defined(requires_android)) { + requires_android = true + } + supports_android = true + jar_path = "$_output_path/classes.jar" + aar_path = invoker.aar_path + output_name = invoker.target_name + + if (!_ignore_proguard_configs) { + if (!defined(proguard_configs)) { + proguard_configs = [] + } + if (_scanned_files.has_proguard_flags) { + proguard_configs += [ "$_output_path/proguard.txt" ] + } + } + public_target_label = invoker.target_name + } + } + + java_group(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) + public_deps = [ ":$_unpack_target_name" ] + deps = [] + if (defined(_jar_target_name)) { + deps += [ ":$_jar_target_name" ] + + # Although subjars are meant to be private, we add them as deps here + # because in practice they seem to contain classes required to be in the + # classpath. + deps += _subjar_targets + } + if (defined(_res_target_name)) { + deps += [ ":$_res_target_name" ] + } + if (defined(_assets_target_name)) { + deps += [ ":$_assets_target_name" ] + } + } + } + + # Create an Android application bundle from one base android_apk target, + # and zero or more associated android_apk. + # + # Variables: + # base_module_target: Name of the android_app_bundle_module target + # corresponding to the base module for this application bundle. The + # bundle file will include the same content in its base module, though in + # a slightly different format. + # + # bundle_base_path: Optional. If set, the bundle will be output to this + # directory. Defaults to "$root_build_dir/apks". + # + # bundle_name: Optional. If set, the bundle will be output to the + # filename "${bundle_name}.aab". + # + # extra_modules: Optional list of scopes, one per extra module used by + # this bundle. Each scope must have a 'name' field that specifies the + # module name (which cannot be 'base', since this is reserved for the + # base module), and an 'apk_target' field that specified the + # corresponding android_apk target name the module is modeled on. + # + # enable_language_splits: Optional. If true, enable APK splits based + # on languages. + # + # keystore_path: optional keystore path, used only when generating APKs. + # keystore_name: optional keystore name, used only when generating APKs. + # keystore_password: optional keystore password, used only when + # generating APKs. + # + # command_line_flags_file: Optional. If provided, named of the on-device + # file that will be used to store command-line arguments. The default + # is 'command_line_flags_file', but this is typically redefined to + # something more specific for certain bundles (e.g. the Chromium based + # APKs use 'chrome-command-line', the WebView one uses + # 'webview-command-line'). + # + # proguard_enabled: Optional. True if proguarding is enabled for this + # bundle. Default is to enable this only for release builds. Note that + # this will always perform synchronized proguarding. + # + # proguard_enable_obfuscation: Whether to enable obfuscation (default=true) + # + # enable_multidex: Optional. Enable multidexing of optimized modules jars + # when using synchronized proguarding. Only applies to base module. + # + # proguard_android_sdk_dep: Optional. android_system_java_prebuilt() target + # used as a library jar for synchronized proguarding. + # + # compress_shared_libraries: Optional. Whether to compress shared libraries + # such that they are extracted upon install. Libraries prefixed with + # "crazy." are never compressed. + # + # system_image_locale_allowlist: List of locales that should be included + # on system APKs generated from this bundle. + # + # static_library_provider: Specifies a single target that this target will + # use as a static library APK. + # Additionally, when allotting libraries to be packaged into modules, the + # libraries packaged into the static library will be accounted for to + # avoid library duplication. Effectively, the static library will be + # treated as the parent of the base module. + # + # expected_libs_and_assets: Verify the list of included native libraries + # and assets is consistent with the given expectation file. + # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff + # with this file as the base. + # expected_proguard_config: Checks that the merged set of proguard flags + # matches the given config. + # expected_proguard_config_base: Treat expected_proguard_config as a diff + # with this file as the base. + # + # version_code: Optional. Version code of the target. + # + # is_multi_abi: If true will add a library placeholder for the missing ABI + # if either the primary or the secondary ABI has no native libraries set. + # + # default_modules_for_testing: (optional): A list of DFM that the wrapper + # script should install. This is for local testing only, and does not + # affect the actual DFM in production. + # Example: + # android_app_bundle("chrome_public_bundle") { + # base_module_target = "//chrome/android:chrome_public_apk" + # extra_modules = [ + # { # NOTE: Scopes require one field per line, and no comma separators. + # name = "my_module" + # module_target = ":my_module" + # }, + # ] + # } + # + template("android_app_bundle") { + _target_name = target_name + _uses_static_library = defined(invoker.static_library_provider) + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + + if (defined(invoker.version_code)) { + _version_code = invoker.version_code + } else { + _version_code = android_default_version_code + } + + if (android_override_version_code != "") { + _version_code = android_override_version_code + } + + # Prevent "unused variable". + not_needed([ "_version_code" ]) + + _bundle_base_path = "$root_build_dir/apks" + if (defined(invoker.bundle_base_path)) { + _bundle_base_path = invoker.bundle_base_path + } + + _bundle_name = _target_name + if (defined(invoker.bundle_name)) { + _bundle_name = invoker.bundle_name + } + _bundle_path = "$_bundle_base_path/${_bundle_name}.aab" + _rebased_bundle_path = rebase_path(_bundle_path, root_build_dir) + + _base_target_name = get_label_info(invoker.base_module_target, "name") + _base_target_gen_dir = + get_label_info(invoker.base_module_target, "target_gen_dir") + _base_module_build_config = + "$_base_target_gen_dir/${_base_target_name}.build_config.json" + _base_module_build_config_target = + "${invoker.base_module_target}$build_config_target_suffix" + _rebased_base_module_build_config = + rebase_path(_base_module_build_config, root_build_dir) + + _modules = [ + { + name = "base" + module_target = invoker.base_module_target + build_config = _base_module_build_config + build_config_target = _base_module_build_config_target + if (_uses_static_library) { + parent = "lib" + } + }, + ] + + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + + # Prevent "unused variable". + not_needed([ "_enable_multidex" ]) + + if (_proguard_enabled) { + _uses_static_library_synchronized_proguard = + defined(invoker.static_library_synchronized_proguard) && + invoker.static_library_synchronized_proguard + + # TODO(crbug.com/1032609): Remove dexsplitter from Trichrome Proguard. + _dex_target = "${_target_name}__dex" + _proguard_mapping_path = "${_bundle_path}.mapping" + } + + assert(_proguard_enabled || !defined(invoker.enable_multidex), + "Bundle only adds dexing step if proguarding is enabled.") + + if (defined(invoker.extra_modules)) { + _module_count = 0 + not_needed([ "_module_count" ]) + + foreach(_module, invoker.extra_modules) { + _module_count += 1 + assert(defined(_module.name), + "Missing 'name' field for extra module #${_module_count}.") + assert(_module.name != "base", + "Module name 'base' is reserved for the main bundle module") + assert( + defined(_module.module_target), + "Missing 'module_target' field for extra module ${_module.name}.") + _module_target = _module.module_target + _module_target_name = get_label_info(_module_target, "name") + _module_target_gen_dir = + get_label_info(_module_target, "target_gen_dir") + _module.build_config = + "$_module_target_gen_dir/${_module_target_name}.build_config.json" + _module.build_config_target = + "$_module_target$build_config_target_suffix" + _module.parent = "base" + _modules += [ _module ] + } + } + + # Make build config, which is required for synchronized proguarding. + _module_java_targets = [] + _module_build_configs = [] + _module_targets = [] + foreach(_module, _modules) { + _module_targets += [ _module.module_target ] + _module_java_targets += [ "${_module.module_target}__java" ] + _module_build_configs += [ _module.build_config ] + } + + if (_uses_static_library) { + _lib_proxy_module = { + name = "lib" + } + _static_library_target_name = + get_label_info(invoker.static_library_provider, "name") + _static_library_gen_dir = + get_label_info(invoker.static_library_provider, "target_gen_dir") + _lib_proxy_module.build_config = "$_static_library_gen_dir/$_static_library_target_name.build_config.json" + _lib_proxy_module.build_config_target = + "${invoker.static_library_provider}$build_config_target_suffix" + } + + # Allot native libraries to modules they should be packaged into. This is + # necessary since all libraries that are depended on by multiple modules + # have to go into base or the static shared library if it exists. + # TODO(crbug.com/1021565): It would be nice if this lived outside the + # android_app_bundle template and the static shared library would pull in + # the libs as allotted by this step. + _native_libraries_config = + "$target_gen_dir/$_target_name.native_libraries_config" + _native_libraries_config_target = "${_target_name}__allot_native_libraries" + allot_native_libraries(_native_libraries_config_target) { + modules = _modules + native_libraries_filearg_keys = [ + "native:libraries", + "native:loadable_modules", + ] + output = _native_libraries_config + if (_uses_static_library) { + modules += [ _lib_proxy_module ] + } + } + if (defined(android_app_secondary_abi)) { + _secondary_abi_native_libraries_config = + "$target_gen_dir/$_target_name.secondary_abi_native_libraries_config" + _secondary_abi_native_libraries_config_target = + "${_target_name}__allot_secondary_abi_native_libraries" + allot_native_libraries(_secondary_abi_native_libraries_config_target) { + modules = _modules + native_libraries_filearg_keys = [ + "native:secondary_abi_libraries", + "native:secondary_abi_loadable_modules", + ] + output = _secondary_abi_native_libraries_config + if (_uses_static_library) { + modules += [ _lib_proxy_module ] + } + } + } + + # Used to expose the module Java targets of the bundle. + group("${_target_name}__java") { + deps = _module_java_targets + } + group("${_target_name}__compile_resources") { + deps = [ "${invoker.base_module_target}__compile_resources" ] + } + + _build_config = "$target_gen_dir/${_target_name}.build_config.json" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _build_config_target = "$_target_name$build_config_target_suffix" + if (defined(invoker.proguard_android_sdk_dep)) { + proguard_android_sdk_dep_ = invoker.proguard_android_sdk_dep + } else { + proguard_android_sdk_dep_ = "//third_party/android_sdk:android_sdk_java" + } + + if (_proguard_enabled) { + _proguard_mapping_path = "${_bundle_path}.mapping" + } + + write_build_config(_build_config_target) { + type = "android_app_bundle" + possible_config_deps = _module_targets + [ proguard_android_sdk_dep_ ] + build_config = _build_config + proguard_enabled = _proguard_enabled + module_build_configs = _module_build_configs + + if (_proguard_enabled) { + proguard_mapping_path = _proguard_mapping_path + } + } + + if (_proguard_enabled) { + # If this Bundle uses a static library, the static library APK will + # create the synchronized dex file path. + if (!_uses_static_library_synchronized_proguard) { + dex(_dex_target) { + forward_variables_from(invoker, + [ + "expected_proguard_config", + "expected_proguard_config_base", + "min_sdk_version", + "proguard_enable_obfuscation", + ]) + if (defined(expected_proguard_config)) { + top_target_name = _target_name + } + enable_multidex = _enable_multidex + proguard_enabled = true + proguard_mapping_path = _proguard_mapping_path + proguard_sourcefile_suffix = "$android_channel-$_version_code" + build_config = _build_config + + deps = _module_java_targets + [ ":$_build_config_target" ] + modules = _modules + } + } + } + + _all_create_module_targets = [] + _all_module_zip_paths = [] + _all_module_build_configs = [] + _all_module_unused_resources_deps = [] + foreach(_module, _modules) { + _module_target = _module.module_target + _module_build_config = _module.build_config + _module_build_config_target = _module.build_config_target + + if (!_proguard_enabled) { + _dex_target_for_module = "${_module_target}__final_dex" + } else { + _dex_target_for_module = ":$_dex_target" + } + + # Generate one module .zip file per bundle module. + # + # Important: the bundle tool uses the module's zip filename as + # the internal module name inside the final bundle, in other words, + # this file *must* be named ${_module.name}.zip + _create_module_target = "${_target_name}__${_module.name}__create" + _module_zip_path = "$target_gen_dir/$target_name/${_module.name}.zip" + create_android_app_bundle_module(_create_module_target) { + forward_variables_from(invoker, + [ + "is_multi_abi", + "min_sdk_version", + "uncompress_dex", + "proguard_enabled", + ]) + module_name = _module.name + build_config = _module_build_config + module_zip_path = _module_zip_path + native_libraries_config = _native_libraries_config + + if (module_name == "base" && + defined(invoker.expected_libs_and_assets)) { + forward_variables_from(invoker, + [ + "expected_libs_and_assets", + "expected_libs_and_assets_base", + ]) + top_target_name = _target_name + build_config_target = _module_build_config_target + native_libraries_config_target = ":$_native_libraries_config_target" + if (defined(android_app_secondary_abi)) { + secondary_abi_native_libraries_config_target = + ":$_secondary_abi_native_libraries_config_target" + } + } + + deps = [ + ":$_native_libraries_config_target", + _dex_target_for_module, + _module_build_config_target, + _module_target, + ] + + if (defined(android_app_secondary_abi)) { + secondary_abi_native_libraries_config = + _secondary_abi_native_libraries_config + deps += [ ":$_secondary_abi_native_libraries_config_target" ] + } + } + + _all_create_module_targets += [ + ":$_create_module_target", + _module_build_config_target, + "${_module_target}__compile_resources", + ] + _all_module_zip_paths += [ _module_zip_path ] + _all_module_build_configs += [ _module_build_config ] + _all_module_unused_resources_deps += [ + "${_module_target}__compile_resources", + _dex_target_for_module, + _module_build_config_target, + ] + } + if (defined(invoker.strip_unused_resources) && + invoker.strip_unused_resources) { + # Resources only live in the base module so we define the unused resources + # target only on the base module target. + _unused_resources_target = "${_base_target_name}__unused_resources" + _unused_resources_config = + "${_base_target_gen_dir}/${_base_target_name}_unused_resources.config" + unused_resources(_unused_resources_target) { + deps = _all_module_unused_resources_deps + all_module_build_configs = _all_module_build_configs + build_config = _base_module_build_config + if (_proguard_enabled) { + proguard_mapping_path = _proguard_mapping_path + } + output_config = _unused_resources_config + } + } + + _all_rebased_module_zip_paths = + rebase_path(_all_module_zip_paths, root_build_dir) + + _enable_language_splits = defined(invoker.enable_language_splits) && + invoker.enable_language_splits + + _split_dimensions = [] + if (_enable_language_splits) { + _split_dimensions += [ "language" ] + } + + _keystore_path = android_keystore_path + _keystore_password = android_keystore_password + _keystore_name = android_keystore_name + + if (defined(invoker.keystore_path)) { + _keystore_path = invoker.keystore_path + _keystore_password = invoker.keystore_password + _keystore_name = invoker.keystore_name + } + + _rebased_keystore_path = rebase_path(_keystore_path, root_build_dir) + + _bundle_target_name = "${_target_name}__bundle" + action_with_pydeps(_bundle_target_name) { + script = "//build/android/gyp/create_app_bundle.py" + inputs = _all_module_zip_paths + _all_module_build_configs + outputs = [ _bundle_path ] + deps = _all_create_module_targets + [ ":$_build_config_target" ] + args = [ + "--out-bundle=$_rebased_bundle_path", + "--rtxt-out-path=$_rebased_bundle_path.R.txt", + "--pathmap-out-path=$_rebased_bundle_path.pathmap.txt", + "--module-zips=$_all_rebased_module_zip_paths", + ] + if (_split_dimensions != []) { + args += [ "--split-dimensions=$_split_dimensions" ] + } + if (defined(invoker.compress_shared_libraries) && + invoker.compress_shared_libraries) { + args += [ "--compress-shared-libraries" ] + } + _min_sdk_version = default_min_sdk_version + if (defined(invoker.min_sdk_version)) { + _min_sdk_version = invoker.min_sdk_version + } + + # Android P+ support loading from stored dex. + if (_min_sdk_version < 27) { + args += [ "--compress-dex" ] + } + + if (treat_warnings_as_errors) { + args += [ "--warnings-as-errors" ] + } + + if (_enable_language_splits) { + args += [ + "--base-allowlist-rtxt-path=@FileArg(" + "${_rebased_base_module_build_config}:deps_info:base_allowlist_rtxt_path)", + "--base-module-rtxt-path=@FileArg(" + + "${_rebased_base_module_build_config}:deps_info:r_text_path)", + ] + } + if (defined(invoker.validate_services) && invoker.validate_services) { + args += [ "--validate-services" ] + } + + foreach(_module, _modules) { + _rebased_build_config = + rebase_path(_module.build_config, root_build_dir) + args += [ + "--uncompressed-assets=@FileArg(" + + "$_rebased_build_config:uncompressed_assets)", + "--rtxt-in-paths=@FileArg(" + + "$_rebased_build_config:deps_info:r_text_path)", + "--pathmap-in-paths=@FileArg(" + + "$_rebased_build_config:deps_info:module_pathmap_path)", + "--module-name=" + _module.name, + ] + } + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + + # Create size info files for targets that care about size + # (have proguard enabled). + if (_proguard_enabled) { + # Merge all module targets to obtain size info files for all targets. + _all_module_targets = _module_targets + + _size_info_target = "${_target_name}__size_info" + create_size_info_files(_size_info_target) { + name = "$_bundle_name.aab" + deps = _all_module_targets + [ ":$_build_config_target" ] + module_build_configs = _all_module_build_configs + } + } + + if (_uses_static_library) { + _install_artifacts_target = "${target_name}__install_artifacts" + _install_artifacts_json = + "${target_gen_dir}/${target_name}.install_artifacts" + generated_file(_install_artifacts_target) { + output_conversion = "json" + deps = [ invoker.static_library_provider ] + outputs = [ _install_artifacts_json ] + data_keys = [ "install_artifacts" ] + rebase = root_build_dir + } + } + + # Generate a wrapper script for the bundle. + _android_aapt2_path = android_sdk_tools_bundle_aapt2 + + _bundle_apks_path = "$_bundle_base_path/$_bundle_name.apks" + _bundle_wrapper_script_dir = "$root_build_dir/bin" + _bundle_wrapper_script_path = "$_bundle_wrapper_script_dir/$_target_name" + + action_with_pydeps("${_target_name}__wrapper_script") { + script = "//build/android/gyp/create_bundle_wrapper_script.py" + inputs = [ _base_module_build_config ] + outputs = [ _bundle_wrapper_script_path ] + + # Telemetry for bundles uses the wrapper script for installation. + data = [ + _bundle_wrapper_script_path, + _android_aapt2_path, + _keystore_path, + _bundle_path, + ] + data_deps = [ + "//build/android:apk_operations_py", + "//build/android:stack_tools", + ] + + deps = [ _base_module_build_config_target ] + args = [ + "--script-output-path", + rebase_path(_bundle_wrapper_script_path, root_build_dir), + "--package-name=@FileArg(" + + "$_rebased_base_module_build_config:deps_info:package_name)", + "--aapt2", + rebase_path(_android_aapt2_path, root_build_dir), + "--bundle-path", + _rebased_bundle_path, + "--bundle-apks-path", + rebase_path(_bundle_apks_path, root_build_dir), + "--target-cpu=$target_cpu", + "--keystore-path", + _rebased_keystore_path, + "--keystore-password", + _keystore_password, + "--key-name", + _keystore_name, + ] + if (defined(invoker.default_modules_for_testing)) { + args += [ "--default-modules" ] + invoker.default_modules_for_testing + } + if (defined(invoker.system_image_locale_allowlist)) { + args += [ + "--system-image-locales=${invoker.system_image_locale_allowlist}", + ] + } + if (defined(invoker.command_line_flags_file)) { + args += [ + "--command-line-flags-file", + invoker.command_line_flags_file, + ] + } + if (_uses_static_library) { + deps += [ ":$_install_artifacts_target" ] + _rebased_install_artifacts_json = + rebase_path(_install_artifacts_json, root_build_dir) + _static_library_apk_path = + "@FileArg($_rebased_install_artifacts_json[])" + args += [ + "--additional-apk", + _static_library_apk_path, + ] + } + + if (_proguard_enabled) { + args += [ + "--proguard-mapping-path", + rebase_path(_proguard_mapping_path, root_build_dir), + ] + + # Required by logcat command. + data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] + data += [ _proguard_mapping_path ] + } + } + + _enable_lint = defined(invoker.enable_lint) && invoker.enable_lint && + !disable_android_lint + if (_enable_lint) { + android_lint("${target_name}__lint") { + forward_variables_from(invoker, + [ + "lint_baseline_file", + "lint_suppressions_file", + "min_sdk_version", + ]) + build_config = _build_config + build_config_dep = ":$_build_config_target" + deps = _module_java_targets + if (defined(invoker.lint_suppressions_dep)) { + deps += [ invoker.lint_suppressions_dep ] + } + if (defined(invoker.lint_min_sdk_version)) { + min_sdk_version = invoker.lint_min_sdk_version + } + } + } else { + not_needed(invoker, + [ + "lint_baseline_file", + "lint_min_sdk_version", + "lint_suppressions_dep", + "lint_suppressions_file", + ]) + } + + group(_target_name) { + public_deps = [ + ":$_bundle_target_name", + ":${_target_name}__wrapper_script", + ] + if (defined(_size_info_target)) { + public_deps += [ ":$_size_info_target" ] + } + if (_enable_lint) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${target_name}__lint" ] + } + } + + _apks_path = "$root_build_dir/apks/$_bundle_name.apks" + action_with_pydeps("${_target_name}_apks") { + script = "//build/android/gyp/create_app_bundle_apks.py" + inputs = [ _bundle_path ] + outputs = [ _apks_path ] + data = [ _apks_path ] + args = [ + "--bundle", + _rebased_bundle_path, + "--output", + rebase_path(_apks_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--keystore-path", + rebase_path(android_keystore_path, root_build_dir), + "--keystore-name", + android_keystore_name, + "--keystore-password", + android_keystore_password, + ] + if (debuggable_apks) { + args += [ "--local-testing" ] + } + deps = [ ":$_bundle_target_name" ] + metadata = { + install_artifacts = [ _apks_path ] + } + if (defined(invoker.static_library_provider)) { + metadata.install_artifacts_barrier = [] + } + + # http://crbug.com/725224. Fix for bots running out of memory. + if (defined(java_cmd_pool_size)) { + pool = "//build/config/android:java_cmd_pool($default_toolchain)" + } else { + pool = "//build/toolchain:link_pool($default_toolchain)" + } + } + } + + # Create an .apks file from an .aab file. The .apks file will contain the + # minimal set of .apk files needed for tracking binary size. + # The file will be created at "$bundle_path_without_extension.minimal.apks". + # + # Variables: + # bundle_path: Path to the input .aab file. + # + # Example: + # create_app_bundle_minimal_apks("minimal_apks") { + # deps = [ + # ":bundle_target", + # ] + # bundle_path = "$root_build_dir/apks/Bundle.aab" + # } + template("create_app_bundle_minimal_apks") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "deps" ]) + script = "//build/android/gyp/create_app_bundle_apks.py" + _dir = get_path_info(invoker.bundle_path, "dir") + _name = get_path_info(invoker.bundle_path, "name") + _output_path = "$_dir/$_name.minimal.apks" + outputs = [ _output_path ] + inputs = [ invoker.bundle_path ] + args = [ + "--bundle", + rebase_path(invoker.bundle_path, root_build_dir), + "--output", + rebase_path(_output_path, root_build_dir), + "--aapt2-path", + rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), + "--keystore-path", + rebase_path(android_keystore_path, root_build_dir), + "--keystore-name", + android_keystore_name, + "--keystore-password", + android_keystore_password, + "--minimal", + ] + } + } +} + +# Generate an Android resources target that contains localized strings +# describing the current locale used by the Android framework to display +# UI strings. These are used by +# org.chromium.chrome.browser.ChromeLocalizationUtils. +# +# Variables: +# ui_locales: List of Chromium locale names to generate resources for. +# +template("generate_ui_locale_resources") { + _generating_target_name = "${target_name}__generate" + _rebased_output_zip_path = rebase_path(target_gen_dir, root_gen_dir) + _output_zip = "${root_out_dir}/resource_zips/${_rebased_output_zip_path}/" + + "${target_name}.zip" + + action_with_pydeps(_generating_target_name) { + script = "//build/android/gyp/create_ui_locale_resources.py" + outputs = [ _output_zip ] + args = [ + "--locale-list=${invoker.ui_locales}", + "--output-zip", + rebase_path(_output_zip, root_build_dir), + ] + } + + android_generated_resources(target_name) { + generating_target = ":$_generating_target_name" + generated_resources_zip = _output_zip + } +} diff --git a/third_party/libwebrtc/build/config/android/sdk.gni b/third_party/libwebrtc/build/config/android/sdk.gni new file mode 100644 index 0000000000..8547170167 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/sdk.gni @@ -0,0 +1,10 @@ +# Copyright 2017 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. + +# The default SDK release used by public builds. Value may differ in +# internal builds. +default_android_sdk_release = "s" + +# SDK releases against which public builds are supported. +public_sdk_releases = [ "s" ] diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn b/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn new file mode 100644 index 0000000000..decd1a84d2 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/BUILD.gn @@ -0,0 +1,111 @@ +# Copyright 2021 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. + +import("//build/config/android/rules.gni") + +template("test_resources") { + jinja_template_resources(target_name) { + forward_variables_from(invoker, "*") + testonly = true + variables = [ "resource_name=$resource_name" ] + res_dir = "java/res_template" + resources = [ "java/res_template/values/values.xml" ] + } +} + +template("generate_dummy_android_library") { + # No underscores to avoid crbug.com/908819. + _generate_java_source_target_name = "${target_name}generatejavasource" + jinja_template(_generate_java_source_target_name) { + testonly = true + input = "java/src/org/chromium/build/classpath_order/Dummy.java.jinja2" + output = "$target_gen_dir/java/src/org/chromium/build/classpath_order/${invoker.class_name}.java" + variables = [ "class_name=${invoker.class_name}" ] + } + + android_library(target_name) { + forward_variables_from(invoker, "*") + + if (!defined(invoker.deps)) { + deps = [] + } + + sources = get_target_outputs(":${_generate_java_source_target_name}") + deps += [ ":${_generate_java_source_target_name}" ] + } +} + +# Test that classpath order keeps resources accessible when multiple targets generate +# resources for the same package. Specifically, test that an android_library precedes +# its dependencies regardless of the relative lexographic order. + +test_resources("a1_dependency_resources") { + resource_name = "a1_dependency_resource" +} + +generate_dummy_android_library("a1_dependency_java") { + testonly = true + class_name = "A1Dependency" + resources_package = "org.chromium.build.classpath_order.test1" + deps = [ ":a1_dependency_resources" ] +} + +test_resources("z1_master_resources") { + resource_name = "z1_master_resource" + deps = [ ":a1_dependency_resources" ] +} + +generate_dummy_android_library("z1_master_java") { + testonly = true + class_name = "Z1Master" + resources_package = "org.chromium.build.classpath_order.test1" + deps = [ + ":a1_dependency_java", + ":z1_master_resources", + ] +} + +test_resources("z2_dependency_resources") { + resource_name = "z2_dependency_resource" +} + +generate_dummy_android_library("z2_dependency_java") { + testonly = true + class_name = "Z2Dependency" + resources_package = "org.chromium.build.classpath_order.test2" + deps = [ ":z2_dependency_resources" ] +} + +test_resources("a2_master_resources") { + resource_name = "a2_master_resource" + deps = [ ":z2_dependency_resources" ] +} + +generate_dummy_android_library("a2_master_java") { + testonly = true + class_name = "A2Master" + resources_package = "org.chromium.build.classpath_order.test2" + deps = [ + ":a2_master_resources", + ":z2_dependency_java", + ] +} + +java_library("junit_tests") { + bypass_platform_checks = true + testonly = true + sources = + [ "java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java" ] + deps = [ + ":a1_dependency_java", + ":a2_master_java", + ":z1_master_java", + ":z2_dependency_java", + "//testing/android/junit:junit_test_support", + "//third_party/android_deps:robolectric_all_java", + "//third_party/android_support_test_runner:runner_java", + "//third_party/androidx:androidx_test_runner_java", + "//third_party/junit", + ] +} diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml b/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml new file mode 100644 index 0000000000..ee706b289b --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/res_template/values/values.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <integer name="{{resource_name}}">42</integer> +</resources> diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java new file mode 100644 index 0000000000..c5a9202605 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/ClassPathOrderTest.java @@ -0,0 +1,32 @@ +// Copyright 2021 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. + +package org.chromium.build.classpath_order; + +import static org.junit.Assert.assertTrue; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.testing.local.LocalRobolectricTestRunner; + +/** + * Test that resources defined in different android_resources() targets but with the same + * package are accessible. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public final class ClassPathOrderTest { + @Test + @SmallTest + public void testAll() { + assertTrue(org.chromium.build.classpath_order.test1.R.integer.a1_dependency_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test1.R.integer.z1_master_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test2.R.integer.z2_dependency_resource >= 0); + assertTrue(org.chromium.build.classpath_order.test2.R.integer.a2_master_resource >= 0); + } +} diff --git a/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 new file mode 100644 index 0000000000..0ccf28b284 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/classpath_order/java/src/org/chromium/build/classpath_order/Dummy.java.jinja2 @@ -0,0 +1,8 @@ +// Copyright 2021 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. + +package org.chromium.build.classpath_order; + +public class {{class_name}} { +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn b/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn new file mode 100644 index 0000000000..a28111a66a --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/BUILD.gn @@ -0,0 +1,103 @@ +# Copyright 2020 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. + +import("//build/config/android/rules.gni") +import("//third_party/protobuf/proto_library.gni") + +# The purpose of these targets is test that |deps| satisfies java compilation +# dependencies, and that |import_dirs| allows us to deal with various relative +# imports to other proto dependencies. Although we should strive to avoid using +# |import_dirs| and relative import paths, preferring to use absolute imports +# whenever possible. See https://crbug.com/691451. While this target is +# primarily to test that the Java proto targets build correctly, also build the +# C++ versions of the protos as well. There are currently some configurations of +# Java protos that can be built but will not work for C++, see +# https://crbug.com/1039014, so make sure we don't create any tests that would +# violate that. +group("test_build_protos") { + deps = [ + ":absolute_root_proto", + ":absolute_root_proto_java", + ":relative_root_proto", + ":relative_root_proto_java", + ] +} + +proto_java_library("absolute_root_proto_java") { + proto_path = "//" + import_dirs = [ "relative_dep/" ] + sources = [ + "root/absolute_child.proto", + "root/absolute_root.proto", + ] + deps = [ + ":absolute_dep_proto_java", + ":relative_dep_proto_java", + ] +} + +proto_java_library("relative_root_proto_java") { + proto_path = "root/" + import_dirs = [ + "relative_dep/", + "//", + ] + sources = [ + "root/relative_child.proto", + "root/relative_root.proto", + ] + deps = [ + ":absolute_dep_proto_java", + ":relative_dep_proto_java", + ] +} + +proto_java_library("absolute_dep_proto_java") { + proto_path = "//" + sources = [ "absolute_dep/absolute_dep.proto" ] +} + +proto_java_library("relative_dep_proto_java") { + proto_path = "relative_dep/" + sources = [ "relative_dep/relative_dep.proto" ] +} + +proto_library("absolute_root_proto") { + proto_in_dir = "//" + import_dirs = [ "relative_dep/" ] + sources = [ + "root/absolute_child.proto", + "root/absolute_root.proto", + ] + link_deps = [ + ":absolute_dep_proto", + ":relative_dep_proto", + ] +} + +proto_library("relative_root_proto") { + proto_in_dir = "root/" + import_dirs = [ + "relative_dep/", + "//", + ] + sources = [ + "root/relative_child.proto", + "root/relative_root.proto", + ] + link_deps = [ + ":absolute_dep_proto", + ":relative_dep_proto", + ] +} + +proto_library("absolute_dep_proto") { + proto_in_dir = "//" + sources = [ "absolute_dep/absolute_dep.proto" ] +} + +proto_library("relative_dep_proto") { + proto_in_dir = "relative_dep/" + sources = [ "relative_dep/relative_dep.proto" ] +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto b/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto new file mode 100644 index 0000000000..46dcce7679 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/absolute_dep/absolute_dep.proto @@ -0,0 +1,10 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message AbsoluteDep {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto b/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto new file mode 100644 index 0000000000..600b6ca7fe --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/relative_dep/relative_dep.proto @@ -0,0 +1,10 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message RelativeDep {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto new file mode 100644 index 0000000000..d6a6a13f36 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_child.proto @@ -0,0 +1,10 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message AbsoluteChild {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto new file mode 100644 index 0000000000..3e200978d9 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/absolute_root.proto @@ -0,0 +1,18 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +import "build/config/android/test/proto/root/absolute_child.proto"; +import "build/config/android/test/proto/absolute_dep/absolute_dep.proto"; +import "relative_dep.proto"; + +message AbsoluteRoot { + optional AbsoluteChild absolute_child = 1; + optional AbsoluteDep absolute_dep = 2; + optional RelativeDep relative_dep = 3; +} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto b/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto new file mode 100644 index 0000000000..10f7ed4277 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/relative_child.proto @@ -0,0 +1,10 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +message RelativeChild {} diff --git a/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto b/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto new file mode 100644 index 0000000000..a37a268b4f --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/proto/root/relative_root.proto @@ -0,0 +1,18 @@ +// Copyright 2020 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. + +syntax = "proto2"; + +package build.config.android.test; +option java_package = "build.config.android.test"; + +import "relative_child.proto"; +import "build/config/android/test/proto/absolute_dep/absolute_dep.proto"; +import "relative_dep.proto"; + +message RelativeRoot { + optional RelativeChild relative_child = 1; + optional AbsoluteDep absolute_dep = 2; + optional RelativeDep relative_dep = 3; +} diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn b/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn new file mode 100644 index 0000000000..4a063d2215 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright 2020 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. + +import("//build/config/android/rules.gni") + +# Tests for 'resource_overlay' parameter in android_resources() template. + +template("test_resources") { + jinja_template_resources(target_name) { + forward_variables_from(invoker, "*") + testonly = true + variables = [ + "resource_name=$resource_name", + "resource_value=$resource_value", + ] + res_dir = "java/res_template" + resources = [ "java/res_template/values/values.xml" ] + } +} + +test_resources("dependency_tagged_dependency_resources") { + resource_overlay = true + resource_name = "resource_overlay_dependency_tagged_secret" + resource_value = 41 +} + +test_resources("dependency_tagged_root_resources") { + resource_name = "resource_overlay_dependency_tagged_secret" + resource_value = 42 + deps = [ ":dependency_tagged_dependency_resources" ] +} + +test_resources("root_tagged_dependency_resources") { + resource_name = "resource_overlay_root_tagged_secret" + resource_value = 41 +} + +test_resources("root_tagged_root_resources") { + resource_overlay = true + resource_name = "resource_overlay_root_tagged_secret" + resource_value = 42 + deps = [ ":root_tagged_dependency_resources" ] +} + +android_library("javatests") { + testonly = true + sources = [ + "java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java", + ] + resources_package = "org.chromium.build.resource_overlay" + deps = [ + ":dependency_tagged_root_resources", + ":root_tagged_root_resources", + "//base:base_java_test_support", + "//third_party/android_support_test_runner:runner_java", + "//third_party/androidx:androidx_test_runner_java", + "//third_party/junit", + ] +} diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml new file mode 100644 index 0000000000..973f855206 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/res_template/values/values.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. +--> + +<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <integer name="{{resource_name}}">{{resource_value}}</integer> +</resources>
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java new file mode 100644 index 0000000000..794cafac53 --- /dev/null +++ b/third_party/libwebrtc/build/config/android/test/resource_overlay/java/src/org/chromium/build/resource_overlay/ResourceOverlayTest.java @@ -0,0 +1,49 @@ +// Copyright 2020 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. + +package org.chromium.build.resource_overlay; + +import static org.junit.Assert.assertEquals; + +import android.content.res.Resources; +import android.support.test.InstrumentationRegistry; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; + +/** + * Test for resource_overlay parameter in android_resources() build rule. + */ +@RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) +public class ResourceOverlayTest { + /** + * Test that when an android_resources() target with resource_overlay=false has a resource with + * the same name but a different value as a dependency with resource_overlay=true that the value + * of the resource in the dependency is used. + */ + @Test + @SmallTest + public void testDependencyTagged() { + Resources resources = InstrumentationRegistry.getTargetContext().getResources(); + assertEquals(41, resources.getInteger(R.integer.resource_overlay_dependency_tagged_secret)); + } + + /** + * Test that when an android_resources() target with resource_overlay=true has a resource with + * the same name but different value as one of its dependencies that the value of resource in + * the target with resource_overlay=true is used. + */ + @Test + @SmallTest + public void testRootTagged() { + Resources resources = InstrumentationRegistry.getTargetContext().getResources(); + assertEquals(42, resources.getInteger(R.integer.resource_overlay_root_tagged_secret)); + } +} diff --git a/third_party/libwebrtc/build/config/apple/OWNERS b/third_party/libwebrtc/build/config/apple/OWNERS new file mode 100644 index 0000000000..6f3324f07c --- /dev/null +++ b/third_party/libwebrtc/build/config/apple/OWNERS @@ -0,0 +1 @@ +file://build/apple/OWNERS diff --git a/third_party/libwebrtc/build/config/apple/sdk_info.py b/third_party/libwebrtc/build/config/apple/sdk_info.py new file mode 100644 index 0000000000..fea680101b --- /dev/null +++ b/third_party/libwebrtc/build/config/apple/sdk_info.py @@ -0,0 +1,177 @@ +# Copyright 2014 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. + +from __future__ import print_function + +import argparse +import doctest +import itertools +import os +import plistlib +import re +import subprocess +import sys + +if sys.version_info.major < 3: + basestring_compat = basestring +else: + basestring_compat = str + +# src directory +ROOT_SRC_DIR = os.path.dirname( + os.path.dirname(os.path.dirname(os.path.dirname( + os.path.realpath(__file__))))) + +# This script prints information about the build system, the operating +# system and the iOS or Mac SDK (depending on the platform "iphonesimulator", +# "iphoneos" or "macosx" generally). + + +def LoadPList(path): + """Loads Plist at |path| and returns it as a dictionary.""" + # Cloned from //build/apple/plist_util.py. + if sys.version_info.major == 2: + return plistlib.readPlist(path) + with open(path, 'rb') as f: + return plistlib.load(f) + + +def SplitVersion(version): + """Splits the Xcode version to 3 values. + + >>> list(SplitVersion('8.2.1.1')) + ['8', '2', '1'] + >>> list(SplitVersion('9.3')) + ['9', '3', '0'] + >>> list(SplitVersion('10.0')) + ['10', '0', '0'] + """ + version = version.split('.') + return itertools.islice(itertools.chain(version, itertools.repeat('0')), 0, 3) + + +def FormatVersion(version): + """Converts Xcode version to a format required for DTXcode in Info.plist + + >>> FormatVersion('8.2.1') + '0821' + >>> FormatVersion('9.3') + '0930' + >>> FormatVersion('10.0') + '1000' + """ + major, minor, patch = SplitVersion(version) + return ('%2s%s%s' % (major, minor, patch)).replace(' ', '0') + + +def FillXcodeVersion(settings, developer_dir): + """Fills the Xcode version and build number into |settings|.""" + if developer_dir: + xcode_version_plist_path = os.path.join(developer_dir, + 'Contents/version.plist') + version_plist = LoadPList(xcode_version_plist_path) + settings['xcode_version'] = FormatVersion( + version_plist['CFBundleShortVersionString']) + settings['xcode_version_int'] = int(settings['xcode_version'], 10) + settings['xcode_build'] = version_plist['ProductBuildVersion'] + return + + lines = subprocess.check_output(['xcodebuild', + '-version']).decode('UTF-8').splitlines() + settings['xcode_version'] = FormatVersion(lines[0].split()[-1]) + settings['xcode_version_int'] = int(settings['xcode_version'], 10) + settings['xcode_build'] = lines[-1].split()[-1] + + +def FillMachineOSBuild(settings): + """Fills OS build number into |settings|.""" + machine_os_build = subprocess.check_output(['sw_vers', '-buildVersion' + ]).decode('UTF-8').strip() + settings['machine_os_build'] = machine_os_build + + +def FillSDKPathAndVersion(settings, platform, xcode_version): + """Fills the SDK path and version for |platform| into |settings|.""" + settings['sdk_path'] = subprocess.check_output( + ['xcrun', '-sdk', platform, '--show-sdk-path']).decode('UTF-8').strip() + settings['sdk_version'] = subprocess.check_output( + ['xcrun', '-sdk', platform, + '--show-sdk-version']).decode('UTF-8').strip() + settings['sdk_platform_path'] = subprocess.check_output( + ['xcrun', '-sdk', platform, + '--show-sdk-platform-path']).decode('UTF-8').strip() + settings['sdk_build'] = subprocess.check_output( + ['xcrun', '-sdk', platform, + '--show-sdk-build-version']).decode('UTF-8').strip() + settings['toolchains_path'] = os.path.join( + subprocess.check_output(['xcode-select', + '-print-path']).decode('UTF-8').strip(), + 'Toolchains/XcodeDefault.xctoolchain') + + +def CreateXcodeSymlinkAt(src, dst): + """Create symlink to Xcode directory at target location.""" + + if not os.path.isdir(dst): + os.makedirs(dst) + + dst = os.path.join(dst, os.path.basename(src)) + updated_value = '//' + os.path.relpath(dst, ROOT_SRC_DIR) + + # Update the symlink only if it is different from the current destination. + if os.path.islink(dst): + current_src = os.readlink(dst) + if current_src == src: + return updated_value + os.unlink(dst) + sys.stderr.write('existing symlink %s points %s; want %s. Removed.' % + (dst, current_src, src)) + os.symlink(src, dst) + return updated_value + + +if __name__ == '__main__': + doctest.testmod() + + parser = argparse.ArgumentParser() + parser.add_argument("--developer_dir", dest="developer_dir", required=False) + parser.add_argument("--get_sdk_info", + action="store_true", + dest="get_sdk_info", + default=False, + help="Returns SDK info in addition to xcode info.") + parser.add_argument("--get_machine_info", + action="store_true", + dest="get_machine_info", + default=False, + help="Returns machine info in addition to xcode info.") + parser.add_argument("--create_symlink_at", + action="store", + dest="create_symlink_at", + help="Create symlink of SDK at given location and " + "returns the symlinked paths as SDK info instead " + "of the original location.") + args, unknownargs = parser.parse_known_args() + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + + if len(unknownargs) != 1: + sys.stderr.write('usage: %s [iphoneos|iphonesimulator|macosx]\n' % + os.path.basename(sys.argv[0])) + sys.exit(1) + + settings = {} + if args.get_machine_info: + FillMachineOSBuild(settings) + FillXcodeVersion(settings, args.developer_dir) + if args.get_sdk_info: + FillSDKPathAndVersion(settings, unknownargs[0], settings['xcode_version']) + + for key in sorted(settings): + value = settings[key] + if args.create_symlink_at and '_path' in key: + value = CreateXcodeSymlinkAt(value, args.create_symlink_at) + if isinstance(value, basestring_compat): + value = '"%s"' % value + print('%s=%s' % (key, value)) diff --git a/third_party/libwebrtc/build/config/apple/symbols.gni b/third_party/libwebrtc/build/config/apple/symbols.gni new file mode 100644 index 0000000000..dd1d796fa6 --- /dev/null +++ b/third_party/libwebrtc/build/config/apple/symbols.gni @@ -0,0 +1,30 @@ +# Copyright 2016 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. + +import("//build/config/chrome_build.gni") +import("//build/config/sanitizers/sanitizers.gni") + +# This file declares arguments and configs that control whether dSYM debug +# info is produced and whether build products are stripped. + +declare_args() { + # Produce dSYM files for targets that are configured to do so. dSYM + # generation is controlled globally as it is a linker output (produced via + # the //build/toolchain/apple/linker_driver.py. Enabling this will result in + # all shared library, loadable module, and executable targets having a dSYM + # generated. + enable_dsyms = is_official_build || using_sanitizer + + # Strip symbols from linked targets by default. If this is enabled, the + # //build/config/mac:strip_all config will be applied to all linked targets. + # If custom stripping parameters are required, remove that config from a + # linked target and apply custom -Wcrl,strip flags. See + # //build/toolchain/apple/linker_driver.py for more information. + enable_stripping = is_official_build +} + +# Save unstripped copies of targets with a ".unstripped" suffix. This is +# useful to preserve the original output when enable_stripping=true but +# we're not actually generating real dSYMs. +save_unstripped_output = enable_stripping && !enable_dsyms diff --git a/third_party/libwebrtc/build/config/arm.gni b/third_party/libwebrtc/build/config/arm.gni new file mode 100644 index 0000000000..a0ada42453 --- /dev/null +++ b/third_party/libwebrtc/build/config/arm.gni @@ -0,0 +1,136 @@ +# Copyright 2014 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. + +import("//build/config/v8_target_cpu.gni") + +# These are primarily relevant in target_cpu == "arm" contexts, where +# ARM code is being compiled. But they can also be relevant in the +# other contexts when the code will change its behavior based on the +# cpu it wants to generate code for. +if (target_cpu == "arm" || v8_target_cpu == "arm") { + declare_args() { + # Version of the ARM processor when compiling on ARM. Ignored on non-ARM + # platforms. + arm_version = 7 + + # The ARM architecture. This will be a string like "armv6" or "armv7-a". + # An empty string means to use the default for the arm_version. + arm_arch = "" + + # The ARM floating point hardware. This will be a string like "neon" or + # "vfpv3". An empty string means to use the default for the arm_version. + arm_fpu = "" + + # The ARM variant-specific tuning mode. This will be a string like "armv6" + # or "cortex-a15". An empty string means to use the default for the + # arm_version. + arm_tune = "" + + # Whether to use the neon FPU instruction set or not. + arm_use_neon = "" + + # Whether to enable optional NEON code paths. + arm_optionally_use_neon = false + + # Thumb is a reduced instruction set available on some ARM processors that + # has increased code density. + arm_use_thumb = true + } + + if (current_os == "android" || target_os == "android") { + arm_float_abi = "softfp" + } else { + declare_args() { + # The ARM floating point mode. This is either the string "hard", "soft", + # or "softfp". An empty string means to use the default one for the + # arm_version. + arm_float_abi = "" + } + } + assert(arm_float_abi == "" || arm_float_abi == "hard" || + arm_float_abi == "soft" || arm_float_abi == "softfp") + + if (arm_use_neon == "") { + if (current_os == "linux" && target_cpu != v8_target_cpu) { + # Don't use neon on V8 simulator builds as a default. + arm_use_neon = false + } else { + arm_use_neon = true + } + } + + if (arm_version == 6) { + if (arm_arch == "") { + arm_arch = "armv6" + } + if (arm_tune != "") { + arm_tune = "" + } + if (arm_float_abi == "") { + arm_float_abi = "softfp" + } + if (arm_fpu == "") { + arm_fpu = "vfp" + } + arm_use_thumb = false + arm_use_neon = false + } else if (arm_version == 7) { + if (arm_arch == "") { + arm_arch = "armv7-a" + } + if (arm_tune == "") { + arm_tune = "generic-armv7-a" + } + + if (arm_float_abi == "") { + if (current_os == "linux" && target_cpu != v8_target_cpu) { + # Default to the same as Android for V8 simulator builds. + arm_float_abi = "softfp" + } else { + arm_float_abi = "hard" + } + } + + if (arm_fpu == "") { + if (arm_use_neon) { + arm_fpu = "neon" + } else { + arm_fpu = "vfpv3-d16" + } + } + } else if (arm_version == 8) { + if (arm_arch == "") { + arm_arch = "armv8-a" + } + if (arm_tune == "") { + arm_tune = "generic-armv8-a" + } + + if (arm_float_abi == "") { + arm_float_abi = "hard" + } + + if (arm_fpu == "") { + if (arm_use_neon) { + arm_fpu = "neon" + } else { + arm_fpu = "vfpv3-d16" + } + } + } +} else if (target_cpu == "arm64" || v8_target_cpu == "arm64") { + # arm64 supports only "hard". + arm_float_abi = "hard" + arm_use_neon = true + declare_args() { + # Enables the new Armv8 branch protection features. Valid strings are: + # - "standard": Enables both Pointer Authentication Code (featured in + # Armv8.3) and Branch Target Identification (Armv8.5). + # - "none": No branch protection. + arm_control_flow_integrity = "none" + } + assert(arm_control_flow_integrity == "none" || + arm_control_flow_integrity == "standard", + "Invalid branch protection option") +} diff --git a/third_party/libwebrtc/build/config/buildflags_paint_preview.gni b/third_party/libwebrtc/build/config/buildflags_paint_preview.gni new file mode 100644 index 0000000000..7129e76634 --- /dev/null +++ b/third_party/libwebrtc/build/config/buildflags_paint_preview.gni @@ -0,0 +1,16 @@ +# Copyright 2019 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. + +import("//build/config/chromecast_build.gni") +import("//build/config/features.gni") + +declare_args() { + # Enable basic paint preview support. Does not work on iOS or Fuchsia. Should + # not be included with Chromecast. Not ready for shipping builds yet so + # include in unofficial builds. + # Used by //components/paint_preview and //third_party/harfbuzz-ng. + # TODO(bug/webrtc:11223) Move back this file in //components/paint_preview/ + # once WebRTC doesn't roll harfbuzz-ng anymore, for consistency sake. + enable_paint_preview = !is_chromecast && !is_ios && !is_fuchsia +} diff --git a/third_party/libwebrtc/build/config/c++/BUILD.gn b/third_party/libwebrtc/build/config/c++/BUILD.gn new file mode 100644 index 0000000000..e7ed69ec81 --- /dev/null +++ b/third_party/libwebrtc/build/config/c++/BUILD.gn @@ -0,0 +1,145 @@ +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/dcheck_always_on.gni") +import("//buildtools/deps_revisions.gni") + +assert(use_custom_libcxx, "should only be used if use_custom_libcxx is set") + +declare_args() { + # lldb pretty printing only works when libc++ is built in the __1 (or __ndk1) + # namespaces. For pretty printing to work out-of-the-box on Mac (where lldb + # is primarily used), this flag is set to false to build with the __1 + # namespace (to maintain ABI compatibility, this implies building without + # _LIBCPP_ABI_UNSTABLE). This is not necessary on non-component builds + # because we leave the ABI version set to __1 in that case because libc++ + # symbols are not exported. + # TODO(thomasanderson): Set this to true by default once rL352899 is available + # in MacOS's lldb. + libcxx_abi_unstable = !(is_apple && is_debug && is_component_build) +} + +# TODO(xiaohuic): https://crbug/917533 Crashes on internal ChromeOS build. +# Do unconditionally once the underlying problem is fixed. +if (is_chromeos_ash && is_chrome_branded) { + libcxx_abi_unstable = false +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is specific to libc++. Please see that target for advice on what should +# go in :runtime_library vs. :compiler. +config("runtime_library") { + cflags = [] + cflags_cc = [] + defines = [] + include_dirs = [] + ldflags = [] + libs = [] + + if (libcxx_abi_unstable) { + defines += [ "_LIBCPP_ABI_UNSTABLE" ] + } + + if (libcxx_is_shared) { + # When libcxx_is_shared is true, symbols from libc++.so are exported for + # all DSOs to use. If the system libc++ gets loaded (indirectly through + # a system library), then it will conflict with our libc++.so. Add a + # custom ABI version if we're building with _LIBCPP_ABI_UNSTABLE to avoid + # conflicts. + # + # Windows doesn't need to set _LIBCPP_ABI_VERSION since there's no system + # C++ library we could conflict with. + if (libcxx_abi_unstable && !is_win) { + defines += [ "_LIBCPP_ABI_VERSION=Cr" ] + } + } else { + # Don't leak any symbols on a static build. + defines += [ "_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS" ] + if (!export_libcxxabi_from_executables && !is_win) { + defines += [ "_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS" ] + } + } + + defines += [ "_LIBCPP_ENABLE_NODISCARD" ] + + include_dirs += [ "//buildtools/third_party/libc++" ] + + # Work around a symbol conflict between GRPC and the Fuchsia SDK. + # TODO(crbug.com/1166970): Remove this when resolved. + if (is_fuchsia) { + defines += [ "_LIBCPP_NO_NATIVE_SEMAPHORES" ] + } + + # The Windows component build fails to link with libc++'s debug mode. See + # https://crbug.com/923166#c33, https://crbug.com/923166#c44, and + # https://llvm.org/PR41018. + if (!(is_win && is_component_build)) { + # libc++ has two levels of debug mode. Setting _LIBCPP_DEBUG to zero + # enables most assertions. Setting it to one additionally enables iterator + # debugging. See https://libcxx.llvm.org/docs/DesignDocs/DebugMode.html + if (enable_iterator_debugging) { + defines += [ "_LIBCPP_DEBUG=1" ] + } else if (is_debug || dcheck_always_on) { + defines += [ "_LIBCPP_DEBUG=0" ] + } + } + + if (is_win) { + # Intentionally not using libc++abi on Windows because libc++abi only + # implements the Itanium C++ ABI, and not the Microsoft ABI which we use on + # Windows (and we need to use in order to interoperate correctly with COM + # among other things). + assert(!export_libcxxabi_from_executables, + "Don't use libcxxabi on Windows.") + + cflags_cc += + [ "-I" + rebase_path("$libcxx_prefix/include", root_build_dir) ] + + # Prevent libc++ from embedding linker flags to try to automatically link + # against its runtime library. This is unnecessary with our build system, + # and can also result in build failures if libc++'s name for a library + # does not match ours. + defines += [ "_LIBCPP_NO_AUTO_LINK" ] + + # Add a debug visualizer for Microsoft's debuggers so that they can display + # libc++ types well. + if (libcxx_natvis_include) { + # chrome.natvis listed as an input in //buildtools/third_party/libc++ to + # guarantee relinking on changes. + ldflags += [ "/NATVIS:" + rebase_path("libc++.natvis", root_build_dir) ] + } + } else { + cflags_cc += [ + "-nostdinc++", + "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir), + "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir), + ] + cflags_objcc = cflags_cc + + defines += [ "CR_LIBCXX_REVISION=$libcxx_revision" ] + + # Make sure we don't link against the system libstdc++ or libc++. + if (is_clang) { + ldflags += [ "-nostdlib++" ] + } else { + # Gcc has a built-in abs() definition with default visibility. + # If it was not disabled, it would conflict with libc++'s abs() + # with hidden visibility. + cflags += [ "-fno-builtin-abs" ] + + ldflags += [ "-nodefaultlibs" ] + + # Unfortunately, there's no way to disable linking against just libc++ + # (gcc doesn't have -notstdlib++: + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83931); -nodefaultlibs + # removes all of the default libraries, so add back the ones that we need. + libs += [ + "c", + "gcc_s", + "m", + "rt", + ] + } + } +} diff --git a/third_party/libwebrtc/build/config/c++/c++.gni b/third_party/libwebrtc/build/config/c++/c++.gni new file mode 100644 index 0000000000..10a780c19b --- /dev/null +++ b/third_party/libwebrtc/build/config/c++/c++.gni @@ -0,0 +1,81 @@ +# Copyright 2017 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. + +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/sanitizers/sanitizers.gni") + +declare_args() { + # Use in-tree libc++ (buildtools/third_party/libc++ and + # buildtools/third_party/libc++abi) instead of the system C++ library for C++ + # standard library support. + # Don't check in changes that set this to false for more platforms; doing so + # is not supported. + use_custom_libcxx = + is_fuchsia || is_android || is_mac || is_linux || is_chromeos_lacros || + (is_ios && !use_xcode_clang) || (is_win && is_clang) || + (is_chromeos && default_toolchain != "//build/toolchain/cros:target") + + # Use libc++ instead of stdlibc++ when using the host_cpu toolchain, even if + # use_custom_libcxx is false. This is useful for cross-compiles where a custom + # toolchain for the target_cpu has been set as the default toolchain, but + # use_custom_libcxx should still be true when building for the host. The + # expected usage is to set use_custom_libcxx=false and + # use_custom_libcxx_for_host=true in the passed in buildargs. + use_custom_libcxx_for_host = false + + # Builds libcxx Natvis into the symbols for type visualization. + # Set to false to workaround http://crbug.com/966676 and + # http://crbug.com/966687. + libcxx_natvis_include = true + + # When set, enables libc++ debug mode with iterator debugging. + # + # Iterator debugging is generally useful for catching bugs. But it can + # introduce extra locking to check the state of an iterator against the state + # of the current object. For iterator- and thread-heavy code, this can + # significantly slow execution - two orders of magnitude slowdown has been + # seen (crbug.com/903553) and iterator debugging also slows builds by making + # generation of snapshot_blob.bin take ~40-60 s longer. Therefore this + # defaults to off. + enable_iterator_debugging = false +} + +use_custom_libcxx = + use_custom_libcxx || (use_custom_libcxx_for_host && !is_a_target_toolchain) +use_custom_libcxx = use_custom_libcxx && !is_nacl + +declare_args() { + # WARNING: Setting this to a non-default value is highly discouraged. + # If true, libc++ will be built as a shared library; otherwise libc++ will be + # linked statically. Setting this to something other than the default is + # unsupported and can be broken by libc++ rolls. Note that if this is set to + # true, you must also set libcxx_abi_unstable=false, which is bad for + # performance and memory use. + libcxx_is_shared = use_custom_libcxx && is_component_build +} + +# libc++abi needs to be exported from executables to be picked up by shared +# libraries on certain instrumented builds. +export_libcxxabi_from_executables = + use_custom_libcxx && !is_apple && !is_win && !is_component_build && + (is_asan || is_ubsan_vptr) + +# On Android, many shared libraries get loaded from the context of a JRE. In +# this case, there's no "main executable" to export libc++abi from. We could +# export libc++abi from each "toplevel" shared library instead, but that would +# require adding an explicit dependency for each one, and might introduce +# subtle, hard-to-fix problems down the line if the dependency is missing. +# +# export_libcxxabi_from_executables was added to avoid having an RPATH set in +# static sanitizer builds just for executables to find libc++. But on Android, +# the Bionic dynamic loader doesn't even look at RPATH; instead, LD_LIBRARY_PATH +# is set for tests. Because of this, we make libc++ a shared library on android +# since it should get loaded properly. +if (is_android && export_libcxxabi_from_executables) { + export_libcxxabi_from_executables = false + libcxx_is_shared = true +} + +libcxx_prefix = "//buildtools/third_party/libc++/trunk" +libcxxabi_prefix = "//buildtools/third_party/libc++abi/trunk" diff --git a/third_party/libwebrtc/build/config/c++/libc++.natvis b/third_party/libwebrtc/build/config/c++/libc++.natvis new file mode 100644 index 0000000000..9a49a2935a --- /dev/null +++ b/third_party/libwebrtc/build/config/c++/libc++.natvis @@ -0,0 +1,435 @@ +<?xml version="1.0" encoding="utf-8" ?> +<AutoVisualizer + xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + + <!-- libc++'s __compressed_pair is an internal type used pervasively for + doing the empty base class optimization. + + __compressed_pair<U,V> derives from __compressed_pair_elem<U,0> and + __compressed_pair_elem<V,1>. __compressed_pair_elem<T> is specialized on + a 3rd template parameter: + * if T is empty and non-final the 3rd param is 1 and it derives from T + * else it has a member variable __value_ of type T + --> + <Type Name="std::__1::__compressed_pair_elem<*,*,0>"> + <DisplayString>{__value_}</DisplayString> + <Expand> + <ExpandedItem>__value_</ExpandedItem> + </Expand> + </Type> + <Type Name="std::__1::__compressed_pair_elem<*,*,1>"> + <DisplayString>{*($T1*)this}</DisplayString> + <Expand> + <ExpandedItem>*($T1*)this</ExpandedItem> + </Expand> + </Type> + + <Type Name="std::__1::array<*,*>"> + <DisplayString>{{ size={$T2} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>$T2</Size> + <ValuePointer>__elems_</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <!--libc++'s short string optimization: + A basic_string is 3 size_t words long. In the "alternate string layout" + that we use, they are: pointer to data, size, capacity. + (In the normal layout, it's capacity, size, data instead.) + If a string is short enough that it fits in these three size_ts instead, + the string data is stored inline in these 3 words, with the last byte of + the storage storing the length of the string. + The highest bit of the "capacity" word is set for normal, "long" strings, + and that bit needs to be masked out to know the real capacity. + If this bit is not set, the string data is stored inline. + (In the normal layout, if the lowest bit in the first byte is set, + it's a "long" string, requiring a long string to always have even + capacity. A short string here stores its length in the first byte + and the inline data in the remaining storage.) + --> + + <Type Name="std::__1::basic_string<char,*>"> + <!--<Intrinsic Name="is_long" + Expression="((__rep*)&__r_)->__s.__size_ & 0x80" />--> + <!-- The above doesn't work because of https://llvm.org/PR41615 + TODO(thakis): Now that we have clang r362038, try the above approach + again. + The below assumes the alternate string layout and little endianness :/ + --> + <Intrinsic Name="is_long" + Expression="*(((char*)this) + 3*sizeof(size_t) - 1) & 0x80" /> + <DisplayString Condition="is_long()">{*(char**)this}</DisplayString> + <DisplayString Condition="!is_long()">{(char*)this}</DisplayString> + <StringView Condition="is_long()">*(char**)this</StringView> + <StringView Condition="!is_long()">(char*)this</StringView> + <Expand> + <Item Name="[size]" Condition="is_long()" + ExcludeView="simple">((size_t*)this)[1]</Item> + <Item Name="[size]" Condition="!is_long()" + ExcludeView="simple">*(((char*)this) + 3*sizeof(size_t) - 1)</Item> + <Item Name="[capacity]" Condition="is_long()" ExcludeView="simple"> + ((size_t*)this)[2] & (~((size_t)0) >> 1) + </Item> + <Item Name="[capacity]" Condition="!is_long()" + ExcludeView="simple">22</Item> + <ArrayItems> + <Size Condition="is_long()">((size_t*)this)[1]</Size> + <Size Condition="!is_long()"> + *(((char*)this) + 3*sizeof(size_t) - 1) + </Size> + <ValuePointer Condition="is_long()">*(char**)this</ValuePointer> + <ValuePointer Condition="!is_long()">(char*)this</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="std::__1::basic_string<wchar_t,*>"> + <Intrinsic Name="is_long" + Expression="*(((char*)this) + 3*sizeof(size_t) - 1) & 0x80" /> + <DisplayString Condition="is_long()">{*(wchar_t**)this}</DisplayString> + <DisplayString Condition="!is_long()">{(wchar_t*)this}</DisplayString> + <StringView Condition="is_long()">*(wchar_t**)this</StringView> + <StringView Condition="!is_long()">(wchar_t*)this</StringView> + <Expand> + <Item Name="[size]" Condition="is_long()" + ExcludeView="simple">((size_t*)this)[1]</Item> + <Item Name="[size]" Condition="!is_long()" + ExcludeView="simple">*(((char*)this) + 3*sizeof(size_t) - 1)</Item> + <Item Name="[capacity]" Condition="is_long()" ExcludeView="simple"> + ((size_t*)this)[2] & (~((size_t)0) >> 1) + </Item> + <Item Name="[capacity]" Condition="!is_long()" + ExcludeView="simple">10</Item> + <ArrayItems> + <Size Condition="is_long()">((size_t*)this)[1]</Size> + <Size Condition="!is_long()"> + *(((char*)this) + 3*sizeof(size_t) - 1) + </Size> + <ValuePointer Condition="is_long()">*(wchar_t**)this</ValuePointer> + <ValuePointer Condition="!is_long()">(wchar_t*)this</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="std::__1::deque<*,*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__size_" /> + <Intrinsic Name="block_size" + Expression="sizeof($T1) < 256 ? 4096 / sizeof($T1) : 16" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <IndexListItems> + <Size>size()</Size> + <ValueNode> + *(*(__map_.__begin_ + ($i + __start_) / block_size()) + + ($i + __start_) % block_size()) + </ValueNode> + </IndexListItems> + </Expand> + </Type> + + <Type Name="std::__1::forward_list<*>"> + <Intrinsic Name="head" + Expression="((__node_pointer)&__before_begin_)->__next_" /> + <DisplayString Condition="head() == 0">empty</DisplayString> + <DisplayString Condition="head() != 0">non-empty</DisplayString> + <Expand> + <LinkedListItems> + <HeadPointer>head()</HeadPointer> + <NextPointer>__next_</NextPointer> + <ValueNode>__value_</ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <!-- Note: Not in __1! But will win over the one in stl.natvis --> + <Type Name="std::initializer_list<*>"> + <DisplayString>{{ size={__size_} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>__size_</Size> + <ValuePointer>__begin_</ValuePointer> + </ArrayItems> + </Expand> + </Type> + + <Type Name="std::__1::list<*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__size_alloc_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <LinkedListItems> + <Size>size()</Size> + <HeadPointer>__end_.__next_</HeadPointer> + <NextPointer>__next_</NextPointer> + <ValueNode> + ((std::__1::list<$T1,$T2>::__node_pointer)this) + ->__value_ + </ValueNode> + </LinkedListItems> + </Expand> + </Type> + + <Type Name="std::__1::map<*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <Item Name="[size]">size()</Item> + <TreeItems> + <Size>size()</Size> + <HeadPointer> + ((__node_pointer)&__tree_.__pair1_)->__left_ + </HeadPointer> + <LeftPointer> + ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__left_ + </LeftPointer> + <RightPointer> + ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__right_ + </RightPointer> + <ValueNode> + ((std::__1::map<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__value_.__cc + </ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::__1::multimap<*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <Item Name="[size]">size()</Item> + <TreeItems> + <Size>size()</Size> + <HeadPointer> + ((__node_pointer)&__tree_.__pair1_)->__left_ + </HeadPointer> + <LeftPointer> + ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__left_ + </LeftPointer> + <RightPointer> + ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__right_ + </RightPointer> + <ValueNode> + ((std::__1::multimap<$T1,$T2,$T3,$T4>::__node_pointer)this) + ->__value_.__cc + </ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::__1::multiset<*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <Item Name="[size]">size()</Item> + <TreeItems> + <Size>size()</Size> + <HeadPointer> + ((__base::__node_pointer)&__tree_.__pair1_)->__left_ + </HeadPointer> + <LeftPointer> + ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__left_ + </LeftPointer> + <RightPointer> + ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__right_ + </RightPointer> + <ValueNode> + ((std::__1::multiset<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__value_ + </ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::__1::priority_queue<*>"> + <DisplayString>{c}</DisplayString> + <Expand> + <ExpandedItem>c</ExpandedItem> + <Item Name="[comp]">comp</Item> + </Expand> + </Type> + + <Type Name="std::__1::set<*>"> + <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <Item Name="[size]">size()</Item> + <TreeItems> + <Size>size()</Size> + <HeadPointer> + ((__base::__node_pointer)&__tree_.__pair1_)->__left_ + </HeadPointer> + <LeftPointer> + ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__left_ + </LeftPointer> + <RightPointer> + ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__right_ + </RightPointer> + <ValueNode> + ((std::__1::set<$T1,$T2,$T3>::__base::__node_pointer)this) + ->__value_ + </ValueNode> + </TreeItems> + </Expand> + </Type> + + <Type Name="std::__1::stack<*>"> + <AlternativeType Name="std::__1::queue<*>" /> + <DisplayString>{c}</DisplayString> + <Expand> + <ExpandedItem>c</ExpandedItem> + </Expand> + </Type> + + <Type Name="std::__1::__tuple_leaf<*,*,0>"> + <DisplayString>{__value_}</DisplayString> + </Type> + + <Type Name="std::__1::tuple<>"> + <DisplayString>()</DisplayString> + </Type> + + <Type Name="std::__1::tuple<*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_}, {(std::__1::__tuple_leaf<6,$T7,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> + <Item Name="[6]">(std::__1::__tuple_leaf<6,$T7,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::unique_ptr<*>"> + <Intrinsic Name="value" Expression="*($T1**)&__ptr_" /> + <SmartPointer Usage="Minimal">value()</SmartPointer> + <DisplayString Condition="value() == 0">empty</DisplayString> + <DisplayString Condition="value() != 0"> + unique_ptr {value()}</DisplayString> + <Expand> + <Item Condition="value() != 0" Name="[ptr]">value()</Item> + </Expand> + </Type> + +<Type Name="std::__1::unordered_map<*>"> + <AlternativeType Name="std::__1::unordered_multimap<*>" /> + <AlternativeType Name="std::__1::unordered_multiset<*>" /> + <AlternativeType Name="std::__1::unordered_set<*>" /> + <Intrinsic Name="size" Expression="*(size_type*)&__table_.__p2_" /> + <Intrinsic Name="bucket_count" + Expression="*(size_type*)& + ((__table::__bucket_list_deleter*) + ((void**)&__table_.__bucket_list_ + 1)) + ->__data_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <Item Name="[bucket_count]">bucket_count()</Item> + <Item Name="[load_factor]"> + bucket_count() != 0 ? (float)size() / bucket_count() : 0.f</Item> + <Item Name="[max_load_factor]">*(float*)&__table_.__p3_</Item> + <!-- Use CustomListItems instead of LinkedListItems because we + need to cast to __table::__node_pointer and LinkedListItems + evaluates <Value> in the context of the node, not of the container, + so we'd have to say std::unordered_map<$T1,...>::__table::__node_pointer + and then we couldn't share this <Type> between unordered_(multi)map + and unordered_(multi)set. --> + <CustomListItems> + <Variable Name="node" + InitialValue="*(__table::__next_pointer*)&__table_.__p1_" /> + <Size>size()</Size> + <Loop> + <Item>(*(__table::__node_pointer*)&node)->__value_</Item> + <Exec>node = node->__next_</Exec> + </Loop> + </CustomListItems> + </Expand> + </Type> + <!-- This is the node __value_ of an unordered_(multi)map. Expand it through + a separate formatter instead of in the <Item> expression above so that the + same <Type> works for unordered_(multi)set and unordered_(multi)map. --> + <Type Name="std::__1::__hash_value_type<*>"> + <DisplayString>{__cc}</DisplayString> + <Expand> + <ExpandedItem>__cc</ExpandedItem> + </Expand> + </Type> + + <Type Name="std::__1::vector<*>"> + <Intrinsic Name="size" Expression="__end_ - __begin_" /> + <DisplayString>{{ size={size()} }}</DisplayString> + <Expand> + <ArrayItems> + <Size>size()</Size> + <ValuePointer>__begin_</ValuePointer> + </ArrayItems> + </Expand> + </Type> +</AutoVisualizer> diff --git a/third_party/libwebrtc/build/config/chrome_build.gni b/third_party/libwebrtc/build/config/chrome_build.gni new file mode 100644 index 0000000000..5c51d7f2cc --- /dev/null +++ b/third_party/libwebrtc/build/config/chrome_build.gni @@ -0,0 +1,25 @@ +# 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. + +declare_args() { + # Select the desired branding flavor. False means normal Chromium branding, + # true means official Google Chrome branding (requires extra Google-internal + # resources). + is_chrome_branded = false +} + +declare_args() { + # Refers to the subdirectory for branding in various places including + # chrome/app/theme. + if (is_chrome_branded) { + branding_path_component = "google_chrome" + } else { + branding_path_component = "chromium" + } +} + +declare_args() { + # The path to the BRANDING file in chrome/app/theme. + branding_file_path = "//chrome/app/theme/$branding_path_component/BRANDING" +} diff --git a/third_party/libwebrtc/build/config/chromecast/BUILD.gn b/third_party/libwebrtc/build/config/chromecast/BUILD.gn new file mode 100644 index 0000000000..d52d19cad8 --- /dev/null +++ b/third_party/libwebrtc/build/config/chromecast/BUILD.gn @@ -0,0 +1,95 @@ +# 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. + +import("//build/config/chromecast_build.gni") + +assert(is_chromecast) + +config("static_config") { + if (!is_clang) { + ldflags = [ + # Don't allow visible symbols from libraries that contain + # assembly code with symbols that aren't hidden properly. + # http://b/26390825 + "-Wl,--exclude-libs=libffmpeg.a", + ] + + if (!is_android) { + ldflags += [ + # We want to statically link libstdc++/libgcc on Linux. + # (On Android, libstdc++ and libgcc aren't used.) + "-static-libstdc++", + "-static-libgcc", + ] + } + } +} + +config("ldconfig") { + visibility = [ ":*" ] + configs = [] + + # Chromecast executables depend on several shared libraries in + # /oem_cast_shlib, $ORIGIN, and $ORIGIN/lib. Add these rpaths to each binary. + # This is explicitly disabled in Chrome for security reasons (see comments in + # //build/config/gcc/BUILD.gn), but necessary on Chromecast so that OEM's may + # override the default libraries shipped in the Cast receiver package. + if (target_rpath == "") { + ldflags = [ + "-Wl,-rpath=/oem_cast_shlib", + "-Wl,-rpath=\$ORIGIN/lib", + "-Wl,-rpath=\$ORIGIN", + ] + } else { + ldflags = [ "-Wl,-rpath=${target_rpath}" ] + } + + if (chromecast_branding != "public") { + # Some internal x64 builds need additional rpath and dynamic-linker config. + configs += [ "//chromecast/internal/build/config/ldconfig" ] + } + + # Binaries which don't live in the same directory as Chrome component + # libraries may still depend on them. Explicitly add the component library + # directory to the rpath for the component build. + if (is_component_build) { + ldflags += [ "-Wl,-rpath=/system/chrome" ] + } +} + +config("executable_config") { + configs = [ ":ldconfig" ] + + if (!is_clang && target_cpu == "arm") { + ldflags = [ + # Export stdlibc++ and libgcc symbols to force shlibs to refer to these + # symbols from the executable. + "-Wl,--export-dynamic", + + "-lm", # stdlibc++ requires math.h + + # In case we redefined stdlibc++ symbols (e.g. tc_malloc) + "-Wl,--allow-multiple-definition", + + "-Wl,--whole-archive", + "-l:libstdc++.a", + "-l:libgcc.a", + "-Wl,--no-whole-archive", + ] + + # Despite including libstdc++/libgcc archives, we still need to specify + # static linking for them in order to prevent the executable from having a + # dynamic dependency on them. + configs += [ ":static_config" ] + } +} + +# Shared libaries should not have RPATH or RUNPATH set. This allows the +# shared libs to inherit RPATH from the parent executable that is loading +# the shared library. (See internal b/37514052 for more details.) +config("shared_library_config") { + if (target_cpu == "arm") { + configs = [ ":static_config" ] + } +} diff --git a/third_party/libwebrtc/build/config/chromecast_build.gni b/third_party/libwebrtc/build/config/chromecast_build.gni new file mode 100644 index 0000000000..b309e29d96 --- /dev/null +++ b/third_party/libwebrtc/build/config/chromecast_build.gni @@ -0,0 +1,121 @@ +# 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. + +# The args declared in this file should be referenced by components outside of +# //chromecast. Args needed only in //chromecast should be declared in +# //chromecast/chromecast.gni. +declare_args() { + # Set this true for a Chromecast build. Chromecast builds are supported on + # Linux and Android. + is_chromecast = false + + # If true, IS_CAST_DEBUG_BUILD() will evaluate to 1 in version.h. Otherwise, + # it will evaluate to 0. Overriding this when is_debug=false is useful for + # doing engineering builds. + cast_is_debug = is_debug + + # chromecast_branding is used to include or exclude Google-branded components. + # Set it to "public" for a Chromium build. + chromecast_branding = "public" + + # Set this true for an audio-only Chromecast build. + is_cast_audio_only = false + + # If non empty, rpath of executables is set to this. + # If empty, default value is used. + target_rpath = "" + + # Set true to enable modular_updater. + enable_modular_updater = false +} + +# Note(slan): This arg depends on the value of is_chromecast, and thus must be +# declared in a separate block. These blocks can be combined when/if +# crbug.com/542846 is resolved. +declare_args() { + # True if Chromecast build is targeted for linux desktop. This type of build + # is useful for testing and development, but currently supports only a subset + # of Cast functionality. Though this defaults to true for x86 Linux devices, + # this should be overriden manually for an embedded x86 build. + # TODO(slan): Remove instances of this when x86 is a fully supported platform. + is_cast_desktop_build = is_chromecast && target_os == "linux" && + (target_cpu == "x86" || target_cpu == "x64") + + # Mozilla added: Until upstream's build repo is updated to + # 56e01bffd1de3e5b27e0da87f8019d44aa55a562, we'll default this to false + # to keep the build happy. + is_castos = false +} + +declare_args() { + # True to enable the cast renderer. It is enabled by default for linux and + # android audio only builds. + enable_cast_renderer = is_chromecast && (is_linux || is_chromeos || + (is_cast_audio_only && is_android)) +} + +declare_args() { + # True to enable the cast audio renderer. + enable_cast_audio_renderer = false +} + +# Configures media options for cast. See media/media_options.gni +cast_mojo_media_services = [] +cast_mojo_media_host = "" + +if (enable_cast_audio_renderer) { + if (is_android) { + cast_mojo_media_services = [ + "cdm", + "audio_decoder", + ] + } + + if (!is_cast_audio_only) { + cast_mojo_media_services += [ "video_decoder" ] + } + + if (is_android && is_cast_audio_only) { + cast_mojo_media_host = "browser" + } else { + cast_mojo_media_host = "gpu" + } +} else if (enable_cast_renderer) { + # In this path, mojo media services are hosted in two processes: + # 1. "renderer" and "cdm" run in browser process. This is hard coded in the + # code. + # 2. "video_decoder" runs in the process specified by "cast_mojo_media_host". + cast_mojo_media_services = [ + "cdm", + "renderer", + ] + if (!is_cast_audio_only) { + cast_mojo_media_services += [ "video_decoder" ] + } + + cast_mojo_media_host = "gpu" +} else if (is_android) { + # On Android, all the enabled mojo media services run in the process specified + # by "cast_mojo_media_host". + cast_mojo_media_services = [ + "cdm", + "audio_decoder", + ] + if (!is_cast_audio_only) { + # These are Cast/Android devices with Video capabilities (and GPU) + cast_mojo_media_services += [ "video_decoder" ] + cast_mojo_media_host = "gpu" + } else { + # These are Cast/Android devices with only Audio capabilities (no GPU) + cast_mojo_media_host = "browser" + } +} + +# Assert that Chromecast is being built for a supported platform. +assert(is_linux || is_chromeos || is_android || is_fuchsia || !is_chromecast, + "Chromecast builds are not supported on $target_os") + +# Assert that is_cast_audio_only and is_cast_desktop_build are both false on a +# non-Chromecast build. +assert(is_chromecast || (!is_cast_audio_only && !is_cast_desktop_build)) diff --git a/third_party/libwebrtc/build/config/chromeos/BUILD.gn b/third_party/libwebrtc/build/config/chromeos/BUILD.gn new file mode 100644 index 0000000000..f3dfe70d42 --- /dev/null +++ b/third_party/libwebrtc/build/config/chromeos/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright 2019 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. + +import("//build/config/chromeos/ui_mode.gni") + +assert(is_chromeos_ash) + +declare_args() { + # The location to a file used to dump symbols ordered by Call-Chain Clustering (C3) + # https://research.fb.com/wp-content/uploads/2017/01/cgo2017-hfsort-final1.pdf? + # to a file, used for generating orderfiles in Chrome OS + dump_call_chain_clustering_order = "" +} + +declare_args() { + # Whether or not we're using new pass manager to build and link Chrome + use_new_pass_manager = dump_call_chain_clustering_order != "" +} + +config("print_orderfile") { + if (dump_call_chain_clustering_order != "") { + _output_orderfile = + rebase_path(dump_call_chain_clustering_order, root_build_dir) + ldflags = [ "-Wl,--print-symbol-order=$_output_orderfile" ] + } +} + +config("compiler") { + if (use_new_pass_manager) { + cflags = [ "-fexperimental-new-pass-manager" ] + ldflags = [ "-fexperimental-new-pass-manager" ] + } +} diff --git a/third_party/libwebrtc/build/config/chromeos/args.gni b/third_party/libwebrtc/build/config/chromeos/args.gni new file mode 100644 index 0000000000..99c7d601a3 --- /dev/null +++ b/third_party/libwebrtc/build/config/chromeos/args.gni @@ -0,0 +1,30 @@ +# Copyright 2019 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. + +declare_args() { + # This is used only by Simple Chrome to bind its value to test-runner scripts + # generated at build-time. + cros_board = "" + + # Similar to cros_board above, this used only by test-runner scripts in + # Simple Chrome. + cros_sdk_version = "" +} + +# Ensure that if one is set, the other is as well. +assert(cros_board == "" == (cros_sdk_version == "")) + +declare_args() { + # Determines if we're building for a Chrome OS device (or VM) and not just + # linux-chromeos. NOTE: Most test targets in Chrome expect to run under + # linux-chromeos, so some have compile-time asserts that intentionally fail + # when this build flag is set. Build and run the tests for linux-chromeos + # instead. + # https://chromium.googlesource.com/chromium/src/+/main/docs/chromeos_build_instructions.md + # https://chromium.googlesource.com/chromiumos/docs/+/main/simple_chrome_workflow.md + is_chromeos_device = false + + # Determines if we run the test in skylab, aka the CrOS labs. + is_skylab = false +} diff --git a/third_party/libwebrtc/build/config/chromeos/rules.gni b/third_party/libwebrtc/build/config/chromeos/rules.gni new file mode 100644 index 0000000000..09f9701a7a --- /dev/null +++ b/third_party/libwebrtc/build/config/chromeos/rules.gni @@ -0,0 +1,510 @@ +# Copyright 2018 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. + +import("//build/config/chrome_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/gclient_args.gni") +import("//build/config/python.gni") +import("//build/util/generate_wrapper.gni") + +assert((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device) + +# Determine the real paths for various items in the SDK, which may be used +# in the 'generate_runner_script' template below. We do so outside the template +# to confine exec_script to a single invocation. +if (cros_sdk_version != "") { + # Ideally these should be maps, however, gn doesn't support map, so using a + # list of list to simulate a map: + # [key1, [value1, value2, ...]], [key2, [value1, value2, ...]], where + # the keys are boards and values are symlinks or symlink targets, and the + # mapping shouldn't be used for anything else. + # + # A sample usage is: + # foreach(m, _symlink_targets_map) { + # if(m[0] == target_key) { + # target_value = m[1] + # } + # } + # + _symlink_map = [] + _symlink_targets_map = [] + + if (is_chromeos_ash) { + _potential_test_boards = [ cros_board ] + } else { + _potential_test_boards = [] + if (cros_boards != "") { + _potential_test_boards += string_split(cros_boards, ":") + } + if (cros_boards_with_qemu_images != "") { + _potential_test_boards += string_split(cros_boards_with_qemu_images, ":") + } + } + + foreach(b, _potential_test_boards) { + _cache_path_prefix = + "//build/cros_cache/chrome-sdk/symlinks/${b}+${cros_sdk_version}" + + _cros_is_vm = false + foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { + if (b == b1) { + _cros_is_vm = true + } + } + + _symlinks = [] + _symlinks = [ + # Tast harness & test data. + rebase_path("${_cache_path_prefix}+chromeos-base/tast-cmd"), + rebase_path("${_cache_path_prefix}+chromeos-base/tast-remote-tests-cros"), + + # Binutils (and other toolchain tools) used to deploy Chrome to the device. + rebase_path( + "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz"), + rebase_path("${_cache_path_prefix}+target_toolchain"), + ] + if (_cros_is_vm) { + # VM-related tools. + _symlinks += [ + rebase_path("${_cache_path_prefix}+sys-firmware/seabios"), + rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz"), + rebase_path("${_cache_path_prefix}+app-emulation/qemu"), + ] + } + _symlink_map += [ [ + b, + _symlinks, + ] ] + } + + _all_symlinks = [] + foreach(m, _symlink_map) { + _all_symlinks += m[1] + } + _all_symlink_targets = + exec_script("//build/get_symlink_targets.py", _all_symlinks, "list lines") + _index = 0 + foreach(m, _symlink_map) { + _symlink_targets = [] + foreach(_, m[1]) { + _symlink_targets += [ _all_symlink_targets[_index] ] + _index += 1 + } + + _symlink_targets_map += [ [ + m[0], + _symlink_targets, + ] ] + } +} + +# Creates a script at $generated_script that can be used to launch a cros VM +# and optionally run a test within it. +# Args: +# test_exe: Name of test binary located in the out dir. This will get copied +# to the VM and executed there. +# tast_attr_expr: Tast expression to pass to local_test_runner on the VM. +# tast_tests: List of Tast tests to run on the VM. Note that when this is +# specified, the target name used to invoke this template will be +# designated as the "name" of this test and will primarly used for test +# results tracking and displaying (eg: flakiness dashboard). +# generated_script: Path to place the generated script. +# deploy_chrome: If true, deploys a locally built chrome located in the root +# build dir to the VM or DUT after launching it. +# deploy_lacros: If true, deploys a locally built Lacros located in the root +# build dir to the VM or DUT after launching it. +# runtime_deps_file: Path to file listing runtime deps for the test. If set, +# all files listed will be copied to the VM before testing. +# skip_generating_board_args: By default, this template generates an '--board' +# arg with corresponding '--flash' or '--use-vm' args for device and vm +# respectively. This argument instructs the template to skip generating +# them, and it's designed for use cases where one builds for one board +# (e.g. amd64-generic), but tests on a different board (e.g. eve). +# tast_vars: A list of "key=value" runtime variable pairs to pass to invoke +# the Tast tests. For more details, please see: +# https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Runtime-variables +template("generate_runner_script") { + forward_variables_from(invoker, + [ + "deploy_chrome", + "deploy_lacros", + "generated_script", + "runtime_deps_file", + "skip_generating_board_args", + "tast_attr_expr", + "tast_tests", + "tast_vars", + "testonly", + "test_exe", + ]) + + if (!defined(skip_generating_board_args)) { + skip_generating_board_args = false + } + + if (skip_generating_board_args) { + # cros_board is not needed, so setting it to empty to avoid being used + # accidentally below. + cros_board = "" + not_needed([ cros_board ]) + } + + if (!defined(deploy_chrome)) { + deploy_chrome = false + } + if (!defined(deploy_lacros)) { + deploy_lacros = false + } + assert(!(deploy_chrome && deploy_lacros), + "deploy_chrome and deploy_lacros are exclusive.") + + is_tast = defined(tast_attr_expr) || defined(tast_tests) + assert(!(is_tast && defined(test_exe)), + "Tast tests are invoked from binaries shipped with the VM image. " + + "There should be no locally built binary needed.") + assert(is_tast || !defined(tast_vars), + "tast_vars is only support for Tast tests") + + # If we're in the cros chrome-sdk (and not the raw ebuild), the test will + # need some additional runtime data located in the SDK cache. + _sdk_data = [] + if (cros_sdk_version != "") { + assert(defined(generated_script), + "Must specify where to place generated test launcher script via " + + "'generated_script'") + + foreach(b, _potential_test_boards) { + _cros_is_vm = false + foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { + if (b == b1) { + _cros_is_vm = true + } + } + + # Determine the real paths for various items in the SDK, which may be used + # in the 'generate_runner_script' template below. + if (is_tast || _cros_is_vm || deploy_chrome) { + _symlink_targets = [] + foreach(m, _symlink_targets_map) { + if (b == m[0]) { + _symlink_targets = [] + _symlink_targets = m[1] + } + } + + if (is_tast) { + # Add tast sdk items. + _sdk_data += [ + _symlink_targets[0], + _symlink_targets[1], + ] + } + if (deploy_chrome) { + # To deploy chrome to the VM, it needs to be stripped down to fit into + # the VM. This is done by using binutils in the toolchain. So add the + # toolchain to the data. + _sdk_data += [ + _symlink_targets[2], + _symlink_targets[3], + ] + } + if (_cros_is_vm) { + # Add vm sdk items. + _sdk_data += [ + _symlink_targets[4], + _symlink_targets[5], + _symlink_targets[6], + ] + } + } + } + } + + generate_wrapper(target_name) { + executable = "//build/chromeos/test_runner.py" + use_vpython3 = true + wrapper_script = generated_script + executable_args = [] + + if (defined(runtime_deps_file)) { + write_runtime_deps = runtime_deps_file + } + + # Build executable_args for the three different test types: GTest, Tast, + # and host-side commands (eg telemetry). + if (defined(test_exe)) { + executable_args += [ + "gtest", + "--test-exe", + test_exe, + ] + if (defined(runtime_deps_file)) { + executable_args += [ + "--runtime-deps-path", + rebase_path(runtime_deps_file, root_build_dir), + ] + } + } else if (is_tast) { + # When --tast-tests is specified, test_runner.py will call + # local_test_runner on the VM to run the set of tests. + executable_args += [ + "tast", + "--suite-name", + target_name, + ] + if (defined(tast_attr_expr)) { + executable_args += [ + "--attr-expr", + tast_attr_expr, + ] + } else { + foreach(test, tast_tests) { + executable_args += [ + "-t", + test, + ] + } + } + if (defined(tast_vars)) { + foreach(var, tast_vars) { + executable_args += [ + "--tast-var", + var, + ] + } + } + } else { + executable_args += [ "host-cmd" ] + } + executable_args += [ + "--cros-cache", + "build/cros_cache/", + "--path-to-outdir", + rebase_path(root_out_dir, "//"), + "-v", + ] + + if (!skip_generating_board_args) { + executable_args += [ + "--board", + cros_board, + ] + + _cros_is_vm = false + foreach(b, string_split(cros_boards_with_qemu_images, ":")) { + if (cros_board == b) { + _cros_is_vm = true + } + } + if (_cros_is_vm) { + executable_args += [ "--use-vm" ] + } else { + executable_args += [ "--flash" ] + } + } + + # If we have public Chromium builds, use public Chromium OS images when + # flashing the test device. + if (!is_chrome_branded) { + executable_args += [ "--public-image" ] + } + + if (deploy_lacros) { + executable_args += [ "--deploy-lacros" ] + } + + if (deploy_chrome && !defined(test_exe) && !is_tast) { + executable_args += [ "--deploy-chrome" ] + } + + # executable_args should be finished, now build the data and deps lists. + deps = [ "//testing/buildbot/filters:chromeos_filters" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + data = [ + "//.vpython", + "//.vpython3", + + # We use android test-runner's results libs to construct gtest output + # json. + "//build/android/pylib/__init__.py", + "//build/android/pylib/base/", + "//build/android/pylib/results/", + "//build/chromeos/", + "//build/util/", + + # Needed for various SDK components used below. + "//build/cros_cache/chrome-sdk/misc/", + "//build/cros_cache/chrome-sdk/symlinks/", + + # The LKGM file controls what version of the VM image to download. Add it + # as data here so that changes to it will trigger analyze. + "//chromeos/CHROMEOS_LKGM", + "//third_party/chromite/", + ] + + data += _sdk_data + + if (defined(invoker.data)) { + data += invoker.data + } + + data_deps = [ "//testing:test_scripts_shared" ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + } +} + +template("tast_test") { + forward_variables_from(invoker, "*") + + # Default the expression to match any chrome-related test. + if (!defined(tast_attr_expr) && !defined(tast_tests)) { + # The following expression filters out all non-critical tests. See the link + # below for more details: + # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md + tast_attr_expr = "\"group:mainline\" && \"dep:chrome\"" + + if (defined(enable_tast_informational_tests) && + enable_tast_informational_tests) { + tast_attr_expr += " && informational" + } else { + tast_attr_expr += " && !informational" + } + if (!is_chrome_branded) { + tast_attr_expr += " && !\"dep:chrome_internal\"" + } + } else { + assert(defined(tast_attr_expr) != defined(tast_tests), + "Specify one of tast_tests or tast_attr_expr.") + } + + # Append any disabled tests to the expression. + if (defined(tast_disabled_tests)) { + assert(defined(tast_attr_expr), + "tast_attr_expr must be used when specifying tast_disabled_tests.") + foreach(test, tast_disabled_tests) { + tast_attr_expr += " && !\"name:${test}\"" + } + } + if (defined(tast_attr_expr)) { + tast_attr_expr = "( " + tast_attr_expr + " )" + } + generate_runner_script(target_name) { + testonly = true + generated_script = "$root_build_dir/bin/run_${target_name}" + runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" + deploy_chrome = true + data_deps = [ + "//:chromiumos_preflight", # Builds the browser. + "//chromeos:cros_chrome_deploy", # Adds additional browser run-time deps. + + # Tools used to symbolize Chrome crash dumps. + # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by + # default. + "//third_party/breakpad:dump_syms", + "//third_party/breakpad:minidump_dump", + "//third_party/breakpad:minidump_stackwalk", + ] + + data = [ "//components/crash/content/tools/generate_breakpad_symbols.py" ] + } +} + +template("lacros_tast_tests") { + forward_variables_from(invoker, + [ + "tast_attr_expr", + "tast_disabled_tests", + "tast_tests", + ]) + assert(defined(tast_attr_expr) != defined(tast_tests), + "Specify one of tast_tests or tast_attr_expr.") + + # Append any disabled tests to the expression. + if (defined(tast_disabled_tests)) { + assert(defined(tast_attr_expr), + "tast_attr_expr must be used when specifying tast_disabled_tests.") + foreach(test, tast_disabled_tests) { + tast_attr_expr += " && !\"name:${test}\"" + } + } + if (defined(tast_attr_expr)) { + tast_attr_expr = "( " + tast_attr_expr + " )" + } + + generate_runner_script(target_name) { + testonly = true + deploy_lacros = true + generated_script = "$root_build_dir/bin/run_${target_name}" + runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" + + # At build time, Lacros tests don't know whether they'll run on VM or HW, + # and instead, these flags are specified at runtime when invoking the + # generated runner script. + skip_generating_board_args = true + + # By default, tast tests download a lacros-chrome from a gcs location and + # use it for testing. To support running lacros tast tests from Chromium CI, + # a Var is added to support pointing the tast tests to use a specified + # pre-deployed lacros-chrome. The location is decided by: + # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61 + tast_vars = [ "lacrosDeployedBinary=/usr/local/lacros-chrome" ] + + data_deps = [ + "//chrome", # Builds the browser. + + # Tools used to symbolize Chrome crash dumps. + # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by + # default. + "//third_party/breakpad:dump_syms", + "//third_party/breakpad:minidump_dump", + "//third_party/breakpad:minidump_stackwalk", + ] + + data = [ + "//components/crash/content/tools/generate_breakpad_symbols.py", + + # A script needed to launch Lacros in Lacros Tast tests. + "//build/lacros/mojo_connection_lacros_launcher.py", + ] + } +} + +template("generate_skylab_runner_script") { + forward_variables_from(invoker, + [ + "generated_script", + "test_exe", + ]) + + action(target_name) { + script = "//build/chromeos/gen_skylab_runner.py" + outputs = [ generated_script ] + args = [ + "--test-exe", + test_exe, + "--output", + rebase_path(generated_script, root_build_dir), + ] + + deps = [ "//testing/buildbot/filters:chromeos_filters" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + data = [ generated_script ] + if (defined(invoker.data)) { + data += invoker.data + } + + data_deps = [ "//testing:test_scripts_shared" ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + } +} diff --git a/third_party/libwebrtc/build/config/chromeos/ui_mode.gni b/third_party/libwebrtc/build/config/chromeos/ui_mode.gni new file mode 100644 index 0000000000..aff59afa66 --- /dev/null +++ b/third_party/libwebrtc/build/config/chromeos/ui_mode.gni @@ -0,0 +1,40 @@ +# Copyright 2020 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. + +declare_args() { + # Deprecated, use is_lacros. + # + # This controls UI configuration for Chrome. + # If this flag is set, we assume Chrome runs on Chrome OS devices, using + # Wayland (instead of X11). + # + # TODO(crbug.com/1052397): + # Define chromeos_product instead, which takes either "browser" or "ash". + # Re-define the following variables as: + # is_lacros = chromeos_product == "browser" + # is_ash = chromeos_product == "ash" + chromeos_is_browser_only = false + + # Setting this to true when building LaCrOS-chrome will cause it to + # *also* build ash-chrome in a subdirectory using an alternate toolchain. + # Don't set this unless you're sure you want it, because it'll double + # your build time. + also_build_ash_chrome = false + + # Setting this to true when building ash-chrome will cause it to + # *also* build lacros-chrome in a subdirectory using an alternate toolchain. + also_build_lacros_chrome = false +} + +# is_chromeos_{ash,lacros} is used to specify that it is specific to either +# ash or lacros chrome for chromeos. For platform specific logic that +# applies to both, use is_chromeos instead. +# .gn files are evaluated multiple times for each toolchain. +# is_chromeos_{ash,lacros} should be set true only for builds with target +# toolchains. +is_chromeos_ash = is_chromeos && !chromeos_is_browser_only +is_chromeos_lacros = is_chromeos && chromeos_is_browser_only + +# also_build_ash_chrome and also_build_lacros_chrome cannot be both true. +assert(!(also_build_ash_chrome && also_build_lacros_chrome)) diff --git a/third_party/libwebrtc/build/config/clang/BUILD.gn b/third_party/libwebrtc/build/config/clang/BUILD.gn new file mode 100644 index 0000000000..9512c66246 --- /dev/null +++ b/third_party/libwebrtc/build/config/clang/BUILD.gn @@ -0,0 +1,59 @@ +# 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. + +import("clang.gni") + +config("find_bad_constructs") { + if (clang_use_chrome_plugins) { + cflags = [] + + # The plugin is built directly into clang, so there's no need to load it + # dynamically. + cflags += [ + "-Xclang", + "-add-plugin", + "-Xclang", + "find-bad-constructs", + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "raw-ptr-template-as-trivial-member", + ] + + if (is_linux || is_chromeos || is_android || is_fuchsia) { + cflags += [ + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "check-ipc", + ] + } + } +} + +# Enables some extra Clang-specific warnings. Some third-party code won't +# compile with these so may want to remove this config. +config("extra_warnings") { + cflags = [ + "-Wheader-hygiene", + + # Warns when a const char[] is converted to bool. + "-Wstring-conversion", + + "-Wtautological-overlap-compare", + ] +} + +group("llvm-symbolizer_data") { + if (is_win) { + data = [ "$clang_base_path/bin/llvm-symbolizer.exe" ] + } else { + data = [ "$clang_base_path/bin/llvm-symbolizer" ] + + if (!is_apple) { + # llvm-symbolizer uses libstdc++ from the clang package. + data += [ "$clang_base_path/lib/libstdc++.so.6" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/clang/clang.gni b/third_party/libwebrtc/build/config/clang/clang.gni new file mode 100644 index 0000000000..588864586d --- /dev/null +++ b/third_party/libwebrtc/build/config/clang/clang.gni @@ -0,0 +1,18 @@ +# Copyright 2014 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. + +import("//build/toolchain/toolchain.gni") + +default_clang_base_path = "//third_party/llvm-build/Release+Asserts" + +declare_args() { + # Indicates if the build should use the Chrome-specific plugins for enforcing + # coding guidelines, etc. Only used when compiling with Chrome's Clang, not + # Chrome OS's. + clang_use_chrome_plugins = + is_clang && !is_nacl && !use_xcode_clang && + default_toolchain != "//build/toolchain/cros:target" + + clang_base_path = default_clang_base_path +} diff --git a/third_party/libwebrtc/build/config/compiler/BUILD.gn b/third_party/libwebrtc/build/config/compiler/BUILD.gn new file mode 100644 index 0000000000..a1293bc431 --- /dev/null +++ b/third_party/libwebrtc/build/config/compiler/BUILD.gn @@ -0,0 +1,2648 @@ +# 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. + +import("//build/buildflag_header.gni") +import("//build/config/android/config.gni") +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/coverage/coverage.gni") +import("//build/config/dcheck_always_on.gni") +#import("//build/config/gclient_args.gni") +import("//build/config/host_byteorder.gni") +import("//build/config/rust.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/config/ui.gni") +import("//build/toolchain/cc_wrapper.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/rbe.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +if (target_cpu == "arm" || target_cpu == "arm64") { + import("//build/config/arm.gni") +} +if (target_cpu == "mipsel" || target_cpu == "mips64el" || + target_cpu == "mips" || target_cpu == "mips64") { + import("//build/config/mips.gni") +} +if (target_cpu == "x64") { + import("//build/config/x64.gni") +} +if (is_mac) { + import("//build/config/apple/symbols.gni") +} +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") +} +if (is_nacl) { + # To keep NaCl variables out of builds that don't include NaCl, all + # variables defined in nacl/config.gni referenced here should be protected by + # is_nacl conditions. + import("//build/config/nacl/config.gni") +} + +lld_path = "" +if (!is_clang) { + declare_args() { + # This allows overriding the location of lld. + lld_path = rebase_path("$clang_base_path/bin", root_build_dir) + } +} else { + # clang looks for lld next to it, no need for -B. + lld_path = "" +} + +declare_args() { + # Normally, Android builds are lightly optimized, even for debug builds, to + # keep binary size down. Setting this flag to true disables such optimization + android_full_debug = false + + # Compile in such a way as to make it possible for the profiler to unwind full + # stack frames. Setting this flag has a large effect on the performance of the + # generated code than just setting profiling, but gives the profiler more + # information to analyze. + # Requires profiling to be set to true. + enable_full_stack_frames_for_profiling = false + + # When we are going to use gold we need to find it. + # This is initialized below, after use_gold might have been overridden. + gold_path = "" + + # Enable fatal linker warnings. Building Chromium with certain versions + # of binutils can cause linker warning. + fatal_linker_warnings = true + + # Build with C++ RTTI enabled. Chromium builds without RTTI by default, + # but some sanitizers are known to require it, like CFI diagnostics + # and UBsan variants. + use_rtti = use_cfi_diag || is_ubsan_vptr || is_ubsan_security + + # AFDO (Automatic Feedback Directed Optimizer) is a form of profile-guided + # optimization that GCC supports. It used by ChromeOS in their official + # builds. To use it, set auto_profile_path to the path to a file containing + # the needed gcov profiling data. + auto_profile_path = "" + + # Allow projects that wish to stay on C++11 to override Chromium's default. + use_cxx11 = false + + # Path to an AFDO profile to use while building with clang, if any. Empty + # implies none. + clang_sample_profile_path = "" + + # Some configurations have default sample profiles. If this is true and + # clang_sample_profile_path is empty, we'll fall back to the default. + # + # We currently only have default profiles for Chromium in-tree, so we disable + # this by default for all downstream projects, since these profiles are likely + # nonsensical for said projects. + clang_use_default_sample_profile = + chrome_pgo_phase == 0 && build_with_chromium && is_official_build && + (is_android || chromeos_is_browser_only || is_chromecast) + + # This configuration is used to select a default profile in Chrome OS based on + # the microarchitectures we are using. This is only used if + # clang_use_default_sample_profile is true and clang_sample_profile_path is + # empty. + chromeos_afdo_platform = "atom" + + # Emit debug information for profiling wile building with clang. + clang_emit_debug_info_for_profiling = false + + # Turn this on to have the compiler output extra timing information. + compiler_timing = false + + # Turn this on to use ghash feature of lld for faster debug link on Windows. + # http://blog.llvm.org/2018/01/improving-link-time-on-windows-with.html + use_ghash = true + + # Whether to enable ThinLTO optimizations. Turning ThinLTO optimizations on + # can substantially increase link time and binary size, but they generally + # also make binaries a fair bit faster. + # + # TODO(gbiv): We disable optimizations by default on most platforms because + # the space overhead is too great. We should use some mixture of profiles and + # optimization settings to better tune the size increase. + thin_lto_enable_optimizations = + (is_chromeos_ash || is_android || is_win || is_linux) && is_official_build + + # Initialize all local variables with a pattern. This flag will fill + # uninitialized floating-point types (and 32-bit pointers) with 0xFF and the + # rest with 0xAA. This makes behavior of uninitialized memory bugs consistent, + # recognizable in the debugger, and crashes on memory accesses through + # uninitialized pointers. + # + # TODO(crbug.com/1131993): Enabling this when 'is_android' is true breaks + # content_shell_test_apk on both ARM and x86. + init_stack_vars = !is_android + + # This argument is to control whether enabling text section splitting in the + # final binary. When enabled, the separated text sections with prefix + # '.text.hot', '.text.unlikely', '.text.startup' and '.text.exit' will not be + # merged to '.text' section. This allows us to identify the hot code section + # ('.text.hot') in the binary which may be mlocked or mapped to huge page to + # reduce TLB misses which gives performance improvement on cpu usage. + # The gold linker by default has text section splitting enabled. + use_text_section_splitting = false + + # Token limits may not be accurate for build configs not covered by the CQ, + # so only enable them by default for mainstream build configs. + enable_wmax_tokens = + !is_official_build && !(is_component_build && !is_debug) && + ((is_mac && target_cpu == "x64" && !use_system_xcode) || + (is_linux && !is_chromeos && target_cpu == "x64") || + (is_win && target_cpu == "x86") || (is_win && target_cpu == "x64") || + (is_android && target_cpu == "arm") || + (is_android && target_cpu == "arm64")) + + # Turn off the --call-graph-profile-sort flag for lld by default. Enable + # selectively for targets where it's beneficial. + enable_call_graph_profile_sort = chrome_pgo_phase == 2 + + # Enable DWARF v5. + use_dwarf5 = false + + # Override this to put full paths to PDBs in Windows PE files. This helps + # windbg and Windows Performance Analyzer with finding the PDBs in some local- + # build scenarios. This is never needed for bots or official builds. Because + # this puts the output directory in the DLLs/EXEs it breaks build determinism. + # Bugs have been reported to the windbg/WPA teams and this workaround will be + # removed when they are fixed. + use_full_pdb_paths = false + + # Enable -H, which prints the include tree during compilation. + # For use by tools/clang/scripts/analyze_includes.py + show_includes = false +} + +declare_args() { + # C++11 may not be an option if Android test infrastructure is used. + use_cxx11_on_android = use_cxx11 +} + +declare_args() { + # Set to true to use icf, Identical Code Folding. + # + # icf=all is broken in older golds, see + # https://sourceware.org/bugzilla/show_bug.cgi?id=17704 + # chromeos binutils has been patched with the fix, so always use icf there. + # The bug only affects x86 and x64, so we can still use ICF when targeting + # other architectures. + # + # lld doesn't have the bug. + use_icf = + (is_posix || is_fuchsia) && !is_debug && !using_sanitizer && + !use_clang_coverage && !(is_android && use_order_profiling) && + (use_lld || (use_gold && (is_chromeos_ash || !(target_cpu == "x86" || + target_cpu == "x64")))) +} + +if (is_android || (is_chromeos_ash && is_chromeos_device)) { + # Set the path to use orderfile for linking Chrome + # Note that this is for using only one orderfile for linking + # the Chrome binary/library. + declare_args() { + chrome_orderfile_path = "" + + if (defined(default_chrome_orderfile)) { + # Allow downstream tools to set orderfile path with + # another variable. + chrome_orderfile_path = default_chrome_orderfile + } else if (is_chromeos_ash && is_chromeos_device) { + chrome_orderfile_path = "//chromeos/profiles/chromeos.orderfile.txt" + } + } +} + +assert(!(llvm_force_head_revision && use_goma), + "can't use goma with trunk clang") +assert(!(llvm_force_head_revision && use_rbe), "can't use rbe with trunk clang") + +# default_include_dirs --------------------------------------------------------- +# +# This is a separate config so that third_party code (which would not use the +# source root and might have conflicting versions of some headers) can remove +# this and specify their own include paths. +config("default_include_dirs") { + include_dirs = [ + "//", + root_gen_dir, + ] +} + +# Compiler instrumentation can introduce dependencies in DSOs to symbols in +# the executable they are loaded into, so they are unresolved at link-time. +config("no_unresolved_symbols") { + if (!using_sanitizer && + (is_linux || is_chromeos || is_android || is_fuchsia)) { + ldflags = [ + "-Wl,-z,defs", + "-Wl,--as-needed", + ] + } +} + +# compiler --------------------------------------------------------------------- +# +# Base compiler configuration. +# +# See also "runtime_library" below for related stuff and a discussion about +# where stuff should go. Put warning related stuff in the "warnings" config. + +config("compiler") { + asmflags = [] + cflags = [] + cflags_c = [] + cflags_cc = [] + cflags_objc = [] + cflags_objcc = [] + ldflags = [] + defines = [] + configs = [] + + # System-specific flags. If your compiler flags apply to one of the + # categories here, add it to the associated file to keep this shared config + # smaller. + if (is_win) { + configs += [ "//build/config/win:compiler" ] + } else if (is_android) { + configs += [ "//build/config/android:compiler" ] + } else if (is_linux || is_chromeos) { + configs += [ "//build/config/linux:compiler" ] + if (is_chromeos_ash) { + configs += [ "//build/config/chromeos:compiler" ] + } + } else if (is_nacl) { + configs += [ "//build/config/nacl:compiler" ] + } else if (is_mac) { + configs += [ "//build/config/mac:compiler" ] + } else if (is_ios) { + configs += [ "//build/config/ios:compiler" ] + } else if (is_fuchsia) { + configs += [ "//build/config/fuchsia:compiler" ] + } else if (current_os == "aix") { + configs += [ "//build/config/aix:compiler" ] + } + + configs += [ + # See the definitions below. + ":clang_revision", + ":compiler_cpu_abi", + ":compiler_codegen", + ":compiler_deterministic", + ] + + # Here we enable -fno-delete-null-pointer-checks, which makes various nullptr + # operations (e.g. dereferencing) into defined behavior. This avoids deletion + # of some security-critical code: see https://crbug.com/1139129. + # Nacl does not support the flag. And, we still want UBSAN to catch undefined + # behavior related to nullptrs, so do not add this flag if UBSAN is enabled. + # GCC seems to have some bugs compiling constexpr code when this is defined, + # so only enable it if using_clang. See: https://gcc.gnu.org/PR97913 + # TODO(mpdenton): remove is_clang once GCC bug is fixed. + if (!is_nacl && !is_ubsan && is_clang) { + cflags += [ "-fno-delete-null-pointer-checks" ] + } + + # Don't emit the GCC version ident directives, they just end up in the + # .comment section or debug info taking up binary size, and makes comparing + # .o files built with different compiler versions harder. + if (!is_win || is_clang) { + cflags += [ "-fno-ident" ] + } + + # In general, Windows is totally different, but all the other builds share + # some common compiler and linker configuration. + if (!is_win) { + # Common POSIX compiler flags setup. + # -------------------------------- + cflags += [ "-fno-strict-aliasing" ] # See http://crbug.com/32204 + + # Stack protection. + if (is_mac) { + # The strong variant of the stack protector significantly increases + # binary size, so only enable it in debug mode. + if (is_debug) { + cflags += [ "-fstack-protector-strong" ] + } else { + cflags += [ "-fstack-protector" ] + } + } else if ((is_posix && !is_chromeos_ash && !is_nacl) || is_fuchsia) { + # TODO(phajdan.jr): Use -fstack-protector-strong when our gcc supports it. + # See also https://crbug.com/533294 + cflags += [ "--param=ssp-buffer-size=4" ] + + # The x86 toolchain currently has problems with stack-protector. + if (is_android && target_cpu == "x86") { + cflags += [ "-fno-stack-protector" ] + } else if (current_os != "aix") { + # Not available on aix. + cflags += [ "-fstack-protector" ] + } + } + + if (use_lld) { + ldflags += [ "-fuse-ld=lld" ] + if (lld_path != "") { + ldflags += [ "-B$lld_path" ] + } + } + + # Linker warnings. + if (fatal_linker_warnings && !is_apple && current_os != "aix") { + ldflags += [ "-Wl,--fatal-warnings" ] + } + if (fatal_linker_warnings && is_apple) { + ldflags += [ "-Wl,-fatal_warnings" ] + } + } + + if (is_clang && is_debug) { + # Allow comparing the address of references and 'this' against 0 + # in debug builds. Technically, these can never be null in + # well-defined C/C++ and Clang can optimize such checks away in + # release builds, but they may be used in asserts in debug builds. + cflags_cc += [ + "-Wno-undefined-bool-conversion", + "-Wno-tautological-undefined-compare", + ] + } + + # Non-Mac Posix and Fuchsia compiler flags setup. + # ----------------------------------- + if ((is_posix && !is_apple) || is_fuchsia) { + if (enable_profiling) { + if (!is_debug) { + cflags += [ "-g" ] + + if (enable_full_stack_frames_for_profiling) { + cflags += [ + "-fno-inline", + "-fno-optimize-sibling-calls", + ] + } + } + } + + # Explicitly pass --build-id to ld. Compilers used to always pass this + # implicitly but don't any more (in particular clang when built without + # ENABLE_LINKER_BUILD_ID=ON). + if (is_official_build) { + # The sha1 build id has lower risk of collision but is more expensive to + # compute, so only use it in the official build to avoid slowing down + # links. + ldflags += [ "-Wl,--build-id=sha1" ] + } else if (current_os != "aix") { + ldflags += [ "-Wl,--build-id" ] + } + + if (!is_android) { + defines += [ + # _FILE_OFFSET_BITS=64 should not be set on Android in order to maintain + # the behavior of the Android NDK from earlier versions. + # See https://android-developers.googleblog.com/2017/09/introducing-android-native-development.html + "_FILE_OFFSET_BITS=64", + "_LARGEFILE_SOURCE", + "_LARGEFILE64_SOURCE", + ] + } + + if (!is_nacl) { + if (exclude_unwind_tables) { + cflags += [ + "-fno-unwind-tables", + "-fno-asynchronous-unwind-tables", + ] + defines += [ "NO_UNWIND_TABLES" ] + } else { + cflags += [ "-funwind-tables" ] + } + } + } + + # Linux/Android/Fuchsia common flags setup. + # --------------------------------- + if (is_linux || is_chromeos || is_android || is_fuchsia) { + asmflags += [ "-fPIC" ] + cflags += [ "-fPIC" ] + ldflags += [ "-fPIC" ] + + if (!is_clang) { + # Use pipes for communicating between sub-processes. Faster. + # (This flag doesn't do anything with Clang.) + cflags += [ "-pipe" ] + } + + ldflags += [ + "-Wl,-z,noexecstack", + "-Wl,-z,relro", + ] + + if (!is_component_build) { + ldflags += [ "-Wl,-z,now" ] + } + } + + # Linux-specific compiler flags setup. + # ------------------------------------ + if ((is_posix || is_fuchsia) && !is_apple && use_lld) { + if (target_cpu == "arm64") { + # Reduce the page size from 65536 in order to reduce binary size slightly + # by shrinking the alignment gap between segments. This also causes all + # segments to be mapped adjacently, which breakpad relies on. + ldflags += [ "-Wl,-z,max-page-size=4096" ] + } + } else if (use_gold) { + ldflags += [ "-fuse-ld=gold" ] + if (!is_android) { + # On Android, this isn't needed. gcc in the NDK knows to look next to + # it with -fuse-ld=gold, and clang gets a --gcc-toolchain flag passed + # above. + if (gold_path != "") { + ldflags += [ "-B$gold_path" ] + } + + ldflags += [ + # Experimentation found that using four linking threads + # saved ~20% of link time. + # https://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/281527606915bb36 + # Only apply this to the target linker, since the host + # linker might not be gold, but isn't used much anyway. + "-Wl,--threads", + "-Wl,--thread-count=4", + ] + } + + # TODO(thestig): Make this flag work with GN. + #if (!is_official_build && !is_chromeos && !(is_asan || is_lsan || is_tsan || is_msan)) { + # ldflags += [ + # "-Wl,--detect-odr-violations", + # ] + #} + } + + if (use_icf && !is_apple) { + ldflags += [ "-Wl,--icf=all" ] + } + + if (is_linux || is_chromeos) { + cflags += [ "-pthread" ] + # Do not use the -pthread ldflag here since it becomes a no-op + # when using -nodefaultlibs, which would cause an unused argument + # error. "-lpthread" is added in //build/config:default_libs. + } + + # Clang-specific compiler flags setup. + # ------------------------------------ + if (is_clang) { + cflags += [ "-fcolor-diagnostics" ] + + # Enable -fmerge-all-constants. This used to be the default in clang + # for over a decade. It makes clang non-conforming, but is fairly safe + # in practice and saves some binary size. We might want to consider + # disabling this (https://bugs.llvm.org/show_bug.cgi?id=18538#c13), + # but for now it looks like our build might rely on it + # (https://crbug.com/829795). + cflags += [ "-fmerge-all-constants" ] + } + + if (use_lld) { + # TODO(thakis): Make the driver pass --color-diagnostics to the linker + # if -fcolor-diagnostics is passed to it, and pass -fcolor-diagnostics + # in ldflags instead. + if (is_win) { + # On Windows, we call the linker directly, instead of calling it through + # the driver. + ldflags += [ "--color-diagnostics" ] + } else { + ldflags += [ "-Wl,--color-diagnostics" ] + } + } + + # Enable text section splitting only on linux when using lld for now. Other + # platforms can be added later if needed. + if ((is_linux || is_chromeos) && use_lld && use_text_section_splitting) { + ldflags += [ "-Wl,-z,keep-text-section-prefix" ] + } + + if (is_clang && !is_nacl && !use_xcode_clang) { + cflags += [ "-fcrash-diagnostics-dir=" + clang_diagnostic_dir ] + + # TODO(hans): Remove this once Clang generates better optimized debug info + # by default. https://crbug.com/765793 + cflags += [ + "-mllvm", + "-instcombine-lower-dbg-declare=0", + ] + if (!is_debug && use_thin_lto && is_a_target_toolchain) { + if (is_win) { + ldflags += [ "-mllvm:-instcombine-lower-dbg-declare=0" ] + } else { + ldflags += [ "-Wl,-mllvm,-instcombine-lower-dbg-declare=0" ] + } + } + + # TODO(crbug.com/1235145): Investigate why/if this should be needed. + if (is_win) { + cflags += [ "/clang:-ffp-contract=off" ] + } else { + cflags += [ "-ffp-contract=off" ] + } + } + + # C11/C++11 compiler flags setup. + # --------------------------- + if (is_linux || is_chromeos || is_android || (is_nacl && is_clang) || + current_os == "aix") { + if (target_os == "android") { + cxx11_override = use_cxx11_on_android + } else { + cxx11_override = use_cxx11 + } + + if (is_clang) { + standard_prefix = "c" + + # Since we build with -std=c* and not -std=gnu*, _GNU_SOURCE will not be + # defined by the compiler. However, lots of code relies on the + # non-standard features that _GNU_SOURCE enables, so define it manually. + defines += [ "_GNU_SOURCE" ] + + if (is_nacl) { + # Undefine __STRICT_ANSI__ to get non-standard features which would + # otherwise not be enabled by NaCl's sysroots. + cflags += [ "-U__STRICT_ANSI__" ] + } + } else { + # Gcc does not support ##__VA_ARGS__ when in standards-conforming mode, + # but we use this feature in several places in Chromium. + # TODO(thomasanderson): Replace usages of ##__VA_ARGS__ with the + # standard-compliant __VA_OPT__ added by C++20, and switch the gcc build + # to -std=c*. + standard_prefix = "gnu" + } + + cflags_c += [ "-std=${standard_prefix}11" ] + if (cxx11_override) { + # Override Chromium's default for projects that wish to stay on C++11. + cflags_cc += [ "-std=${standard_prefix}++11" ] + } else { + cflags_cc += [ "-std=${standard_prefix}++14" ] + } + } else if (!is_win && !is_nacl) { + if (target_os == "android") { + cxx11_override = use_cxx11_on_android + } else { + cxx11_override = use_cxx11 + } + + # TODO(mcgrathr) - the NaCl GCC toolchain doesn't support either gnu11/gnu++11 + # or c11/c++11; we technically don't need this toolchain any more, but there + # are still a few buildbots using it, so until those are turned off + # we need the !is_nacl clause and the (is_nacl && is_clang) clause, above. + cflags_c += [ "-std=c11" ] + if (cxx11_override) { + cflags_cc += [ "-std=c++11" ] + } else { + cflags_cc += [ "-std=c++14" ] + } + } + + # C++17 removes trigraph support, so preemptively disable trigraphs. This is + # especially useful given the collision with ecmascript's logical assignment + # operators: https://github.com/tc39/proposal-logical-assignment + if (is_clang) { + # clang-cl disables trigraphs by default + if (!is_win) { + # The gnu variants of C++11 and C++14 already disable trigraph support, + # but when building with clang, we use -std=c++11 / -std=c++14, which + # enables trigraph support: override that here. + cflags_cc += [ "-fno-trigraphs" ] + } + + # Don't warn that trigraphs are ignored, since trigraphs are disabled + # anyway. + cflags_cc += [ "-Wno-trigraphs" ] + } + + if (is_mac) { + # The system libc++ on Mac doesn't have aligned allocation in C++17. + defines += [ "_LIBCPP_HAS_NO_ALIGNED_ALLOCATION" ] + cflags_cc += [ "-stdlib=libc++" ] + ldflags += [ "-stdlib=libc++" ] + } + + # Add flags for link-time optimization. These flags enable + # optimizations/transformations that require whole-program visibility at link + # time, so they need to be applied to all translation units, and we may end up + # with miscompiles if only part of the program is compiled with LTO flags. For + # that reason, we cannot allow targets to enable or disable these flags, for + # example by disabling the optimize configuration. + # TODO(pcc): Make this conditional on is_official_build rather than on gn + # flags for specific features. + if (!is_debug && use_thin_lto && is_a_target_toolchain) { + assert(use_lld, "LTO is only supported with lld") + + cflags += [ + "-flto=thin", + "-fsplit-lto-unit", + ] + + # Limit the size of the ThinLTO cache to the lesser of 10% of + # available disk space, 40GB and 100000 files. + cache_policy = "cache_size=10%:cache_size_bytes=40g:cache_size_files=100000" + + # TODO(gbiv): We ideally shouldn't need to specify this; ThinLTO + # should be able to better manage binary size increases on its own. + import_instr_limit = 5 + + if (is_win) { + ldflags += [ + "/opt:lldltojobs=all", + "-mllvm:-import-instr-limit=$import_instr_limit", + "/lldltocache:" + + rebase_path("$root_out_dir/thinlto-cache", root_build_dir), + "/lldltocachepolicy:$cache_policy", + ] + } else { + ldflags += [ "-flto=thin" ] + + # Enabling ThinLTO on Chrome OS too, in an effort to reduce the memory + # usage in crbug.com/1038040. Note this will increase build time in + # Chrome OS. + + # In ThinLTO builds, we run at most one link process at a time, + # and let it use all cores. + # TODO(thakis): Check if '=0' (that is, number of cores, instead + # of "all" which means number of hardware threads) is faster. + ldflags += [ "-Wl,--thinlto-jobs=all" ] + if (is_mac) { + ldflags += + [ "-Wl,-cache_path_lto," + + rebase_path("$root_out_dir/thinlto-cache", root_build_dir) ] + } else { + ldflags += + [ "-Wl,--thinlto-cache-dir=" + + rebase_path("$root_out_dir/thinlto-cache", root_build_dir) ] + } + + ldflags += [ "-Wl,--thinlto-cache-policy=$cache_policy" ] + + if (is_chromeos_ash) { + # Not much performance difference was noted between the default (100) + # and these. ARM was originally set lower than x86 to keep the size + # bloat of ThinLTO to <10%, but that's potentially no longer true. + # FIXME(inglorion): maybe tune these? + if (target_cpu == "arm" || target_cpu == "arm64") { + import_instr_limit = 20 + } else { + import_instr_limit = 30 + } + } + + ldflags += [ "-Wl,-mllvm,-import-instr-limit=$import_instr_limit" ] + } + + # TODO(https://crbug.com/1211155): investigate why this isn't effective on arm32. + if (!is_android || target_cpu == "arm64") { + cflags += [ "-fwhole-program-vtables" ] + if (!is_win) { + ldflags += [ "-fwhole-program-vtables" ] + } + } + + # This flag causes LTO to create an .ARM.attributes section with the correct + # architecture. This is necessary because LLD will refuse to link a program + # unless the architecture revision in .ARM.attributes is sufficiently new. + # TODO(pcc): The contents of .ARM.attributes should be based on the + # -march flag passed at compile time (see llvm.org/pr36291). + if (target_cpu == "arm") { + ldflags += [ "-march=$arm_arch" ] + } + } + + if (compiler_timing) { + if (is_clang && !is_nacl) { + cflags += [ "-ftime-trace" ] + } else if (is_win) { + cflags += [ + # "Documented" here: + # http://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/ + "/d2cgsummary", + ] + } + } + + # Pass flag to LLD so Android builds can allow debuggerd to properly symbolize + # stack crashes (http://crbug.com/919499). + if (use_lld && is_android) { + ldflags += [ "-Wl,--no-rosegment" ] + } + + # LLD does call-graph-sorted binary layout by default when profile data is + # present. On Android this increases binary size due to more thinks for long + # jumps. Turn it off by default and enable selectively for targets where it's + # beneficial. + if (use_lld && !enable_call_graph_profile_sort) { + if (is_win) { + ldflags += [ "/call-graph-profile-sort:no" ] + } else if (!is_apple) { + # TODO(thakis): Once LLD's Mach-O port basically works, implement call + # graph profile sorting for it, add an opt-out flag, and pass it here. + ldflags += [ "-Wl,--no-call-graph-profile-sort" ] + } + } + + if (is_clang && !is_nacl && show_includes) { + if (is_win) { + # TODO(crbug.com/1223741): Goma mixes the -H and /showIncludes output. + assert(!use_goma, "show_includes on Windows is not reliable with goma") + cflags += [ + "/clang:-H", + "/clang:-fshow-skipped-includes", + ] + } else { + cflags += [ + "-H", + "-fshow-skipped-includes", + ] + } + } + + # This flag enforces that member pointer base types are complete. It helps + # prevent us from running into problems in the Microsoft C++ ABI (see + # https://crbug.com/847724). + # TODO(crbug/1052397): Remove is_chromeos_lacros once lacros-chrome switches + # to target_os="chromeos". + if (is_clang && !is_nacl && target_os != "chromeos" && !use_xcode_clang && + !is_chromeos_lacros && (is_win || use_custom_libcxx)) { + cflags += [ "-fcomplete-member-pointers" ] + } + + # Pass the same C/C++ flags to the objective C/C++ compiler. + cflags_objc += cflags_c + cflags_objcc += cflags_cc + + # Assign any flags set for the C compiler to asmflags so that they are sent + # to the assembler. The Windows assembler takes different types of flags + # so only do so for posix platforms. + if (is_posix || is_fuchsia) { + asmflags += cflags + asmflags += cflags_c + } + + # Rust compiler flags setup. + # --------------------------- + rustflags = [ + # Overflow checks are optional in Rust, but even if switched + # off they do not cause undefined behavior (the overflowing + # behavior is defined). Because containers are bounds-checked + # in safe Rust, they also can't provoke buffer overflows. + # As such these checks may be less important in Rust than C++. + # But in (simplistic) testing they have negligible performance + # overhead, and this helps to provide consistent behavior + # between different configurations, so we'll keep them on until + # we discover a reason to turn them off. + "-Coverflow-checks=on", + + # To make Rust .d files compatible with ninja + "-Z", + "dep-info-omit-d-target", + ] + if (rust_abi_target != "") { + rustflags += [ "--target=$rust_abi_target" ] + } + if (use_lto_in_rustc_linking) { + rustflags += [ "-Clinker-plugin-lto" ] + } + if (!use_thin_lto) { + # Optimization - don't include bitcode if it won't be used. + rustflags += [ "-Cembed-bitcode=no" ] + } +} + +# The BUILDCONFIG file sets this config on targets by default, which means when +# building with ThinLTO, no optimization is performed in the link step. +config("thinlto_optimize_default") { + if (!is_debug && use_thin_lto && is_a_target_toolchain) { + lto_opt_level = 0 + + if (is_win) { + ldflags = [ "/opt:lldlto=" + lto_opt_level ] + } else { + ldflags = [ "-Wl,--lto-O" + lto_opt_level ] + } + } +} + +# Use this to enable optimization in the ThinLTO link step for select targets +# when thin_lto_enable_optimizations is set by doing: +# +# configs -= [ "//build/config/compiler:thinlto_optimize_default" ] +# configs += [ "//build/config/compiler:thinlto_optimize_max" ] +# +# Since it makes linking significantly slower and more resource intensive, only +# use it on important targets such as the main browser executable or dll. +config("thinlto_optimize_max") { + if (!is_debug && use_thin_lto && is_a_target_toolchain) { + if (thin_lto_enable_optimizations) { + lto_opt_level = 2 + } else { + lto_opt_level = 0 + } + + if (is_win) { + ldflags = [ "/opt:lldlto=" + lto_opt_level ] + } else { + ldflags = [ "-Wl,--lto-O" + lto_opt_level ] + } + } +} + +# This provides the basic options to select the target CPU and ABI. +# It is factored out of "compiler" so that special cases can use this +# without using everything that "compiler" brings in. Options that +# tweak code generation for a particular CPU do not belong here! +# See "compiler_codegen", below. +config("compiler_cpu_abi") { + cflags = [] + ldflags = [] + defines = [] + + if ((is_posix && !is_apple) || is_fuchsia) { + # CPU architecture. We may or may not be doing a cross compile now, so for + # simplicity we always explicitly set the architecture. + if (target_cpu == "x64") { + cflags += [ + "-m64", + "-march=$x64_arch", + "-msse3", + ] + ldflags += [ "-m64" ] + } else if (target_cpu == "x86") { + cflags += [ "-m32" ] + ldflags += [ "-m32" ] + if (!is_nacl) { + cflags += [ + "-mfpmath=sse", + "-msse2", + ] + } + } else if (target_cpu == "arm") { + if (is_clang && !is_android && !is_nacl) { + cflags += [ "--target=arm-linux-gnueabihf" ] + ldflags += [ "--target=arm-linux-gnueabihf" ] + } + if (!is_nacl) { + cflags += [ + "-march=$arm_arch", + "-mfloat-abi=$arm_float_abi", + ] + } + if (arm_tune != "") { + cflags += [ "-mtune=$arm_tune" ] + } + } else if (target_cpu == "arm64") { + if (is_clang && !is_android && !is_nacl && !is_fuchsia) { + cflags += [ "--target=aarch64-linux-gnu" ] + ldflags += [ "--target=aarch64-linux-gnu" ] + } + } else if (target_cpu == "mipsel" && !is_nacl) { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { + if (is_android) { + cflags += [ "--target=mipsel-linux-android" ] + ldflags += [ "--target=mipsel-linux-android" ] + } else { + cflags += [ "--target=mipsel-linux-gnu" ] + ldflags += [ "--target=mipsel-linux-gnu" ] + } + } else { + cflags += [ "-EL" ] + ldflags += [ "-EL" ] + } + } + + if (mips_arch_variant == "r6") { + cflags += [ "-mno-odd-spreg" ] + ldflags += [ "-mips32r6" ] + if (is_clang) { + cflags += [ + "-march=mipsel", + "-mcpu=mips32r6", + ] + } else { + cflags += [ + "-mips32r6", + "-Wa,-mips32r6", + ] + if (is_android) { + ldflags += [ "-Wl,-melf32ltsmip" ] + } + } + if (mips_use_msa == true) { + cflags += [ + "-mmsa", + "-mfp64", + ] + } + } else if (mips_arch_variant == "r2") { + ldflags += [ "-mips32r2" ] + if (is_clang) { + cflags += [ + "-march=mipsel", + "-mcpu=mips32r2", + ] + } else { + cflags += [ + "-mips32r2", + "-Wa,-mips32r2", + ] + if (mips_float_abi == "hard" && mips_fpu_mode != "") { + cflags += [ "-m$mips_fpu_mode" ] + } + } + } else if (mips_arch_variant == "r1") { + ldflags += [ "-mips32" ] + if (is_clang) { + cflags += [ + "-march=mipsel", + "-mcpu=mips32", + ] + } else { + cflags += [ + "-mips32", + "-Wa,-mips32", + ] + } + } else if (mips_arch_variant == "loongson3") { + defines += [ "_MIPS_ARCH_LOONGSON" ] + cflags += [ + "-march=loongson3a", + "-mno-branch-likely", + "-Wa,-march=loongson3a", + ] + } + + if (mips_dsp_rev == 1) { + cflags += [ "-mdsp" ] + } else if (mips_dsp_rev == 2) { + cflags += [ "-mdspr2" ] + } + + cflags += [ "-m${mips_float_abi}-float" ] + } else if (target_cpu == "mips" && !is_nacl) { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { + cflags += [ "--target=mips-linux-gnu" ] + ldflags += [ "--target=mips-linux-gnu" ] + } else { + cflags += [ "-EB" ] + ldflags += [ "-EB" ] + } + } + + if (mips_arch_variant == "r6") { + cflags += [ + "-mips32r6", + "-Wa,-mips32r6", + ] + if (mips_use_msa == true) { + cflags += [ + "-mmsa", + "-mfp64", + ] + } + } else if (mips_arch_variant == "r2") { + cflags += [ + "-mips32r2", + "-Wa,-mips32r2", + ] + if (mips_float_abi == "hard" && mips_fpu_mode != "") { + cflags += [ "-m$mips_fpu_mode" ] + } + } else if (mips_arch_variant == "r1") { + cflags += [ + "-mips32", + "-Wa,-mips32", + ] + } + + if (mips_dsp_rev == 1) { + cflags += [ "-mdsp" ] + } else if (mips_dsp_rev == 2) { + cflags += [ "-mdspr2" ] + } + + cflags += [ "-m${mips_float_abi}-float" ] + } else if (target_cpu == "mips64el") { + cflags += [ "-D__SANE_USERSPACE_TYPES__" ] + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { + if (is_android) { + cflags += [ "--target=mips64el-linux-android" ] + ldflags += [ "--target=mips64el-linux-android" ] + } else { + cflags += [ "--target=mips64el-linux-gnuabi64" ] + ldflags += [ "--target=mips64el-linux-gnuabi64" ] + } + } else { + cflags += [ + "-EL", + "-mabi=64", + ] + ldflags += [ + "-EL", + "-mabi=64", + ] + } + } + + if (mips_arch_variant == "r6") { + if (is_clang) { + cflags += [ + "-march=mips64el", + "-mcpu=mips64r6", + ] + } else { + cflags += [ + "-mips64r6", + "-Wa,-mips64r6", + ] + ldflags += [ "-mips64r6" ] + } + if (mips_use_msa == true) { + cflags += [ + "-mmsa", + "-mfp64", + ] + } + } else if (mips_arch_variant == "r2") { + ldflags += [ "-mips64r2" ] + if (is_clang) { + cflags += [ + "-march=mips64el", + "-mcpu=mips64r2", + ] + } else { + cflags += [ + "-mips64r2", + "-Wa,-mips64r2", + ] + } + } else if (mips_arch_variant == "loongson3") { + defines += [ "_MIPS_ARCH_LOONGSON" ] + cflags += [ + "-march=loongson3a", + "-mno-branch-likely", + "-Wa,-march=loongson3a", + ] + } + } else if (target_cpu == "mips64") { + ldflags += [ "-Wl,--hash-style=sysv" ] + if (custom_toolchain == "") { + if (is_clang) { + cflags += [ "--target=mips64-linux-gnuabi64" ] + ldflags += [ "--target=mips64-linux-gnuabi64" ] + } else { + cflags += [ + "-EB", + "-mabi=64", + ] + ldflags += [ + "-EB", + "-mabi=64", + ] + } + } + + if (mips_arch_variant == "r6") { + cflags += [ + "-mips64r6", + "-Wa,-mips64r6", + ] + ldflags += [ "-mips64r6" ] + + if (mips_use_msa == true) { + cflags += [ + "-mmsa", + "-mfp64", + ] + } + } else if (mips_arch_variant == "r2") { + cflags += [ + "-mips64r2", + "-Wa,-mips64r2", + ] + ldflags += [ "-mips64r2" ] + } + } else if (target_cpu == "pnacl" && is_nacl_nonsfi) { + if (target_cpu == "x86" || target_cpu == "x64") { + cflags += [ + "-arch", + "x86-32-nonsfi", + "--pnacl-bias=x86-32-nonsfi", + "--target=i686-unknown-nacl", + ] + ldflags += [ + "-arch", + "x86-32-nonsfi", + "--target=i686-unknown-nacl", + ] + } else if (target_cpu == "arm") { + cflags += [ + "-arch", + "arm-nonsfi", + "-mfloat-abi=hard", + "--pnacl-bias=arm-nonsfi", + "--target=armv7-unknown-nacl-gnueabihf", + ] + ldflags += [ + "-arch", + "arm-nonsfi", + "--target=armv7-unknown-nacl-gnueabihf", + ] + } + } else if (target_cpu == "ppc64") { + if (current_os == "aix") { + cflags += [ "-maix64" ] + ldflags += [ "-maix64" ] + } else { + cflags += [ "-m64" ] + ldflags += [ "-m64" ] + } + } else if (target_cpu == "s390x") { + cflags += [ "-m64" ] + ldflags += [ "-m64" ] + } + } + + asmflags = cflags +} + +# This provides options to tweak code generation that are necessary +# for particular Chromium code or for working around particular +# compiler bugs (or the combination of the two). +config("compiler_codegen") { + configs = [] + cflags = [] + ldflags = [] + + if (is_nacl) { + configs += [ "//build/config/nacl:compiler_codegen" ] + } + + if (target_cpu == "arm64" && is_android) { + # On arm64 disable outlining for Android. See crbug.com/931297 for more + # information. + cflags += [ "-mno-outline" ] + + # This can be removed once https://bugs.llvm.org/show_bug.cgi?id=40348 + # has been resolved, and -mno-outline is obeyed by the linker during + # ThinLTO. + ldflags += [ "-Wl,-mllvm,-enable-machine-outliner=never" ] + } + + asmflags = cflags +} + +# This provides options that make the build deterministic, so that the same +# revision produces the same output, independent of the name of the build +# directory and of the computer the build is done on. +# The relative path from build dir to source dir makes it into the build +# outputs, so it's recommended that you use a build dir two levels deep +# (e.g. "out/Release") so that you get the same "../.." path as all the bots +# in your build outputs. +config("compiler_deterministic") { + cflags = [] + ldflags = [] + + # Eliminate build metadata (__DATE__, __TIME__ and __TIMESTAMP__) for + # deterministic build. See https://crbug.com/314403 + if (!is_official_build) { + if (is_win && !is_clang) { + cflags += [ + "/wd4117", # Trying to define or undefine a predefined macro. + "/D__DATE__=", + "/D__TIME__=", + "/D__TIMESTAMP__=", + ] + } else { + cflags += [ + "-Wno-builtin-macro-redefined", + "-D__DATE__=", + "-D__TIME__=", + "-D__TIMESTAMP__=", + ] + } + } + + # Makes builds independent of absolute file path. + if (is_clang && strip_absolute_paths_from_debug_symbols) { + # If debug option is given, clang includes $cwd in debug info by default. + # For such build, this flag generates reproducible obj files even we use + # different build directory like "out/feature_a" and "out/feature_b" if + # we build same files with same compile flag. + # Other paths are already given in relative, no need to normalize them. + if (is_nacl) { + # TODO(https://crbug.com/1231236): Use -ffile-compilation-dir= here. + cflags += [ + "-Xclang", + "-fdebug-compilation-dir", + "-Xclang", + ".", + ] + } else { + # -ffile-compilation-dir is an alias for both -fdebug-compilation-dir= + # and -fcoverage-compilation-dir=. + cflags += [ "-ffile-compilation-dir=." ] + } + if (!is_win) { + # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167) + asmflags = [ "-Wa,-fdebug-compilation-dir,." ] + } + + if (is_win && use_lld) { + if (symbol_level == 2 || (is_clang && using_sanitizer)) { + # Absolutize source file paths for PDB. Pass the real build directory + # if the pdb contains source-level debug information and if linker + # reproducibility is not critical. + ldflags += [ "/PDBSourcePath:" + rebase_path(root_build_dir) ] + } else { + # Use a fake fixed base directory for paths in the pdb to make the pdb + # output fully deterministic and independent of the build directory. + ldflags += [ "/PDBSourcePath:o:\fake\prefix" ] + } + } + } + + # Tells the compiler not to use absolute paths when passing the default + # paths to the tools it invokes. We don't want this because we don't + # really need it and it can mess up the goma cache entries. + if (is_clang && !is_nacl) { + cflags += [ "-no-canonical-prefixes" ] + + # Same for links: Let the compiler driver invoke the linker + # with a relative path and pass relative paths to built-in + # libraries. Not needed on Windows because we call the linker + # directly there, not through the compiler driver. + # We don't link on goma, so this change is just for cleaner + # internal linker invocations, for people who work on the build. + if (!is_win) { + ldflags += [ "-no-canonical-prefixes" ] + } + } +} + +config("clang_revision") { + if (false && is_clang && clang_base_path == default_clang_base_path) { + update_args = [ + "--print-revision", + "--verify-version=$clang_version", + ] + if (llvm_force_head_revision) { + update_args += [ "--llvm-force-head-revision" ] + } + clang_revision = exec_script("//tools/clang/scripts/update.py", + update_args, + "trim string") + + # This is here so that all files get recompiled after a clang roll and + # when turning clang on or off. (defines are passed via the command line, + # and build system rebuild things when their commandline changes). Nothing + # should ever read this define. + defines = [ "CR_CLANG_REVISION=\"$clang_revision\"" ] + } +} + +config("compiler_arm_fpu") { + if (target_cpu == "arm" && !is_ios && !is_nacl) { + cflags = [ "-mfpu=$arm_fpu" ] + if (!arm_use_thumb) { + cflags += [ "-marm" ] + } + asmflags = cflags + } +} + +config("compiler_arm_thumb") { + if (target_cpu == "arm" && arm_use_thumb && is_posix && + !(is_apple || is_nacl)) { + cflags = [ "-mthumb" ] + } +} + +config("compiler_arm") { + if (target_cpu == "arm" && (is_chromeos_ash || is_chromeos_lacros)) { + # arm is normally the default mode for clang, but on chromeos a wrapper + # is used to pass -mthumb, and therefor change the default. + cflags = [ "-marm" ] + } +} + +# runtime_library ------------------------------------------------------------- +# +# Sets the runtime library and associated options. +# +# How do you determine what should go in here vs. "compiler" above? Consider if +# a target might choose to use a different runtime library (ignore for a moment +# if this is possible or reasonable on your system). If such a target would want +# to change or remove your option, put it in the runtime_library config. If a +# target wants the option regardless, put it in the compiler config. + +config("runtime_library") { + configs = [] + + # The order of this config is important: it must appear before + # android:runtime_library. This is to ensure libc++ appears before + # libandroid_support in the -isystem include order. Otherwise, there will be + # build errors related to symbols declared in math.h. + if (use_custom_libcxx) { + configs += [ "//build/config/c++:runtime_library" ] + } + + # TODO(crbug.com/830987): Come up with a better name for is POSIX + Fuchsia + # configuration. + if (is_posix || is_fuchsia) { + configs += [ "//build/config/posix:runtime_library" ] + } + + # System-specific flags. If your compiler flags apply to one of the + # categories here, add it to the associated file to keep this shared config + # smaller. + if (is_win) { + configs += [ "//build/config/win:runtime_library" ] + } else if (is_linux || is_chromeos) { + configs += [ "//build/config/linux:runtime_library" ] + } else if (is_ios) { + configs += [ "//build/config/ios:runtime_library" ] + } else if (is_mac) { + configs += [ "//build/config/mac:runtime_library" ] + } else if (is_android) { + configs += [ "//build/config/android:runtime_library" ] + } + + if (is_component_build) { + defines = [ "COMPONENT_BUILD" ] + } +} + +# default_warnings ------------------------------------------------------------ +# +# Collects all warning flags that are used by default. This is used as a +# subconfig of both chromium_code and no_chromium_code. This way these +# flags are guaranteed to appear on the compile command line after -Wall. +config("default_warnings") { + cflags = [] + cflags_c = [] + cflags_cc = [] + ldflags = [] + + if (is_win) { + if (treat_warnings_as_errors) { + cflags += [ "/WX" ] + } + if (fatal_linker_warnings) { + ldflags = [ "/WX" ] + } + + cflags += [ + # Warnings permanently disabled: + + # C4091: 'typedef ': ignored on left of 'X' when no variable is + # declared. + # This happens in a number of Windows headers. Dumb. + "/wd4091", + + # C4127: conditional expression is constant + # This warning can in theory catch dead code and other problems, but + # triggers in far too many desirable cases where the conditional + # expression is either set by macros or corresponds some legitimate + # compile-time constant expression (due to constant template args, + # conditionals comparing the sizes of different types, etc.). Some of + # these can be worked around, but it's not worth it. + "/wd4127", + + # C4251: 'identifier' : class 'type' needs to have dll-interface to be + # used by clients of class 'type2' + # This is necessary for the shared library build. + "/wd4251", + + # C4275: non dll-interface class used as base for dll-interface class + # This points out a potential (but rare) problem with referencing static + # fields of a non-exported base, through the base's non-exported inline + # functions, or directly. The warning is subtle enough that people just + # suppressed it when they saw it, so it's not worth it. + "/wd4275", + + # C4312 is a VS 2015 64-bit warning for integer to larger pointer. + # TODO(brucedawson): fix warnings, crbug.com/554200 + "/wd4312", + + # C4324 warns when padding is added to fulfill alignas requirements, + # but can trigger in benign cases that are difficult to individually + # suppress. + "/wd4324", + + # C4351: new behavior: elements of array 'array' will be default + # initialized + # This is a silly "warning" that basically just alerts you that the + # compiler is going to actually follow the language spec like it's + # supposed to, instead of not following it like old buggy versions did. + # There's absolutely no reason to turn this on. + "/wd4351", + + # C4355: 'this': used in base member initializer list + # It's commonly useful to pass |this| to objects in a class' initializer + # list. While this warning can catch real bugs, most of the time the + # constructors in question don't attempt to call methods on the passed-in + # pointer (until later), and annotating every legit usage of this is + # simply more hassle than the warning is worth. + "/wd4355", + + # C4503: 'identifier': decorated name length exceeded, name was + # truncated + # This only means that some long error messages might have truncated + # identifiers in the presence of lots of templates. It has no effect on + # program correctness and there's no real reason to waste time trying to + # prevent it. + "/wd4503", + + # Warning C4589 says: "Constructor of abstract class ignores + # initializer for virtual base class." Disable this warning because it + # is flaky in VS 2015 RTM. It triggers on compiler generated + # copy-constructors in some cases. + "/wd4589", + + # C4611: interaction between 'function' and C++ object destruction is + # non-portable + # This warning is unavoidable when using e.g. setjmp/longjmp. MSDN + # suggests using exceptions instead of setjmp/longjmp for C++, but + # Chromium code compiles without exception support. We therefore have to + # use setjmp/longjmp for e.g. JPEG decode error handling, which means we + # have to turn off this warning (and be careful about how object + # destruction happens in such cases). + "/wd4611", + + # Warnings to evaluate and possibly fix/reenable later: + + "/wd4100", # Unreferenced formal function parameter. + "/wd4121", # Alignment of a member was sensitive to packing. + "/wd4244", # Conversion: possible loss of data. + "/wd4505", # Unreferenced local function has been removed. + "/wd4510", # Default constructor could not be generated. + "/wd4512", # Assignment operator could not be generated. + "/wd4610", # Class can never be instantiated, constructor required. + "/wd4838", # Narrowing conversion. Doesn't seem to be very useful. + "/wd4995", # 'X': name was marked as #pragma deprecated + "/wd4996", # Deprecated function warning. + + # These are variable shadowing warnings that are new in VS2015. We + # should work through these at some point -- they may be removed from + # the RTM release in the /W4 set. + "/wd4456", + "/wd4457", + "/wd4458", + "/wd4459", + + # All of our compilers support the extensions below. + "/wd4200", # nonstandard extension used: zero-sized array in struct/union + "/wd4201", # nonstandard extension used: nameless struct/union + "/wd4204", # nonstandard extension used : non-constant aggregate + # initializer + + "/wd4221", # nonstandard extension used : 'identifier' : cannot be + # initialized using address of automatic variable + + # http://crbug.com/588506 - Conversion suppressions waiting on Clang + # -Wconversion. + "/wd4245", # 'conversion' : conversion from 'type1' to 'type2', + # signed/unsigned mismatch + + "/wd4267", # 'var' : conversion from 'size_t' to 'type', possible loss of + # data + + "/wd4305", # 'identifier' : truncation from 'type1' to 'type2' + "/wd4389", # 'operator' : signed/unsigned mismatch + + "/wd4702", # unreachable code + + # http://crbug.com/848979 - MSVC is more conservative than Clang with + # regards to variables initialized and consumed in different branches. + "/wd4701", # Potentially uninitialized local variable 'name' used + "/wd4703", # Potentially uninitialized local pointer variable 'name' used + + # http://crbug.com/848979 - Remaining Clang permitted warnings. + "/wd4661", # 'identifier' : no suitable definition provided for explicit + # template instantiation request + + "/wd4706", # assignment within conditional expression + # MSVC is stricter and requires a boolean expression. + + "/wd4715", # 'function' : not all control paths return a value' + # MSVC does not analyze switch (enum) for completeness. + ] + + cflags_cc += [ + # Allow "noexcept" annotations even though we compile with exceptions + # disabled. + "/wd4577", + ] + + if (target_cpu == "x86") { + cflags += [ + # VC++ 2015 changes 32-bit size_t truncation warnings from 4244 to + # 4267. Example: short TruncTest(size_t x) { return x; } + # Since we disable 4244 we need to disable 4267 during migration. + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + "/wd4267", + ] + } + } else { + if (is_apple && !is_nacl) { + # When compiling Objective-C, warns if a method is used whose + # availability is newer than the deployment target. + cflags += [ "-Wunguarded-availability" ] + } + + if (is_ios) { + # When compiling Objective-C, warns if a selector named via @selector has + # not been defined in any visible interface. + cflags += [ "-Wundeclared-selector" ] + } + + # Suppress warnings about ABI changes on ARM (Clang doesn't give this + # warning). + if (target_cpu == "arm" && !is_clang) { + cflags += [ "-Wno-psabi" ] + } + + if (!is_clang) { + cflags_cc += [ + # See comment for -Wno-c++11-narrowing. + "-Wno-narrowing", + ] + + # -Wno-class-memaccess warns about hash table and vector in blink. + # But the violation is intentional. + if (!is_nacl) { + cflags_cc += [ "-Wno-class-memaccess" ] + } + + # -Wunused-local-typedefs is broken in gcc, + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63872 + cflags += [ "-Wno-unused-local-typedefs" ] + + # Don't warn about "maybe" uninitialized. Clang doesn't include this + # in -Wall but gcc does, and it gives false positives. + cflags += [ "-Wno-maybe-uninitialized" ] + cflags += [ "-Wno-deprecated-declarations" ] + + # -Wcomment gives too many false positives in the case a + # backslash ended comment line is followed by a new line of + # comments + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61638 + cflags += [ "-Wno-comments" ] + + # -Wpacked-not-aligned complains all generated mojom-shared-internal.h + # files. + cflags += [ "-Wno-packed-not-aligned" ] + } + } + + # Common Clang and GCC warning setup. + if (!is_win || is_clang) { + cflags += [ + # Disables. + "-Wno-missing-field-initializers", # "struct foo f = {0};" + "-Wno-unused-parameter", # Unused function parameters. + ] + } + + if (is_clang) { + cflags += [ + "-Wloop-analysis", + + # TODO(thakis): This used to be implied by -Wno-unused-function, + # which we no longer use. Check if it makes sense to remove + # this as well. http://crbug.com/316352 + "-Wno-unneeded-internal-declaration", + ] + + # use_xcode_clang only refers to the iOS toolchain, host binaries use + # chromium's clang always. + if (!is_nacl || is_nacl_saigo) { + if (is_win) { + # TODO(thakis): https://crbug.com/617318 + # Currently goma can not handle case sensitiveness for windows well. + cflags += [ "-Wno-nonportable-include-path" ] + + # Warns in ATL headers; see https://crbug.com/1208419. + cflags += [ "-Wno-null-pointer-subtraction" ] + } + + if (current_toolchain == host_toolchain || !use_xcode_clang) { + # Flags Xcode 9.2 (Clang clang-900.0.39.2) does not recognize. + cflags += [ + "-Wenum-compare-conditional", + + # An ABI compat warning we don't care about, https://crbug.com/1102157 + # TODO(thakis): Push this to the (few) targets that need it, + # instead of having a global flag. + "-Wno-psabi", + + # Ignore warnings about MSVC optimization pragmas. + # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662 + "-Wno-ignored-pragma-optimize", + + # TODO(https://crbug.com/1016945) Clean up, enable. + "-Wno-builtin-assume-aligned-alignment", + ] + + # NaCl does not support flags from ToT. + if (!is_nacl) { + cflags += [ + # TODO(https://crbug.com/1203071): Clean up and enable. + "-Wno-unused-but-set-parameter", + "-Wno-unused-but-set-variable", + ] + } + + if (is_fuchsia) { + # TODO(https://bugs.chromium.org/p/fuchsia/issues/detail?id=77383) + cflags += [ "-Wno-deprecated-copy" ] + } + + if (enable_wmax_tokens) { + cflags += [ "-Wmax-tokens" ] + } + } + } + } +} + +# chromium_code --------------------------------------------------------------- +# +# Toggles between higher and lower warnings for code that is (or isn't) +# part of Chromium. + +config("chromium_code") { + if (is_win) { + cflags = [ "/W4" ] # Warning level 4. + + if (is_clang) { + # Opt in to additional [[nodiscard]] on standard library methods. + defines = [ "_HAS_NODISCARD" ] + } + } else { + cflags = [ "-Wall" ] + if (treat_warnings_as_errors) { + cflags += [ "-Werror" ] + + # The compiler driver can sometimes (rarely) emit warnings before calling + # the actual linker. Make sure these warnings are treated as errors as + # well. + ldflags = [ "-Werror" ] + } + if (is_clang) { + # Enable extra warnings for chromium_code when we control the compiler. + cflags += [ "-Wextra" ] + } + + # In Chromium code, we define __STDC_foo_MACROS in order to get the + # C99 macros on Mac and Linux. + defines = [ + "__STDC_CONSTANT_MACROS", + "__STDC_FORMAT_MACROS", + ] + + if (!is_debug && !using_sanitizer && target_cpu != "s390x" && + target_cpu != "s390" && target_cpu != "ppc64" && + target_cpu != "mips" && target_cpu != "mips64") { + # Non-chromium code is not guaranteed to compile cleanly with + # _FORTIFY_SOURCE. Also, fortified build may fail when optimizations are + # disabled, so only do that for Release build. + defines += [ "_FORTIFY_SOURCE=2" ] + } + + if (is_mac) { + cflags_objc = [ "-Wobjc-missing-property-synthesis" ] + cflags_objcc = [ "-Wobjc-missing-property-synthesis" ] + } + + if (is_ios) { + cflags_objc = [ "-Wimplicit-retain-self" ] + cflags_objcc = cflags_objc + } + } + + if (is_clang) { + cflags += [ + # Warn on missing break statements at the end of switch cases. + # For intentional fallthrough, use FALLTHROUGH; from + # base/compiler_specific.h + "-Wimplicit-fallthrough", + ] + + # TODO(thakis): Enable this more often, https://crbug.com/346399 + # use_libfuzzer: https://crbug.com/1063180 + if (!is_nacl && !use_libfuzzer) { + cflags += [ "-Wunreachable-code-aggressive" ] + } + + # Thread safety analysis is broken under nacl: https://crbug.com/982423. + if (!is_nacl) { + cflags += [ + # Thread safety analysis. See base/thread_annotations.h and + # https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + "-Wthread-safety", + ] + } + + # TODO(thakis): Enable this for more platforms, https://crbug.com/926235 + # ChromeOS: http://crbug.com/940863 + # Chromecast: http://crbug.com/942554 + has_dchecks = is_debug || dcheck_always_on + if (!has_dchecks && is_chromeos_ash && is_chrome_branded) { + # Temporarily disable -Wextra-semi for Chrome on Chrome OS. + } else if (is_chromecast && chromecast_branding != "public") { + # Temporarily disable -Wextra-semi for Chromecast. + } else { + cflags += [ "-Wextra-semi" ] + } + } + + configs = [ ":default_warnings" ] +} + +config("no_chromium_code") { + cflags = [] + cflags_cc = [] + defines = [] + + if (is_win) { + cflags += [ + "/W3", # Warning level 3. + "/wd4800", # Disable warning when forcing value to bool. + "/wd4267", # TODO(jschuh): size_t to int. + "/wd4996", # Deprecated function warning. + ] + defines += [ + "_CRT_NONSTDC_NO_WARNINGS", + "_CRT_NONSTDC_NO_DEPRECATE", + ] + } else { + # GCC may emit unsuppressible warnings so don't add -Werror for no chromium + # code. crbug.com/589724 + if (treat_warnings_as_errors && is_clang) { + cflags += [ "-Werror" ] + ldflags = [ "-Werror" ] + } + if (is_clang && !is_nacl) { + # TODO(thakis): Remove !is_nacl once + # https://codereview.webrtc.org/1552863002/ made its way into chromium. + cflags += [ "-Wall" ] + } + } + + if (is_clang) { + cflags += [ + # Lots of third-party libraries have unused variables. Instead of + # suppressing them individually, we just blanket suppress them here. + "-Wno-unused-variable", + + # Similarly, we're not going to fix all the C++11 narrowing issues in + # third-party libraries. + "-Wno-c++11-narrowing", + ] + if (!is_nacl && (current_toolchain == host_toolchain || !use_xcode_clang)) { + cflags += [ + # TODO(https://crbug.com/1202159): Clean up and enable. + "-Wno-misleading-indentation", + ] + } + } + + configs = [ ":default_warnings" ] +} + +# noshadowing ----------------------------------------------------------------- +# +# Allows turning -Wshadow on. + +config("noshadowing") { + # This flag has to be disabled for nacl because the nacl compiler is too + # strict about shadowing. + if (is_clang && !is_nacl) { + cflags = [ "-Wshadow" ] + } +} + +# rtti ------------------------------------------------------------------------ +# +# Allows turning Run-Time Type Identification on or off. + +config("rtti") { + if (is_win) { + cflags_cc = [ "/GR" ] + } else { + cflags_cc = [ "-frtti" ] + } +} + +config("no_rtti") { + # Some sanitizer configs may require RTTI to be left enabled globally + if (!use_rtti) { + if (is_win) { + cflags_cc = [ "/GR-" ] + } else { + cflags_cc = [ "-fno-rtti" ] + cflags_objcc = cflags_cc + } + } +} + +# export_dynamic --------------------------------------------------------------- +# +# Ensures all exported symbols are added to the dynamic symbol table. This is +# necessary to expose Chrome's custom operator new() and operator delete() (and +# other memory-related symbols) to libraries. Otherwise, they might +# (de)allocate memory on a different heap, which would spell trouble if pointers +# to heap-allocated memory are passed over shared library boundaries. +config("export_dynamic") { + # TODO(crbug.com/1052397): Revisit after target_os flip is completed. + if (is_linux || is_bsd || is_chromeos_lacros || export_libcxxabi_from_executables) { + ldflags = [ "-rdynamic" ] + } +} + +# thin_archive ----------------------------------------------------------------- +# +# Enables thin archives on posix, and on windows when the lld linker is used. +# Regular archives directly include the object files used to generate it. +# Thin archives merely reference the object files. +# This makes building them faster since it requires less disk IO, but is +# inappropriate if you wish to redistribute your static library. +# This config is added to the global config, so thin archives should already be +# enabled. If you want to make a distributable static library, you need to do 2 +# things: +# 1. Set complete_static_lib so that all dependencies of the library make it +# into the library. See `gn help complete_static_lib` for details. +# 2. Remove the thin_archive config, so that the .a file actually contains all +# .o files, instead of just references to .o files in the build directoy +config("thin_archive") { + # The macOS and iOS default linker ld64 does not support reading thin + # archives. + # TODO(crbug.com/1221615): Enable on is_apple if use_lld once that no longer + # confuses lldb. + if ((is_posix && !is_nacl && !is_apple) || is_fuchsia) { + arflags = [ "-T" ] + } else if (is_win && use_lld) { + arflags = [ "/llvmlibthin" ] + } +} + +# exceptions ------------------------------------------------------------------- +# +# Allows turning Exceptions on or off. +# Note: exceptions are disallowed in Google code. + +config("exceptions") { + if (is_win) { + # Enables exceptions in the STL. + if (!use_custom_libcxx) { + defines = [ "_HAS_EXCEPTIONS=1" ] + } + cflags_cc = [ "/EHsc" ] + } else { + cflags_cc = [ "-fexceptions" ] + cflags_objcc = cflags_cc + } +} + +config("no_exceptions") { + if (is_win) { + # Disables exceptions in the STL. + # libc++ uses the __has_feature macro to control whether to use exceptions, + # so defining this macro is unnecessary. Defining _HAS_EXCEPTIONS to 0 also + # breaks libc++ because it depends on MSVC headers that only provide certain + # declarations if _HAS_EXCEPTIONS is 1. Those MSVC headers do not use + # exceptions, despite being conditional on _HAS_EXCEPTIONS. + if (!use_custom_libcxx) { + defines = [ "_HAS_EXCEPTIONS=0" ] + } + } else { + cflags_cc = [ "-fno-exceptions" ] + cflags_objcc = cflags_cc + } +} + +# Warnings --------------------------------------------------------------------- + +# Generate a warning for code that might emit a static initializer. +# See: //docs/static_initializers.md +# See: https://groups.google.com/a/chromium.org/d/topic/chromium-dev/B9Q5KTD7iCo/discussion +config("wglobal_constructors") { + if (is_clang) { + cflags = [ "-Wglobal-constructors" ] + } +} + +# This will generate warnings when using Clang if code generates exit-time +# destructors, which will slow down closing the program. +# TODO(thakis): Make this a blocklist instead, http://crbug.com/101600 +config("wexit_time_destructors") { + if (is_clang) { + cflags = [ "-Wexit-time-destructors" ] + } +} + +# Some code presumes that pointers to structures/objects are compatible +# regardless of whether what they point to is already known to be valid. +# gcc 4.9 and earlier had no way of suppressing this warning without +# suppressing the rest of them. Here we centralize the identification of +# the gcc 4.9 toolchains. +config("no_incompatible_pointer_warnings") { + cflags = [] + if (is_clang) { + cflags += [ "-Wno-incompatible-pointer-types" ] + } else if (target_cpu == "mipsel" || target_cpu == "mips64el") { + cflags += [ "-w" ] + } else if (is_chromeos_ash && target_cpu == "arm") { + cflags += [ "-w" ] + } +} + +# Optimization ----------------------------------------------------------------- +# +# The BUILDCONFIG file sets the "default_optimization" config on targets by +# default. It will be equivalent to either "optimize" (release) or +# "no_optimize" (debug) optimization configs. +# +# You can override the optimization level on a per-target basis by removing the +# default config and then adding the named one you want: +# +# configs -= [ "//build/config/compiler:default_optimization" ] +# configs += [ "//build/config/compiler:optimize_max" ] + +# Shared settings for both "optimize" and "optimize_max" configs. +# IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags. +if (is_win) { + common_optimize_on_cflags = [ + "/Ob2", # Both explicit and auto inlining. + "/Oy-", # Disable omitting frame pointers, must be after /O2. + "/Zc:inline", # Remove unreferenced COMDAT (faster links). + ] + if (!is_asan) { + common_optimize_on_cflags += [ + # Put data in separate COMDATs. This allows the linker + # to put bit-identical constants at the same address even if + # they're unrelated constants, which saves binary size. + # This optimization can't be used when ASan is enabled because + # it is not compatible with the ASan ODR checker. + "/Gw", + ] + } + common_optimize_on_ldflags = [] + + # /OPT:ICF is not desirable in Debug builds, since code-folding can result in + # misleading symbols in stack traces. + if (!is_debug && !is_component_build) { + common_optimize_on_ldflags += [ "/OPT:ICF" ] # Redundant COMDAT folding. + } + + if (is_official_build) { + common_optimize_on_ldflags += [ "/OPT:REF" ] # Remove unreferenced data. + # TODO(thakis): Add LTO/PGO clang flags eventually, https://crbug.com/598772 + } +} else { + common_optimize_on_cflags = [] + common_optimize_on_ldflags = [] + + if (is_android) { + # TODO(jdduke) Re-enable on mips after resolving linking + # issues with libc++ (crbug.com/456380). + if (target_cpu != "mipsel" && target_cpu != "mips64el") { + common_optimize_on_ldflags += [ + # Warn in case of text relocations. + "-Wl,--warn-shared-textrel", + ] + } + } + + if (is_apple) { + common_optimize_on_ldflags += [ "-Wl,-dead_strip" ] + + if (is_official_build) { + common_optimize_on_ldflags += [ + "-Wl,-no_data_in_code_info", + "-Wl,-no_function_starts", + ] + } + } else if (current_os != "aix") { + # Non-Mac Posix flags. + # Aix does not support these. + + common_optimize_on_cflags += [ + # Put data and code in their own sections, so that unused symbols + # can be removed at link time with --gc-sections. + "-fdata-sections", + "-ffunction-sections", + ] + if (!is_nacl && is_clang) { + # We don't care about unique section names, this makes object files a bit + # smaller. + common_optimize_on_cflags += [ "-fno-unique-section-names" ] + } + + common_optimize_on_ldflags += [ + # Specifically tell the linker to perform optimizations. + # See http://lwn.net/Articles/192624/ . + # -O2 enables string tail merge optimization in gold and lld. + "-Wl,-O2", + "-Wl,--gc-sections", + ] + } +} + +config("default_stack_frames") { + if (is_posix || is_fuchsia) { + if (enable_frame_pointers) { + cflags = [ "-fno-omit-frame-pointer" ] + + # Omit frame pointers for leaf functions on x86, otherwise building libyuv + # gives clang's register allocator issues, see llvm.org/PR15798 / + # crbug.com/233709 + if (is_clang && target_cpu == "x86" && !is_apple) { + cflags += [ "-momit-leaf-frame-pointer" ] + } + } else { + cflags = [ "-fomit-frame-pointer" ] + } + } + # On Windows, the flag to enable framepointers "/Oy-" must always come after + # the optimization flag [e.g. "/O2"]. The optimization flag is set by one of + # the "optimize" configs, see rest of this file. The ordering that cflags are + # applied is well-defined by the GN spec, and there is no way to ensure that + # cflags set by "default_stack_frames" is applied after those set by an + # "optimize" config. Similarly, there is no way to propagate state from this + # config into the "optimize" config. We always apply the "/Oy-" config in the + # definition for common_optimize_on_cflags definition, even though this may + # not be correct. +} + +# Default "optimization on" config. +config("optimize") { + if (is_win) { + if (chrome_pgo_phase != 2) { + # Favor size over speed, /O1 must be before the common flags. + # /O1 implies /Os and /GF. + cflags = [ "/O1" ] + common_optimize_on_cflags + [ "/Oi" ] + } else { + # PGO requires all translation units to be compiled with /O2. The actual + # optimization level will be decided based on the profiling data. + cflags = [ "/O2" ] + common_optimize_on_cflags + [ "/Oi" ] + } + } else if (optimize_for_size && !is_nacl) { + # Favor size over speed. + # TODO(crbug.com/718650): Fix -Os in PNaCl compiler and remove the is_nacl + # guard above. + if (is_clang) { + cflags = [ "-Oz" ] + common_optimize_on_cflags + } else { + cflags = [ "-Os" ] + common_optimize_on_cflags + } + } else if (is_chromeos_ash) { + # TODO(gbiv): This is partially favoring size over speed. CrOS exclusively + # uses clang, and -Os in clang is more of a size-conscious -O2 than "size at + # any cost" (AKA -Oz). It'd be nice to: + # - Make `optimize_for_size` apply to all platforms where we're optimizing + # for size by default (so, also Windows) + # - Investigate -Oz here, maybe just for ARM? + cflags = [ "-Os" ] + common_optimize_on_cflags + } else { + cflags = [ "-O2" ] + common_optimize_on_cflags + } + if (optimize_for_size) { + rustflags = [ "-Copt-level=s" ] + } else { + rustflags = [ "-Copt-level=3" ] + } + ldflags = common_optimize_on_ldflags +} + +# Turn off optimizations. +config("no_optimize") { + if (is_win) { + cflags = [ + "/Od", # Disable optimization. + "/Ob0", # Disable all inlining (on by default). + "/GF", # Enable string pooling (off by default). + ] + + if (target_cpu == "arm64") { + # Disable omitting frame pointers for no_optimize build because stack + # traces on Windows ARM64 rely on it. + cflags += [ "/Oy-" ] + } + } else if (is_android && !android_full_debug) { + # On Android we kind of optimize some things that don't affect debugging + # much even when optimization is disabled to get the binary size down. + if (is_clang) { + cflags = [ "-Oz" ] + common_optimize_on_cflags + } else { + cflags = [ "-Os" ] + common_optimize_on_cflags + } + + if (!is_component_build) { + # Required for library partitions. Without this all symbols just end up + # in the base partition. + ldflags = [ "-Wl,--gc-sections" ] + } + } else if (is_fuchsia) { + # On Fuchsia, we optimize for size here to reduce the size of debug build + # packages so they can be run in a KVM. See crbug.com/910243 for details. + cflags = [ "-Og" ] + } else { + cflags = [ "-O0" ] + ldflags = [] + } +} + +# Turns up the optimization level. On Windows, this implies whole program +# optimization and link-time code generation which is very expensive and should +# be used sparingly. +config("optimize_max") { + if (is_nacl && is_nacl_irt) { + # The NaCl IRT is a special case and always wants its own config. + # Various components do: + # if (!is_debug) { + # configs -= [ "//build/config/compiler:default_optimization" ] + # configs += [ "//build/config/compiler:optimize_max" ] + # } + # So this config has to have the selection logic just like + # "default_optimization", below. + configs = [ "//build/config/nacl:irt_optimize" ] + } else { + ldflags = common_optimize_on_ldflags + if (is_win) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O2" ] + common_optimize_on_cflags + } + rustflags = [ "-Copt-level=3" ] + } +} + +# This config can be used to override the default settings for per-component +# and whole-program optimization, optimizing the particular target for speed +# instead of code size. This config is exactly the same as "optimize_max" +# except that we use -O3 instead of -O2 on non-win, non-IRT platforms. +# +# TODO(crbug.com/621335) - rework how all of these configs are related +# so that we don't need this disclaimer. +config("optimize_speed") { + if (is_nacl && is_nacl_irt) { + # The NaCl IRT is a special case and always wants its own config. + # Various components do: + # if (!is_debug) { + # configs -= [ "//build/config/compiler:default_optimization" ] + # configs += [ "//build/config/compiler:optimize_max" ] + # } + # So this config has to have the selection logic just like + # "default_optimization", below. + configs = [ "//build/config/nacl:irt_optimize" ] + } else { + ldflags = common_optimize_on_ldflags + if (is_win) { + # Favor speed over size, /O2 must be before the common flags. + # /O2 implies /Ot, /Oi, and /GF. + cflags = [ "/O2" ] + common_optimize_on_cflags + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O3" ] + common_optimize_on_cflags + } + rustflags = [ "-Copt-level=3" ] + } +} + +config("optimize_fuzzing") { + cflags = [ "-O1" ] + common_optimize_on_cflags + rustflags = [ "-Copt-level=1" ] + ldflags = common_optimize_on_ldflags + visibility = [ ":default_optimization" ] +} + +# The default optimization applied to all targets. This will be equivalent to +# either "optimize" or "no_optimize", depending on the build flags. +config("default_optimization") { + if (is_nacl && is_nacl_irt) { + # The NaCl IRT is a special case and always wants its own config. + # It gets optimized the same way regardless of the type of build. + configs = [ "//build/config/nacl:irt_optimize" ] + } else if (is_debug) { + configs = [ ":no_optimize" ] + } else if (optimize_for_fuzzing) { + assert(!is_win, "Fuzzing optimize level not supported on Windows") + + # Coverage build is quite slow. Using "optimize_for_fuzzing" makes it even + # slower as it uses "-O1" instead of "-O3". Prevent that from happening. + assert(!use_clang_coverage, + "optimize_for_fuzzing=true should not be used with " + + "use_clang_coverage=true.") + configs = [ ":optimize_fuzzing" ] + } else { + configs = [ ":optimize" ] + } +} + +_clang_sample_profile = "" +if (is_clang && is_a_target_toolchain) { + if (clang_sample_profile_path != "") { + _clang_sample_profile = clang_sample_profile_path + } else if (clang_use_default_sample_profile) { + assert(build_with_chromium, + "Our default profiles currently only apply to Chromium") + assert(is_android || is_chromeos_lacros || is_chromeos_ash || is_chromecast, + "The current platform has no default profile") + if (is_android || is_chromecast) { + _clang_sample_profile = "//chrome/android/profiles/afdo.prof" + } else { + assert(chromeos_afdo_platform == "atom" || + chromeos_afdo_platform == "bigcore", + "Only atom and bigcore are valid Chrome OS profiles.") + _clang_sample_profile = + "//chromeos/profiles/${chromeos_afdo_platform}.afdo.prof" + } + } +} + +# Clang offers a way to assert that AFDO profiles are accurate, which causes it +# to optimize functions not represented in a profile more aggressively for size. +# This config can be toggled in cases where shaving off binary size hurts +# performance too much. +config("afdo_optimize_size") { + if (_clang_sample_profile != "" && sample_profile_is_accurate) { + cflags = [ "-fprofile-sample-accurate" ] + } +} + +# GCC and clang support a form of profile-guided optimization called AFDO. +# There are some targeted places that AFDO regresses (and an icky interaction +# between //base/allocator:tcmalloc and AFDO on GCC), so we provide a separate +# config to allow AFDO to be disabled per-target. +config("afdo") { + if (is_clang) { + cflags = [] + if (clang_emit_debug_info_for_profiling) { + # Add the following flags to generate debug info for profiling. + cflags += [ "-gline-tables-only" ] + if (!is_nacl) { + cflags += [ "-fdebug-info-for-profiling" ] + } + } + if (_clang_sample_profile != "") { + assert(chrome_pgo_phase == 0, "AFDO can't be used in PGO builds") + rebased_clang_sample_profile = + rebase_path(_clang_sample_profile, root_build_dir) + cflags += [ "-fprofile-sample-use=${rebased_clang_sample_profile}" ] + inputs = [ _clang_sample_profile ] + } + } else if (auto_profile_path != "" && is_a_target_toolchain) { + cflags = [ "-fauto-profile=${auto_profile_path}" ] + inputs = [ auto_profile_path ] + } +} + +# Symbols ---------------------------------------------------------------------- + +# The BUILDCONFIG file sets the "default_symbols" config on targets by +# default. It will be equivalent to one the three specific symbol levels. +# +# You can override the symbol level on a per-target basis by removing the +# default config and then adding the named one you want: +# +# configs -= [ "//build/config/compiler:default_symbols" ] +# configs += [ "//build/config/compiler:symbols" ] + +# A helper config that all configs passing /DEBUG to the linker should +# include as sub-config. +config("win_pdbaltpath") { + visibility = [ + ":minimal_symbols", + ":symbols", + ] + + # /DEBUG causes the linker to generate a pdb file, and to write the absolute + # path to it in the executable file it generates. This flag turns that + # absolute path into just the basename of the pdb file, which helps with + # build reproducibility. Debuggers look for pdb files next to executables, + # so there's minimal downside to always using this. However, post-mortem + # debugging of Chromium crash dumps and ETW tracing can be complicated by this + # switch so an option to omit it is important. + if (!use_full_pdb_paths) { + ldflags = [ "/pdbaltpath:%_PDB%" ] + } +} + +# Full symbols. +config("symbols") { + if (is_win) { + if (is_clang) { + cflags = [ "/Z7" ] # Debug information in the .obj files. + } else { + cflags = [ "/Zi" ] # Produce PDB file, no edit and continue. + } + + if (is_clang && use_lld && use_ghash) { + cflags += [ "-gcodeview-ghash" ] + ldflags = [ "/DEBUG:GHASH" ] + } else { + ldflags = [ "/DEBUG" ] + } + + # All configs using /DEBUG should include this: + configs = [ ":win_pdbaltpath" ] + } else { + cflags = [] + if (is_mac && enable_dsyms) { + # If generating dSYMs, specify -fno-standalone-debug. This was + # originally specified for https://crbug.com/479841 because dsymutil + # could not handle a 4GB dSYM file. But dsymutil from Xcodes prior to + # version 7 also produces debug data that is incompatible with Breakpad + # dump_syms, so this is still required (https://crbug.com/622406). + cflags += [ "-fno-standalone-debug" ] + } else if (is_mac && !use_dwarf5) { + # clang defaults to DWARF2 on macOS unless mac_deployment_target is + # at least 10.11. + # TODO(thakis): Remove this once mac_deployment_target is 10.11. + cflags += [ "-gdwarf-4" ] + } + + if (use_dwarf5 && !is_nacl) { + cflags += [ "-gdwarf-5" ] + } + + # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see + # elsewhere in this file), so they can't have build-dir-independent output. + # Disable symbols for nacl object files to get deterministic, + # build-directory-independent output. pnacl and nacl-clang do support that + # flag, so we can use use -g1 for pnacl and nacl-clang compiles. + # gcc nacl is is_nacl && !is_clang, pnacl and nacl-clang are && is_clang. + if (!is_nacl || is_clang) { + cflags += [ "-g2" ] + } + + if (!is_nacl && is_clang && !is_tsan && !is_asan) { + # gcc generates dwarf-aranges by default on -g1 and -g2. On clang it has + # to be manually enabled. + # + # It is skipped in tsan and asan because enabling it causes some + # formatting changes in the output which would require fixing bunches + # of expectation regexps. + cflags += [ "-gdwarf-aranges" ] + } + + if (is_apple) { + swiftflags = [ "-g" ] + } + + if (use_debug_fission) { + cflags += [ "-gsplit-dwarf" ] + } + asmflags = cflags + ldflags = [] + + # Split debug info with all thinlto builds except nacl and apple. + # thinlto requires -gsplit-dwarf in ldflags. + if (use_debug_fission && use_thin_lto && !is_nacl && !is_apple) { + ldflags += [ "-gsplit-dwarf" ] + } + + # TODO(thakis): Figure out if there's a way to make this go for 32-bit, + # currently we get "warning: + # obj/native_client/src/trusted/service_runtime/sel_asm/nacl_switch_32.o: + # DWARF info may be corrupt; offsets in a range list entry are in different + # sections" there. Maybe just a bug in nacl_switch_32.S. + if (!is_apple && !is_nacl && target_cpu != "x86" && + (use_gold || use_lld)) { + if (is_clang) { + # This flag enables the GNU-format pubnames and pubtypes sections, + # which lld needs in order to generate a correct GDB index. + # TODO(pcc): Try to make lld understand non-GNU-format pubnames + # sections (llvm.org/PR34820). + cflags += [ "-ggnu-pubnames" ] + } + ldflags += [ "-Wl,--gdb-index" ] + } + } + + if (is_clang && !is_nacl && !use_xcode_clang) { + if (is_apple) { + # TODO(https://crbug.com/1050118): Investigate missing debug info on mac. + # Make sure we don't use constructor homing on mac. + cflags += [ + "-Xclang", + "-debug-info-kind=limited", + ] + } else { + # Use constructor homing for debug info. This option reduces debug info + # by emitting class type info only when constructors are emitted. + cflags += [ + "-Xclang", + "-fuse-ctor-homing", + ] + } + } + rustflags = [ "-g" ] +} + +# Minimal symbols. +# This config guarantees to hold symbol for stack trace which are shown to user +# when crash happens in unittests running on buildbot. +config("minimal_symbols") { + if (is_win) { + # Functions, files, and line tables only. + cflags = [] + + if (is_clang && use_lld && use_ghash) { + cflags += [ "-gcodeview-ghash" ] + ldflags = [ "/DEBUG:GHASH" ] + } else { + ldflags = [ "/DEBUG" ] + } + + # All configs using /DEBUG should include this: + configs = [ ":win_pdbaltpath" ] + + # Enable line tables for clang. MSVC doesn't have an equivalent option. + if (is_clang) { + # -gline-tables-only is the same as -g1, but clang-cl only exposes the + # former. + cflags += [ "-gline-tables-only" ] + } + } else { + cflags = [] + if (is_mac && !use_dwarf5) { + # clang defaults to DWARF2 on macOS unless mac_deployment_target is + # at least 10.11. + # TODO(thakis): Remove this once mac_deployment_target is 10.11. + cflags += [ "-gdwarf-4" ] + } + + if (use_dwarf5 && !is_nacl) { + cflags += [ "-gdwarf-5" ] + } + + # The gcc-based nacl compilers don't support -fdebug-compilation-dir (see + # elsewhere in this file), so they can't have build-dir-independent output. + # Disable symbols for nacl object files to get deterministic, + # build-directory-independent output. pnacl and nacl-clang do support that + # flag, so we can use use -g1 for pnacl and nacl-clang compiles. + # gcc nacl is is_nacl && !is_clang, pnacl and nacl-clang are && is_clang. + if (!is_nacl || is_clang) { + cflags += [ "-g1" ] + } + + if (!is_nacl && is_clang && !is_tsan && !is_asan) { + # See comment for -gdwarf-aranges in config("symbols"). + cflags += [ "-gdwarf-aranges" ] + } + + ldflags = [] + if (is_android && is_clang) { + # Android defaults to symbol_level=1 builds in production builds + # (https://crbug.com/648948), but clang, unlike gcc, doesn't emit + # DW_AT_linkage_name in -g1 builds. -fdebug-info-for-profiling enables + # that (and a bunch of other things we don't need), so that we get + # qualified names in stacks. + # TODO(thakis): Consider making clang emit DW_AT_linkage_name in -g1 mode; + # failing that consider doing this on non-Android too. + cflags += [ "-fdebug-info-for-profiling" ] + } + + # Note: debug_fission is no-op with symbol_level=1 since all -g1 debug_info + # will stay in the executable. + + asmflags = cflags + } + rustflags = [ "-Cdebuginfo=1" ] +} + +# This configuration contains function names only. That is, the compiler is +# told to not generate debug information and the linker then just puts function +# names in the final debug information. +config("no_symbols") { + if (is_win) { + ldflags = [ "/DEBUG" ] + + # All configs using /DEBUG should include this: + configs = [ ":win_pdbaltpath" ] + } else { + cflags = [ "-g0" ] + asmflags = cflags + } +} + +# Default symbols. +config("default_symbols") { + if (symbol_level == 0) { + configs = [ ":no_symbols" ] + } else if (symbol_level == 1) { + configs = [ ":minimal_symbols" ] + } else if (symbol_level == 2) { + configs = [ ":symbols" ] + } else { + assert(false) + } + + # This config is removed by base unittests apk. + if (is_android && is_clang && strip_debug_info) { + configs += [ ":strip_debug" ] + } +} + +config("strip_debug") { + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ "-Wl,--strip-debug" ] +} + +if (is_apple) { + # On Mac and iOS, this enables support for ARC (automatic ref-counting). + # See http://clang.llvm.org/docs/AutomaticReferenceCounting.html. + config("enable_arc") { + common_flags = [ "-fobjc-arc" ] + cflags_objc = common_flags + cflags_objcc = common_flags + } +} + +if (is_chromeos_ash && is_chromeos_device) { + # This config is intended to be a temporary to facilitate + # the transition to use orderfile in Chrome OS. Once orderfile + # use becomes a default in Chrome OS, this config should not + # be needed. + config("use_orderfile_for_hugepage") { + if (chrome_orderfile_path != "") { + defines = [ "CHROMEOS_ORDERFILE_USE" ] + } + } +} + +if (is_android || (is_chromeos_ash && is_chromeos_device)) { + # Use orderfile for linking Chrome on Android and Chrome OS. + # This config enables using an orderfile for linking in LLD. + # TODO: Consider using call graph sort instead, at least on Android. + config("chrome_orderfile_config") { + if (chrome_orderfile_path != "" && !enable_call_graph_profile_sort) { + assert(use_lld) + _rebased_orderfile = rebase_path(chrome_orderfile_path, root_build_dir) + ldflags = [ + "-Wl,--symbol-ordering-file", + "-Wl,$_rebased_orderfile", + "-Wl,--no-warn-symbol-ordering", + ] + inputs = [ chrome_orderfile_path ] + } + } +} + +# Initialize all variables on the stack if needed. +config("default_init_stack_vars") { + cflags = [] + if (init_stack_vars && is_clang && !is_nacl && !using_sanitizer) { + cflags += [ "-ftrivial-auto-var-init=pattern" ] + } +} + +buildflag_header("compiler_buildflags") { + header = "compiler_buildflags.h" + + flags = [ + "CLANG_PGO=$chrome_pgo_phase", + "SYMBOL_LEVEL=$symbol_level", + ] +} + +config("cet_shadow_stack") { + if (enable_cet_shadow_stack && is_win) { + assert(target_cpu == "x64") + ldflags = [ "/CETCOMPAT" ] + } +} diff --git a/third_party/libwebrtc/build/config/compiler/compiler.gni b/third_party/libwebrtc/build/config/compiler/compiler.gni new file mode 100644 index 0000000000..55ae571ab7 --- /dev/null +++ b/third_party/libwebrtc/build/config/compiler/compiler.gni @@ -0,0 +1,324 @@ +# 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. + +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/compiler/pgo/pgo.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/cc_wrapper.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +if (is_android) { + import("//build/config/android/abi.gni") +} +if (target_cpu == "arm" || target_cpu == "arm64") { + import("//build/config/arm.gni") +} + +if (is_apple) { + import("//build/config/apple/symbols.gni") +} + +if (is_ios) { + import("//build/config/ios/config.gni") +} + +declare_args() { + # Default to warnings as errors for default workflow, where we catch + # warnings with known toolchains. Allow overriding this e.g. for Chromium + # builds on Linux that could use a different version of the compiler. + # With GCC, warnings in no-Chromium code are always not treated as errors. + treat_warnings_as_errors = true + + # How many symbols to include in the build. This affects the performance of + # the build since the symbols are large and dealing with them is slow. + # 2 means regular build with symbols. + # 1 means minimal symbols, usually enough for backtraces only. Symbols with + # internal linkage (static functions or those in anonymous namespaces) may not + # appear when using this level. + # 0 means no symbols. + # -1 means auto-set according to debug/release and platform. + symbol_level = -1 + + # Android-only: Strip the debug info of libraries within lib.unstripped to + # reduce size. As long as symbol_level > 0, this will still allow stacks to be + # symbolized. + strip_debug_info = false + + # Compile in such a way as to enable profiling of the generated code. For + # example, don't omit the frame pointer and leave in symbols. + enable_profiling = false + + # use_debug_fission: whether to use split DWARF debug info + # files. This can reduce link time significantly, but is incompatible + # with some utilities such as icecc and ccache. Requires gold and + # gcc >= 4.8 or clang. + # http://gcc.gnu.org/wiki/DebugFission + # + # This is a placeholder value indicating that the code below should set + # the default. This is necessary to delay the evaluation of the default + # value expression until after its input values such as use_gold have + # been set, e.g. by a toolchain_args() block. + use_debug_fission = "default" + + # Enables support for ThinLTO, which links 3x-10x faster than full LTO. See + # also http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html + # Use it by default on official-optimized android and Chrome OS builds, but + # not ARC or linux-chromeos since it's been seen to not play nicely with + # Chrome's clang. crbug.com/1033839 + use_thin_lto = + is_cfi || + (is_official_build && chrome_pgo_phase != 1 && + (is_linux || is_win || (is_android && target_os != "chromeos") || + ((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device))) + + # If true, use Goma for ThinLTO code generation where applicable. + use_goma_thin_lto = false + + # Whether we're using a sample profile collected on an architecture different + # than the one we're compiling for. + # + # It's currently not possible to collect AFDO profiles on anything but + # x86{,_64}. + using_mismatched_sample_profile = target_cpu != "x64" && target_cpu != "x86" + + # Whether an error should be raised on attempts to make debug builds with + # is_component_build=false. Very large debug symbols can have unwanted side + # effects so this is enforced by default for chromium. + forbid_non_component_debug_builds = build_with_chromium + + # Exclude unwind tables by default for official builds as unwinding can be + # done from stack dumps produced by Crashpad at a later time "offline" in the + # crash server. Since this increases binary size, we don't recommend including + # them in shipping builds. + # For unofficial (e.g. development) builds and non-Chrome branded (e.g. Cronet + # which doesn't use Crashpad, crbug.com/479283) builds it's useful to be able + # to unwind at runtime. + # Include the unwind tables on Android even for official builds, as otherwise + # the crash dumps generated by Android's debuggerd are largely useless, and + # having this additional mechanism to understand issues is particularly helpful + # to WebView. + exclude_unwind_tables = is_official_build && !is_android + + # Where to redirect clang crash diagnoses + clang_diagnostic_dir = + rebase_path("//tools/clang/crashreports", root_build_dir) + + # Mark binaries as compatible with Shadow Stack of Control-flow Enforcement + # Technology (CET). If Windows version and hardware supports the feature and + # it's enabled by OS then additional validation of return address will be + # performed as mitigation against Return-oriented programming (ROP). + # https://chromium.googlesource.com/chromium/src/+/main/docs/design/sandbox.md#cet-shadow-stack + enable_cet_shadow_stack = target_cpu == "x64" +} + +assert(!is_cfi || use_thin_lto, "CFI requires ThinLTO") + +# If true, optimize for size. Does not affect windows builds. +# Linux & Mac favor speed over size. +# TODO(brettw) it's weird that Mac and desktop Linux are different. We should +# explore favoring size over speed in this case as well. +optimize_for_size = is_android || is_chromecast || is_fuchsia || is_ios + +declare_args() { + # Whether we should consider the profile we're using to be accurate. Accurate + # profiles have the benefit of (potentially substantial) binary size + # reductions, by instructing the compiler to optimize cold and uncovered + # functions heavily for size. This often comes at the cost of performance. + sample_profile_is_accurate = optimize_for_size +} + +# Determine whether to enable or disable frame pointers, based on the platform +# and build arguments. +# TODO(crbug.com/1052397): Consider changing is_chromeos_ash to is_chromeos after +# lacros-chrome switches to target_os="chromeos". +if (is_chromeos_ash || is_chromeos_lacros) { + # ChromeOS generally prefers frame pointers, to support CWP. + # However, Clang does not currently generate usable frame pointers in ARM + # 32-bit builds (https://bugs.llvm.org/show_bug.cgi?id=18505) so disable them + # there to avoid the unnecessary overhead. + enable_frame_pointers = target_cpu != "arm" +} else if (is_apple || is_linux || is_chromeos) { + enable_frame_pointers = true +} else if (is_win) { + # 64-bit Windows ABI doesn't support frame pointers. + if (target_cpu == "x64") { + enable_frame_pointers = false + } else { + enable_frame_pointers = true + } +} else if (is_android) { + enable_frame_pointers = + enable_profiling || + # Ensure that stacks from arm64 crash dumps are usable (crbug.com/391706). + target_cpu == "arm64" || + # For x86 Android, unwind tables are huge without frame pointers + # (crbug.com/762629). Enabling frame pointers grows the code size slightly + # but overall shrinks binaries considerably by avoiding huge unwind + # tables. + (target_cpu == "x86" && !exclude_unwind_tables && optimize_for_size) || + using_sanitizer || + # For caller-callee instrumentation version which needs frame pointers to + # get the caller address. + use_call_graph +} else { + # Explicitly ask for frame pointers, otherwise: + # * Stacks may be missing for sanitizer and profiling builds. + # * Debug tcmalloc can crash (crbug.com/636489). + enable_frame_pointers = using_sanitizer || enable_profiling || is_debug +} + +# In general assume that if we have frame pointers then we can use them to +# unwind the stack. However, this requires that they are enabled by default for +# most translation units, that they are emitted correctly, and that the +# compiler or platform provides a way to access them. +can_unwind_with_frame_pointers = enable_frame_pointers +if (target_cpu == "arm" && arm_use_thumb) { + # We cannot currently unwind ARM Thumb frame pointers correctly. + # See https://bugs.llvm.org/show_bug.cgi?id=18505 + can_unwind_with_frame_pointers = false +} else if (is_win) { + # Windows 32-bit does provide frame pointers, but the compiler does not + # provide intrinsics to access them, so we don't use them. + can_unwind_with_frame_pointers = false +} + +assert(!can_unwind_with_frame_pointers || enable_frame_pointers) + +# Unwinding with CFI table is only possible on static library builds and +# requried only when frame pointers are not enabled. +can_unwind_with_cfi_table = is_android && !is_component_build && + !enable_frame_pointers && target_cpu == "arm" + +# Whether or not cfi table should be enabled on arm. +# TODO(crbug.com/1090409): Replace can_unwind_with_cfi_table with this once +# sampling profiler is enabled on android. +enable_arm_cfi_table = is_android && !is_component_build && target_cpu == "arm" + +declare_args() { + # If this running on a GPU FYI bot. + # TODO(https://crbug.com/1233871): Remove this again. + is_gpu_fyi_bot = false +} + +declare_args() { + # Set to true to use lld, the LLVM linker. + # In late bring-up on macOS (see docs/mac_lld.md). + # Tentatively used on iOS, except in cronet builds (cronet still supports 32-bit builds, which + # lld doesn't support). + # The default linker everywhere else. + use_lld = + is_clang && !(is_ios && is_cronet_build) && !(is_mac && is_gpu_fyi_bot) +} + +declare_args() { + # Whether to use the gold linker from binutils instead of lld or bfd. + use_gold = !use_lld && !(is_chromecast && is_linux && + (target_cpu == "arm" || target_cpu == "mipsel")) && + (((is_linux || is_chromeos_lacros) && + (target_cpu == "x64" || target_cpu == "x86" || + target_cpu == "arm" || target_cpu == "arm64" || + target_cpu == "mipsel" || target_cpu == "mips64el")) || + (is_android && (target_cpu == "x86" || target_cpu == "x64" || + target_cpu == "arm" || target_cpu == "arm64"))) +} + +# Use relative paths for debug info. This is important to make the build +# results independent of the checkout and build directory names, which +# in turn is important for goma compile hit rate. +# Setting this to true may make it harder to debug binaries on Linux, see +# https://chromium.googlesource.com/chromium/src/+/main/docs/linux/debugging.md#Source-level-debug-with-fdebug_compilation_dir +# It's not clear if the crash server will correctly handle dSYMs with relative +# paths, so we disable this feature for official benefit. The main benefit is +# deterministic builds to reduce compile times, so this is less relevant for +# official builders. +strip_absolute_paths_from_debug_symbols_default = + is_android || is_fuchsia || is_nacl || (is_win && use_lld) || is_linux || + is_chromeos || (is_apple && !enable_dsyms) + +# If the platform uses stripped absolute paths by default, then we don't expose +# it as a configuration option. If this is causing problems, please file a bug. +if (strip_absolute_paths_from_debug_symbols_default) { + strip_absolute_paths_from_debug_symbols = true +} else { + declare_args() { + strip_absolute_paths_from_debug_symbols = false + } +} + +# If it wasn't manually set, then default use_debug_fission to false. +assert( + use_debug_fission == "default" || use_debug_fission || !use_debug_fission, + "Invalid use_debug_fission.") +if (use_debug_fission == "default") { + use_debug_fission = is_debug && !is_android && !is_fuchsia && !is_apple && + !is_win && (use_gold || use_lld) && cc_wrapper == "" +} + +# If it wasn't manually set, set to an appropriate default. +assert(symbol_level >= -1 && symbol_level <= 2, "Invalid symbol_level") +if (symbol_level == -1) { + if (is_android && !is_component_build && !use_debug_fission) { + # Reduce symbol level when it will cause invalid elf files to be created + # (due to file size). https://crbug.com/648948. + symbol_level = 1 + } else if (is_chromeos_device) { + # Use lower symbol level in Simple Chrome build for faster link time. + # For Simple Chrome, this should take precedence over is_official_build, + # turned on by --internal. + if ((target_cpu == "x64" || target_cpu == "x86") && !is_debug) { + # For release x86/x64 build, specify symbol_level=0 for faster link time. + # x86/x64 shows backtraces with symbol_level=0 (arm requires + # symbol_level=1). + symbol_level = 0 + } else { + symbol_level = 1 + } + } else if (using_sanitizer) { + # Sanitizers need line table info for stack traces. They don't need type + # info or variable info, so we can leave that out to speed up the build. + # Sanitizers also require symbols for filename suppressions to work. + symbol_level = 1 + } else if ((!is_nacl && !is_linux && !is_chromeos && !is_fuchsia && + current_os != "aix") || is_debug || is_official_build || + is_chromecast) { + # Linux builds slower by having symbols as part of the target binary, + # whereas Mac and Windows have them separate, so in Release Linux, default + # them off, but keep them on for Official builds and Chromecast builds. + symbol_level = 2 + } else { + symbol_level = 0 + } +} + +# Split dwarf works only for symbol_level == 2. +use_debug_fission = use_debug_fission && symbol_level == 2 + +# Non-component debug builds with symbol_level = 2 are an undesirable (very slow +# build times) and unsupported (some test binaries will fail with > 4 GB PDBs) +# combination. This is only checked when current_toolchain == default_toolchain +# because the is_component_build flag is set to false in various components of +# the build (like nacl) and we don't want to assert on those. +# iOS does not support component builds so add an exception for this platform. +if (forbid_non_component_debug_builds) { + assert(symbol_level != 2 || current_toolchain != default_toolchain || + is_component_build || !is_debug || is_ios, + "Can't do non-component debug builds at symbol_level=2") +} + +# Assert that the configuration isn't going to hit https://crbug.com/648948. +# An exception is made when target_os == "chromeos" as we only use the Android +# toolchain there to build relatively small binaries. +assert( + ignore_elf32_limitations || !is_android || target_os == "chromeos" || + is_component_build || symbol_level < 2 || use_debug_fission || + (android_64bit_target_cpu && skip_secondary_abi_for_cq), + "Android 32-bit non-component builds without DWARF Fission cannot " + + "have symbol_level=2 due to 4GiB file size limit, see " + + "https://crbug.com/648948. " + "If you really want to try this out, " + + "set ignore_elf32_limitations=true.") diff --git a/third_party/libwebrtc/build/config/compiler/pgo/BUILD.gn b/third_party/libwebrtc/build/config/compiler/pgo/BUILD.gn new file mode 100644 index 0000000000..3e8502ed77 --- /dev/null +++ b/third_party/libwebrtc/build/config/compiler/pgo/BUILD.gn @@ -0,0 +1,100 @@ +# Copyright 2016 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. + +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/compiler/pgo/pgo.gni") +import("//build/toolchain/toolchain.gni") + +# Configuration that enables PGO instrumentation. +config("pgo_instrumentation_flags") { + visibility = [ ":default_pgo_flags" ] + + # Only add flags when chrome_pgo_phase == 1, so that variables we would use + # are not required to be defined when we're not actually using PGO. + if (chrome_pgo_phase == 1 && is_clang && !is_nacl && is_a_target_toolchain) { + cflags = [ "-fprofile-generate" ] + if (!is_win) { + # Windows directly calls link.exe instead of the compiler driver when + # linking, and embeds the path to the profile runtime library as + # dependent library into each object file. + ldflags = [ "-fprofile-generate" ] + } + } +} + +# Configuration that enables optimization using profile data. +config("pgo_optimization_flags") { + visibility = [ ":default_pgo_flags" ] + + # Only add flags when chrome_pgo_phase == 2, so that variables we would use + # are not required to be defined when we're not actually using PGO. + if (chrome_pgo_phase == 2 && is_clang && !is_nacl && is_a_target_toolchain) { + _pgo_target = "" + + # There are txt files used by //tools/update_pgo_profiles.py to decide which + # profiles to use, adding them as inputs so that analyzer recognizes the + # dependencies. + inputs = [] + + if (is_win) { + if (target_cpu == "x64") { + _pgo_target = "win64" + inputs = [ "//chrome/build/win64.pgo.txt" ] + } else { + _pgo_target = "win32" + inputs = [ "//chrome/build/win32.pgo.txt" ] + } + } else if (is_mac) { + _pgo_target = "mac" + inputs = [ "//chrome/build/mac.pgo.txt" ] + } else if (is_linux || is_chromeos_lacros) { + _pgo_target = "linux" + inputs = [ "//chrome/build/linux.pgo.txt" ] + } + + if (pgo_data_path == "" && _pgo_target != "") { + pgo_data_path = rebase_path(exec_script("//tools/update_pgo_profiles.py", + [ + "--target", + _pgo_target, + "get_profile_path", + ], + "value"), + root_build_dir) + } + assert(pgo_data_path != "", + "Please set pgo_data_path to point at the profile data") + cflags = [ + "-fprofile-instr-use=$pgo_data_path", + + # It's possible to have some profile data legitimately missing, + # and at least some profile data always ends up being considered + # out of date, so make sure we don't error for those cases. + "-Wno-profile-instr-unprofiled", + "-Wno-profile-instr-out-of-date", + + # Some hashing conflict results in a lot of warning like this when doing + # a PGO build: + # warning: foo.cc: Function control flow change detected (hash mismatch) + # [-Wbackend-plugin] + # See https://crbug.com/978401 + "-Wno-backend-plugin", + ] + } +} + +# Applies flags necessary when profile-guided optimization is used. +# Flags are only added if PGO is enabled, so that this config is safe to +# include by default. +config("default_pgo_flags") { + if (chrome_pgo_phase == 0) { + # Nothing. This config should be a no-op when chrome_pgo_phase == 0. + } else if (chrome_pgo_phase == 1) { + configs = [ ":pgo_instrumentation_flags" ] + } else if (chrome_pgo_phase == 2) { + configs = [ ":pgo_optimization_flags" ] + } +} diff --git a/third_party/libwebrtc/build/config/compiler/pgo/pgo.gni b/third_party/libwebrtc/build/config/compiler/pgo/pgo.gni new file mode 100644 index 0000000000..c053eb530b --- /dev/null +++ b/third_party/libwebrtc/build/config/compiler/pgo/pgo.gni @@ -0,0 +1,25 @@ +# Copyright 2016 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. + +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/ui_mode.gni") + +declare_args() { + # Specify the current PGO phase. + # Here's the different values that can be used: + # 0 : Means that PGO is turned off. + # 1 : Used during the PGI (instrumentation) phase. + # 2 : Used during the PGO (optimization) phase. + chrome_pgo_phase = 0 + if (is_official_build && + # TODO(crbug.com/1052397): Remove chromeos_is_browser_only once + # target_os switch for lacros-chrome is completed. + (is_win || is_mac || + (is_linux && !chromeos_is_browser_only && !is_chromecast))) { + chrome_pgo_phase = 2 + } + + # When using chrome_pgo_phase = 2, read profile data from this path. + pgo_data_path = "" +} diff --git a/third_party/libwebrtc/build/config/compute_inputs_for_analyze.gni b/third_party/libwebrtc/build/config/compute_inputs_for_analyze.gni new file mode 100644 index 0000000000..050ab70a3f --- /dev/null +++ b/third_party/libwebrtc/build/config/compute_inputs_for_analyze.gni @@ -0,0 +1,14 @@ +# Copyright 2018 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. + +declare_args() { + # Enable this flag when running "gn analyze". + # + # This causes some gn actions to compute inputs immediately (via exec_script) + # where they would normally compute them only when executed (and write them to + # a depfile). + # + # This flag will slow down GN, but is required for analyze to work properly. + compute_inputs_for_analyze = false +} diff --git a/third_party/libwebrtc/build/config/coverage/BUILD.gn b/third_party/libwebrtc/build/config/coverage/BUILD.gn new file mode 100644 index 0000000000..09c227dce8 --- /dev/null +++ b/third_party/libwebrtc/build/config/coverage/BUILD.gn @@ -0,0 +1,34 @@ +# Copyright 2017 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. + +import("//build/config/coverage/coverage.gni") + +config("default_coverage") { + if (use_clang_coverage) { + ldflags = [] + if (!is_win) { + # Windows directly calls link.exe instead of the compiler driver when + # linking, and embeds the path to the profile runtime library as + # dependent library into each object file. + ldflags += [ "-fprofile-instr-generate" ] + } + + cflags = [ + "-fprofile-instr-generate", + "-fcoverage-mapping", + + # Following experimental flags removes unused header functions from the + # coverage mapping data embedded in the test binaries, and the reduction + # of binary size enables building Chrome's large unit test targets on + # MacOS. Please refer to crbug.com/796290 for more details. + "-mllvm", + "-limited-coverage-experimental=true", + ] + + if (is_linux || is_chromeos) { + # TODO(crbug.com/1194301): Remove this flag. + cflags += [ "-fno-use-cxa-atexit" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/coverage/OWNERS b/third_party/libwebrtc/build/config/coverage/OWNERS new file mode 100644 index 0000000000..0fc481f477 --- /dev/null +++ b/third_party/libwebrtc/build/config/coverage/OWNERS @@ -0,0 +1,3 @@ +inferno@chromium.org +liaoyuke@chromium.org +ochang@chromium.org diff --git a/third_party/libwebrtc/build/config/coverage/coverage.gni b/third_party/libwebrtc/build/config/coverage/coverage.gni new file mode 100644 index 0000000000..b0e01c1d4e --- /dev/null +++ b/third_party/libwebrtc/build/config/coverage/coverage.gni @@ -0,0 +1,40 @@ +# Copyright 2017 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. + +import("//build/toolchain/toolchain.gni") +if (is_fuchsia) { + import("//third_party/fuchsia-sdk/sdk/build/component.gni") +} + +# There are two ways to enable code coverage instrumentation: +# 1. When |use_clang_coverage| or |use_jacoco_coverage| is true and +# |coverage_instrumentation_input_file| is empty, all source files or +# Java class files are instrumented. +# 2. When |use_clang_coverage| or |use_jacoco_coverage| is true and +# |coverage_instrumentation_input_file| is NOT empty and points to +# a text file on the file system, ONLY source files specified in the +# input file or Java class files related to source files are instrumented. +declare_args() { + # Enable Clang's Source-based Code Coverage. + if (is_fuchsia) { + use_clang_coverage = fuchsia_code_coverage + } else { + use_clang_coverage = false + } + + # Enables JaCoCo Java code coverage. + use_jacoco_coverage = false + + # The path to the coverage instrumentation input file should be a source root + # absolute path (e.g. //out/Release/coverage_instrumentation_input.txt), and + # the file consists of multiple lines where each line represents a path to a + # source file, and the paths must be relative to the root build directory. + # e.g. ../../base/task/post_task.cc for build directory 'out/Release'. + # + # NOTE that this arg will be non-op if use_clang_coverage is false. + coverage_instrumentation_input_file = "" +} + +assert(!use_clang_coverage || is_clang, + "Clang Source-based Code Coverage requires clang.") diff --git a/third_party/libwebrtc/build/config/crypto.gni b/third_party/libwebrtc/build/config/crypto.gni new file mode 100644 index 0000000000..4d2c01128d --- /dev/null +++ b/third_party/libwebrtc/build/config/crypto.gni @@ -0,0 +1,15 @@ +# 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 file declares build flags for the SSL library configuration. +# +# TODO(brettw) this should probably be moved to src/crypto or somewhere, and +# the global build dependency on it should be removed. +# +# PLEASE TRY TO AVOID ADDING FLAGS TO THIS FILE in cases where grit isn't +# required. See the declare_args block of BUILDCONFIG.gn for advice on how +# to set up feature flags. + +# True if NSS is used for certificate handling. +use_nss_certs = is_linux || is_chromeos diff --git a/third_party/libwebrtc/build/config/dcheck_always_on.gni b/third_party/libwebrtc/build/config/dcheck_always_on.gni new file mode 100644 index 0000000000..0e8443f907 --- /dev/null +++ b/third_party/libwebrtc/build/config/dcheck_always_on.gni @@ -0,0 +1,40 @@ +# Copyright (c) 2016 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. + +# TODO(crbug.com/1233050): Until the bug is resolved we need to include +# gclient_args for the definition of build_with_chromium and build_overrides +# for client overrides of that flag. The latter should go away. +import("//build/config/gclient_args.gni") +import("//build_overrides/build.gni") +declare_args() { + # Enables DCHECKs to be built-in, but to default to being non-fatal/log-only. + # DCHECKS can then be set as fatal/non-fatal via the DCheckIsFatal feature. + # See https://bit.ly/dcheck-albatross for details on how this is used. + dcheck_is_configurable = false +} + +declare_args() { + # Set to false to disable DCHECK in Release builds. This is enabled by default + # for non-official builds on the below platforms. + # This default only affects Chromium as indicated by build_with_chromium. + # Other clients typically set this to false. If another client wants to use + # the same default value as Chromium, we'd need to add a separate gclient + # variable to replace build_with_chromium here. + # Note: If you are here to revert because DCHECKs are failing on a specific OS + # please prefer excluding OSes rather than reverting . I.e. if Mac builds + # break badly but other platforms are reasonably stable, add "&& !is_mac" + # instead of reverting. + dcheck_always_on = + (build_with_chromium && !is_official_build) || dcheck_is_configurable +} + +declare_args() { + # Set to false to disable EXPENSIVE_DCHECK()s. + # TODO(crbug.com/1225701): Hash out whether expensive DCHECKs need to be + # disabled for developers by default. There's concern that disabling these + # globally by default effectively reduces them to zero coverage. This is + # in place so that you can disable expensive DCHECKs while retaining some + # DCHECK coverage, which is especially important in user-facing builds. + enable_expensive_dchecks = is_debug || dcheck_always_on +} diff --git a/third_party/libwebrtc/build/config/devtools.gni b/third_party/libwebrtc/build/config/devtools.gni new file mode 100644 index 0000000000..7a6d2b2f06 --- /dev/null +++ b/third_party/libwebrtc/build/config/devtools.gni @@ -0,0 +1,37 @@ +# Copyright (c) 2021 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. + +import("//build/config/chrome_build.gni") +import("//build_overrides/build.gni") + +declare_args() { + if (build_with_chromium) { + # devtools_location is used in DevTools to resolve to the correct location + # for any script/file referenced in the DevTools build scripts. Since + # DevTools supports both a standalone build and build integration with + # Chromium, we need to differentiate between the two versions. + # devtools_location points to the Chromium version in both Chrome-branded + # and not Chrome-branded builds. devtools_root_location points to the root + # of the Chrome-branded version when is_chrome_branded is true and to the root + # of the Chromium version when is_chrome_branded is false. + # devtools_grd_location is the location of the GRD file listing all DevTools + # resources. + if (is_chrome_branded) { + devtools_root_location = "third_party/devtools-frontend-internal" + devtools_location = "$devtools_root_location/devtools-frontend/" + devtools_grd_location = + "$devtools_root_location/chrome_devtools_resources.grd" + } else { + devtools_root_location = "third_party/devtools-frontend/src" + devtools_location = "third_party/devtools-frontend/src/" + devtools_grd_location = + "$devtools_root_location/front_end/devtools_resources.grd" + } + } else { + # DevTools is building a standalone version + devtools_location = "" + devtools_root_location = "" + devtools_grd_location = "" + } +} diff --git a/third_party/libwebrtc/build/config/features.gni b/third_party/libwebrtc/build/config/features.gni new file mode 100644 index 0000000000..62bf4bcb35 --- /dev/null +++ b/third_party/libwebrtc/build/config/features.gni @@ -0,0 +1,40 @@ +# Copyright 2014 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. + +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# These flags are effectively global. Your feature flag should go near the +# code it controls. Most of these items are here now because they control +# legacy global #defines passed to the compiler (now replaced with generated +# buildflag headers -- see //build/buildflag_header.gni). +# +# There is more advice on where to put build flags in the "Build flag" section +# of //build/config/BUILDCONFIG.gn. + +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") + +declare_args() { + # Enables proprietary codecs and demuxers; e.g. H264, AAC, MP3, and MP4. + # We always build Google Chrome and Chromecast with proprietary codecs. + # + # Note: this flag is used by WebRTC which is DEPSed into Chrome. Moving it + # out of //build will require using the build_overrides directory. + proprietary_codecs = is_chrome_branded || is_chromecast + + # libudev usage. This currently only affects the content layer. + use_udev = (is_linux || is_chromeos) && !is_chromecast + + use_dbus = (is_linux || is_chromeos) && !is_chromecast + + use_gio = is_linux && !is_chromecast +} +# +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# See comment at the top. diff --git a/third_party/libwebrtc/build/config/freetype/BUILD.gn b/third_party/libwebrtc/build/config/freetype/BUILD.gn new file mode 100644 index 0000000000..76cb025fbb --- /dev/null +++ b/third_party/libwebrtc/build/config/freetype/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2017 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. + +import("//build/config/features.gni") +import("//build/config/freetype/freetype.gni") + +group("freetype") { + if (use_system_freetype) { + public_configs = [ "//build/linux:freetype_from_pkgconfig" ] + } else { + public_deps = [ "//third_party:freetype_harfbuzz" ] + } +} diff --git a/third_party/libwebrtc/build/config/freetype/OWNERS b/third_party/libwebrtc/build/config/freetype/OWNERS new file mode 100644 index 0000000000..3277f87312 --- /dev/null +++ b/third_party/libwebrtc/build/config/freetype/OWNERS @@ -0,0 +1,2 @@ +bungeman@chromium.org +drott@chromium.org diff --git a/third_party/libwebrtc/build/config/freetype/freetype.gni b/third_party/libwebrtc/build/config/freetype/freetype.gni new file mode 100644 index 0000000000..b4eced2d65 --- /dev/null +++ b/third_party/libwebrtc/build/config/freetype/freetype.gni @@ -0,0 +1,14 @@ +# Copyright 2017 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. + +declare_args() { + # Blink needs a recent and properly build-configured FreeType version to + # support OpenType variations, color emoji and avoid security bugs. By default + # we ship and link such a version as part of Chrome. For distributions that + # prefer to keep linking to the version the system, FreeType must be newer + # than version 2.7.1 and have color bitmap support compiled in. WARNING: + # System FreeType configurations other than as described WILL INTRODUCE TEXT + # RENDERING AND SECURITY REGRESSIONS. + use_system_freetype = false +} diff --git a/third_party/libwebrtc/build/config/fuchsia/BUILD.gn b/third_party/libwebrtc/build/config/fuchsia/BUILD.gn new file mode 100644 index 0000000000..88922a11e8 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright 2017 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. + +import("//build/config/chromecast_build.gni") + +assert(is_fuchsia) +assert(!is_posix) + +config("compiler") { + configs = [ "//third_party/fuchsia-sdk/sdk/build/config:compiler" ] + + # TODO(https://crbug.com/706592): The stack defaults to 256k on Fuchsia (see + # https://fuchsia.googlesource.com/zircon/+/master/system/private/zircon/stack.h#9), + # but on other platforms it's much higher, so a variety of code assumes more + # will be available. Raise to 8M which matches e.g. macOS. + ldflags = [ "-Wl,-z,stack-size=0x800000" ] + + # Allow this in chromium-only builds, but do not allow this in Chromecast + # builds. + if (!is_chromecast) { + cflags_cc = [ "-fexperimental-relative-c++-abi-vtables" ] + ldflags += [ "-fexperimental-relative-c++-abi-vtables" ] + } +} + +# Settings for executables. +config("executable_config") { + ldflags = [ "-pie" ] +} diff --git a/third_party/libwebrtc/build/config/fuchsia/DIR_METADATA b/third_party/libwebrtc/build/config/fuchsia/DIR_METADATA new file mode 100644 index 0000000000..6d8f079aa5 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/DIR_METADATA @@ -0,0 +1,7 @@ +monorail { + component: "Fuchsia" +} + +team_email: "cr-fuchsia@chromium.org" + +os: FUCHSIA diff --git a/third_party/libwebrtc/build/config/fuchsia/OWNERS b/third_party/libwebrtc/build/config/fuchsia/OWNERS new file mode 100644 index 0000000000..3a1056b296 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/OWNERS @@ -0,0 +1,4 @@ +file://build/fuchsia/OWNERS + +per-file *.cmx=set noparent +per-file *.cmx=file://fuchsia/SECURITY_OWNERS diff --git a/third_party/libwebrtc/build/config/fuchsia/build_cmx_from_fragment.py b/third_party/libwebrtc/build/config/fuchsia/build_cmx_from_fragment.py new file mode 100644 index 0000000000..ac7e34988d --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/build_cmx_from_fragment.py @@ -0,0 +1,49 @@ +# Copyright 2020 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. +"""Creates a complete CMX (v1) component manifest, from a program name and + manifest fragment file.""" + +import argparse +import json +import sys + + +def BuildCmxFromFragment(output_file, fragment_file, program_binary): + """Reads a CMX fragment specifying e.g. features & sandbox, and a program + binary's filename, and writes out the full CMX. + + output_file: Build-relative filename at which to write the full CMX. + fragment_file: Build-relative filename of the CMX fragment to read from. + program_binary: Package-relative filename of the program binary. + """ + + with open(output_file, 'w') as component_manifest_file: + component_manifest = json.load(open(fragment_file, 'r')) + component_manifest.update({ + 'program': { + 'binary': program_binary + }, + }) + json.dump(component_manifest, component_manifest_file) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--cmx-fragment', + required=True, + help='Path to the CMX fragment to read from') + parser.add_argument( + '--cmx', required=True, help='Path to write the complete CMX file to') + parser.add_argument( + '--program', + required=True, + help='Package-relative path to the program binary') + args = parser.parse_args() + + return BuildCmxFromFragment(args.cmx, args.cmx_fragment, args.program) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/libwebrtc/build/config/fuchsia/build_symbol_archive.py b/third_party/libwebrtc/build/config/fuchsia/build_symbol_archive.py new file mode 100755 index 0000000000..c763627bf9 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/build_symbol_archive.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# Copyright 2018 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. + +"""Creates a compressed archive of unstripped binaries cataloged by +"ids.txt".""" + +import argparse +import os +import subprocess +import sys +import tarfile + + +def main(args): + parser = argparse.ArgumentParser() + parser.add_argument('ids_txt', type=str, nargs=1, + help='Path to ids.txt files.') + parser.add_argument('-o', '--output_tarball', nargs=1, type=str, + help='Path which the tarball will be written to.') + parser.add_argument('--fuchsia-build-id-dir', type=str, required=True, + help='Directory containing symbols for SDK prebuilts.') + args = parser.parse_args(args) + + ids_txt = args.ids_txt[0] + build_ids_archive = tarfile.open(args.output_tarball[0], 'w:bz2') + for line in open(ids_txt, 'r'): + build_id, binary_path = line.strip().split(' ') + + # Look for prebuilt symbols in the SDK first. + symbol_source_path = os.path.join(args.fuchsia_build_id_dir, + build_id[:2], + build_id[2:] + '.debug') + if not os.path.exists(symbol_source_path): + symbol_source_path = os.path.abspath( + os.path.join(os.path.dirname(ids_txt), binary_path)) + + if os.path.getsize(symbol_source_path) == 0: + # This is a prebuilt which wasn't accompanied by SDK symbols. + continue + + # Exclude stripped binaries (indicated by their lack of symbol tables). + readelf_output = subprocess.check_output( + ['readelf', '-S', symbol_source_path], universal_newlines=True) + if not '.symtab' in readelf_output: + continue + + # Archive the unstripped ELF binary, placing it in a hierarchy keyed to the + # GNU build ID. The binary resides in a directory whose name is the first + # two characters of the build ID, with the binary file itself named after + # the remaining characters of the build ID. So, a binary file with the build + # ID "deadbeef" would be located at the path 'de/adbeef.debug'. + build_ids_archive.add(symbol_source_path, + '%s/%s.debug' % (build_id[:2], build_id[2:])) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/third_party/libwebrtc/build/config/fuchsia/config.gni b/third_party/libwebrtc/build/config/fuchsia/config.gni new file mode 100644 index 0000000000..5a00cc5a85 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/config.gni @@ -0,0 +1,11 @@ +# Copyright 2017 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. + +assert(is_fuchsia) + +# Compute the AEMU path. +aemu_root = "//third_party/aemu-${host_os}-${target_cpu}" + +# Compute the path to the arch-specific boot image directory. +boot_image_root = "//third_party/fuchsia-sdk/images/${target_cpu}" diff --git a/third_party/libwebrtc/build/config/fuchsia/extend_fvm.py b/third_party/libwebrtc/build/config/fuchsia/extend_fvm.py new file mode 100644 index 0000000000..44e5ee30e1 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/extend_fvm.py @@ -0,0 +1,26 @@ +# Copyright 2018 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. + +"""Copies a FVM file and extends it by a specified amount. + +Arg #1: path to 'fvm'. + #2: the path to the source fvm.blk. + #3: the path that the extended FVM file will be written to. + #4: the additional number of bytes to grow fvm.blk by.""" + +import os +import shutil +import subprocess +import sys + +def ExtendFVM(fvm_tool_path, src_path, dest_path, delta): + old_size = os.path.getsize(src_path) + new_size = old_size + int(delta) + shutil.copyfile(src_path, dest_path) + subprocess.check_call([fvm_tool_path, dest_path, 'extend', '--length', + str(new_size)]) + return 0 + +if __name__ == '__main__': + sys.exit(ExtendFVM(*sys.argv[1:])) diff --git a/third_party/libwebrtc/build/config/fuchsia/generate_runner_scripts.gni b/third_party/libwebrtc/build/config/fuchsia/generate_runner_scripts.gni new file mode 100644 index 0000000000..3349b2b869 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/generate_runner_scripts.gni @@ -0,0 +1,284 @@ +# Copyright 2018 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. + +assert(is_fuchsia) + +import("//build/config/chromecast_build.gni") +import("//build/config/fuchsia/config.gni") +import("//build/config/fuchsia/package.gni") +import("//build/config/gclient_args.gni") +import("//build/config/sysroot.gni") +import("//build/util/generate_wrapper.gni") + +declare_args() { + # Sets the Fuchsia Amber repository which will be used by default by the + # generated installation scripts. If not specified, then no default directory + # will be used. + default_fuchsia_build_dir_for_installation = "" + + # Sets the Fuchsia device node name which will be used by default by the + # generated runner scripts. If not specficed, then no default node name will + # be used. + default_fuchsia_device_node_name = "" + + # CPU architecture of the host used to run the tests. + test_host_cpu = host_cpu + + # Sets whether emulators need to be included in the test isolates + test_isolate_uses_emulator = true + + # A list of additional Fuchsia boot images to include in the test isolates. + fuchsia_additional_boot_images = [] +} + +# Generates a script which deploys and optionally executes a package on a +# device. +# +# Parameters: +# package: The package() target which will be run. +# package_name_override: Specifies the name of the generated package, if its +# name is different than the |package| target name. This value must match +# package_name_override in the |package| target. +# package_deps: An array of [package, package_name_override] array pairs +# which specify additional dependency packages to be installed +# prior to execution. +# runner_script: The runner script implementation to use, relative to +# "build/fuchsia". Defaults to "test_runner.py". +# install_only: If true, executing the script will only install the package +# on the device, but not run it. +# is_test_exe: If true, the generated script will run the command under +# test_env.py and add arguments expected to be passed to test exes. +template("fuchsia_package_runner") { + forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "runner_script" ]) + + if (defined(invoker.package_name_override)) { + _pkg_shortname = invoker.package_name_override + } else { + _pkg_shortname = get_label_info(invoker.package, "name") + } + + _pkg_dir = "$root_out_dir/gen/" + get_label_info(invoker.package, "dir") + + "/" + _pkg_shortname + _package_path = "$_pkg_dir/${_pkg_shortname}.far" + + generated_run_pkg_script_path = "$root_build_dir/bin/run_${_pkg_shortname}" + generated_install_pkg_script_path = + "$root_build_dir/bin/install_$_pkg_shortname" + + _generate_runner_target = "${target_name}__generate_runner" + _generate_installer_target = "${target_name}__generate_installer" + + # Generates a script which installs and runs a test. + generate_wrapper(_generate_runner_target) { + forward_variables_from(invoker, [ "target" ]) + + _is_test_exe = defined(invoker.is_test_exe) && invoker.is_test_exe + + if (defined(runner_script)) { + _runner_script = runner_script + } else { + _runner_script = "//build/fuchsia/test_runner.py" + } + + if (_is_test_exe) { + executable = "//testing/test_env.py" + executable_args = + [ "@WrappedPath(" + rebase_path(_runner_script, root_out_dir) + ")" ] + data = [ + _runner_script, + "//.vpython", + ] + data_deps = [ "//testing:test_scripts_shared" ] + } else { + executable = rebase_path(_runner_script) + executable_args = [] + data = [] + data_deps = [] + } + + if (defined(invoker.data)) { + data += invoker.data + } + + wrapper_script = generated_run_pkg_script_path + + data_deps += [ + invoker.package, + + # Runner scripts require access to "ids.txt" for symbolization, and to + # the "package" from which to get the name & version to deploy, which + # are outputs of the archive manifest generation action. + "${invoker.package}__archive-manifest", + + # Runner scripts require access to "meta.far" from which to calculate the + # expected Merkle root for the package, to verify it has been cached. + "${invoker.package}__archive-metadata", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + + # Declares the files that are needed for test execution on the + # swarming test client. + data += [ + "//build/fuchsia/", + "//build/util/lib/", + "//third_party/fuchsia-sdk/sdk/.build-id/", + "//third_party/fuchsia-sdk/sdk/bin/fpave.sh", + "//third_party/fuchsia-sdk/sdk/bin/fuchsia-common.sh", + "//third_party/fuchsia-sdk/sdk/meta/manifest.json", + ] + + # TODO(crbug.com/1137662): Remove checkout_fuchsia_for_arm64_host from + # gclient_gn_args in //DEPS as well as this condition when builders have + # test_host_cpu set correctly. + if (checkout_fuchsia_for_arm64_host) { + test_host_cpu = "arm64" + } + + if (test_host_cpu == "x64") { + data_deps += + [ "//build/config/clang:llvm-symbolizer_data($host_toolchain)" ] + } + + data += [ + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/device-finder", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/ffx", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/fvm", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/merkleroot", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/pm", + + # TODO(crbug.com/1162314) Remove "symbolize" when transition to + # "symbolizer" is complete. + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/symbolize", + + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/symbolizer", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/zbi", + ] + + if (test_isolate_uses_emulator) { + data += [ + "${boot_image_root}/qemu/qemu-kernel.kernel", + "${boot_image_root}/qemu/storage-full.blk", + "${boot_image_root}/qemu/zircon-a.zbi", + "//third_party/fuchsia-sdk/sdk/tools/${test_host_cpu}/fvdl", + "//third_party/qemu-${host_os}-${test_host_cpu}/", + "${aemu_root}/", + ] + } + + foreach(fuchsia_additional_boot_image, fuchsia_additional_boot_images) { + data += [ "${fuchsia_additional_boot_image}/" ] + } + + package_paths = [ rebase_path(_package_path, root_build_dir) ] + if (defined(invoker.package_deps)) { + foreach(package_dep, invoker.package_deps) { + package_dep_target = package_dep[0] + package_dep_name = package_dep[1] + + data_deps += [ + package_dep_target, + package_dep_target + "__archive-manifest", + package_dep_target + "__archive-metadata", + ] + package_dep_path = rebase_path( + get_label_info(package_dep_target, "target_gen_dir") + "/" + + package_dep_name + "/" + package_dep_name + ".far", + root_build_dir) + package_paths += [ package_dep_path ] + } + } + + foreach(package_path, package_paths) { + executable_args += [ + "--package", + "@WrappedPath(${package_path})", + ] + } + + executable_args += [ + "--out-dir", + "@WrappedPath(.)", + "--target-cpu", + target_cpu, + "--package-name", + _pkg_shortname, + ] + + if (defined(invoker.use_run_test_component) && + invoker.use_run_test_component) { + executable_args += [ "--use-run-test-component" ] + } + + if (defined(invoker.use_test_server) && invoker.use_test_server) { + executable_args += [ "--enable-test-server" ] + } + + if (default_fuchsia_build_dir_for_installation != "") { + executable_args += [ + "--fuchsia-out-dir", + default_fuchsia_build_dir_for_installation, + ] + } + + if (default_fuchsia_device_node_name != "") { + executable_args += [ + "--node-name", + default_fuchsia_device_node_name, + ] + } + } + + # Produces a script which installs a package and its dependencies into the + # package repository of a pre-existing Fuchsia build directory. + generate_wrapper(_generate_installer_target) { + executable = rebase_path("//build/fuchsia/deploy_to_pkg_repo.py") + wrapper_script = generated_install_pkg_script_path + + data_deps = [ invoker.package ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + + # Build a list of all packages to install, and pass the list to the runner + # script. + package_paths = [ rebase_path(_package_path, root_build_dir) ] + if (defined(invoker.package_deps)) { + foreach(package_dep, invoker.package_deps) { + package_dep_target = package_dep[0] + package_dep_name = package_dep[1] + + data_deps += [ package_dep_target ] + package_dep_path = rebase_path( + get_label_info(package_dep_target, "target_gen_dir") + "/" + + package_dep_name + "/" + package_dep_name + ".far", + root_build_dir) + package_paths += [ package_dep_path ] + } + } + executable_args = [] + foreach(package_path, package_paths) { + executable_args += [ + "--package", + "@WrappedPath(${package_path})", + ] + + if (default_fuchsia_build_dir_for_installation != "") { + executable_args += [ + "--fuchsia-out-dir", + default_fuchsia_build_dir_for_installation, + ] + } + } + } + + group(target_name) { + deps = [ ":${_generate_installer_target}" ] + + if (!defined(invoker.install_only) || invoker.install_only == false) { + deps += [ ":${_generate_runner_target}" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/gfx_tests.cmx b/third_party/libwebrtc/build/config/fuchsia/gfx_tests.cmx new file mode 100644 index 0000000000..0786fb0b98 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/gfx_tests.cmx @@ -0,0 +1,31 @@ +{ + "sandbox": { + "features": [ + "deprecated-ambient-replace-as-executable", + "isolated-persistent-storage", + "isolated-temp", + "vulkan" + ], + "dev": [ + "null", + "zero" + ], + "services": [ + "fuchsia.accessibility.semantics.SemanticsManager", + "fuchsia.device.NameProvider", + "fuchsia.fonts.Provider", + "fuchsia.intl.PropertyProvider", + "fuchsia.logger.LogSink", + "fuchsia.media.ProfileProvider", + "fuchsia.memorypressure.Provider", + "fuchsia.process.Launcher", + "fuchsia.sys.Environment", + "fuchsia.sys.Loader", + "fuchsia.sysmem.Allocator", + "fuchsia.tracing.provider.Registry", + "fuchsia.ui.policy.Presenter", + "fuchsia.ui.scenic.Scenic", + "fuchsia.vulkan.loader.Loader" + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/package.gni b/third_party/libwebrtc/build/config/fuchsia/package.gni new file mode 100644 index 0000000000..ff6ffd0a3d --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/package.gni @@ -0,0 +1,114 @@ +# Copyright 2018 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. + +import("//third_party/fuchsia-sdk/sdk/build/component.gni") +import("//third_party/fuchsia-sdk/sdk/build/package.gni") + +# DEPRECATED: Use the Fuchsia SDK's fuchsia_component() and fuchsia_package() +# templates directly, in new code. +# +# Creates a Fuchsia .far package file containing a Fuchsia component. +# +# Parameters are: +# package_name_override: Specifies the name of the package to generate, +# if different than |target_name|. +# binary: The executable target which should be launched. +# manifest: A path to the manifest that will be used. +# "testonly" targets default to using +# //build/config/fuchsia/tests-with-exec.cmx. +# Non-test targets must explicitly specify a |manifest|. +# additional_manifests: Manifest files that should be included in the package in +# the /meta directory. This allows to package more than one component per +# manifest. These manifest files must specify program/binary to run, which +# is not required for the main manifest file where this parameter is added +# during build. +# component_name_override: If set, specifies the name of the component. +# By default, the component name is the same as the package name. +# deps: Additional targets to build and include in the package (optional). +# +# TODO(https://crbug.com/1050703): Migrate consumers to GN SDK equivalents. +template("cr_fuchsia_package") { + assert(defined(invoker.binary)) + + if (defined(invoker.package_name_override)) { + _package_name = invoker.package_name_override + } else { + _package_name = invoker.target_name + } + + _package_contents = [ invoker.binary ] + if (defined(invoker.deps)) { + _package_contents += invoker.deps + } + + _component_cmx_target = target_name + "__cr-component-cmx" + _component_target = target_name + "__cr-component" + _package_components = [ ":${_component_target}" ] + _component_manifest = "${target_gen_dir}/${target_name}.cmx" + + # Process the CMX fragment in |manifest| to get a full manifest. + action(_component_cmx_target) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + + script = "//build/config/fuchsia/build_cmx_from_fragment.py" + + inputs = [ invoker.manifest ] + outputs = [ _component_manifest ] + + args = [ + "--cmx-fragment", + rebase_path(invoker.manifest), + "--cmx", + rebase_path(_component_manifest), + "--program", + get_label_info(invoker.binary, "name"), + ] + } + + # Declare the primary component for this package. + fuchsia_component(_component_target) { + forward_variables_from(invoker, [ "testonly" ]) + + deps = [ ":${_component_cmx_target}" ] + data_deps = _package_contents + manifest = _component_manifest + + if (defined(invoker.component_name_override)) { + manifest_output_name = "${invoker.component_name_override}" + } else { + manifest_output_name = "${_package_name}" + } + } + + # Bundle manifests providing additional entrypoints into the package. + if (defined(invoker.additional_manifests)) { + foreach(filename, invoker.additional_manifests) { + _additional_component_target = + target_name + "_" + get_path_info(filename, "name") + _package_components += [ ":${_additional_component_target}" ] + fuchsia_component(_additional_component_target) { + forward_variables_from(invoker, [ "testonly" ]) + data_deps = _package_contents + manifest = filename + + # Depend upon the invoker's |deps|, in case they include a dependency + # responsible for generating this additional component's manifest file. + deps = _package_contents + } + } + } + + fuchsia_package(target_name) { + forward_variables_from(invoker, [ "testonly" ]) + package_name = _package_name + if (defined(invoker.excluded_files)) { + excluded_files = invoker.excluded_files + } + deps = _package_components + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/rules.gni b/third_party/libwebrtc/build/config/fuchsia/rules.gni new file mode 100644 index 0000000000..689e130b65 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/rules.gni @@ -0,0 +1,5 @@ +# Copyright 2019 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. + +import("//build/config/fuchsia/generate_runner_scripts.gni") diff --git a/third_party/libwebrtc/build/config/fuchsia/sizes.gni b/third_party/libwebrtc/build/config/fuchsia/sizes.gni new file mode 100644 index 0000000000..20a5bf831e --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/sizes.gni @@ -0,0 +1,46 @@ +# Copyright 2020 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. + +import("//build/util/generate_wrapper.gni") + +template("compute_fuchsia_package_sizes") { + generate_wrapper(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + ]) + testonly = true + executable = "//build/fuchsia/binary_sizes.py" + wrapper_script = "$root_out_dir/bin/run_${target_name}" + + assert(target_cpu == "arm64" || target_cpu == "x64", + "target_cpu must be arm64 or x64") + + if (!defined(data)) { + data = [] + } + + if (!defined(data_deps)) { + data_deps = [] + } + + # Declares the files that are needed for test execution on the + # swarming test client. + data += [ + "//build/fuchsia/", + "//fuchsia/release/size_tests/", + "//third_party/fuchsia-sdk/sdk/arch/", + "//third_party/fuchsia-sdk/sdk/tools/${target_cpu}/", + ] + + executable_args = [ + "--output-directory", + "@WrappedPath(.)", + ] + if (defined(invoker.executable_args)) { + executable_args += invoker.executable_args + } + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/symbol_archive.gni b/third_party/libwebrtc/build/config/fuchsia/symbol_archive.gni new file mode 100644 index 0000000000..9dcb53cae0 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/symbol_archive.gni @@ -0,0 +1,47 @@ +# Copyright 2019 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. + +assert(is_fuchsia) + +# Creates a tarball of unstripped binaries, structured according to the +# ".build_ids" convention used by the symbolizer and GNU GDB. +# +# Parameters: +# deps: Must all be cr_fuchsia_package() or fuchsia_package() targets. +# ids_txt: The "ids.txt" file which lists the relative paths to unstripped +# executables and libraries, along with their build IDs. +# archive_name: The path to the compressed tarball that will be generated. +template("symbol_archive") { + assert(!is_debug) + + action(target_name) { + _ids_txt = invoker.ids_txt + _build_ids = invoker.archive_name + + script = "//build/config/fuchsia/build_symbol_archive.py" + + inputs = [ _ids_txt ] + + outputs = [ _build_ids ] + + # For each package in |deps| it is necessary to additionally depend upon + # the corresponding archive-manifest target, which is what creates the + # ids.txt file. + deps = [] + foreach(package, invoker.deps) { + deps += [ + package, + package + "__archive-manifest", + ] + } + + args = [ + rebase_path(_ids_txt), + "-o", + rebase_path(_build_ids), + "--fuchsia-build-id-dir", + rebase_path("//third_party/fuchsia-sdk/sdk/.build-id"), + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/test/OWNERS b/third_party/libwebrtc/build/config/fuchsia/test/OWNERS new file mode 100644 index 0000000000..3be17de545 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/OWNERS @@ -0,0 +1,7 @@ +file://build/fuchsia/OWNERS + +per-file *.test-cmx=set noparent +per-file *.test-cmx=ddorwin@chromium.org +per-file *.test-cmx=wez@chromium.org +# Please prefer the above when possible. +per-file *.test-cmx=file://fuchsia/SECURITY_OWNERS diff --git a/third_party/libwebrtc/build/config/fuchsia/test/README.md b/third_party/libwebrtc/build/config/fuchsia/test/README.md new file mode 100644 index 0000000000..8427f4a49f --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/README.md @@ -0,0 +1,61 @@ +## CMX Fragments + +This directory contains the cmx fragments that are required for running +Fuchsia tests hermetically. Tests start from `minimum_capabilities.test-cmx` +and add additional capabilities as necessary by providing the +`additional_manifest_fragments` argument. Some fragments are explained in detail +below: + +### General Purpose Fragments + +#### font_capabilities.test-cmx +For tests that test fonts by providing `fuchsia.fonts.Provider`. + +#### jit_capabilities.test-cmx +Required by tests that execute JavaScript. Should only be required in a small +number of tests. + +#### minimum_capabilites.test-cmx +Capabilities required by anything that uses `//base/test`, used as the base +fragment for all test suites. + +#### read_debug_data.test-cmx +Required by tests that need access to its debug directory. Should only be +required in a small number of tests. + +#### test_logger_capabilities.test-cmx +For tests that test logging functionality by providing `fuchsia.logger.Log`. + +### WebEngine Fragments +The following fragments are specific to WebEngine functionality as documented +documentation at +https://fuchsia.dev/reference/fidl/fuchsia.web#CreateContextParams and +https://fuchsia.dev/reference/fidl/fuchsia.web#ContextFeatureFlags. +Any test-specific exceptions are documented for each file. + +#### audio_capabilities.test-cmx +Corresponds to the `AUDIO` flag. Required for enabling audio input and output. + +#### network_capabilities.test-cmx +Corresponds to the `NETWORK` flag. Required for enabling network access. Note +that access to the root SSL certificates is not needed if ContextProvider is +used to launch the `Context`. The `fuchsia.device.NameProvider` dependency comes +from fdio. + +#### present_view_capabilities.test-cmx +Services that are needed to render web content in a Scenic view and present it. +Most services are required per the FIDL documentation. +`fuchsia.ui.policy.Presenter` is additionally required by tests that create +views. + +#### vulkan_capabilities.test-cmx +Corresponds to the `VULKAN` flag. Required for enabling GPU-accelerated +rendering of the web content. + +#### web_engine_required_capabilities.test-cmx +Contains services that need to be present when creating a +`fuchsia.web.Context`. Note that the `fuchsia.scheduler.ProfileProvider` service +is only used in tests that encounter memory pressure code. + +#### web_instance_host_capabilities.test-cmx +Contains services that need to be present to use `WebInstanceHost`.
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/audio_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/audio_capabilities.test-cmx new file mode 100644 index 0000000000..2e2013f9ea --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/audio_capabilities.test-cmx @@ -0,0 +1,18 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.mediacodec.CodecFactory": "fuchsia-pkg://fuchsia.com/codec_factory#meta/codec_factory.cmx" + }, + "system-services": [ + "fuchsia.media.Audio" + ] + } + }, + "sandbox": { + "services": [ + "fuchsia.media.Audio", + "fuchsia.mediacodec.CodecFactory" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/font_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/font_capabilities.test-cmx new file mode 100644 index 0000000000..4c8661bb80 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/font_capabilities.test-cmx @@ -0,0 +1,14 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.fonts.Provider": "fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx", + } + } + }, + "sandbox": { + "services": [ + "fuchsia.fonts.Provider" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/jit_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/jit_capabilities.test-cmx new file mode 100644 index 0000000000..ff70e256be --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/jit_capabilities.test-cmx @@ -0,0 +1,7 @@ +{ + "sandbox": { + "features": [ + "deprecated-ambient-replace-as-executable" + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/test/minimum_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/minimum_capabilities.test-cmx new file mode 100644 index 0000000000..5b9f7bf705 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/minimum_capabilities.test-cmx @@ -0,0 +1,30 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.intl.PropertyProvider": "fuchsia-pkg://fuchsia.com/intl_property_manager#meta/intl_property_manager.cmx" + }, + "system-services": [ + "fuchsia.boot.ReadOnlyLog" + ] + } + }, + "sandbox": { + "dev": [ + "null", + "zero" + ], + "features": [ + "isolated-persistent-storage", + "isolated-temp" + ], + "services": [ + "fuchsia.intl.PropertyProvider", + "fuchsia.logger.LogSink", + "fuchsia.media.ProfileProvider", + "fuchsia.process.Launcher", + "fuchsia.sys.Launcher", + "fuchsia.sys.Loader" + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/test/network_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/network_capabilities.test-cmx new file mode 100644 index 0000000000..7218c3f875 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/network_capabilities.test-cmx @@ -0,0 +1,25 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.net.interfaces.State": "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cmx", + "fuchsia.net.name.Lookup": "fuchsia-pkg://fuchsia.com/dns-resolver#meta/dns-resolver.cmx", + "fuchsia.posix.socket.Provider": "fuchsia-pkg://fuchsia.com/netstack#meta/netstack.cmx" + }, + "system-services": [ + "fuchsia.device.NameProvider" + ] + } + }, + "sandbox": { + "features": [ + "root-ssl-certificates" + ], + "services": [ + "fuchsia.device.NameProvider", + "fuchsia.net.name.Lookup", + "fuchsia.net.interfaces.State", + "fuchsia.posix.socket.Provider" + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/test/present_view_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/present_view_capabilities.test-cmx new file mode 100644 index 0000000000..201c8b2212 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/present_view_capabilities.test-cmx @@ -0,0 +1,24 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.accessibility.semantics.SemanticsManager": "fuchsia-pkg://fuchsia.com/a11y-manager#meta/a11y-manager.cmx", + "fuchsia.ui.input3.Keyboard": "fuchsia-pkg://fuchsia.com/ime_service#meta/ime_service.cmx", + }, + "system-services": [ + "fuchsia.sysmem.Allocator", + "fuchsia.ui.policy.Presenter", + "fuchsia.ui.scenic.Scenic" + ] + } + }, + "sandbox": { + "services": [ + "fuchsia.accessibility.semantics.SemanticsManager", + "fuchsia.sysmem.Allocator", + "fuchsia.ui.input3.Keyboard", + "fuchsia.ui.policy.Presenter", + "fuchsia.ui.scenic.Scenic" + ] + } +} diff --git a/third_party/libwebrtc/build/config/fuchsia/test/read_debug_data.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/read_debug_data.test-cmx new file mode 100644 index 0000000000..b0c95b0883 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/read_debug_data.test-cmx @@ -0,0 +1,7 @@ +{ + "sandbox": { + "features": [ + "hub" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/test_logger_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/test_logger_capabilities.test-cmx new file mode 100644 index 0000000000..68b2a67012 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/test_logger_capabilities.test-cmx @@ -0,0 +1,7 @@ +{ + "sandbox": { + "services": [ + "fuchsia.logger.Log" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/vulkan_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/vulkan_capabilities.test-cmx new file mode 100644 index 0000000000..0436ffd5e3 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/vulkan_capabilities.test-cmx @@ -0,0 +1,19 @@ +{ + "facets": { + "fuchsia.test": { + "system-services": [ + "fuchsia.sysmem.Allocator", + "fuchsia.vulkan.loader.Loader" + ] + } + }, + "sandbox": { + "features": [ + "vulkan" + ], + "services": [ + "fuchsia.sysmem.Allocator", + "fuchsia.vulkan.loader.Loader" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/web_engine_required_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/web_engine_required_capabilities.test-cmx new file mode 100644 index 0000000000..4cb61fe7f1 --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/web_engine_required_capabilities.test-cmx @@ -0,0 +1,25 @@ +{ + "facets": { + "fuchsia.test": { + "injected-services": { + "fuchsia.fonts.Provider": "fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx", + "fuchsia.memorypressure.Provider": "fuchsia-pkg://fuchsia.com/memory_monitor#meta/memory_monitor.cmx", + "fuchsia.web.ContextProvider": "fuchsia-pkg://fuchsia.com/web_engine#meta/context_provider.cmx", + }, + "system-services": [ + "fuchsia.device.NameProvider", + "fuchsia.scheduler.ProfileProvider", + "fuchsia.sysmem.Allocator" + ] + } + }, + "sandbox": { + "services": [ + "fuchsia.device.NameProvider", + "fuchsia.fonts.Provider", + "fuchsia.memorypressure.Provider", + "fuchsia.sysmem.Allocator", + "fuchsia.web.ContextProvider" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx b/third_party/libwebrtc/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx new file mode 100644 index 0000000000..762916ba9f --- /dev/null +++ b/third_party/libwebrtc/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx @@ -0,0 +1,8 @@ +{ + "sandbox": { + "services": [ + "fuchsia.sys.Environment", + "fuchsia.sys.Loader" + ] + } +}
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/gcc/BUILD.gn b/third_party/libwebrtc/build/config/gcc/BUILD.gn new file mode 100644 index 0000000000..ff47e2542c --- /dev/null +++ b/third_party/libwebrtc/build/config/gcc/BUILD.gn @@ -0,0 +1,116 @@ +# Copyright 2014 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. + +import("//build/config/c++/c++.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/config/sysroot.gni") +import("//build/toolchain/toolchain.gni") + +declare_args() { + # When non empty, overrides the target rpath value. This allows a user to + # make a Chromium build where binaries and shared libraries are meant to be + # installed into separate directories, like /usr/bin/chromium and + # /usr/lib/chromium for instance. It is useful when a build system that + # generates a whole target root filesystem (like Yocto) is used on top of gn, + # especially when cross-compiling. + # Note: this gn arg is similar to gyp target_rpath generator flag. + gcc_target_rpath = "" + ldso_path = "" +} + +# 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 +# which functions we want to export from components. +# +# Some third_party code assumes all functions are exported so this is separated +# into its own config so such libraries can remove this config to make symbols +# public again. +# +# See http://gcc.gnu.org/wiki/Visibility +config("symbol_visibility_hidden") { + cflags = [ "-fvisibility=hidden" ] + + # Visibility attribute is not supported on AIX. + if (current_os != "aix") { + cflags_cc = [ "-fvisibility-inlines-hidden" ] + cflags_objcc = cflags_cc + } +} + +# This config is usually set when :symbol_visibility_hidden is removed. +# It's often a good idea to set visibility explicitly, as there're flags +# which would error out otherwise (e.g. -fsanitize=cfi-unrelated-cast) +config("symbol_visibility_default") { + cflags = [ "-fvisibility=default" ] +} + +# The rpath is the dynamic library search path. Setting this config on a link +# step will put the directory where the build generates shared libraries into +# the rpath. +# +# This is required for component builds since the build generates many shared +# libraries in the build directory that we expect to be automatically loaded. +# It will be automatically applied in this case by :executable_config. +# +# In non-component builds, certain test binaries may expect to load dynamic +# libraries from the current directory. As long as these aren't distributed, +# this is OK. For these cases use something like this: +# +# if ((is_linux || is_chromeos) && !is_component_build) { +# configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] +# } +config("rpath_for_built_shared_libraries") { + if (!is_android && current_os != "aix") { + # Note: Android, Aix don't support rpath. + if (current_toolchain != default_toolchain || gcc_target_rpath == "") { + ldflags = [ + # Want to pass "\$". GN will re-escape as required for ninja. + "-Wl,-rpath=\$ORIGIN", + ] + } else { + ldflags = [ "-Wl,-rpath=${gcc_target_rpath}" ] + } + if (current_toolchain == default_toolchain && ldso_path != "") { + ldflags += [ "-Wl,--dynamic-linker=${ldso_path}" ] + } + } +} + +if (is_component_build && !is_android) { + # See the rpath_for... config above for why this is necessary for component + # builds. + executable_and_shared_library_configs_ = + [ ":rpath_for_built_shared_libraries" ] +} else { + executable_and_shared_library_configs_ = [] +} + +# Settings for executables. +config("executable_config") { + configs = executable_and_shared_library_configs_ + ldflags = [ "-pie" ] + if (is_android) { + ldflags += [ + "-Bdynamic", + "-Wl,-z,nocopyreloc", + ] + } + + if (!is_android && current_os != "aix") { + ldflags += [ + # TODO(GYP): Do we need a check on the binutils version here? + # + # 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. + "-Wl,--disable-new-dtags", + ] + } +} + +# Settings for shared libraries. +config("shared_library_config") { + configs = executable_and_shared_library_configs_ +} diff --git a/third_party/libwebrtc/build/config/gclient_args.gni b/third_party/libwebrtc/build/config/gclient_args.gni new file mode 100644 index 0000000000..fa77ecc6d4 --- /dev/null +++ b/third_party/libwebrtc/build/config/gclient_args.gni @@ -0,0 +1 @@ +# Generated from 'DEPS'
\ No newline at end of file diff --git a/third_party/libwebrtc/build/config/get_host_byteorder.py b/third_party/libwebrtc/build/config/get_host_byteorder.py new file mode 100755 index 0000000000..fc01d85718 --- /dev/null +++ b/third_party/libwebrtc/build/config/get_host_byteorder.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# Copyright 2017 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. + +"""Get Byteorder of host architecture""" + +from __future__ import print_function + +import sys + +print(sys.byteorder) diff --git a/third_party/libwebrtc/build/config/host_byteorder.gni b/third_party/libwebrtc/build/config/host_byteorder.gni new file mode 100644 index 0000000000..48a1a7f1e3 --- /dev/null +++ b/third_party/libwebrtc/build/config/host_byteorder.gni @@ -0,0 +1,27 @@ +# Copyright (c) 2017 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 header file defines the "host_byteorder" variable. +# Not that this is currently used only for building v8. +# The chromium code generally assumes little-endianness. +declare_args() { + host_byteorder = "undefined" +} + +# Detect host byteorder +# ppc64 can be either BE or LE +if (host_cpu == "ppc64") { + if (current_os == "aix") { + host_byteorder = "big" + } else { + # Only use the script when absolutely necessary + host_byteorder = + exec_script("//build/config/get_host_byteorder.py", [], "trim string") + } +} else if (host_cpu == "ppc" || host_cpu == "s390" || host_cpu == "s390x" || + host_cpu == "mips" || host_cpu == "mips64") { + host_byteorder = "big" +} else { + host_byteorder = "little" +} diff --git a/third_party/libwebrtc/build/config/ios/BUILD.gn b/third_party/libwebrtc/build/config/ios/BUILD.gn new file mode 100644 index 0000000000..525c439e7e --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/BUILD.gn @@ -0,0 +1,264 @@ +# Copyright 2014 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. + +import("//build/config/ios/ios_sdk.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +declare_args() { + # Enabling this option makes clang compile to an intermediate + # representation ("bitcode"), and not to native code. This is preferred + # when including WebRTC in the apps that will be sent to Apple's App Store + # and mandatory for the apps that run on watchOS or tvOS. + # The option only works when building with Xcode (use_xcode_clang = true). + # Mimicking how Xcode handles it, the production builds (is_debug = false) + # get real bitcode sections added, while the debug builds (is_debug = true) + # only get bitcode-section "markers" added in them. + enable_ios_bitcode = false +} + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic. +config("compiler") { + # These flags are shared between the C compiler and linker. + common_flags = [] + + # CPU architecture. + if (target_cpu == "x64") { + triplet_cpu = "x86_64" + } else if (target_cpu == "x86") { + triplet_cpu = "i386" + } else if (target_cpu == "arm" || target_cpu == "armv7") { + triplet_cpu = "armv7" + } else if (target_cpu == "arm64") { + triplet_cpu = "arm64" + } else { + assert(false, "unsupported cpu: $target_cpu") + } + + # Environment. + if (target_environment == "simulator") { + triplet_environment = "-simulator" + } else if (target_environment == "device") { + triplet_environment = "" + } else if (target_environment == "catalyst") { + triplet_environment = "-macabi" + } else { + assert(false, "unsupported environment: $target_environment") + } + + # OS. + triplet_os = "apple-ios" + + # Set target. + common_flags = [ + "-target", + "$triplet_cpu-$triplet_os$ios_deployment_target$triplet_environment", + ] + + # This is here so that all files get recompiled after an Xcode update. + # (defines are passed via the command line, and build system rebuild things + # when their commandline changes). Nothing should ever read this define. + defines = [ "CR_XCODE_VERSION=$xcode_version" ] + + asmflags = common_flags + cflags = common_flags + swiftflags = common_flags + + swiftflags += [ + "-swift-version", + "5", + ] + + # Without this, the constructors and destructors of a C++ object inside + # an Objective C struct won't be called, which is very bad. + cflags_objcc = [ "-fobjc-call-cxx-cdtors" ] + + ldflags = common_flags +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is iOS-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + # The variable ios_sdk_path is relative to root_build_dir when using Goma RBE + # and system Xcode (since Goma RBE only supports paths relative to source). + # Rebase the value in that case since gn does not convert paths in compiler + # flags (since it is not aware they are paths). + _sdk_root = ios_sdk_path + if (use_system_xcode && use_goma) { + _sdk_root = rebase_path(ios_sdk_path, root_build_dir) + } + + common_flags = [ + "-isysroot", + _sdk_root, + ] + swiftflags = [ + "-sdk", + _sdk_root, + ] + + if (target_environment == "catalyst") { + common_flags += [ + "-isystem", + "$_sdk_root/System/iOSSupport/usr/include", + "-iframework", + "$_sdk_root/System/iOSSupport/System/Library/Frameworks", + ] + } + + if (use_xcode_clang && enable_ios_bitcode) { + if (is_debug) { + common_flags += [ "-fembed-bitcode-marker" ] + } else { + common_flags += [ "-fembed-bitcode" ] + } + } + + asmflags = common_flags + cflags = common_flags + ldflags = common_flags +} + +config("ios_executable_flags") { + ldflags = [] + + # On "catalyst", the bundle structure is different (uses the same structure + # as a regular macOS app), so an additional -rpath is required. + if (target_environment == "catalyst") { + ldflags += [ "-Wl,-rpath,@loader_path/../Frameworks" ] + } + + ldflags += [ "-Wl,-rpath,@executable_path/Frameworks" ] +} + +config("ios_extension_executable_flags") { + configs = default_executable_configs + + ldflags = [ + "-e", + "_NSExtensionMain", + "-fapplication-extension", + ] + + # On "catalyst", the bundle structure is different (uses the same structure + # as a regular macOS app), so an additional -rpath is required. + if (target_environment == "catalyst") { + ldflags += [ "-Wl,-rpath,@loader_path/../../../../Frameworks" ] + } + + ldflags += [ "-Wl,-rpath,@executable_path/../../Frameworks" ] +} + +config("ios_dynamic_flags") { + ldflags = [ + # Always load Objective-C categories and class. + "-Wl,-ObjC", + ] + + # The path to the Swift compatibility libraries (required to run code built + # with version N of the SDK on older version of the OS) is relative to the + # toolchains directory and changes with the environment. + _swift_compatibility_libs_dir_prefix = "$ios_toolchains_path/usr/lib/swift" + if (target_environment == "simulator") { + _swift_compatibility_libs_dir = + "$_swift_compatibility_libs_dir_prefix/iphonesimulator" + } else if (target_environment == "device") { + _swift_compatibility_libs_dir = + "$_swift_compatibility_libs_dir_prefix/iphoneos" + } else if (target_environment == "catalyst") { + _swift_compatibility_libs_dir = + "$_swift_compatibility_libs_dir_prefix/maccatalyst" + } + + lib_dirs = [ + "$ios_sdk_path/usr/lib/swift", + _swift_compatibility_libs_dir, + ] +} + +config("ios_shared_library_flags") { + ldflags = [ + "-Wl,-rpath,@executable_path/Frameworks", + "-Wl,-rpath,@loader_path/Frameworks", + ] +} + +config("disable_implicit_retain_self_warning") { + cflags_objc = [ "-Wno-implicit-retain-self" ] + cflags_objcc = cflags_objc +} + +config("xctest_config") { + # Use -iframework for XCTest.framework so that the compiler will treat it as a + # system framework and ignore warnings in XCTest framework headers. + common_flags = [ + "-iframework", + rebase_path("$ios_sdk_platform_path/Developer/Library/Frameworks", + root_build_dir), + ] + cflags = common_flags + ldflags = common_flags + + frameworks = [ + "Foundation.framework", + "XCTest.framework", + ] +} + +group("xctest") { + public_configs = [ ":xctest_config" ] +} + +_xctrunner_path = + "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app" + +# When building with Goma RBE, $ios_sdk_platform_path corresponds to a symlink +# below $root_build_dir that points to the real SDK to use. Because the files +# are below $root_build_dir, it is not possible to list them as a target input +# without gn complaining (as it can't find a target creating those files). +# +# The symlinks are created by //build/config/apple/sdk_info.py script invoked +# via exec_script() from //build/config/{ios/ios_sdk.gni,mac/mac_sdk.gni}. +# As the invocation is done by exec_script, there is no target that can list +# those files as output. +# +# To workaround this, add a target that pretends to create those files +# (but does nothing). See https://crbug.com/1061487 for why this is needed. +if (use_system_xcode && use_goma) { + action("copy_xctrunner_app") { + testonly = true + script = "//build/noop.py" + outputs = [ + "$_xctrunner_path/Info.plist", + "$_xctrunner_path/PkgInfo", + "$_xctrunner_path/XCTRunner", + ] + } +} + +# When creating the test runner for an XCUITest, the arm64e slice of the binary +# must be removed (at least until the app ships with arm64e slice which is not +# yet supported by Apple). +action("xctest_runner_without_arm64e") { + testonly = true + script = "//build/config/ios/strip_arm64e.py" + sources = [ "$_xctrunner_path/XCTRunner" ] + outputs = [ "$target_out_dir/XCTRunner" ] + args = [ + "--output", + rebase_path(outputs[0], root_build_dir), + "--input", + rebase_path(sources[0], root_build_dir), + "--xcode-version", + xcode_version, + ] + + if (use_system_xcode && use_goma) { + deps = [ ":copy_xctrunner_app" ] + } +} diff --git a/third_party/libwebrtc/build/config/ios/BuildInfo.plist b/third_party/libwebrtc/build/config/ios/BuildInfo.plist new file mode 100644 index 0000000000..3595e5aefb --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/BuildInfo.plist @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>BuildMachineOSBuild</key> + <string>${BUILD_MACHINE_OS_BUILD}</string> + <key>CFBundleSupportedPlatforms</key> + <array> + <string>${IOS_SUPPORTED_PLATFORM}</string> + </array> + <key>DTCompiler</key> + <string>${GCC_VERSION}</string> + <key>DTPlatformName</key> + <string>${IOS_PLATFORM_NAME}</string> + <key>DTPlatformVersion</key> + <string>${IOS_PLATFORM_VERSION}</string> + <key>DTPlatformBuild</key> + <string>${IOS_PLATFORM_BUILD}</string> + <key>DTSDKBuild</key> + <string>${IOS_SDK_BUILD}</string> + <key>DTSDKName</key> + <string>${IOS_SDK_NAME}</string> + <key>MinimumOSVersion</key> + <string>${IOS_DEPLOYMENT_TARGET}</string> + <key>DTXcode</key> + <string>${XCODE_VERSION}</string> + <key>DTXcodeBuild</key> + <string>${XCODE_BUILD}</string> + <key>UIDeviceFamily</key> + <array> + <integer>1</integer> + <integer>2</integer> + </array> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/ios/Host-Info.plist b/third_party/libwebrtc/build/config/ios/Host-Info.plist new file mode 100644 index 0000000000..9f6f5deef9 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/Host-Info.plist @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${IOS_BUNDLE_ID_PREFIX}.test.${EXECUTABLE_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSAllowsArbitraryLoads</key> + <true/> + </dict> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UILaunchImages</key> + <array> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{320, 480}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{320, 568}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{375, 667}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{414, 736}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Landscape</string> + <key>UILaunchImageSize</key> + <string>{414, 736}</string> + </dict> + </array> + <key>UILaunchImages~ipad</key> + <array> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{768, 1024}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Landscape</string> + <key>UILaunchImageSize</key> + <string>{768, 1024}</string> + </dict> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/ios/Module-Info.plist b/third_party/libwebrtc/build/config/ios/Module-Info.plist new file mode 100644 index 0000000000..d1bf77faf0 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/Module-Info.plist @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>${IOS_BUNDLE_ID_PREFIX}.${MODULE_BUNDLE_ID:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>NSPrincipalClass</key> + <string>${XCTEST_BUNDLE_PRINCIPAL_CLASS}</string> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/ios/OWNERS b/third_party/libwebrtc/build/config/ios/OWNERS new file mode 100644 index 0000000000..6f3324f07c --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/OWNERS @@ -0,0 +1 @@ +file://build/apple/OWNERS diff --git a/third_party/libwebrtc/build/config/ios/asset_catalog.gni b/third_party/libwebrtc/build/config/ios/asset_catalog.gni new file mode 100644 index 0000000000..84dd92cce2 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/asset_catalog.gni @@ -0,0 +1,150 @@ +# Copyright 2017 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. + +import("//build/config/ios/ios_sdk.gni") + +# This template declares a bundle_data target that references an asset +# catalog so that it is compiled to the asset catalog of the generated +# bundle. +# +# The create_bundle target requires that all asset catalogs are part of an +# .xcasset bundle. This requirement comes from actool that only receives +# the path to the .xcasset bundle directory and not to the individual +# .imageset directories. +# +# The requirement is a bit problematic as it prevents compiling only a +# subset of the asset catakig that are contained in a .xcasset. This template +# fixes that by instead copying the content of the asset catalog to temporary +# .xcasset directory (below $root_out_dir) and defining a bundle_data +# target that refers to those copies (this is efficient as the "copy" is +# implemented by hardlinking if possible on macOS). +# +# Since the create_data target will only refer to the .xcasset directory +# and additional "action" target that runs a dummy script is defined. It +# does nothing but pretends to generate the .xcassets directory (while +# it is really created as a side-effect of the "copy" step). This allows +# to workaround the check in "gn" that all inputs below $root_out_dir have +# to be outputs of another target with a public dependency path. +# +# This template also ensures that the file are only copied once when the +# build targets multiple architectures at the same time (aka "fat build"). +# +# Arguments +# +# sources: +# required, list of strings, paths to the file contained in the +# asset catalog directory; this must contain the Contents.json file +# and all the image referenced by it (not enforced by the template). +# +# asset_type: +# required, string, type of the asset catalog, that is the extension +# of the directory containing the images and the Contents.json file. +# +template("asset_catalog") { + assert(defined(invoker.sources) && invoker.sources != [], + "sources must be defined and not empty for $target_name") + + assert(defined(invoker.asset_type) && invoker.asset_type != "", + "asset_type must be defined and not empty for $target_name") + + if (is_fat_secondary_toolchain) { + group(target_name) { + public_deps = [ ":$target_name($primary_fat_toolchain_name)" ] + } + } else { + _copy_target_name = target_name + "__copy" + _data_target_name = target_name + + _sources = invoker.sources + _outputs = [] + + # The compilation of resources into Assets.car is enabled automatically + # by the "create_bundle" target if any of the "bundle_data" sources's + # path is in a .xcassets directory and matches one of the know asset + # catalog type. + _xcassets_dir = "$target_gen_dir/${target_name}.xcassets" + _output_dir = "$_xcassets_dir/" + + get_path_info(get_path_info(_sources[0], "dir"), "file") + + foreach(_source, invoker.sources) { + _dir = get_path_info(_source, "dir") + _outputs += [ "$_output_dir/" + get_path_info(_source, "file") ] + + assert(get_path_info(_dir, "extension") == invoker.asset_type, + "$_source dirname must have .${invoker.asset_type} extension") + } + + action(_copy_target_name) { + # Forward "deps", "public_deps" and "testonly" in case some of the + # source files are generated. + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + ]) + + script = "//build/config/ios/hardlink.py" + + visibility = [ ":$_data_target_name" ] + sources = _sources + outputs = _outputs + [ _xcassets_dir ] + + args = [ + rebase_path(get_path_info(_sources[0], "dir"), root_build_dir), + rebase_path(_output_dir, root_build_dir), + ] + } + + bundle_data(_data_target_name) { + forward_variables_from(invoker, + "*", + [ + "deps", + "outputs", + "public_deps", + "sources", + ]) + + sources = _outputs + outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ] + public_deps = [ ":$_copy_target_name" ] + } + } +} + +# Those templates are specialisation of the asset_catalog template for known +# types of asset catalog types (imageset, launchimage, appiconset). +# +# Arguments +# +# sources: +# required, list of strings, paths to the file contained in the +# asset catalog directory; this must contain the Contents.json file +# and all the image referenced by it (not enforced by the template). +# +template("appiconset") { + asset_catalog(target_name) { + forward_variables_from(invoker, "*", [ "asset_type" ]) + asset_type = "appiconset" + } +} +template("colorset") { + asset_catalog(target_name) { + forward_variables_from(invoker, "*", [ "asset_type" ]) + asset_type = "colorset" + } +} +template("imageset") { + asset_catalog(target_name) { + forward_variables_from(invoker, "*", [ "asset_type" ]) + asset_type = "imageset" + } +} +template("launchimage") { + asset_catalog(target_name) { + forward_variables_from(invoker, "*", [ "asset_type" ]) + asset_type = "launchimage" + } +} diff --git a/third_party/libwebrtc/build/config/ios/codesign.py b/third_party/libwebrtc/build/config/ios/codesign.py new file mode 100644 index 0000000000..15d25a78df --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/codesign.py @@ -0,0 +1,691 @@ +# Copyright 2016 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. + +from __future__ import print_function + +import argparse +import codecs +import datetime +import fnmatch +import glob +import json +import os +import plistlib +import shutil +import subprocess +import sys +import tempfile + +if sys.version_info.major < 3: + basestring_compat = basestring +else: + basestring_compat = str + + +def GetProvisioningProfilesDir(): + """Returns the location of the installed mobile provisioning profiles. + + Returns: + The path to the directory containing the installed mobile provisioning + profiles as a string. + """ + return os.path.join( + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') + + +def ReadPlistFromString(plist_bytes): + """Parse property list from given |plist_bytes|. + + Args: + plist_bytes: contents of property list to load. Must be bytes in python 3. + + Returns: + The contents of property list as a python object. + """ + if sys.version_info.major == 2: + return plistlib.readPlistFromString(plist_bytes) + else: + return plistlib.loads(plist_bytes) + + +def LoadPlistFile(plist_path): + """Loads property list file at |plist_path|. + + Args: + plist_path: path to the property list file to load. + + Returns: + The content of the property list file as a python object. + """ + if sys.version_info.major == 2: + return plistlib.readPlistFromString( + subprocess.check_output( + ['xcrun', 'plutil', '-convert', 'xml1', '-o', '-', plist_path])) + else: + with open(plist_path, 'rb') as fp: + return plistlib.load(fp) + + +def CreateSymlink(value, location): + """Creates symlink with value at location if the target exists.""" + target = os.path.join(os.path.dirname(location), value) + if os.path.exists(location): + os.unlink(location) + os.symlink(value, location) + + +class Bundle(object): + """Wraps a bundle.""" + + def __init__(self, bundle_path, platform): + """Initializes the Bundle object with data from bundle Info.plist file.""" + self._path = bundle_path + self._kind = Bundle.Kind(platform, os.path.splitext(bundle_path)[-1]) + self._data = None + + def Load(self): + self._data = LoadPlistFile(self.info_plist_path) + + @staticmethod + def Kind(platform, extension): + if platform == 'iphonesimulator' or platform == 'iphoneos': + return 'ios' + if platform == 'macosx': + if extension == '.framework': + return 'mac_framework' + return 'mac' + raise ValueError('unknown bundle type %s for %s' % (extension, platform)) + + @property + def kind(self): + return self._kind + + @property + def path(self): + return self._path + + @property + def contents_dir(self): + if self._kind == 'mac': + return os.path.join(self.path, 'Contents') + if self._kind == 'mac_framework': + return os.path.join(self.path, 'Versions/A') + return self.path + + @property + def executable_dir(self): + if self._kind == 'mac': + return os.path.join(self.contents_dir, 'MacOS') + return self.contents_dir + + @property + def resources_dir(self): + if self._kind == 'mac' or self._kind == 'mac_framework': + return os.path.join(self.contents_dir, 'Resources') + return self.path + + @property + def info_plist_path(self): + if self._kind == 'mac_framework': + return os.path.join(self.resources_dir, 'Info.plist') + return os.path.join(self.contents_dir, 'Info.plist') + + @property + def signature_dir(self): + return os.path.join(self.contents_dir, '_CodeSignature') + + @property + def identifier(self): + return self._data['CFBundleIdentifier'] + + @property + def binary_name(self): + return self._data['CFBundleExecutable'] + + @property + def binary_path(self): + return os.path.join(self.executable_dir, self.binary_name) + + def Validate(self, expected_mappings): + """Checks that keys in the bundle have the expected value. + + Args: + expected_mappings: a dictionary of string to object, each mapping will + be looked up in the bundle data to check it has the same value (missing + values will be ignored) + + Returns: + A dictionary of the key with a different value between expected_mappings + and the content of the bundle (i.e. errors) so that caller can format the + error message. The dictionary will be empty if there are no errors. + """ + errors = {} + for key, expected_value in expected_mappings.items(): + if key in self._data: + value = self._data[key] + if value != expected_value: + errors[key] = (value, expected_value) + return errors + + +class ProvisioningProfile(object): + """Wraps a mobile provisioning profile file.""" + + def __init__(self, provisioning_profile_path): + """Initializes the ProvisioningProfile with data from profile file.""" + self._path = provisioning_profile_path + self._data = ReadPlistFromString( + subprocess.check_output([ + 'xcrun', 'security', 'cms', '-D', '-u', 'certUsageAnyCA', '-i', + provisioning_profile_path + ])) + + @property + def path(self): + return self._path + + @property + def team_identifier(self): + return self._data.get('TeamIdentifier', [''])[0] + + @property + def name(self): + return self._data.get('Name', '') + + @property + def application_identifier_pattern(self): + return self._data.get('Entitlements', {}).get('application-identifier', '') + + @property + def application_identifier_prefix(self): + return self._data.get('ApplicationIdentifierPrefix', [''])[0] + + @property + def entitlements(self): + return self._data.get('Entitlements', {}) + + @property + def expiration_date(self): + return self._data.get('ExpirationDate', datetime.datetime.now()) + + def ValidToSignBundle(self, bundle_identifier): + """Checks whether the provisioning profile can sign bundle_identifier. + + Args: + bundle_identifier: the identifier of the bundle that needs to be signed. + + Returns: + True if the mobile provisioning profile can be used to sign a bundle + with the corresponding bundle_identifier, False otherwise. + """ + return fnmatch.fnmatch( + '%s.%s' % (self.application_identifier_prefix, bundle_identifier), + self.application_identifier_pattern) + + def Install(self, installation_path): + """Copies mobile provisioning profile info to |installation_path|.""" + shutil.copy2(self.path, installation_path) + + +class Entitlements(object): + """Wraps an Entitlement plist file.""" + + def __init__(self, entitlements_path): + """Initializes Entitlements object from entitlement file.""" + self._path = entitlements_path + self._data = LoadPlistFile(self._path) + + @property + def path(self): + return self._path + + def ExpandVariables(self, substitutions): + self._data = self._ExpandVariables(self._data, substitutions) + + def _ExpandVariables(self, data, substitutions): + if isinstance(data, basestring_compat): + for key, substitution in substitutions.items(): + data = data.replace('$(%s)' % (key,), substitution) + return data + + if isinstance(data, dict): + for key, value in data.items(): + data[key] = self._ExpandVariables(value, substitutions) + return data + + if isinstance(data, list): + for i, value in enumerate(data): + data[i] = self._ExpandVariables(value, substitutions) + + return data + + def LoadDefaults(self, defaults): + for key, value in defaults.items(): + if key not in self._data: + self._data[key] = value + + def WriteTo(self, target_path): + with open(target_path, 'wb') as fp: + if sys.version_info.major == 2: + plistlib.writePlist(self._data, fp) + else: + plistlib.dump(self._data, fp) + + +def FindProvisioningProfile(bundle_identifier, required): + """Finds mobile provisioning profile to use to sign bundle. + + Args: + bundle_identifier: the identifier of the bundle to sign. + + Returns: + The ProvisioningProfile object that can be used to sign the Bundle + object or None if no matching provisioning profile was found. + """ + provisioning_profile_paths = glob.glob( + os.path.join(GetProvisioningProfilesDir(), '*.mobileprovision')) + + # Iterate over all installed mobile provisioning profiles and filter those + # that can be used to sign the bundle, ignoring expired ones. + now = datetime.datetime.now() + valid_provisioning_profiles = [] + one_hour = datetime.timedelta(0, 3600) + for provisioning_profile_path in provisioning_profile_paths: + provisioning_profile = ProvisioningProfile(provisioning_profile_path) + if provisioning_profile.expiration_date - now < one_hour: + sys.stderr.write( + 'Warning: ignoring expired provisioning profile: %s.\n' % + provisioning_profile_path) + continue + if provisioning_profile.ValidToSignBundle(bundle_identifier): + valid_provisioning_profiles.append(provisioning_profile) + + if not valid_provisioning_profiles: + if required: + sys.stderr.write( + 'Error: no mobile provisioning profile found for "%s".\n' % + bundle_identifier) + sys.exit(1) + return None + + # Select the most specific mobile provisioning profile, i.e. the one with + # the longest application identifier pattern (prefer the one with the latest + # expiration date as a secondary criteria). + selected_provisioning_profile = max( + valid_provisioning_profiles, + key=lambda p: (len(p.application_identifier_pattern), p.expiration_date)) + + one_week = datetime.timedelta(7) + if selected_provisioning_profile.expiration_date - now < 2 * one_week: + sys.stderr.write( + 'Warning: selected provisioning profile will expire soon: %s' % + selected_provisioning_profile.path) + return selected_provisioning_profile + + +def CodeSignBundle(bundle_path, identity, extra_args): + process = subprocess.Popen( + ['xcrun', 'codesign', '--force', '--sign', identity, '--timestamp=none'] + + list(extra_args) + [bundle_path], + stderr=subprocess.PIPE, + universal_newlines=True) + _, stderr = process.communicate() + if process.returncode: + sys.stderr.write(stderr) + sys.exit(process.returncode) + for line in stderr.splitlines(): + if line.endswith(': replacing existing signature'): + # Ignore warning about replacing existing signature as this should only + # happen when re-signing system frameworks (and then it is expected). + continue + sys.stderr.write(line) + sys.stderr.write('\n') + + +def InstallSystemFramework(framework_path, bundle_path, args): + """Install framework from |framework_path| to |bundle| and code-re-sign it.""" + installed_framework_path = os.path.join( + bundle_path, 'Frameworks', os.path.basename(framework_path)) + + if os.path.isfile(framework_path): + shutil.copy(framework_path, installed_framework_path) + elif os.path.isdir(framework_path): + if os.path.exists(installed_framework_path): + shutil.rmtree(installed_framework_path) + shutil.copytree(framework_path, installed_framework_path) + + CodeSignBundle(installed_framework_path, args.identity, + ['--deep', '--preserve-metadata=identifier,entitlements,flags']) + + +def GenerateEntitlements(path, provisioning_profile, bundle_identifier): + """Generates an entitlements file. + + Args: + path: path to the entitlements template file + provisioning_profile: ProvisioningProfile object to use, may be None + bundle_identifier: identifier of the bundle to sign. + """ + entitlements = Entitlements(path) + if provisioning_profile: + entitlements.LoadDefaults(provisioning_profile.entitlements) + app_identifier_prefix = \ + provisioning_profile.application_identifier_prefix + '.' + else: + app_identifier_prefix = '*.' + entitlements.ExpandVariables({ + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + }) + return entitlements + + +def GenerateBundleInfoPlist(bundle, plist_compiler, partial_plist): + """Generates the bundle Info.plist for a list of partial .plist files. + + Args: + bundle: a Bundle instance + plist_compiler: string, path to the Info.plist compiler + partial_plist: list of path to partial .plist files to merge + """ + + # Filter empty partial .plist files (this happens if an application + # does not compile any asset catalog, in which case the partial .plist + # file from the asset catalog compilation step is just a stamp file). + filtered_partial_plist = [] + for plist in partial_plist: + plist_size = os.stat(plist).st_size + if plist_size: + filtered_partial_plist.append(plist) + + # Invoke the plist_compiler script. It needs to be a python script. + subprocess.check_call([ + 'python', + plist_compiler, + 'merge', + '-f', + 'binary1', + '-o', + bundle.info_plist_path, + ] + filtered_partial_plist) + + +class Action(object): + """Class implementing one action supported by the script.""" + + @classmethod + def Register(cls, subparsers): + parser = subparsers.add_parser(cls.name, help=cls.help) + parser.set_defaults(func=cls._Execute) + cls._Register(parser) + + +class CodeSignBundleAction(Action): + """Class implementing the code-sign-bundle action.""" + + name = 'code-sign-bundle' + help = 'perform code signature for a bundle' + + @staticmethod + def _Register(parser): + parser.add_argument( + '--entitlements', '-e', dest='entitlements_path', + help='path to the entitlements file to use') + parser.add_argument( + 'path', help='path to the iOS bundle to codesign') + parser.add_argument( + '--identity', '-i', required=True, + help='identity to use to codesign') + parser.add_argument( + '--binary', '-b', required=True, + help='path to the iOS bundle binary') + parser.add_argument( + '--framework', '-F', action='append', default=[], dest='frameworks', + help='install and resign system framework') + parser.add_argument( + '--disable-code-signature', action='store_true', dest='no_signature', + help='disable code signature') + parser.add_argument( + '--disable-embedded-mobileprovision', action='store_false', + default=True, dest='embedded_mobileprovision', + help='disable finding and embedding mobileprovision') + parser.add_argument( + '--platform', '-t', required=True, + help='platform the signed bundle is targeting') + parser.add_argument( + '--partial-info-plist', '-p', action='append', default=[], + help='path to partial Info.plist to merge to create bundle Info.plist') + parser.add_argument( + '--plist-compiler-path', '-P', action='store', + help='path to the plist compiler script (for --partial-info-plist)') + parser.set_defaults(no_signature=False) + + @staticmethod + def _Execute(args): + if not args.identity: + args.identity = '-' + + bundle = Bundle(args.path, args.platform) + + if args.partial_info_plist: + GenerateBundleInfoPlist(bundle, args.plist_compiler_path, + args.partial_info_plist) + + # The bundle Info.plist may have been updated by GenerateBundleInfoPlist() + # above. Load the bundle information from Info.plist after the modification + # have been written to disk. + bundle.Load() + + # According to Apple documentation, the application binary must be the same + # as the bundle name without the .app suffix. See crbug.com/740476 for more + # information on what problem this can cause. + # + # To prevent this class of error, fail with an error if the binary name is + # incorrect in the Info.plist as it is not possible to update the value in + # Info.plist at this point (the file has been copied by a different target + # and ninja would consider the build dirty if it was updated). + # + # Also checks that the name of the bundle is correct too (does not cause the + # build to be considered dirty, but still terminate the script in case of an + # incorrect bundle name). + # + # Apple documentation is available at: + # https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html + bundle_name = os.path.splitext(os.path.basename(bundle.path))[0] + errors = bundle.Validate({ + 'CFBundleName': bundle_name, + 'CFBundleExecutable': bundle_name, + }) + if errors: + for key in sorted(errors): + value, expected_value = errors[key] + sys.stderr.write('%s: error: %s value incorrect: %s != %s\n' % ( + bundle.path, key, value, expected_value)) + sys.stderr.flush() + sys.exit(1) + + # Delete existing embedded mobile provisioning. + embedded_provisioning_profile = os.path.join( + bundle.path, 'embedded.mobileprovision') + if os.path.isfile(embedded_provisioning_profile): + os.unlink(embedded_provisioning_profile) + + # Delete existing code signature. + if os.path.exists(bundle.signature_dir): + shutil.rmtree(bundle.signature_dir) + + # Install system frameworks if requested. + for framework_path in args.frameworks: + InstallSystemFramework(framework_path, args.path, args) + + # Copy main binary into bundle. + if not os.path.isdir(bundle.executable_dir): + os.makedirs(bundle.executable_dir) + shutil.copy(args.binary, bundle.binary_path) + + if bundle.kind == 'mac_framework': + # Create Versions/Current -> Versions/A symlink + CreateSymlink('A', os.path.join(bundle.path, 'Versions/Current')) + + # Create $binary_name -> Versions/Current/$binary_name symlink + CreateSymlink(os.path.join('Versions/Current', bundle.binary_name), + os.path.join(bundle.path, bundle.binary_name)) + + # Create optional symlinks. + for name in ('Headers', 'Resources', 'Modules'): + target = os.path.join(bundle.path, 'Versions/A', name) + if os.path.exists(target): + CreateSymlink(os.path.join('Versions/Current', name), + os.path.join(bundle.path, name)) + else: + obsolete_path = os.path.join(bundle.path, name) + if os.path.exists(obsolete_path): + os.unlink(obsolete_path) + + if args.no_signature: + return + + codesign_extra_args = [] + + if args.embedded_mobileprovision: + # Find mobile provisioning profile and embeds it into the bundle (if a + # code signing identify has been provided, fails if no valid mobile + # provisioning is found). + provisioning_profile_required = args.identity != '-' + provisioning_profile = FindProvisioningProfile( + bundle.identifier, provisioning_profile_required) + if provisioning_profile and args.platform != 'iphonesimulator': + provisioning_profile.Install(embedded_provisioning_profile) + + if args.entitlements_path is not None: + temporary_entitlements_file = \ + tempfile.NamedTemporaryFile(suffix='.xcent') + codesign_extra_args.extend( + ['--entitlements', temporary_entitlements_file.name]) + + entitlements = GenerateEntitlements( + args.entitlements_path, provisioning_profile, bundle.identifier) + entitlements.WriteTo(temporary_entitlements_file.name) + + CodeSignBundle(bundle.path, args.identity, codesign_extra_args) + + +class CodeSignFileAction(Action): + """Class implementing code signature for a single file.""" + + name = 'code-sign-file' + help = 'code-sign a single file' + + @staticmethod + def _Register(parser): + parser.add_argument( + 'path', help='path to the file to codesign') + parser.add_argument( + '--identity', '-i', required=True, + help='identity to use to codesign') + parser.add_argument( + '--output', '-o', + help='if specified copy the file to that location before signing it') + parser.set_defaults(sign=True) + + @staticmethod + def _Execute(args): + if not args.identity: + args.identity = '-' + + install_path = args.path + if args.output: + + if os.path.isfile(args.output): + os.unlink(args.output) + elif os.path.isdir(args.output): + shutil.rmtree(args.output) + + if os.path.isfile(args.path): + shutil.copy(args.path, args.output) + elif os.path.isdir(args.path): + shutil.copytree(args.path, args.output) + + install_path = args.output + + CodeSignBundle(install_path, args.identity, + ['--deep', '--preserve-metadata=identifier,entitlements']) + + +class GenerateEntitlementsAction(Action): + """Class implementing the generate-entitlements action.""" + + name = 'generate-entitlements' + help = 'generate entitlements file' + + @staticmethod + def _Register(parser): + parser.add_argument( + '--entitlements', '-e', dest='entitlements_path', + help='path to the entitlements file to use') + parser.add_argument( + 'path', help='path to the entitlements file to generate') + parser.add_argument( + '--info-plist', '-p', required=True, + help='path to the bundle Info.plist') + + @staticmethod + def _Execute(args): + info_plist = LoadPlistFile(args.info_plist) + bundle_identifier = info_plist['CFBundleIdentifier'] + provisioning_profile = FindProvisioningProfile(bundle_identifier, False) + entitlements = GenerateEntitlements( + args.entitlements_path, provisioning_profile, bundle_identifier) + entitlements.WriteTo(args.path) + + +class FindProvisioningProfileAction(Action): + """Class implementing the find-codesign-identity action.""" + + name = 'find-provisioning-profile' + help = 'find provisioning profile for use by Xcode project generator' + + @staticmethod + def _Register(parser): + parser.add_argument('--bundle-id', + '-b', + required=True, + help='bundle identifier') + + @staticmethod + def _Execute(args): + provisioning_profile_info = {} + provisioning_profile = FindProvisioningProfile(args.bundle_id, False) + for key in ('team_identifier', 'name'): + if provisioning_profile: + provisioning_profile_info[key] = getattr(provisioning_profile, key) + else: + provisioning_profile_info[key] = '' + print(json.dumps(provisioning_profile_info)) + + +def Main(): + # Cache this codec so that plistlib can find it. See + # https://crbug.com/999461#c12 for more details. + codecs.lookup('utf-8') + + parser = argparse.ArgumentParser('codesign iOS bundles') + subparsers = parser.add_subparsers() + + actions = [ + CodeSignBundleAction, + CodeSignFileAction, + GenerateEntitlementsAction, + FindProvisioningProfileAction, + ] + + for action in actions: + action.Register(subparsers) + + args = parser.parse_args() + args.func(args) + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/third_party/libwebrtc/build/config/ios/compile_ib_files.py b/third_party/libwebrtc/build/config/ios/compile_ib_files.py new file mode 100644 index 0000000000..84781c1773 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/compile_ib_files.py @@ -0,0 +1,57 @@ +# Copyright 2016 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. + +from __future__ import print_function + +import argparse +import logging +import os +import re +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser( + description='A script to compile xib and storyboard.', + fromfile_prefix_chars='@') + parser.add_argument('-o', '--output', required=True, + help='Path to output bundle.') + parser.add_argument('-i', '--input', required=True, + help='Path to input xib or storyboard.') + args, unknown_args = parser.parse_known_args() + + ibtool_args = [ + 'xcrun', 'ibtool', + '--errors', '--warnings', '--notices', + '--output-format', 'human-readable-text' + ] + ibtool_args += unknown_args + ibtool_args += [ + '--compile', + os.path.abspath(args.output), + os.path.abspath(args.input) + ] + + ibtool_section_re = re.compile(r'/\*.*\*/') + ibtool_re = re.compile(r'.*note:.*is clipping its content') + try: + stdout = subprocess.check_output(ibtool_args) + except subprocess.CalledProcessError as e: + print(e.output) + raise + current_section_header = None + for line in stdout.splitlines(): + if ibtool_section_re.match(line): + current_section_header = line + elif not ibtool_re.match(line): + if current_section_header: + print(current_section_header) + current_section_header = None + print(line) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py b/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py new file mode 100644 index 0000000000..7655df8c05 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/compile_xcassets_unittests.py @@ -0,0 +1,141 @@ +# Copyright 2017 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. + +import unittest +import compile_xcassets + + +class TestFilterCompilerOutput(unittest.TestCase): + + relative_paths = { + '/Users/janedoe/chromium/src/Chromium.xcassets': + '../../Chromium.xcassets', + '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car': + 'Chromium.app/Assets.car', + } + + def testNoError(self): + self.assertEquals( + '', + compile_xcassets.FilterCompilerOutput( + '/* com.apple.actool.compilation-results */\n' + '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n', + self.relative_paths)) + + def testNoErrorRandomMessages(self): + self.assertEquals( + '', + compile_xcassets.FilterCompilerOutput( + '2017-07-04 04:59:19.460 ibtoold[23487:41214] CoreSimulator is att' + 'empting to unload a stale CoreSimulatorService job. Existing' + ' job (com.apple.CoreSimulator.CoreSimulatorService.179.1.E8tt' + 'yeDeVgWK) is from an older version and is being removed to pr' + 'event problems.\n' + '/* com.apple.actool.compilation-results */\n' + '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n', + self.relative_paths)) + + def testWarning(self): + self.assertEquals( + '/* com.apple.actool.document.warnings */\n' + '../../Chromium.xcassets:./image1.imageset/[universal][][][1x][][][][' + '][][]: warning: The file "image1.png" for the image set "image1"' + ' does not exist.\n', + compile_xcassets.FilterCompilerOutput( + '/* com.apple.actool.document.warnings */\n' + '/Users/janedoe/chromium/src/Chromium.xcassets:./image1.imageset/[' + 'universal][][][1x][][][][][][]: warning: The file "image1.png' + '" for the image set "image1" does not exist.\n' + '/* com.apple.actool.compilation-results */\n' + '/Users/janedoe/chromium/src/out/Default/Chromium.app/Assets.car\n', + self.relative_paths)) + + def testError(self): + self.assertEquals( + '/* com.apple.actool.errors */\n' + '../../Chromium.xcassets: error: The output directory "/Users/janedoe/' + 'chromium/src/out/Default/Chromium.app" does not exist.\n', + compile_xcassets.FilterCompilerOutput( + '/* com.apple.actool.errors */\n' + '/Users/janedoe/chromium/src/Chromium.xcassets: error: The output ' + 'directory "/Users/janedoe/chromium/src/out/Default/Chromium.a' + 'pp" does not exist.\n' + '/* com.apple.actool.compilation-results */\n', + self.relative_paths)) + + def testSpurious(self): + self.assertEquals( + '/* com.apple.actool.document.warnings */\n' + '../../Chromium.xcassets:./AppIcon.appiconset: warning: A 1024x1024 ap' + 'p store icon is required for iOS apps\n', + compile_xcassets.FilterCompilerOutput( + '/* com.apple.actool.document.warnings */\n' + '/Users/janedoe/chromium/src/Chromium.xcassets:./AppIcon.appiconse' + 't: warning: A 1024x1024 app store icon is required for iOS ap' + 'ps\n' + '/* com.apple.actool.document.notices */\n' + '/Users/janedoe/chromium/src/Chromium.xcassets:./AppIcon.appiconse' + 't/[][ipad][76x76][][][1x][][]: notice: (null)\n', + self.relative_paths)) + + def testComplexError(self): + self.assertEquals( + '/* com.apple.actool.errors */\n' + ': error: Failed to find a suitable device for the type SimDeviceType ' + ': com.apple.dt.Xcode.IBSimDeviceType.iPad-2x with runtime SimRunt' + 'ime : 10.3.1 (14E8301) - com.apple.CoreSimulator.SimRuntime.iOS-1' + '0-3\n' + ' Failure Reason: Failed to create SimDeviceSet at path /Users/jane' + 'doe/Library/Developer/Xcode/UserData/IB Support/Simulator Devices' + '. You\'ll want to check the logs in ~/Library/Logs/CoreSimulator ' + 'to see why creating the SimDeviceSet failed.\n' + ' Underlying Errors:\n' + ' Description: Failed to initialize simulator device set.\n' + ' Failure Reason: Failed to subscribe to notifications from Cor' + 'eSimulatorService.\n' + ' Underlying Errors:\n' + ' Description: Error returned in reply to notification requ' + 'est: Connection invalid\n' + ' Failure Reason: Software caused connection abort\n', + compile_xcassets.FilterCompilerOutput( + '2017-07-07 10:37:27.367 ibtoold[88538:12553239] CoreSimulator det' + 'ected Xcode.app relocation or CoreSimulatorService version ch' + 'ange. Framework path (/Applications/Xcode.app/Contents/Devel' + 'oper/Library/PrivateFrameworks/CoreSimulator.framework) and v' + 'ersion (375.21) does not match existing job path (/Library/De' + 'veloper/PrivateFrameworks/CoreSimulator.framework/Versions/A/' + 'XPCServices/com.apple.CoreSimulator.CoreSimulatorService.xpc)' + ' and version (459.13). Attempting to remove the stale servic' + 'e in order to add the expected version.\n' + '2017-07-07 10:37:27.625 ibtoold[88538:12553256] CoreSimulatorServ' + 'ice connection interrupted. Resubscribing to notifications.\n' + '2017-07-07 10:37:27.632 ibtoold[88538:12553264] CoreSimulatorServ' + 'ice connection became invalid. Simulator services will no lo' + 'nger be available.\n' + '2017-07-07 10:37:27.642 ibtoold[88538:12553274] CoreSimulatorServ' + 'ice connection became invalid. Simulator services will no lo' + 'nger be available.\n' + '/* com.apple.actool.errors */\n' + ': error: Failed to find a suitable device for the type SimDeviceT' + 'ype : com.apple.dt.Xcode.IBSimDeviceType.iPad-2x with runtime' + ' SimRuntime : 10.3.1 (14E8301) - com.apple.CoreSimulator.SimR' + 'untime.iOS-10-3\n' + ' Failure Reason: Failed to create SimDeviceSet at path /Users/' + 'janedoe/Library/Developer/Xcode/UserData/IB Support/Simulator' + ' Devices. You\'ll want to check the logs in ~/Library/Logs/Co' + 'reSimulator to see why creating the SimDeviceSet failed.\n' + ' Underlying Errors:\n' + ' Description: Failed to initialize simulator device set.\n' + ' Failure Reason: Failed to subscribe to notifications from' + ' CoreSimulatorService.\n' + ' Underlying Errors:\n' + ' Description: Error returned in reply to notification ' + 'request: Connection invalid\n' + ' Failure Reason: Software caused connection abort\n' + '/* com.apple.actool.compilation-results */\n', + self.relative_paths)) + + +if __name__ == '__main__': + unittest.main() diff --git a/third_party/libwebrtc/build/config/ios/config.gni b/third_party/libwebrtc/build/config/ios/config.gni new file mode 100644 index 0000000000..358c7ccd2a --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/config.gni @@ -0,0 +1,28 @@ +# Copyright 2020 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. + +declare_args() { + # Configure the environment for which to build. Could be either "device", + # "simulator" or "catalyst". If unspecified, then it will be assumed to be + # "simulator" if the target_cpu is "x68" or "x64", "device" otherwise. The + # default is only there for compatibility reasons and will be removed (see + # crbug.com/1138425 for more details). + target_environment = "" + + # Control whether cronet is built (this is usually set by the script + # components/cronet/tools/cr_cronet.py as cronet requires specific + # gn args to build correctly). + is_cronet_build = false +} + +if (target_environment == "") { + if (target_cpu == "x86" || target_cpu == "x64") { + target_environment = "simulator" + } else { + target_environment = "device" + } +} + +assert(target_environment == "simulator" || target_environment == "device" || + target_environment == "catalyst") diff --git a/third_party/libwebrtc/build/config/ios/dummy.py b/third_party/libwebrtc/build/config/ios/dummy.py new file mode 100644 index 0000000000..b23b7dab96 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/dummy.py @@ -0,0 +1,15 @@ +# Copyright 2017 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. + +"""Empty script that does nothing and return success error code. + +This script is used by some gn targets that pretend creating some output +but instead depend on another target creating the output indirectly (in +general this output is a directory that is used as input by a bundle_data +target). + +It ignores all parameters and terminate with a success error code. It +does the same thing as the unix command "true", but gn can only invoke +python scripts. +""" diff --git a/third_party/libwebrtc/build/config/ios/entitlements.plist b/third_party/libwebrtc/build/config/ios/entitlements.plist new file mode 100644 index 0000000000..429762e3a3 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/entitlements.plist @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>application-identifier</key> + <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string> + <key>keychain-access-groups</key> + <array> + <string>$(AppIdentifierPrefix)$(CFBundleIdentifier)</string> + </array> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/ios/find_signing_identity.py b/third_party/libwebrtc/build/config/ios/find_signing_identity.py new file mode 100644 index 0000000000..d508e2bb46 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/find_signing_identity.py @@ -0,0 +1,89 @@ +# Copyright (c) 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. + +from __future__ import print_function + +import argparse +import os +import subprocess +import sys +import re + + +def Redact(value, from_nth_char=5): + """Redact value past the N-th character.""" + return value[:from_nth_char] + '*' * (len(value) - from_nth_char) + + +class Identity(object): + """Represents a valid identity.""" + + def __init__(self, identifier, name, team): + self.identifier = identifier + self.name = name + self.team = team + + def redacted(self): + return Identity(Redact(self.identifier), self.name, Redact(self.team)) + + def format(self): + return '%s: "%s (%s)"' % (self.identifier, self.name, self.team) + + +def ListIdentities(): + return subprocess.check_output([ + 'xcrun', + 'security', + 'find-identity', + '-v', + '-p', + 'codesigning', + ]).decode('utf8') + + +def FindValidIdentity(pattern): + """Find all identities matching the pattern.""" + lines = list(l.strip() for l in ListIdentities().splitlines()) + # Look for something like "2) XYZ "iPhone Developer: Name (ABC)"" + regex = re.compile('[0-9]+\) ([A-F0-9]+) "([^"(]*) \(([^)"]*)\)"') + + result = [] + for line in lines: + res = regex.match(line) + if res is None: + continue + if pattern is None or pattern in res.group(2): + result.append(Identity(*res.groups())) + return result + + +def Main(args): + parser = argparse.ArgumentParser('codesign iOS bundles') + parser.add_argument('--matching-pattern', + dest='pattern', + help='Pattern used to select the code signing identity.') + parsed = parser.parse_args(args) + + identities = FindValidIdentity(parsed.pattern) + if len(identities) == 1: + print(identities[0].identifier, end='') + return 0 + + all_identities = FindValidIdentity(None) + + print('Automatic code signing identity selection was enabled but could not') + print('find exactly one codesigning identity matching "%s".' % parsed.pattern) + print('') + print('Check that the keychain is accessible and that there is exactly one') + print('valid codesigning identity matching the pattern. Here is the parsed') + print('output of `xcrun security find-identity -v -p codesigning`:') + print() + for i, identity in enumerate(all_identities): + print(' %d) %s' % (i + 1, identity.redacted().format())) + print(' %d valid identities found' % (len(all_identities))) + return 1 + + +if __name__ == '__main__': + sys.exit(Main(sys.argv[1:])) diff --git a/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py b/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py new file mode 100644 index 0000000000..8547e18aa7 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/generate_umbrella_header.py @@ -0,0 +1,75 @@ +# Copyright 2018 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. + +"""Generates an umbrella header for an iOS framework.""" + +import argparse +import datetime +import os +import re +import string + + +HEADER_TEMPLATE = string.Template('''\ +// Copyright $year 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 file is auto-generated by //build/ios/config/generate_umbrella_header.py + +#ifndef $header_guard +#define $header_guard + +$imports + +#endif // $header_guard +''') + + +def ComputeHeaderGuard(file_path): + """Computes the header guard for a file path. + + Args: + file_path: The path to convert into an header guard. + Returns: + The header guard string for the file_path. + """ + return re.sub(r'[.+/\\]', r'_', file_path.upper()) + '_' + + +def WriteUmbrellaHeader(output_path, imported_headers): + """Writes the umbrella header. + + Args: + output_path: The path to the umbrella header. + imported_headers: A list of headers to #import in the umbrella header. + """ + year = datetime.date.today().year + header_guard = ComputeHeaderGuard(output_path) + imports = '\n'.join([ + '#import "%s"' % os.path.basename(header) + for header in sorted(imported_headers) + ]) + with open(output_path, 'w') as output_file: + output_file.write( + HEADER_TEMPLATE.safe_substitute({ + 'year': year, + 'header_guard': header_guard, + 'imports': imports, + })) + + +def Main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--output-path', required=True, type=str, + help='Path to the generated umbrella header.') + parser.add_argument('imported_headers', type=str, nargs='+', + help='Headers to #import in the umbrella header.') + options = parser.parse_args() + + return WriteUmbrellaHeader(options.output_path, options.imported_headers) + + +if __name__ == '__main__': + Main() diff --git a/third_party/libwebrtc/build/config/ios/hardlink.py b/third_party/libwebrtc/build/config/ios/hardlink.py new file mode 100644 index 0000000000..38f60d4013 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/hardlink.py @@ -0,0 +1,71 @@ +# Copyright 2017 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. + +"""Recursively create hardlink to target named output.""" + + +import argparse +import os +import shutil + + +def CreateHardlinkHelper(target, output): + """Recursively create a hardlink named output pointing to target. + + Args: + target: path to an existing file or directory + output: path to the newly created hardlink + + This function assumes that output does not exists but that the parent + directory containing output does. If those conditions are false, then + the function will fails with an exception corresponding to an OS error. + """ + if os.path.islink(target): + os.symlink(os.readlink(target), output) + elif not os.path.isdir(target): + try: + os.link(target, output) + except: + shutil.copy(target, output) + else: + os.mkdir(output) + for name in os.listdir(target): + CreateHardlinkHelper( + os.path.join(target, name), + os.path.join(output, name)) + + +def CreateHardlink(target, output): + """Recursively create a hardlink named output pointing to target. + + Args: + target: path to an existing file or directory + output: path to the newly created hardlink + + If output already exists, it is first removed. In all cases, the + parent directory containing output is created. + """ + if os.path.isdir(output): + shutil.rmtree(output) + elif os.path.exists(output): + os.unlink(output) + + parent_dir = os.path.dirname(os.path.abspath(output)) + if not os.path.isdir(parent_dir): + os.makedirs(parent_dir) + + CreateHardlinkHelper(target, output) + + +def Main(): + parser = argparse.ArgumentParser() + parser.add_argument('target', help='path to the file or directory to link to') + parser.add_argument('output', help='name of the hardlink to create') + args = parser.parse_args() + + CreateHardlink(args.target, args.output) + + +if __name__ == '__main__': + Main() diff --git a/third_party/libwebrtc/build/config/ios/ios_sdk.gni b/third_party/libwebrtc/build/config/ios/ios_sdk.gni new file mode 100644 index 0000000000..ffff5921d8 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/ios_sdk.gni @@ -0,0 +1,185 @@ +# 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. + +import("//build/config/ios/config.gni") +import("//build/config/ios/ios_sdk_overrides.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +assert(current_os == "ios") +assert(use_system_xcode, "Hermetic xcode doesn't work for ios.") + +declare_args() { + # SDK path to use. When empty this will use the default SDK based on the + # value of target_environment. + ios_bin_path = "" + ios_sdk_path = "" + ios_sdk_name = "" + ios_sdk_version = "" + ios_sdk_platform = "" + ios_sdk_platform_path = "" + ios_toolchains_path = "" + xcode_version = "" + xcode_version_int = 0 + xcode_build = "" + machine_os_build = "" + + # Set DEVELOPER_DIR while running sdk_info.py. + ios_sdk_developer_dir = "" + + # Control whether codesiging is enabled (ignored for simulator builds). + ios_enable_code_signing = true + + # Explicitly select the identity to use for codesigning. If defined, must + # be set to a non-empty string that will be passed to codesigning. Can be + # left unspecified if ios_code_signing_identity_description is used instead. + ios_code_signing_identity = "" + + # Pattern used to select the identity to use for codesigning. If defined, + # must be a substring of the description of exactly one of the identities by + # `security find-identity -v -p codesigning`. + ios_code_signing_identity_description = "Apple Development" + + # Prefix for CFBundleIdentifier property of iOS bundles (correspond to the + # "Organization Identifier" in Xcode). Code signing will fail if no mobile + # provisioning for the selected code signing identify support that prefix. + ios_app_bundle_id_prefix = "org.chromium" + + # If non-empty, this list must contain valid cpu architecture, and the final + # build will be a multi-architecture build (aka fat build) supporting the + # main $target_cpu architecture and all of $additional_target_cpus. + # + # For example to build an application that will run on both arm64 and armv7 + # devices, you would use the following in args.gn file when running "gn args": + # + # target_os = "ios" + # target_cpu = "arm64" + # additional_target_cpus = [ "arm" ] + # + # You can also pass the value via "--args" parameter for "gn gen" command by + # using the syntax --args='additional_target_cpus=["arm"] target_cpu="arm64"'. + additional_target_cpus = [] +} + +declare_args() { + # This variable is set by the toolchain. It is set to true if the toolchain + # is a secondary toolchain as part of a "fat" build. + is_fat_secondary_toolchain = false + + # This variable is set by the toolchain. It is the name of the primary + # toolchain for the fat build (could be current_toolchain). + primary_fat_toolchain_name = "" +} + +# Official builds may not use goma. +assert(!(use_goma && is_chrome_branded && is_official_build && + target_cpu == "arm64"), + "goma use is forbidden for official iOS builds.") + +assert(custom_toolchain == "" || additional_target_cpus == [], + "cannot define both custom_toolchain and additional_target_cpus") + +# If codesigning is enabled, use must configure either a codesigning identity +# or a filter to automatically select the codesigning identity. +if (target_environment == "device" && ios_enable_code_signing) { + assert(ios_code_signing_identity == "" || + ios_code_signing_identity_description == "", + "You should either specify the precise identity to use with " + + "ios_code_signing_identity or let the code select an identity " + + "automatically (via find_signing_identity.py which use the " + + "variable ios_code_signing_identity_description to set the " + + "pattern to match the identity to use).") +} + +# Initialize additional_toolchains from additional_target_cpus. Assert here +# that the list does not contains $target_cpu nor duplicates as this would +# cause weird errors during the build. +additional_toolchains = [] +if (additional_target_cpus != [] && !is_fat_secondary_toolchain) { + foreach(_additional_target_cpu, additional_target_cpus) { + assert(_additional_target_cpu != target_cpu, + "target_cpu must not be listed in additional_target_cpus") + + _toolchain = "${current_toolchain}_fat_${_additional_target_cpu}" + foreach(_additional_toolchain, additional_toolchains) { + assert(_toolchain != _additional_toolchain, + "additional_target_cpus must not contains duplicate values") + } + + additional_toolchains += [ _toolchain ] + } +} + +if (ios_sdk_path == "") { + # Compute default target. + if (target_environment == "simulator") { + ios_sdk_name = "iphonesimulator" + ios_sdk_platform = "iPhoneSimulator" + } else if (target_environment == "device") { + ios_sdk_name = "iphoneos" + ios_sdk_platform = "iPhoneOS" + } else if (target_environment == "catalyst") { + ios_sdk_name = "macosx" + ios_sdk_platform = "MacOSX" + } else { + assert(false, "unsupported environment: $target_environment") + } + + ios_sdk_info_args = [ + "--get_sdk_info", + "--get_machine_info", + ] + ios_sdk_info_args += [ ios_sdk_name ] + if (ios_sdk_developer_dir != "") { + ios_sdk_info_args += [ + "--developer_dir", + ios_sdk_developer_dir, + ] + } + if (use_system_xcode && use_goma) { + ios_sdk_info_args += [ + "--create_symlink_at", + "sdk/xcode_links", + ] + } + script_name = "//build/config/apple/sdk_info.py" + _ios_sdk_result = exec_script(script_name, ios_sdk_info_args, "scope") + ios_bin_path = + rebase_path("${_ios_sdk_result.toolchains_path}/usr/bin/", root_build_dir) + ios_sdk_path = _ios_sdk_result.sdk_path + ios_sdk_platform_path = _ios_sdk_result.sdk_platform_path + ios_sdk_version = _ios_sdk_result.sdk_version + ios_sdk_build = _ios_sdk_result.sdk_build + ios_toolchains_path = _ios_sdk_result.toolchains_path + xcode_version = _ios_sdk_result.xcode_version + xcode_version_int = _ios_sdk_result.xcode_version_int + xcode_build = _ios_sdk_result.xcode_build + machine_os_build = _ios_sdk_result.machine_os_build + if (target_environment == "simulator") { + # This is weird, but Xcode sets DTPlatformBuild to an empty field for + # simulator builds. + ios_platform_build = "" + } else { + ios_platform_build = ios_sdk_build + } +} + +if (target_environment == "device" && ios_enable_code_signing) { + # Automatically select a codesigning identity if no identity is configured. + # This only applies to device build as simulator builds are not signed. + if (ios_code_signing_identity == "") { + find_signing_identity_args = [] + if (ios_code_signing_identity_description != "") { + find_signing_identity_args = [ + "--matching-pattern", + ios_code_signing_identity_description, + ] + } + ios_code_signing_identity = exec_script("find_signing_identity.py", + find_signing_identity_args, + "trim string") + } +} diff --git a/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni b/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni new file mode 100644 index 0000000000..12d52521da --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/ios_sdk_overrides.gni @@ -0,0 +1,17 @@ +# Copyright 2017 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 file contains arguments that subprojects may choose to override. It +# asserts that those overrides are used, to prevent unused args warnings. + +declare_args() { + # Version of iOS that we're targeting. + ios_deployment_target = "14.0" +} + +# Always assert that ios_deployment_target is used on non-iOS platforms to +# prevent unused args warnings. +if (!is_ios) { + assert(ios_deployment_target == "14.0" || true) +} diff --git a/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni b/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni new file mode 100644 index 0000000000..115db7ffdb --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/ios_test_runner_wrapper.gni @@ -0,0 +1,143 @@ +# Copyright 2020 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. + +import("//build/config/coverage/coverage.gni") +import("//build/config/ios/ios_sdk.gni") +import("//build/util/generate_wrapper.gni") + +# Invokes generate_wrapper to create an executable script wrapping iOS' +# run.py with baked in arguments. Only takes effect when test entry in +# gn_isolate_map.pyl is updated to type="generated_script" with script +# set to the wrapper output path. +# +# Arguments: +# +# data +# (optional, default [ "//ios/build/bots/scripts/" ]) list of files or +# directories required to run target +# +# data_deps +# (optional) list of target non-linked labels +# +# deps +# (optional) list of files or directories required to run target +# +# executable_args +# (optional) a list of string arguments to pass to run.py +# +# retries +# (optional, default 3) number of retry attempts +# +# shards +# (optional, default 1) number of shards to execute tests in parallel. not +# the same as swarming shards. +# +# wrapper_output_name +# (optional, default "run_${target_name}") name of the wrapper script +# +template("ios_test_runner_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, + [ + "deps", + "retries", + "shards", + "wrapper_output_name", + ]) + testonly = true + executable = "//testing/test_env.py" + + # iOS main test runner + _runner_path = + rebase_path("//ios/build/bots/scripts/run.py", root_build_dir) + + executable_args = [ "@WrappedPath(${_runner_path})" ] + + # arguments passed to run.py + if (defined(invoker.executable_args)) { + executable_args += invoker.executable_args + } + + _rebased_mac_toolchain = rebase_path("//mac_toolchain", root_build_dir) + _rebased_xcode_path = rebase_path("//Xcode.app", root_build_dir) + _rebased_ios_runtime_cache_prefix = + rebase_path("//Runtime-ios-", root_build_dir) + + # --out-dir argument is specified in gn_isolate_map.pyl because + # ${ISOLATED_OUTDIR} doesn't get resolved through this wrapper. + executable_args += [ + "--xcode-path", + "@WrappedPath(${_rebased_xcode_path})", + "--mac-toolchain-cmd", + "@WrappedPath(${_rebased_mac_toolchain})", + "--runtime-cache-prefix", + "@WrappedPath(${_rebased_ios_runtime_cache_prefix})", + ] + + # Default retries to 3 + if (!defined(retries)) { + retries = 3 + } + executable_args += [ + "--retries", + "${retries}", + ] + + # Default shards to 1 + if (!defined(shards)) { + shards = 1 + } + executable_args += [ + "--shards", + "${shards}", + ] + + data_deps = [ "//testing:test_scripts_shared" ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } + + # test runner relies on iossim for simulator builds. + if (target_environment == "simulator") { + _rebased_root_build_dir = rebase_path("${root_build_dir}", root_build_dir) + data_deps += [ "//testing/iossim" ] + + executable_args += [ + "--iossim", + "@WrappedPath(${_rebased_root_build_dir}/iossim)", + ] + } + + if (use_clang_coverage) { + executable_args += [ "--use-clang-coverage" ] + } + + if (!is_debug) { + executable_args += [ "--release" ] + } + + # wrapper script output name and path + if (!defined(wrapper_output_name)) { + _wrapper_output_name = "run_${target_name}" + } else { + _wrapper_output_name = wrapper_output_name + } + + # Test targets may attempt to generate multiple wrappers for a suite with + # multiple different toolchains when running with additional_target_cpus. + # Generate the wrapper script into root_out_dir rather than root_build_dir + # to ensure those wrappers are distinct. + wrapper_script = "${root_out_dir}/bin/${_wrapper_output_name}" + + data = [] + if (defined(invoker.data)) { + data += invoker.data + } + data += [ + "//.vpython", + "//ios/build/bots/scripts/", + "//testing/test_env.py", + ] + } +} diff --git a/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist b/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist new file mode 100644 index 0000000000..cf9463f694 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/resources/XCTRunnerAddition+Info.plist @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleIdentifier</key> + <string>com.apple.test.${EXECUTABLE_NAME}</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/ios/rules.gni b/third_party/libwebrtc/build/config/ios/rules.gni new file mode 100644 index 0000000000..04d605dd97 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/rules.gni @@ -0,0 +1,2173 @@ +# 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. + +import("//build/apple/apple_info_plist.gni") +import("//build/config/apple/symbols.gni") +import("//build/config/ios/ios_sdk.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +declare_args() { + # Set to true if an Xcode project is generated for this build. Set this to + # false if you do not plan to run `gn gen --ide=xcode` in this directory. + # This will speed up the generation at the cost of generating an invalid + # Xcode project if `gn gen --ide=xcode` is used. Defaults to true (favor + # correctness over speed). + ios_set_attributes_for_xcode_project_generation = true +} + +# Constants corresponding to the bundle type identifiers use application, +# application extension, XCTest and XCUITest targets respectively. +_ios_xcode_app_bundle_id = "com.apple.product-type.application" +_ios_xcode_appex_bundle_id = "com.apple.product-type.app-extension" +_ios_xcode_xctest_bundle_id = "com.apple.product-type.bundle.unit-test" +_ios_xcode_xcuitest_bundle_id = "com.apple.product-type.bundle.ui-testing" + +# Invokes lipo on multiple arch-specific binaries to create a fat binary. +# +# Arguments +# +# arch_binary_target +# name of the target generating the arch-specific binaries, they must +# be named $target_out_dir/$toolchain_cpu/$arch_binary_output. +# +# arch_binary_output +# (optional, defaults to the name of $arch_binary_target) base name of +# the arch-specific binary generated by arch_binary_target. +# +# output_name +# (optional, defaults to $target_name) base name of the target output, +# the full path will be $target_out_dir/$output_name. +# +# configs +# (optional) a list of configurations, this is used to check whether +# the binary should be stripped, when "enable_stripping" is true. +# +template("lipo_binary") { + assert(defined(invoker.arch_binary_target), + "arch_binary_target must be defined for $target_name") + + assert(!is_fat_secondary_toolchain, + "lipo_binary can only be used in the primary toolchain of a fat build") + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _all_target_cpu = [ target_cpu ] + additional_target_cpus + _all_toolchains = [ current_toolchain ] + additional_toolchains + + _arch_binary_target = invoker.arch_binary_target + _arch_binary_output = get_label_info(_arch_binary_target, "name") + if (defined(invoker.arch_binary_output)) { + _arch_binary_output = invoker.arch_binary_output + } + + action(_target_name) { + forward_variables_from(invoker, + "*", + [ + "arch_binary_output", + "arch_binary_target", + "configs", + "output_name", + ]) + + script = "//build/toolchain/apple/linker_driver.py" + + # http://crbug.com/762840. Fix for bots running out of memory. + pool = "//build/toolchain:link_pool($default_toolchain)" + + outputs = [ "$target_out_dir/$_output_name" ] + + deps = [] + _index = 0 + inputs = [] + foreach(_cpu, _all_target_cpu) { + _toolchain = _all_toolchains[_index] + _index = _index + 1 + + inputs += + [ get_label_info("$_arch_binary_target($_toolchain)", + "target_out_dir") + "/$_cpu/$_arch_binary_output" ] + + deps += [ "$_arch_binary_target($_toolchain)" ] + } + + args = [ + "xcrun", + "lipo", + "-create", + "-output", + rebase_path("$target_out_dir/$_output_name", root_build_dir), + ] + rebase_path(inputs, root_build_dir) + + if (enable_dsyms) { + _dsyms_output_dir = "$root_out_dir/$_output_name.dSYM" + outputs += [ + "$_dsyms_output_dir/", + "$_dsyms_output_dir/Contents/Info.plist", + "$_dsyms_output_dir/Contents/Resources/DWARF/$_output_name", + ] + args += [ "-Wcrl,dsym," + rebase_path("$root_out_dir/.", root_build_dir) ] + if (!use_xcode_clang) { + args += [ "-Wcrl,dsymutilpath," + + rebase_path("//tools/clang/dsymutil/bin/dsymutil", + root_build_dir) ] + } + } + + if (enable_stripping) { + args += [ "-Wcrl,strip,-x,-S" ] + if (save_unstripped_output) { + outputs += [ "$root_out_dir/$_output_name.unstripped" ] + args += [ "-Wcrl,unstripped," + + rebase_path("$root_out_dir/.", root_build_dir) ] + } + } + } +} + +# Wrapper around create_bundle taking care of code signature settings. +# +# Arguments +# +# product_type +# string, product type for the generated Xcode project. +# +# bundle_gen_dir +# (optional) directory where the bundle is generated; must be below +# root_out_dir and defaults to root_out_dir if omitted. +# +# bundle_deps +# (optional) list of additional dependencies. +# +# bundle_deps_filter +# (optional) list of dependencies to filter (for more information +# see "gn help bundle_deps_filter"). +# +# bundle_extension +# string, extension of the bundle, used to generate bundle name. +# +# bundle_binary_target +# (optional) string, label of the target generating the bundle main +# binary. This target and bundle_binary_path are mutually exclusive. +# +# bundle_binary_output +# (optional) string, base name of the binary generated by the +# bundle_binary_target target, defaults to the target name. +# +# bundle_binary_path +# (optional) string, path to the bundle main binary. This target and +# bundle_binary_target are mutually exclusive. +# +# output_name: +# (optional) string, name of the generated application, if omitted, +# defaults to the target_name. +# +# extra_system_frameworks +# (optional) list of system framework to copy to the bundle. +# +# enable_code_signing +# (optional) boolean, control whether code signing is enabled or not, +# default to ios_enable_code_signing if not defined. +# +# entitlements_path: +# (optional) path to the template to use to generate the application +# entitlements by performing variable substitutions, defaults to +# //build/config/ios/entitlements.plist. +# +# entitlements_target: +# (optional) label of the target generating the application +# entitlements (must generate a single file as output); cannot be +# defined if entitlements_path is set. +# +# has_public_headers: +# (optional) boolean, defaults to false; only meaningful if the bundle +# is a framework bundle; if true, then the frameworks includes public +# headers +# +# disable_entitlements +# (optional, defaults to false) boolean, control whether entitlements willi +# be embedded in the application during signature. If false and no +# entitlements are provided, default empty entitlements will be used. +# +# disable_embedded_mobileprovision +# (optional, default to false) boolean, control whether mobile provisions +# will be embedded in the bundle. If true, the existing +# embedded.mobileprovision will be deleted. +# +# xcode_extra_attributes +# (optional) scope, extra attributes for Xcode projects. +# +# xcode_test_application_name: +# (optional) string, name of the test application for Xcode unit or ui +# test target. +# +# xcode_product_bundle_id: +# (optional) string, the bundle ID that will be added in the XCode +# attributes to enable some features when debugging (e.g. MetricKit). +# +# primary_info_plist: +# (optional) path to Info.plist to merge with the $partial_info_plist +# generated by the compilation of the asset catalog. +# +# partial_info_plist: +# (optional) path to the partial Info.plist generated by the asset +# catalog compiler; if defined $primary_info_plist must also be defined. +# +template("create_signed_bundle") { + assert(defined(invoker.product_type), + "product_type must be defined for $target_name") + assert(defined(invoker.bundle_extension), + "bundle_extension must be defined for $target_name") + assert(defined(invoker.bundle_binary_target) != + defined(invoker.bundle_binary_path), + "Only one of bundle_binary_target or bundle_binary_path may be " + + "specified for $target_name") + assert(!defined(invoker.partial_info_plist) || + defined(invoker.primary_info_plist), + "primary_info_plist must be defined when partial_info_plist is " + + "defined for $target_name") + + if (defined(invoker.xcode_test_application_name)) { + assert( + invoker.product_type == _ios_xcode_xctest_bundle_id || + invoker.product_type == _ios_xcode_xcuitest_bundle_id, + "xcode_test_application_name can be only defined for Xcode unit or ui test target.") + } + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + if (defined(invoker.bundle_binary_path)) { + _bundle_binary_path = invoker.bundle_binary_path + } else { + _bundle_binary_target = invoker.bundle_binary_target + _bundle_binary_output = get_label_info(_bundle_binary_target, "name") + if (defined(invoker.bundle_binary_output)) { + _bundle_binary_output = invoker.bundle_binary_output + } + _bundle_binary_path = + get_label_info(_bundle_binary_target, "target_out_dir") + + "/$_bundle_binary_output" + } + + _bundle_gen_dir = root_out_dir + if (defined(invoker.bundle_gen_dir)) { + _bundle_gen_dir = invoker.bundle_gen_dir + } + + _bundle_extension = invoker.bundle_extension + + _enable_embedded_mobileprovision = true + if (defined(invoker.disable_embedded_mobileprovision)) { + _enable_embedded_mobileprovision = !invoker.disable_embedded_mobileprovision + } + + if (target_environment == "catalyst") { + _enable_embedded_mobileprovision = false + } + + _enable_entitlements = true + if (defined(invoker.disable_entitlements)) { + _enable_entitlements = !invoker.disable_entitlements + } + + if (_enable_entitlements) { + if (!defined(invoker.entitlements_target)) { + _entitlements_path = "//build/config/ios/entitlements.plist" + if (defined(invoker.entitlements_path)) { + _entitlements_path = invoker.entitlements_path + } + } else { + assert(!defined(invoker.entitlements_path), + "Cannot define both entitlements_path and entitlements_target " + + "for $target_name") + + _entitlements_target_outputs = + get_target_outputs(invoker.entitlements_target) + _entitlements_path = _entitlements_target_outputs[0] + } + } + + _enable_code_signing = ios_enable_code_signing + if (defined(invoker.enable_code_signing)) { + _enable_code_signing = invoker.enable_code_signing + } + + if (!ios_set_attributes_for_xcode_project_generation) { + not_needed(invoker, + [ + "xcode_product_bundle_id", + "xcode_extra_attributes", + ]) + } + + create_bundle(_target_name) { + forward_variables_from(invoker, + [ + "bundle_deps_filter", + "data_deps", + "deps", + "partial_info_plist", + "product_type", + "public_configs", + "public_deps", + "testonly", + "visibility", + "xcode_test_application_name", + ]) + + bundle_root_dir = "$_bundle_gen_dir/$_output_name$_bundle_extension" + if (target_environment == "simulator" || target_environment == "device") { + bundle_contents_dir = bundle_root_dir + bundle_resources_dir = bundle_contents_dir + bundle_executable_dir = bundle_contents_dir + } else if (target_environment == "catalyst") { + if (_bundle_extension != ".framework") { + bundle_contents_dir = "$bundle_root_dir/Contents" + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = "$bundle_contents_dir/MacOS" + } else { + bundle_contents_dir = "$bundle_root_dir/Versions/A" + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = bundle_contents_dir + } + } + + if (!defined(public_deps)) { + public_deps = [] + } + + if (ios_set_attributes_for_xcode_project_generation) { + _xcode_product_bundle_id = "" + if (defined(invoker.xcode_product_bundle_id)) { + _xcode_product_bundle_id = invoker.xcode_product_bundle_id + } + + if (_xcode_product_bundle_id != "") { + _ios_provisioning_profile_info = + exec_script("//build/config/ios/codesign.py", + [ + "find-provisioning-profile", + "-b=" + _xcode_product_bundle_id, + ], + "json") + } + + xcode_extra_attributes = { + IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target + if (_xcode_product_bundle_id != "") { + CODE_SIGN_IDENTITY = "iPhone Developer" + DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier + PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id + PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name + } + + # If invoker has defined extra attributes, they override the defaults. + if (defined(invoker.xcode_extra_attributes)) { + forward_variables_from(invoker.xcode_extra_attributes, "*") + } + } + } + + if (defined(invoker.bundle_binary_target)) { + public_deps += [ invoker.bundle_binary_target ] + } + + if (defined(invoker.bundle_deps)) { + if (!defined(deps)) { + deps = [] + } + deps += invoker.bundle_deps + } + if (!defined(deps)) { + deps = [] + } + + code_signing_script = "//build/config/ios/codesign.py" + code_signing_sources = [ _bundle_binary_path ] + if (_enable_entitlements) { + if (defined(invoker.entitlements_target)) { + deps += [ invoker.entitlements_target ] + } + code_signing_sources += [ _entitlements_path ] + } + code_signing_outputs = [ "$bundle_executable_dir/$_output_name" ] + if (_enable_code_signing) { + code_signing_outputs += + [ "$bundle_contents_dir/_CodeSignature/CodeResources" ] + } + if (ios_code_signing_identity != "" && target_environment == "device" && + _enable_embedded_mobileprovision) { + code_signing_outputs += + [ "$bundle_contents_dir/embedded.mobileprovision" ] + } + if (_bundle_extension == ".framework") { + if (target_environment == "catalyst") { + code_signing_outputs += [ + "$bundle_root_dir/Versions/Current", + "$bundle_root_dir/$_output_name", + ] + + if (defined(invoker.has_public_headers) && invoker.has_public_headers) { + code_signing_outputs += [ + "$bundle_root_dir/Headers", + "$bundle_root_dir/Modules", + ] + } + } else { + not_needed(invoker, [ "has_public_headers" ]) + } + } + + if (defined(invoker.extra_system_frameworks)) { + foreach(_framework, invoker.extra_system_frameworks) { + code_signing_outputs += [ "$bundle_contents_dir/Frameworks/" + + get_path_info(_framework, "file") ] + } + } + + code_signing_args = [ + "code-sign-bundle", + "-t=" + ios_sdk_name, + "-i=" + ios_code_signing_identity, + "-b=" + rebase_path(_bundle_binary_path, root_build_dir), + ] + if (_enable_entitlements) { + code_signing_args += + [ "-e=" + rebase_path(_entitlements_path, root_build_dir) ] + } + if (!_enable_embedded_mobileprovision) { + code_signing_args += [ "--disable-embedded-mobileprovision" ] + } + code_signing_args += [ rebase_path(bundle_root_dir, root_build_dir) ] + if (!_enable_code_signing) { + code_signing_args += [ "--disable-code-signature" ] + } + if (defined(invoker.extra_system_frameworks)) { + # All framework in extra_system_frameworks are expected to be system + # framework and the path to be already system absolute so do not use + # rebase_path here unless using Goma RBE and system Xcode (as in that + # case the system framework are found via a symlink in root_build_dir). + foreach(_framework, invoker.extra_system_frameworks) { + if (use_system_xcode && use_goma) { + _framework_path = rebase_path(_framework, root_build_dir) + } else { + _framework_path = _framework + } + code_signing_args += [ "-F=$_framework_path" ] + } + } + if (defined(invoker.partial_info_plist)) { + _partial_info_plists = [ + invoker.primary_info_plist, + invoker.partial_info_plist, + ] + + _plist_compiler_path = "//build/apple/plist_util.py" + + code_signing_sources += _partial_info_plists + code_signing_sources += [ _plist_compiler_path ] + if (target_environment != "catalyst" || + _bundle_extension != ".framework") { + code_signing_outputs += [ "$bundle_contents_dir/Info.plist" ] + } else { + code_signing_outputs += [ "$bundle_resources_dir/Info.plist" ] + } + + code_signing_args += + [ "-P=" + rebase_path(_plist_compiler_path, root_build_dir) ] + foreach(_partial_info_plist, _partial_info_plists) { + code_signing_args += + [ "-p=" + rebase_path(_partial_info_plist, root_build_dir) ] + } + } + } +} + +# Generates Info.plist files for Mac apps and frameworks. +# +# Arguments +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# executable_name: +# string, name of the generated target used for the product +# and executable name as specified in the output Info.plist. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +template("ios_info_plist") { + assert(defined(invoker.info_plist) != defined(invoker.info_plist_target), + "Only one of info_plist or info_plist_target may be specified in " + + target_name) + + if (defined(invoker.info_plist)) { + _info_plist = invoker.info_plist + } else { + _info_plist_target_output = get_target_outputs(invoker.info_plist_target) + _info_plist = _info_plist_target_output[0] + } + + apple_info_plist(target_name) { + format = "binary1" + extra_substitutions = [] + if (defined(invoker.extra_substitutions)) { + extra_substitutions = invoker.extra_substitutions + } + extra_substitutions += [ + "IOS_BUNDLE_ID_PREFIX=$ios_app_bundle_id_prefix", + "IOS_PLATFORM_BUILD=$ios_platform_build", + "IOS_PLATFORM_NAME=$ios_sdk_name", + "IOS_PLATFORM_VERSION=$ios_sdk_version", + "IOS_SDK_BUILD=$ios_sdk_build", + "IOS_SDK_NAME=$ios_sdk_name$ios_sdk_version", + "IOS_SUPPORTED_PLATFORM=$ios_sdk_platform", + "BUILD_MACHINE_OS_BUILD=$machine_os_build", + "IOS_DEPLOYMENT_TARGET=$ios_deployment_target", + "XCODE_BUILD=$xcode_build", + "XCODE_VERSION=$xcode_version", + ] + plist_templates = [ + "//build/config/ios/BuildInfo.plist", + _info_plist, + ] + if (defined(invoker.info_plist_target)) { + deps = [ invoker.info_plist_target ] + } + forward_variables_from(invoker, + [ + "executable_name", + "output_name", + "visibility", + "testonly", + ]) + } +} + +# Template to build an application bundle for iOS. +# +# This should be used instead of "executable" built-in target type on iOS. +# As the template forward the generation of the application executable to +# an "executable" target, all arguments supported by "executable" targets +# are also supported by this template. +# +# Arguments +# +# output_name: +# (optional) string, name of the generated application, if omitted, +# defaults to the target_name. +# +# extra_substitutions: +# (optional) list of string in "key=value" format, each value will +# be used as an additional variable substitution rule when generating +# the application Info.plist +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# entitlements_path: +# (optional) path to the template to use to generate the application +# entitlements by performing variable substitutions, defaults to +# //build/config/ios/entitlements.plist. +# +# entitlements_target: +# (optional) label of the target generating the application +# entitlements (must generate a single file as output); cannot be +# defined if entitlements_path is set. +# +# product_type +# (optional) string, product type for the generated Xcode project, +# default to "com.apple.product-type.application". Should only be +# overriden when building application extension. +# +# enable_code_signing +# (optional) boolean, control whether code signing is enabled or not, +# default to ios_enable_code_signing if not defined. +# +# variants +# (optional) list of scopes, each scope needs to define the attributes +# "name" and "bundle_deps"; if defined and non-empty, then one bundle +# named $target_out_dir/$variant/$output_name will be created for each +# variant with the same binary but the correct bundle_deps, the bundle +# at $target_out_dir/$output_name will be a copy of the first variant. +# +# xcode_product_bundle_id: +# (optional) string, the bundle ID that will be added in the XCode +# attributes to enable some features when debugging (e.g. MetricKit). +# defaults to "$ios_app_bundle_id_prefix.$output_name". +# +# For more information, see "gn help executable". +template("ios_app_bundle") { + _output_name = target_name + _target_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _primary_toolchain = current_toolchain + if (is_fat_secondary_toolchain) { + _primary_toolchain = primary_fat_toolchain_name + } + + assert( + !defined(invoker.bundle_extension), + "bundle_extension must not be set for ios_app_bundle template for $target_name") + + _xcode_product_bundle_id = "$ios_app_bundle_id_prefix.$_output_name" + if (defined(invoker.xcode_product_bundle_id)) { + _xcode_product_bundle_id = invoker.xcode_product_bundle_id + _xcode_product_bundle_id = + "$ios_app_bundle_id_prefix.$_xcode_product_bundle_id" + } else if (defined(invoker.bundle_id)) { + _xcode_product_bundle_id = invoker.bundle_id + } + + # Bundle ID should respect rfc1034 and replace _ with -. + _xcode_product_bundle_id = + string_replace("$_xcode_product_bundle_id", "_", "-") + + _arch_executable_source = _target_name + "_arch_executable_sources" + _arch_executable_target = _target_name + "_arch_executable" + _lipo_executable_target = _target_name + "_executable" + + if (defined(invoker.variants) && invoker.variants != []) { + _variants = [] + + foreach(_variant, invoker.variants) { + assert(defined(_variant.name) && _variant.name != "", + "name must be defined for all $target_name variants") + + assert(defined(_variant.bundle_deps), + "bundle_deps must be defined for all $target_name variants") + + _variants += [ + { + name = _variant.name + bundle_deps = _variant.bundle_deps + target_name = "${_target_name}_variants_${_variant.name}" + bundle_gen_dir = "$root_out_dir/variants/${_variant.name}" + }, + ] + } + } else { + # If no variants are passed to the template, use a fake variant with + # no name to avoid duplicating code. As no variant can have an empty + # name except this fake variant, it is possible to know if a variant + # is fake or not. + _variants = [ + { + name = "" + bundle_deps = [] + target_name = _target_name + bundle_gen_dir = root_out_dir + }, + ] + } + + _default_variant = _variants[0] + + source_set(_arch_executable_source) { + forward_variables_from(invoker, + "*", + [ + "bundle_deps", + "bundle_deps_filter", + "bundle_extension", + "enable_code_signing", + "entitlements_path", + "entitlements_target", + "extra_substitutions", + "extra_system_frameworks", + "info_plist", + "info_plist_target", + "output_name", + "product_type", + "visibility", + "xcode_extra_attributes", + ]) + + visibility = [ ":$_arch_executable_target" ] + } + + if (!is_fat_secondary_toolchain || target_environment == "simulator") { + _generate_entitlements_target = _target_name + "_gen_entitlements" + _generate_entitlements_output = + get_label_info(":$_generate_entitlements_target($_primary_toolchain)", + "target_out_dir") + "/$_output_name.xcent" + } + + _product_type = _ios_xcode_app_bundle_id + if (defined(invoker.product_type)) { + _product_type = invoker.product_type + } + + if (_product_type == _ios_xcode_app_bundle_id) { + _bundle_extension = ".app" + } else if (_product_type == _ios_xcode_appex_bundle_id) { + _bundle_extension = ".appex" + } else { + assert(false, "unknown product_type \"$product_type\" for $_target_name") + } + + _is_app_bundle = _product_type == _ios_xcode_app_bundle_id + + executable(_arch_executable_target) { + forward_variables_from(invoker, + "*", + [ + "bundle_deps", + "bundle_deps_filter", + "bundle_extension", + "enable_code_signing", + "entitlements_path", + "entitlements_target", + "extra_substitutions", + "extra_system_frameworks", + "info_plist", + "info_plist_target", + "output_name", + "product_type", + "sources", + "visibility", + "xcode_extra_attributes", + ]) + + visibility = [ ":$_lipo_executable_target($_primary_toolchain)" ] + if (is_fat_secondary_toolchain) { + visibility += [ ":$_target_name" ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_arch_executable_source" ] + + if (!defined(frameworks)) { + frameworks = [] + } + frameworks += [ "UIKit.framework" ] + + if (target_environment == "simulator") { + deps += [ ":$_generate_entitlements_target($_primary_toolchain)" ] + + if (!defined(inputs)) { + inputs = [] + } + inputs += [ _generate_entitlements_output ] + + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ "-Wl,-sectcreate,__TEXT,__entitlements," + + rebase_path(_generate_entitlements_output, root_build_dir) ] + } + + output_name = _output_name + output_prefix_override = true + output_dir = "$target_out_dir/$target_cpu" + } + + if (is_fat_secondary_toolchain) { + # For fat builds, only the default toolchain will generate an application + # bundle. For the other toolchains, the template is only used for building + # the arch-specific binary, thus the default target is just a group(). + + group(_target_name) { + forward_variables_from(invoker, + [ + "visibility", + "testonly", + ]) + public_deps = [ ":$_arch_executable_target" ] + } + } else { + lipo_binary(_lipo_executable_target) { + forward_variables_from(invoker, + [ + "configs", + "testonly", + ]) + + visibility = [] + foreach(_variant, _variants) { + visibility += [ ":${_variant.target_name}" ] + } + + output_name = _output_name + arch_binary_target = ":$_arch_executable_target" + arch_binary_output = _output_name + } + + _generate_info_plist = target_name + "_generate_info_plist" + ios_info_plist(_generate_info_plist) { + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + ]) + + executable_name = _output_name + } + + if (!is_fat_secondary_toolchain) { + if (!defined(invoker.entitlements_target)) { + _entitlements_path = "//build/config/ios/entitlements.plist" + if (defined(invoker.entitlements_path)) { + _entitlements_path = invoker.entitlements_path + } + } else { + assert(!defined(invoker.entitlements_path), + "Cannot define both entitlements_path and entitlements_target" + + "for $_target_name") + + _entitlements_target_outputs = + get_target_outputs(invoker.entitlements_target) + _entitlements_path = _entitlements_target_outputs[0] + } + + action(_generate_entitlements_target) { + _gen_info_plist_outputs = get_target_outputs(":$_generate_info_plist") + _info_plist_path = _gen_info_plist_outputs[0] + + script = "//build/config/ios/codesign.py" + deps = [ ":$_generate_info_plist" ] + if (defined(invoker.entitlements_target)) { + deps += [ invoker.entitlements_target ] + } + sources = [ + _entitlements_path, + _info_plist_path, + ] + outputs = [ _generate_entitlements_output ] + + args = [ + "generate-entitlements", + "-e=" + rebase_path(_entitlements_path, root_build_dir), + "-p=" + rebase_path(_info_plist_path, root_build_dir), + ] + rebase_path(outputs, root_build_dir) + } + } + + # Only write PkgInfo for real application, not application extension. + if (_is_app_bundle) { + _create_pkg_info = target_name + "_pkg_info" + action(_create_pkg_info) { + forward_variables_from(invoker, [ "testonly" ]) + script = "//build/apple/write_pkg_info.py" + inputs = [ "//build/apple/plist_util.py" ] + sources = get_target_outputs(":$_generate_info_plist") + outputs = [ + # Cannot name the output PkgInfo as the name will not be unique if + # multiple ios_app_bundle are defined in the same BUILD.gn file. The + # file is renamed in the bundle_data outputs to the correct name. + "$target_gen_dir/$target_name", + ] + args = [ "--plist" ] + rebase_path(sources, root_build_dir) + + [ "--output" ] + rebase_path(outputs, root_build_dir) + deps = [ ":$_generate_info_plist" ] + } + + _bundle_data_pkg_info = target_name + "_bundle_data_pkg_info" + bundle_data(_bundle_data_pkg_info) { + forward_variables_from(invoker, [ "testonly" ]) + sources = get_target_outputs(":$_create_pkg_info") + outputs = [ "{{bundle_resources_dir}}/PkgInfo" ] + public_deps = [ ":$_create_pkg_info" ] + } + } + + foreach(_variant, _variants) { + create_signed_bundle(_variant.target_name) { + forward_variables_from(invoker, + [ + "bundle_deps", + "bundle_deps_filter", + "data_deps", + "deps", + "enable_code_signing", + "entitlements_path", + "entitlements_target", + "extra_system_frameworks", + "public_configs", + "public_deps", + "testonly", + "visibility", + "xcode_extra_attributes", + ]) + + output_name = _output_name + bundle_gen_dir = _variant.bundle_gen_dir + bundle_binary_target = ":$_lipo_executable_target" + bundle_binary_output = _output_name + bundle_extension = _bundle_extension + product_type = _product_type + xcode_product_bundle_id = _xcode_product_bundle_id + + _generate_info_plist_outputs = + get_target_outputs(":$_generate_info_plist") + primary_info_plist = _generate_info_plist_outputs[0] + partial_info_plist = + "$target_gen_dir/${_variant.target_name}_partial_info.plist" + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_generate_info_plist" ] + + if (!defined(bundle_deps)) { + bundle_deps = [] + } + if (_is_app_bundle) { + bundle_deps += [ ":$_bundle_data_pkg_info" ] + } + bundle_deps += _variant.bundle_deps + + if (target_environment == "simulator") { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//testing/iossim" ] + } + } + } + + if (_default_variant.name != "") { + _bundle_short_name = "$_output_name$_bundle_extension" + action(_target_name) { + forward_variables_from(invoker, [ "testonly" ]) + + script = "//build/config/ios/hardlink.py" + public_deps = [] + foreach(_variant, _variants) { + public_deps += [ ":${_variant.target_name}" ] + } + + sources = [ "${_default_variant.bundle_gen_dir}/$_bundle_short_name" ] + outputs = [ "$root_out_dir/$_bundle_short_name" ] + + args = rebase_path(sources, root_build_dir) + + rebase_path(outputs, root_build_dir) + } + } + } + + if (is_fat_secondary_toolchain) { + not_needed("*") + } +} + +set_defaults("ios_app_bundle") { + configs = default_executable_configs +} + +# Template to build an application extension bundle for iOS. +# +# This should be used instead of "executable" built-in target type on iOS. +# As the template forward the generation of the application executable to +# an "executable" target, all arguments supported by "executable" targets +# are also supported by this template. +# +# Arguments +# +# output_name: +# (optional) string, name of the generated application, if omitted, +# defaults to the target_name. +# +# extra_substitutions: +# (optional) list of string in "key=value" format, each value will +# be used as an additional variable substitution rule when generating +# the application Info.plist +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# For more information, see "gn help executable". +template("ios_appex_bundle") { + ios_app_bundle(target_name) { + forward_variables_from(invoker, + "*", + [ + "bundle_extension", + "product_type", + ]) + product_type = _ios_xcode_appex_bundle_id + } +} + +set_defaults("ios_appex_bundle") { + configs = [ "//build/config/ios:ios_extension_executable_flags" ] +} + +# Template to compile .xib and .storyboard files. +# +# Arguments +# +# sources: +# list of string, sources to compile +# +# ibtool_flags: +# (optional) list of string, additional flags to pass to the ibtool +template("compile_ib_files") { + action_foreach(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + assert(defined(invoker.sources), + "sources must be specified for $target_name") + assert(defined(invoker.output_extension), + "output_extension must be specified for $target_name") + + ibtool_flags = [] + if (defined(invoker.ibtool_flags)) { + ibtool_flags = invoker.ibtool_flags + } + + _output_extension = invoker.output_extension + + script = "//build/config/ios/compile_ib_files.py" + sources = invoker.sources + outputs = [ + "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension", + ] + args = [ + "--input", + "{{source}}", + "--output", + rebase_path( + "$target_gen_dir/$target_name/{{source_name_part}}.$_output_extension", + root_build_dir), + ] + args += ibtool_flags + } +} + +# Compile a xib or storyboard file and add it to a bundle_data so that it is +# available at runtime in the bundle. +# +# Arguments +# +# source: +# string, path of the xib or storyboard to compile. +# +# Forwards all variables to the bundle_data target. +template("bundle_data_ib_file") { + assert(defined(invoker.source), "source needs to be defined for $target_name") + + _source_extension = get_path_info(invoker.source, "extension") + assert(_source_extension == "xib" || _source_extension == "storyboard", + "source must be a .xib or .storyboard for $target_name") + + _target_name = target_name + if (_source_extension == "xib") { + _compile_ib_file = target_name + "_compile_xib" + _output_extension = "nib" + } else { + _compile_ib_file = target_name + "_compile_storyboard" + _output_extension = "storyboardc" + } + + compile_ib_files(_compile_ib_file) { + sources = [ invoker.source ] + output_extension = _output_extension + visibility = [ ":$_target_name" ] + ibtool_flags = [ + "--minimum-deployment-target", + ios_deployment_target, + "--auto-activate-custom-fonts", + "--target-device", + "iphone", + "--target-device", + "ipad", + ] + } + + bundle_data(_target_name) { + forward_variables_from(invoker, "*", [ "source" ]) + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_compile_ib_file" ] + + sources = get_target_outputs(":$_compile_ib_file") + + outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ] + } +} + +# Compile a strings file and add it to a bundle_data so that it is available +# at runtime in the bundle. +# +# Arguments +# +# source: +# string, path of the strings file to compile. +# +# output: +# string, path of the compiled file in the final bundle. +# +# Forwards all variables to the bundle_data target. +template("bundle_data_strings") { + assert(defined(invoker.source), "source needs to be defined for $target_name") + assert(defined(invoker.output), "output needs to be defined for $target_name") + + _source_extension = get_path_info(invoker.source, "extension") + assert(_source_extension == "strings", + "source must be a .strings for $target_name") + + _target_name = target_name + _convert_target = target_name + "_compile_strings" + + convert_plist(_convert_target) { + visibility = [ ":$_target_name" ] + source = invoker.source + output = + "$target_gen_dir/$_target_name/" + get_path_info(invoker.source, "file") + format = "binary1" + } + + bundle_data(_target_name) { + forward_variables_from(invoker, + "*", + [ + "source", + "output", + ]) + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_convert_target" ] + + sources = get_target_outputs(":$_convert_target") + + outputs = [ invoker.output ] + } +} + +# Template to package a shared library into an iOS framework bundle. +# +# By default, the bundle target this template generates does not link the +# resulting framework into anything that depends on it. If a dependency wants +# a link-time (as well as build-time) dependency on the framework bundle, +# depend against "$target_name+link". If only the build-time dependency is +# required (e.g., for copying into another bundle), then use "$target_name". +# +# Arguments +# +# output_name: +# (optional) string, name of the generated framework without the +# .framework suffix. If omitted, defaults to target_name. +# +# public_headers: +# (optional) list of paths to header file that needs to be copied +# into the framework bundle Headers subdirectory. If omitted or +# empty then the Headers subdirectory is not created. +# +# sources +# (optional) list of files. Needs to be defined and non-empty if +# public_headers is defined and non-empty. +# +# enable_code_signing +# (optional) boolean, control whether code signing is enabled or not, +# default to ios_enable_code_signing if not defined. +# +# This template provides two targets for the resulting framework bundle. The +# link-time behavior varies depending on which of the two targets below is +# added as a dependency: +# - $target_name only adds a build-time dependency. Targets that depend on +# it will not link against the framework. +# - $target_name+link adds a build-time and link-time dependency. Targets +# that depend on it will link against the framework. +# +# The build-time-only dependency is used for when a target needs to use the +# framework either only for resources, or because the target loads it at run- +# time, via dlopen() or NSBundle. The link-time dependency will cause the +# dependee to have the framework loaded by dyld at launch. +# +# Example of build-time only dependency: +# +# framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# The GoatTeleporter.app will not directly link against +# CoreTeleportation.framework, but it will be included in the bundle's +# Frameworks directory. +# +# Example of link-time dependency: +# +# framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# ldflags = [ +# "-install_name", +# "@executable_path/../Frameworks/$target_name.framework" +# ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation+link" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# Note that the framework is still copied to the app's bundle, but dyld will +# load this library when the app is launched because it uses the "+link" +# target as a dependency. This also requires that the framework set its +# install_name so that dyld can locate it. +# +# See "gn help shared_library" for more information on arguments supported +# by shared library target. +template("ios_framework_bundle") { + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _has_public_headers = + defined(invoker.public_headers) && invoker.public_headers != [] + + _primary_toolchain = current_toolchain + if (is_fat_secondary_toolchain) { + _primary_toolchain = primary_fat_toolchain_name + } + + # Public configs are not propagated across toolchain (see crbug.com/675224) + # so some configs have to be defined for both default_toolchain and all others + # toolchains when performing a fat build. Use "get_label_info" to construct + # the path since they need to be relative to the default_toolchain. + + _default_toolchain_root_out_dir = + get_label_info("$_target_name($_primary_toolchain)", "root_out_dir") + + _arch_shared_library_source = _target_name + "_arch_shared_library_sources" + _arch_shared_library_target = _target_name + "_arch_shared_library" + _lipo_shared_library_target = _target_name + "_shared_library" + _link_target_name = _target_name + "+link" + + if (_has_public_headers) { + _default_toolchain_target_gen_dir = + get_label_info("$_target_name($_primary_toolchain)", "target_gen_dir") + + _framework_headers_target = _target_name + "_framework_headers" + + _headers_map_config = _target_name + "_headers_map" + _header_map_filename = + "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap" + config(_headers_map_config) { + visibility = [ + ":${_arch_shared_library_source}", + ":${_target_name}_signed_bundle", + ] + include_dirs = [ _header_map_filename ] + } + } + + _framework_headers_config = _target_name + "_framework_headers_config" + config(_framework_headers_config) { + framework_dirs = [ _default_toolchain_root_out_dir ] + } + + _framework_public_config = _target_name + "_public_config" + config(_framework_public_config) { + configs = [ ":$_framework_headers_config" ] + frameworks = [ "$_output_name.framework" ] + } + + source_set(_arch_shared_library_source) { + forward_variables_from(invoker, + "*", + [ + "bundle_deps", + "bundle_deps_filter", + "data_deps", + "enable_code_signing", + "extra_substitutions", + "info_plist", + "info_plist_target", + "output_name", + "public_configs", + "visibility", + ]) + + visibility = [ ":$_arch_shared_library_target" ] + + if (_has_public_headers) { + configs += [ ":$_headers_map_config" ] + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_framework_headers_target($_primary_toolchain)" ] + } + } + + shared_library(_arch_shared_library_target) { + forward_variables_from(invoker, + "*", + [ + "bundle_deps", + "bundle_deps_filter", + "data_deps", + "enable_code_signing", + "extra_substitutions", + "info_plist", + "info_plist_target", + "output_name", + "sources", + "public_configs", + "visibility", + ]) + + visibility = [ ":$_lipo_shared_library_target($_primary_toolchain)" ] + if (is_fat_secondary_toolchain) { + visibility += [ + ":${_target_name}", + ":${_target_name}_signed_bundle", + ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_arch_shared_library_source" ] + if (_has_public_headers) { + deps += [ ":$_framework_headers_target($_primary_toolchain)" ] + } + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += + [ "-Wl,-install_name,@rpath/$_output_name.framework/$_output_name" ] + + output_extension = "" + output_name = _output_name + output_prefix_override = true + output_dir = "$target_out_dir/$target_cpu" + } + + if (is_fat_secondary_toolchain) { + # For fat builds, only the default toolchain will generate a framework + # bundle. For the other toolchains, the template is only used for building + # the arch-specific binary, thus the default target is just a group(). + + group(_target_name) { + forward_variables_from(invoker, + [ + "visibility", + "testonly", + ]) + public_deps = [ ":$_arch_shared_library_target" ] + } + + group(_link_target_name) { + forward_variables_from(invoker, + [ + "public_configs", + "visibility", + "testonly", + ]) + public_deps = [ ":$_link_target_name($_primary_toolchain)" ] + + if (_has_public_headers) { + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":$_framework_headers_config" ] + } + if (!defined(all_dependent_configs)) { + all_dependent_configs = [] + } + all_dependent_configs += [ ":$_framework_public_config" ] + } + + group("$_target_name+bundle") { + forward_variables_from(invoker, [ "testonly" ]) + public_deps = [ ":$_target_name+bundle($_primary_toolchain)" ] + } + + not_needed(invoker, "*") + } else { + if (_has_public_headers) { + _public_headers = invoker.public_headers + + _framework_root_dir = "$root_out_dir/$_output_name.framework" + if (target_environment == "simulator" || target_environment == "device") { + _framework_contents_dir = _framework_root_dir + } else if (target_environment == "catalyst") { + _framework_contents_dir = "$_framework_root_dir/Versions/A" + } + + _compile_headers_map_target = _target_name + "_compile_headers_map" + action(_compile_headers_map_target) { + visibility = [ ":$_framework_headers_target" ] + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + ]) + script = "//build/config/ios/write_framework_hmap.py" + outputs = [ _header_map_filename ] + + # The header map generation only wants the list of headers, not all of + # sources, so filter any non-header source files from "sources". It is + # less error prone that having the developer duplicate the list of all + # headers in addition to "sources". + sources = [] + foreach(_source, invoker.sources) { + if (get_path_info(_source, "extension") == "h") { + sources += [ _source ] + } + } + + args = [ + rebase_path(_header_map_filename), + rebase_path(_framework_root_dir, root_build_dir), + ] + rebase_path(sources, root_build_dir) + } + + _create_module_map_target = _target_name + "_module_map" + action(_create_module_map_target) { + visibility = [ ":$_framework_headers_target" ] + script = "//build/config/ios/write_framework_modulemap.py" + outputs = [ "$_framework_contents_dir/Modules/module.modulemap" ] + args = [ + _output_name, + rebase_path("$_framework_contents_dir/Modules", root_build_dir), + ] + } + + _copy_public_headers_target = _target_name + "_copy_public_headers" + copy(_copy_public_headers_target) { + forward_variables_from(invoker, + [ + "testonly", + "deps", + ]) + visibility = [ ":$_framework_headers_target" ] + sources = _public_headers + outputs = [ "$_framework_contents_dir/Headers/{{source_file_part}}" ] + + # Do not use forward_variables_from for "public_deps" as + # we do not want to forward those dependencies. + if (defined(invoker.public_deps)) { + if (!defined(deps)) { + deps = [] + } + deps += invoker.public_deps + } + } + + group(_framework_headers_target) { + forward_variables_from(invoker, [ "testonly" ]) + deps = [ + ":$_compile_headers_map_target", + ":$_create_module_map_target", + ] + public_deps = [ ":$_copy_public_headers_target" ] + } + } + + lipo_binary(_lipo_shared_library_target) { + forward_variables_from(invoker, + [ + "configs", + "testonly", + ]) + + visibility = [ ":${_target_name}_signed_bundle" ] + output_name = _output_name + arch_binary_target = ":$_arch_shared_library_target" + arch_binary_output = _output_name + } + + _info_plist_target = _target_name + "_info_plist" + _info_plist_bundle = _target_name + "_info_plist_bundle" + ios_info_plist(_info_plist_target) { + visibility = [ ":$_info_plist_bundle" ] + executable_name = _output_name + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + ]) + } + + bundle_data(_info_plist_bundle) { + visibility = [ ":${_target_name}_signed_bundle" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = get_target_outputs(":$_info_plist_target") + public_deps = [ ":$_info_plist_target" ] + + if (target_environment != "catalyst") { + outputs = [ "{{bundle_contents_dir}}/Info.plist" ] + } else { + outputs = [ "{{bundle_resources_dir}}/Info.plist" ] + } + } + + create_signed_bundle(_target_name + "_signed_bundle") { + forward_variables_from(invoker, + [ + "bundle_deps", + "bundle_deps_filter", + "data_deps", + "deps", + "enable_code_signing", + "public_configs", + "public_deps", + "testonly", + "visibility", + ]) + + product_type = "com.apple.product-type.framework" + bundle_extension = ".framework" + + output_name = _output_name + bundle_binary_target = ":$_lipo_shared_library_target" + bundle_binary_output = _output_name + + has_public_headers = _has_public_headers + + # Framework do not have entitlements nor mobileprovision because they use + # the one from the bundle using them (.app or .appex) as they are just + # dynamic library with shared code. + disable_entitlements = true + disable_embedded_mobileprovision = true + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_info_plist_bundle" ] + } + + group(_target_name) { + forward_variables_from(invoker, + [ + "public_configs", + "public_deps", + "testonly", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":${_target_name}_signed_bundle" ] + + if (_has_public_headers) { + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":$_framework_headers_config" ] + } + } + + group(_link_target_name) { + forward_variables_from(invoker, + [ + "public_configs", + "public_deps", + "testonly", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_target_name" ] + + if (!defined(all_dependent_configs)) { + all_dependent_configs = [] + } + all_dependent_configs += [ ":$_framework_public_config" ] + } + + bundle_data(_target_name + "+bundle") { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + public_deps = [ ":$_target_name" ] + sources = [ "$root_out_dir/$_output_name.framework" ] + outputs = [ "{{bundle_contents_dir}}/Frameworks/$_output_name.framework" ] + } + } +} + +set_defaults("ios_framework_bundle") { + configs = default_shared_library_configs +} + +# Template to build a xctest bundle that contains a loadable module for iOS. +# +# Arguments +# +# deps: +# list of labels to depends on, these values are used to create the +# loadable module. +# +# product_type +# string, product type for the generated Xcode project, use +# "com.apple.product-type.bundle.unit-test" for unit test and +# "com.apple.product-type.bundle.ui-testing" for UI testing. +# +# host_target: +# string, name of the target that depends on the generated bundle, this +# value is used to restrict visibilities. +# +# xcode_test_application_name: +# string, name of the test application for Xcode unit or ui test target. +# +# output_name +# (optional) string, name of the generated application, if omitted, +# defaults to the target_name. +# +# This template defines two targets, one named "${target_name}" is the xctest +# bundle, and the other named "${target_name}_bundle" is a bundle_data that +# wraps the xctest bundle and that only the "${host_target}" can depend on. +# +template("ios_xctest_bundle") { + assert(defined(invoker.deps), "deps must be defined for $target_name") + assert(defined(invoker.product_type), + "product_type must be defined for $target_name") + assert(invoker.product_type == _ios_xcode_xctest_bundle_id || + invoker.product_type == _ios_xcode_xcuitest_bundle_id, + "product_type defined for $target_name is invalid.") + assert(defined(invoker.host_target), + "host_target must be defined for $target_name") + assert(defined(invoker.xcode_test_application_name), + "xcode_test_application_name must be defined for $target_name") + + # Silence "assignment had no effect" error for non-default toolchains as + # following variables are only used in the expansion of the template for the + # default toolchain. + if (is_fat_secondary_toolchain) { + not_needed(invoker, "*") + } + + _target_name = target_name + _output_name = target_name + + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _arch_loadable_module_source = _target_name + "_arch_loadable_module_source" + _arch_loadable_module_target = _target_name + "_arch_loadable_module" + _lipo_loadable_module_target = _target_name + "_loadable_module" + + _primary_toolchain = current_toolchain + if (is_fat_secondary_toolchain) { + _primary_toolchain = primary_fat_toolchain_name + } + + source_set(_arch_loadable_module_source) { + forward_variables_from(invoker, [ "deps" ]) + + testonly = true + visibility = [ ":$_arch_loadable_module_target" ] + } + + loadable_module(_arch_loadable_module_target) { + testonly = true + visibility = [ ":$_lipo_loadable_module_target($_primary_toolchain)" ] + if (is_fat_secondary_toolchain) { + visibility += [ ":$_target_name" ] + } + + deps = [ ":$_arch_loadable_module_source" ] + configs += [ "//build/config/ios:xctest_config" ] + + output_dir = "$target_out_dir/$target_cpu" + output_name = _output_name + output_prefix_override = true + output_extension = "" + } + + if (is_fat_secondary_toolchain) { + # For fat builds, only the default toolchain will generate a test bundle. + # For the other toolchains, the template is only used for building the + # arch-specific binary, thus the default target is just a group(). + group(_target_name) { + forward_variables_from(invoker, [ "visibility" ]) + testonly = true + + public_deps = [ ":$_arch_loadable_module_target" ] + } + + not_needed(invoker, "*") + } else { + _info_plist_target = _target_name + "_info_plist" + _info_plist_bundle = _target_name + "_info_plist_bundle" + + ios_info_plist(_info_plist_target) { + testonly = true + visibility = [ ":$_info_plist_bundle" ] + + info_plist = "//build/config/ios/Module-Info.plist" + executable_name = _output_name + + if (defined(invoker.xctest_bundle_principal_class)) { + _principal_class = invoker.xctest_bundle_principal_class + } else { + # Fall back to a reasonable default value. + _principal_class = "NSObject" + } + extra_substitutions = [ + "XCTEST_BUNDLE_PRINCIPAL_CLASS=${_principal_class}", + "MODULE_BUNDLE_ID=gtest.$_output_name", + ] + } + + bundle_data(_info_plist_bundle) { + testonly = true + visibility = [ ":$_target_name" ] + + public_deps = [ ":$_info_plist_target" ] + + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_contents_dir}}/Info.plist" ] + } + + lipo_binary(_lipo_loadable_module_target) { + forward_variables_from(invoker, [ "configs" ]) + + testonly = true + visibility = [ ":$_target_name" ] + + output_name = _output_name + arch_binary_target = ":$_arch_loadable_module_target" + arch_binary_output = _output_name + } + + _xctest_bundle = _target_name + "_bundle" + create_signed_bundle(_target_name) { + forward_variables_from(invoker, + [ + "bundle_id", + "data_deps", + "enable_code_signing", + "product_type", + "xcode_test_application_name", + ]) + + testonly = true + visibility = [ ":$_xctest_bundle" ] + + bundle_extension = ".xctest" + + output_name = _output_name + bundle_binary_target = ":$_lipo_loadable_module_target" + bundle_binary_output = _output_name + + if (ios_set_attributes_for_xcode_project_generation) { + _xcode_product_bundle_id = + "$ios_app_bundle_id_prefix.gtest.$_output_name" + + _ios_provisioning_profile_info = + exec_script("//build/config/ios/codesign.py", + [ + "find-provisioning-profile", + "-b=" + _xcode_product_bundle_id, + ], + "json") + + xcode_extra_attributes = { + IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target + CODE_SIGN_IDENTITY = "iPhone Developer" + DEVELOPMENT_TEAM = _ios_provisioning_profile_info.team_identifier + PRODUCT_BUNDLE_IDENTIFIER = _xcode_product_bundle_id + PROVISIONING_PROFILE_SPECIFIER = _ios_provisioning_profile_info.name + + # For XCUITest, Xcode requires specifying the host application name + # via the TEST_TARGET_NAME attribute. + if (invoker.product_type == _ios_xcode_xcuitest_bundle_id) { + TEST_TARGET_NAME = invoker.xcode_test_application_name + } + + # For XCTest, Xcode requires specifying the host application path via + # both BUNDLE_LOADER and TEST_HOST attributes. + if (invoker.product_type == _ios_xcode_xctest_bundle_id) { + _xcode_app_name = invoker.xcode_test_application_name + if (defined(invoker.xcode_test_application_output_name)) { + _xcode_app_name = invoker.xcode_test_application_output_name + } + + BUNDLE_LOADER = "\$(TEST_HOST)" + TEST_HOST = "\$(BUILT_PRODUCTS_DIR)/" + + "${_xcode_app_name}.app/${_xcode_app_name}" + } + } + } else { + not_needed(invoker, + [ + "xcode_test_application_name", + "xcode_test_application_output_name", + ]) + } + + deps = [ ":$_info_plist_bundle" ] + } + + bundle_data(_xctest_bundle) { + forward_variables_from(invoker, [ "host_target" ]) + + testonly = true + visibility = [ ":$host_target" ] + + public_deps = [ ":$_target_name" ] + sources = [ "$root_out_dir/$_output_name.xctest" ] + outputs = [ "{{bundle_contents_dir}}/PlugIns/$_output_name.xctest" ] + } + } +} + +set_defaults("ios_xctest_bundle") { + configs = default_shared_library_configs +} + +# For Chrome on iOS we want to run XCTests for all our build configurations +# (Debug, Release, ...). In addition, the symbols visibility is configured to +# private by default. To simplify testing with those constraints, our tests are +# compiled in the TEST_HOST target instead of the .xctest bundle. +template("ios_xctest_test") { + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _xctest_target = _target_name + "_module" + _xctest_output = _output_name + "_module" + + _host_target = _target_name + _host_output = _output_name + + # Allow invokers to specify their own target for the xctest module, but + # fall back to a default (empty) module otherwise. + if (defined(invoker.xctest_module_target)) { + _xctest_module_target = invoker.xctest_module_target + } else { + _xctest_module_target_name = _xctest_target + "shell_source" + _xctest_module_target = ":$_xctest_module_target_name" + source_set(_xctest_module_target_name) { + sources = [ "//build/config/ios/xctest_shell.mm" ] + + configs += [ "//build/config/ios:xctest_config" ] + } + } + + ios_xctest_bundle(_xctest_target) { + forward_variables_from(invoker, [ "data_deps" ]) + output_name = _xctest_output + product_type = _ios_xcode_xctest_bundle_id + host_target = _host_target + + # TODO(crbug.com/1056328) The change in output name results in a mismatch + # between this value and the ios_app_bundle target name. To mitigate, this + # has been modified to _host_target. output_name is set to _host_output + # to mitigate the naming. + xcode_test_application_name = _host_target + xcode_test_application_output_name = _host_output + + deps = [ _xctest_module_target ] + } + + ios_app_bundle(_host_target) { + forward_variables_from(invoker, "*", [ "testonly" ]) + + testonly = true + output_name = _host_output + configs += [ "//build/config/ios:xctest_config" ] + + if (!defined(invoker.info_plist) && !defined(invoker.info_plist_target)) { + info_plist = "//build/config/ios/Host-Info.plist" + } + + # Xcode needs the following frameworks installed in the application (and + # signed) for the XCTest to run, so install them using + # extra_system_frameworks. + extra_system_frameworks = [ + "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework", + "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib", + ] + + # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over + # everything that Xcode copies. + if (xcode_version_int >= 1300) { + extra_system_frameworks += [ + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework", + "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib", + ] + } + + _xctest_bundle = _xctest_target + "_bundle" + if (!is_fat_secondary_toolchain) { + if (!defined(bundle_deps)) { + bundle_deps = [] + } + bundle_deps += [ ":$_xctest_bundle" ] + } + } +} + +set_defaults("ios_xctest_test") { + configs = default_executable_configs +} + +# Template to build a xcuitest test runner bundle. +# +# Xcode requires a test runner application with a copy of the XCTest dynamic +# library bundle in it for the XCUITest to run. The test runner bundle is created +# by copying the system bundle XCTRunner.app from Xcode SDK with the plist file +# being properly tweaked, and a xctest and it needs to be code signed in order +# to run on devices. +# +# Arguments +# +# xctest_bundle +# string, name of the dependent xctest bundle target. +# +# output_name +# (optional) string, name of the generated application, if omitted, +# defaults to the target_name. +# +template("ios_xcuitest_test_runner_bundle") { + assert(defined(invoker.xctest_bundle), + "xctest_bundle must be defined for $target_name") + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _xctrunner_path = + "$ios_sdk_platform_path/Developer/Library/Xcode/Agents/XCTRunner.app" + + _info_plist_merge_plist = _target_name + "_info_plist_merge_plist" + _info_plist_target = _target_name + "_info_plist" + _info_plist_bundle = _target_name + "_info_plist_bundle" + + action(_info_plist_merge_plist) { + testonly = true + script = "//build/apple/plist_util.py" + + sources = [ + "$_xctrunner_path/Info.plist", + + # NOTE: The XCTRunnerAddition+Info.plist must come after the Info.plist + # because it overrides the values under "CFBundleIdentifier" and + # "CFBundleName". + "//build/config/ios/resources/XCTRunnerAddition+Info.plist", + ] + + _output_name = "$target_gen_dir/${_target_name}_merged.plist" + outputs = [ _output_name ] + args = [ + "merge", + "-f=xml1", + "-x=$xcode_version", + "-o=" + rebase_path(_output_name, root_build_dir), + ] + rebase_path(sources, root_build_dir) + + if (use_system_xcode && use_goma) { + deps = [ "//build/config/ios:copy_xctrunner_app" ] + } + } + + ios_info_plist(_info_plist_target) { + testonly = true + visibility = [ ":$_info_plist_bundle" ] + + executable_name = _output_name + info_plist_target = ":$_info_plist_merge_plist" + } + + bundle_data(_info_plist_bundle) { + testonly = true + visibility = [ ":$_target_name" ] + + public_deps = [ ":$_info_plist_target" ] + + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_contents_dir}}/Info.plist" ] + } + + _pkginfo_bundle = _target_name + "_pkginfo_bundle" + bundle_data(_pkginfo_bundle) { + testonly = true + visibility = [ ":$_target_name" ] + + sources = [ "$_xctrunner_path/PkgInfo" ] + + outputs = [ "{{bundle_contents_dir}}/PkgInfo" ] + + if (use_system_xcode && use_goma) { + public_deps = [ "//build/config/ios:copy_xctrunner_app" ] + } + } + + _xctest_bundle = invoker.xctest_bundle + create_signed_bundle(_target_name) { + testonly = true + + bundle_binary_target = "//build/config/ios:xctest_runner_without_arm64e" + bundle_binary_output = "XCTRunner" + bundle_extension = ".app" + product_type = _ios_xcode_app_bundle_id + + output_name = _output_name + + # Xcode needs the following frameworks installed in the application + # (and signed) for the XCUITest to run, so install them using + # extra_system_frameworks. + extra_system_frameworks = [ + "$ios_sdk_platform_path/Developer/Library/Frameworks/XCTest.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTAutomationSupport.framework", + ] + + # Xcode 13 now depends on XCTestCore. To keep things future proof, copy over + # everything that Xcode copies. + if (xcode_version_int >= 1300) { + extra_system_frameworks += [ + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCTestCore.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUIAutomation.framework", + "$ios_sdk_platform_path/Developer/Library/PrivateFrameworks/XCUnit.framework", + "$ios_sdk_platform_path/Developer/usr/lib/libXCTestSwiftSupport.dylib", + ] + } + + bundle_deps = [] + if (defined(invoker.bundle_deps)) { + bundle_deps += invoker.bundle_deps + } + bundle_deps += [ + ":$_info_plist_bundle", + ":$_pkginfo_bundle", + ":$_xctest_bundle", + ] + } +} + +# Template to build a XCUITest that consists of two parts: the test runner +# application bundle and the xctest dynamic library. +# +# Arguments +# +# deps: +# list of labels to depends on, these values are used to create the +# xctest dynamic library. +# +# xcode_test_application_name: +# string, name of the test application for the ui test target. +# +# This template defines two targets, one named "${target_name}_module" is the +# xctest dynamic library, and the other named "${target_name}_runner" is the +# test runner application bundle. +# +template("ios_xcuitest_test") { + assert(defined(invoker.deps), "deps must be defined for $target_name") + assert(defined(invoker.xcode_test_application_name), + "xcode_test_application_name must be defined for $target_name") + + _xcuitest_target = target_name + if (defined(invoker.output_name)) { + _xcuitest_target = invoker.output_name + } + + _xcuitest_runner_target = _xcuitest_target + "_runner" + _xcuitest_module_target = _xcuitest_target + "_module" + + group(target_name) { + testonly = true + + deps = [ ":$_xcuitest_runner_target" ] + } + + _xcuitest_module_output = _xcuitest_target + ios_xctest_bundle(_xcuitest_module_target) { + forward_variables_from(invoker, + [ + "xcode_test_application_name", + "xctest_bundle_principal_class", + "data_deps", + ]) + + product_type = _ios_xcode_xcuitest_bundle_id + host_target = _xcuitest_runner_target + output_name = _xcuitest_module_output + + deps = invoker.deps + } + + _xcuitest_runner_output = _xcuitest_target + "-Runner" + ios_xcuitest_test_runner_bundle(_xcuitest_runner_target) { + output_name = _xcuitest_runner_output + xctest_bundle = _xcuitest_module_target + "_bundle" + forward_variables_from(invoker, [ "bundle_deps" ]) + } +} + +set_defaults("ios_xcuitest_test") { + configs = default_executable_configs +} diff --git a/third_party/libwebrtc/build/config/ios/strip_arm64e.py b/third_party/libwebrtc/build/config/ios/strip_arm64e.py new file mode 100644 index 0000000000..f21baf423d --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/strip_arm64e.py @@ -0,0 +1,70 @@ +# Copyright 2020 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. +"""Strip arm64e architecture from a binary if present.""" + +import argparse +import os +import shutil +import subprocess +import sys + + +def check_output(command): + """Returns the output from |command| or propagates error, quitting script.""" + process = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + outs, errs = process.communicate() + if process.returncode: + sys.stderr.write('error: command failed with retcode %d: %s\n\n' % + (process.returncode, ' '.join(map(repr, command)))) + sys.stderr.write(errs.decode('UTF-8', errors='ignore')) + sys.exit(process.returncode) + return outs.decode('UTF-8') + + +def check_call(command): + """Invokes |command| or propagates error.""" + check_output(command) + + +def parse_args(args): + """Parses the command-line.""" + parser = argparse.ArgumentParser() + parser.add_argument('--input', required=True, help='Path to input binary') + parser.add_argument('--output', required=True, help='Path to output binary') + parser.add_argument('--xcode-version', required=True, help='Version of Xcode') + return parser.parse_args(args) + + +def get_archs(path): + """Extracts the architectures present in binary at |path|.""" + outputs = check_output(["xcrun", "lipo", "-info", os.path.abspath(path)]) + return outputs.split(': ')[-1].split() + + +def main(args): + parsed = parse_args(args) + + outdir = os.path.dirname(parsed.output) + if not os.path.isdir(outdir): + os.makedirs(outdir) + + if os.path.exists(parsed.output): + os.unlink(parsed.output) + + # As "lipo" fails with an error if asked to remove an architecture that is + # not included, only use it if "arm64e" is present in the binary. Otherwise + # simply copy the file. + if 'arm64e' in get_archs(parsed.input): + check_output([ + "xcrun", "lipo", "-remove", "arm64e", "-output", + os.path.abspath(parsed.output), + os.path.abspath(parsed.input) + ]) + else: + shutil.copy(parsed.input, parsed.output) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/third_party/libwebrtc/build/config/ios/write_framework_hmap.py b/third_party/libwebrtc/build/config/ios/write_framework_hmap.py new file mode 100644 index 0000000000..ac467ee92a --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/write_framework_hmap.py @@ -0,0 +1,103 @@ +# Copyright 2016 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. + +from __future__ import print_function + +import os +import struct +import sys + +def Main(args): + if len(args) < 4: + print( + "Usage: %s output.hmap Foo.framework header1.h..." % args[0], + file=sys.stderr) + return 1 + + (out, framework, all_headers) = args[1], args[2], args[3:] + + framework_name = os.path.basename(framework).split('.')[0] + all_headers = map(os.path.abspath, all_headers) + filelist = {} + for header in all_headers: + filename = os.path.basename(header) + filelist[filename] = header + filelist[os.path.join(framework_name, filename)] = header + WriteHmap(out, filelist) + return 0 + + +def NextGreaterPowerOf2(x): + return 2**(x).bit_length() + + +def WriteHmap(output_name, filelist): + """Generates a header map based on |filelist|. + + Per Mark Mentovai: + A header map is structured essentially as a hash table, keyed by names used + in #includes, and providing pathnames to the actual files. + + The implementation below and the comment above comes from inspecting: + http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt + while also looking at the implementation in clang in: + https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp + """ + magic = 1751998832 + version = 1 + _reserved = 0 + count = len(filelist) + capacity = NextGreaterPowerOf2(count) + strings_offset = 24 + (12 * capacity) + max_value_length = len(max(filelist.values(), key=lambda v: len(v))) + + out = open(output_name, 'wb') + out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset, + count, capacity, max_value_length)) + + # Create empty hashmap buckets. + buckets = [None] * capacity + for file, path in filelist.items(): + key = 0 + for c in file: + key += ord(c.lower()) * 13 + + # Fill next empty bucket. + while buckets[key & capacity - 1] is not None: + key = key + 1 + buckets[key & capacity - 1] = (file, path) + + next_offset = 1 + for bucket in buckets: + if bucket is None: + out.write(struct.pack('<LLL', 0, 0, 0)) + else: + (file, path) = bucket + key_offset = next_offset + prefix_offset = key_offset + len(file) + 1 + suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1 + next_offset = suffix_offset + len(os.path.basename(path)) + 1 + out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset)) + + # Pad byte since next offset starts at 1. + out.write(struct.pack('<x')) + + for bucket in buckets: + if bucket is not None: + (file, path) = bucket + base = os.path.dirname(path) + os.sep + path = os.path.basename(path) + file = file.encode('UTF-8') + base = base.encode('UTF-8') + path = path.encode('UTF-8') + out.write(struct.pack('<%ds' % len(file), file)) + out.write(struct.pack('<s', b'\0')) + out.write(struct.pack('<%ds' % len(base), base)) + out.write(struct.pack('<s', b'\0')) + out.write(struct.pack('<%ds' % len(path), path)) + out.write(struct.pack('<s', b'\0')) + + +if __name__ == '__main__': + sys.exit(Main(sys.argv)) diff --git a/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py b/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py new file mode 100644 index 0000000000..dcc88a8ea6 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/write_framework_modulemap.py @@ -0,0 +1,28 @@ +# Copyright 2016 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. + +import os +import sys + +MODULE_MAP_TEMPLATE = '''\ +framework module %(framework_name)s { + umbrella header "%(framework_name)s.h" + + export * + module * { export * } +} +''' + + +def Main(framework_name, modules_dir): + # Find the name of the binary based on the part before the ".framework". + if not os.path.isdir(modules_dir): + os.makedirs(modules_dir) + + with open(os.path.join(modules_dir, 'module.modulemap'), 'w') as module_file: + module_file.write(MODULE_MAP_TEMPLATE % {'framework_name': framework_name}) + + +if __name__ == '__main__': + Main(*sys.argv[1:]) diff --git a/third_party/libwebrtc/build/config/ios/xctest_shell.mm b/third_party/libwebrtc/build/config/ios/xctest_shell.mm new file mode 100644 index 0000000000..dcf5bad5e7 --- /dev/null +++ b/third_party/libwebrtc/build/config/ios/xctest_shell.mm @@ -0,0 +1,19 @@ +// Copyright 2016 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. + +#import <UIKit/UIKit.h> +#import <XCTest/XCTest.h> + +// For Chrome on iOS we want to run EarlGrey tests (that are XCTests) for all +// our build configurations (Debug, Release, ...). In addition, the symbols +// visibility is configured to private by default. To simplify testing with +// those constraints, our tests are compiled in the TEST_HOST target instead +// of the .xctest bundle that all link against this single test (just there to +// ensure that the bundle is not empty). + +@interface XCTestShellEmptyClass : NSObject +@end + +@implementation XCTestShellEmptyClass +@end diff --git a/third_party/libwebrtc/build/config/linux/BUILD.gn b/third_party/libwebrtc/build/config/linux/BUILD.gn new file mode 100644 index 0000000000..c036e4ae94 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/BUILD.gn @@ -0,0 +1,79 @@ +# 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. + +import("../../../webrtc.gni") + +import("//build/config/c++/c++.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/linux/pkg_config.gni") +import("//build/config/ui.gni") + +group("linux") { + visibility = [ "//:optimize_gn_gen" ] +} + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic that is +# Linux-only. This is not applied to Android, but is applied to ChromeOS. +config("compiler") { + if (target_cpu == "arm64") { + import("//build/config/arm.gni") + cflags = [] + asmflags = [] + if (arm_control_flow_integrity == "standard") { + cflags += [ "-mbranch-protection=standard" ] + asmflags += [ "-mbranch-protection=standard" ] + } + } +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Linux-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + # Set here because OS_CHROMEOS cannot be autodetected in build_config.h like + # OS_LINUX and the like. + if (is_chromeos) { + defines = [ "OS_CHROMEOS" ] + } + + if ((!(is_chromeos_ash || is_chromeos_lacros) || + default_toolchain != "//build/toolchain/cros:target") && + (!use_custom_libcxx || target_cpu == "mipsel") && !build_with_mozilla) { + libs = [ "atomic" ] + } +} + +config("libcap") { + libs = [ "cap" ] +} + +config("libresolv") { + libs = [ "resolv" ] +} + +if (false && use_glib) { + pkg_config("glib") { + packages = [ + "glib-2.0", + "gmodule-2.0", + "gobject-2.0", + "gthread-2.0", + ] + defines = [ + "GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_40", + "GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40", + ] + } +} + +# Ensures all exported symbols are added to the dynamic symbol table. This is +# necessary to expose Chrome's custom operator new() and operator delete() (and +# other memory-related symbols) to libraries. Otherwise, they might +# (de)allocate memory on a different heap, which would spell trouble if pointers +# to heap-allocated memory are passed over shared library boundaries. +config("export_dynamic") { + ldflags = [ "-rdynamic" ] +} diff --git a/third_party/libwebrtc/build/config/linux/OWNERS b/third_party/libwebrtc/build/config/linux/OWNERS new file mode 100644 index 0000000000..280ba478dc --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/OWNERS @@ -0,0 +1 @@ +thomasanderson@chromium.org diff --git a/third_party/libwebrtc/build/config/linux/atk/BUILD.gn b/third_party/libwebrtc/build/config/linux/atk/BUILD.gn new file mode 100644 index 0000000000..92baff2a9b --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/atk/BUILD.gn @@ -0,0 +1,35 @@ +# Copyright 2016 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. + +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/features.gni") +import("//build/config/linux/pkg_config.gni") +import("//build/config/ui.gni") + +# CrOS doesn't install GTK or any gnome packages. +assert(!is_chromeos) + +# These packages should _only_ be expected when building for a target. +assert(current_toolchain == default_toolchain) + +if (use_atk) { + assert(use_glib, "use_atk=true requires that use_glib=true") +} + +pkg_config("atk") { + packages = [ + "atk", + "atk-bridge-2.0", + ] + atk_lib_dir = exec_script(pkg_config_script, + pkg_config_args + [ + "--libdir", + "atk", + ], + "string") + defines = [ + "ATK_LIB_DIR=\"$atk_lib_dir\"", + "USE_ATK_BRIDGE", + ] +} diff --git a/third_party/libwebrtc/build/config/linux/atspi2/BUILD.gn b/third_party/libwebrtc/build/config/linux/atspi2/BUILD.gn new file mode 100644 index 0000000000..988a995681 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/atspi2/BUILD.gn @@ -0,0 +1,29 @@ +# Copyright 2018 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. + +import("//build/config/linux/pkg_config.gni") +import("//build/config/ui.gni") + +# These packages should _only_ be expected when building for a target. +assert(current_toolchain == default_toolchain) + +if (use_atk) { + pkg_config("atspi2") { + packages = [ "atspi-2" ] + atspi_version = exec_script(pkg_config_script, + pkg_config_args + [ + "atspi-2", + "--version-as-components", + ], + "value") + atspi_major_version = atspi_version[0] + atspi_minor_version = atspi_version[1] + atspi_micro_version = atspi_version[2] + defines = [ + "ATSPI_MAJOR_VERSION=$atspi_major_version", + "ATSPI_MINOR_VERSION=$atspi_minor_version", + "ATSPI_MICRO_VERSION=$atspi_micro_version", + ] + } +} diff --git a/third_party/libwebrtc/build/config/linux/dbus/BUILD.gn b/third_party/libwebrtc/build/config/linux/dbus/BUILD.gn new file mode 100644 index 0000000000..f11cf7101c --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/dbus/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2016 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. + +import("//build/config/features.gni") +import("//build/config/linux/pkg_config.gni") + +assert(use_dbus) + +# Note: if your target also depends on //dbus, you don't need to add this +# config (it will get added automatically if you depend on //dbus). +pkg_config("dbus") { + packages = [ "dbus-1" ] +} diff --git a/third_party/libwebrtc/build/config/linux/dri/BUILD.gn b/third_party/libwebrtc/build/config/linux/dri/BUILD.gn new file mode 100644 index 0000000000..cad883b76d --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/dri/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2017 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. + +import("//build/config/linux/pkg_config.gni") + +assert(is_linux, "This file should only be referenced on Linux") + +pkg_config("dri") { + packages = [ "dri" ] + dri_driver_dir = exec_script(pkg_config_script, + pkg_config_args + [ + "--dridriverdir", + "dri", + ], + "string") + defines = [ "DRI_DRIVER_DIR=\"$dri_driver_dir\"" ] +} diff --git a/third_party/libwebrtc/build/config/linux/gtk/BUILD.gn b/third_party/libwebrtc/build/config/linux/gtk/BUILD.gn new file mode 100644 index 0000000000..6590023971 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/gtk/BUILD.gn @@ -0,0 +1,69 @@ +# Copyright 2016 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. + +import("//build/config/linux/gtk/gtk.gni") +import("//build/config/linux/pkg_config.gni") + +assert(is_linux, "This file should only be referenced on Linux") + +declare_args() { + # The (major) version of GTK to build against. A different version may be + # loaded at runtime. + gtk_version = 3 +} + +# GN doesn't check visibility for configs so we give this an obviously internal +# name to discourage random targets from accidentally depending on this and +# bypassing the GTK target's visibility. +pkg_config("gtk_internal_config") { + # Gtk requires gmodule, but it does not list it as a dependency in some + # misconfigured systems. + packages = [ + "gmodule-2.0", + "gthread-2.0", + ] + if (gtk_version == 3) { + packages += [ "gtk+-3.0" ] + } else { + assert(gtk_version == 4) + packages += [ "gtk4" ] + } +} + +group("gtk") { + visibility = [ + # This is the only target that can depend on GTK. Do not add more targets + # to this list. + "//ui/gtk:gtk_stubs", + + # These are allow-listed for WebRTC builds. + "//examples:peerconnection_client", + "//remoting/host:common", + "//remoting/host:remoting_me2me_host_static", + "//remoting/host/file_transfer", + "//remoting/host/it2me:common", + "//remoting/host/it2me:remote_assistance_host", + "//remoting/host/linux", + "//remoting/host/remote_open_url:common", + "//remoting/test:it2me_standalone_host_main", + "//webrtc/examples:peerconnection_client", + ] + + public_configs = [ ":gtk_internal_config" ] +} + +# Depend on "gtkprint" to get this. +pkg_config("gtkprint_internal_config") { + if (gtk_version == 3) { + packages = [ "gtk+-unix-print-3.0" ] + } else { + assert(gtk_version == 4) + packages = [ "gtk4-unix-print" ] + } +} + +group("gtkprint") { + visibility = [ "//ui/gtk:*" ] + public_configs = [ ":gtkprint_internal_config" ] +} diff --git a/third_party/libwebrtc/build/config/linux/gtk/gtk.gni b/third_party/libwebrtc/build/config/linux/gtk/gtk.gni new file mode 100644 index 0000000000..70cb823154 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/gtk/gtk.gni @@ -0,0 +1,10 @@ +# Copyright 2018 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. + +import("//build/config/ui.gni") + +declare_args() { + # Whether or not we should use libgtk. + use_gtk = (is_linux || is_bsd) && !is_chromecast +} diff --git a/third_party/libwebrtc/build/config/linux/libdrm/BUILD.gn b/third_party/libwebrtc/build/config/linux/libdrm/BUILD.gn new file mode 100644 index 0000000000..79695cbc60 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/libdrm/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright 2018 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. +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/linux/pkg_config.gni") + +assert(is_linux || is_chromeos) + +declare_args() { + # Controls whether the build should use the version of libdrm library shipped + # with the system. In release builds of desktop Linux and Chrome OS we use the + # system version. Some Chromecast devices use this as well. + use_system_libdrm = is_chromeos_device || ((is_linux || is_bsd) && !is_chromecast) +} + +if (use_system_libdrm) { + pkg_config("libdrm_config") { + packages = [ "libdrm" ] + } + group("libdrm") { + public_configs = [ ":libdrm_config" ] + } +} else { + group("libdrm") { + public_deps = [ "//third_party/libdrm" ] + } + config("libdrm_exynos_include_config") { + include_dirs = [ "//third_party/libdrm/src/exynos" ] + } +} diff --git a/third_party/libwebrtc/build/config/linux/libffi/BUILD.gn b/third_party/libwebrtc/build/config/linux/libffi/BUILD.gn new file mode 100644 index 0000000000..fb4fa18bf7 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/libffi/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2016 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. + +import("//build/config/linux/pkg_config.gni") + +if (default_toolchain == "//build/toolchain/cros:target") { + pkg_config("libffi") { + packages = [ "libffi" ] + } +} else { + # On Linux, statically link libffi. This is necessary to prevent a situation + # where the runtime version of libffi is different from the build-time version + # from the sysroot. + config("libffi") { + libs = [ ":libffi_pic.a" ] + } +} diff --git a/third_party/libwebrtc/build/config/linux/libva/BUILD.gn b/third_party/libwebrtc/build/config/linux/libva/BUILD.gn new file mode 100644 index 0000000000..ada5d665fb --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/libva/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright 2018 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. + +import("//build/config/linux/pkg_config.gni") + +assert(is_linux || is_chromeos, "This file should only be referenced on Linux") + +pkg_config("libva") { + packages = [ "libva" ] + + # Do not use exec_script to check the version here. It is done with a + # static_assert instead. + + # vaapi decoders use dlopen pre-sandbox anyway to improve startup times. + ignore_libs = true +} diff --git a/third_party/libwebrtc/build/config/linux/nss/BUILD.gn b/third_party/libwebrtc/build/config/linux/nss/BUILD.gn new file mode 100644 index 0000000000..8c27938b76 --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/nss/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright 2014 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. + +import("//build/config/linux/pkg_config.gni") + +if (is_linux || is_chromeos) { + # This is a dependency on NSS with no libssl. On Linux we use a built-in SSL + # library but the system NSS libraries. Non-Linux platforms using NSS use the + # hermetic one in //third_party/nss. + # + # Generally you should depend on //crypto:platform instead of using this + # config since that will properly pick up NSS or OpenSSL depending on + # platform and build config. + pkg_config("system_nss_no_ssl_config") { + packages = [ "nss" ] + extra_args = [ + "-v", + "-lssl3", + ] + } +} diff --git a/third_party/libwebrtc/build/config/linux/pangocairo/BUILD.gn b/third_party/libwebrtc/build/config/linux/pangocairo/BUILD.gn new file mode 100644 index 0000000000..ddcc754bbd --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/pangocairo/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright 2016 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. + +import("//build/config/linux/pangocairo/pangocairo.gni") +import("//build/config/linux/pkg_config.gni") + +if (use_pangocairo) { + pkg_config("pangocairo") { + packages = [ "pangocairo" ] + + # We don't want pkgconfig for pangocairo to explicitly request FreeType to get + # linked, because we control which FreeType to link to. + extra_args = [ + "-v", + "freetype", + ] + } +} diff --git a/third_party/libwebrtc/build/config/linux/pangocairo/pangocairo.gni b/third_party/libwebrtc/build/config/linux/pangocairo/pangocairo.gni new file mode 100644 index 0000000000..6bc75294cd --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/pangocairo/pangocairo.gni @@ -0,0 +1,10 @@ +# Copyright 2017 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. + +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/ui.gni") + +declare_args() { + use_pangocairo = is_linux && !is_chromecast +} diff --git a/third_party/libwebrtc/build/config/linux/pkg-config.py b/third_party/libwebrtc/build/config/linux/pkg-config.py new file mode 100755 index 0000000000..5adf70cc3b --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/pkg-config.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python +# 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. + +from __future__ import print_function + +import json +import os +import subprocess +import sys +import re +from optparse import OptionParser + +# This script runs pkg-config, optionally filtering out some results, and +# returns the result. +# +# The result will be [ <includes>, <cflags>, <libs>, <lib_dirs>, <ldflags> ] +# where each member is itself a list of strings. +# +# You can filter out matches using "-v <regexp>" where all results from +# pkgconfig matching the given regular expression will be ignored. You can +# specify more than one regular expression my specifying "-v" more than once. +# +# You can specify a sysroot using "-s <sysroot>" where sysroot is the absolute +# system path to the sysroot used for compiling. This script will attempt to +# generate correct paths for the sysroot. +# +# When using a sysroot, you must also specify the architecture via +# "-a <arch>" where arch is either "x86" or "x64". +# +# CrOS systemroots place pkgconfig files at <systemroot>/usr/share/pkgconfig +# and one of <systemroot>/usr/lib/pkgconfig or <systemroot>/usr/lib64/pkgconfig +# depending on whether the systemroot is for a 32 or 64 bit architecture. They +# specify the 'lib' or 'lib64' of the pkgconfig path by defining the +# 'system_libdir' variable in the args.gn file. pkg_config.gni communicates this +# variable to this script with the "--system_libdir <system_libdir>" flag. If no +# flag is provided, then pkgconfig files are assumed to come from +# <systemroot>/usr/lib/pkgconfig. +# +# Additionally, you can specify the option --atleast-version. This will skip +# the normal outputting of a dictionary and instead print true or false, +# depending on the return value of pkg-config for the given package. + + +def SetConfigPath(options): + """Set the PKG_CONFIG_LIBDIR environment variable. + + This takes into account any sysroot and architecture specification from the + options on the given command line. + """ + + sysroot = options.sysroot + assert sysroot + + # Compute the library path name based on the architecture. + arch = options.arch + if sysroot and not arch: + print("You must specify an architecture via -a if using a sysroot.") + sys.exit(1) + + libdir = sysroot + '/usr/' + options.system_libdir + '/pkgconfig' + libdir += ':' + sysroot + '/usr/share/pkgconfig' + os.environ['PKG_CONFIG_LIBDIR'] = libdir + return libdir + + +def GetPkgConfigPrefixToStrip(options, args): + """Returns the prefix from pkg-config where packages are installed. + + This returned prefix is the one that should be stripped from the beginning of + directory names to take into account sysroots. + """ + # Some sysroots, like the Chromium OS ones, may generate paths that are not + # relative to the sysroot. For example, + # /path/to/chroot/build/x86-generic/usr/lib/pkgconfig/pkg.pc may have all + # paths relative to /path/to/chroot (i.e. prefix=/build/x86-generic/usr) + # instead of relative to /path/to/chroot/build/x86-generic (i.e prefix=/usr). + # To support this correctly, it's necessary to extract the prefix to strip + # from pkg-config's |prefix| variable. + prefix = subprocess.check_output([options.pkg_config, + "--variable=prefix"] + args, env=os.environ).decode('utf-8') + if prefix[-4] == '/usr': + return prefix[4:] + return prefix + + +def MatchesAnyRegexp(flag, list_of_regexps): + """Returns true if the first argument matches any regular expression in the + given list.""" + for regexp in list_of_regexps: + if regexp.search(flag) != None: + return True + return False + + +def RewritePath(path, strip_prefix, sysroot): + """Rewrites a path by stripping the prefix and prepending the sysroot.""" + if os.path.isabs(path) and not path.startswith(sysroot): + if path.startswith(strip_prefix): + path = path[len(strip_prefix):] + path = path.lstrip('/') + return os.path.join(sysroot, path) + else: + return path + + +def main(): + # If this is run on non-Linux platforms, just return nothing and indicate + # success. This allows us to "kind of emulate" a Linux build from other + # platforms. + if "linux" not in sys.platform: + print("[[],[],[],[],[]]") + return 0 + + parser = OptionParser() + parser.add_option('-d', '--debug', action='store_true') + parser.add_option('-p', action='store', dest='pkg_config', type='string', + default='pkg-config') + parser.add_option('-v', action='append', dest='strip_out', type='string') + parser.add_option('-s', action='store', dest='sysroot', type='string') + parser.add_option('-a', action='store', dest='arch', type='string') + parser.add_option('--system_libdir', action='store', dest='system_libdir', + type='string', default='lib') + parser.add_option('--atleast-version', action='store', + dest='atleast_version', type='string') + parser.add_option('--libdir', action='store_true', dest='libdir') + parser.add_option('--dridriverdir', action='store_true', dest='dridriverdir') + parser.add_option('--version-as-components', action='store_true', + dest='version_as_components') + (options, args) = parser.parse_args() + + # Make a list of regular expressions to strip out. + strip_out = [] + if options.strip_out != None: + for regexp in options.strip_out: + strip_out.append(re.compile(regexp)) + + if options.sysroot: + libdir = SetConfigPath(options) + if options.debug: + sys.stderr.write('PKG_CONFIG_LIBDIR=%s\n' % libdir) + prefix = GetPkgConfigPrefixToStrip(options, args) + else: + prefix = '' + + if options.atleast_version: + # When asking for the return value, just run pkg-config and print the return + # value, no need to do other work. + if not subprocess.call([options.pkg_config, + "--atleast-version=" + options.atleast_version] + + args): + print("true") + else: + print("false") + return 0 + + if options.version_as_components: + cmd = [options.pkg_config, "--modversion"] + args + try: + version_string = subprocess.check_output(cmd).decode('utf-8') + except: + sys.stderr.write('Error from pkg-config.\n') + return 1 + print(json.dumps(list(map(int, version_string.strip().split("."))))) + return 0 + + + if options.libdir: + cmd = [options.pkg_config, "--variable=libdir"] + args + if options.debug: + sys.stderr.write('Running: %s\n' % cmd) + try: + libdir = subprocess.check_output(cmd).decode('utf-8') + except: + print("Error from pkg-config.") + return 1 + sys.stdout.write(libdir.strip()) + return 0 + + if options.dridriverdir: + cmd = [options.pkg_config, "--variable=dridriverdir"] + args + if options.debug: + sys.stderr.write('Running: %s\n' % cmd) + try: + dridriverdir = subprocess.check_output(cmd).decode('utf-8') + except: + print("Error from pkg-config.") + return 1 + sys.stdout.write(dridriverdir.strip()) + return + + cmd = [options.pkg_config, "--cflags", "--libs"] + args + if options.debug: + sys.stderr.write('Running: %s\n' % ' '.join(cmd)) + + try: + flag_string = subprocess.check_output(cmd).decode('utf-8') + except: + sys.stderr.write('Could not run pkg-config.\n') + return 1 + + # For now just split on spaces to get the args out. This will break if + # pkgconfig returns quoted things with spaces in them, but that doesn't seem + # to happen in practice. + all_flags = flag_string.strip().split(' ') + + + sysroot = options.sysroot + if not sysroot: + sysroot = '' + + includes = [] + cflags = [] + libs = [] + lib_dirs = [] + + for flag in all_flags[:]: + if len(flag) == 0 or MatchesAnyRegexp(flag, strip_out): + continue; + + if flag[:2] == '-l': + libs.append(RewritePath(flag[2:], prefix, sysroot)) + elif flag[:2] == '-L': + lib_dirs.append(RewritePath(flag[2:], prefix, sysroot)) + elif flag[:2] == '-I': + includes.append(RewritePath(flag[2:], prefix, sysroot)) + elif flag[:3] == '-Wl': + # Don't allow libraries to control ld flags. These should be specified + # only in build files. + pass + elif flag == '-pthread': + # Many libs specify "-pthread" which we don't need since we always include + # this anyway. Removing it here prevents a bunch of duplicate inclusions + # on the command line. + pass + else: + cflags.append(flag) + + # Output a GN array, the first one is the cflags, the second are the libs. The + # JSON formatter prints GN compatible lists when everything is a list of + # strings. + print(json.dumps([includes, cflags, libs, lib_dirs])) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/libwebrtc/build/config/linux/pkg_config.gni b/third_party/libwebrtc/build/config/linux/pkg_config.gni new file mode 100644 index 0000000000..f3b40755bd --- /dev/null +++ b/third_party/libwebrtc/build/config/linux/pkg_config.gni @@ -0,0 +1,128 @@ +# 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. + +import("//build/config/sysroot.gni") + +# Defines a config specifying the result of running pkg-config for the given +# packages. Put the package names you want to query in the "packages" variable +# inside the template invocation. +# +# You can also add defines via the "defines" variable. This can be useful to +# add this to the config to pass defines that the library expects to get by +# users of its headers. +# +# Example: +# pkg_config("mything") { +# packages = [ "mything1", "mything2" ] +# defines = [ "ENABLE_AWESOME" ] +# } +# +# You can also use "extra args" to filter out results (see pkg-config.py): +# extra_args = [ "-v, "foo" ] +# To ignore libs and ldflags (only cflags/defines will be set, which is useful +# when doing manual dynamic linking), set: +# ignore_libs = true + +declare_args() { + # A pkg-config wrapper to call instead of trying to find and call the right + # pkg-config directly. Wrappers like this are common in cross-compilation + # environments. + # Leaving it blank defaults to searching PATH for 'pkg-config' and relying on + # the sysroot mechanism to find the right .pc files. + pkg_config = "" + + # A optional pkg-config wrapper to use for tools built on the host. + host_pkg_config = "" + + # CrOS systemroots place pkgconfig files at <systemroot>/usr/share/pkgconfig + # and one of <systemroot>/usr/lib/pkgconfig or <systemroot>/usr/lib64/pkgconfig + # depending on whether the systemroot is for a 32 or 64 bit architecture. + # + # When build under GYP, CrOS board builds specify the 'system_libdir' variable + # as part of the GYP_DEFINES provided by the CrOS emerge build or simple + # chrome build scheme. This variable permits controlling this for GN builds + # in similar fashion by setting the `system_libdir` variable in the build's + # args.gn file to 'lib' or 'lib64' as appropriate for the target architecture. + system_libdir = "lib" +} + +pkg_config_script = "//build/config/linux/pkg-config.py" + +# Define the args we pass to the pkg-config script for other build files that +# need to invoke it manually. +pkg_config_args = [] + +if (sysroot != "") { + # Pass the sysroot if we're using one (it requires the CPU arch also). + pkg_config_args += [ + "-s", + rebase_path(sysroot), + "-a", + target_cpu, + ] +} + +if (pkg_config != "") { + pkg_config_args += [ + "-p", + pkg_config, + ] +} + +# Only use the custom libdir when building with the target sysroot. +if (target_sysroot != "" && sysroot == target_sysroot) { + pkg_config_args += [ + "--system_libdir", + system_libdir, + ] +} + +if (host_pkg_config != "") { + host_pkg_config_args = [ + "-p", + host_pkg_config, + ] +} else { + host_pkg_config_args = pkg_config_args +} + +template("pkg_config") { + assert(defined(invoker.packages), + "Variable |packages| must be defined to be a list in pkg_config.") + config(target_name) { + if (host_toolchain == current_toolchain) { + args = host_pkg_config_args + invoker.packages + } else { + args = pkg_config_args + invoker.packages + } + if (defined(invoker.extra_args)) { + args += invoker.extra_args + } + + pkgresult = exec_script(pkg_config_script, args, "value") + cflags = pkgresult[1] + + foreach(include, pkgresult[0]) { + if (use_sysroot) { + # We want the system include paths to use -isystem instead of -I to + # suppress warnings in those headers. + include_relativized = rebase_path(include, root_build_dir) + cflags += [ "-isystem$include_relativized" ] + } else { + cflags += [ "-I$include" ] + } + } + + if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) { + libs = pkgresult[2] + lib_dirs = pkgresult[3] + } + + forward_variables_from(invoker, + [ + "defines", + "visibility", + ]) + } +} diff --git a/third_party/libwebrtc/build/config/locales.gni b/third_party/libwebrtc/build/config/locales.gni new file mode 100644 index 0000000000..1d57b877dc --- /dev/null +++ b/third_party/libwebrtc/build/config/locales.gni @@ -0,0 +1,251 @@ +# Copyright 2014 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. + +import("//build/config/chromeos/ui_mode.gni") + +# This file creates the |locales| which is the set of current +# locales based on the current platform. Locales in this list are formated +# based on what .pak files expect. +# The |locales| variable *may* contain pseudolocales, depending on the +# |enable_pseudolocales| flag. +# If you specifically want to have the locales variable with or without +# pseudolocales, then use |locales_with_pseudolocales| or +# |locales_without_pseudolocales|. + +# The following additional platform specific lists are created: +# - |android_bundle_locales_as_resources| locales formatted for XML output names +# - |locales_as_mac_outputs| formated for mac output bundles +# - |ios_packed_locales| subset for iOS +# - |ios_packed_locales_as_mac_outputs| subset for iOS output + +# Chrome on iOS only ships with a subset of the locales supported by other +# version of Chrome as the corresponding locales are not supported by the +# operating system (but for simplicity, the corresponding .pak files are +# still generated). +ios_unsupported_locales = [ + "am", + "bn", + "et", + "fil", + "gu", + "kn", + "lv", + "ml", + "mr", + "sl", + "sw", + "ta", + "te", +] + +# These list are defined even when not building for Android or iOS for the +# sake of build/locale_tool.py. Ensure that GN doesn't complain about them +# being unused. +not_needed([ "ios_unsupported_locales" ]) + +# Superset of all locales used in Chrome with platform specific changes noted. +all_chrome_locales = [ + "af", + "am", + "ar", + "as", + "az", + "be", + "bg", + "bn", + "bs", + "ca", + "cs", + "da", + "de", + "el", + "en-GB", + "en-US", + "es", + "es-419", # "es-MX" in iOS (Mexico vs Latin America) "es-US" on Android + "et", + "eu", + "fa", + "fi", + "fil", # "tl" in .xml but "fil" in TC and .pak + "fr", + "fr-CA", + "gl", + "gu", + "he", # "iw" in .xml and TC but "he" in .pak + "hi", + "hr", + "hu", + "hy", + "id", # "in" in .xml but "id" in TC and .pak + "is", + "it", + "ja", + "ka", + "kk", + "km", + "kn", + "ko", + "ky", + "lo", + "lt", + "lv", + "mk", + "ml", + "mn", + "mr", + "ms", + "my", + "nb", # "no" in TC but "nb" in .xml and .pak + "ne", + "nl", + "or", + "pa", + "pl", + "pt-BR", # just "pt" in iOS + "pt-PT", + "ro", + "ru", + "si", + "sk", + "sl", + "sq", + "sr", + "sr-Latn", # -b+sr+Latn in .xml + "sv", + "sw", + "ta", + "te", + "th", + "tr", + "uk", + "ur", + "uz", + "vi", + "zh-CN", + "zh-HK", + "zh-TW", + "zu", +] + +# New locales added to Chrome Android bundle builds. +android_bundle_only_locales = [ + "af", + "as", + "az", + "be", + "bs", + "eu", + "fr-CA", + "gl", + "hy", + "is", + "ka", + "kk", + "km", + "ky", + "lo", + "mk", + "mn", + "my", + "ne", + "or", + "pa", + "si", + "sq", + "sr-Latn", + "ur", + "uz", + "zh-HK", + "zu", +] + +# New locales added to ChromeOS builds. +chromeos_only_locales = [ "is" ] + +if (is_android) { + locales = all_chrome_locales + + # List for Android locale names in .xml exports. Note: needs to stay in sync + # with |ToAndroidLocaleName| in build/android/gyp/util/resource_utils.py. + # - add r: (e.g. zh-HK -> zh-rHK ) + android_bundle_locales_as_resources = [] + foreach(_locale, locales) { + android_bundle_locales_as_resources += + [ string_replace(_locale, "-", "-r") ] + } + + # - remove en-US + # - swap: (he, id, en-419, fil) -> (iw, in, es-rUS, tl) + # - sr-rLatn -> -b+sr+Latn + android_bundle_locales_as_resources -= [ + "en-rUS", + "es-r419", + "fil", + "he", + "id", + "sr-rLatn", + ] + android_bundle_locales_as_resources += [ + "b+sr+Latn", + "es-rUS", + "in", + "iw", + "tl", + ] +} else if (is_chromeos_ash || is_chromeos_lacros) { + # In ChromeOS we support a few more locales than standard Chrome. + locales = + all_chrome_locales - android_bundle_only_locales + chromeos_only_locales +} else { + # Change if other platforms support more locales. + locales = all_chrome_locales - android_bundle_only_locales +} + +# Chrome on iOS uses different names for "es-419" and "pt-BR" (called +# respectively "es-MX" and "pt" on iOS). +if (is_ios) { + locales -= [ + "es-419", + "pt-BR", + ] + locales += [ + "es-MX", + "pt", + ] +} + +pseudolocales = [ + "ar-XB", + "en-XA", +] +locales_without_pseudolocales = locales +locales_with_pseudolocales = locales + pseudolocales + +declare_args() { + # We want to give pseudolocales to everyone except end-users (devs & QA). + enable_pseudolocales = !is_official_build +} + +if (enable_pseudolocales) { + # Note that this only packages the locales in, and doesn't add the ui to enable them. + locales += pseudolocales +} + +# Same as the locales list but in the format Mac expects for output files: +# it uses underscores instead of hyphens, and "en" instead of "en-US". +locales_as_mac_outputs = [] +foreach(locale, locales) { + if (locale == "en-US") { + locales_as_mac_outputs += [ "en" ] + } else { + locales_as_mac_outputs += [ string_replace(locale, "-", "_") ] + } +} + +if (is_ios) { + ios_packed_locales = locales - ios_unsupported_locales + ios_packed_locales_as_mac_outputs = + locales_as_mac_outputs - ios_unsupported_locales +} diff --git a/third_party/libwebrtc/build/config/logging.gni b/third_party/libwebrtc/build/config/logging.gni new file mode 100644 index 0000000000..c2f94e929e --- /dev/null +++ b/third_party/libwebrtc/build/config/logging.gni @@ -0,0 +1,13 @@ +# Copyright 2019 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. + +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/dcheck_always_on.gni") + +declare_args() { + # Use LogErrorNotReached() for NOTREACHED(). + enable_log_error_not_reached = + is_chromeos_ash && !(is_debug || dcheck_always_on) + enable_stack_trace_line_numbers = false +} diff --git a/third_party/libwebrtc/build/config/mac/BUILD.gn b/third_party/libwebrtc/build/config/mac/BUILD.gn new file mode 100644 index 0000000000..032c77ee34 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/BUILD.gn @@ -0,0 +1,136 @@ +# 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. + +import("//build/config/apple/symbols.gni") +import("//build/config/c++/c++.gni") +import("//build/config/mac/mac_sdk.gni") +import("//build/config/sysroot.gni") + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic. +config("compiler") { + # These flags are shared between the C compiler and linker. + common_mac_flags = [] + + # CPU architecture. + if (target_cpu == "x64") { + clang_arch = "x86_64" + } else if (target_cpu == "x86") { + clang_arch = "i386" + } else if (target_cpu == "arm64") { + clang_arch = target_cpu + } else { + assert(false, "unknown target_cpu $target_cpu") + } + if (host_os == "mac") { + common_mac_flags += [ + "-arch", + clang_arch, + ] + } else { + common_mac_flags += [ "--target=$clang_arch-apple-macos" ] + } + + # This is here so that all files get recompiled after an Xcode update. + # (defines are passed via the command line, and build system rebuild things + # when their commandline changes). Nothing should ever read this define. + defines = [ "CR_XCODE_VERSION=$xcode_version" ] + + asmflags = common_mac_flags + cflags = common_mac_flags + + # Without this, the constructors and destructors of a C++ object inside + # an Objective C struct won't be called, which is very bad. + cflags_objcc = [ "-fobjc-call-cxx-cdtors" ] + + ldflags = common_mac_flags + + if (save_unstripped_output) { + ldflags += [ "-Wcrl,unstripped," + rebase_path(root_out_dir) ] + } + + if (export_libcxxabi_from_executables) { + ldflags += [ "-Wl,-undefined,dynamic_lookup" ] + } +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Mac-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + common_flags = [ + "-isysroot", + rebase_path(sysroot, root_build_dir), + "-mmacosx-version-min=$mac_deployment_target", + ] + + asmflags = common_flags + cflags = common_flags + ldflags = common_flags + + # Prevent Mac OS X AssertMacros.h (included by system header) from defining + # macros that collide with common names, like 'check', 'require', and + # 'verify'. + # http://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/AssertMacros.h + defines = [ "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0" ] +} + +# On Mac, this is used for everything except static libraries. +config("mac_dynamic_flags") { + ldflags = [ "-Wl,-ObjC" ] # Always load Objective-C categories and classes. + + if (is_component_build) { + ldflags += [ + # Path for loading shared libraries for unbundled binaries. + "-Wl,-rpath,@loader_path/.", + + # Path for loading shared libraries for bundled binaries. Get back from + # Binary.app/Contents/MacOS. + "-Wl,-rpath,@loader_path/../../..", + ] + } +} + +# The ldflags referenced below are handled by +# //build/toolchain/apple/linker_driver.py. +# Remove this config if a target wishes to change the arguments passed to the +# strip command during linking. This config by default strips all symbols +# from a binary, but some targets may wish to specify an exports file to +# preserve specific symbols. +config("strip_all") { + if (enable_stripping) { + ldflags = [ "-Wcrl,strip,-x,-S" ] + } +} + +# When building with Goma, all inputs must be relative to the build directory. +# If using the system Xcode, which typically resides outside the build root, a +# symlink to the SDK is created in the build directory, and the path to that +# link is stored in $mac_sdk_path. If an action references a file in the SDK as +# an input, GN will complain that no target generates the file because it is +# below the $root_build_dir. The below action lists as outputs the files in the +# SDK that are referenced as inputs to actions, so that GN thinks a target has +# generated them. The list is centralized here, as multiple targets need to +# reference the same files, and an output can only be generated once. +# +# The symbolic link for $mac_sdk_path is set up by +# //build/config/apple/sdk_info.py in //build/config/mac/mac_sdk.gni. +if (use_system_xcode && use_goma && target_os == "mac" && + current_toolchain == default_toolchain) { + action("sdk_inputs") { + script = "//build/noop.py" + outputs = [ + "$mac_sdk_path/usr/include/mach/exc.defs", + "$mac_sdk_path/usr/include/mach/mach_exc.defs", + "$mac_sdk_path/usr/include/mach/notify.defs", + ] + } +} else { + group("sdk_inputs") { + if (current_toolchain != default_toolchain) { + public_deps = [ ":sdk_inputs($default_toolchain)" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/mac/BuildInfo.plist b/third_party/libwebrtc/build/config/mac/BuildInfo.plist new file mode 100644 index 0000000000..bfa3b8d573 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/BuildInfo.plist @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DTCompiler</key> + <string>${GCC_VERSION}</string> + <key>DTSDKBuild</key> + <string>${MAC_SDK_BUILD}</string> + <key>DTSDKName</key> + <string>${MAC_SDK_NAME}</string> + <key>DTXcode</key> + <string>${XCODE_VERSION}</string> + <key>DTXcodeBuild</key> + <string>${XCODE_BUILD}</string> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/mac/OWNERS b/third_party/libwebrtc/build/config/mac/OWNERS new file mode 100644 index 0000000000..6f3324f07c --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/OWNERS @@ -0,0 +1 @@ +file://build/apple/OWNERS diff --git a/third_party/libwebrtc/build/config/mac/mac_sdk.gni b/third_party/libwebrtc/build/config/mac/mac_sdk.gni new file mode 100644 index 0000000000..6671893ae8 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/mac_sdk.gni @@ -0,0 +1,127 @@ +# Copyright 2014 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. + +import("//build/config/chrome_build.gni") +import("//build/config/gclient_args.gni") +import("//build/config/mac/mac_sdk_overrides.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") + +assert(current_os == "mac" || current_toolchain == default_toolchain) + +declare_args() { + # The MACOSX_DEPLOYMENT_TARGET variable used when compiling. This partially + # controls the minimum supported version of macOS for Chromium by + # affecting the symbol availability rules. This may differ from + # mac_min_system_version when dropping support for older macOSes but where + # additional code changes are required to be compliant with the availability + # rules. + # Must be of the form x.x.x for Info.plist files. + mac_deployment_target = "10.11.0" + + # The value of the LSMinimmumSystemVersion in Info.plist files. This partially + # controls the minimum supported version of macOS for Chromium by + # affecting the Info.plist. This may differ from mac_deployment_target when + # dropping support for older macOSes. This should be greater than or equal to + # the mac_deployment_target version. + # Must be of the form x.x.x for Info.plist files. + mac_min_system_version = "10.11.0" + + # Path to a specific version of the Mac SDK, not including a slash at the end. + # If empty, the path to the lowest version greater than or equal to + # mac_sdk_min is used. + mac_sdk_path = "" + + # The SDK name as accepted by xcodebuild. + mac_sdk_name = "macosx" + + # The SDK version used when making official builds. This is a single exact + # version, not a minimum. If this version isn't available official builds + # will fail. + mac_sdk_official_version = "11.3" + + # Production builds should use hermetic Xcode. If you want to do production + # builds with system Xcode to test new SDKs, set this. + # Don't set this on any bots. + mac_allow_system_xcode_for_official_builds_for_testing = false +} + +# Check that the version of macOS SDK used is the one requested when building +# a version of Chrome shipped to the users. Disable the check if building for +# iOS as the version macOS SDK used is not relevant for the tool build for the +# host (they are not shipped) --- this is required as Chrome on iOS is usually +# build with the latest version of Xcode that may not ship with the version of +# the macOS SDK used to build Chrome on mac. +# TODO(crbug.com/635745): the check for target_os should be replaced by a +# check that current_toolchain is default_toolchain, and the file should +# assert that current_os is "mac" once this file is no longer included by +# iOS toolchains. +if (is_chrome_branded && is_official_build && target_os != "ios") { + assert(!use_system_xcode || + mac_allow_system_xcode_for_official_builds_for_testing, + "official branded builds should use hermetic xcode") +} + +# The path to the hermetic install of Xcode. Only relevant when +# use_system_xcode = false. +if (!use_system_xcode) { + _hermetic_xcode_path = "//build/mac_files/xcode_binaries" +} + +script_name = "//build/config/apple/sdk_info.py" +sdk_info_args = [] +if (!use_system_xcode) { + sdk_info_args += [ + "--developer_dir", + rebase_path(_hermetic_xcode_path, "", root_build_dir), + ] +} + +# Goma RBE requires paths relative to source directory. When using system +# Xcode, this is done by creating symbolic links in root_build_dir. +if (use_system_xcode && use_goma) { + sdk_info_args += [ + "--get_sdk_info", + "--create_symlink_at", + "sdk/xcode_links", + ] +} +sdk_info_args += [ mac_sdk_name ] + +#_mac_sdk_result = exec_script(script_name, sdk_info_args, "scope") +#xcode_version = _mac_sdk_result.xcode_version +#xcode_build = _mac_sdk_result.xcode_build +if (mac_sdk_path == "" && use_system_xcode && use_goma) { + mac_sdk_path = _mac_sdk_result.sdk_path +} + +if (use_system_xcode) { + # The tool will print the SDK path on the first line, and the version on the + # second line. + find_sdk_args = [ + "--print_sdk_path", + "--print_bin_path", + mac_sdk_min, + ] + find_sdk_lines = + exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines") + mac_sdk_version = find_sdk_lines[2] + if (mac_sdk_path == "") { + mac_sdk_path = find_sdk_lines[0] + mac_bin_path = find_sdk_lines[1] + } else { + mac_bin_path = find_sdk_lines[1] + } +} else { + mac_sdk_version = mac_sdk_official_version + _dev = _hermetic_xcode_path + "/Contents/Developer" + _sdk = "MacOSX${mac_sdk_version}.sdk" + mac_sdk_path = _dev + "/Platforms/MacOSX.platform/Developer/SDKs/$_sdk" + mac_bin_path = _dev + "/Toolchains/XcodeDefault.xctoolchain/usr/bin/" + + # If we're using hermetic Xcode, then we want the paths to be relative so that + # generated ninja files are independent of the directory location. + # TODO(thakis): Do this at the uses of this variable instead. + mac_bin_path = rebase_path(mac_bin_path, root_build_dir) +} diff --git a/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni b/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni new file mode 100644 index 0000000000..17eb3d9f62 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni @@ -0,0 +1,16 @@ +# Copyright 2017 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 file contains arguments that subprojects may choose to override. It +# asserts that those overrides are used, to prevent unused args warnings. + +_sdk_min_from_env = getenv("FORCE_MAC_SDK_MIN") +declare_args() { + # Minimum supported version of the Mac SDK. + if (_sdk_min_from_env == "") { + mac_sdk_min = "10.15" + } else { + mac_sdk_min = _sdk_min_from_env + } +} diff --git a/third_party/libwebrtc/build/config/mac/package_framework.py b/third_party/libwebrtc/build/config/mac/package_framework.py new file mode 100644 index 0000000000..0026f466b4 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/package_framework.py @@ -0,0 +1,60 @@ +# Copyright 2016 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. + +import argparse +import errno +import os +import shutil +import sys + +def Main(): + parser = argparse.ArgumentParser(description='Create Mac Framework symlinks') + parser.add_argument('--framework', action='store', type=str, required=True) + parser.add_argument('--version', action='store', type=str) + parser.add_argument('--contents', action='store', type=str, nargs='+') + parser.add_argument('--stamp', action='store', type=str, required=True) + args = parser.parse_args() + + VERSIONS = 'Versions' + CURRENT = 'Current' + + # Ensure the Foo.framework/Versions/A/ directory exists and create the + # Foo.framework/Versions/Current symlink to it. + if args.version: + try: + os.makedirs(os.path.join(args.framework, VERSIONS, args.version), 0o755) + except OSError as e: + if e.errno != errno.EEXIST: + raise e + _Relink(os.path.join(args.version), + os.path.join(args.framework, VERSIONS, CURRENT)) + + # Establish the top-level symlinks in the framework bundle. The dest of + # the symlinks may not exist yet. + if args.contents: + for item in args.contents: + _Relink(os.path.join(VERSIONS, CURRENT, item), + os.path.join(args.framework, item)) + + # Write out a stamp file. + if args.stamp: + with open(args.stamp, 'w') as f: + f.write(str(args)) + + return 0 + + +def _Relink(dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + try: + os.remove(link) + except OSError as e: + if e.errno != errno.ENOENT: + shutil.rmtree(link) + os.symlink(dest, link) + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/third_party/libwebrtc/build/config/mac/prepare_framework_version.py b/third_party/libwebrtc/build/config/mac/prepare_framework_version.py new file mode 100644 index 0000000000..db92150698 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/prepare_framework_version.py @@ -0,0 +1,42 @@ +# Copyright 2016 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. + +import os +import shutil +import sys + +# Ensures that the current version matches the last-produced version, which is +# stored in the version_file. If it does not, then the framework_root_dir is +# obliterated. +# Usage: python prepare_framework_version.py out/obj/version_file \ +# out/Framework.framework \ +# 'A' + +def PrepareFrameworkVersion(version_file, framework_root_dir, version): + # Test what the current framework version is. Stop if it is up-to-date. + try: + with open(version_file, 'r') as f: + current_version = f.read() + if current_version == version: + return + except IOError: + pass + + # The framework version has changed, so clobber the framework. + if os.path.exists(framework_root_dir): + shutil.rmtree(framework_root_dir) + + # Write out the new framework version file, making sure its containing + # directory exists. + dirname = os.path.dirname(version_file) + if not os.path.isdir(dirname): + os.makedirs(dirname, 0o700) + + with open(version_file, 'w+') as f: + f.write(version) + + +if __name__ == '__main__': + PrepareFrameworkVersion(sys.argv[1], sys.argv[2], sys.argv[3]) + sys.exit(0) diff --git a/third_party/libwebrtc/build/config/mac/rules.gni b/third_party/libwebrtc/build/config/mac/rules.gni new file mode 100644 index 0000000000..7753a97fe7 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/rules.gni @@ -0,0 +1,628 @@ +# 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. + +import("//build/apple/apple_info_plist.gni") +import("//build/config/apple/symbols.gni") +import("//build/config/mac/mac_sdk.gni") + +# Generates Info.plist files for Mac apps and frameworks. +# +# Arguments +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# executable_name: +# string, name of the generated target used for the product +# and executable name as specified in the output Info.plist. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +template("mac_info_plist") { + assert(defined(invoker.info_plist) != defined(invoker.info_plist_target), + "Only one of info_plist or info_plist_target may be specified in " + + target_name) + + if (defined(invoker.info_plist)) { + _info_plist = invoker.info_plist + } else { + _info_plist_target_output = get_target_outputs(invoker.info_plist_target) + _info_plist = _info_plist_target_output[0] + } + + apple_info_plist(target_name) { + format = "xml1" + extra_substitutions = [] + if (defined(invoker.extra_substitutions)) { + extra_substitutions = invoker.extra_substitutions + } + extra_substitutions += [ + "MAC_SDK_BUILD=$mac_sdk_version", + "MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version", + "MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target", + "CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version", + "XCODE_BUILD=$xcode_build", + "XCODE_VERSION=$xcode_version", + ] + plist_templates = [ + "//build/config/mac/BuildInfo.plist", + _info_plist, + ] + if (defined(invoker.info_plist_target)) { + deps = [ invoker.info_plist_target ] + } + forward_variables_from(invoker, + [ + "testonly", + "executable_name", + ]) + } +} + +# Template to package a shared library into a Mac framework bundle. +# +# By default, the bundle target this template generates does not link the +# resulting framework into anything that depends on it. If a dependency wants +# a link-time (as well as build-time) dependency on the framework bundle, +# depend against "$target_name+link". If only the build-time dependency is +# required (e.g., for copying into another bundle), then use "$target_name". +# +# Arguments +# +# framework_version: +# string, version of the framework. Typically this is a +# single letter, like "A". +# +# framework_contents: +# list of string, top-level items in the framework. This is +# the list of symlinks to create in the .framework directory that link +# into Versions/Current/. +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# output_name: +# (optional) string, name of the generated framework without the +# .framework suffix. If omitted, defaults to target_name. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +# +# This template provides three targets for the resulting framework bundle. The +# link-time behavior varies depending on which of the two targets below is +# added as a dependency: +# - $target_name only adds a build-time dependency. Targets that depend on +# it will not link against the framework. +# - $target_name+link adds a build-time and link-time dependency. Targets +# that depend on it will link against the framework. +# - $target_name+link_nested adds a build-time and link-time dependency, but +# only on the shared library and not the fully-assembled framework bundle. +# This should only be used for other nested binary components of the +# framework bundle (e.g. Helpers) that themselves depend on the main shared +# library of the framework bundle. +# +# The build-time-only dependency is used for when a target needs to use the +# framework either only for resources, or because the target loads it at run- +# time, via dlopen() or NSBundle. The link-time dependency will cause the +# dependee to have the framework loaded by dyld at launch. +# +# Example of build-time only dependency: +# +# mac_framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# The GoatTeleporter.app will not directly link against +# CoreTeleportation.framework, but it will be included in the bundle's +# Frameworks directory. +# +# Example of link-time dependency: +# +# mac_framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# ldflags = [ +# "-install_name", +# "@executable_path/../Frameworks/$target_name.framework" +# ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation+link" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# Note that the framework is still copied to the app's bundle, but dyld will +# load this library when the app is launched because it uses the "+link" +# target as a dependency. This also requires that the framework set its +# install_name so that dyld can locate it. +# +# See "gn help shared_library" for more information on arguments supported +# by shared library target. +template("mac_framework_bundle") { + assert(defined(invoker.deps) || defined(invoker.public_deps), + "Dependencies must be specified for $target_name") + assert(invoker.framework_version != "", "framework_version is required") + assert(defined(invoker.framework_contents), "framework_contents is required") + + _info_plist_target = target_name + "_info_plist" + + mac_info_plist(_info_plist_target) { + executable_name = target_name + if (defined(invoker.output_name)) { + executable_name = invoker.output_name + } + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + "testonly", + ]) + } + + _info_plist_bundle_data = _info_plist_target + "_bundle_data" + + bundle_data(_info_plist_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_resources_dir}}/Info.plist" ] + public_deps = [ ":$_info_plist_target" ] + } + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + # Create a file to track the build dependency on the framework_version and + # framework_contents variables. + _framework_toc = [ + "Version=" + invoker.framework_version, + _output_name, + ] + invoker.framework_contents + _framework_contents = [ _output_name ] + invoker.framework_contents + _framework_toc_file = "$target_out_dir/${target_name}.toc" + write_file(_framework_toc_file, _framework_toc) + + # Create local variables for referencing different parts of the bundle. + _framework_target = _target_name + _framework_name = _output_name + ".framework" + _framework_base_dir = "$root_out_dir/$_framework_name" + _framework_root_dir = + _framework_base_dir + "/Versions/${invoker.framework_version}" + + # Clean the entire framework if the framework_version changes. + _version_file = "$target_out_dir/${target_name}_version" + exec_script("//build/config/mac/prepare_framework_version.py", + [ + rebase_path(_version_file), + rebase_path(_framework_base_dir), + invoker.framework_version, + ]) + + # Create the symlinks. + _framework_package_target = target_name + "_package" + action(_framework_package_target) { + script = "//build/config/mac/package_framework.py" + + # The TOC file never needs to be read, since its contents are the values + # of GN variables. It is only used to trigger this rule when the values + # change. + inputs = [ _framework_toc_file ] + + _stamp_file = "$target_out_dir/run_${_framework_package_target}.stamp" + outputs = [ _stamp_file ] + + visibility = [ ":$_framework_target" ] + + args = [ + "--framework", + rebase_path(_framework_base_dir, root_build_dir), + "--stamp", + rebase_path(_stamp_file, root_build_dir), + "--version", + invoker.framework_version, + "--contents", + ] + _framework_contents + + # It is not possible to list _framework_contents as outputs, since + # ninja does not properly stat symbolic links. + # https://github.com/ninja-build/ninja/issues/1186 + } + + _link_shared_library_target = target_name + "_shared_library" + _shared_library_bundle_data = target_name + "_shared_library_bundle_data" + + shared_library(_link_shared_library_target) { + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "bundle_deps", + "code_signing_enabled", + "data_deps", + "info_plist", + "info_plist_target", + "output_name", + "visibility", + ]) + visibility = [ + ":$_shared_library_bundle_data", + ":${_framework_target}+link_nested", + ] + output_name = _output_name + output_prefix_override = true + output_extension = "" + output_dir = "$target_out_dir/$_link_shared_library_target" + } + + bundle_data(_shared_library_bundle_data) { + visibility = [ ":$_framework_target" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = [ "$target_out_dir/$_link_shared_library_target/$_output_name" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_link_shared_library_target" ] + } + + _framework_public_config = _target_name + "_public_config" + config(_framework_public_config) { + visibility = [ ":$_framework_target+link" ] + framework_dirs = [ root_out_dir ] + frameworks = [ _framework_name ] + } + + create_bundle(_framework_target) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + ]) + + if (defined(invoker.visibility)) { + visibility = invoker.visibility + visibility += [ ":$_target_name+link" ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_info_plist_bundle_data" ] + + if (defined(invoker.bundle_deps)) { + deps += invoker.bundle_deps + } + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ + ":$_framework_package_target", + ":$_shared_library_bundle_data", + ] + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name", + ] + } + + bundle_root_dir = _framework_base_dir + bundle_contents_dir = _framework_root_dir + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = bundle_contents_dir + } + + group(_target_name + "+link") { + forward_variables_from(invoker, + [ + "public_configs", + "testonly", + "visibility", + ]) + public_deps = [ ":$_target_name" ] + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":$_framework_public_config" ] + } + + group(_target_name + "+link_nested") { + forward_variables_from(invoker, + [ + "public_configs", + "testonly", + "visibility", + ]) + + # Depend only on the shared library. Nested code will be a dependency of + # the create_bundle target, which would be cyclic with depending on the + # framework itself. This is sufficient to link; for loading, a proper + # install_name should be set. + public_deps = [ ":$_link_shared_library_target" ] + } +} + +set_defaults("mac_framework_bundle") { + configs = default_shared_library_configs +} + +# Template to create a Mac executable application bundle. +# +# Arguments +# +# package_type: +# (optional) string, the product package type to create. Options are: +# "app" to create a .app bundle (default) +# "xpc" to create an .xpc service bundle +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# output_name: +# (optional) string, name of the generated app without the +# .app suffix. If omitted, defaults to target_name. +# +# extra_configs: +# (optional) list of label, additional configs to apply to the +# executable target. +# +# remove_configs: +# (optional) list of label, default configs to remove from the target. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +template("mac_app_bundle") { + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _package_type = "app" + if (defined(invoker.package_type)) { + _package_type = invoker.package_type + } + + if (_package_type == "app") { + _output_extension = "app" + _product_type = "com.apple.product-type.application" + _write_pkg_info = true + } else if (_package_type == "xpc") { + _output_extension = "xpc" + _product_type = "com.apple.product-type.xpc-service" + _write_pkg_info = false + } else if (_package_type == "bundle") { + _output_extension = "bundle" + _product_type = "com.apple.product-type.bundle" + _write_pkg_info = false + } else { + assert(false, "Unsupported packge_type: " + packge_type) + } + + _executable_target = target_name + "_executable" + _executable_bundle_data = _executable_target + "_bundle_data" + + _info_plist_target = target_name + "_info_plist" + + mac_info_plist(_info_plist_target) { + executable_name = _output_name + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + "testonly", + ]) + } + + if (_write_pkg_info) { + _pkg_info_target = target_name + "_pkg_info" + + action(_pkg_info_target) { + forward_variables_from(invoker, [ "testonly" ]) + script = "//build/apple/write_pkg_info.py" + inputs = [ "//build/apple/plist_util.py" ] + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "$target_gen_dir/$_pkg_info_target" ] + args = [ "--plist" ] + rebase_path(sources, root_build_dir) + + [ "--output" ] + rebase_path(outputs, root_build_dir) + deps = [ ":$_info_plist_target" ] + } + } + + executable(_executable_target) { + visibility = [ ":$_executable_bundle_data" ] + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "data_deps", + "info_plist", + "output_name", + "visibility", + ]) + if (defined(extra_configs)) { + configs += extra_configs + } + if (defined(remove_configs)) { + configs -= remove_configs + } + output_name = _output_name + output_dir = "$target_out_dir/$_executable_target" + } + + bundle_data(_executable_bundle_data) { + visibility = [ ":$_target_name" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = [ "$target_out_dir/$_executable_target/$_output_name" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_executable_target" ] + } + + _info_plist_bundle_data = _info_plist_target + "_bundle_data" + + bundle_data(_info_plist_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_contents_dir}}/Info.plist" ] + public_deps = [ ":$_info_plist_target" ] + } + + if (_write_pkg_info) { + _pkg_info_bundle_data = _pkg_info_target + "_bundle_data" + + bundle_data(_pkg_info_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = get_target_outputs(":$_pkg_info_target") + outputs = [ "{{bundle_contents_dir}}/PkgInfo" ] + public_deps = [ ":$_pkg_info_target" ] + } + } + + create_bundle(_target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + deps += [ + ":$_executable_bundle_data", + ":$_info_plist_bundle_data", + ] + if (_write_pkg_info) { + deps += [ ":$_pkg_info_bundle_data" ] + } + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name", + ] + } + + product_type = _product_type + bundle_root_dir = "$root_out_dir/${_output_name}.${_output_extension}" + bundle_contents_dir = "$bundle_root_dir/Contents" + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = "$bundle_contents_dir/MacOS" + } +} + +# Template to package a loadable_module into a .plugin bundle. +# +# This takes no extra arguments that differ from a loadable_module. +template("mac_plugin_bundle") { + assert(defined(invoker.deps), + "Dependencies must be specified for $target_name") + + _target_name = target_name + _loadable_module_target = _target_name + "_loadable_module" + _loadable_module_bundle_data = _loadable_module_target + "_bundle_data" + + _output_name = _target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + loadable_module(_loadable_module_target) { + visibility = [ ":$_loadable_module_bundle_data" ] + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "data_deps", + "output_name", + "visibility", + ]) + output_dir = "$target_out_dir" + output_name = _output_name + } + + bundle_data(_loadable_module_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = [ "$target_out_dir/$_output_name.so" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_loadable_module_target" ] + } + + create_bundle(_target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_loadable_module_bundle_data" ] + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.so.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.so.dSYM/Contents/Resources/DWARF/$_output_name.so", + ] + } + + bundle_root_dir = "$root_out_dir/$_output_name.plugin" + bundle_contents_dir = "$bundle_root_dir/Contents" + bundle_executable_dir = "$bundle_contents_dir/MacOS" + } +} diff --git a/third_party/libwebrtc/build/config/mips.gni b/third_party/libwebrtc/build/config/mips.gni new file mode 100644 index 0000000000..8ad7e27911 --- /dev/null +++ b/third_party/libwebrtc/build/config/mips.gni @@ -0,0 +1,67 @@ +# 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. + +import("//build/config/v8_target_cpu.gni") + +# These are primarily relevant in target_cpu == "mips*" contexts, where +# MIPS code is being compiled. But they can also be relevant in the +# other contexts when the code will change its behavior based on the +# cpu it wants to generate code for. +declare_args() { + # MIPS MultiMedia Instruction compilation flag. + mips_use_mmi = false +} + +if (target_cpu == "mipsel" || v8_target_cpu == "mipsel" || + target_cpu == "mips" || v8_target_cpu == "mips") { + declare_args() { + # MIPS arch variant. Possible values are: + # "r1" + # "r2" + # "r6" + # "loongson3" + mips_arch_variant = "r1" + + # MIPS DSP ASE revision. Possible values are: + # 0: unavailable + # 1: revision 1 + # 2: revision 2 + mips_dsp_rev = 0 + + # MIPS SIMD Arch compilation flag. + mips_use_msa = false + + # MIPS floating-point ABI. Possible values are: + # "hard": sets the GCC -mhard-float option. + # "soft": sets the GCC -msoft-float option. + mips_float_abi = "hard" + + # MIPS32 floating-point register width. Possible values are: + # "fp32": sets the GCC -mfp32 option. + # "fp64": sets the GCC -mfp64 option. + # "fpxx": sets the GCC -mfpxx option. + mips_fpu_mode = "fp32" + } +} else if (target_cpu == "mips64el" || v8_target_cpu == "mips64el" || + target_cpu == "mips64" || v8_target_cpu == "mips64") { + # MIPS arch variant. Possible values are: + # "r2" + # "r6" + # "loongson3" + if (current_os == "android" || target_os == "android") { + declare_args() { + mips_arch_variant = "r6" + + # MIPS SIMD Arch compilation flag. + mips_use_msa = true + } + } else { + declare_args() { + mips_arch_variant = "r2" + + # MIPS SIMD Arch compilation flag. + mips_use_msa = false + } + } +} diff --git a/third_party/libwebrtc/build/config/nacl/BUILD.gn b/third_party/libwebrtc/build/config/nacl/BUILD.gn new file mode 100644 index 0000000000..89fbf85aa5 --- /dev/null +++ b/third_party/libwebrtc/build/config/nacl/BUILD.gn @@ -0,0 +1,143 @@ +# Copyright (c) 2014 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/nacl/config.gni") + +# Native Client Definitions +config("nacl_defines") { + if (is_linux || is_chromeos || is_android || is_nacl) { + defines = [ + "_POSIX_C_SOURCE=199506", + "_XOPEN_SOURCE=600", + "_GNU_SOURCE=1", + "__STDC_LIMIT_MACROS=1", + ] + } else if (is_win) { + defines = [ "__STDC_LIMIT_MACROS=1" ] + } + + if (target_cpu == "pnacl" && !is_nacl_nonsfi) { + # TODO: Remove the following definition once NACL_BUILD_ARCH and + # NACL_BUILD_SUBARCH are defined by the PNaCl toolchain. + defines += [ "NACL_BUILD_ARCH=pnacl" ] + } +} + +config("nexe_defines") { + defines = [ + "DYNAMIC_ANNOTATIONS_ENABLED=1", + "DYNAMIC_ANNOTATIONS_PREFIX=NACL_", + ] +} + +config("nacl_warnings") { + if (is_win) { + # Some NaCl code uses forward declarations of static const variables, + # with initialized definitions later on. (The alternative would be + # many, many more forward declarations of everything used in that + # const variable's initializer before the definition.) The Windows + # compiler is too stupid to notice that there is an initializer later + # in the file, and warns about the forward declaration. + cflags = [ "/wd4132" ] + } +} + +# The base target that all targets in the NaCl build should depend on. +# This allows configs to be modified for everything in the NaCl build, even when +# the NaCl build is composed into the Chrome build. (GN has no functionality to +# add flags to everything in //native_client, having a base target works around +# that limitation.) +source_set("nacl_base") { + public_configs = [ + ":nacl_defines", + ":nacl_warnings", + ] + if (current_os == "nacl") { + public_configs += [ ":nexe_defines" ] + } +} + +config("compiler") { + configs = [] + cflags = [] + ldflags = [] + libs = [] + + if (is_clang && target_cpu != "pnacl") { + # -no-integrated-as is the default in nacl-clang for historical + # compatibility with inline assembly code and so forth. But there + # are no such cases in Chromium code, and -integrated-as is nicer in + # general. Moreover, the IRT must be built using LLVM's assembler + # on x86-64 to preserve sandbox base address hiding. Use it + # everywhere for consistency (and possibly quicker builds). + cflags += [ "-integrated-as" ] + } + if (is_nacl_nonsfi) { + cflags += [ "--pnacl-allow-translate" ] + ldflags += [ + "--pnacl-allow-translate", + "--pnacl-allow-native", + "-Wl,--noirt", + "-Wt,--noirt", + "-Wt,--noirtshim", + + # The clang driver automatically injects -lpthread when using libc++, but + # the toolchain doesn't have it yet. To get around this, use + # -nodefaultlibs and make each executable target depend on + # "//native_client/src/nonsfi/irt:nacl_sys_private". + "-nodefaultlibs", + ] + libs += [ + "c++", + "m", + "c", + "pnaclmm", + ] + include_dirs = [ "//native_client/src/public/linux_syscalls" ] + } + + asmflags = cflags +} + +config("compiler_codegen") { + cflags = [] + + if (is_nacl_irt) { + cflags += [ + # A debugger should be able to unwind IRT call frames. This is + # the default behavior on x86-64 and when compiling C++ with + # exceptions enabled; the change is for the benefit of x86-32 C. + # The frame pointer is unnecessary when unwind tables are used. + "-fasynchronous-unwind-tables", + "-fomit-frame-pointer", + ] + + if (target_cpu == "x86") { + # The x86-32 IRT needs to be callable with an under-aligned + # stack; so we disable SSE instructions, which can fault on + # misaligned addresses. See + # https://code.google.com/p/nativeclient/issues/detail?id=3935 + cflags += [ + "-mstackrealign", + "-mno-sse", + ] + } + } + + asmflags = cflags +} + +config("irt_optimize") { + cflags = [ + # Optimize for space, keep the IRT nexe small. + "-Os", + + # These are omitted from non-IRT libraries to keep the libraries + # themselves small. + "-ffunction-sections", + "-fdata-sections", + ] + + ldflags = [ "-Wl,--gc-sections" ] +} diff --git a/third_party/libwebrtc/build/config/nacl/config.gni b/third_party/libwebrtc/build/config/nacl/config.gni new file mode 100644 index 0000000000..9ebdb39c35 --- /dev/null +++ b/third_party/libwebrtc/build/config/nacl/config.gni @@ -0,0 +1,61 @@ +# 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. + +declare_args() { + # Native Client supports multiple toolchains: + # - nacl_glibc, based on gcc and glibc. + # - pnacl_newlib, based on llvm 3.7 and newlib (default). + # - saigo_newlib, based on llvm 12+ and newlib. + + # True if nacl_glibc is used. + is_nacl_glibc = false + + # True if saigo_newlib is used. + is_nacl_saigo = false +} + +is_nacl_irt = false +is_nacl_nonsfi = false + +nacl_toolchain_dir = "//native_client/toolchain/${host_os}_x86" + +if (is_nacl_glibc) { + if (target_cpu == "x86" || target_cpu == "x64") { + nacl_toolchain_package = "nacl_x86_glibc" + } else if (target_cpu == "arm") { + nacl_toolchain_package = "nacl_arm_glibc" + } +} else { + nacl_toolchain_package = "pnacl_newlib" +} + +if (target_cpu == "pnacl") { + _nacl_tuple = "pnacl" +} else if (target_cpu == "x86" || target_cpu == "x64") { + _nacl_tuple = "x86_64-nacl" +} else if (target_cpu == "arm") { + _nacl_tuple = "arm-nacl" +} else if (target_cpu == "mipsel") { + _nacl_tuple = "mipsel-nacl" +} else { + # In order to allow this file to be included unconditionally + # from build files that can't depend on //components/nacl/features.gni + # we provide a dummy value that should be harmless if nacl isn't needed. + # If nacl *is* needed this will result in a real error, indicating that + # people need to set the toolchain path correctly. + _nacl_tuple = "unknown" +} + +nacl_toolchain_bindir = "${nacl_toolchain_dir}/${nacl_toolchain_package}/bin" +nacl_toolchain_tooldir = + "${nacl_toolchain_dir}/${nacl_toolchain_package}/${_nacl_tuple}" +nacl_toolprefix = "${nacl_toolchain_bindir}/${_nacl_tuple}-" + +nacl_irt_toolchain = "//build/toolchain/nacl:irt_" + target_cpu +is_nacl_irt = current_toolchain == nacl_irt_toolchain + +# Non-SFI mode is a lightweight sandbox used by Chrome OS for running ARC +# applications. +nacl_nonsfi_toolchain = "//build/toolchain/nacl:newlib_pnacl_nonsfi" +is_nacl_nonsfi = current_toolchain == nacl_nonsfi_toolchain diff --git a/third_party/libwebrtc/build/config/nacl/rules.gni b/third_party/libwebrtc/build/config/nacl/rules.gni new file mode 100644 index 0000000000..42bb248357 --- /dev/null +++ b/third_party/libwebrtc/build/config/nacl/rules.gni @@ -0,0 +1,180 @@ +# Copyright 2015 The Native Client Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/nacl/config.gni") + +# Generate a nmf file +# +# Native Client Manifest (nmf) is a JSON file that tells the browser where to +# download and load Native Client application files and libraries. +# +# Variables: +# executables: .nexe/.pexe/.bc executables to generate nmf for +# lib_prefix: path to prepend to shared libraries in the nmf +# nmf: the name and the path of the output file +# nmfflags: additional flags for the nmf generator +# stage_dependencies: directory for staging libraries +template("generate_nmf") { + assert(defined(invoker.executables), "Must define executables") + assert(defined(invoker.nmf), "Must define nmf") + + action(target_name) { + forward_variables_from(invoker, + [ + "deps", + "data_deps", + "executables", + "lib_prefix", + "nmf", + "nmfflags", + "public_deps", + "stage_dependencies", + "testonly", + "visibility", + ]) + if (!defined(nmfflags)) { + nmfflags = [] + } + + # TODO(phosek): Remove this conditional once + # https://bugs.chromium.org/p/nativeclient/issues/detail?id=4339 is + # resolved. + if (target_cpu == "pnacl") { + objdump = rebase_path("${nacl_toolchain_bindir}/x86_64-nacl-objdump") + } else { + objdump = rebase_path("${nacl_toolprefix}objdump") + } + if (host_os == "win") { + objdump += ".exe" + } + + script = "//native_client_sdk/src/tools/create_nmf.py" + inputs = [ objdump ] + sources = executables + outputs = [ nmf ] + if (is_nacl_glibc) { + if (defined(stage_dependencies)) { + nmfflags += [ "--stage-dependencies=" + + rebase_path(stage_dependencies, root_build_dir) ] + lib_path = stage_dependencies + } else { + lib_path = root_build_dir + } + if (defined(lib_prefix)) { + nmfflags += [ "--lib-prefix=" + lib_prefix ] + lib_path += "/${lib_prefix}" + } + + # Starts empty so the code below can use += everywhere. + data = [] + + nmfflags += + [ "--library-path=" + rebase_path(root_out_dir, root_build_dir) ] + + # NOTE: There is no explicit dependency for the lib directory + # (lib32 and lib64 for x86/x64) created in the product directory. + # They are created as a side-effect of nmf creation. + if (target_cpu != "x86" && target_cpu != "x64") { + nmfflags += + [ "--library-path=" + + rebase_path("${nacl_toolchain_tooldir}/lib", root_build_dir) ] + if (target_cpu == "arm") { + data += [ "${lib_path}/libarm/" ] + } else { + data += [ "${lib_path}/lib/" ] + } + } else { + # For x86-32, the lib/ directory is called lib32/ instead. + if (target_cpu == "x86") { + nmfflags += + [ "--library-path=" + + rebase_path("${nacl_toolchain_tooldir}/lib32", root_build_dir) ] + data += [ "${lib_path}/lib32/" ] + } + + # x86-32 Windows needs to build both x86-32 and x86-64 NaCl + # binaries into the same nmf covering both architectures. That + # gets handled at a higher level (see the nacl_test_data template), + # so a single generate_nmf invocation gets both x86-32 and x86-64 + # nexes listed in executables. + if (target_cpu == "x64" || target_os == "win") { + # For x86-64, the lib/ directory is called lib64/ instead + # when copied by create_nmf.py. + glibc_tc = "//build/toolchain/nacl:glibc" + assert(current_toolchain == "${glibc_tc}_${target_cpu}") + if (target_cpu == "x64") { + x64_out_dir = root_out_dir + } else { + x64_out_dir = get_label_info(":${target_name}(${glibc_tc}_x64)", + "root_out_dir") + } + nmfflags += [ + "--library-path=" + rebase_path(x64_out_dir, root_build_dir), + "--library-path=" + + rebase_path("${nacl_toolchain_tooldir}/lib", root_build_dir), + ] + data += [ "${lib_path}/lib64/" ] + } + } + } + args = [ + "--no-default-libpath", + "--objdump=" + rebase_path(objdump, root_build_dir), + "--output=" + rebase_path(nmf, root_build_dir), + ] + nmfflags + rebase_path(sources, root_build_dir) + if (is_nacl_glibc && target_cpu == "arm") { + deps += [ "//native_client/src/untrusted/elf_loader:elf_loader" ] + } + } +} + +# Generate a nmf file for Non-SFI tests +# +# Non-SFI tests use a different manifest format from regular Native Client and +# as such requires a different generator. +# +# Variables: +# executable: Non-SFI .nexe executable to generate nmf for +# nmf: the name and the path of the output file +# nmfflags: additional flags for the nmf generator +template("generate_nonsfi_test_nmf") { + assert(defined(invoker.executable), "Must define executable") + assert(defined(invoker.nmf), "Must define nmf") + + action(target_name) { + forward_variables_from(invoker, + [ + "deps", + "data_deps", + "executable", + "nmf", + "testonly", + "public_deps", + "visibility", + ]) + + script = "//ppapi/tests/create_nonsfi_test_nmf.py" + sources = [ executable ] + outputs = [ nmf ] + + # NOTE: We use target_cpu rather than target_cpu on purpose because + # target_cpu is always going to be pnacl for Non-SFI, but the Non-SFI + # .nexe executable is always translated to run on the target machine. + if (target_cpu == "x86") { + arch = "x86-32" + } else if (target_cpu == "x64") { + arch = "x86-64" + } else { + arch = target_cpu + } + args = [ + "--program=" + rebase_path(executable, root_build_dir), + "--arch=${arch}", + "--output=" + rebase_path(nmf, root_build_dir), + ] + if (defined(invoker.nmfflags)) { + args += invoker.nmfflags + } + } +} diff --git a/third_party/libwebrtc/build/config/ozone.gni b/third_party/libwebrtc/build/config/ozone.gni new file mode 100644 index 0000000000..bf6eb78272 --- /dev/null +++ b/third_party/libwebrtc/build/config/ozone.gni @@ -0,0 +1,152 @@ +# Copyright 2020 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. + +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/toolchain/toolchain.gni") + +declare_args() { + # Indicates if Ozone is enabled. Ozone is a low-level library layer for Linux + # that does not require X11. + use_ozone = + is_chromeos || (is_chromecast && !is_android) || is_fuchsia || is_linux || is_bsd +} + +declare_args() { + # Ozone extra platforms file path. Can be overridden to build out of + # tree ozone platforms. + ozone_extra_path = "//build/config/ozone_extra.gni" + + # Select platforms automatically. Turn this off for manual control. + ozone_auto_platforms = use_ozone + + # TODO(petermcneeley): Backwards compatiblity support for VM images. + # Remove when deprecated. (https://crbug.com/1122009) + ozone_platform_gbm = -1 + + # Enable explicit apitrace (https://apitrace.github.io) loading. + # This requires apitrace library with additional bindings. + # See ChromeOS package for details: + # https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/2659419 + # Chrome will not start without an apitrace.so library. + # Trace will be saved to /tmp/gltrace.dat file by default. You can + # override it at run time with TRACE_FILE=<path> environment variable. + enable_opengl_apitrace = false +} + +declare_args() { + # The platform that will used at runtime by default. This can be overridden + # with the command line flag --ozone-platform=<platform>. + ozone_platform = "" + + # Compile the 'cast' platform. + ozone_platform_cast = false + + # Compile the 'drm' platform. + ozone_platform_drm = false + + # Compile the 'headless' platform. + ozone_platform_headless = false + + # Compile the 'scenic' platform. + ozone_platform_scenic = false + + # Compile the 'flatland' platform. + ozone_platform_flatland = false + + # Compile the 'x11' platform. + ozone_platform_x11 = false + + # Compile the 'wayland' platform. + ozone_platform_wayland = false + + # Compile the 'windows' platform. + ozone_platform_windows = false + + if (ozone_auto_platforms) { + # Use headless as the default platform unless modified below. + ozone_platform = "headless" + ozone_platform_headless = true + + if (is_cast_audio_only) { + # Just use headless for audio-only Cast platforms. + } else if (is_chromecast && !is_fuchsia) { + # Enable the Cast ozone platform on all A/V Cast builds except Fuchsia. + ozone_platform_cast = true + + # For visual desktop Chromecast builds, override the default "headless" + # platform with --ozone-platform=x11. + # TODO(halliwell): Create a libcast_graphics implementation for desktop + # using X11, and disable this platform. + if (is_cast_desktop_build && !is_cast_audio_only) { + ozone_platform_x11 = true + } else { + ozone_platform = "cast" + } + } else if (is_chromeos_ash) { + ozone_platform = "x11" + ozone_platform_drm = true + ozone_platform_x11 = true + } else if (is_chromeos_lacros) { + ozone_platform = "wayland" + ozone_platform_wayland = true + } else if (is_linux || is_bsd) { + ozone_platform = "x11" + ozone_platform_wayland = true + ozone_platform_x11 = true + } else if (is_win) { + ozone_platform = "windows" + ozone_platform_windows = true + } else if (is_fuchsia) { + ozone_platform = "scenic" + ozone_platform_scenic = true + ozone_platform_flatland = true + } + } + + # TODO(petermcneeley): Backwards compatiblity support for VM images. + # Remove when deprecated. (https://crbug.com/1122009) + if (ozone_platform_gbm != -1) { + ozone_platform_drm = ozone_platform_gbm + } +} + +declare_args() { + # Deprecated. Ozone/X11 is default path on Linux now. However, there are still + # some components like remoting, angle, webrtc (desktop capture) that relies + # on this gn arg and on the USE_X11 define. This will be gradually removed + # once all the other places are fixed. + # TODO(1096425): remove use_x11. + use_x11 = + ozone_platform_x11 && (is_linux || is_bsd) && !is_chromecast && !is_chromeos_lacros +} + +import(ozone_extra_path) + +_ozone_extra_directory = get_path_info(ozone_extra_path, "dir") + +# Extra paths to add to targets visibility list. +ozone_external_platform_visibility = [ "$_ozone_extra_directory/*" ] + +if (is_a_target_toolchain) { + assert( + use_ozone || !(ozone_platform_cast || ozone_platform_drm || + ozone_platform_flatland || ozone_platform_headless || + ozone_platform_x11 || ozone_platform_wayland || + ozone_platform_windows || ozone_platform_scenic), + "Must set use_ozone to select ozone platforms") +} + +# TODO(petermcneeley): Backwards compatiblity support for VM images. +# Remove when deprecated. (https://crbug.com/1122009) + +assert(ozone_platform_gbm == -1 || ozone_platform_drm == ozone_platform_gbm) + +ozone_platform_gbm = ozone_platform_drm + +if (ozone_platform == "gbm") { + ozone_platform = "drm" +} + +assert(use_x11 == ozone_platform_x11 || !is_linux || !is_bsd || is_chromecast) diff --git a/third_party/libwebrtc/build/config/ozone_extra.gni b/third_party/libwebrtc/build/config/ozone_extra.gni new file mode 100644 index 0000000000..57fa791354 --- /dev/null +++ b/third_party/libwebrtc/build/config/ozone_extra.gni @@ -0,0 +1,24 @@ +# Copyright 2016 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 list contains the name of external platforms that are passed to the +# --ozone-platform command line argument or used for the ozone_platform build +# config. For example ozone_external_platforms = [ "foo1", "foo2", ... ] +ozone_external_platforms = [] + +# This list contains dependencies for external platforms. Typically, the Ozone +# implementations are placed into ui/ozone/platform/ and so this will look +# something like: +# ozone_external_platform_deps = [ "platform/foo1", "platform/foo_2", ... ] +ozone_external_platform_deps = [] + +# If a platform has unit tests, the corresponding source_set can be listed here +# so that they get included into ozone_unittests. +# ozone_external_platform_test_deps = [ "platform/foo1:foo1_unitests", ... ] +ozone_external_platform_test_deps = [] + +# If a platform has test support files for ui, the corresponding source_set can +# be listed here so that they get included into ui_test_support. +# ozone_external_platform_ui_test_support_deps = [ "platform/foo1:ui_test_support", ... ] +ozone_external_platform_ui_test_support_deps = [] diff --git a/third_party/libwebrtc/build/config/pch.gni b/third_party/libwebrtc/build/config/pch.gni new file mode 100644 index 0000000000..efc8a3be36 --- /dev/null +++ b/third_party/libwebrtc/build/config/pch.gni @@ -0,0 +1,15 @@ +# Copyright 2016 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. + +import("//build/toolchain/goma.gni") +import("//build/toolchain/rbe.gni") + +declare_args() { + # Precompiled header file support is by default available, + # but for distributed build system uses (like goma or rbe) or when + # doing official builds. + # On Linux it slows down the build, so don't enable it by default. + enable_precompiled_headers = + !is_official_build && !(use_goma || use_remoteexec) && !is_linux +} diff --git a/third_party/libwebrtc/build/config/posix/BUILD.gn b/third_party/libwebrtc/build/config/posix/BUILD.gn new file mode 100644 index 0000000000..a49254f019 --- /dev/null +++ b/third_party/libwebrtc/build/config/posix/BUILD.gn @@ -0,0 +1,59 @@ +# 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. + +import("//build/config/sysroot.gni") + +# This build configuration is used by both Fuchsia and POSIX systems. +assert(is_posix || is_fuchsia) + +group("posix") { + visibility = [ "//:optimize_gn_gen" ] +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Posix-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + asmflags = [] + cflags = [] + cflags_c = [] + cflags_cc = [] + cflags_objc = [] + cflags_objcc = [] + defines = [] + ldflags = [] + + if (!is_apple && sysroot != "") { + # Pass the sysroot to all C compiler variants, the assembler, and linker. + sysroot_flags = [ "--sysroot=" + rebase_path(sysroot, root_build_dir) ] + if (is_linux || is_chromeos) { + # This is here so that all files get recompiled after a sysroot roll and + # when turning the sysroot on or off. (defines are passed via the command + # line, and build system rebuilds things when their commandline + # changes). Nothing should ever read this define. + sysroot_hash = + exec_script("//build/linux/sysroot_scripts/install-sysroot.py", + [ "--print-hash=$target_cpu" ], + "trim string", + [ "//build/linux/sysroot_scripts/sysroots.json" ]) + defines += [ "CR_SYSROOT_HASH=$sysroot_hash" ] + } + asmflags += sysroot_flags + ldflags += sysroot_flags + + # When use_custom_libcxx=true, some -isystem flags get passed to + # cflags_cc to set up libc++ include paths. We want to make sure + # the sysroot includes take lower precendence than the libc++ + # ones, so they must appear later in the command line. However, + # the gn reference states "These variant-specific versions of + # cflags* will be appended on the compiler command line after + # 'cflags'." Because of this, we must set the sysroot flags for + # all cflags variants instead of using 'cflags' directly. + cflags_c += sysroot_flags + cflags_cc += sysroot_flags + cflags_objc += sysroot_flags + cflags_objcc += sysroot_flags + } +} diff --git a/third_party/libwebrtc/build/config/profiling/OWNERS b/third_party/libwebrtc/build/config/profiling/OWNERS new file mode 100644 index 0000000000..3d69566fd5 --- /dev/null +++ b/third_party/libwebrtc/build/config/profiling/OWNERS @@ -0,0 +1,2 @@ +liaoyuke@chromium.org +sajjadm@chromium.org diff --git a/third_party/libwebrtc/build/config/profiling/profiling.gni b/third_party/libwebrtc/build/config/profiling/profiling.gni new file mode 100644 index 0000000000..9ca3d4aa1b --- /dev/null +++ b/third_party/libwebrtc/build/config/profiling/profiling.gni @@ -0,0 +1,14 @@ +# Copyright 2020 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. + +import("//build/config/compiler/pgo/pgo.gni") +import("//build/config/coverage/coverage.gni") + +declare_args() { + use_clang_profiling = + is_a_target_toolchain && (use_clang_coverage || chrome_pgo_phase == 1) +} + +assert(!use_clang_profiling || is_clang, + "Clang Source-based profiling requires clang.") diff --git a/third_party/libwebrtc/build/config/python.gni b/third_party/libwebrtc/build/config/python.gni new file mode 100644 index 0000000000..2dfb7e9270 --- /dev/null +++ b/third_party/libwebrtc/build/config/python.gni @@ -0,0 +1,161 @@ +# Copyright 2018 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. + +# Creates a group() that lists Python sources as |data|. +# Having such targets serves two purposes: +# 1) Causes files to be included in runtime_deps, so that they are uploaded to +# swarming when running tests remotely. +# 2) Causes "gn analyze" to know about all Python inputs so that tests will be +# re-run when relevant Python files change. +# +# All non-trivial Python scripts should use a "pydeps" file to track their +# sources. To create a .pydep file for a target in //example: +# +# build/print_python_deps.py \ +# --root example \ +# --output example/$target_name.pydeps \ +# path/to/your/script.py +# +# Keep the .pydep file up-to-date by adding to //PRESUBMIT.py under one of: +# _ANDROID_SPECIFIC_PYDEPS_FILES, _GENERIC_PYDEPS_FILES +# +# Variables +# pydeps_file: Path to .pydeps file to read sources from (optional). +# data: Additional files to include in data. E.g. non-.py files needed by the +# library, or .py files that are conditionally / lazily imported. +# +# Example +# python_library("my_library_py") { +# pydeps_file = "my_library.pydeps" +# data = [ "foo.dat" ] +# } +template("python_library") { + group(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "testonly", + "visibility", + ]) + + if (defined(invoker.pydeps_file)) { + # Read and filter out comments. + _pydeps_lines = read_file(invoker.pydeps_file, "list lines") + _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) + + # Dependencies are listed relative to the pydeps file directory, but data + # parameter expects paths that are relative to the current BUILD.gn + _script_dir = get_path_info(invoker.pydeps_file, "dir") + _rebased_pydeps_entries = rebase_path(_pydeps_entries, ".", _script_dir) + + # Even though the .pydep file is not used at runtime, it must be added + # so that "gn analyze" will mark the target as changed when .py files + # are removed but none are added or modified. + data = _rebased_pydeps_entries + [ invoker.pydeps_file ] + } else { + data = [] + } + if (defined(invoker.data)) { + data += invoker.data + } + } +} + +# A template used for actions that execute a Python script, which has an +# associated .pydeps file. In other words: +# +# - This is very similar to just an action(), except that |script| must point +# to a Python script (e.g. "//build/.../foo.py") that has a corresponding +# .pydeps file in the source tree (e.g. "//build/.../foo.pydeps"). +# +# - The .pydeps file contains a list of python dependencies (imports really) +# and is generated _manually_ by using a command like: +# +# build/print_python_deps.py --inplace build/android/gyp/foo.py +# +# Example +# action_with_pydeps("create_foo") { +# script = "myscript.py" +# args = [...] +# } +template("action_with_pydeps") { + action(target_name) { + # Ensure that testonly and visibility are forwarded + # explicitly, since this performs recursive scope lookups, which is + # required to ensure their definition from scopes above the caller are + # properly handled. All other variables are forwarded with "*", which + # doesn't perform recursive lookups at all. See https://crbug.com/862232 + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + forward_variables_from(invoker, + "*", + [ + "testonly", + "visibility", + ]) + + # Read and filter out comments. + # Happens every time the template is instantiated, but benchmarking shows no + # perceivable impact on overall 'gn gen' speed. + _pydeps_file = invoker.script + "deps" + + _pydeps_lines = + read_file(_pydeps_file, "list lines") # https://crbug.com/1102058 + _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) + + if (!defined(inputs)) { + inputs = [] + } + + # Dependencies are listed relative to the script directory, but inputs + # expects paths that are relative to the current BUILD.gn + _script_dir = get_path_info(_pydeps_file, "dir") + inputs += rebase_path(_pydeps_entries, ".", _script_dir) + } +} + +template("action_foreach_with_pydeps") { + action_foreach(target_name) { + # Ensure that testonly and visibility are forwarded + # explicitly, since this performs recursive scope lookups, which is + # required to ensure their definition from scopes above the caller are + # properly handled. All other variables are forwarded with "*", which + # doesn't perform recursive lookups at all. See https://crbug.com/862232 + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + forward_variables_from(invoker, + "*", + [ + "testonly", + "visibility", + ]) + + # Read and filter out comments. + # Happens every time the template is instantiated, but benchmarking shows no + # perceivable impact on overall 'gn gen' speed. + if (defined(invoker.deps_file)) { + _pydeps_file = invoker.deps_file + } else { + _pydeps_file = invoker.script + "deps" + } + _pydeps_lines = read_file(_pydeps_file, "list lines") + _pydeps_entries = filter_exclude(_pydeps_lines, [ "#*" ]) + + if (!defined(inputs)) { + inputs = [] + } + + # Dependencies are listed relative to the script directory, but inputs + # expects paths that are relative to the current BUILD.gn + _script_dir = get_path_info(script, "dir") + inputs += rebase_path(_pydeps_entries, ".", _script_dir) + } +} diff --git a/third_party/libwebrtc/build/config/rts.gni b/third_party/libwebrtc/build/config/rts.gni new file mode 100644 index 0000000000..677b3fa2fe --- /dev/null +++ b/third_party/libwebrtc/build/config/rts.gni @@ -0,0 +1,5 @@ +declare_args() { + # For more info about RTS, please see + # //docs/testing/regression-test-selection.md + use_rts = false +} diff --git a/third_party/libwebrtc/build/config/rust.gni b/third_party/libwebrtc/build/config/rust.gni new file mode 100644 index 0000000000..5ff90e6d19 --- /dev/null +++ b/third_party/libwebrtc/build/config/rust.gni @@ -0,0 +1,138 @@ +# Copyright 2021 The Chromium Project. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chrome_build.gni") +import("//build/config/compiler/compiler.gni") +import("//build/toolchain/toolchain.gni") + +if (is_android) { + import("//build/config/android/config.gni") +} + +declare_args() { + # Whether to allow Rust code to be part of the Chromium *build process*. + # This can be used to create Rust test binaries, even if the flag below + # is false. + enable_rust = false + + # Whether to allow Rust code to contribute to the main Chromium binaries. + enable_rust_in_chromium = false + + # Use unverified, untrusted, Rust toolchains from the internet + # (which support more platforms and options than those we trust for real + # builds). + use_unverified_rust_toolchain = false + + # If using an unverified Rust toolchain, use this prefix for where to find + # the binaries. + rust_bin_dir = "" + + # Use LTO when using rustc to link binaries. Experimental. Currently incompatible + # with the options we use in our C++ toolchain to split LTO units. + # This has no effect on the production of normal Chrome binaries, which are + # linked by clang/lld rather than rustc. + # https://crbug.com/1229419 + use_lto_in_rustc_linking = false + + # Use goma for Rust builds. Experimental. The only known problem is + # b/193072381, but then again, we don't expect a build speedup before much + # more work is done. + use_goma_rust = false +} + +# Rust code may end up being linked into a final executable by: +# * rustc (which calls lld) +# * our pre-existing C++ linker invocations +# At the moment, this first pipeline is incompatible with the ldflags we use +# for thin LTO, due to some problem in escaping gn rules. There's a further +# problem with -lunwind on Android. +# However, Rust code is still useful if it's contributing to our existing +# C++ linker invocations, so this doesn't disable Rust entirely. It does +# disable Rust unit test executables, so we do need to fix this. +# https://crbug.com/1229423 +rustc_can_link = !use_thin_lto && !is_android + +# Has a Rust toolchain available in the build by default. +toolchain_has_official_rust = + (!is_nacl && + (is_android && (target_cpu == "arm" || target_cpu == "arm64" || + target_cpu == "x64" || target_cpu == "x86"))) || + (is_linux && target_cpu == "x64") + +toolchain_has_rust = enable_rust && (toolchain_has_official_rust || + use_unverified_rust_toolchain) + +# We use the Rust linker for building test executables, so we only build them +# if we're able to use the Rust linker. We could use the C++ linker for this +# too, we've just not set up GN to do so at the moment. +build_rust_unit_tests = rustc_can_link + +if (use_unverified_rust_toolchain) { + assert(rust_bin_dir != "") + rust_prefix = "$rust_bin_dir/" +} else if (toolchain_has_official_rust) { + if (host_os != "linux") { +# assert(false, +# "Attempt to use standard Rust toolchain on an unsupported platform") + } + rust_prefix = + rebase_path("//third_party/android_rust_toolchain/toolchain/1.54.0/bin/") +} + +assert(!toolchain_has_rust || defined(rust_prefix)) + +# Figure out the Rust target triple (aka 'rust_abi_target') +# +# This is here rather than in the toolchain files because it's used +# also by //build/rust/std to find the Rust standard library. +# +# The list of architectures supported by Rust is here: +# https://doc.rust-lang.org/nightly/rustc/platform-support.html +# Although most of these are not yet supported by our limited +# official Rust toolchain (see 'toolchain_has_official_rust' above) +# it's useful to be able to experiment with our other platforms, +# so we try to be comprehensive here. +# +# It's OK if rust_abi_target is blank. That means we're building for the host +# and the host stdlib will be used. +rust_abi_target = "" +if (is_android) { + import("//build/config/android/abi.gni") + rust_abi_target = android_abi_target + if (rust_abi_target == "arm-linux-androideabi") { + # Android clang target specifications mostly match Rust, but this + # is an exception + rust_abi_target = "armv7-linux-androideabi" + } +} else if (is_fuchsia) { + if (target_cpu == "arm64") { + rust_abi_target = "aarch64-fuchsia" + } else if (target_cpu == "x64") { + rust_abi_target = "x86_64-fuchsia" + } else { + assert(false, "Architecture not supported") + } +} else if (is_ios) { + if (target_cpu == "arm64") { + rust_abi_target = "aarch64-apple-ios" + } else if (target_cpu == "arm") { + # There's also an armv7s-apple-ios, which targets a more recent ARMv7 + # generation CPU found in later iPhones. We'll go with the older one for + # maximal compatibility. As we come to support all the different platforms + # with Rust, we might want to be more precise here. + rust_abi_target = "armv7-apple-ios" + } else if (target_cpu == "x64") { + rust_abi_target = "x86_64-apple-ios" + } else if (target_cpu == "x86") { + rust_abi_target = "i386-apple-ios" + } else { + assert(false, "Architecture not supported") + } +} + +# Arguments for Rust invocation. +# This is common between gcc/clang, Mac and Windows toolchains so specify once, +# here. This is not the complete command-line: toolchains should add -o +# and probably --emit arguments too. +rustc_common_args = "--crate-name {{crate_name}} {{source}} --crate-type {{crate_type}} {{rustflags}} {{rustdeps}} {{externs}}" diff --git a/third_party/libwebrtc/build/config/sanitizers/BUILD.gn b/third_party/libwebrtc/build/config/sanitizers/BUILD.gn new file mode 100644 index 0000000000..8c31a78085 --- /dev/null +++ b/third_party/libwebrtc/build/config/sanitizers/BUILD.gn @@ -0,0 +1,610 @@ +# Copyright 2014 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. + +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") +import("//build/config/clang/clang.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") +} + +# Contains the dependencies needed for sanitizers to link into executables and +# shared_libraries. +group("deps") { + if (using_sanitizer) { + public_configs = [ + ":sanitizer_options_link_helper", + + # Even when a target removes default_sanitizer_flags, it may be depending + # on a library that did not remove default_sanitizer_flags. Thus, we need + # to add the ldflags here as well as in default_sanitizer_flags. + ":default_sanitizer_ldflags", + ] + deps = [ ":options_sources" ] + if (is_win) { + exe = ".exe" + } else { + exe = "" + } + data = [ + "//tools/valgrind/asan/", + "$clang_base_path/bin/llvm-symbolizer${exe}", + ] + if (use_prebuilt_instrumented_libraries || + use_locally_built_instrumented_libraries) { + deps += [ "//third_party/instrumented_libraries:deps" ] + } + } + if (is_asan) { + # ASAN is supported on iOS but the runtime library depends on the compiler + # used (Chromium version of clang versus Xcode version of clang). Only copy + # the ASAN runtime on iOS if building with Chromium clang. + if (is_win || is_mac || (is_ios && !use_xcode_clang)) { + data_deps = [ ":copy_asan_runtime" ] + } + if (is_mac || (is_ios && !use_xcode_clang)) { + public_deps = [ ":asan_runtime_bundle_data" ] + } + } +} + +assert(!(is_win && is_asan && target_cpu == "x86"), + "ASan is only supported in 64-bit builds on Windows.") + +if ((is_mac || is_win || (is_ios && !use_xcode_clang)) && is_asan) { + if (is_mac) { + _clang_rt_dso_path = "darwin/libclang_rt.asan_osx_dynamic.dylib" + } else if (is_ios) { + _clang_rt_dso_path = "darwin/libclang_rt.asan_iossim_dynamic.dylib" + } else if (is_win && target_cpu == "x64") { + _clang_rt_dso_path = "windows/clang_rt.asan_dynamic-x86_64.dll" + } + + _clang_rt_dso_full_path = + "$clang_base_path/lib/clang/$clang_version/lib/$_clang_rt_dso_path" + + if (!is_ios) { + copy("copy_asan_runtime") { + sources = [ _clang_rt_dso_full_path ] + outputs = [ "$root_out_dir/{{source_file_part}}" ] + } + } else { + # On iOS, the runtime library need to be code signed (adhoc signature) + # starting with Xcode 8, so use an action instead of a copy on iOS. + action("copy_asan_runtime") { + script = "//build/config/ios/codesign.py" + sources = [ _clang_rt_dso_full_path ] + outputs = [ "$root_out_dir/" + get_path_info(sources[0], "file") ] + args = [ + "code-sign-file", + "--identity=" + ios_code_signing_identity, + "--output=" + rebase_path(outputs[0], root_build_dir), + rebase_path(sources[0], root_build_dir), + ] + } + } + + if (is_apple) { + bundle_data("asan_runtime_bundle_data") { + sources = get_target_outputs(":copy_asan_runtime") + outputs = [ "{{bundle_executable_dir}}/{{source_file_part}}" ] + public_deps = [ ":copy_asan_runtime" ] + } + } +} + +config("sanitizer_options_link_helper") { + if (is_apple) { + ldflags = [ "-Wl,-U,_sanitizer_options_link_helper" ] + } else if (!is_win) { + ldflags = [ "-Wl,-u_sanitizer_options_link_helper" ] + } +} + +static_library("options_sources") { + # This is a static_library instead of a source_set, as it shouldn't be + # unconditionally linked into targets. + visibility = [ + ":deps", + "//:gn_visibility", + ] + sources = [ "//build/sanitizers/sanitizer_options.cc" ] + + # Don't compile this target with any sanitizer code. It can be called from + # the sanitizer runtimes, so instrumenting these functions could cause + # recursive calls into the runtime if there is an error. + configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ] + + if (is_asan) { + if (!defined(asan_suppressions_file)) { + asan_suppressions_file = "//build/sanitizers/asan_suppressions.cc" + } + sources += [ asan_suppressions_file ] + } + + if (is_lsan) { + if (!defined(lsan_suppressions_file)) { + lsan_suppressions_file = "//build/sanitizers/lsan_suppressions.cc" + } + sources += [ lsan_suppressions_file ] + } + + if (is_tsan) { + if (!defined(tsan_suppressions_file)) { + tsan_suppressions_file = "//build/sanitizers/tsan_suppressions.cc" + } + sources += [ tsan_suppressions_file ] + } +} + +# Applies linker flags necessary when either :deps or :default_sanitizer_flags +# are used. +config("default_sanitizer_ldflags") { + visibility = [ + ":default_sanitizer_flags", + ":deps", + + # https://crbug.com/360158. + "//tools/ipc_fuzzer/fuzzer:ipc_fuzzer", + ] + + if (is_posix || is_fuchsia) { + ldflags = [] + if (is_asan) { + ldflags += [ "-fsanitize=address" ] + } + if (is_hwasan) { + ldflags += [ "-fsanitize=hwaddress" ] + } + if (is_lsan) { + ldflags += [ "-fsanitize=leak" ] + } + if (is_tsan) { + ldflags += [ "-fsanitize=thread" ] + } + if (is_msan) { + ldflags += [ "-fsanitize=memory" ] + } + if (is_ubsan || is_ubsan_security) { + ldflags += [ "-fsanitize=undefined" ] + } + if (is_ubsan_null) { + ldflags += [ "-fsanitize=null" ] + } + if (is_ubsan_vptr) { + ldflags += [ "-fsanitize=vptr" ] + } + + if (use_sanitizer_coverage) { + if (use_libfuzzer) { + ldflags += [ "-fsanitize=fuzzer-no-link" ] + if (is_mac) { + # TODO(crbug.com/926588): on macOS, dead code stripping does not work + # well with `pc-table` instrumentation enabled by `fuzzer-no-link`. + ldflags += [ "-fno-sanitize-coverage=pc-table" ] + } + } else { + ldflags += [ "-fsanitize-coverage=$sanitizer_coverage_flags" ] + } + } + + if (is_cfi && current_toolchain == default_toolchain) { + ldflags += [ "-fsanitize=cfi-vcall" ] + if (use_cfi_cast) { + ldflags += [ + "-fsanitize=cfi-derived-cast", + "-fsanitize=cfi-unrelated-cast", + ] + } + if (use_cfi_icall) { + ldflags += [ "-fsanitize=cfi-icall" ] + } + if (use_cfi_diag) { + ldflags += [ "-fno-sanitize-trap=cfi" ] + if (use_cfi_recover) { + ldflags += [ "-fsanitize-recover=cfi" ] + } + } + } + } else if (is_win) { + # Windows directly calls link.exe instead of the compiler driver when + # linking. Hence, pass the runtime libraries instead of -fsanitize=address + # or -fsanitize=fuzzer. + if (is_asan && is_component_build) { + # In the static-library build, ASan libraries are different for + # executables and dlls, see link_executable and link_shared_library below. + # This here handles only the component build. + if (target_cpu == "x64") { + # Windows 64-bit. + libs = [ + "clang_rt.asan_dynamic-x86_64.lib", + "clang_rt.asan_dynamic_runtime_thunk-x86_64.lib", + ] + } else { + assert(target_cpu == "x86", "WinASan unsupported architecture") + libs = [ + "clang_rt.asan_dynamic-i386.lib", + "clang_rt.asan_dynamic_runtime_thunk-i386.lib", + ] + } + } + if (use_libfuzzer) { + assert(target_cpu == "x64", "LibFuzzer unsupported architecture") + assert(!is_component_build, + "LibFuzzer only supports non-component builds on Windows") + + # Incremental linking causes padding that messes up SanitizerCoverage. + # Don't do it. + ldflags = [ "/INCREMENTAL:NO" ] + } + } +} + +config("common_sanitizer_flags") { + cflags = [] + + if (using_sanitizer) { + assert(is_clang, "sanitizers only supported with clang") + + # Allow non-default toolchains to enable sanitizers in toolchain_args even + # in official builds. + assert(current_toolchain != default_toolchain || !is_official_build, + "sanitizers not supported in official builds") + + cflags += [ + # Column info in debug data confuses Visual Studio's debugger, so don't + # use this by default. However, clusterfuzz needs it for good + # attribution of reports to CLs, so turn it on there. + "-gcolumn-info", + ] + + # Frame pointers are controlled in //build/config/compiler:default_stack_frames + } +} + +config("asan_flags") { + cflags = [] + if (is_asan) { + cflags += [ "-fsanitize=address" ] + if (is_win) { + if (!defined(asan_win_blocklist_path)) { + asan_win_blocklist_path = + rebase_path("//tools/memory/asan/blocklist_win.txt", root_build_dir) + } + cflags += [ "-fsanitize-ignorelist=$asan_win_blocklist_path" ] + } + } +} + +config("link_executable") { + if (is_asan && is_win && !is_component_build) { + if (target_cpu == "x64") { + ldflags = [ "-wholearchive:clang_rt.asan-x86_64.lib" ] + } else { + assert(target_cpu == "x86", "WinASan unsupported architecture") + ldflags = [ "-wholearchive:clang_rt.asan-i386.lib" ] + } + } +} + +config("link_shared_library") { + if (is_asan && is_win && !is_component_build) { + if (target_cpu == "x64") { + libs = [ "clang_rt.asan_dll_thunk-x86_64.lib" ] + } else { + assert(target_cpu == "x86", "WinASan unsupported architecture") + libs = [ "clang_rt.asan_dll_thunk-i386.lib" ] + } + } +} + +config("cfi_flags") { + cflags = [] + if (is_cfi && current_toolchain == default_toolchain) { + if (!defined(cfi_ignorelist_path)) { + cfi_ignorelist_path = + rebase_path("//tools/cfi/ignores.txt", root_build_dir) + } + cflags += [ + "-fsanitize=cfi-vcall", + "-fsanitize-ignorelist=$cfi_ignorelist_path", + ] + + if (use_cfi_cast) { + cflags += [ + "-fsanitize=cfi-derived-cast", + "-fsanitize=cfi-unrelated-cast", + ] + } + + if (use_cfi_icall) { + cflags += [ "-fsanitize=cfi-icall" ] + } + + if (use_cfi_diag) { + cflags += [ "-fno-sanitize-trap=cfi" ] + if (is_win) { + cflags += [ + "/Oy-", + "/Ob0", + ] + } else { + cflags += [ + "-fno-inline-functions", + "-fno-inline", + "-fno-omit-frame-pointer", + "-O1", + ] + } + if (use_cfi_recover) { + cflags += [ "-fsanitize-recover=cfi" ] + } + } + } +} + +# crbug.com/785442: Fix cfi-icall failures for code that casts pointer argument +# types in function pointer type signatures. +config("cfi_icall_generalize_pointers") { + if (is_clang && is_cfi && use_cfi_icall) { + cflags = [ "-fsanitize-cfi-icall-generalize-pointers" ] + } +} + +config("cfi_icall_disable") { + if (is_clang && is_cfi && use_cfi_icall) { + cflags = [ "-fno-sanitize=cfi-icall" ] + } +} + +config("coverage_flags") { + cflags = [] + if (use_sanitizer_coverage) { + # Used by sandboxing code to allow coverage dump to be written on the disk. + defines = [ "SANITIZER_COVERAGE" ] + + if (use_libfuzzer) { + cflags += [ "-fsanitize=fuzzer-no-link" ] + if (is_mac) { + # TODO(crbug.com/926588): on macOS, dead code stripping does not work + # well with `pc-table` instrumentation enabled by `fuzzer-no-link`. + cflags += [ "-fno-sanitize-coverage=pc-table" ] + } + } else { + cflags += [ + "-fsanitize-coverage=$sanitizer_coverage_flags", + "-mllvm", + "-sanitizer-coverage-prune-blocks=1", + ] + if (target_cpu == "arm") { + # http://crbug.com/517105 + cflags += [ + "-mllvm", + "-sanitizer-coverage-block-threshold=0", + ] + } + } + } +} + +config("hwasan_flags") { + if (is_hwasan) { + asmflags = [ "-fsanitize=hwaddress" ] + cflags = [ "-fsanitize=hwaddress" ] + } +} + +config("lsan_flags") { + if (is_lsan) { + cflags = [ "-fsanitize=leak" ] + } +} + +config("msan_flags") { + if (is_msan) { + assert(is_linux || is_chromeos, + "msan only supported on linux x86_64/ChromeOS") + if (!defined(msan_ignorelist_path)) { + msan_ignorelist_path = + rebase_path("//tools/msan/ignorelist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=memory", + "-fsanitize-memory-track-origins=$msan_track_origins", + "-fsanitize-ignorelist=$msan_ignorelist_path", + ] + } +} + +config("tsan_flags") { + if (is_tsan) { + assert(is_linux || is_chromeos, "tsan only supported on linux x86_64") + if (!defined(tsan_ignorelist_path)) { + tsan_ignorelist_path = + rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir) + } + cflags = [ + "-fsanitize=thread", + "-fsanitize-ignorelist=$tsan_ignorelist_path", + ] + } +} + +config("ubsan_flags") { + cflags = [] + if (is_ubsan) { + if (!defined(ubsan_ignorelist_path)) { + ubsan_ignorelist_path = + rebase_path("//tools/ubsan/ignorelist.txt", root_build_dir) + } + cflags += [ + "-fsanitize=bool", + "-fsanitize=bounds", + "-fsanitize=builtin", + "-fsanitize=float-divide-by-zero", + "-fsanitize=integer-divide-by-zero", + "-fsanitize=null", + "-fsanitize=object-size", + "-fsanitize=return", + "-fsanitize=returns-nonnull-attribute", + "-fsanitize=shift-exponent", + "-fsanitize=signed-integer-overflow", + "-fsanitize=unreachable", + "-fsanitize=vla-bound", + "-fsanitize-ignorelist=$ubsan_ignorelist_path", + ] + + # Chromecast ubsan builds fail to compile with these + # experimental flags, so only add them to non-chromecast ubsan builds. + if (!is_chromecast) { + cflags += [ + # Employ the experimental PBQP register allocator to avoid slow + # compilation on files with too many basic blocks. + # See http://crbug.com/426271. + "-mllvm", + "-regalloc=pbqp", + + # Speculatively use coalescing to slightly improve the code generated + # by PBQP regallocator. May increase compile time. + "-mllvm", + "-pbqp-coalescing", + ] + } + } +} + +config("ubsan_no_recover") { + if (is_ubsan_no_recover) { + cflags = [ "-fno-sanitize-recover=undefined" ] + } +} + +config("ubsan_security_flags") { + if (is_ubsan_security) { + if (!defined(ubsan_security_ignorelist_path)) { + ubsan_security_ignorelist_path = + rebase_path("//tools/ubsan/security_ignorelist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=function", + "-fsanitize=shift", + "-fsanitize=signed-integer-overflow", + "-fsanitize=vla-bound", + "-fsanitize-ignorelist=$ubsan_security_ignorelist_path", + ] + } +} + +config("ubsan_null_flags") { + if (is_ubsan_null) { + cflags = [ "-fsanitize=null" ] + } +} + +config("ubsan_vptr_flags") { + if (is_ubsan_vptr) { + if (!defined(ubsan_vptr_ignorelist_path)) { + ubsan_vptr_ignorelist_path = + rebase_path("//tools/ubsan/vptr_ignorelist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=vptr", + "-fsanitize-ignorelist=$ubsan_vptr_ignorelist_path", + ] + } +} + +config("fuzzing_build_mode") { + if (use_fuzzing_engine && optimize_for_fuzzing) { + defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ] + } +} + +all_sanitizer_configs = [ + ":common_sanitizer_flags", + ":coverage_flags", + ":default_sanitizer_ldflags", + ":asan_flags", + ":cfi_flags", + ":hwasan_flags", + ":lsan_flags", + ":msan_flags", + ":tsan_flags", + ":ubsan_flags", + ":ubsan_no_recover", + ":ubsan_null_flags", + ":ubsan_security_flags", + ":ubsan_vptr_flags", + ":fuzzing_build_mode", +] + +# This config is applied by default to all targets. It sets the compiler flags +# for sanitizer usage, or, if no sanitizer is set, does nothing. +# +# This needs to be in a separate config so that targets can opt out of +# sanitizers (by removing the config) if they desire. Even if a target +# removes this config, executables & shared libraries should still depend on +# :deps if any of their dependencies have not opted out of sanitizers. +# Keep this list in sync with default_sanitizer_flags_but_ubsan_vptr. +config("default_sanitizer_flags") { + configs = all_sanitizer_configs + + if (use_sanitizer_configs_without_instrumentation) { + configs = [] + } +} + +# This config is equivalent to default_sanitizer_flags, but excludes ubsan_vptr. +# This allows to selectively disable ubsan_vptr, when needed. In particular, +# if some third_party code is required to be compiled without rtti, which +# is a requirement for ubsan_vptr. +config("default_sanitizer_flags_but_ubsan_vptr") { + configs = all_sanitizer_configs - [ ":ubsan_vptr_flags" ] + + if (use_sanitizer_configs_without_instrumentation) { + configs = [] + } +} + +config("default_sanitizer_flags_but_coverage") { + configs = all_sanitizer_configs - [ ":coverage_flags" ] + + if (use_sanitizer_configs_without_instrumentation) { + configs = [] + } +} + +# This config is used by parts of code that aren't targeted in fuzzers and +# therefore don't need coverage instrumentation and possibly wont need +# sanitizer instrumentation either. The config also tells the compiler to +# perform additional optimizations on the configured code and ensures that +# linking it to the rest of the binary which is instrumented with sanitizers +# works. The config only does anything if the build is a fuzzing build. +config("not_fuzzed") { + if (use_fuzzing_engine) { + # Since we aren't instrumenting with coverage, code size is less of a + # concern, so use a more aggressive optimization level than + # optimize_for_fuzzing (-O1). When given multiple optimization flags, clang + # obeys the last one, so as long as this flag comes after -O1, it should work. + # Since this config will always be depended on after + # "//build/config/compiler:default_optimization" (which adds -O1 when + # optimize_for_fuzzing is true), -O2 should always be the second flag. Even + # though this sounds fragile, it isn't a big deal if it breaks, since proto + # fuzzers will still work, they will just be slightly slower. + cflags = [ "-O2" ] + + # We need to include this config when we remove default_sanitizer_flags or + # else there will be linking errors. We would remove default_sanitizer_flags + # here as well, but gn doesn't permit this. + if (!is_msan) { + # We don't actually remove sanitization when MSan is being used so there + # is no need to add default_sanitizer_ldflags in that case + configs = [ ":default_sanitizer_ldflags" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/sanitizers/OWNERS b/third_party/libwebrtc/build/config/sanitizers/OWNERS new file mode 100644 index 0000000000..f6a122b518 --- /dev/null +++ b/third_party/libwebrtc/build/config/sanitizers/OWNERS @@ -0,0 +1,3 @@ +inferno@chromium.org +metzman@chromium.org +ochang@chromium.org diff --git a/third_party/libwebrtc/build/config/sanitizers/sanitizers.gni b/third_party/libwebrtc/build/config/sanitizers/sanitizers.gni new file mode 100644 index 0000000000..3bb41df05f --- /dev/null +++ b/third_party/libwebrtc/build/config/sanitizers/sanitizers.gni @@ -0,0 +1,298 @@ +# 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. + +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/profiling/profiling.gni") +import("//build/toolchain/toolchain.gni") + +declare_args() { + # Compile for Address Sanitizer to find memory bugs. + is_asan = false + + # Compile for Hardware-Assisted Address Sanitizer to find memory bugs + # (android/arm64 only). + # See http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html + is_hwasan = false + + # Compile for Leak Sanitizer to find leaks. + is_lsan = false + + # Compile for Memory Sanitizer to find uninitialized reads. + is_msan = false + + # Compile for Thread Sanitizer to find threading bugs. + is_tsan = false + + # Compile for Undefined Behaviour Sanitizer to find various types of + # undefined behaviour (excludes vptr checks). + is_ubsan = false + + # Halt the program if a problem is detected. + is_ubsan_no_recover = false + + # Compile for Undefined Behaviour Sanitizer's null pointer checks. + is_ubsan_null = false + + # Track where uninitialized memory originates from. From fastest to slowest: + # 0 - no tracking, 1 - track only the initial allocation site, 2 - track the + # chain of stores leading from allocation site to use site. + msan_track_origins = 2 + + # Use dynamic libraries instrumented by one of the sanitizers instead of the + # standard system libraries. Set this flag to build the libraries from source. + use_locally_built_instrumented_libraries = false + + # Compile with Control Flow Integrity to protect virtual calls and casts. + # See http://clang.llvm.org/docs/ControlFlowIntegrity.html + # + # TODO(pcc): Remove this flag if/when CFI is enabled in all official builds. + # + # Disable this on linux-chromeos to avoid using ThinLTO there; + # crbug.com/1033839. Similarly, don't use this on ARC builds. + # + # TODO(crbug.com/1159424): Reassess the validity of the next expression. + is_cfi = + is_official_build && + (((target_os == "linux" || is_chromeos_lacros) && target_cpu == "x64") || + ((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device)) + + # Enable checks for indirect function calls via a function pointer. + # TODO(pcc): remove this when we're ready to add these checks by default. + # https://crbug.com/701919 + # + # TODO(crbug.com/1159424): Reassess the validity of the next expression. + use_cfi_icall = (target_os == "linux" || is_chromeos_lacros) && + target_cpu == "x64" && is_official_build + + # Print detailed diagnostics when Control Flow Integrity detects a violation. + use_cfi_diag = false + + # Let Control Flow Integrity continue execution instead of crashing when + # printing diagnostics (use_cfi_diag = true). + use_cfi_recover = false + + # Compile for fuzzing with LLVM LibFuzzer. + # See http://www.chromium.org/developers/testing/libfuzzer + use_libfuzzer = false + + # Compile for fuzzing with AFL. + use_afl = false + + # Compile for fuzzing with an external engine (e.g., Grammarinator). + use_external_fuzzing_engine = false + + # Enables core ubsan security features. Will later be removed once it matches + # is_ubsan. + is_ubsan_security = false + + # Helper variable for testing builds with disabled libfuzzer. + # Not for client use. + disable_libfuzzer = false + + # Optimize for coverage guided fuzzing (balance between speed and number of + # branches). Can be also used to remove non-determinism and other issues. + optimize_for_fuzzing = false + + # Value for -fsanitize-coverage flag. Setting this causes + # use_sanitizer_coverage to be enabled. + # This flag is not used for libFuzzer (use_libfuzzer=true). Instead, we use: + # -fsanitize=fuzzer-no-link + # Default value when unset and use_fuzzing_engine=true: + # trace-pc-guard + # Default value when unset and use_sanitizer_coverage=true: + # trace-pc-guard,indirect-calls + sanitizer_coverage_flags = "" + + # When enabled, only relevant sanitizer defines are set, but compilation + # happens with no extra flags. This is useful when in component build + # enabling sanitizers only in some of the components. + use_sanitizer_configs_without_instrumentation = false + + # When true, seed corpora archives are built. + archive_seed_corpus = true +} + +declare_args() { + # Enable checks for bad casts: derived cast and unrelated cast. + # TODO(krasin): remove this, when we're ready to add these checks by default. + # https://crbug.com/626794 + use_cfi_cast = is_cfi && (is_chromeos_ash || is_chromeos_lacros) + + # Compile for Undefined Behaviour Sanitizer's vptr checks. + is_ubsan_vptr = is_ubsan_security +} + +assert(!is_hwasan || (target_os == "android" && target_cpu == "arm64"), + "HWASan only supported on Android ARM64 builds.") + +# Disable sanitizers for non-target toolchains. +if (!is_a_target_toolchain) { + is_asan = false + is_cfi = false + is_hwasan = false + is_lsan = false + is_msan = false + is_tsan = false + is_ubsan = false + is_ubsan_null = false + is_ubsan_no_recover = false + is_ubsan_security = false + is_ubsan_vptr = false + msan_track_origins = 0 + sanitizer_coverage_flags = "" + use_afl = false + use_cfi_diag = false + use_cfi_recover = false + use_libfuzzer = false + use_locally_built_instrumented_libraries = false + use_sanitizer_coverage = false +} else if (target_cpu != "arm64") { + is_hwasan = false +} + +# Use dynamic libraries instrumented by one of the sanitizers instead of the +# standard system libraries. We have instrumented system libraries for msan, +# which requires them to prevent false positives. +# TODO(thakis): Maybe remove this variable. +use_prebuilt_instrumented_libraries = is_msan + +# Whether we are doing a fuzzer build. Normally this should be checked instead +# of checking "use_libfuzzer || use_afl" because often developers forget to +# check for "use_afl". +use_fuzzing_engine = use_libfuzzer || use_afl || use_external_fuzzing_engine + +# Args that are in turn dependent on other args must be in a separate +# declare_args block. User overrides are only applied at the end of a +# declare_args block. +declare_args() { + # Generates an owners file for each fuzzer test. + # TODO(crbug.com/1194183): Remove this arg when finding OWNERS is faster. + generate_fuzzer_owners = use_fuzzing_engine + + use_sanitizer_coverage = + !use_clang_coverage && + (use_fuzzing_engine || sanitizer_coverage_flags != "") + + # https://crbug.com/1002058: Code coverage works inside the sandbox via the + # help of several helper IPCs. Unfortunately, the sandbox-only path does not + # work well for fuzzing builds. Since fuzzing builds already disable the + # sandbox when dumping coverage, limit the sandbox-only path to non-fuzzing + # builds. + # Everything is IPC on Fuchsia, so this workaround for code coverage inside + # the sandbox does not apply. + use_clang_profiling_inside_sandbox = + use_clang_profiling && !use_fuzzing_engine && !is_fuchsia +} + +if (use_fuzzing_engine && sanitizer_coverage_flags == "") { + sanitizer_coverage_flags = "trace-pc-guard" +} else if (use_sanitizer_coverage && sanitizer_coverage_flags == "") { + sanitizer_coverage_flags = "trace-pc-guard,indirect-calls" +} + +# Whether we are linking against a sanitizer runtime library. Among other +# things, this changes the default symbol level and other settings in order to +# prepare to create stack traces "live" using the sanitizer runtime. +using_sanitizer = is_asan || is_hwasan || is_lsan || is_tsan || is_msan || + is_ubsan || is_ubsan_null || is_ubsan_vptr || + is_ubsan_security || use_sanitizer_coverage || use_cfi_diag + +assert(!using_sanitizer || is_clang, + "Sanitizers (is_*san) require setting is_clang = true in 'gn args'") + +assert(!is_cfi || is_clang, + "is_cfi requires setting is_clang = true in 'gn args'") + +prebuilt_instrumented_libraries_available = + is_msan && (msan_track_origins == 0 || msan_track_origins == 2) + +if (use_libfuzzer && (is_linux || is_chromeos)) { + if (is_asan) { + # We do leak checking with libFuzzer on Linux. Set is_lsan for code that + # relies on LEAK_SANITIZER define to avoid false positives. + is_lsan = true + } +} + +# MSan only links Chrome properly in release builds (brettw -- 9/1/2015). The +# same is possibly true for the other non-ASan sanitizers. But regardless of +# whether it links, one would normally never run a sanitizer in debug mode. +# Running in debug mode probably indicates you forgot to set the "is_debug = +# false" flag in the build args. ASan seems to run fine in debug mode. +# +# If you find a use-case where you want to compile a sanitizer in debug mode +# and have verified it works, ask brettw and we can consider removing it from +# this condition. We may also be able to find another way to enable your case +# without having people accidentally get broken builds by compiling an +# unsupported or unadvisable configurations. +# +# For one-off testing, just comment this assertion out. +assert(!is_debug || !(is_msan || is_ubsan || is_ubsan_null || is_ubsan_vptr), + "Sanitizers should generally be used in release (set is_debug=false).") + +assert(!is_msan || ((is_linux || is_chromeos) && target_cpu == "x64"), + "MSan currently only works on 64-bit Linux and ChromeOS builds.") + +assert(!is_lsan || is_asan, "is_lsan = true requires is_asan = true also.") + +# ASAN build on Windows is not working in debug mode. Intercepting memory +# allocation functions is hard on Windows and not yet implemented in LLVM. +assert(!is_win || !is_debug || !is_asan, + "ASan on Windows doesn't work in debug (set is_debug=false).") + +# libFuzzer targets can fail to build or behave incorrectly when built without +# ASAN on Windows. +assert(!is_win || !use_libfuzzer || is_asan, + "use_libfuzzer on Windows requires setting is_asan = true") + +# Make sure that if we recover on detection (i.e. not crash), diagnostics are +# printed. +assert(!use_cfi_recover || use_cfi_diag, + "Only use CFI recovery together with diagnostics.") + +# TODO(crbug.com/753445): the use_sanitizer_coverage arg is currently +# not supported by the Chromium mac_clang_x64 toolchain on iOS distribution. +# The coverage works with iOS toolchain but it is broken when the mac +# toolchain is used as a secondary one on iOS distribution. E.g., it should be +# possible to build the "net" target for iOS with the sanitizer coverage +# enabled. +assert( + !(use_sanitizer_coverage && is_mac && target_os == "ios"), + "crbug.com/753445: use_sanitizer_coverage=true is not supported by the " + + "Chromium mac_clang_x64 toolchain on iOS distribution. Please set " + + "the argument value to false.") + +# Use these lists of configs to disable instrumenting code that is part of a +# fuzzer, but which isn't being targeted (such as libprotobuf-mutator, *.pb.cc +# and libprotobuf when they are built as part of a proto fuzzer). Adding or +# removing these lists does not have any effect if use_libfuzzer or use_afl are +# not passed as arguments to gn. +not_fuzzed_remove_configs = [] +not_fuzzed_remove_nonasan_configs = [] + +if (use_fuzzing_engine) { + # Removing coverage should always just work. + not_fuzzed_remove_configs += [ "//build/config/coverage:default_coverage" ] + not_fuzzed_remove_nonasan_configs += + [ "//build/config/coverage:default_coverage" ] + + if (!is_msan) { + # Allow sanitizer instrumentation to be removed if we are not using MSan + # since binaries cannot be partially instrumented with MSan. + not_fuzzed_remove_configs += + [ "//build/config/sanitizers:default_sanitizer_flags" ] + + # Certain parts of binaries must be instrumented with ASan if the rest of + # the binary is. For these, only remove non-ASan sanitizer instrumentation. + if (!is_asan) { + not_fuzzed_remove_nonasan_configs += + [ "//build/config/sanitizers:default_sanitizer_flags" ] + + assert(not_fuzzed_remove_nonasan_configs == not_fuzzed_remove_configs) + } + } +} diff --git a/third_party/libwebrtc/build/config/sysroot.gni b/third_party/libwebrtc/build/config/sysroot.gni new file mode 100644 index 0000000000..9d2c828c63 --- /dev/null +++ b/third_party/libwebrtc/build/config/sysroot.gni @@ -0,0 +1,81 @@ +# 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 header file defines the "sysroot" variable which is the absolute path +# of the sysroot. If no sysroot applies, the variable will be an empty string. + +import("//build/config/chrome_build.gni") + +declare_args() { + # The path of the sysroot that is applied when compiling using the target + # toolchain. + target_sysroot = "" + + # The path to directory containing linux sysroot images. + target_sysroot_dir = "//build/linux" + + # The path of the sysroot for the current toolchain. If empty, default + # sysroot is used. + sysroot = "" + + # Controls default is_linux sysroot. If set to true, and sysroot + # is empty, default sysroot is calculated. + use_sysroot = target_cpu == "x86" || target_cpu == "x64" || + target_cpu == "arm" || target_cpu == "arm64" || + target_cpu == "mipsel" || target_cpu == "mips64el" +} + +if (sysroot == "") { + if (current_os == target_os && target_cpu == target_cpu && + target_sysroot != "") { + sysroot = target_sysroot + } else if (is_android) { + import("//build/config/android/config.gni") + + # Android uses unified headers, and thus a single compile time sysroot + sysroot = "$android_toolchain_root/sysroot" + } else if ((is_linux || is_chromeos) && use_sysroot) { + # By default build against a sysroot image downloaded from Cloud Storage + # during gclient runhooks. + if (target_cpu == "x64") { + sysroot = "$target_sysroot_dir/debian_sid_amd64-sysroot" + } else if (target_cpu == "x86") { + sysroot = "$target_sysroot_dir/debian_sid_i386-sysroot" + } else if (target_cpu == "mipsel") { + sysroot = "$target_sysroot_dir/debian_sid_mips-sysroot" + } else if (target_cpu == "mips64el") { + sysroot = "$target_sysroot_dir/debian_sid_mips64el-sysroot" + } else if (target_cpu == "arm") { + sysroot = "$target_sysroot_dir/debian_sid_arm-sysroot" + } else if (target_cpu == "arm64") { + sysroot = "$target_sysroot_dir/debian_sid_arm64-sysroot" + } else { + assert(false, "No linux sysroot for cpu: $target_cpu") + } + + if (sysroot != "") { + _script_arch = target_cpu + if (_script_arch == "x86") { + _script_arch = "i386" + } else if (_script_arch == "x64") { + _script_arch = "amd64" + } + #assert( + # exec_script("//build/dir_exists.py", + # [ rebase_path(sysroot) ], + # "string") == "True", + # "Missing sysroot ($sysroot). To fix, run: build/linux/sysroot_scripts/install-sysroot.py --arch=$_script_arch") + } + } else if (is_mac) { + import("//build/config/mac/mac_sdk.gni") + sysroot = mac_sdk_path + } else if (is_ios) { + import("//build/config/ios/ios_sdk.gni") + sysroot = ios_sdk_path + } else if (is_fuchsia) { + if (target_cpu == "arm64" || target_cpu == "x64") { + sysroot = "//third_party/fuchsia-sdk/sdk/arch/$target_cpu/sysroot" + } + } +} diff --git a/third_party/libwebrtc/build/config/ui.gni b/third_party/libwebrtc/build/config/ui.gni new file mode 100644 index 0000000000..1bcc33e192 --- /dev/null +++ b/third_party/libwebrtc/build/config/ui.gni @@ -0,0 +1,52 @@ +# Copyright 2014 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. + +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# These flags are effectively global. Your feature flag should go near the +# code it controls. Most of these items are here now because they control +# legacy global #defines passed to the compiler (now replaced with generated +# buildflag headers -- see //build/buildflag_header.gni). +# +# These flags are ui-related so should eventually be moved to various places +# in //ui/*. +# +# There is more advice on where to put build flags in the "Build flag" section +# of //build/config/BUILDCONFIG.gn. + +import("//build/config/chromecast_build.gni") +import("//build/config/chromeos/args.gni") +import("//build/config/chromeos/ui_mode.gni") +import("//build/config/ozone.gni") + +declare_args() { + # Indicates if Aura is enabled. Aura is a low-level windowing library, sort + # of a replacement for GDI or GTK. + use_aura = is_win || is_linux || is_chromeos || is_fuchsia +} + +declare_args() { + # True means the UI is built using the "views" framework. + toolkit_views = is_mac || is_win || is_linux || is_chromeos || is_fuchsia + + use_glib = (is_linux || is_bsd) && !is_chromecast +} + +assert(!use_glib || ((is_linux || is_bsd) && !is_chromecast)) + +use_atk = (is_linux || is_bsd) && !is_chromecast && use_glib && + current_toolchain == default_toolchain + +# Whether using Xvfb to provide a display server for a test might be +# necessary. +use_xvfb_in_this_config = + is_linux || (is_chromeos_lacros && !is_chromeos_device) +# +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# See comment at the top. diff --git a/third_party/libwebrtc/build/config/v8_target_cpu.gni b/third_party/libwebrtc/build/config/v8_target_cpu.gni new file mode 100644 index 0000000000..305981f3fa --- /dev/null +++ b/third_party/libwebrtc/build/config/v8_target_cpu.gni @@ -0,0 +1,61 @@ +# Copyright 2016 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. + +import("//build/config/sanitizers/sanitizers.gni") + +declare_args() { + # This arg is used when we want to tell the JIT-generating v8 code + # that we want to have it generate for an architecture that is different + # than the architecture that v8 will actually run on; we then run the + # code under an emulator. For example, we might run v8 on x86, but + # generate arm code and run that under emulation. + # + # This arg is defined here rather than in the v8 project because we want + # some of the common architecture-specific args (like arm_float_abi or + # mips_arch_variant) to be set to their defaults either if the current_cpu + # applies *or* if the v8_current_cpu applies. + # + # As described below, you can also specify the v8_target_cpu to use + # indirectly by specifying a `custom_toolchain` that contains v8_$cpu in the + # name after the normal toolchain. + # + # For example, `gn gen --args="custom_toolchain=...:clang_x64_v8_arm64"` + # is equivalent to setting --args=`v8_target_cpu="arm64"`. Setting + # `custom_toolchain` is more verbose but makes the toolchain that is + # (effectively) being used explicit. + # + # v8_target_cpu can only be used to target one architecture in a build, + # so if you wish to build multiple copies of v8 that are targeting + # different architectures, you will need to do something more + # complicated involving multiple toolchains along the lines of + # custom_toolchain, above. + v8_target_cpu = "" +} + +if (v8_target_cpu == "") { + if (current_toolchain == "//build/toolchain/linux:clang_x64_v8_arm64") { + v8_target_cpu = "arm64" + } else if (current_toolchain == "//build/toolchain/linux:clang_x86_v8_arm") { + v8_target_cpu = "arm" + } else if (current_toolchain == + "//build/toolchain/linux:clang_x86_v8_mips64el") { + v8_target_cpu = "mips64el" + } else if (current_toolchain == + "//build/toolchain/linux:clang_x86_v8_mipsel") { + v8_target_cpu = "mipsel" + } else if (is_msan) { + # If we're running under a sanitizer, if we configure v8 to generate + # code that will be run under a simulator, then the generated code + # also gets the benefits of the sanitizer. + v8_target_cpu = "arm64" + } else { + v8_target_cpu = target_cpu + } +} + +declare_args() { + # This argument is declared here so that it can be overridden in toolchains. + # It should never be explicitly set by the user. + v8_current_cpu = v8_target_cpu +} diff --git a/third_party/libwebrtc/build/config/win/BUILD.gn b/third_party/libwebrtc/build/config/win/BUILD.gn new file mode 100644 index 0000000000..afeea308df --- /dev/null +++ b/third_party/libwebrtc/build/config/win/BUILD.gn @@ -0,0 +1,610 @@ +# 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. + +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/config/win/control_flow_guard.gni") +import("//build/config/win/visual_studio_version.gni") +import("//build/timestamp.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") + +assert(is_win) + +declare_args() { + # Turn this on to have the linker output extra timing information. + win_linker_timing = false + + # possible values for target_winuwp_version: + # "10" - Windows UWP 10 + # "8.1" - Windows RT 8.1 + # "8.0" - Windows RT 8.0 + target_winuwp_version = "10" + + # possible values: + # "app" - Windows Store Applications + # "phone" - Windows Phone Applications + # "system" - Windows Drivers and Tools + # "server" - Windows Server Applications + # "desktop" - Windows Desktop Applications + target_winuwp_family = "app" + + # Set this to use clang-style diagnostics format instead of MSVC-style, which + # is useful in e.g. Emacs compilation mode. + # E.g.: + # Without this, clang emits a diagnostic message like this: + # foo/bar.cc(12,34): error: something went wrong + # and with this switch, clang emits it like this: + # foo/bar.cc:12:34: error: something went wrong + use_clang_diagnostics_format = false +} + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic that is +# Windows-only. +config("compiler") { + if (target_cpu == "x86") { + asmflags = [ + # When /safeseh is specified, the linker will only produce an image if it + # can also produce a table of the image's safe exception handlers. This + # table specifies for the operating system which exception handlers are + # valid for the image. Note that /SAFESEH isn't accepted on the command + # line, only /safeseh. This is only accepted by ml.exe, not ml64.exe. + "/safeseh", + ] + } + + cflags = [ + "/Gy", # Enable function-level linking. + "/FS", # Preserve previous PDB behavior. + "/bigobj", # Some of our files are bigger than the regular limits. + "/utf-8", # Assume UTF-8 by default to avoid code page dependencies. + ] + + if (is_clang) { + cflags += [ "/Zc:twoPhase" ] + } + + # Force C/C++ mode for the given GN detected file type. This is necessary + # for precompiled headers where the same source file is compiled in both + # modes. + cflags_c = [ "/TC" ] + cflags_cc = [ "/TP" ] + + cflags += [ + # Work around crbug.com/526851, bug in VS 2015 RTM compiler. + "/Zc:sizedDealloc-", + ] + + if (is_clang) { + # Required to make the 19041 SDK compatible with clang-cl. + # See https://crbug.com/1089996 issue #2 for details. + cflags += [ "/D__WRL_ENABLE_FUNCTION_STATICS__" ] + + # Tell clang which version of MSVC to emulate. + cflags += [ "-fmsc-version=1916" ] + + if (is_component_build) { + cflags += [ + # Do not export inline member functions. This makes component builds + # faster. This is similar to -fvisibility-inlines-hidden. + "/Zc:dllexportInlines-", + ] + } + + if (target_cpu == "x86") { + cflags += [ "-m32" ] + } else if (target_cpu == "x64") { + cflags += [ "-m64" ] + } else if (target_cpu == "arm64") { + cflags += [ "--target=arm64-windows" ] + } else { + assert(false, "unknown target_cpu " + target_cpu) + } + + # Chrome currently requires SSE3. Clang supports targeting any Intel + # microarchitecture. MSVC only supports a subset of architectures, and the + # next step after SSE2 will be AVX. + if (target_cpu == "x86" || target_cpu == "x64") { + cflags += [ "-msse3" ] + } + + if (exec_script("//build/win/use_ansi_codes.py", [], "trim string") == + "True") { + cflags += [ + # cmd.exe doesn't understand ANSI escape codes by default, + # so only enable them if something emulating them is around. + "-fansi-escape-codes", + ] + } + + if (use_clang_diagnostics_format) { + cflags += [ "/clang:-fdiagnostics-format=clang" ] + } + } + + # Disabled with cc_wrapper because of https://github.com/mozilla/sccache/issues/264 + if (use_lld && !use_thin_lto && (is_clang || !use_goma) && cc_wrapper == "") { + # /Brepro lets the compiler not write the mtime field in the .obj output. + # link.exe /incremental relies on this field to work correctly, but lld + # never looks at this timestamp, so it's safe to pass this flag with + # lld and get more deterministic compiler output in return. + # In LTO builds, the compiler doesn't write .obj files containing mtimes, + # so /Brepro is ignored there. + cflags += [ "/Brepro" ] + } + + ldflags = [] + + if (use_lld) { + # lld defaults to writing the current time in the pe/coff header. + # For build reproducibility, pass an explicit timestamp. See + # build/compute_build_timestamp.py for how the timestamp is chosen. + # (link.exe also writes the current time, but it doesn't have a flag to + # override that behavior.) + ldflags += [ "/TIMESTAMP:" + build_timestamp ] + + # Don't look for libpaths in %LIB%, similar to /X in cflags above. + ldflags += [ "/lldignoreenv" ] + } + + if (!is_debug && !is_component_build) { + # Enable standard linker optimizations like GC (/OPT:REF) and ICF in static + # release builds. + # Release builds always want these optimizations, so enable them explicitly. + ldflags += [ + "/OPT:REF", + "/OPT:ICF", + "/INCREMENTAL:NO", + "/FIXED:NO", + ] + + if (use_lld) { + # String tail merging leads to smaller binaries, but they don't compress + # as well, leading to increased mini_installer size (crbug.com/838449). + ldflags += [ "/OPT:NOLLDTAILMERGE" ] + } + + # TODO(siggi): Is this of any use anymore? + # /PROFILE ensures that the PDB file contains FIXUP information (growing the + # PDB file by about 5%) but does not otherwise alter the output binary. It + # is enabled opportunistically for builds where it is not prohibited (not + # supported when incrementally linking, or using /debug:fastlink). + ldflags += [ "/PROFILE" ] + } + + # arflags apply only to static_libraries. The normal linker configs are only + # set for executable and shared library targets so arflags must be set + # elsewhere. Since this is relatively contained, we just apply them in this + # more general config and they will only have an effect on static libraries. + arflags = [ + # "No public symbols found; archive member will be inaccessible." This + # means that one or more object files in the library can never be + # pulled in to targets that link to this library. It's just a warning that + # the source file is a no-op. + "/ignore:4221", + ] +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Windows-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + cflags = [] + cflags_cc = [] + + # Defines that set up the CRT. + defines = [ + "__STD_C", + "_CRT_RAND_S", + "_CRT_SECURE_NO_DEPRECATE", + "_SCL_SECURE_NO_DEPRECATE", + ] + + # Defines that set up the Windows SDK. + defines += [ + "_ATL_NO_OPENGL", + "_WINDOWS", + "CERT_CHAIN_PARA_HAS_EXTRA_FIELDS", + "PSAPI_VERSION=2", + "WIN32", + "_SECURE_ATL", + ] + + if (current_os == "winuwp") { + # When targeting Windows Runtime, certain compiler/linker flags are + # necessary. + defines += [ + "WINUWP", + "__WRL_NO_DEFAULT_LIB__", + ] + if (target_winuwp_family == "app") { + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PC_APP" ] + } else if (target_winuwp_family == "phone") { + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP" ] + } else if (target_winuwp_family == "system") { + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SYSTEM" ] + } else if (target_winuwp_family == "server") { + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_SERVER" ] + } else { + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ] + } + cflags_cc += [ "/EHsc" ] + + # This warning is given because the linker cannot tell the difference + # between consuming WinRT APIs versus authoring WinRT within static + # libraries as such this warning is always given by the linker. Since + # consuming WinRT APIs within a library is legitimate but authoring + # WinRT APis is not allowed, this warning is disabled to ignore the + # legitimate consumption of WinRT APIs within static library builds. + arflags = [ "/IGNORE:4264" ] + + if (target_winuwp_version == "10") { + defines += [ "WIN10=_WIN32_WINNT_WIN10" ] + } else if (target_winuwp_version == "8.1") { + defines += [ "WIN8_1=_WIN32_WINNT_WINBLUE" ] + } else if (target_winuwp_version == "8.0") { + defines += [ "WIN8=_WIN32_WINNT_WIN8" ] + } + } else { + # When not targeting Windows Runtime, make sure the WINAPI family is set + # to desktop. + defines += [ "WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP" ] + } +} + +# Chromium supports running on Windows 7, but if these constants are set to +# Windows 7, then newer APIs aren't made available by the Windows SDK. +# So we set this to Windows 10 and then are careful to check at runtime +# to only call newer APIs when they're available. +# Some third-party libraries assume that these defines set what version of +# Windows is available at runtime. Targets using these libraries need to +# manually override this config for their compiles. +config("winver") { + defines = [ + "NTDDI_VERSION=0x0A000000", + + # We can't say `=_WIN32_WINNT_WIN10` here because some files do + # `#if WINVER < 0x0600` without including windows.h before, + # and then _WIN32_WINNT_WIN10 isn't yet known to be 0x0A00. + "_WIN32_WINNT=0x0A00", + "WINVER=0x0A00", + ] +} + +# Linker flags for Windows SDK setup, this is applied only to EXEs and DLLs. +config("sdk_link") { + assert(target_cpu == "x64" || target_cpu == "x86" || target_cpu == "arm" || + target_cpu == "arm64", + "Only supports x64, x86, arm and arm64 CPUs") + if (target_cpu == "x64") { + ldflags = [ "/MACHINE:X64" ] + } else if (target_cpu == "x86") { + ldflags = [ + "/MACHINE:X86", + "/SAFESEH", # Not compatible with x64 so use only for x86. + "/largeaddressaware", + ] + } else if (target_cpu == "arm") { + ldflags = [ "/MACHINE:ARM" ] + } else if (target_cpu == "arm64") { + ldflags = [ "/MACHINE:ARM64" ] + } + + vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py", + [ + visual_studio_path, + windows_sdk_path, + visual_studio_runtime_dirs, + current_os, + target_cpu, + "none", + ], + "scope") + + vc_lib_path = vcvars_toolchain_data.vc_lib_path + if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) { + vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path + } + vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path + + lib_dirs = [ + "$vc_lib_um_path", + "$vc_lib_path", + ] + if (defined(vc_lib_atlmfc_path)) { + lib_dirs += [ "$vc_lib_atlmfc_path" ] + } +} + +# This default linker setup is provided separately from the SDK setup so +# targets who want different library configurations can remove this and specify +# their own. +config("common_linker_setup") { + ldflags = [ + "/FIXED:NO", + "/ignore:4199", + "/ignore:4221", + "/NXCOMPAT", + "/DYNAMICBASE", + ] + + if (win_linker_timing) { + ldflags += [ + "/time", + "/verbose:incr", + ] + } +} + +config("default_cfg_compiler") { + # Emit table of address-taken functions for Control-Flow Guard (CFG). + # This is needed to allow functions to be called by code that is built + # with CFG enabled, such as system libraries. + # The CFG guards are only emitted if |win_enable_cfg_guards| is enabled. + if (is_clang) { + if (win_enable_cfg_guards) { + cflags = [ "/guard:cf" ] + } else { + cflags = [ "/guard:cf,nochecks" ] + } + } +} + +# To disable CFG guards for a target, remove the "default_cfg_compiler" +# config, and add "disable_guards_cfg_compiler" config. +config("disable_guards_cfg_compiler") { + # Emit table of address-taken functions for Control-Flow Guard (CFG). + # This is needed to allow functions to be called by code that is built + # with CFG enabled, such as system libraries. + if (is_clang) { + cflags = [ "/guard:cf,nochecks" ] + } +} + +config("cfi_linker") { + # Control Flow Guard (CFG) + # https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx + # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG cannot be + # turned on either. + # ASan and CFG leads to slow process startup. Chromium's test runner uses + # lots of child processes, so this means things are really slow. Disable CFG + # for now. https://crbug.com/846966 + if (!is_debug && !is_asan) { + # Turn on CFG bitmap generation and CFG load config. + ldflags = [ "/guard:cf" ] + } +} + +# This is a superset of all the delayloads needed for chrome.exe, chrome.dll, +# chrome_child.dll, and chrome_elf.dll. The linker will automatically ignore +# anything which is not linked to the binary at all. +# Most of the dlls are simply not required at startup (or at all, depending +# on how the browser is used). The following dlls are interconnected and need to +# be delayloaded together to ensure user32 does not load too early or at all, +# depending on the process type: user32, gdi32, comctl32, comdlg32, cryptui, +# d3d9, dwmapi, imm32, msi, ole32, oleacc, rstrtmgr, shell32, shlwapi, and +# uxtheme. +# There are some exceptions to this list which need to be declared separately. +# Some dlls cannot be delayloaded by chrome_child.dll due to the sandbox +# restrictions that prevent them from being loaded properly. Those dlls are +# specified in the separate config below. +# This config should also be used for any test binary whose goal is to run +# tests with the full browser. +config("delayloads") { + ldflags = [ + "/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll", + "/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll", + "/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll", + "/DELAYLOAD:comctl32.dll", + "/DELAYLOAD:comdlg32.dll", + "/DELAYLOAD:credui.dll", + "/DELAYLOAD:cryptui.dll", + "/DELAYLOAD:d3d11.dll", + "/DELAYLOAD:d3d9.dll", + "/DELAYLOAD:dwmapi.dll", + "/DELAYLOAD:dxgi.dll", + "/DELAYLOAD:dxva2.dll", + "/DELAYLOAD:esent.dll", + "/DELAYLOAD:gdi32.dll", + "/DELAYLOAD:hid.dll", + "/DELAYLOAD:imagehlp.dll", + "/DELAYLOAD:imm32.dll", + "/DELAYLOAD:msi.dll", + "/DELAYLOAD:netapi32.dll", + "/DELAYLOAD:ncrypt.dll", + "/DELAYLOAD:ole32.dll", + "/DELAYLOAD:oleacc.dll", + "/DELAYLOAD:propsys.dll", + "/DELAYLOAD:psapi.dll", + "/DELAYLOAD:rpcrt4.dll", + "/DELAYLOAD:rstrtmgr.dll", + "/DELAYLOAD:setupapi.dll", + "/DELAYLOAD:shell32.dll", + "/DELAYLOAD:shlwapi.dll", + "/DELAYLOAD:urlmon.dll", + "/DELAYLOAD:user32.dll", + "/DELAYLOAD:usp10.dll", + "/DELAYLOAD:uxtheme.dll", + "/DELAYLOAD:wer.dll", + "/DELAYLOAD:wevtapi.dll", + "/DELAYLOAD:wininet.dll", + "/DELAYLOAD:winusb.dll", + "/DELAYLOAD:wsock32.dll", + "/DELAYLOAD:wtsapi32.dll", + ] +} + +config("delayloads_not_for_child_dll") { + ldflags = [ + "/DELAYLOAD:advapi32.dll", + "/DELAYLOAD:crypt32.dll", + "/DELAYLOAD:dbghelp.dll", + "/DELAYLOAD:dhcpcsvc.dll", + "/DELAYLOAD:dwrite.dll", + "/DELAYLOAD:iphlpapi.dll", + "/DELAYLOAD:oleaut32.dll", + "/DELAYLOAD:secur32.dll", + "/DELAYLOAD:uiautomationcore.dll", + "/DELAYLOAD:userenv.dll", + "/DELAYLOAD:winhttp.dll", + "/DELAYLOAD:winmm.dll", + "/DELAYLOAD:winspool.drv", + "/DELAYLOAD:wintrust.dll", + "/DELAYLOAD:ws2_32.dll", + ] +} + +# CRT -------------------------------------------------------------------------- + +# Configures how the runtime library (CRT) is going to be used. +# See https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a reference of +# what each value does. +config("default_crt") { + if (is_component_build) { + # Component mode: dynamic CRT. Since the library is shared, it requires + # exceptions or will give errors about things not matching, so keep + # exceptions on. + configs = [ ":dynamic_crt" ] + } else { + if (current_os == "winuwp") { + # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/ + # contains a details explanation of what is happening with the Windows + # CRT in Visual Studio releases related to Windows store applications. + configs = [ ":dynamic_crt" ] + } else { + # Desktop Windows: static CRT. + configs = [ ":static_crt" ] + } + } +} + +# Use this to force use of the release CRT when building perf-critical build +# tools that need to be fully optimized even in debug builds, for those times +# when the debug CRT is part of the bottleneck. This also avoids *implicitly* +# defining _DEBUG. +config("release_crt") { + if (is_component_build) { + cflags = [ "/MD" ] + + if (use_custom_libcxx) { + # On Windows, including libcpmt[d]/msvcprt[d] explicitly links the C++ + # standard library, which libc++ needs for exception_ptr internals. + ldflags = [ "/DEFAULTLIB:msvcprt.lib" ] + } + } else { + cflags = [ "/MT" ] + if (use_custom_libcxx) { + ldflags = [ "/DEFAULTLIB:libcpmt.lib" ] + } + } +} + +config("dynamic_crt") { + if (is_debug) { + # This pulls in the DLL debug CRT and defines _DEBUG + cflags = [ "/MDd" ] + if (use_custom_libcxx) { + ldflags = [ "/DEFAULTLIB:msvcprtd.lib" ] + } + } else { + cflags = [ "/MD" ] + if (use_custom_libcxx) { + ldflags = [ "/DEFAULTLIB:msvcprt.lib" ] + } + } +} + +config("static_crt") { + if (is_debug) { + # This pulls in the static debug CRT and defines _DEBUG + cflags = [ "/MTd" ] + if (use_custom_libcxx) { + ldflags = [ "/DEFAULTLIB:libcpmtd.lib" ] + } + } else { + cflags = [ "/MT" ] + if (use_custom_libcxx) { + ldflags = [ "/DEFAULTLIB:libcpmt.lib" ] + } + } +} + +# Subsystem -------------------------------------------------------------------- + +# This is appended to the subsystem to specify a minimum version. +if (target_cpu == "x64") { + # The number after the comma is the minimum required OS version. + # 5.02 = Windows Server 2003. + subsystem_version_suffix = ",5.02" +} else if (target_cpu == "arm64") { + # Windows ARM64 requires Windows 10. + subsystem_version_suffix = ",10.0" +} else { + # 5.01 = Windows XP. + subsystem_version_suffix = ",5.01" +} + +config("console") { + ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ] +} +config("windowed") { + ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ] +} + +# Incremental linking ---------------------------------------------------------- + +# Applies incremental linking or not depending on the current configuration. +config("default_incremental_linking") { + # Enable incremental linking for debug builds and all component builds - any + # builds where performance is not job one. + # TODO(thakis): Always turn this on with lld, no reason not to. + if (is_debug || is_component_build) { + ldflags = [ "/INCREMENTAL" ] + if (use_lld) { + # lld doesn't use ilk files and doesn't really have an incremental link + # mode; the only effect of the flag is that the .lib file timestamp isn't + # updated if the .lib doesn't change. + # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise? + # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in + # lld. + ldflags += [ "/OPT:NOREF" ] + } + } else { + ldflags = [ "/INCREMENTAL:NO" ] + } +} + +# Character set ---------------------------------------------------------------- + +# Not including this config means "ansi" (8-bit system codepage). +config("unicode") { + defines = [ + "_UNICODE", + "UNICODE", + ] +} + +# Lean and mean ---------------------------------------------------------------- + +# Some third party code might not compile with WIN32_LEAN_AND_MEAN so we have +# to have a separate config for it. Remove this config from your target to +# get the "bloaty and accommodating" version of windows.h. +config("lean_and_mean") { + defines = [ "WIN32_LEAN_AND_MEAN" ] +} + +# Nominmax -------------------------------------------------------------------- + +# Some third party code defines NOMINMAX before including windows.h, which +# then causes warnings when it's been previously defined on the command line. +# For such targets, this config can be removed. + +config("nominmax") { + defines = [ "NOMINMAX" ] +} diff --git a/third_party/libwebrtc/build/config/win/console_app.gni b/third_party/libwebrtc/build/config/win/console_app.gni new file mode 100644 index 0000000000..cac2ef5d73 --- /dev/null +++ b/third_party/libwebrtc/build/config/win/console_app.gni @@ -0,0 +1,18 @@ +# Copyright 2016 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. + +import("//build/config/sanitizers/sanitizers.gni") + +declare_args() { + # If true, builds as a console app (rather than a windowed app), which allows + # logging to be printed to the user. This will cause a terminal window to pop + # up when the executable is not run from the command line, so should only be + # used for development. Only has an effect on Windows builds. + win_console_app = false +} + +if (is_win && is_asan) { + # AddressSanitizer build should be a console app since it writes to stderr. + win_console_app = true +} diff --git a/third_party/libwebrtc/build/config/win/control_flow_guard.gni b/third_party/libwebrtc/build/config/win/control_flow_guard.gni new file mode 100644 index 0000000000..bf6a82af0c --- /dev/null +++ b/third_party/libwebrtc/build/config/win/control_flow_guard.gni @@ -0,0 +1,23 @@ +# Copyright 2020 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. + +import("//build/config/sanitizers/sanitizers.gni") + +declare_args() { + # Set this to true to enable generation of CFG indirect call dispatch + # guards. + win_enable_cfg_guards = false +} + +if (win_enable_cfg_guards) { + # Control Flow Guard (CFG) + # https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065.aspx + # /DYNAMICBASE (ASLR) is turned off in debug builds, therefore CFG can't be + # turned on either. + # ASan and CFG leads to slow process startup. Chromium's test runner uses + # lots of child processes, so this means things are really slow. Disable CFG + # for now. https://crbug.com/846966 + assert(!is_debug && !is_asan, + "CFG does not work well in debug builds or with ASAN") +} diff --git a/third_party/libwebrtc/build/config/win/manifest.gni b/third_party/libwebrtc/build/config/win/manifest.gni new file mode 100644 index 0000000000..e2115083fe --- /dev/null +++ b/third_party/libwebrtc/build/config/win/manifest.gni @@ -0,0 +1,118 @@ +# 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. + +# HOW MANIFESTS WORK IN THE GN BUILD +# +# Use the windows_manifest template to declare a manifest generation step. +# This will combine all listed .manifest files. To link this manifest, just +# depend on the manifest target from your executable or shared library. +# +# This will define an empty placeholder target on non-Windows platforms so +# the manifest declarations and dependencies do not need to be inside of OS +# conditionals. +# +# A binary can depend on only one manifest target, but the manifest target +# can depend on many individual .manifest files which will be merged. As a +# result, only executables and shared libraries should depend on manifest +# targets. If you want to add a manifest to a component, put the dependency +# behind a "if (is_component_build)" conditional. +# +# Generally you will just want the defaults for the Chrome build. In this case +# the binary should just depend on one of the targets in //build/win/. There +# are also individual manifest files in that directory you can reference via +# the *_manifest variables defined below to pick and choose only some defaults. +# You might combine these with a custom manifest file to get specific behavior. + +# Reference this manifest as a source from windows_manifest targets to get +# the default Chrome OS compatibility list. +default_compatibility_manifest = "//build/win/compatibility.manifest" + +# Reference this manifest as a source from windows_manifest targets to get +# the default Chrome common constrols compatibility. +common_controls_manifest = "//build/win/common_controls.manifest" + +# Reference this manifest to request that Windows not perform any elevation +# when running your program. Otherwise, it might do some autodetection and +# request elevated privileges from the user. This is normally what you want. +as_invoker_manifest = "//build/win/as_invoker.manifest" + +# An alternative to as_invoker_manifest when you want the application to always +# elevate. +require_administrator_manifest = "//build/win/require_administrator.manifest" + +# Request the segment heap. See https://crbug.com/1014701 for details. +declare_args() { + enable_segment_heap = false +} +segment_heap_manifest = "//build/win/segment_heap.manifest" + +# Construct a target to combine the given manifest files into a .rc file. +# +# Variables for the windows_manifest template: +# +# sources: (required) +# List of source .manifest files to add. +# +# deps: (optional) +# visibility: (optional) +# Normal meaning. +# +# Example: +# +# windows_manifest("doom_melon_manifest") { +# sources = [ +# "doom_melon.manifest", # Custom values in here. +# default_compatibility_manifest, # Want the normal OS compat list. +# ] +# } +# +# executable("doom_melon") { +# deps = [ ":doom_melon_manifest" ] +# ... +# } + +if (is_win) { + template("windows_manifest") { + config_name = "${target_name}__config" + source_set_name = target_name + + config(config_name) { + visibility = [ ":$source_set_name" ] + assert(defined(invoker.sources), + "\"sources\" must be defined for a windows_manifest target") + manifests = [] + foreach(i, rebase_path(invoker.sources, root_build_dir)) { + manifests += [ "/manifestinput:" + i ] + } + ldflags = [ + "/manifest:embed", + + # We handle UAC by adding explicit .manifest files instead. + "/manifestuac:no", + ] + manifests + } + + # This source set only exists to add a dep on the invoker's deps and to + # add a public_config that sets ldflags on dependents. + source_set(source_set_name) { + forward_variables_from(invoker, [ "visibility" ]) + public_configs = [ ":$config_name" ] + + # Apply any dependencies from the invoker to this target, since those + # dependencies may have created the input manifest files. + forward_variables_from(invoker, [ "deps" ]) + } + } +} else { + # Make a no-op group on non-Windows platforms so windows_manifest + # instantiations don't need to be inside windows blocks. + template("windows_manifest") { + group(target_name) { + # Prevent unused variable warnings on non-Windows platforms. + assert(invoker.sources != "") + assert(!defined(invoker.deps) || invoker.deps != "") + assert(!defined(invoker.visibility) || invoker.visibility != "") + } + } +} diff --git a/third_party/libwebrtc/build/config/win/visual_studio_version.gni b/third_party/libwebrtc/build/config/win/visual_studio_version.gni new file mode 100644 index 0000000000..80eb0355c4 --- /dev/null +++ b/third_party/libwebrtc/build/config/win/visual_studio_version.gni @@ -0,0 +1,39 @@ +# Copyright 2014 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. + +declare_args() { + # Path to Visual Studio. If empty, the default is used which is to use the + # automatic toolchain in depot_tools. If set, you must also set the + # visual_studio_version and wdk_path. + visual_studio_path = "" + + # Version of Visual Studio pointed to by the visual_studio_path. + # Currently always "2015". + visual_studio_version = "" + + # Directory of the Windows driver kit. If visual_studio_path is empty, this + # will be auto-filled. + wdk_path = "" + + # Full path to the Windows SDK, not including a backslash at the end. + # This value is the default location, override if you have a different + # installation location. + windows_sdk_path = "C:\Program Files (x86)\Windows Kits\10" +} + +if (visual_studio_path == "") { + toolchain_data = + exec_script("../../vs_toolchain.py", [ "get_toolchain_dir" ], "scope") + visual_studio_path = toolchain_data.vs_path + windows_sdk_path = toolchain_data.sdk_path + visual_studio_version = toolchain_data.vs_version + wdk_path = toolchain_data.wdk_dir + visual_studio_runtime_dirs = toolchain_data.runtime_dirs +} else { + assert(visual_studio_version != "", + "You must set the visual_studio_version if you set the path") + assert(wdk_path != "", + "You must set the wdk_path if you set the visual studio path") + visual_studio_runtime_dirs = "" +} diff --git a/third_party/libwebrtc/build/config/x64.gni b/third_party/libwebrtc/build/config/x64.gni new file mode 100644 index 0000000000..eccf417c07 --- /dev/null +++ b/third_party/libwebrtc/build/config/x64.gni @@ -0,0 +1,24 @@ +# Copyright 2019 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. + +# These are primarily relevant in target_cpu == "x64" contexts, where +# X64 code is being compiled. +if (target_cpu == "x64") { + declare_args() { + # The micro architecture of x64 cpu. This will be a string like "haswell" or + # "skylake". An empty string means to use the default architecture which is + # "x86-64". + # CPU options for "x86-64" in GCC can be found at + # https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html + # CPU options for "x86-64" in llvm can be found at + # https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/Support/X86TargetParser.def + x64_arch = "" + } + + if ((is_posix && !is_apple) || is_fuchsia) { + if (x64_arch == "") { + x64_arch = "x86-64" + } + } +} diff --git a/third_party/libwebrtc/build/config/zip.gni b/third_party/libwebrtc/build/config/zip.gni new file mode 100644 index 0000000000..68bc49444c --- /dev/null +++ b/third_party/libwebrtc/build/config/zip.gni @@ -0,0 +1,48 @@ +# Copyright 2014 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. + +import("python.gni") + +# Creates a zip archive of the inputs. +# +# output (required) +# Path to output zip. +# inputs (required) +# List of input files to zip. +# base_dir (optional) +# If provided, the archive paths will be relative to this directory. +# Applies only to |inputs|. +# +# deps, public_deps, data, data_deps, testonly, visibility +# Normal meaning. +template("zip") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + script = "//build/android/gyp/zip.py" + inputs = invoker.inputs + outputs = [ invoker.output ] + + args = [ + "--output", + rebase_path(invoker.output, root_build_dir), + ] + + _rebased_inputs = rebase_path(invoker.inputs, root_build_dir) + args += [ "--input-files=$_rebased_inputs" ] + if (defined(invoker.base_dir)) { + args += [ + "--input-files-base-dir", + rebase_path(invoker.base_dir, root_build_dir), + ] + } + } +} |