diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-08-07 22:45:47 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-08-07 22:45:47 +0200 |
commit | 65e39b7046a29aa299f06285441b62bcf1e4df01 (patch) | |
tree | 2eb012aabb59533b954aa169199733292de336cf /deps/v8/build/config | |
parent | 936cd90b7def6ef7c1e0b80265a9dc77a9ad23c6 (diff) | |
download | android-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.tar.gz android-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.tar.bz2 android-node-v8-65e39b7046a29aa299f06285441b62bcf1e4df01.zip |
Move v8/build into this repository.
Since we need to patch some files, we don't let depot_tools
manage these files anymore.
build.git commit a0b2e3b2708bcf81ec00ac1738b586bcc5e04eea
Diffstat (limited to 'deps/v8/build/config')
122 files changed, 25002 insertions, 0 deletions
diff --git a/deps/v8/build/config/BUILD.gn b/deps/v8/build/config/BUILD.gn new file mode 100644 index 0000000000..6a6b8f8a45 --- /dev/null +++ b/deps/v8/build/config/BUILD.gn @@ -0,0 +1,437 @@ +# 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/allocator.gni") +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") + +declare_args() { + # When set (the default) enables C++ iterator debugging in debug builds. + # Iterator debugging is always off in release builds (technically, this flag + # affects the "debug" config, which is always available but applied by + # default only in debug builds). + # + # 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 +} + +# ============================================== +# 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 (use_allocator != "tcmalloc") { + defines += [ "NO_TCMALLOC" ] + } + if (is_asan || is_hwasan || is_lsan || is_tsan || is_msan) { + defines += [ + "MEMORY_TOOL_REPLACES_ALLOCATOR", + "MEMORY_SANITIZER_INITIAL_SIZE", + ] + } + if (is_asan) { + defines += [ "ADDRESS_SANITIZER" ] + } + if (is_lsan) { + defines += [ "LEAK_SANITIZER" ] + } + if (is_tsan) { + defines += [ + "THREAD_SANITIZER", + "DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1", + "WTF_USE_DYNAMIC_ANNOTATIONS_NOIMPL=1", + ] + } + if (is_msan) { + defines += [ "MEMORY_SANITIZER" ] + } + if (is_ubsan || is_ubsan_null || is_ubsan_vptr || is_ubsan_security) { + defines += [ "UNDEFINED_SANITIZER" ] + } + if (safe_browsing_mode == 1) { + defines += [ "FULL_SAFE_BROWSING" ] + defines += [ "SAFE_BROWSING_CSD" ] + defines += [ "SAFE_BROWSING_DB_LOCAL" ] + } else if (safe_browsing_mode == 2) { + defines += [ "SAFE_BROWSING_DB_REMOTE" ] + } else if (safe_browsing_mode == 3) { + defines += [ "SAFE_BROWSING_DB_LOCAL" ] + } + if (is_official_build) { + defines += [ "OFFICIAL_BUILD" ] + } + if (is_chrome_branded) { + defines += [ "GOOGLE_CHROME_BUILD" ] + } else { + defines += [ "CHROMIUM_BUILD" ] + } + + # ============================================== + # PLEASE DO NOT ADD MORE THINGS TO THIS LIST + # ============================================== + # + # See the comment at the top. +} + +# Debug/release ---------------------------------------------------------------- + +config("debug") { + defines = [ + "_DEBUG", + "DYNAMIC_ANNOTATIONS_ENABLED=1", + "WTF_USE_DYNAMIC_ANNOTATIONS=1", + ] + + if (is_nacl) { + defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ] + } + + if (is_win) { + if (!enable_iterator_debugging) { + # 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 && current_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", + "WTF_USE_DYNAMIC_ANNOTATIONS=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. + libs = [ + "CoreFoundation.framework", + "CoreGraphics.framework", + "CoreText.framework", + "Foundation.framework", + ] + } else if (is_linux) { + 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_win && generate_order_files && !is_nacl) { + public_deps += [ "//tools/cygprofile_win" ] + } + + if (is_fuchsia) { + public_deps += [ "//third_party/fuchsia-sdk:runtime_library" ] + } +} + +# 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 + + # Currently only turn on linker CFI for executables. + configs += [ "//build/config/win:cfi_linker" ] + } 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_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" ] + } else if (is_chromecast) { + configs += [ "//build/config/chromecast:shared_library_config" ] + } else if (is_linux || 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) { + precompiled_source = "//build/precompile.h" + } + } +} diff --git a/deps/v8/build/config/BUILDCONFIG.gn b/deps/v8/build/config/BUILDCONFIG.gn new file mode 100644 index 0000000000..9fea836a46 --- /dev/null +++ b/deps/v8/build/config/BUILDCONFIG.gn @@ -0,0 +1,622 @@ +# 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 + + # Whether we're a traditional desktop unix. + is_desktop_linux = current_os == "linux" + + # Set to true when compiling with the Clang compiler. + is_clang = current_os != "linux" || + (current_cpu != "s390x" && current_cpu != "s390" && + current_cpu != "ppc64" && current_cpu != "ppc" && + current_cpu != "mips" && current_cpu != "mips64") + + # 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/+/master/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") { + 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") { + # 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/mac:ios_clang_$target_cpu" +} else if (target_os == "mac") { + assert(host_os == "mac", "Mac cross-compiles are unsupported.") + _default_toolchain = host_toolchain +} 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 Windows). +# - is_linux is true for desktop Linux and ChromeOS, but not 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 == "chromeos" || current_os == "linux" +is_mac = current_os == "mac" +is_nacl = current_os == "nacl" +is_win = current_os == "win" || current_os == "winuwp" + +is_posix = !is_win && !is_fuchsia + +# ============================================================================= +# SOURCES FILTERS +# ============================================================================= +# +# These patterns filter out platform-specific files when assigning to the +# sources variable. The magic variable |sources_assignment_filter| is applied +# to each assignment or appending to the sources variable and matches are +# automatically removed. +# +# Note that the patterns are NOT regular expressions. Only "*" and "\b" (path +# boundary = end of string or slash) are supported, and the entire string +# must match the pattern (so you need "*.cc" to match all .cc files, for +# example). + +# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call +# below. +sources_assignment_filter = [] + +if (!is_win) { + sources_assignment_filter += [ + "*_win.cc", + "*_win.h", + "*_win_unittest.cc", + "*\bwin/*", + "*.def", + "*.rc", + ] +} +if (!is_mac) { + sources_assignment_filter += [ + "*_mac.h", + "*_mac.cc", + "*_mac.mm", + "*_mac_unittest.h", + "*_mac_unittest.cc", + "*_mac_unittest.mm", + "*\bmac/*", + "*_cocoa.h", + "*_cocoa.cc", + "*_cocoa.mm", + "*_cocoa_unittest.h", + "*_cocoa_unittest.cc", + "*_cocoa_unittest.mm", + "*\bcocoa/*", + ] +} +if (!is_ios) { + sources_assignment_filter += [ + "*_ios.h", + "*_ios.cc", + "*_ios.mm", + "*_ios_unittest.h", + "*_ios_unittest.cc", + "*_ios_unittest.mm", + "*\bios/*", + ] +} +if (!is_mac && !is_ios) { + sources_assignment_filter += [ "*.mm" ] +} +if (!is_linux) { + sources_assignment_filter += [ + "*_linux.h", + "*_linux.cc", + "*_linux_unittest.h", + "*_linux_unittest.cc", + "*\blinux/*", + ] +} +if (!is_android) { + sources_assignment_filter += [ + "*_android.h", + "*_android.cc", + "*_android_unittest.h", + "*_android_unittest.cc", + "*\bandroid/*", + ] +} +if (!is_chromeos) { + sources_assignment_filter += [ + "*_chromeos.h", + "*_chromeos.cc", + "*_chromeos_unittest.h", + "*_chromeos_unittest.cc", + "*\bchromeos/*", + ] +} + +# DO NOT ADD MORE PATTERNS TO THIS LIST, see set_sources_assignment_filter call +# below. + +# Actually save this list. +# +# These patterns are executed for every file in the source tree of every run. +# Therefore, adding more patterns slows down the build for everybody. We should +# only add automatic patterns for configurations affecting hundreds of files +# across many projects in the tree. +# +# Therefore, we only add rules to this list corresponding to platforms on the +# Chromium waterfall. This is not for non-officially-supported platforms +# (FreeBSD, etc.) toolkits, (X11, GTK, etc.), or features. For these cases, +# write a conditional in the target to remove the file(s) from the list when +# your platform/toolkit/feature doesn't apply. +set_sources_assignment_filter(sources_assignment_filter) + +# ============================================================================= +# 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:assembler_debug_dir", + "//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/coverage:default_coverage", + "//build/config/sanitizers:default_sanitizer_flags", +] + +if (is_win) { + default_compiler_configs += [ + "//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_win) { + default_compiler_configs += + [ "//build/config/win:default_cygprofile_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 +} + +# 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 +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_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" ] + } +} + +# Sets default dependencies for executable and shared_library targets. +# +# Variables +# no_default_deps: If true, no standard dependencies will be added. +foreach(_target_type, + [ + "executable", + "loadable_module", + "shared_library", + ]) { + template(_target_type) { + target(_target_type, target_name) { + forward_variables_from(invoker, "*", [ "no_default_deps" ]) + if (!defined(deps)) { + deps = [] + } + if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) { + deps += [ "//build/config:${_target_type}_deps" ] + } + } + } +} + +# ============================================================================== +# 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)) { + # 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) { + # Explicitly forward visibility, implicitly forward everything else. + # Forwarding "*" doesn't recurse into nested scopes (to avoid copying all + # globals into each template invocation), so won't pick up file-scoped + # variables. Normally this isn't too bad, but visibility is commonly + # defined at the file scope. Explicitly forwarding visibility and then + # excluding it from the "*" set works around this problem. + # See http://crbug.com/594610 + forward_variables_from(invoker, [ "visibility" ]) + forward_variables_from(invoker, "*", [ "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/deps/v8/build/config/OWNERS b/deps/v8/build/config/OWNERS new file mode 100644 index 0000000000..082e53e018 --- /dev/null +++ b/deps/v8/build/config/OWNERS @@ -0,0 +1,4 @@ +dpranke@chromium.org +scottmg@chromium.org + +per-file *jumbo*=bratell@opera.com diff --git a/deps/v8/build/config/aix/BUILD.gn b/deps/v8/build/config/aix/BUILD.gn new file mode 100644 index 0000000000..e3f21c39c5 --- /dev/null +++ b/deps/v8/build/config/aix/BUILD.gn @@ -0,0 +1,50 @@ +# 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 = [ + "-std=gnu++11", + "-fno-rtti", + "-fno-exceptions", + "-Wno-narrowing", + "-Wno-non-virtual-dtor", + ] + + ldflags = [ + "-pthread", + "-maix64", + "-Wl,-bbigtoc", + ] +} diff --git a/deps/v8/build/config/allocator.gni b/deps/v8/build/config/allocator.gni new file mode 100644 index 0000000000..52dcc5f101 --- /dev/null +++ b/deps/v8/build/config/allocator.gni @@ -0,0 +1,58 @@ +# 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/sanitizers/sanitizers.gni") + +# Temporarily disable tcmalloc on arm64 linux to get rid of compilation errors. +if (is_android || is_mac || is_ios || is_asan || is_lsan || is_tsan || + is_msan || is_win || is_fuchsia || (is_linux && target_cpu == "arm64")) { + _default_allocator = "none" +} else { + _default_allocator = "tcmalloc" +} + +# The debug CRT on Windows has some debug features that are incompatible with +# the shim. NaCl in particular does seem to link some binaries statically +# against the debug CRT with "is_nacl=false". +if ((is_linux || is_android || is_mac || + (is_win && !is_component_build && !is_debug)) && !is_asan && !is_hwasan && + !is_lsan && !is_tsan && !is_msan) { + _default_use_allocator_shim = true +} else { + _default_use_allocator_shim = false +} + +declare_args() { + # Memory allocator to use. Set to "none" to use default allocator. + use_allocator = _default_allocator + + # Causes all the allocations to be routed via allocator_shim.cc. + use_allocator_shim = _default_use_allocator_shim + + # Partition alloc is included by default except iOS. + use_partition_alloc = !is_ios + + # Use the new tcmalloc. It's relevant only when use_allocator == "tcmalloc". + use_new_tcmalloc = false +} + +if (is_nacl) { + # Turn off the build flag for NaCL builds to minimize confusion, as NaCL + # doesn't support the heap shim. + use_allocator_shim = false +} + +assert(use_allocator == "none" || use_allocator == "tcmalloc") + +assert(!is_win || use_allocator == "none", "Tcmalloc doesn't work on Windows.") +assert(!is_mac || use_allocator == "none", "Tcmalloc doesn't work on macOS.") + +assert( + !use_allocator_shim || is_linux || is_android || is_win || is_mac, + "use_allocator_shim is supported only on Linux, Android, Windows and macOS targets") + +if (is_win && use_allocator_shim) { + assert(!is_component_build, + "The allocator shim doesn't work for the component build on Windows.") +} diff --git a/deps/v8/build/config/android/BUILD.gn b/deps/v8/build/config/android/BUILD.gn new file mode 100644 index 0000000000..b69d42b700 --- /dev/null +++ b/deps/v8/build/config/android/BUILD.gn @@ -0,0 +1,175 @@ +# 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") + +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 (current_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", + ] + + # $compile_api_level corresponds to the API level used for the sysroot path + # calculation in //build/config/android/config.gni + if (current_cpu == "arm") { + abi_target = "arm-linux-androideabi" + compile_api_level = android32_ndk_api_level + } else if (current_cpu == "x86") { + abi_target = "i686-linux-android" + compile_api_level = android32_ndk_api_level + } else if (current_cpu == "arm64") { + abi_target = "aarch64-linux-android" + compile_api_level = android64_ndk_api_level + } else if (current_cpu == "x64") { + # Place holder for x64 support, not tested. + # TODO: Enable clang support for Android x64. http://crbug.com/539781 + abi_target = "x86_64-linux-android" + compile_api_level = android64_ndk_api_level + } else if (current_cpu == "mipsel") { + abi_target = "mipsel-linux-android" + compile_api_level = android32_ndk_api_level + } else if (current_cpu == "mips64el") { + # Place holder for mips64 support, not tested. + abi_target = "mips64el-linux-android" + compile_api_level = android64_ndk_api_level + } else { + assert(false, "Architecture not supported") + } + cflags += [ + "--target=$abi_target", + "-isystem" + + rebase_path("$android_ndk_root/sysroot/usr/include/$abi_target", + root_build_dir), + "-D__ANDROID_API__=$compile_api_level", + ] + ldflags += [ "--target=$abi_target" ] + + # TODO(crbug.com/771171): Remove this define once code that uses it has been + # updated to no longer need it. This is leftover from older Android NDK + # versions. + if (compile_api_level < 20) { + cflags += [ "-DHAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC=1" ] + } + + # 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") { + # NOTE: The libc++ header include paths below are specified in cflags_cc + # rather than include_dirs because they need to come after include_dirs. + # Think of them like system headers, but don't use '-isystem' because the + # arm-linux-androideabi-4.4.3 toolchain (circa Gingerbread) will exhibit + # strange errors. The include ordering here is important; change with + # caution. + cflags_cc = [ "-isystem" + + rebase_path("$android_ndk_root/sources/android/support/include", + root_build_dir) ] + + defines = [ + "__GNU_SOURCE=1", # Necessary for clone(). + "CHROMIUM_CXX_TWEAK_INLINES", # Saves binary size. + ] + ldflags = [ "-nostdlib" ] + lib_dirs = [ android_libcpp_lib_dir ] + + libs = [] + libs += [ "android_support" ] + + # arm builds of libc++ starting in NDK r12 depend on unwind. + if (current_cpu == "arm") { + libs += [ "unwind" ] + } + + # Manually link the libgcc.a that the cross compiler uses. This is + # absolute because the linker will look inside the sysroot if it's not. + libs += [ + rebase_path(android_libgcc_file), + "c", + ] + + if (current_cpu == "arm" && arm_version == 6) { + libs += [ "atomic" ] + } + + if (current_cpu == "mipsel") { + libs += [ "atomic" ] + } + + # TODO(jdduke) Re-enable on mips after resolving linking + # issues with libc++ (crbug.com/456380). + if (current_cpu != "mipsel" && current_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/D50017 lands and gets rolled in. + ldflags = [ "-Wl,-u,__cyg_profile_func_enter_bare" ] + } + } +} diff --git a/deps/v8/build/config/android/OWNERS b/deps/v8/build/config/android/OWNERS new file mode 100644 index 0000000000..74dca6f718 --- /dev/null +++ b/deps/v8/build/config/android/OWNERS @@ -0,0 +1,6 @@ +agrieve@chromium.org +estevenson@chromium.org +digit@chromium.org +wnwen@chromium.org + +# COMPONENT: Build diff --git a/deps/v8/build/config/android/abi.gni b/deps/v8/build/config/android/abi.gni new file mode 100644 index 0000000000..79e98b8a8c --- /dev/null +++ b/deps/v8/build/config/android/abi.gni @@ -0,0 +1,80 @@ +# 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 + + # Builds secondary abi for APKs, supports build 32-bit arch as secondary + # abi in 64-bit Monochrome and WebView. + build_apk_secondary_abi = true +} + +assert(!devtools_instrumentation_dumping || use_order_profiling, + "devtools_instrumentation_dumping requires use_order_profiling") + +if (current_cpu == "x86") { + android_app_abi = "x86" +} else if (current_cpu == "arm") { + import("//build/config/arm.gni") + if (arm_version < 7) { + android_app_abi = "armeabi" + } else { + android_app_abi = "armeabi-v7a" + } +} else if (current_cpu == "mipsel") { + android_app_abi = "mips" +} else if (current_cpu == "x64") { + android_app_abi = "x86_64" +} else if (current_cpu == "arm64") { + android_app_abi = "arm64-v8a" +} else if (current_cpu == "mips64el") { + android_app_abi = "mips64" +} else { + assert(false, "Unknown Android ABI: " + current_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/deps/v8/build/config/android/config.gni b/deps/v8/build/config/android/config.gni new file mode 100644 index 0000000000..a4e230c763 --- /dev/null +++ b/deps/v8/build/config/android/config.gni @@ -0,0 +1,380 @@ +# 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_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 + + # Android API level for 32 bits platforms + android32_ndk_api_level = 16 + + # Android API level for 64 bits platforms + android64_ndk_api_level = 21 + } + + if (enable_chrome_android_internal) { + import("//clank/config.gni") + } else { + import("//build/config/android/sdk.gni") + declare_args() { + # Android SDK release. Currently, only "o_mr1" is publicly supported. + android_sdk_release = default_android_sdk_release + } + } + + if (!defined(extra_chrome_shared_library_configs)) { + extra_chrome_shared_library_configs = [] + } + if (!defined(extra_chrome_shared_library_deps)) { + extra_chrome_shared_library_deps = [] + } + + if (!defined(default_android_ndk_root)) { + default_android_ndk_root = "//third_party/android_ndk" + default_android_ndk_version = "r16" + default_android_ndk_major_version = 16 + } else { + assert(defined(default_android_ndk_version)) + assert(defined(default_android_ndk_major_version)) + } + + if (android_sdk_release == "o_mr1") { + default_android_sdk_root = "//third_party/android_sdk/public" + default_android_sdk_version = 27 + default_android_sdk_build_tools_version = "27.0.3" + default_android_sdk_tools_version_suffix = "-26.0.0-dev" + public_android_sdk = true + } + + if (android_sdk_release == "p") { + default_android_sdk_root = "//third_party/android_sdk/public" + default_android_sdk_version = 28 + default_android_sdk_build_tools_version = "27.0.3" + default_android_sdk_tools_version_suffix = "-26.0.0-dev" + public_android_sdk = true + } + + 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 = "//third_party/android_sdk/public" + default_lint_android_sdk_version = 26 + } + + 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 = "//third_party/android_sdk/public" + } + + 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(system_webview_apk_target)) { + system_webview_apk_target = "//android_webview:system_webview_apk" + } + + 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 + android_sdk_tools_version_suffix = default_android_sdk_tools_version_suffix + + 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 + + # Report Java assert failure on Android. Turning it on will report Java + # assert failure without crash. + report_java_assert = false + + # Mark APKs as android:debuggable="true". + debuggable_apks = !is_official_build + + # Set to false to disable the Errorprone compiler + use_errorprone_java_compiler = true + + # Enables EMMA Java code coverage. Instruments classes during build to + # produce .ec files during runtime + emma_coverage = false + + # EMMA filter string consisting of a list of inclusion/exclusion patterns + # separated with whitespace and/or comma. Only has effect if + # emma_coverage==true + emma_filter = "" + + # Disables process isolation when building _incremental targets. + # Required for Android M+ due to SELinux policies (stronger sandboxing). + disable_incremental_isolated_processes = false + + # Build incremental targets whenever possible. + # Ex. with this arg set to true, the chrome_public_apk target result in + # chrome_public_apk_incremental being built. + incremental_apk_by_default = false + + # 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. + disable_android_lint = false + + # Location of aapt2 binary 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 = + "//third_party/android_build_tools/aapt2/aapt2" + + # Use R8 for Java optimization rather than ProGuard for all targets. R8 is + # already used as the default for public targets. This will evenutally be + # the default. https://crbug.com/908988 + use_r8 = false + + # Checks that proguard flags have not changed (!is_java_debug only). + check_android_configuration = false + + # Enable the chrome build for devices without touchscreens. + notouch_build = false + + # Move Trichrome assets to the shared library APK. This will be removed + # once P builds are no longer supported. https://crbug.com/943637 + trichrome_shared_assets = android_sdk_release == "q" + } + + if (notouch_build && defined(extra_keymappings)) { + keycode_conversion_data_android_path = extra_keymappings + } + + assert(!(check_android_configuration && is_java_debug), + "check_android_configuration only works when proguard is enabled") + + # 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 + } + + # Speed up dexing using dx --incremental. + enable_incremental_dx = is_java_debug + + # Use hashed symbol names to reduce JNI symbol overhead. + use_hashed_jni_names = !is_java_debug + } + + # This should not be used for release builds since dx --incremental is known + # to not produce byte-for-byte identical output. + assert(!(enable_incremental_dx && !is_java_debug)) + + # Path to where selected build variables are written to. + android_build_vars = "$root_build_dir/build_vars.txt" + + # 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_tools = "${android_sdk_root}/tools" + 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" + + # Subdirectories inside android_ndk_root that contain the sysroot for the + # associated platform. + x86_android_sysroot_subdir = + "platforms/android-${android32_ndk_api_level}/arch-x86" + arm_android_sysroot_subdir = + "platforms/android-${android32_ndk_api_level}/arch-arm" + mips_android_sysroot_subdir = + "platforms/android-${android32_ndk_api_level}/arch-mips" + x86_64_android_sysroot_subdir = + "platforms/android-${android64_ndk_api_level}/arch-x86_64" + arm64_android_sysroot_subdir = + "platforms/android-${android64_ndk_api_level}/arch-arm64" + mips64_android_sysroot_subdir = + "platforms/android-${android64_ndk_api_level}/arch-mips64" + + # Toolchain root directory for each build. The actual binaries are inside + # a "bin" directory inside of these. + _android_toolchain_version = "4.9" + _android_toolchain_detailed_version = "4.9.x" + x86_android_toolchain_root = "$android_ndk_root/toolchains/x86-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + arm_android_toolchain_root = "$android_ndk_root/toolchains/arm-linux-androideabi-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + mips_android_toolchain_root = "$android_ndk_root/toolchains/mipsel-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + x86_64_android_toolchain_root = "$android_ndk_root/toolchains/x86_64-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + arm64_android_toolchain_root = "$android_ndk_root/toolchains/aarch64-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + mips64_android_toolchain_root = "$android_ndk_root/toolchains/mips64el-linux-android-${_android_toolchain_version}/prebuilt/${android_host_os}-${android_host_arch}" + + # 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 (current_cpu == "x86") { + android_prebuilt_arch = "android-x86" + _binary_prefix = "i686-linux-android" + android_toolchain_root = "$x86_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/i686-linux-android/${_android_toolchain_detailed_version}/libgcc.a" + } else if (current_cpu == "arm") { + android_prebuilt_arch = "android-arm" + _binary_prefix = "arm-linux-androideabi" + android_toolchain_root = "$arm_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/arm-linux-androideabi/${_android_toolchain_detailed_version}/libgcc.a" + } else if (current_cpu == "mipsel") { + android_prebuilt_arch = "android-mips" + _binary_prefix = "mipsel-linux-android" + android_toolchain_root = "$mips_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/mipsel-linux-android/${_android_toolchain_detailed_version}/libgcc.a" + } else if (current_cpu == "x64") { + android_prebuilt_arch = "android-x86_64" + _binary_prefix = "x86_64-linux-android" + android_toolchain_root = "$x86_64_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/x86_64-linux-android/${_android_toolchain_detailed_version}/libgcc.a" + } else if (current_cpu == "arm64") { + android_prebuilt_arch = "android-arm64" + _binary_prefix = "aarch64-linux-android" + android_toolchain_root = "$arm64_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/aarch64-linux-android/${_android_toolchain_detailed_version}/libgcc.a" + } else if (current_cpu == "mips64el") { + android_prebuilt_arch = "android-mips64" + _binary_prefix = "mips64el-linux-android" + android_toolchain_root = "$mips64_android_toolchain_root" + android_libgcc_file = "$android_toolchain_root/lib/gcc/mips64el-linux-android/${_android_toolchain_detailed_version}/libgcc.a" + } else { + assert(false, "Need android libgcc support for your target 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" + + # Toolchain stuff ------------------------------------------------------------ + + android_libcpp_root = "$android_ndk_root/sources/cxx-stl/llvm-libc++" + + if (android_libcpp_lib_dir == "") { + android_libcpp_lib_dir = "${android_libcpp_root}/libs/${android_app_abi}" + } +} diff --git a/deps/v8/build/config/android/extract_unwind_tables.gni b/deps/v8/build/config/android/extract_unwind_tables.gni new file mode 100644 index 0000000000..2cf9887747 --- /dev/null +++ b/deps/v8/build/config/android/extract_unwind_tables.gni @@ -0,0 +1,56 @@ +# 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) { + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + + _root_dir = "$root_out_dir" + if (build_apk_secondary_abi && 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) { + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + sources = [ + _asset_path, + ] + disable_compression = true + deps = [ + ":$_unwind_action", + ] + } +} diff --git a/deps/v8/build/config/android/internal_rules.gni b/deps/v8/build/config/android/internal_rules.gni new file mode 100644 index 0000000000..264514adaf --- /dev/null +++ b/deps/v8/build/config/android/internal_rules.gni @@ -0,0 +1,3816 @@ +# 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/dcheck_always_on.gni") +import("//build/config/python.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/util/generate_wrapper.gni") +import("//build_overrides/build.gni") +assert(is_android) + +# These identify targets that have .build_config files (except for android_apk, +# java_binary, resource_rewriter, android_app_bundle since we never need to +# depend on these). +_java_target_whitelist = [ + "*:*_java", + "*:*_javalib", + "*:*_java_*", # e.g. java_test_support + "*:java", + "*:junit", + "*:junit_*", + "*:*_junit_*", + "*:*javatests", + "*:*_assets", + "*android*:assets", + "*:*_apk_*resources", + "*android*:resources", + "*:*_resources", + "*:*_grd", + "*:*locale_paks", + "*_bundle_module", + + # TODO(agrieve): Rename targets below to match above patterns. + "*android_webview/glue:glue", +] + +# Targets that match the whitelist but are not actually java targets. +_java_target_blacklist = [ "*:*_unpack_aar" ] + +_default_proguard_jar_path = "//third_party/proguard/lib/proguard.jar" +_r8_path = "//third_party/r8/lib/r8.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 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 + + # Don't need to enforce naming scheme for these targets since we never + # consider them in dependency chains. + if (_type != "android_apk" && _type != "java_binary" && + _type != "resource_rewriter" && _type != "dist_jar" && + _type != "java_annotation_processor" && _type != "dist_aar" && + _type != "android_app_bundle") { + set_sources_assignment_filter(_java_target_whitelist) + _parent_invoker = invoker.invoker + _target_label = + get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain") + sources = [ + _target_label, + ] + if (sources != []) { + set_sources_assignment_filter(_java_target_blacklist) + sources = [] + sources = [ + _target_label, + ] + if (sources != []) { + assert(false, "Invalid java target name: $_target_label") + } + } + sources = [] + } + + 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 = [] + if (defined(invoker.possible_config_deps)) { + foreach(_possible_dep, invoker.possible_config_deps) { + set_sources_assignment_filter(_java_target_whitelist) + _target_label = get_label_info(_possible_dep, "label_no_toolchain") + sources = [ + _target_label, + ] + if (sources == []) { + set_sources_assignment_filter(_java_target_blacklist) + sources = [] + sources = [ + _target_label, + ] + if (sources != []) { + # Put the bug number in the target name so that false-positives + # have a hint in the error message about non-existent dependencies. + deps += [ "$_target_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(_possible_dep, "target_gen_dir") + _dep_name = get_label_info(_possible_dep, "name") + _deps_configs += [ "$_dep_gen_dir/$_dep_name.build_config" ] + } + } + sources = [] + } + } + _rebased_deps_configs = rebase_path(_deps_configs, root_build_dir) + + args = [ + "--type=$_type", + "--depfile", + rebase_path(depfile, root_build_dir), + "--deps-configs=$_rebased_deps_configs", + "--build-config", + rebase_path(invoker.build_config, root_build_dir), + ] + + if (defined(invoker.jar_path)) { + args += [ + "--jar-path", + rebase_path(invoker.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)) { + _processor_configs = [] + foreach(_processor_dep, invoker.annotation_processor_deps) { + _target_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 += [ "$_target_label$build_config_target_suffix" ] + _processor_configs += [ "$_dep_gen_dir/$_dep_name.build_config" ] + } + _rebased_processor_configs = + rebase_path(_processor_configs, root_build_dir) + args += [ "--annotation-processor-configs=$_rebased_processor_configs" ] + } + + if (defined(invoker.dex_path)) { + args += [ + "--dex-path", + rebase_path(invoker.dex_path, root_build_dir), + ] + } + 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" + 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.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.custom_package)) { + args += [ + "--package-name", + invoker.custom_package, + ] + } + if (defined(invoker.r_text)) { + args += [ + "--r-text", + rebase_path(invoker.r_text, root_build_dir), + ] + } + + if (defined(invoker.resource_dirs)) { + resource_dirs = rebase_path(invoker.resource_dirs, root_build_dir) + args += [ "--resource-dirs=$resource_dirs" ] + } + + 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.module_rtxt_path)) { + _rebased_rtxt_path = rebase_path(invoker.module_rtxt_path, root_build_dir) + args += [ "--module-rtxt-path=$_rebased_rtxt_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_whitelist_rtxt_path)) { + args += [ + "--base-whitelist-rtxt-path", + rebase_path(invoker.base_whitelist_rtxt_path, root_build_dir), + ] + } + + if (defined(invoker.loadable_modules) && invoker.loadable_modules != []) { + _rebased_modules = rebase_path(invoker.loadable_modules, root_build_dir) + args += [ "--native-libs=$_rebased_modules" ] + } + + if (defined(invoker.extra_shared_libraries)) { + _rebased_extra_shared_libraries = + rebase_path(invoker.extra_shared_libraries, root_build_dir) + args += [ "--native-libs=$_rebased_extra_shared_libraries" ] + } + + 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_modules = + rebase_path(invoker.secondary_abi_loadable_modules, root_build_dir) + args += [ "--secondary-native-libs=$_rebased_secondary_abi_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.apk_path)) { + _rebased_apk_path = rebase_path(invoker.apk_path, root_build_dir) + _incremental_allowed = + defined(invoker.incremental_allowed) && invoker.incremental_allowed + args += [ "--apk-path=$_rebased_apk_path" ] + if (_incremental_allowed) { + _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.classpath_deps)) { + _classpath_deps_configs = [] + foreach(d, invoker.classpath_deps) { + _target_label = get_label_info(d, "label_no_toolchain") + deps += [ "$_target_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(d, "target_gen_dir") + _dep_name = get_label_info(d, "name") + _classpath_deps_configs += [ "$_dep_gen_dir/$_dep_name.build_config" ] + } + _rebased_classpath_deps_configs = + rebase_path(_classpath_deps_configs, root_build_dir) + args += [ "--classpath-deps-configs=$_rebased_classpath_deps_configs" ] + } + 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.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.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(d, invoker.static_library_dependent_targets) { + _target_label = get_label_info(d, "label_no_toolchain") + deps += [ "$_target_label$build_config_target_suffix" ] + _dep_gen_dir = get_label_info(d, "target_gen_dir") + _dep_name = get_label_info(d, "name") + _dependent_configs += [ "$_dep_gen_dir/$_dep_name.build_config" ] + } + _rebased_depdent_configs = rebase_path(_dependent_configs, root_build_dir) + args += [ "--static-library-dependent-configs=$_rebased_depdent_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)) { + _target_label = + get_label_info(invoker.base_module_target, "label_no_toolchain") + _dep_gen_dir = get_label_info(_target_label, "target_gen_dir") + _dep_name = get_label_info(_target_label, "name") + deps += [ "$_target_label$build_config_target_suffix" ] + args += [ + "--base-module-build-config", + rebase_path("$_dep_gen_dir/$_dep_name.build_config", root_build_dir), + ] + } + 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: " + get_label_info(":$target_name", "label_with_toolchain"), + "default_toolchain: $default_toolchain", + ] + args += [ "--fail=$_msg" ] + } + } +} + +# 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. +# +template("copy_ex") { + set_sources_assignment_filter([]) + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data", + "deps", + "outputs", + "testonly", + "visibility", + ]) + sources = [] + if (defined(invoker.sources)) { + sources += invoker.sources + } + 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 + rebased_renaming_sources = + rebase_path(invoker.renaming_sources, root_build_dir) + args += [ "--renaming-sources=$rebased_renaming_sources" ] + + renaming_destinations = invoker.renaming_destinations + args += [ "--renaming-destinations=$renaming_destinations" ] + } + } +} + +template("generate_android_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, "*") + 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", + ] + } +} + +# 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_install = + defined(invoker.incremental_install) && invoker.incremental_install + + _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 + } + } + + generate_android_wrapper(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + ]) + if (!defined(deps)) { + deps = [] + } + + if (!defined(data_deps)) { + data_deps = [] + } + + if (defined(android_test_runner_script)) { + executable = android_test_runner_script + } else { + executable = "//build/android/test_runner.py" + } + testonly = true + + data_deps += [ + "//build/android:test_runner_py", + "//build/android:logdog_wrapper_py", + ] + + data = [] + + executable_args = [ + _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" + _rebased_apk_build_config = rebase_path(_apk_build_config, root_build_dir) + assert(_rebased_apk_build_config != "") # Mark as used. + } 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, + ] + } else if (_test_type == "instrumentation") { + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))" + if (_incremental_install) { + _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)) { + 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" + _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:apk_path))" + if (_incremental_install) { + _apk_under_test = "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path))" + } + executable_args += [ + "--apk-under-test", + _apk_under_test, + ] + } + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) { + executable_args += [ "--enable-java-deobfuscation" ] + } + if (emma_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, + ] + if (defined(invoker.android_manifest_path)) { + _rebased_android_manifest_path = + rebase_path(invoker.android_manifest_path, root_build_dir) + executable_args += [ + "--android-manifest-path", + "@WrappedPath(${_rebased_android_manifest_path})", + ] + } else if (defined(invoker.package_name)) { + executable_args += [ + "--package-name", + invoker.package_name, + ] + } else { + assert(false, "Must specify a package_name or android_manifest_path") + } + + deps += [ ":${invoker.test_suite}$build_config_target_suffix" ] + _junit_binary_build_config = + "${target_gen_dir}/${invoker.test_suite}.build_config" + _rebased_build_config = + rebase_path("$_junit_binary_build_config", root_build_dir) + executable_args += [ "@WrappedPathList(--resource-zip, @FileArg($_rebased_build_config:resources:dependency_zips))" ] + + _rebased_robolectric_runtime_deps_dir = + rebase_path("$root_build_dir/lib.java/third_party/robolectric", + root_build_dir) + executable_args += [ + "--robolectric-runtime-deps-dir", + "@WrappedPath(${_rebased_robolectric_runtime_deps_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" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + executable_args += [ + "--additional-apk", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", + "--additional-apk-incremental", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:incremental_apk_path))", + ] + } + } + if (defined(invoker.shard_timeout)) { + executable_args += [ "--shard-timeout=${invoker.shard_timeout}" ] + } + if (_incremental_install) { + 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.generated_script)) { + assert(_test_name != "" || true) # Mark _test_name as used. + wrapper_script = invoker.generated_script + } else { + wrapper_script = "$root_build_dir/bin/run_${_test_name}" + } + } +} + +template("stack_script") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + if (!defined(data_deps)) { + data_deps = [] + } + + data_deps += + [ "//third_party/android_platform/development/scripts:stack_py" ] + + script = "//build/android/gyp/create_stack_script.py" + + _stack_target_name = invoker.stack_target_name + _stack_script = "//third_party/android_platform/development/scripts/stack" + + _generated_script = "$root_build_dir/bin/stack_${_stack_target_name}" + + outputs = [ + _generated_script, + ] + data = [ + _generated_script, + ] + + args = [ + "--output-directory", + rebase_path(root_build_dir, root_build_dir), + "--script-path", + rebase_path(_stack_script, root_build_dir), + "--script-output-path", + rebase_path(_generated_script, root_build_dir), + "--arch=$target_cpu", + ] + if (defined(invoker.packed_libraries)) { + args += [ + "--packed-libs", + invoker.packed_libraries, + ] + } + } +} + +if (enable_java_templates) { + android_sdk_jar = "$android_sdk/android.jar" + android_default_aapt_path = "$android_sdk_build_tools/aapt" + + template("android_lint") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "data_deps", + "public_deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + if (defined(invoker.srcjar_deps)) { + deps += invoker.srcjar_deps + } + + if (defined(invoker.lint_suppressions_file)) { + lint_suppressions_file = invoker.lint_suppressions_file + } else if (!defined(lint_suppressions_file)) { + lint_suppressions_file = "//build/android/lint/suppressions.xml" + } + + _lint_path = "$lint_android_sdk_root/tools-lint/bin/lint" + _cache_dir = "$root_build_dir/android_lint_cache" + _result_path = "$target_gen_dir/$target_name/result.xml" + _config_path = "$target_gen_dir/$target_name/config.xml" + _suppressions_file = lint_suppressions_file + _platform_xml_path = + "${android_sdk_root}/platform-tools/api/api-versions.xml" + + script = "//build/android/gyp/lint.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [ + _platform_xml_path, + _suppressions_file, + ] + + outputs = [ + _result_path, + _config_path, + ] + + args = [ + "--lint-path", + rebase_path(_lint_path, root_build_dir), + "--cache-dir", + rebase_path(_cache_dir, root_build_dir), + "--platform-xml-path", + rebase_path(_platform_xml_path, root_build_dir), + "--android-sdk-version=${lint_android_sdk_version}", + "--depfile", + rebase_path(depfile, root_build_dir), + "--config-path", + rebase_path(_suppressions_file, root_build_dir), + "--product-dir=.", + "--processed-config-path", + rebase_path(_config_path, root_build_dir), + "--result-path", + rebase_path(_result_path, root_build_dir), + "--include-unexpected-failures", + ] + if (defined(invoker.android_manifest)) { + inputs += [ invoker.android_manifest ] + args += [ + "--manifest-path", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + + if (defined(invoker.disable)) { + args += [ "--disable=${invoker.disable}" ] + } + + if (defined(invoker.create_cache) && invoker.create_cache) { + args += [ + "--create-cache", + "--silent", + ] + } else { + inputs += invoker.java_files + inputs += [ invoker.build_config ] + if (invoker.java_files != []) { + inputs += [ invoker.java_sources_file ] + _rebased_java_sources_file = + rebase_path(invoker.java_sources_file, root_build_dir) + args += [ "--java-sources-file=$_rebased_java_sources_file" ] + } + deps += [ "//build/android:prepare_android_lint_cache" ] + + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + args += [ + "--srcjars=@FileArg($_rebased_build_config:gradle:bundled_srcjars)", + "--can-fail-build", + ] + if (invoker.requires_android) { + args += [ + "--resource-sources=@FileArg($_rebased_build_config:deps_info:owned_resources_dirs)", + "--resource-sources=@FileArg($_rebased_build_config:deps_info:owned_resources_zips)", + ] + } + } + } + } + + template("proguard") { + action_with_pydeps(target_name) { + set_sources_assignment_filter([]) + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "public_deps", + "testonly", + ]) + script = "//build/android/gyp/proguard.py" + + # http://crbug.com/725224. Fix for bots running out of memory. + pool = "//build/toolchain:link_pool($default_toolchain)" + + _output_path = invoker.output_path + inputs = [ + invoker.build_config, + ] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + _mapping_path = "$_output_path.mapping" + if (defined(invoker.proguard_mapping_path)) { + _mapping_path = invoker.proguard_mapping_path + } + depfile = "${target_gen_dir}/${target_name}.d" + outputs = [ + _output_path, + _mapping_path, + ] + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--output-path", + rebase_path(_output_path, root_build_dir), + "--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)", + ] + + if (defined(invoker.config_output_path)) { + _config_output_path = invoker.config_output_path + outputs += [ _config_output_path ] + args += [ + "--output-config", + rebase_path(_config_output_path, root_build_dir), + ] + + if (defined(invoker.proguard_expectations_file)) { + _expected_configs_file = invoker.proguard_expectations_file + inputs += [ _expected_configs_file ] + args += [ + "--expected-configs-file", + rebase_path(_expected_configs_file, root_build_dir), + ] + if (check_android_configuration) { + args += [ "--verify-expected-configs" ] + } + } + } + + if (!defined(invoker.proguard_jar_path) || use_r8) { + if (defined(invoker.proguard_jar_path)) { + not_needed(invoker, [ "proguard_jar_path" ]) + } + args += [ + "--r8-path", + rebase_path(_r8_path, root_build_dir), + ] + inputs += [ _r8_path ] + } else { + _proguard_jar_path = invoker.proguard_jar_path + args += [ + "--proguard-path", + rebase_path(_proguard_jar_path, root_build_dir), + ] + inputs += [ _proguard_jar_path ] + } + + if (defined(invoker.args)) { + args += invoker.args + } + } + } + + # 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 for the jar (contains classpath). + # jar_path: Optional. First classpath entry to be inserted before + # the classpath extracted from the build_config. + # script_name: Name of the script to generate. + # wrapper_script_args: List of extra arguments to pass to the executable. + # bootclasspath: Optional. list of zip/jar file paths to add to the boot + # class path when the script will invoke javac. + # + template("java_binary_script") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + + _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, + ] + if (defined(invoker.jar_path)) { + _jar_path_list = [ rebase_path(invoker.jar_path, root_build_dir) ] + args += [ "--classpath=$_jar_path_list" ] + } + args += [ "--classpath=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)" ] + + if (emma_coverage) { + args += [ + "--classpath", + rebase_path("//third_party/android_sdk/public/tools/lib/emma.jar", + root_build_dir), + "--noverify", + ] + } + if (defined(invoker.wrapper_script_args)) { + args += [ "--" ] + invoker.wrapper_script_args + } + if (defined(invoker.bootclasspath)) { + args += [ + "--bootclasspath", + rebase_path(invoker.bootclasspath, root_build_dir), + ] + } + } + } + + template("dex") { + assert(defined(invoker.output)) + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + _proguarding_with_r8 = + _proguard_enabled && (!defined(invoker.proguard_jar_path) || use_r8) + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + _enable_main_dex_list = + _enable_multidex && + (!defined(invoker.min_sdk_version) || invoker.min_sdk_version < 21) + if (!_enable_main_dex_list) { + if (defined(invoker.negative_main_dex_globs)) { + not_needed(invoker, [ "negative_main_dex_globs" ]) + } + } + + assert(!(defined(invoker.input_jars) && _proguard_enabled), + "input_jars can't be specified when proguarding a dex.") + + if (_enable_main_dex_list) { + _main_dex_rules = "//build/android/main_dex_classes.flags" + } + + if (!_proguarding_with_r8) { + _dexing_jars = [] + if (defined(invoker.input_jars)) { + _dexing_jars += invoker.input_jars + } + } + + if (_proguard_enabled) { + if (_proguarding_with_r8) { + _proguard_output_path = invoker.output + _proguard_target_name = target_name + _proguard_config_output_path = "$_proguard_output_path.proguard_flags" + } else { + _proguard_output_path = invoker.output + ".proguard.jar" + _proguard_target_name = "${target_name}__proguard" + _dexing_jars += [ _proguard_output_path ] + } + + proguard(_proguard_target_name) { + forward_variables_from(invoker, + [ + "build_config", + "deps", + "proguard_expectations_file", + "proguard_jar_path", + "proguard_mapping_path", + "testonly", + ]) + inputs = [] + if (defined(invoker.inputs)) { + inputs += invoker.inputs + } + if (defined(invoker.proguard_configs)) { + inputs += invoker.proguard_configs + } + + _rebased_build_config = rebase_path(build_config, root_build_dir) + args = [ + "--proguard-configs=@FileArg($_rebased_build_config:deps_info:proguard_all_configs)", + "--input-paths=@FileArg($_rebased_build_config:deps_info:java_runtime_classpath)", + ] + if (defined(invoker.proguard_config_exclusions)) { + _rebased_proguard_config_exclusions = + rebase_path(invoker.proguard_config_exclusions, root_build_dir) + args += [ + "--proguard-config-exclusions=$_rebased_proguard_config_exclusions", + ] + } + if (defined(invoker.proguard_args)) { + args += invoker.proguard_args + } + + if (defined(invoker.repackage_classes)) { + args += [ + "--repackage-classes", + "${invoker.repackage_classes}", + ] + } + + if (defined(invoker.min_sdk_version)) { + args += [ + "--min-api", + "${invoker.min_sdk_version}", + ] + } + + if (_enable_multidex && _proguarding_with_r8) { + 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 ] + } else { + if (defined(invoker.extra_main_dex_proguard_config)) { + not_needed(invoker, [ "extra_main_dex_proguard_config" ]) + } + } + } + + output_path = _proguard_output_path + if (_proguarding_with_r8) { + config_output_path = _proguard_config_output_path + } + } + } + + if (!_proguarding_with_r8) { + if (_enable_main_dex_list) { + _main_dex_list_path = invoker.output + ".main_dex_list" + _main_dex_list_target_name = "${target_name}__main_dex_list" + action_with_pydeps(_main_dex_list_target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + + script = "//build/android/gyp/main_dex_list.py" + depfile = "$target_gen_dir/$target_name.d" + + # http://crbug.com/725224. Fix for bots running out of memory. + pool = "//build/toolchain:link_pool($default_toolchain)" + + if (defined(invoker.proguard_jar_path)) { + _proguard_jar_path = invoker.proguard_jar_path + } else { + _proguard_jar_path = _default_proguard_jar_path + } + + _shrinked_android = "$android_sdk_build_tools/lib/shrinkedAndroid.jar" + _dx = "$android_sdk_build_tools/lib/dx.jar" + inputs = [ + _main_dex_rules, + _dx, + _proguard_jar_path, + _shrinked_android, + ] + + outputs = [ + _main_dex_list_path, + ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--dx-path", + rebase_path(_dx, root_build_dir), + "--shrinked-android-path", + rebase_path(_shrinked_android, root_build_dir), + "--main-dex-list-path", + rebase_path(_main_dex_list_path, root_build_dir), + "--main-dex-rules-path", + rebase_path(_main_dex_rules, root_build_dir), + "--proguard-path", + rebase_path(_proguard_jar_path, root_build_dir), + ] + + if (defined(invoker.extra_main_dex_proguard_config)) { + inputs += [ invoker.extra_main_dex_proguard_config ] + args += [ + "--main-dex-rules-path", + rebase_path(invoker.extra_main_dex_proguard_config, + root_build_dir), + ] + } + + if (_proguard_enabled) { + deps += [ ":${_proguard_target_name}" ] + } + + if (defined(invoker.negative_main_dex_globs)) { + args += [ + "--negative-main-dex-globs=${invoker.negative_main_dex_globs}", + ] + } + + if (defined(invoker.input_jar_classpath)) { + inputs += [ invoker.build_config ] + args += [ "--inputs=@FileArg(${invoker.input_jar_classpath})" ] + } + + inputs += _dexing_jars + if (_dexing_jars != []) { + args += rebase_path(_dexing_jars, root_build_dir) + } + } + } + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + script = "//build/android/gyp/dex.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [] + outputs = [ + invoker.output, + ] + + _rebased_output = rebase_path(invoker.output, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--dex-path", + _rebased_output, + ] + + if (_proguard_enabled) { + deps += [ ":${_proguard_target_name}" ] + } + + if (_enable_multidex) { + args += [ "--multi-dex" ] + if (_enable_main_dex_list) { + args += [ + "--main-dex-list-path", + rebase_path(_main_dex_list_path, root_build_dir), + ] + deps += [ ":${_main_dex_list_target_name}" ] + inputs += [ _main_dex_list_path ] + } + } + + if (defined(invoker.input_dex_classpath)) { + inputs += [ invoker.build_config ] + args += [ "--inputs=@FileArg(${invoker.input_dex_classpath})" ] + } + + inputs += _dexing_jars + if (_dexing_jars != []) { + args += rebase_path(_dexing_jars, root_build_dir) + } + + 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 + if (_proguard_enabled) { + args += [ + "--proguard-mapping-path", + rebase_path(invoker.proguard_mapping_path, root_build_dir), + ] + inputs += [ invoker.proguard_mapping_path ] + } + } + + if (!is_java_debug) { + args += [ "--release" ] + } + + if (defined(invoker.min_sdk_version)) { + args += [ + "--min-api", + "${invoker.min_sdk_version}", + ] + } + + _d8_path = "//third_party/r8/lib/d8.jar" + inputs += [ _d8_path ] + args += [ + "--d8-jar-path", + rebase_path(_d8_path, root_build_dir), + ] + } + } + } + + template("emma_instr") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + ]) + + _coverage_file = "$target_out_dir/${target_name}.em" + _source_dirs_listing_file = "$target_out_dir/${target_name}_sources.txt" + _emma_jar = "${android_sdk_root}/tools/lib/emma.jar" + + script = "//build/android/gyp/emma_instr.py" + inputs = invoker.java_files + [ + _emma_jar, + invoker.input_jar_path, + ] + outputs = [ + _coverage_file, + _source_dirs_listing_file, + invoker.output_jar_path, + ] + args = [ + "instrument_jar", + "--input-path", + rebase_path(invoker.input_jar_path, root_build_dir), + "--output-path", + rebase_path(invoker.output_jar_path, root_build_dir), + "--coverage-file", + rebase_path(_coverage_file, root_build_dir), + "--sources-list-file", + rebase_path(_source_dirs_listing_file, root_build_dir), + "--src-root", + rebase_path("//", root_build_dir), + "--emma-jar", + rebase_path(_emma_jar, root_build_dir), + ] + _rebased_java_sources_file = + rebase_path(invoker.java_sources_file, root_build_dir) + args += [ "--java-sources-file=$_rebased_java_sources_file" ] + + if (emma_filter != "") { + args += [ + "--filter-string", + emma_filter, + ] + } + } + } + + # TODO(digit): Document this! + # + # Variables: + # testonly: + # build_config: + # input_jar_path: + # output_jar_path: + # enable_build_hooks: + # enable_build_hooks_android: + # supports_android: + # emma_instrument: + # 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. + # strip_resource_classes: + # deps: + # java_files: + # java_sources_file: + # inputs: + # data_deps: + # visibility: + # + template("process_java_prebuilt") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + assert(invoker.build_config != "") + _build_config = invoker.build_config + _rebased_build_config = rebase_path(_build_config, root_build_dir) + assert(_rebased_build_config != "" || true) # Mark used. + + _input_jar_path = invoker.input_jar_path + _output_jar_path = invoker.output_jar_path + + _enable_assert = + defined(invoker.enable_build_hooks) && invoker.enable_build_hooks && + (is_java_debug || dcheck_always_on || report_java_assert) + + _enable_custom_resources = defined(invoker.enable_build_hooks_android) && + invoker.enable_build_hooks_android + + # Turned off because of existing code which fails the assertion + _enable_thread_annotations = false + + _desugar = defined(invoker.supports_android) && invoker.supports_android + _emma_instrument = invoker.emma_instrument + _enable_split_compat = defined(invoker.split_compat_class_names) + _enable_bytecode_rewriter = + _enable_assert || _enable_custom_resources || + _enable_thread_annotations || _enable_split_compat + _is_prebuilt = defined(invoker.is_prebuilt) && invoker.is_prebuilt + _enable_bytecode_checks = !defined(invoker.enable_bytecode_checks) || + invoker.enable_bytecode_checks + + # Release builds don't have asserts enabled, so they often will not run the + # bytecode rewriter. We are okay with having release builds not run the + # bytecode checks at all, since the dependency errors can be caught in debug + # mode. + not_needed([ + "_is_prebuilt", + "_enable_bytecode_checks", + ]) + if (defined(invoker.enable_bytecode_rewriter)) { + not_needed([ + "_enable_assert", + "_enable_custom_resources", + "_enable_thread_annotations", + ]) + _enable_bytecode_rewriter = invoker.enable_bytecode_rewriter + } + + _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 + } + _strip_resource_classes = defined(invoker.strip_resource_classes) && + invoker.strip_resource_classes + _filter_jar = _jar_excluded_patterns != [] || + _jar_included_patterns != [] || _strip_resource_classes + + _deps = [] + _previous_output_jar = _input_jar_path + + if (_enable_bytecode_rewriter) { + _java_bytecode_rewriter_target = "${target_name}__bytecode_rewrite" + _java_bytecode_rewriter_input_jar = _previous_output_jar + _java_bytecode_rewriter_output_jar = + "$target_out_dir/$target_name-bytecode-rewritten.jar" + + action_with_pydeps(_java_bytecode_rewriter_target) { + script = "//build/android/gyp/bytecode_processor.py" + _bytecode_rewriter_script = + "$root_build_dir/bin/helper/java_bytecode_rewriter" + deps = _deps + [ "//build/android/bytecode:java_bytecode_rewriter($default_toolchain)" ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [ + _bytecode_rewriter_script, + _java_bytecode_rewriter_input_jar, + _build_config, + ] + outputs = [ + _java_bytecode_rewriter_output_jar, + ] + args = [ + "--script", + rebase_path(_bytecode_rewriter_script, root_build_dir), + "--input-jar", + rebase_path(_java_bytecode_rewriter_input_jar, root_build_dir), + "--output-jar", + rebase_path(_java_bytecode_rewriter_output_jar, root_build_dir), + ] + if (_is_prebuilt) { + args += [ "--is-prebuilt" ] + } + if (_enable_assert) { + args += [ "--enable-assert" ] + } + if (_enable_custom_resources) { + args += [ "--enable-custom-resources" ] + } + if (_enable_thread_annotations) { + args += [ "--enable-thread-annotations" ] + } + if (_enable_bytecode_checks) { + args += [ "--enable-check-class-path" ] + } + if (_enable_split_compat) { + args += [ "--split-compat-class-names" ] + + invoker.split_compat_class_names + } + args += [ + "--direct-classpath-jars", + "@FileArg($_rebased_build_config:javac:classpath)", + "--sdk-classpath-jars", + "@FileArg($_rebased_build_config:android:sdk_jars)", + "--extra-classpath-jars", + "@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + ] + } + + _deps = [] + _deps = [ ":$_java_bytecode_rewriter_target" ] + _previous_output_jar = _java_bytecode_rewriter_output_jar + } + + if (_desugar) { + _desugar_target = "${target_name}__desugar" + _desugar_input_jar = _previous_output_jar + _desugar_output_jar = "$target_out_dir/$target_name-desugar.jar" + + action_with_pydeps(_desugar_target) { + script = "//build/android/gyp/desugar.py" + deps = _deps + depfile = "$target_gen_dir/$target_name.d" + if (defined(invoker.deps)) { + deps += invoker.deps + } + _desugar_jar = "//third_party/bazel/desugar/Desugar.jar" + + inputs = [ + _build_config, + _desugar_input_jar, + _desugar_jar, + ] + outputs = [ + _desugar_output_jar, + ] + args = [ + "--desugar-jar", + rebase_path(_desugar_jar, root_build_dir), + "--input-jar", + rebase_path(_desugar_input_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), + ] + } + + _deps = [] + _deps = [ ":$_desugar_target" ] + _previous_output_jar = _desugar_output_jar + } + + if (_filter_jar) { + _filter_target = "${target_name}__filter" + _filter_input_jar = _previous_output_jar + _filter_output_jar = "$target_out_dir/$target_name-filtered.jar" + + action_with_pydeps(_filter_target) { + script = "//build/android/gyp/filter_zip.py" + deps = _deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + inputs = [ + _build_config, + _filter_input_jar, + ] + outputs = [ + _filter_output_jar, + ] + args = [ + "--input", + rebase_path(_filter_input_jar, root_build_dir), + "--output", + rebase_path(_filter_output_jar, root_build_dir), + "--exclude-globs=$_jar_excluded_patterns", + "--include-globs=$_jar_included_patterns", + ] + if (_strip_resource_classes) { + args += [ "--strip-resource-classes-for=@FileArg($_rebased_build_config:javac:resource_packages)" ] + } + } + + _deps = [] + _deps = [ ":$_filter_target" ] + _previous_output_jar = _filter_output_jar + } + + if (_emma_instrument) { + # Emma must run after desugar (or else desugar sometimes fails). + _emma_target = "${target_name}__emma" + _emma_input_jar = _previous_output_jar + _emma_output_jar = "$target_out_dir/$target_name-instrumented.jar" + + emma_instr(_emma_target) { + deps = _deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + + forward_variables_from(invoker, + [ + "java_files", + "java_sources_file", + ]) + + input_jar_path = _emma_input_jar + output_jar_path = _emma_output_jar + } + + _deps = [] + _deps = [ ":$_emma_target" ] + _previous_output_jar = _emma_output_jar + } + + _output_jar_target = "${target_name}__copy" + + # This is copy_ex rather than copy to ensure that JARs (rather than + # possibly broken symlinks to them) get copied into the output + # directory. + copy_ex(_output_jar_target) { + forward_variables_from(invoker, [ "inputs" ]) + deps = _deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + dest = _output_jar_path + sources = [ + _previous_output_jar, + ] + outputs = [ + _output_jar_path, + ] + } + + group(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "visibility", + ]) + public_deps = [ + ":$_output_jar_target", + ] + } + } + + template("merge_manifests") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + 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), + "--build-vars", + rebase_path(android_build_vars, 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)", + ] + + if (defined(invoker.expected_manifest)) { + inputs += [ invoker.expected_manifest ] + _normalized_output = "${invoker.output_manifest}.normalized" + outputs += [ _normalized_output ] + args += [ + "--expected-manifest", + rebase_path(invoker.expected_manifest, root_build_dir), + "--normalized-output", + rebase_path(_normalized_output, root_build_dir), + ] + if (check_android_configuration) { + args += [ "--verify-expected-manifest" ] + } + } + } + } + + # 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 file corresponding to the target. + # + # resource_dirs: + # List of directories containing Android resources, layout should be + # similar to what aapt -S <dir> expects. + # + # generated_resource_dirs: (optional) + # List of directories containing generated resources. + # + # generated_resource_files: (optional) + # If generated_resources_dirs is not empty, must list all the files + # within these directories (the directory must appear at the start of + # the file path). + # + # 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. + # + # shared_resources: (optional) + # If true, generate an R.java file that uses non-final resource ID + # variables and an onResourcesLoaded() method. + # + # v14_skip: (optional) + # If true, skip generation of v14 compatible resources. + # (see generate_v14_compatible_resources.py for details). + # + # Output variables: + # zip_path: (optional) + # Path to a .resources.zip that will simply contain all the + # input resources, collected in a single archive. + # + # r_text_out_path: (optional): Path for the generated R.txt file. + # + # srcjar_path: (optional) Path to a generated .srcjar containing the + # generated R.java source file. + # + template("prepare_resources") { + if (defined(invoker.srcjar_path)) { + _srcjar_path = invoker.srcjar_path + } + action_with_pydeps(target_name) { + set_sources_assignment_filter([]) + forward_variables_from(invoker, + [ + "deps", + "testonly", + "visibility", + ]) + script = "//build/android/gyp/prepare_resources.py" + + depfile = "$target_gen_dir/${invoker.target_name}.d" + outputs = [] + _all_resource_dirs = [] + sources = [] + + if (defined(invoker.resource_dirs)) { + _all_resource_dirs += invoker.resource_dirs + + # Speed up "gn gen" by short-circuiting the empty directory. + if (invoker.resource_dirs != [ "//build/android/empty" ] && + invoker.resource_dirs != []) { + _sources_build_rel = + exec_script("//build/android/gyp/find.py", + rebase_path(invoker.resource_dirs, root_build_dir), + "list lines") + sources += rebase_path(_sources_build_rel, ".", root_build_dir) + } + } + + if (defined(invoker.generated_resource_dirs)) { + assert(defined(invoker.generated_resource_files)) + _all_resource_dirs += invoker.generated_resource_dirs + sources += invoker.generated_resource_files + } + + _android_aapt_path = android_default_aapt_path + + inputs = [ + invoker.build_config, + _android_aapt_path, + ] + + _rebased_all_resource_dirs = + rebase_path(_all_resource_dirs, root_build_dir) + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)", + "--aapt-path", + rebase_path(_android_aapt_path, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)", + "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)", + "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)", + ] + + if (defined(invoker.android_manifest)) { + if (defined(invoker.android_manifest_dep)) { + deps += [ invoker.android_manifest_dep ] + } + inputs += [ invoker.android_manifest ] + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, root_build_dir), + ] + } + + if (_rebased_all_resource_dirs != []) { + args += [ "--resource-dirs=$_rebased_all_resource_dirs" ] + } + + if (defined(invoker.zip_path)) { + outputs += [ + invoker.zip_path, + invoker.zip_path + ".info", + ] + args += [ + "--resource-zip-out", + rebase_path(invoker.zip_path, root_build_dir), + ] + } + + 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(_srcjar_path)) { + outputs += [ _srcjar_path ] + args += [ + "--srcjar-out", + rebase_path(_srcjar_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.custom_package)) { + args += [ + "--custom-package", + invoker.custom_package, + ] + } + + if (defined(invoker.strip_drawables) && invoker.strip_drawables) { + args += [ "--strip-drawables" ] + } + + if (defined(invoker.shared_resources) && invoker.shared_resources) { + args += [ "--shared-resources" ] + } + + if (defined(invoker.v14_skip) && invoker.v14_skip) { + args += [ "--v14-skip" ] + } + } + } + + # 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: + # deps: Specifies the input dependencies for this target. + # + # build_config: Path to the .build_config file corresponding to the target. + # + # 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_whitelist: (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_whitelist_locales: (optional) + # If shared_resources_whitelist 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_whitelist + # is defined to a smaller subset. + # + # support_zh_hk: (optional) + # If true, support zh-HK in Chrome on Android by using the resources + # from zh-TW. See https://crbug.com/780847. + # + # aapt_locale_whitelist: (optional) + # Restrict compiled locale-dependent resources to a specific whitelist. + # NOTE: This is a list of Chromium locale names, not Android ones. + # + # resource_blacklist_regex: (optional) + # + # resource_blacklist_exceptions: (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) + # + # proto_format: (optional). If true, compiles resources into protocol + # buffer format. + # + # package_name: (optional) + # Name of the package for the purpose of assigning package ID. + # + # package_name_to_id_mapping: (optional) + # List containing mapping from package names to package IDs. It will be + # used to determine which package ID to assign if package_name variable + # was passed in. + # + # package_id: (optional) + # Use a custom package ID in resource IDs (same purpose as + # package_name_to_id_mapping) + # + # 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. + # + # Output variables: + # output: Path to a zip file containing the compiled resources. + # + # r_text_out_path: (optional): + # Path for the corresponding generated R.txt file. + # + # srcjar_path: (optional) + # Path to a generated .srcjar containing the generated R.java sources + # for all dependent resource libraries. + # + # proguard_file: (optional) + # Path to proguard configuration file for this apk target. + # + # proguard_file_main_dex: (optional) + # + # + template("compile_resources") { + _compile_resources_target_name = target_name + _compiled_resources_path = invoker.output + + if (defined(invoker.srcjar_path)) { + _srcjar_path = invoker.srcjar_path + } + if (defined(invoker.post_process_script)) { + _compile_resources_target_name = "${target_name}__intermediate" + _compiled_resources_path = + get_path_info(_compiled_resources_path, "dir") + "/" + + get_path_info(_compiled_resources_path, "name") + ".intermediate.ap_" + _srcjar_path = "${_srcjar_path}.intermediate.srcjar" + } + + _proto_format = defined(invoker.proto_format) && invoker.proto_format + + # NOTE: Regarding the names of the depfiles used by this template: + # They all have the same prefix, related to invoker.target_name, + # instead of $target_name, so it is important they have different + # file paths. Otherwise, extra-rebuilds or even incorrect builds + # may happen due to incorrect dependency information. The suffixes + # used are: + # + # _1.d for the unprocessed compiled resources. + # _2.d for the optional processed compiled resources. + # _3.d for the proto-compiled resources. + + action_with_pydeps(_compile_resources_target_name) { + set_sources_assignment_filter([]) + forward_variables_from(invoker, + [ + "deps", + "testonly", + "visibility", + ]) + script = "//build/android/gyp/compile_resources.py" + + depfile = "$target_gen_dir/${invoker.target_name}_1.d" + outputs = [] + + _android_aapt_path = android_default_aapt_path + _android_aapt2_path = android_sdk_tools_bundle_aapt2 + if (_proto_format) { + depfile = "$target_gen_dir/${invoker.target_name}_3.d" + } + + inputs = [ + invoker.build_config, + _android_aapt_path, + _android_aapt2_path, + ] + + _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--include-resources=@FileArg($_rebased_build_config:android:sdk_jars)", + "--aapt2-path", + rebase_path(_android_aapt2_path, root_build_dir), + "--dependencies-res-zips=@FileArg($_rebased_build_config:resources:dependency_zips)", + "--extra-res-packages=@FileArg($_rebased_build_config:resources:extra_package_names)", + "--extra-r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_files)", + ] + + inputs += [ invoker.android_manifest ] + args += [ + "--android-manifest", + rebase_path(invoker.android_manifest, 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(_compiled_resources_path)) { + _info_path = invoker.output + ".info" + outputs += [ + _compiled_resources_path, + _info_path, + ] + args += [ + "--apk-path", + rebase_path(_compiled_resources_path, root_build_dir), + "--apk-info-path", + rebase_path(_info_path, root_build_dir), + ] + } + + if (defined(invoker.optimized_resources_path)) { + args += [ + "--optimized-resources-path", + rebase_path(invoker.optimized_resources_path, root_build_dir), + ] + outputs += [ invoker.optimized_resources_path ] + + if (defined(invoker.resources_config_path)) { + inputs += [ invoker.resources_config_path ] + args += [ + "--resources-config-path", + rebase_path(invoker.resources_config_path, root_build_dir), + ] + } + } + + # 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(_srcjar_path)) { + outputs += [ _srcjar_path ] + args += [ + "--srcjar-out", + rebase_path(_srcjar_path, root_build_dir), + ] + } + + if (defined(invoker.custom_package)) { + args += [ + "--custom-package", + invoker.custom_package, + ] + } + + if (_proto_format) { + args += [ "--proto-format" ] + } + + # 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}", + "--package-name-to-id-mapping=${invoker.package_name_to_id_mapping}", + ] + } + if (defined(invoker.arsc_package_name)) { + args += [ + "--arsc-package-name", + invoker.arsc_package_name, + ] + } + + if (defined(invoker.shared_resources_whitelist)) { + inputs += [ invoker.shared_resources_whitelist ] + args += [ + "--shared-resources-whitelist", + rebase_path(invoker.shared_resources_whitelist, root_build_dir), + ] + } + if (defined(invoker.shared_resources_whitelist_locales)) { + args += [ "--shared-resources-whitelist-locales=" + + "${invoker.shared_resources_whitelist_locales}" ] + } + + 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_whitelist)) { + args += [ "--locale-whitelist=${invoker.aapt_locale_whitelist}" ] + } + 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_blacklist_regex)) { + args += + [ "--resource-blacklist-regex=${invoker.resource_blacklist_regex}" ] + if (defined(invoker.resource_blacklist_exceptions)) { + args += [ "--resource-blacklist-exceptions=${invoker.resource_blacklist_exceptions}" ] + } + } + + if (defined(invoker.support_zh_hk) && invoker.support_zh_hk) { + args += [ "--support-zh-hk" ] + } + + 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.post_process_script)) { + action(target_name) { + depfile = "${target_gen_dir}/${invoker.target_name}_2.d" + script = invoker.post_process_script + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--apk-path", + rebase_path(_compiled_resources_path, root_build_dir), + "--output", + rebase_path(invoker.output, root_build_dir), + "--srcjar-in", + rebase_path(_srcjar_path, root_build_dir), + "--srcjar-out", + rebase_path(invoker.srcjar_path, root_build_dir), + ] + if (defined(invoker.shared_resources_whitelist)) { + args += [ + "--r-text-whitelist", + rebase_path(invoker.shared_resources_whitelist, root_build_dir), + "--r-text", + rebase_path(invoker.r_text_out_path, root_build_dir), + ] + } + inputs = [ + _srcjar_path, + _compiled_resources_path, + ] + if (defined(invoker.post_process_script_inputs)) { + inputs += invoker.post_process_script_inputs + } + outputs = [ + invoker.output, + invoker.srcjar_path, + ] + public_deps = [ + ":${_compile_resources_target_name}", + ] + } + } + } + + # 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"). + # packaged_resources_path: Path to .ap_ file. + # + template("create_size_info_files") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "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)", + "--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)", + ] + } + } else { + inputs = [ + invoker.build_config, + invoker.packaged_resources_path, + ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + args += [ + "--jar-files=@FileArg($_rebased_build_config:deps_info:jar_path)", + "--jar-files=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--resource-apk", + rebase_path(invoker.packaged_resources_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 containing merged + # asset information. + # deps: Specifies the dependencies of this target. + # dex_path: Path to classes.dex file to include (optional). + # packaged_resources_path: Path to .ap_ to use. + # output_apk_path: Output path for the generated .apk. + # 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). + # native_libs: List of native libraries. + # native_libs_filearg: @FileArg() of additionally native libraries. + # secondary_abi_native_libs: (optional) List of native libraries for + # secondary ABI. + # secondary_abi_native_libs_filearg: (optional). @FileArg() of additional + # secondary ABI native libs. + # write_asset_list: Adds an extra file to the assets, which contains a list of + # all other asset files. + # 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") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + ]) + _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" + depfile = "$target_gen_dir/$target_name.d" + _apksigner = "$android_sdk_build_tools/apksigner" + _zipalign = "$android_sdk_build_tools/zipalign" + data_deps = [ + "//tools/android/md5sum", + ] # Used when deploying APKs + + inputs = invoker.native_libs + [ + invoker.keystore_path, + invoker.packaged_resources_path, + _apksigner, + _zipalign, + ] + if (defined(invoker.dex_path)) { + inputs += [ invoker.dex_path ] + } + + 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) + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--resource-apk=$_rebased_compiled_resources_path", + "--output-apk=$_rebased_packaged_apk_path", + "--apksigner-path", + 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, + ] + if (defined(invoker.uncompress_dex) && invoker.uncompress_dex) { + args += [ "--uncompress-dex" ] + } + if (defined(invoker.assets_build_config)) { + inputs += [ invoker.assets_build_config ] + _rebased_build_config = + rebase_path(invoker.assets_build_config, root_build_dir) + args += [ + "--assets=@FileArg($_rebased_build_config:assets)", + "--uncompressed-assets=@FileArg($_rebased_build_config:uncompressed_assets)", + ] + + # TODO(mlopatkin) We are relying on the fact that assets_build_config is + # an APK build_config. + args += [ "--java-resources=@FileArg($_rebased_build_config:java_resources_jars)" ] + } + if (defined(invoker.write_asset_list) && invoker.write_asset_list) { + args += [ "--write-asset-list" ] + } + if (defined(invoker.dex_path)) { + _rebased_dex_path = rebase_path(invoker.dex_path, root_build_dir) + args += [ "--dex-file=$_rebased_dex_path" ] + } + if (invoker.native_libs != [] || 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 (invoker.native_libs != []) { + _rebased_native_libs = rebase_path(invoker.native_libs, root_build_dir) + args += [ "--native-libs=$_rebased_native_libs" ] + } + 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 (_secondary_native_lib_placeholders != []) { + args += [ "--secondary-native-lib-placeholders=$_secondary_native_lib_placeholders" ] + } + + if (defined(invoker.secondary_abi_native_libs_filearg)) { + args += [ "--secondary-native-libs=${invoker.secondary_abi_native_libs_filearg}" ] + } + + if (defined(invoker.uncompress_shared_libraries) && + invoker.uncompress_shared_libraries) { + args += [ "--uncompress-shared-libraries=True" ] + } + } + } + + # Packages resources, assets, dex, and native libraries into an apk. Signs and + # zipaligns the apk. + template("create_apk") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + _final_apk_path = invoker.apk_path + + if (defined(invoker.dex_path)) { + _dex_path = invoker.dex_path + } + _load_library_from_apk = invoker.load_library_from_apk + assert(_load_library_from_apk || true) + + _deps = [] + if (defined(invoker.deps)) { + _deps = invoker.deps + } + _incremental_deps = [] + if (defined(invoker.incremental_deps)) { + _incremental_deps = invoker.incremental_deps + } + _native_libs = [] + if (defined(invoker.native_libs)) { + _native_libs = invoker.native_libs + } + _native_libs_even_when_incremental = [] + if (defined(invoker.native_libs_even_when_incremental) && + invoker.native_libs_even_when_incremental != []) { + _native_libs_even_when_incremental = + invoker.native_libs_even_when_incremental + } + + _shared_resources = + defined(invoker.shared_resources) && invoker.shared_resources + assert(_shared_resources || true) # Mark as used. + + _keystore_path = invoker.keystore_path + _keystore_name = invoker.keystore_name + _keystore_password = invoker.keystore_password + + package_apk(target_name) { + forward_variables_from(invoker, + [ + "apk_name", + "assets_build_config", + "native_lib_placeholders", + "native_libs_filearg", + "secondary_native_lib_placeholders", + "secondary_abi_native_libs_filearg", + "secondary_abi_loadable_modules", + "uncompress_dex", + "uncompress_shared_libraries", + "write_asset_list", + ]) + if (!defined(uncompress_shared_libraries)) { + uncompress_shared_libraries = _load_library_from_apk + } + if (defined(invoker.optimized_resources_path)) { + packaged_resources_path = invoker.optimized_resources_path + not_needed(invoker, [ "packaged_resources_path" ]) + } else { + packaged_resources_path = invoker.packaged_resources_path + } + deps = _deps + native_libs = _native_libs + _native_libs_even_when_incremental + keystore_path = _keystore_path + keystore_name = _keystore_name + keystore_password = _keystore_password + + if (defined(_dex_path)) { + dex_path = _dex_path + } + + output_apk_path = _final_apk_path + } + + _incremental_allowed = + defined(invoker.incremental_allowed) && invoker.incremental_allowed + if (_incremental_allowed) { + _android_manifest = invoker.android_manifest + _base_path = invoker.base_path + + _incremental_final_apk_path_helper = + process_file_template( + [ _final_apk_path ], + "{{source_dir}}/{{source_name_part}}_incremental.apk") + _incremental_final_apk_path = _incremental_final_apk_path_helper[0] + + _incremental_compiled_resources_path = "${_base_path}_incremental.ap_" + _incremental_compile_resources_target_name = + "${target_name}_incremental__compile_resources" + + _rebased_build_config = + rebase_path(invoker.assets_build_config, root_build_dir) + + action_with_pydeps(_incremental_compile_resources_target_name) { + deps = _incremental_deps + script = + "//build/android/incremental_install/generate_android_manifest.py" + inputs = [ + _android_manifest, + invoker.assets_build_config, + invoker.packaged_resources_path, + ] + outputs = [ + _incremental_compiled_resources_path, + ] + + args = [ + "--src-manifest", + rebase_path(_android_manifest, root_build_dir), + "--in-apk", + rebase_path(invoker.packaged_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)", + ] + if (disable_incremental_isolated_processes) { + args += [ "--disable-isolated-processes" ] + } + } + + package_apk("${target_name}_incremental") { + forward_variables_from(invoker, + [ + "assets_build_config", + "secondary_abi_loadable_modules", + "uncompress_shared_libraries", + ]) + _dex_target = "//build/android/incremental_install:bootstrap_java__dex" + deps = _incremental_deps + [ + ":${_incremental_compile_resources_target_name}", + _dex_target, + ] + + if (defined(_dex_path)) { + dex_path = + get_label_info(_dex_target, "target_gen_dir") + "/bootstrap.dex" + } + + native_libs = _native_libs_even_when_incremental + keystore_path = _keystore_path + keystore_name = _keystore_name + keystore_password = _keystore_password + + # http://crbug.com/384638 + _has_native_libs = + defined(invoker.native_libs_filearg) || _native_libs != [] + if (_has_native_libs && _native_libs_even_when_incremental == []) { + native_lib_placeholders = [ "libfix.crbug.384638.so" ] + } + + output_apk_path = _incremental_final_apk_path + packaged_resources_path = _incremental_compiled_resources_path + } + } + } + + # 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 the javac.py script, 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. + # srcjar_filearg: Optional @FileArg for additional srcjars. + # 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 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: Optional. 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. + # apk_name: Optional APK name. If provided, will tell javac.py to also + # generate an .apk.jar.info file under size-info/${apk_name}.apk.jar.info + # provider_configurations: Optional list of paths to Java service + # provider configuration files [1]. These will be copied under + # META-INF/services/ in the final .jar file. + # 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" ]) + + _build_config = invoker.build_config + _chromium_code = invoker.chromium_code + + _provider_configurations = [] + if (defined(invoker.provider_configurations)) { + _provider_configurations = invoker.provider_configurations + } + + _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" ] + } + + _javac_args = [] + if (defined(invoker.javac_args)) { + _javac_args = invoker.javac_args + } + + action_with_pydeps(target_name) { + script = "//build/android/gyp/javac.py" + depfile = "$target_gen_dir/$target_name.d" + deps = _srcjar_deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + + outputs = [ + invoker.javac_jar_path, + invoker.javac_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_javac_jar_path = + rebase_path(invoker.javac_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_javac_jar_path", + "--java-srcjars=$_rebased_java_srcjars", + "--java-version=1.8", + "--full-classpath=@FileArg($_rebased_build_config:deps_info:javac_full_classpath)", + "--interface-classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", + "--processorpath=@FileArg($_rebased_build_config:javac:processor_classpath)", + "--processors=@FileArg($_rebased_build_config:javac:processor_classes)", + ] + if (defined(invoker.srcjar_filearg)) { + args += [ "--java-srcjars=${invoker.srcjar_filearg}" ] + } + if (invoker.requires_android) { + args += [ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_interface_jars)" ] + } + if (_chromium_code) { + args += [ "--chromium-code=1" ] + } + + # Use errorprone with checks disabled when !enable_errorprone so that + # compile results are the same across machines. + # TODO(crbug.com/693079): Add javac to DEPS and use it for the + # !enable_errorprone case. + deps += [ "//third_party/errorprone:errorprone($default_toolchain)" ] + args += [ + "--errorprone-path", + "bin/errorprone", + ] + + if (invoker.enable_errorprone) { + deps += [ "//tools/android/errorprone_plugin:errorprone_plugin_java($default_toolchain)" ] + _rebased_errorprone_processorpath = [ + "lib.java/tools/android/errorprone_plugin/errorprone_plugin_java.jar", + ] + args += [ + "--processorpath=$_rebased_errorprone_processorpath", + "--enable-errorprone", + ] + } + foreach(e, _provider_configurations) { + args += [ "--provider-configuration=" + rebase_path(e, root_build_dir) ] + } + 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 ] + } + } + } + + # 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, + [ + "data", + "data_deps", + "public_deps", + "testonly", + "visibility", + ]) + 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. + # final_jar_path: Optional path to the final output .jar file (after + # processing). If not provided, the output will go under + # $root_build_dir/lib.java/ + # output_name: Optional output name for the final jar path. Ignored if + # final_jar_path is provided. Otherwise, used to determine the name + # of the final jar. If not provided, the default is to use the same + # name as jar_path, if provided, or main_target_name. + # dex_path: Optional. Path to the output dex.jar file for this target. + # Ignored if !supports_android. + # 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. + # testonly: True iff target should only be used for tests. + # no_build_hooks: Disables bytecode rewriting of asserts and android + # resources methods. + # 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). + # emma_never_instrument: Optional. If provided, whether to forbid + # instrumentation with the Emma coverage processor. If not provided, + # this is controlled by the global emma_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). + # classpath_deps: Optional list of additional java library dependencies, + # whose .jar files will be added to the compile-time classpath when + # building this target (but not to the runtime classpath). + # 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. + # android_manifest_for_lint: Optional path to Android manifest to use + # if Android linting is enabled. Ignored for 'android_apk' types + # (since the value of android_manifest will be used instead). + # lint_suppressions_file: Optional lint suppressions input 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. + # + # 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_allowed: Optional (default false). True to allow the + # generation of incremental APKs ('android_apk' targets only). + # incremental_apk_path: If incremental_allowed, path to the incremental + # output APK. + # incremental_install_json_path: If incremental_allowed, path to the output + # incremental install json configuration file. + # 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. + # extra_shared_libraries: Optional list of extra native libraries to + # be stored in the APK. + # 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). + # module_rtxt_path: The path of the R.txt file generated when compiling the + # resources for the bundle module. + # base_whitelist_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: + # + # bootclasspath: Optional list of boot class paths used by the generated + # wrapper script. + # 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") { + set_sources_assignment_filter([]) + 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" + _is_system_library = invoker.type == "system_java_library" + _supports_android = + defined(invoker.supports_android) && invoker.supports_android + _requires_android = + defined(invoker.requires_android) && invoker.requires_android + + _main_target_name = target_name + if (defined(invoker.main_target_name)) { + _main_target_name = invoker.main_target_name + } + _java_files = [] + if (defined(invoker.java_files)) { + _java_files = invoker.java_files + } + _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}") + } + + # The only target that might have no prebuilt and no sources is a java_binary. + 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 + } + + # Jar files can be needed at runtime (by Robolectric tests or java binaries), + # so do not put them under gen/. + _target_dir_name = get_label_info(":$_main_target_name", "dir") + _final_jar_path = + "$root_out_dir/lib.java$_target_dir_name/$_output_name.jar" + if (defined(invoker.final_jar_path)) { + _final_jar_path = invoker.final_jar_path + } + _final_ijar_path = + get_path_info(_final_jar_path, "dir") + "/" + + get_path_info(_final_jar_path, "name") + ".interface.jar" + + if (_has_sources) { + _javac_jar_path = "$target_gen_dir/$_main_target_name.javac.jar" + } + + if (_is_prebuilt) { + _unprocessed_jar_path = invoker.jar_path + } else { + _unprocessed_jar_path = _javac_jar_path + } + + if (_supports_android) { + _dex_path = "$target_gen_dir/$_main_target_name.dex.jar" + if (defined(invoker.dex_path)) { + _dex_path = invoker.dex_path + } + } + } + + _accumulated_public_deps = [] + _accumulated_deps = [] + if (defined(invoker.deps)) { + _accumulated_deps = invoker.deps + } + + _enable_build_hooks = + _supports_android && + (!defined(invoker.no_build_hooks) || !invoker.no_build_hooks) + if (_enable_build_hooks) { + _accumulated_deps += [ "//build/android/buildhooks:build_hooks_java" ] + } + + # Some testonly targets use their own resources and the code being + # tested will use custom resources so there's no need to enable this + # for testonly targets. + _enable_build_hooks_android = + _enable_build_hooks && _requires_android && + (!defined(invoker.testonly) || !invoker.testonly) + if (_enable_build_hooks_android) { + _accumulated_deps += + [ "//build/android/buildhooks:build_hooks_android_java" ] + } + + # Don't enable coverage or lint unless the target has some non-generated + # files. + if (defined(invoker.chromium_code)) { + _chromium_code = invoker.chromium_code + } else { + # Default based on whether target is in third_party. + set_sources_assignment_filter([ "*\bthird_party\b*" ]) + sources = [ + get_label_info(":$_main_target_name", "dir"), + ] + _chromium_code = sources != [] + if (!_chromium_code && !_is_prebuilt && _java_files != []) { + # Unless third_party code has an org.chromium file in it. + set_sources_assignment_filter([ "*\bchromium\b*" ]) + sources = _java_files + _chromium_code = _java_files != sources + } + set_sources_assignment_filter([]) + sources = [] + } + + if (defined(_final_jar_path)) { + _emma_instrument = emma_coverage && _chromium_code && _java_files != [] && + (!defined(invoker.testonly) || !invoker.testonly) + if (defined(invoker.emma_never_instrument)) { + _emma_instrument = !invoker.emma_never_instrument && _emma_instrument + } + if (_emma_instrument) { + _accumulated_deps += [ "//third_party/android_sdk:emma_device_java" ] + } + } + + 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)) + } + + _include_android_sdk = !_is_system_library && _supports_android + if (defined(invoker.include_android_sdk)) { + _include_android_sdk = invoker.include_android_sdk + } + if (_include_android_sdk) { + if (defined(invoker.alternative_android_sdk_dep)) { + _accumulated_deps += [ invoker.alternative_android_sdk_dep ] + } else { + _accumulated_deps += [ "//third_party/android_sdk:android_sdk_java" ] + } + } + + # 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" + _build_config_target_name = + "${_main_target_name}$build_config_target_suffix" + + write_build_config(_build_config_target_name) { + forward_variables_from(invoker, + [ + "annotation_processor_deps", + "base_whitelist_rtxt_path", + "classpath_deps", + "gradle_treat_as_prebuilt", + "input_jars_paths", + "loadable_modules", + "main_class", + "proguard_configs", + "proguard_enabled", + "proguard_mapping_path", + "secondary_abi_loadable_modules", + "type", + ]) + if (type == "android_apk" || type == "android_app_bundle_module") { + forward_variables_from( + invoker, + [ + "android_manifest", + "android_manifest_dep", + "extra_shared_libraries", + "final_dex_path", + "native_lib_placeholders", + "secondary_abi_shared_libraries_runtime_deps_file", + "secondary_native_lib_placeholders", + "shared_libraries_runtime_deps_file", + "static_library_dependent_targets", + "uncompress_shared_libraries", + ]) + } + if (type == "android_apk") { + forward_variables_from(invoker, + [ + "apk_path", + "apk_under_test", + "incremental_allowed", + "incremental_apk_path", + "incremental_install_json_path", + ]) + } + if (type == "android_app_bundle_module") { + forward_variables_from(invoker, + [ + "base_module_target", + "module_rtxt_path", + "proto_resources_path", + ]) + } + build_config = _build_config + is_prebuilt = _is_prebuilt + possible_config_deps = _accumulated_deps + if (defined(apk_under_test)) { + possible_config_deps += [ apk_under_test ] + } + supports_android = _supports_android + requires_android = _requires_android + bypass_platform_checks = defined(invoker.bypass_platform_checks) && + invoker.bypass_platform_checks + + if (defined(_final_jar_path)) { + jar_path = _final_jar_path + ijar_path = _final_ijar_path + unprocessed_jar_path = _unprocessed_jar_path + } + if (defined(_dex_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) { + if (defined(invoker.jar_path)) { + # Use original jar_path because _jar_path points to a library without + # resources. + java_resources_jar = invoker.jar_path + } else { + java_resources_jar = _final_jar_path + } + } + } + _accumulated_public_deps += [ ":$_build_config_target_name" ] + + # Don't need to depend on the apk-under-test to be packaged. + if (defined(invoker.apk_under_test)) { + _accumulated_deps += [ "${invoker.apk_under_test}__java" ] + } + if (defined(invoker.android_manifest_dep)) { + _accumulated_deps += [ invoker.android_manifest_dep ] + } + if (defined(invoker.classpath_deps)) { + _accumulated_deps += invoker.classpath_deps + } + if (defined(invoker.annotation_processor_deps)) { + _accumulated_deps += invoker.annotation_processor_deps + } + + # TODO(agrieve): Enable lint for _has_sources rather than just _java_files. + _lint_enabled = _java_files != [] && _supports_android && _chromium_code && + !disable_android_lint + if (defined(invoker.enable_errorprone)) { + _enable_errorprone = invoker.enable_errorprone + } else { + _enable_errorprone = + _java_files != [] && _chromium_code && use_errorprone_java_compiler + } + + if (_has_sources) { + _type = invoker.type + template("compile_java_helper") { + compile_java(target_name) { + forward_variables_from(invoker, "*") + enable_errorprone = invoker.enable_errorprone + javac_jar_path = invoker.javac_jar_path + + main_target_name = _main_target_name + build_config = _build_config + java_files = _java_files + if (_java_files != []) { + java_sources_file = _java_sources_file + } + srcjar_deps = _srcjar_deps + chromium_code = _chromium_code + requires_android = _requires_android + deps = _accumulated_deps + _accumulated_public_deps + + # android_apk and junit_binary pass R.java srcjars via srcjar_deps. + if (_type == "java_library" && _requires_android) { + _rebased_build_config = rebase_path(_build_config, root_build_dir) + srcjar_filearg = "@FileArg($_rebased_build_config:deps_info:owned_resource_srcjars)" + } + } + } + _analysis_public_deps = [] + _compile_java_target = "${_main_target_name}__compile_java" + _compile_java_forward_variables = [ + "additional_jar_files", + "apk_name", + "processor_args_javac", + "provider_configurations", + "javac_args", + ] + compile_java_helper(_compile_java_target) { + forward_variables_from(invoker, _compile_java_forward_variables) + enable_errorprone = false + javac_jar_path = _javac_jar_path + } + if (_enable_errorprone) { + _compile_java_errorprone_target = + "${_main_target_name}__compile_java_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 + } + javac_jar_path = _javac_jar_path + ".errorprone.jar" + } + _analysis_public_deps += [ ":$_compile_java_errorprone_target" ] + } + if (defined(invoker.android_manifest_for_lint)) { + _android_manifest_for_lint = invoker.android_manifest_for_lint + assert(_android_manifest_for_lint != "") # Mark as used. + } + if (_lint_enabled) { + _android_lint_target = "${_main_target_name}__lint" + android_lint(_android_lint_target) { + if (invoker.type == "android_apk" || + invoker.type == "android_app_bundle_module") { + forward_variables_from(invoker, [ "android_manifest" ]) + } else if (defined(_android_manifest_for_lint)) { + android_manifest = _android_manifest_for_lint + } + srcjar_deps = _srcjar_deps + build_config = _build_config + requires_android = _requires_android + deps = _accumulated_deps + _accumulated_public_deps + java_files = _java_files + if (_java_files != []) { + java_sources_file = _java_sources_file + } + if (defined(invoker.lint_suppressions_file)) { + lint_suppressions_file = invoker.lint_suppressions_file + } + } + _analysis_public_deps += [ ":$_android_lint_target" ] + } + + if (_analysis_public_deps != []) { + # Use an intermediate group() rather as the data_deps target in order to + # avoid errorprone or lint artifacts showing up as runtime_deps (while + # still having them run in parallel to other targets). + group("${_main_target_name}__analysis") { + public_deps = _analysis_public_deps + } + } + + # Update this after lint so that lint does not depend on javac. + _accumulated_public_deps += [ ":$_compile_java_target" ] + } # _has_sources + + if (defined(_final_jar_path)) { + if (_is_system_library) { + _copy_system_library_target_name = "${target_name}__copy_system_library" + + # Use copy_ex rather than copy to ensure that we copy symlink targets + # rather than the symlink itself. + copy_ex(_copy_system_library_target_name) { + sources = [ + _unprocessed_jar_path, + ] + dest = _final_jar_path + outputs = [ + _final_jar_path, + ] + } + _accumulated_public_deps += [ ":$_copy_system_library_target_name" ] + } else { + _process_prebuilt_target_name = "${target_name}__process_prebuilt" + process_java_prebuilt(_process_prebuilt_target_name) { + forward_variables_from(invoker, + [ + "enable_bytecode_checks", + "enable_bytecode_rewriter", + "jar_excluded_patterns", + "jar_included_patterns", + "split_compat_class_names", + ]) + is_prebuilt = _is_prebuilt + supports_android = _supports_android + enable_build_hooks = _enable_build_hooks + enable_build_hooks_android = _enable_build_hooks_android + build_config = _build_config + input_jar_path = _unprocessed_jar_path + emma_instrument = _emma_instrument + if (_emma_instrument) { + java_files = _java_files + java_sources_file = _java_sources_file + } + output_jar_path = _final_jar_path + if (_has_sources) { + deps = _accumulated_public_deps # compile & build_config + } else { + deps = _accumulated_deps + _accumulated_public_deps + } + } + _accumulated_public_deps += [ ":$_process_prebuilt_target_name" ] + + if (defined(_dex_path)) { + dex("${target_name}__dex") { + input_jars = [ _final_jar_path ] + output = _dex_path + deps = [ + ":$_process_prebuilt_target_name", + ] + } + _accumulated_public_deps += [ ":${target_name}__dex" ] + } + } + + if (!_is_java_binary) { + # Export the interface jar as the main target (rather than a group) + # so that ninja will notice when the output is unchanged and not rebuild + # reverse-dependencies. Targets that should be rebuilt when the + # non-interface .jar changes use a depfile to indicate that they should + # be rebuilt even when the interface jar does not change. + generate_interface_jar(target_name) { + forward_variables_from(invoker, + [ + "data", + "data_deps", + "deps", + "visibility", + ]) + + # Export all of our steps as "public", so that all outputs can be used + # as inputs to other targets. + public_deps = _accumulated_public_deps + + # 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 + if (_lint_enabled || _enable_errorprone) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${_main_target_name}__analysis" ] + } + + # 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 ijar doesn't use them, it's a convenient spot + # to list them. + # https://crbug.com/827197 + if (defined(invoker.proguard_configs)) { + inputs = invoker.proguard_configs + if (!defined(deps)) { + deps = [] + } + deps += _srcjar_deps # For the aapt-generated proguard rules. + } + } + } + } + + 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, + [ + "bootclasspath", + "main_class", + "wrapper_script_args", + ]) + build_config = _build_config + if (defined(_final_jar_path)) { + jar_path = _final_jar_path + } + script_name = _main_target_name + if (defined(invoker.wrapper_script_name)) { + script_name = invoker.wrapper_script_name + } + deps = _accumulated_public_deps + } + _accumulated_public_deps += [ ":${target_name}__java_binary_script" ] + } + + if (_is_java_binary || + (_is_annotation_processor && !defined(_final_jar_path))) { + group(target_name) { + forward_variables_from(invoker, + [ + "data", + "deps", + "data_deps", + "visibility", + ]) + public_deps = _accumulated_public_deps + if (_lint_enabled || _enable_errorprone) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ ":${_main_target_name}__analysis" ] + } + } + } + } +} + +# 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 ass 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. +# +template("create_android_app_bundle_module") { + _build_config = invoker.build_config + _rebased_build_config = rebase_path(_build_config, root_build_dir) + + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + "deps", + ]) + script = "//build/android/gyp/apkbuilder.py" + depfile = "$target_gen_dir/$target_name.d" + + # 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 through @FileArg() references (see below) and + # will be listed in the generated depfile instead. + inputs = [ + _build_config, + ] + outputs = [ + invoker.module_zip_path, + ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--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_build_config:native:libraries)", + "--native-libs=@FileArg($_rebased_build_config:native:extra_shared_libraries)", + "--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", + "--uncompress-shared-libraries=@FileArg(" + + "$_rebased_build_config:native:uncompress_shared_libraries)", + ] + if (defined(android_app_secondary_abi)) { + args += [ + "--secondary-native-libs=@FileArg(" + + "$_rebased_build_config:native:secondary_abi_libraries)", + "--secondary-android-abi=$android_app_secondary_abi", + ] + } + + # 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)" ] + } + } +} + +# 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. +template("dexsplitter") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "deps" ]) + script = "//build/android/gyp/dexsplitter.py" + inputs = [ + invoker.input_dex_zip, + ] + _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, + "--feature-jars=@FileArg($_rebased_module_build_config:deps_info:java_runtime_classpath)", + "--dex-dest=@FileArg($_rebased_module_build_config:final_dex:path)", + ] + deps += [ _feature_module.build_config_target ] + } + } +} diff --git a/deps/v8/build/config/android/linker_version_script.gni b/deps/v8/build/config/android/linker_version_script.gni new file mode 100644 index 0000000000..6cb3b09013 --- /dev/null +++ b/deps/v8/build/config/android/linker_version_script.gni @@ -0,0 +1,37 @@ +# 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_whitelist_file: Optional. Path to an input file containing +# a whitelist of exported symbols. +# 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_symbol_whitelist_file)) { + inputs += [ invoker.export_symbol_whitelist_file ] + args += + [ "--export-symbol-whitelist-file=" + + rebase_path(invoker.export_symbol_whitelist_file, root_build_dir) ] + } + } +} diff --git a/deps/v8/build/config/android/rules.gni b/deps/v8/build/config/android/rules.gni new file mode 100644 index 0000000000..4846ade15c --- /dev/null +++ b/deps/v8/build/config/android/rules.gni @@ -0,0 +1,4584 @@ +# 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/internal_rules.gni") +import("//build/config/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/dcheck_always_on.gni") +import("//build/config/python.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" ] +} + +if (is_hwasan) { + _sanitizer_runtimes = [ "$clang_base_path/lib/clang/$clang_version/lib/linux/libclang_rt.hwasan-$_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" ]) + + _libraries_list = "${target_gen_dir}/${target_name}_library_dependencies.list" + + _runtime_deps_file = "$target_gen_dir/${target_name}.runtimedeps" + _runtime_deps_target_name = "${target_name}__runtime_deps" + group(_runtime_deps_target_name) { + data = _sanitizer_runtimes + data_deps = [] + if (defined(invoker.deps)) { + data_deps += invoker.deps + } + write_runtime_deps = _runtime_deps_file + } + + _find_deps_target_name = "${target_name}__find_library_dependencies" + + # TODO(agrieve): Extract dependent libs from GN rather than readelf. + action_with_pydeps(_find_deps_target_name) { + deps = invoker.deps + [ ":$_runtime_deps_target_name" ] + script = "//build/android/gyp/write_ordered_libraries.py" + depfile = "$target_gen_dir/$target_name.d" + inputs = [ + invoker.binary, + _runtime_deps_file, + android_readelf, + ] + outputs = [ + _libraries_list, + ] + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--runtime-deps", + rebase_path(_runtime_deps_file, root_build_dir), + "--output", + rebase_path(_libraries_list, root_build_dir), + "--readelf", + rebase_path(android_readelf, 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:lib_paths)", + "--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 = [ + ":$_find_deps_target_name", + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } +} + +# Writes a script to root_out_dir/bin that passes --output-directory to the +# wrapped script, in addition to forwarding arguments. Most / all of these +# wrappers should be made deps of //tools/android:android_tools. +# +# Variables +# target: Script to wrap. +# flag_name: Default is "--output-directory" +# +# Example +# wrapper_script("foo_wrapper") { +# target = "//pkg/foo.py" +# } +template("wrapper_script") { + action_with_pydeps(target_name) { + _name = get_path_info(invoker.target, "name") + _output = "$root_out_dir/bin/$_name" + + script = "//build/android/gyp/create_tool_wrapper.py" + outputs = [ + _output, + ] + + # The target isn't actually used by the script, but it's nice to have GN + # check that it exists. + inputs = [ + invoker.target, + ] + args = [ + "--output", + rebase_path(_output, root_build_dir), + "--target", + rebase_path(invoker.target, root_build_dir), + "--output-directory", + rebase_path(root_out_dir, root_build_dir), + ] + if (defined(invoker.flag_name)) { + args += [ "--flag-name=${invoker.flag_name}" ] + } + } +} + +if (enable_java_templates) { + import("//build/config/sanitizers/sanitizers.gni") + import("//tools/grit/grit_rule.gni") + + # 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 + # jni_package: subdirectory path for generated bindings + # + # Example + # generate_jni("foo_jni") { + # sources = [ + # "android/java/src/org/chromium/foo/Foo.java", + # "android/java/src/org/chromium/foo/FooUtil.java", + # ] + # jni_package = "foo" + # } + template("generate_jni") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + _base_output_dir = "${target_gen_dir}/${target_name}" + _package_output_dir = "${_base_output_dir}/${invoker.jni_package}" + _jni_output_dir = "${_package_output_dir}/jni" + + 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 debugging_buildflags 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", + ] + } + + _foreach_target_name = "${target_name}__jni_gen" + action_foreach_with_pydeps(_foreach_target_name) { + script = "//base/android/jni_generator/jni_generator.py" + sources = invoker.sources + outputs = [ + "${_jni_output_dir}/{{source_name_part}}_jni.h", + ] + + args = [ + "--input_file={{source}}", + "--ptr_type=long", + "--output_dir", + rebase_path(_jni_output_dir, root_build_dir), + "--includes", + rebase_path(_jni_generator_include, _jni_output_dir), + ] + + if (use_hashed_jni_names) { + args += [ "--use_proxy_hash" ] + } + + if (enable_profiling) { + args += [ "--enable_profiling" ] + } + if (defined(invoker.namespace)) { + args += [ "-n ${invoker.namespace}" ] + } + if (enable_jni_tracing) { + args += [ "--enable_tracing" ] + } + } + + config("jni_includes_${target_name}") { + # TODO(cjhopman): #includes should probably all be relative to + # _base_output_dir. Remove that from this config once the includes are + # updated. + include_dirs = [ + _base_output_dir, + _package_output_dir, + ] + } + + group(target_name) { + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_foreach_target_name" ] + public_deps += _jni_generator_include_deps + public_configs = [ ":jni_includes_${target_name}" ] + } + } + + # 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. + # jni_package: subdirectory path for generated bindings + # 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 + # generate_jar_jni("foo_jni") { + # classes = [ + # "android/view/Foo.class", + # ] + # jni_package = "foo" + # } + template("generate_jar_jni") { + forward_variables_from(invoker, [ "testonly" ]) + + if (defined(invoker.jar_file)) { + _jar_file = invoker.jar_file + } else { + _jar_file = android_sdk_jar + } + + _always_mangle = defined(invoker.always_mangle) && invoker.always_mangle + + _base_output_dir = "${target_gen_dir}/${target_name}/${invoker.jni_package}" + _jni_output_dir = "${_base_output_dir}/jni" + + if (defined(invoker.jni_generator_include)) { + _jni_generator_include = invoker.jni_generator_include + } else { + _jni_generator_include = + "//base/android/jni_generator/jni_generator_helper.h" + } + + # TODO(cjhopman): make jni_generator.py support generating jni for multiple + # .class files from a .jar. + _jni_actions = [] + foreach(_class, invoker.classes) { + _classname = get_path_info(_class, "name") + _jni_target_name = "${target_name}__jni_${_classname}" + _jni_actions += [ ":$_jni_target_name" ] + action_with_pydeps(_jni_target_name) { + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//base/android/jni_generator/jni_generator.py" + inputs = [ + _jar_file, + ] + outputs = [ + "${_jni_output_dir}/${_classname}_jni.h", + ] + + args = [ + "--jar_file", + rebase_path(_jar_file, root_build_dir), + "--input_file", + _class, + "--ptr_type=long", + "--output_dir", + rebase_path(_jni_output_dir, root_build_dir), + "--includes", + rebase_path(_jni_generator_include, _jni_output_dir), + ] + + if (enable_profiling) { + args += [ "--enable_profiling" ] + } + if (enable_jni_tracing) { + args += [ "--enable_tracing" ] + } + if (_always_mangle) { + args += [ "--always_mangle" ] + } + } + } + + config("jni_includes_${target_name}") { + include_dirs = [ _base_output_dir ] + } + + group(target_name) { + public_deps = [] + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "visibility", + ]) + public_deps += _jni_actions + public_configs = [ ":jni_includes_${target_name}" ] + } + } + + # 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 + # target: The Apk target to use for the java sources list. + # header_output: Path to the generated .h file (optional). + # sources_blacklist: List of .java files that should be skipped. (optional) + # namespace: Registration functions will be wrapped into this. (optional) + # + # Example + # generate_jni_registration("chrome_jni_registration") { + # target = ":chrome_public_apk" + # header_output = "$target_gen_dir/$target_name.h" + # sources_blacklist = [ + # "//path/to/Exception.java", + # ] + # } + template("generate_jni_registration") { + action_with_pydeps(target_name) { + forward_variables_from(invoker, [ "testonly" ]) + _build_config = get_label_info(invoker.target, "target_gen_dir") + "/" + + get_label_info(invoker.target, "name") + ".build_config" + _rebased_build_config = rebase_path(_build_config, root_build_dir) + _srcjar_output = "$target_gen_dir/$target_name.srcjar" + + script = "//base/android/jni_generator/jni_registration_generator.py" + deps = [ + "${invoker.target}$build_config_target_suffix", + ] + inputs = [ + _build_config, + ] + outputs = [ + _srcjar_output, + ] + depfile = "$target_gen_dir/$target_name.d" + + args = [ + # This is a list of .sources files. + "--sources-files=@FileArg($_rebased_build_config:deps_info:jni:all_source)", + "--srcjar-path", + rebase_path(_srcjar_output, root_build_dir), + "--depfile", + rebase_path(depfile, root_build_dir), + ] + + 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_blacklist)) { + _rebase_sources_blacklist = + rebase_path(invoker.sources_blacklist, root_build_dir) + args += [ "--sources-blacklist=$_rebase_sources_blacklist" ] + } + + 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. + # package_path: this will be the subdirectory for each .java file in the + # .srcjar. + # + # Example + # java_cpp_template("foo_generated_enum") { + # sources = [ + # "android/java/templates/Foo.template", + # ] + # inputs = [ + # "android/java/templates/native_foo_header.h", + # ] + # + # package_path = "org/chromium/base/library_loader" + # include_path = "android/java/templates" + # } + template("java_cpp_template") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + _include_path = "//" + if (defined(invoker.include_path)) { + _include_path = invoker.include_path + } + + _apply_gcc_target_name = "${target_name}__apply_gcc" + _base_gen_dir = "${target_gen_dir}/${target_name}/java_cpp_template" + _package_path = invoker.package_path + + action_foreach_with_pydeps(_apply_gcc_target_name) { + forward_variables_from(invoker, + [ + "deps", + "inputs", + "public_deps", + "data_deps", + ]) + script = "//build/android/gyp/gcc_preprocess.py" + depfile = + "${target_gen_dir}/${invoker.target_name}_{{source_name_part}}.d" + + sources = invoker.sources + + outputs = [ + "$_base_gen_dir/${_package_path}/{{source_name_part}}.java", + ] + + args = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--include-path", + rebase_path(_include_path, root_build_dir), + "--output", + rebase_path(outputs[0], root_build_dir), + "--template={{source}}", + ] + + if (defined(invoker.defines)) { + foreach(_def, invoker.defines) { + args += [ + "--defines", + _def, + ] + } + } + } + + # Filter out .d files. + set_sources_assignment_filter([ "*.d" ]) + sources = get_target_outputs(":$_apply_gcc_target_name") + + zip(target_name) { + forward_variables_from(invoker, [ "visibility" ]) + inputs = sources + output = "${target_gen_dir}/${target_name}.srcjar" + base_dir = _base_gen_dir + deps = [ + ":$_apply_gcc_target_name", + ] + } + } + + # 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") { + set_sources_assignment_filter([]) + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "sources", + "testonly", + "visibility", + ]) + + # The sources aren't compiled so don't check their dependencies. + check_includes = false + script = "//build/android/gyp/java_cpp_enum.py" + depfile = "$target_gen_dir/$target_name.d" + + _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 = [ + "--depfile", + rebase_path(depfile, root_build_dir), + "--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") { + set_sources_assignment_filter([]) + action_with_pydeps(target_name) { + forward_variables_from(invoker, + [ + "sources", + "testonly", + "visibility", + ]) + + # 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 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, + [ + "visibility", + "deps", + "testonly", + ]) + 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}" ] + } + } + } + + # 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: 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_name = ":my_resources__create_zip" + # } + # + template("android_generated_resources") { + forward_variables_from(invoker, [ "testonly" ]) + + _build_config = "$target_gen_dir/${target_name}.build_config" + + write_build_config("$target_name$build_config_target_suffix") { + build_config = _build_config + resources_zip = invoker.generated_resources_zip + type = "android_resources" + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + } + + group(target_name) { + public_deps = [ + ":$target_name$build_config_target_suffix", + invoker.generating_target_name, + ] + } + } + + # 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") { + # JUnit tests use resource zip files. These must not be put in gen/ + # directory or they will not be available to tester bots. + _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir) + _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip" + + _generating_target_name = "${target_name}__template" + + action_with_pydeps(_generating_target_name) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + 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, + [ + "deps", + "testonly", + ]) + generating_target_name = ":$_generating_target_name" + generated_resources_zip = _resources_zip + } + } + + # 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 + # 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. + # resource_dirs: List of directories containing resources for this target. + # generated_resource_dirs: List of directories containing resources for this + # target which are *generated* by a dependency. |generated_resource_files| + # must be specified if |generated_resource_dirs| is specified. + # generated_resource_files: List of all files in |generated_resource_dirs|. + # |generated_resource_dirs| must be specified in |generated_resource_files| + # is specified. + # 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. + # v14_skip: If true, don't run v14 resource generator on this. Defaults to + # false. (see build/android/gyp/generate_v14_compatible_resources.py) + # shared_resources: If true make a resource package that can be loaded by a + # different application at runtime to access the package's resources. + # r_text_file: (optional) path to pre-generated R.txt to be used when + # generating R.java instead of resource-based aapt-generated one. + # create_srcjar: If false, does not create an R.java file. Needed only for + # prebuilts that have R.txt files that do not match their res/ + # (Play Services). + # + # Example: + # android_resources("foo_resources") { + # deps = [":foo_strings_grd"] + # resource_dirs = ["res"] + # custom_package = "org.chromium.foo" + # } + # + # android_resources("foo_resources_overrides") { + # deps = [":foo_resources"] + # resource_dirs = ["res_overrides"] + # } + template("android_resources") { + forward_variables_from(invoker, [ "testonly" ]) + + _base_path = "$target_gen_dir/$target_name" + + # JUnit tests use resource zip files. These must not be put in gen/ + # directory or they will not be available to tester bots. + _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir) + _zip_path = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip" + _r_text_out_path = _base_path + "_R.txt" + _build_config = _base_path + ".build_config" + _build_config_target_name = "$target_name$build_config_target_suffix" + + if (!defined(invoker.create_srcjar) || invoker.create_srcjar) { + _srcjar_path = _base_path + ".srcjar" + } + + _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" ] + } + + write_build_config(_build_config_target_name) { + type = "android_resources" + build_config = _build_config + resources_zip = _zip_path + + resource_dirs = invoker.resource_dirs + if (defined(invoker.generated_resource_dirs)) { + resource_dirs += invoker.generated_resource_dirs + } + + if (defined(_srcjar_path)) { + forward_variables_from(invoker, + [ + "android_manifest", + "android_manifest_dep", + "custom_package", + ]) + + # No package means resources override their deps. + if (defined(custom_package) || defined(android_manifest)) { + r_text = _r_text_out_path + } else { + assert(defined(invoker.deps), + "Must specify deps when custom_package is omitted.") + } + srcjar = _srcjar_path + } + + possible_config_deps = _deps + } + + prepare_resources(target_name) { + forward_variables_from(invoker, + [ + "android_manifest", + "custom_package", + "generated_resource_dirs", + "generated_resource_files", + "resource_dirs", + "v14_skip", + "strip_drawables", + ]) + deps = _deps + deps += [ ":$_build_config_target_name" ] + if (defined(invoker.android_manifest_dep)) { + deps += [ invoker.android_manifest_dep ] + } + + build_config = _build_config + zip_path = _zip_path + r_text_out_path = _r_text_out_path + + if (defined(invoker.r_text_file)) { + r_text_in_path = invoker.r_text_file + } + if (defined(_srcjar_path)) { + srcjar_path = _srcjar_path + } + + # Always generate R.onResourcesLoaded() method, it is required for + # compiling ResourceRewriter, there is no side effect because the + # generated R.class isn't used in final apk. + shared_resources = true + } + } + + # 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" ]) + + _build_config = "$target_gen_dir/$target_name.build_config" + _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", + "visibility", + ]) + 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") { + forward_variables_from(invoker, + [ + "testonly", + "input_jars_paths", + ]) + write_build_config("$target_name$build_config_target_suffix") { + type = "group" + build_config = "$target_gen_dir/${invoker.target_name}.build_config" + supports_android = true + if (defined(invoker.deps)) { + possible_config_deps = invoker.deps + } + } + group(target_name) { + forward_variables_from(invoker, "*") + if (!defined(deps)) { + deps = [] + } + deps += [ ":$target_name$build_config_target_suffix" ] + } + } + + # Declare a target that generates localized strings.xml from a .grd file. + # + # If this target is included in the deps of an android resources/library/apk, + # the strings.xml will be included with that target. + # + # Variables + # deps: Specifies the dependencies of this target. + # grd_file: Path to the .grd file to generate strings.xml from. + # outputs: Expected grit outputs (see grit rule). + # + # Example + # java_strings_grd("foo_strings_grd") { + # grd_file = "foo_strings.grd" + # } + template("java_strings_grd") { + forward_variables_from(invoker, [ "testonly" ]) + + # JUnit tests use resource zip files. These must not be put in gen/ + # directory or they will not be available to tester bots. + _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir) + _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip" + + _grit_target_name = "${target_name}__grit" + _grit_output_dir = "$target_gen_dir/${target_name}_grit_output" + + grit(_grit_target_name) { + forward_variables_from(invoker, + [ + "deps", + "defines", + ]) + grit_flags = [ + "-E", + "ANDROID_JAVA_TAGGED_ONLY=false", + ] + output_dir = _grit_output_dir + resource_ids = "" + source = invoker.grd_file + outputs = invoker.outputs + } + + _zip_target_name = "${target_name}__zip" + + zip(_zip_target_name) { + base_dir = _grit_output_dir + + # This needs to get outputs from grit's internal target, not the final + # source_set. + inputs = get_target_outputs(":${_grit_target_name}_grit") + output = _resources_zip + deps = [ + ":$_grit_target_name", + ] + } + + android_generated_resources(target_name) { + generating_target_name = ":$_zip_target_name" + generated_resources_zip = _resources_zip + } + } + + # Declare a target that packages strings.xml generated from a grd file. + # + # If this target is included in the deps of an android resources/library/apk, + # the strings.xml will be included with that target. + # + # Variables + # grit_output_dir: directory containing grit-generated files. + # generated_files: list of android resource files to package. + # + # Example + # java_strings_grd_prebuilt("foo_strings_grd") { + # grit_output_dir = "$root_gen_dir/foo/grit" + # generated_files = [ + # "values/strings.xml" + # ] + # } + template("java_strings_grd_prebuilt") { + forward_variables_from(invoker, [ "testonly" ]) + + # JUnit tests use resource zip files. These must not be put in gen/ + # directory or they will not be available to tester bots. + _resources_zip_rebased_path = rebase_path(target_gen_dir, root_gen_dir) + _resources_zip = "${root_out_dir}/resource_zips/${_resources_zip_rebased_path}/${target_name}.resources.zip" + + _zip_target_name = "${target_name}__zip" + + zip(_zip_target_name) { + forward_variables_from(invoker, [ "visibility" ]) + + base_dir = invoker.grit_output_dir + inputs = rebase_path(invoker.generated_files, ".", base_dir) + output = _resources_zip + if (defined(invoker.deps)) { + deps = invoker.deps + } + } + + android_generated_resources(target_name) { + generating_target_name = ":$_zip_target_name" + generated_resources_zip = _resources_zip + } + } + + # 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") { + # java_files = [ "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, "*") + type = "java_binary" + } + } + + # Declare a Java Annotation Processor. + # + # Supports all variables of java_library(), plus: + # jar_path: Path to a prebuilt jar. Mutually exclusive with java_files & + # srcjar_deps. + # main_class: The fully-quallified class name of the processor's entry + # point. + # + # Example + # java_annotation_processor("foo_processor") { + # java_files = [ "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, "*") + 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") { + # java_files = [ "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" + _build_config_target_name = "$target_name$build_config_target_suffix" + _deps = [ + "//testing/android/junit:junit_test_support", + "//third_party/junit", + "//third_party/mockito:mockito_java", + "//third_party/robolectric:robolectric_all_java", + + # This dep is required if any deps require android (but it doesn't hurt + # to add it regardless) and is used by bytecode rewritten classes. + "//build/android/buildhooks:build_hooks_android_impl_java", + ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + # 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_path)) { + _package_name = "org.chromium.test" + } + + _prepare_resources_target = "${target_name}__prepare_resources" + prepare_resources(_prepare_resources_target) { + deps = _deps + [ ":$_build_config_target_name" ] + build_config = _build_config + srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + if (defined(_package_name)) { + custom_package = _package_name + } + if (defined(invoker.android_manifest_path)) { + android_manifest = invoker.android_manifest_path + } else { + android_manifest = "//build/android/AndroidManifest.xml" + } + } + + _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 + target = ":$_outer_target_name" + } + + java_library_impl(_java_binary_target_name) { + forward_variables_from(invoker, "*", [ "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" + if (!defined(srcjar_deps)) { + srcjar_deps = [] + } + srcjar_deps += [ + ":$_jni_srcjar_target", + ":$_prepare_resources_target", + + # This dep is required for any targets that depend on //base:base_java. + "//base:base_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 + forward_variables_from(invoker, [ "android_manifest_path" ]) + if (defined(_package_name)) { + package_name = _package_name + } + } + + group(target_name) { + 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. + # annotation_processor_deps: List of java_annotation_processor targets to + # use when compiling. + # + # jar_path: Path to a prebuilt jar. Mutually exclusive with java_files & + # srcjar_deps. + # java_files: List of .java files included in this library. + # srcjar_deps: List of srcjar dependencies. The .java files in the srcjars + # will be added to java_files 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. + # classpath_deps: Deps that should added to the classpath for this target, + # but not linked into the apk (use this for annotation processors). + # + # chromium_code: If true, extra analysis warning/errors will be enabled. + # enable_errorprone: If true, enables the errorprone compiler. + # + # 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. + # + # 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. + # + # 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") { + # java_files = [ + # "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, "*") + 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, "*") + 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" + # } + # dist_jar("sideloaded_dex") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # dex_path = "$root_build_dir/MyLibrary.dex" + # } + template("dist_jar") { + forward_variables_from(invoker, [ "testonly" ]) + _supports_android = + !defined(invoker.supports_android) || invoker.supports_android + _requires_android = + defined(invoker.requires_android) && invoker.requires_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" ] + } + _enable_build_hooks = + _supports_android && + (!defined(invoker.no_build_hooks) || !invoker.no_build_hooks) + if (_enable_build_hooks && _requires_android) { + _deps += [ "//build/android/buildhooks:build_hooks_android_impl_java" ] + } + + if (defined(invoker.override_build_config)) { + _build_config = invoker.override_build_config + } else { + _build_config = "$target_gen_dir/$target_name.build_config" + _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 = _requires_android + possible_config_deps = _deps + 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:java_runtime_classpath)" ] + } + } + if (defined(invoker.jar_excluded_patterns)) { + args += + [ "--input-zips-excluded-globs=${invoker.jar_excluded_patterns}" ] + } + } + } + + # Combines all dependent .jar files into a single proguarded .dex file. + # + # Variables: + # output: Path to the output dex. + # proguard_configs: List of proguard configs. + # proguard_jar_path: The path to proguard.jar you wish to use. If undefined, + # the proguard used will be the checked in one in //third_party/proguard. + # + # Example + # dist_dex("lib_fatjar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # } + # dist_jar("sideloaded_dex") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.jar" + # dex_path = "$root_build_dir/MyLibrary.dex" + # } + template("proguarded_dist_dex") { + _deps = [ + "//third_party/android_sdk:android_sdk_java", + "//build/android/buildhooks:build_hooks_android_impl_java", + ] + if (defined(invoker.deps)) { + _deps += invoker.deps + } + + _build_config = "$target_gen_dir/$target_name.build_config" + _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" ]) + supports_android = true + requires_android = true + proguard_enabled = true + possible_config_deps = _deps + build_config = _build_config + } + + _deps += [ ":$_build_config_target_name" ] + + dex(target_name) { + deps = _deps + build_config = _build_config + proguard_enabled = true + forward_variables_from(invoker, + [ + "proguard_configs", + "min_sdk_version", + ]) + output = invoker.output + } + } + + # 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). + # + # Example + # dist_aar("my_aar") { + # deps = [ ":my_java_lib" ] + # output = "$root_build_dir/MyLibrary.aar" + # } + template("dist_aar") { + forward_variables_from(invoker, [ "testonly" ]) + + _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" + _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 + 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:resources:dependency_zips)", + "--r-text-files=@FileArg($_rebased_build_config:resources:extra_r_text_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", + ] + } + } + } + + # Declare an Android library target + # + # This target creates an Android library containing java code and Android + # resources. + # + # Supports all variables of java_library(), plus: + # android_manifest_for_lint: Path to AndroidManifest.xml (optional). This + # manifest will be used by Android lint, but will not be merged into apks. + # To have a manifest merged, add it to an android_resources() target. + # deps: In addition to defining java deps, this can also include + # android_assets() and android_resources() targets. + # dex_path: If set, the resulting .dex.jar file will be placed under this + # path. + # 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") { + # java_files = [ + # "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, "*") + + 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", + ] + if (use_hashed_jni_names) { + jar_excluded_patterns += [ "J/N.class" ] + } else { + jar_excluded_patterns += [ "*/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, "*") + } + } + + template("android_system_java_prebuilt") { + java_library_impl(target_name) { + forward_variables_from(invoker, "*") + no_build_hooks = true + supports_android = true + type = "system_java_library" + } + } + + # Creates org/chromium/base/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. All other variables are + # ignored when this is false. + # build_config: Path to build_config used for locale list + # enable_multidex: Value for ENABLE_MULTIDEX. + # firebase_app_id: Value for FIREBASE_APP_ID. + # min_sdk_version: Value for MIN_SDK_VERSION. + # + template("generate_build_config_srcjar") { + java_cpp_template(target_name) { + package_path = "org/chromium/base" + sources = [ + "//base/android/java/templates/BuildConfig.template", + ] + defines = [] + + # TODO(agrieve): These two are not target-specific and should be moved + # to BuildHooks.java. + # Set these even when !use_final_fields so that they have correct default + # values withnin junit_binary(). + if (is_java_debug || dcheck_always_on) { + defines += [ "_DCHECK_IS_ON" ] + } + if (use_cfi_diag || is_ubsan || is_ubsan_security || is_ubsan_vptr) { + defines += [ "_IS_UBSAN" ] + } + + if (invoker.use_final_fields) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + defines += [ "USE_FINAL" ] + if (invoker.enable_multidex) { + defines += [ "ENABLE_MULTIDEX" ] + } + inputs = [ + invoker.build_config, + ] + _rebased_build_config = + rebase_path(invoker.build_config, root_build_dir) + defines += [ + "COMPRESSED_LOCALE_LIST=" + + "@FileArg($_rebased_build_config:compressed_locales_java_list)", + "UNCOMPRESSED_LOCALE_LIST=" + + "@FileArg($_rebased_build_config:uncompressed_locales_java_list)", + ] + if (defined(invoker.firebase_app_id)) { + defines += [ "_FIREBASE_APP_ID=${invoker.firebase_app_id}" ] + } + 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}", + ] + } + } + } + } + + # 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. + # 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 for _incremental targets. + # * 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). + # write_asset_list: Adds an extra file to the assets, which contains a list of + # all other asset files. + # generate_buildconfig_java: If defined and false, skip generating the + # BuildConfig java class describing the build configuration. The default + # is true 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_blacklist: List of source path to exclude from the + # final_jni step. + # firebase_app_id: The value for BuildConfig.FIREBASE_APP_ID (optional). + # Identifier is sent with crash reports to enable Java stack deobfuscation. + # aapt_locale_whitelist: If set, all locales not in this list will be + # stripped from resources.arsc. + # resource_blacklist_regex: Causes all drawable images matching the regex to + # be excluded (mipmaps are still included). + # resource_blacklist_exceptions: A list of globs used when + # resource_blacklist_regex is set. Files that match this whitelist will + # still be included. + # 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_whitelist_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. + # optimize_resources: True if resource names should be stripped from the + # resources.arsc file in the apk or module. + # resources_config_path: Path to the aapt2 optimize config file that tags + # resources with acceptable/non-acceptable optimizations. + # verify_android_configuration: Enables verification of expected merged + # manifest and proguard flags based on a golden file. + template("android_apk_or_module") { + forward_variables_from(invoker, [ "testonly" ]) + + assert(defined(invoker.final_apk_path) || defined(invoker.name)) + assert(defined(invoker.android_manifest)) + _gen_dir = "$target_gen_dir/$target_name" + _base_path = "$_gen_dir/$target_name" + _build_config = "$target_gen_dir/$target_name.build_config" + _build_config_target = "$target_name$build_config_target_suffix" + + # Mark as used + assert(!defined(invoker.min_sdk_version) || invoker.min_sdk_version != 0) + + # JUnit tests use resource zip files. These must not be put in gen/ + # directory or they will not be available to tester bots. + _jar_path = "$_base_path.jar" + _lib_dex_path = "$_base_path.dex.jar" + _template_name = target_name + + _is_bundle_module = + defined(invoker.is_bundle_module) && invoker.is_bundle_module + _is_base_module = defined(invoker.is_base_module) && invoker.is_base_module + + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + _final_dex_path = "$_gen_dir/classes.dex.zip" + + if (defined(invoker.final_apk_path)) { + _final_apk_path = invoker.final_apk_path + } else { + _final_apk_path = "$root_build_dir/apks/${invoker.name}.apk" + } + if (!_is_bundle_module) { + _final_rtxt_path = "${_final_apk_path}.R.txt" + } + _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] + assert(_final_apk_path_no_ext != "") # Mark as used. + + # Non-base bundle modules create only proto resources. + if (!_is_bundle_module || _is_base_module) { + _packaged_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_gen_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_" + } + _optimize_resources = + defined(invoker.optimize_resources) && invoker.optimize_resources + if (_optimize_resources) { + _optimized_resources_path = "$target_out_dir/$_template_name.optimized." + if (_is_bundle_module) { + _optimized_resources_path += ".proto.ap_" + } else { + _optimized_resources_path += ".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 + } + + _use_build_hooks = + !defined(invoker.no_build_hooks) || !invoker.no_build_hooks + if (defined(invoker.build_hooks_android_impl_deps)) { + assert(_use_build_hooks, + "Cannot set no_build_hooks and build_hooks_android_impl_deps at " + + "the same time") + _deps += invoker.build_hooks_android_impl_deps + } else if (_use_build_hooks) { + _deps += [ "//build/android/buildhooks:build_hooks_android_impl_java" ] + } + + _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 + + _load_library_from_apk = + defined(invoker.load_library_from_apk) && invoker.load_library_from_apk + + assert(_use_chromium_linker || true) # Mark as used. + 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 != [] + _secondary_abi_native_libs_deps = [] + assert(_secondary_abi_native_libs_deps == []) # mark as used. + _secondary_abi_shared_libraries_is_valid = + defined(invoker.secondary_abi_shared_libraries) && + invoker.secondary_abi_shared_libraries != [] + + if (_shared_libraries_is_valid) { + _native_libs_deps += invoker.shared_libraries + + # To determine the filenames of all dependent shared libraries, write the + # runtime deps of |shared_libraries| to a file during "gn gen". + # write_build_config.py will then grep this file for *.so to obtain the + # complete list. + _runtime_deps_file = + "$target_gen_dir/${_template_name}.native.runtimedeps" + group("${_template_name}__runtime_deps") { + deps = _native_libs_deps + write_runtime_deps = _runtime_deps_file + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__runtime_deps") { + } + } + + if (_secondary_abi_shared_libraries_is_valid) { + _secondary_abi_native_libs_deps += invoker.secondary_abi_shared_libraries + + # To determine the filenames of all dependent shared libraries, write the + # runtime deps of |shared_libraries| to a file during "gn gen". + # write_build_config.py will then grep this file for *.so to obtain the + # complete list. + _secondary_abi_runtime_deps_file = + "$target_gen_dir/${_template_name}.secondary.abi.native.runtimedeps" + group("${_template_name}__secondary_abi__runtime_deps") { + deps = _secondary_abi_native_libs_deps + write_runtime_deps = _secondary_abi_runtime_deps_file + } + } else { + # Must exist for instrumentation_test_apk() to depend on. + group("${_template_name}__secondary_abi__runtime_deps") { + } + } + + if (_shared_libraries_is_valid || + _secondary_abi_shared_libraries_is_valid) { + _native_lib_version_rule = "" + if (defined(invoker.native_lib_version_rule)) { + _native_lib_version_rule = invoker.native_lib_version_rule + } + _native_lib_version_arg = "\"\"" + if (defined(invoker.native_lib_version_arg)) { + _native_lib_version_arg = invoker.native_lib_version_arg + } + } + + _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 + } + + # 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 (_proguard_enabled) { + _proguard_mapping_path = "$_final_apk_path.mapping" + } + + # TODO(crbug.com/864142): Allow incremental installs of bundle modules. + _incremental_allowed = + !_is_bundle_module && + !(defined(invoker.never_incremental) && invoker.never_incremental) + if (_incremental_allowed) { + _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" + } + + _verify_android_configuration = + defined(invoker.verify_android_configuration) && + invoker.verify_android_configuration && !is_java_debug + if (_verify_android_configuration) { + _target_src_dir = get_label_info(":$target_name", "dir") + } + + _android_manifest = + "$target_gen_dir/${_template_name}_manifest/AndroidManifest.xml" + _merge_manifest_target = "${_template_name}__merge_manifests" + merge_manifests(_merge_manifest_target) { + input_manifest = _android_root_manifest + output_manifest = _android_manifest + build_config = _build_config + if (_verify_android_configuration) { + expected_manifest = + "$_target_src_dir/java/$_template_name.AndroidManifest.expected" + } + deps = _android_root_manifest_deps + [ ":$_build_config_target" ] + } + + _final_deps = [] + + _enable_main_dex_list = + _enable_multidex && + (!defined(invoker.min_sdk_version) || invoker.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)) { + _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(invoker.shared_resources_whitelist_target)) { + _whitelist_gen_dir = + get_label_info(invoker.shared_resources_whitelist_target, + "target_gen_dir") + _whitelist_target_name = + get_label_info(invoker.shared_resources_whitelist_target, "name") + _whitelist_r_txt_path = + "${_whitelist_gen_dir}/${_whitelist_target_name}" + + "__compile_resources_R.txt" + _whitelist_deps = + "${invoker.shared_resources_whitelist_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_whitelist", + "app_as_shared_lib", + "no_xml_namespaces", + "package_name", + "package_name_to_id_mapping", + "png_to_webp", + "resource_blacklist_exceptions", + "resource_blacklist_regex", + "resource_ids_provider_dep", + "resources_config_path", + "shared_resources", + "shared_resources_whitelist_locales", + "support_zh_hk", + ]) + android_manifest = _android_manifest + version_code = _version_code + version_name = _version_name + + if (defined(invoker.post_process_package_resources_script)) { + post_process_script = invoker.post_process_package_resources_script + } + srcjar_path = "${target_gen_dir}/${target_name}.srcjar" + r_text_out_path = _compile_resources_rtxt_out + emit_ids_out_path = _compile_resources_emit_ids_out + proguard_file = _generated_proguard_config + if (_enable_main_dex_list) { + proguard_file_main_dex = _generated_proguard_main_dex_config + } + + build_config = _build_config + deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + _android_sdk_dep, + ] + + 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. + arsc_package_name = + "@FileArg($_rebased_build_config:resources: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 + + deps += [ "${invoker.apk_under_test}__compile_resources" ] + include_resource = + get_label_info(invoker.apk_under_test, "target_out_dir") + "/" + + get_label_info(invoker.apk_under_test, "name") + ".ap_" + } + + if (_is_bundle_module) { + proto_format = true + output = _proto_resources_path + + if (defined(invoker.base_module_target)) { + deps += [ "${invoker.base_module_target}__compile_arsc_resources" ] + include_resource = + get_label_info(invoker.base_module_target, "target_out_dir") + + "/" + get_label_info(invoker.base_module_target, "name") + ".ap_" + } + } else { + output = _packaged_resources_path + } + + if (_optimize_resources) { + optimized_resources_path = _optimized_resources_path + } + + if (defined(invoker.shared_resources_whitelist_target)) { + # Used to ensure that the WebView resources are properly shared + # (i.e. are non-final and with package ID 0). + shared_resources_whitelist = _whitelist_r_txt_path + deps += [ _whitelist_deps ] + } + } + 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 = [ + _packaged_resources_path, + ] + outputs = [ + _resource_sizes_arsc_path, + ] + } + _final_deps += [ ":$_copy_arsc_target" ] + } + + 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 (_is_base_module && _is_bundle_module) { + # Bundle modules have to reference resources from the base module. + # However, to compile the bundle module's resources we have to give it an + # arsc resource to link against (aapt2 fails with proto resources). Thus, + # add an arsc resource compilation step to make the bundle module's link + # step work. + compile_resources("${_template_name}__compile_arsc_resources") { + forward_variables_from(invoker, + [ + "support_zh_hk", + "aapt_locale_whitelist", + "resource_blacklist_regex", + "resource_blacklist_exceptions", + "png_to_webp", + "no_xml_namespaces", + ]) + android_manifest = _android_manifest + version_code = _version_code + version_name = _version_name + + proto_format = false + output = _packaged_resources_path + + build_config = _build_config + deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + _android_sdk_dep, + ] + } + } + + _srcjar_deps += [ ":$_compile_resources_target" ] + + if (_native_libs_deps != [] || _secondary_abi_native_libs_deps != []) { + _enable_chromium_linker_tests = false + if (defined(invoker.enable_chromium_linker_tests)) { + _enable_chromium_linker_tests = invoker.enable_chromium_linker_tests + } + _ordered_libraries_json = + "$target_gen_dir/$target_name.ordered_libraries.json" + _rebased_ordered_libraries_json = + rebase_path(_ordered_libraries_json, root_build_dir) + _ordered_libraries_target = "${_template_name}__write_ordered_libraries" + + # TODO(agrieve): Make GN write runtime deps in dependency order so as to + # not need this manual sorting step. + action_with_pydeps(_ordered_libraries_target) { + script = "//build/android/gyp/write_ordered_libraries.py" + deps = [ + ":$_build_config_target", + ":${_template_name}__runtime_deps", + ":${_template_name}__secondary_abi__runtime_deps", + ] + if (_native_libs_deps != []) { + _deps_file_to_use = _runtime_deps_file + } else { + _deps_file_to_use = _secondary_abi_runtime_deps_file + } + inputs = [ + _deps_file_to_use, + ] + outputs = [ + _ordered_libraries_json, + ] + _rebased_android_readelf = rebase_path(android_readelf, root_build_dir) + args = [ + "--readelf=$_rebased_android_readelf", + "--output=$_rebased_ordered_libraries_json", + "--runtime-deps=" + rebase_path(_deps_file_to_use, root_build_dir), + ] + if (defined(invoker.dont_load_shared_libraries)) { + args += [ "--exclude-shared-libraries=" + + invoker.dont_load_shared_libraries ] + } + } + + java_cpp_template("${_template_name}__native_libraries_srcjar") { + package_path = "org/chromium/base/library_loader" + sources = [ + "//base/android/java/templates/NativeLibraries.template", + ] + inputs = [ + _ordered_libraries_json, + ] + deps = [ + ":${_ordered_libraries_target}", + ] + if (_native_lib_version_rule != "") { + deps += [ _native_lib_version_rule ] + } + + defines = [ + "NATIVE_LIBRARIES_LIST=" + + "@FileArg($_rebased_ordered_libraries_json:java_libraries_list)", + "NATIVE_LIBRARIES_VERSION_NUMBER=$_native_lib_version_arg", + ] + if (current_cpu == "arm" || current_cpu == "arm64") { + defines += [ "ANDROID_APP_CPU_FAMILY_ARM" ] + } else if (current_cpu == "x86" || current_cpu == "x64") { + defines += [ "ANDROID_APP_CPU_FAMILY_X86" ] + } else if (current_cpu == "mipsel" || current_cpu == "mips64el") { + defines += [ "ANDROID_APP_CPU_FAMILY_MIPS" ] + } else { + assert(false, "Unsupported CPU family") + } + if (_use_chromium_linker) { + defines += [ "ENABLE_CHROMIUM_LINKER" ] + } + if (_load_library_from_apk) { + defines += [ "ENABLE_CHROMIUM_LINKER_LIBRARY_IN_ZIP_FILE" ] + } + if (_enable_chromium_linker_tests) { + defines += [ "ENABLE_CHROMIUM_LINKER_TESTS" ] + } + } + _srcjar_deps += [ ":${_template_name}__native_libraries_srcjar" ] + } + + _extra_native_libs = [] + _extra_native_libs_deps = [] + assert(_extra_native_libs_deps == []) # Mark as used. + if (_native_libs_deps != []) { + _extra_native_libs += _sanitizer_runtimes + if (_use_chromium_linker) { + _extra_native_libs += + [ "$root_out_dir/libchromium_android_linker$shlib_extension" ] + _extra_native_libs_deps += + [ "//base/android/linker:chromium_android_linker" ] + } + } + + if (_generate_buildconfig_java) { + generate_build_config_srcjar("${_template_name}__build_config_srcjar") { + forward_variables_from(invoker, + [ + "firebase_app_id", + "min_sdk_version", + ]) + use_final_fields = true + build_config = _build_config + enable_multidex = _enable_multidex + 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_final_jni) { + generate_jni_registration("${_template_name}__final_jni") { + target = ":$_template_name" + if (defined(invoker.jni_registration_header)) { + header_output = invoker.jni_registration_header + } + if (defined(invoker.jni_sources_blacklist)) { + sources_blacklist = invoker.jni_sources_blacklist + } + } + _srcjar_deps += [ ":${_template_name}__final_jni" ] + } + + _java_target = "${_template_name}__java" + java_library_impl(_java_target) { + forward_variables_from(invoker, + [ + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "apk_under_test", + "base_module_target", + "chromium_code", + "classpath_deps", + "emma_never_instrument", + "java_files", + "javac_args", + "loadable_modules", + "native_lib_placeholders", + "no_build_hooks", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + "static_library_dependent_targets", + ]) + if (_is_bundle_module) { + type = "android_app_bundle_module" + } else { + type = "android_apk" + } + main_target_name = _template_name + supports_android = true + requires_android = true + deps = _deps + + srcjar_deps = _srcjar_deps + final_jar_path = _jar_path + dex_path = _lib_dex_path + final_dex_path = _final_dex_path + + if (_is_bundle_module) { + proto_resources_path = _proto_resources_path + module_rtxt_path = _compile_resources_rtxt_out + } else { + apk_path = _final_apk_path + incremental_allowed = _incremental_allowed + if (_incremental_allowed) { + incremental_apk_path = "${_final_apk_path_no_ext}_incremental.apk" + 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_main_dex_list) { + proguard_configs += [ "//build/android/multidex.flags" ] + } + proguard_mapping_path = _proguard_mapping_path + } + + # Don't depend on the runtime_deps target in order to avoid having to + # build the native libraries just to create the .build_config file. + # The dep is unnecessary since the runtime_deps file is created by gn gen + # and the runtime_deps file is added to write_build_config.py's depfile. + if (_native_libs_deps != []) { + shared_libraries_runtime_deps_file = _runtime_deps_file + } + if (_secondary_abi_native_libs_deps != []) { + secondary_abi_shared_libraries_runtime_deps_file = + _secondary_abi_runtime_deps_file + } + + extra_shared_libraries = _extra_native_libs + + uncompress_shared_libraries = _uncompress_shared_libraries + + if (defined(_whitelist_r_txt_path) && _is_bundle_module) { + # Used to write the file path to the target's .build_config only. + base_whitelist_rtxt_path = _whitelist_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", + ] + } + } + + # Dex generation for app bundle modules with proguarding enabled takes + # place later due to synchronized proguarding. For more details, + # read build/android/docs/android_app_bundles.md + if (!(_is_bundle_module && _proguard_enabled)) { + _final_dex_target_name = "${_template_name}__final_dex" + dex(_final_dex_target_name) { + forward_variables_from(invoker, + [ + "min_sdk_version", + "dexlayout_profile", + ]) + proguard_enabled = _proguard_enabled + build_config = _build_config + deps = [ + ":$_build_config_target", + ":$_java_target", + ] + if (_proguard_enabled) { + forward_variables_from(invoker, [ "proguard_jar_path" ]) + deps += _deps + [ ":$_compile_resources_target" ] + proguard_mapping_path = _proguard_mapping_path + if (!defined(invoker.proguard_jar_path) && + _verify_android_configuration) { + proguard_expectations_file = + "$_target_src_dir/java/$_template_name.proguard_flags.expected" + } + } else { + input_jars = [ _lib_dex_path ] + input_dex_classpath = + "${_rebased_build_config}:final_dex:dependency_dex_files" + if (_enable_main_dex_list) { + input_jar_classpath = + "${_rebased_build_config}:deps_info:java_runtime_classpath" + } + } + + output = _final_dex_path + enable_multidex = _enable_multidex + + if (_enable_main_dex_list) { + forward_variables_from(invoker, [ "negative_main_dex_globs" ]) + extra_main_dex_proguard_config = _generated_proguard_main_dex_config + deps += [ ":$_compile_resources_target" ] + } else if (_enable_multidex) { + if (defined(invoker.negative_main_dex_globs)) { + not_needed(invoker, [ "negative_main_dex_globs" ]) + } + } + } + } else { + # A small sanity check to help developers with a subtle point! + assert( + !defined(invoker.proguard_jar_path), + "proguard_jar_path should not be used for app bundle modules " + + "when proguard is enabled. Pass it to the android_app_bundle() " + + "target instead!") + + _final_deps += [ ":$_java_target" ] + } + + _extra_native_libs_even_when_incremental = [] + assert(_extra_native_libs_even_when_incremental == []) # Mark as used. + if (_native_libs_deps != []) { + _create_stack_script_rule_name = "${_template_name}__stack_script" + _final_deps += [ ":${_create_stack_script_rule_name}" ] + stack_script(_create_stack_script_rule_name) { + stack_target_name = invoker.target_name + deps = _native_libs_deps + } + } + + if (defined(invoker.loadable_modules) && invoker.loadable_modules != []) { + _extra_native_libs_even_when_incremental += invoker.loadable_modules + } + + _all_native_libs_deps = [] + if (_native_libs_deps != [] || + _extra_native_libs_even_when_incremental != []) { + _native_libs_file_arg_dep = ":$_build_config_target" + if (!_is_bundle_module) { + _native_libs_file_arg = + "@FileArg($_rebased_build_config:native:libraries)" + } + _all_native_libs_deps += _native_libs_deps + _extra_native_libs_deps + + [ _native_libs_file_arg_dep ] + } + + if (!_is_bundle_module) { + # Generate size-info/*.jar.info files. + if (defined(invoker.name)) { + # Create size info files for targets that care about size + # (have proguard enabled). + if (_proguard_enabled) { + _size_info_target = "${target_name}__size_info" + create_size_info_files(_size_info_target) { + name = "${invoker.name}.apk" + build_config = _build_config + packaged_resources_path = _packaged_resources_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 + } + + _create_apk_target = "${_template_name}__create" + _final_deps += [ ":$_create_apk_target" ] + create_apk("$_create_apk_target") { + forward_variables_from(invoker, + [ + "native_lib_placeholders", + "public_deps", + "secondary_native_lib_placeholders", + "shared_resources", + "write_asset_list", + "uncompress_dex", + ]) + packaged_resources_path = _packaged_resources_path + if (_optimize_resources) { + optimized_resources_path = _optimized_resources_path + } + + apk_path = _final_apk_path + assets_build_config = _build_config + dex_path = _final_dex_path + load_library_from_apk = _load_library_from_apk + + keystore_name = _keystore_name + keystore_path = _keystore_path + keystore_password = _keystore_password + + incremental_allowed = _incremental_allowed + if (_incremental_allowed) { + android_manifest = _android_manifest + base_path = _base_path + } + + # Incremental apk does not use native libs nor final dex. + incremental_deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_compile_resources_target", + ] + + # This target generates the input file _all_resources_zip_path. + deps = _deps + [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_final_dex_target_name", + ":$_compile_resources_target", + ] + + if (_native_libs_deps != [] || + _extra_native_libs_even_when_incremental != []) { + native_libs_filearg = _native_libs_file_arg + native_libs = _extra_native_libs + native_libs_even_when_incremental = + _extra_native_libs_even_when_incremental + } + deps += _all_native_libs_deps + deps += _secondary_abi_native_libs_deps + secondary_abi_native_libs_filearg = + "@FileArg($_rebased_build_config:native:secondary_abi_libraries)" + + uncompress_shared_libraries = _uncompress_shared_libraries + } + } else { + _final_deps += [ + ":$_merge_manifest_target", + ":$_build_config_target", + ":$_compile_resources_target", + ] + _all_native_libs_deps + _secondary_abi_native_libs_deps + } + + if (_incremental_allowed) { + _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", + ] + + data = [ + _incremental_install_json_path, + ] + inputs = [ + _build_config, + ] + outputs = [ + _incremental_install_json_path, + ] + + _rebased_apk_path_no_ext = + rebase_path(_final_apk_path_no_ext, root_build_dir) + _rebased_incremental_install_json_path = + rebase_path(_incremental_install_json_path, root_build_dir) + _rebased_lib_dex_path = rebase_path(_lib_dex_path, root_build_dir) + _dex_arg_key = "${_rebased_build_config}:final_dex:dependency_dex_files" + args = [ + "--apk-path=${_rebased_apk_path_no_ext}_incremental.apk", + "--output-path=$_rebased_incremental_install_json_path", + "--dex-file=$_rebased_lib_dex_path", + "--dex-file-list=@FileArg($_dex_arg_key)", + ] + if (_proguard_enabled) { + args += [ "--show-proguard-warning" ] + } + if (_native_libs_deps != []) { + args += [ "--native-libs=$_native_libs_file_arg" ] + deps += [ _native_libs_file_arg_dep ] + } + if (_extra_native_libs != []) { + _rebased_extra_native_libs = + rebase_path(_extra_native_libs, root_build_dir) + args += [ "--native-libs=$_rebased_extra_native_libs" ] + } + if (_load_library_from_apk) { + args += [ "--dont-even-try=Incremental builds do not work with load_library_from_apk. Try setting is_component_build=true in your GN args." ] + } + } + _incremental_apk_operations = [] + } + + _apk_operations = [] + + # Generate apk operation related script. + if (!_is_bundle_module && + (!defined(invoker.create_apk_script) || invoker.create_apk_script)) { + _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, + ] + if (_proguard_enabled) { + # Required by logcat command. + data_deps = [ + "//build/android/stacktrace:java_deobfuscate", + ] + } + args = [ + "--script-output-path", + rebase_path(_generated_script, root_build_dir), + "--apk-path", + rebase_path(_final_apk_path, 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_allowed) { + args += [ + "--incremental-install-json-path", + rebase_path(_incremental_install_json_path, root_build_dir), + ] + } + if (_proguard_enabled) { + args += [ + "--proguard-mapping-path", + rebase_path("$_final_apk_path.mapping", root_build_dir), + ] + } + } + _apk_operations += [ ":$_apk_operations_target_name" ] + if (_incremental_allowed) { + _incremental_apk_operations += [ ":$_apk_operations_target_name" ] + } + } + + group(target_name) { + if (_incremental_allowed && incremental_apk_by_default) { + deps = [ + ":${target_name}_incremental", + ] + assert(_apk_operations != [] || true) # Prevent "unused variable". + } else { + forward_variables_from(invoker, + [ + "data", + "data_deps", + ]) + public_deps = _final_deps + + # Generate apk related operations at runtime. + public_deps += _apk_operations + } + } + + if (_incremental_allowed) { + group("${target_name}_incremental") { + forward_variables_from(invoker, + [ + "data", + "data_deps", + ]) + if (!defined(data_deps)) { + data_deps = [] + } + + # device/commands is used by the installer script to push files via .zip. + data_deps += [ "//build/android/pylib/device/commands" ] + + _native_libs_deps + _extra_native_libs_deps + + # Since the _incremental.apk does not include use .so nor .dex from the + # actual target, but instead loads them at runtime, we need to explicitly + # depend on them here. + public_deps = [ + ":${_java_target}", + ":${_template_name}__create_incremental", + ":${_write_installer_json_rule_name}", + ] + + # Generate incremental apk related operations at runtime. + public_deps += _incremental_apk_operations + } + } + } + + # 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. + # + # Example + # android_apk("foo_apk") { + # android_manifest = "AndroidManifest.xml" + # java_files = [ + # "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") { + android_apk_or_module(target_name) { + forward_variables_from(invoker, + [ + "aapt_locale_whitelist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "apk_under_test", + "app_as_shared_lib", + "build_hooks_android_impl_deps", + "chromium_code", + "classpath_deps", + "command_line_flags_file", + "create_apk_script", + "data", + "data_deps", + "deps", + "dexlayout_profile", + "dist_ijar_path", + "dont_load_shared_libraries", + "emit_resource_ids", + "emma_never_instrument", + "enable_chromium_linker_tests", + "enable_multidex", + "final_apk_path", + "firebase_app_id", + "generate_buildconfig_java", + "generate_final_jni", + "input_jars_paths", + "java_files", + "javac_args", + "jni_registration_header", + "jni_sources_blacklist", + "keystore_name", + "keystore_password", + "keystore_path", + "load_library_from_apk", + "loadable_modules", + "min_sdk_version", + "native_lib_placeholders", + "native_lib_version_arg", + "native_lib_version_rule", + "negative_main_dex_globs", + "never_incremental", + "no_build_hooks", + "no_xml_namespaces", + "optimize_resources", + "png_to_webp", + "post_process_package_resources_script", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "verify_android_configuration", + "proguard_jar_path", + "resource_blacklist_regex", + "resource_blacklist_exceptions", + "resource_ids_provider_dep", + "resources_config_path", + "secondary_abi_loadable_modules", + "secondary_abi_shared_libraries", + "secondary_native_lib_placeholders", + "shared_libraries", + "shared_resources", + "shared_resources_whitelist_locales", + "shared_resources_whitelist_target", + "srcjar_deps", + "static_library_dependent_targets", + "support_zh_hk", + "testonly", + "uncompress_shared_libraries", + "uncompress_dex", + "use_chromium_linker", + "version_code", + "version_name", + "write_asset_list", + ]) + is_bundle_module = false + if (defined(invoker.apk_name)) { + name = invoker.apk_name + } + } + } + + # 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. + # native_switches: Forwarded switches to decide how to assign native + # libraries and placeholders (optional). Its members are: + # * is_64_bit_browser + # * include_32_bit_webview + # loadable_modules_if_32_bit: Native libraries to use if the binary ABI is + # 32-bit (optional). + # loadable_modules_if_64_bit: Native libraries to use if the binary ABI is + # 64-bit (optional). + 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.write_asset_list)) + assert(!defined(invoker.firebase_app_id)) + assert(!defined(invoker.app_as_shared_lib)) + assert(!defined(invoker.shared_resources)) + assert(!defined(invoker.shared_resources_whitelist_target)) + assert(!defined(invoker.shared_resources_whitelist_locales)) + assert(!defined(invoker.build_hooks_android_impl_deps)) + assert(!defined(invoker.shared_libraries)) + assert(defined(invoker.base_module_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_whitelist", + "additional_jar_files", + "alternative_android_sdk_dep", + "android_manifest", + "android_manifest_dep", + "app_as_shared_lib", + "base_module_target", + "chromium_code", + "classpath_deps", + "data", + "data_deps", + "deps", + "emma_never_instrument", + "enable_chromium_linker_tests", + "enable_multidex", + "firebase_app_id", + "generate_buildconfig_java", + "generate_final_jni", + "input_jars_paths", + "is_base_module", + "java_files", + "javac_args", + "jni_registration_header", + "jni_sources_blacklist", + "load_library_from_apk", + "min_sdk_version", + "native_lib_version_arg", + "native_lib_version_rule", + "negative_main_dex_globs", + "no_xml_namespaces", + "optimize_resources", + "package_name", + "package_name_to_id_mapping", + "png_to_webp", + "product_version_resources_dep", + "proguard_configs", + "proguard_enabled", + "proguard_jar_path", + "resource_blacklist_exceptions", + "resource_blacklist_regex", + "resources_config_path", + "secondary_abi_shared_libraries", + "shared_libraries", + "shared_resources", + "shared_resources_whitelist_locales", + "shared_resources_whitelist_target", + "srcjar_deps", + "support_zh_hk", + "testonly", + "uncompress_shared_libraries", + "use_chromium_linker", + "verify_android_configuration", + "version_code", + "version_name", + "write_asset_list", + ]) + + # Specify native libraries and placeholders. + if (defined(invoker.native_switches)) { + assert(invoker.loadable_modules_if_32_bit != []) + assert(invoker.loadable_modules_if_64_bit != []) + + # Decision logic: Assign decision variables: + # loadable_modules_to_use: Either |loadable_modules_if_64_bit| or + # |loadable_modules_if_32_bit|. + # native_is_primary: Whether |loadable_modules_to_use| should be + # assigned as primary ABI or secondary ABI. + # native_need_placeholder: Whether a placeholder is needed for the + # complementary ABI to the library. + _native_switches = invoker.native_switches + if (_native_switches.is_64_bit_browser) { + _loadable_modules_to_use = invoker.loadable_modules_if_64_bit + _native_is_primary = + !build_apk_secondary_abi || android_64bit_target_cpu + _native_need_placeholder = + build_apk_secondary_abi && _native_switches.include_32_bit_webview + } else { + _loadable_modules_to_use = invoker.loadable_modules_if_32_bit + _native_is_primary = + !build_apk_secondary_abi || !android_64bit_target_cpu + _native_need_placeholder = + build_apk_secondary_abi && android_64bit_target_cpu + } + + # Realization logic: Assign libraries and placeholders. + if (_native_is_primary) { + loadable_modules = _loadable_modules_to_use + if (_native_need_placeholder) { + secondary_native_lib_placeholders = [ "libdummy.so" ] + } + } else { + secondary_abi_loadable_modules = _loadable_modules_to_use + if (_native_need_placeholder) { + native_lib_placeholders = [ "libdummy.so" ] + } + } + } else { + assert(!defined(invoker.loadable_modules_if_32_bit)) + assert(!defined(invoker.loadable_modules_if_64_bit)) + forward_variables_from(invoker, + [ + "loadable_modules", + "native_lib_placeholders", + "secondary_abi_loadable_modules", + "secondary_native_lib_placeholders", + ]) + } + + is_bundle_module = true + generate_buildconfig_java = _is_base_module + no_build_hooks = !_is_base_module + if (defined(invoker.module_name)) { + name = invoker.module_name + } + } + } + + # 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 + # instrumentation_test_apk("foo_test_apk") { + # android_manifest = "AndroidManifest.xml" + # apk_name = "FooTest" + # apk_under_test = "Foo" + # java_files = [ + # "android/org/chromium/foo/FooTestCase.java", + # "android/org/chromium/foo/FooExampleTest.java", + # ] + # deps = [ + # ":foo_test_support_java" + # ] + # } + template("instrumentation_test_apk") { + assert(defined(invoker.apk_name)) + testonly = true + _incremental_allowed = + !defined(invoker.never_incremental) || !invoker.never_incremental + _apk_target_name = "${target_name}__apk" + _test_runner_target_name = "${target_name}__test_runner_script" + _dist_ijar_path = + "$root_build_dir/test.lib.java/" + invoker.apk_name + ".jar" + if (_incremental_allowed) { + _incremental_test_runner_target_name = + "${_test_runner_target_name}_incremental" + _incremental_test_name = "${invoker.target_name}_incremental" + } + + if (incremental_apk_by_default && _incremental_allowed) { + _incremental_test_runner_target_name = _test_runner_target_name + _incremental_test_name = invoker.target_name + } + + if (!incremental_apk_by_default || + (incremental_apk_by_default && !_incremental_allowed)) { + test_runner_script(_test_runner_target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "apk_under_test", + "data", + "data_deps", + "deps", + "ignore_all_data_deps", + "proguard_enabled", + "public_deps", + ]) + test_name = invoker.target_name + test_type = "instrumentation" + apk_target = ":$_apk_target_name" + test_jar = _dist_ijar_path + } + } + if (_incremental_allowed) { + test_runner_script(_incremental_test_runner_target_name) { + forward_variables_from(invoker, + [ + "additional_apks", + "apk_under_test", + "data", + "data_deps", + "deps", + "ignore_all_data_deps", + "public_deps", + ]) + test_name = _incremental_test_name + test_type = "instrumentation" + apk_target = ":$_apk_target_name" + test_jar = _dist_ijar_path + incremental_install = true + } + } + + android_apk(_apk_target_name) { + deps = [] + data_deps = [] + forward_variables_from(invoker, "*") + deps += [ "//testing/android/broker:broker_java" ] + data_deps += [ + "//build/android/pylib/device/commands", + "//tools/android/forwarder2", + "//tools/android/md5sum", + ] + if (defined(invoker.apk_under_test)) { + data_deps += [ invoker.apk_under_test ] + } + if (defined(invoker.additional_apks)) { + data_deps += invoker.additional_apks + } + if (defined(invoker.apk_under_test)) { + # Prevent a build_hooks_android_impl exising in both the test apks as + # well as the apk_under_test. + no_build_hooks = true + } + + if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) { + # 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. + if (!defined(invoker.proguard_configs)) { + proguard_configs = [] + } + proguard_configs += [ "//testing/android/proguard_for_test.flags" ] + if (defined(final_apk_path)) { + _final_apk_path = final_apk_path + } else { + _final_apk_path = "$root_build_dir/apks/${apk_name}.apk" + } + data = [ + "$_final_apk_path.mapping", + ] + data_deps += [ "//build/android/stacktrace:java_deobfuscate" ] + } + + dist_ijar_path = _dist_ijar_path + create_apk_script = false + } + + group(target_name) { + if (incremental_apk_by_default && _incremental_allowed) { + public_deps = [ + ":${target_name}_incremental", + ] + } else { + public_deps = [ + ":$_apk_target_name", + ":$_test_runner_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 ] + } + } + + # Ensure unstripped libraries are included in runtime deps so that + # symbolization can be done. + deps = [ + ":${_apk_target_name}__runtime_deps", + ":${_apk_target_name}__secondary_abi__runtime_deps", + ] + if (defined(invoker.apk_under_test)) { + _under_test_label = + get_label_info(invoker.apk_under_test, "label_no_toolchain") + deps += [ + "${_under_test_label}__runtime_deps", + "${_under_test_label}__secondary_abi__runtime_deps", + ] + } + } + + if (_incremental_allowed) { + group("${target_name}_incremental") { + public_deps = [ + ":$_incremental_test_runner_target_name", + ":${_apk_target_name}_dist_ijar", + ":${_apk_target_name}_incremental", + ] + if (defined(invoker.apk_under_test)) { + public_deps += [ "${invoker.apk_under_test}_incremental" ] + } + } + } + } + + # 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. + # 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") { + _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)) { + jinja_template("${target_name}_manifest") { + _native_library_name = get_label_info(invoker.shared_library, "name") + 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}", + ] + } + } + + android_apk(target_name) { + data_deps = [] + forward_variables_from(invoker, "*") + testonly = true + create_apk_script = false + + 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 += [ "//testing/android/native_test:native_test_java" ] + } + shared_libraries = [ invoker.shared_library ] + deps += [ + ":${target_name}__runtime_deps", + ":${target_name}__secondary_abi__runtime_deps", + "//base:base_java", + "//testing/android/reporter:reporter_java", + ] + data_deps += [ + "//build/android/pylib/device/commands", + "//tools/android/md5sum", + ] + if (host_os == "linux") { + data_deps += [ "//tools/android/forwarder2" ] + } + } + } + + # 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) { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + + script = "//build/android/gyp/aidl.py" + 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), + ] + if (defined(invoker.import_include) && invoker.import_include != []) { + # TODO(cjhopman): aidl supports creating a depfile. We should be able to + # switch to constructing a depfile for the overall action from that + # instead of having all the .java files in the include paths as inputs. + _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 + _java_files_build_rel = [] + _java_files_build_rel = + exec_script("//build/android/gyp/find.py", + [ "--pattern=*.java" ] + _rebased_import_path, + "list lines") + inputs += rebase_path(_java_files_build_rel, ".", root_build_dir) + } + 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. + # + # generate_nano (optional, default false) + # Whether to generate nano protos. If false, this will use the lite proto generator. + # Nano protos are deprecated, so please use lite new proto libraries. + # + # Example: + # proto_java_library("foo_proto_java") { + # proto_path = "src/foo" + # sources = [ "$proto_path/foo.proto" ] + # } + template("proto_java_library") { + set_sources_assignment_filter([]) + forward_variables_from(invoker, [ "testonly" ]) + _generate_nano = + defined(invoker.generate_nano) && invoker.generate_nano == true + + if (_generate_nano) { + # Use the legacy Android nano proto generator. + _protoc_dep = + "//third_party/android_protobuf:android_protoc($host_toolchain)" + _protoc_out_dir = get_label_info(_protoc_dep, "root_out_dir") + _protoc_bin = "$_protoc_out_dir/android_protoc" + _proto_runtime = "//third_party/android_protobuf:protobuf_nano_javalib" + } else { + # Use the regular proto library to generate lite protos. + _protoc_dep = "//third_party/protobuf:protoc($host_toolchain)" + _protoc_out_dir = get_label_info(_protoc_dep, "root_out_dir") + _protoc_bin = "$_protoc_out_dir/protoc" + _proto_runtime = + "//third_party/android_deps:com_google_protobuf_protobuf_lite_java" + _protoc_javalite_plugin_dir = "//third_party/protoc_javalite/" + } + _proto_path = invoker.proto_path + _template_name = target_name + + action_with_pydeps("${_template_name}__protoc_java") { + _srcjar_path = "$target_gen_dir/$target_name.srcjar" + script = "//build/protoc_java.py" + + deps = [ + _protoc_dep, + ] + 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(_protoc_bin, root_build_dir), + "--proto-path", + rebase_path(_proto_path, root_build_dir), + "--srcjar", + rebase_path(_srcjar_path, root_build_dir), + ] + rebase_path(sources, root_build_dir) + if (_generate_nano) { + args += [ "--nano" ] + } else { + args += [ + "--protoc-javalite-plugin-dir", + rebase_path(_protoc_javalite_plugin_dir, root_build_dir), + ] + } + } + + android_library(target_name) { + chromium_code = false + java_files = [] + srcjar_deps = [ ":${_template_name}__protoc_java" ] + deps = [ + _proto_runtime, + ] + } + } + + # 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_native_libraries: Whether to ignore .so files found in the .aar. + # See also extract_native_libraries. + # 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. + # split_compat_class_names: Names of the classes that will have their + # bytecode rewritten to inject the call to SplitCompat.install(). + # Used to make dependencies compatible with SplitCompat to immediately + # access resources brought in by the modules. + # create_srcjar: If false, does not create an R.java file. + # 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_gen_dir}/${target_name}" + _unpack_target_name = "${target_name}__unpack_aar" + _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl + _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets + _ignore_native_libraries = defined(invoker.ignore_native_libraries) && + invoker.ignore_native_libraries + _extract_native_libraries = defined(invoker.extract_native_libraries) && + invoker.extract_native_libraries + + # Scan the AAR file and determine the resources and jar files. + # Some libraries might not have resources; others might have two jars. + if (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") + + assert(_ignore_aidl || _scanned_files.aidl == [], + "android_aar_prebuilt() aidl not yet supported." + + " Implement or use ignore_aidl = true." + + " http://crbug.com/644439") + assert(_ignore_assets || _scanned_files.assets == [], + "android_aar_prebuilt() assets not yet supported." + + " Implement or use ignore_assets = true." + + " http://crbug.com/643966") + 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), + ] + inputs = [ + invoker.aar_path, + ] + outputs = [ + "${_output_path}/AndroidManifest.xml", + ] + + if (_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 (_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 (_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") + } + } + + _strip_resources = + defined(invoker.strip_resources) && invoker.strip_resources + _has_unignored_resources = + !_strip_resources && + (_scanned_files.resources != [] || _scanned_files.has_r_text_file) + + # Create the android_resources target for resources. + if (_has_unignored_resources || !_scanned_files.is_manifest_empty) { + _res_target_name = "${target_name}__res" + android_resources(_res_target_name) { + forward_variables_from(invoker, + [ + "create_srcjar", + "deps", + "testonly", + "strip_drawables", + ]) + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_unpack_target_name" ] + android_manifest_dep = ":$_unpack_target_name" + android_manifest = "${_output_path}/AndroidManifest.xml" + resource_dirs = [] + generated_resource_dirs = [] + if (!_strip_resources && _scanned_files.resources != []) { + generated_resource_dirs += [ "${_output_path}/res" ] + } + generated_resource_files = [] + if (!_strip_resources) { + generated_resource_files = + rebase_path(_scanned_files.resources, "", _output_path) + } + if (!_strip_resources && _scanned_files.has_r_text_file) { + r_text_file = "${_output_path}/R.txt" + } + v14_skip = true + } + } else if (defined(invoker.strip_drawables)) { + not_needed(invoker, [ "strip_drawables" ]) + } + + # 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, + [ + "jar_excluded_patterns", + "jar_included_patterns", + "requires_android", + ]) + 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" + } + } + + # Create android_java_prebuilt target for classes.jar. + if (_scanned_files.has_classes_jar) { + _jar_target_name = "${target_name}__classes" + java_prebuilt(_jar_target_name) { + forward_variables_from(invoker, + [ + "deps", + "input_jars_paths", + "jar_excluded_patterns", + "jar_included_patterns", + "proguard_configs", + "requires_android", + "split_compat_class_names", + "testonly", + ]) + 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" + output_name = invoker.target_name + + if (_scanned_files.has_proguard_flags) { + if (!defined(proguard_configs)) { + proguard_configs = [] + } + proguard_configs += [ "$_output_path/proguard.txt" ] + } + } + } + + java_group(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "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" ] + } + } + } + + # 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. + # A scope may have an additional field, 'proguard_async', that + # specifies whether or not the module is asynchronous. This field should + # be set to true if the module is asynchronous, and set to false or left + # undefined otherwise. + # Async modules are those that are proguarded in a separate build step. + # This ensures that changes to these modules do not change the base + # module. + # + # enable_language_splits: Optional. If true, enable APK splits based + # on languages. + # + # sign_bundle: Optional. If true, sign the bundle. Default is false + # because signing is very slow, and there is no reason to do it + # unless one wants to upload the bundle to the Play Store (e.g. + # for official builds). + # + # 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_jar_path: Optional. Path to custom proguard jar used for + # proguarding. + # + # 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_whitelist: List of locales that should be included + # on system APKs generated from this bundle. + # + # 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") { + _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" + _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) + + _sync_modules = [ + { + name = "base" + module_target = invoker.base_module_target + build_config = _base_module_build_config + build_config_target = _base_module_build_config_target + }, + ] + + _async_modules = [] + + _proguard_enabled = + defined(invoker.proguard_enabled) && invoker.proguard_enabled + _enable_multidex = + !defined(invoker.enable_multidex) || invoker.enable_multidex + + if (!_proguard_enabled && defined(invoker.min_sdk_version)) { + not_needed(invoker, [ "min_sdk_version" ]) + } + + # Prevent "unused variable". + not_needed([ "_enable_multidex" ]) + + 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" ]) + + # Define unique package for each async proguarding run. + _async_package_number = 1 + + not_needed([ "_async_package_number" ]) + + 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" + _module.build_config_target = + "$_module_target$build_config_target_suffix" + + if (defined(_module.proguard_async) && _module.proguard_async) { + if (_proguard_enabled) { + # Use asynchronous proguarding for async modules. + # TODO(crbug.com/938635): Combine async module mapping paths with the sync one. + _async_proguard_mapping_path = + "${_bundle_path}_${_module.name}.mapping" + + _dex_zip = "${target_out_dir}/${target_name}/${target_name}_${_module.name}_dex.zip" + _module.dex_path = _dex_zip + + # Give unique name to each async dex target using module name. + _async_dex_target = "${target_name}_${_module.name}_dex" + + dex(_async_dex_target) { + enable_multidex = _enable_multidex + proguard_enabled = true + proguard_mapping_path = _async_proguard_mapping_path + forward_variables_from(invoker, + [ + "proguard_jar_path", + "min_sdk_version", + ]) + build_config = _module.build_config + repackage_classes = "ap${_async_package_number}" + + deps = [ + _module.module_target, + ] + + output = _dex_zip + } + _module.async_dex_target = _async_dex_target + _async_package_number += 1 + } + + _async_modules += [ _module ] + } else { + _sync_modules += [ _module ] + } + } + } + + # Make build config, which is required for synchronized proguarding. + _sync_module_targets = [] + foreach(_module, _sync_modules) { + _sync_module_targets += [ _module.module_target ] + } + _build_config = "$target_gen_dir/${target_name}.build_config" + _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" + } + write_build_config(_build_config_target) { + # We don't want async modules to be proguarded synchronously, so we leave + # them out of possible_config_deps. + type = "android_app_bundle" + possible_config_deps = + _sync_module_targets + [ proguard_android_sdk_dep_ ] + build_config = _build_config + proguard_enabled = _proguard_enabled + } + + if (_proguard_enabled) { + _proguard_mapping_path = "${_bundle_path}.mapping" + _unsplit_dex_zip = + "${target_gen_dir}/${target_name}/${target_name}__unsplit_dex.zip" + _unsplit_dex_target = "${target_name}__unsplit_dex" + dex(_unsplit_dex_target) { + enable_multidex = _enable_multidex + proguard_enabled = true + proguard_mapping_path = _proguard_mapping_path + forward_variables_from(invoker, + [ + "proguard_jar_path", + "min_sdk_version", + ]) + build_config = _build_config + + deps = _sync_module_targets + [ ":$_build_config_target" ] + output = _unsplit_dex_zip + } + + _dexsplitter_target = "${_unsplit_dex_target}__dexsplitter" + dexsplitter(_dexsplitter_target) { + input_dex_zip = _unsplit_dex_zip + proguard_mapping = _proguard_mapping_path + all_modules = _sync_modules + deps = [ + ":${_unsplit_dex_target}", + ] + } + } + + # Merge async and sync module scopes. + _all_modules = _sync_modules + _async_modules + + _all_create_module_targets = [] + _all_module_zip_paths = [] + _all_module_build_configs = [] + foreach(_module, _all_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 if (defined(_module.dex_path)) { + _dex_target_for_module = ":${_module.async_dex_target}" + } else { + _dex_target_for_module = ":$_dexsplitter_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) { + build_config = _module_build_config + module_zip_path = _module_zip_path + + # If module is async, use defined dex_path directly rather than + # build config FileArg. + if (defined(_module.dex_path)) { + dex_path = _module.dex_path + } + + deps = [ + _dex_target_for_module, + _module_build_config_target, + _module_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_rebased_module_zip_paths = + rebase_path(_all_module_zip_paths, root_build_dir) + + _sign_bundle = defined(invoker.sign_bundle) && invoker.sign_bundle + + _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) + + if (_sign_bundle) { + # For now, the same keys are used to sign the bundle and the set of + # generated APKs. In the future, signing the bundle may require a + # different set of keys. + _bundle_keystore_name = _keystore_name + } + + _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, + ] + data = [ + _bundle_path, + ] + deps = _all_create_module_targets + [ ":$_build_config_target" ] + args = [ + "--out-bundle=$_rebased_bundle_path", + "--rtxt-out-path=$_rebased_bundle_path.R.txt", + "--module-zips=$_all_rebased_module_zip_paths", + ] + if (_sign_bundle) { + args += [ + "--keystore-path", + _rebased_keystore_path, + "--keystore-password", + _keystore_password, + "--key-name", + _bundle_keystore_name, + ] + } + if (_split_dimensions != []) { + args += [ "--split-dimensions=$_split_dimensions" ] + } + if (defined(invoker.compress_shared_libraries) && + invoker.compress_shared_libraries) { + args += [ "--compress-shared-libraries" ] + } + + if (_enable_language_splits) { + args += [ + "--base-whitelist-rtxt-path=@FileArg(" + "${_rebased_base_module_build_config}:deps_info:base_whitelist_rtxt_path)", + "--base-module-rtxt-path=@FileArg(" + "${_rebased_base_module_build_config}:deps_info:module_rtxt_path)", + ] + } + + foreach(build_config, _all_module_build_configs) { + _rebased_build_config = rebase_path(build_config, root_build_dir) + args += [ + "--uncompressed-assets=@FileArg(" + + "$_rebased_build_config:uncompressed_assets)", + "--rtxt-in-paths=@FileArg(" + + "$_rebased_build_config:deps_info:module_rtxt_path)", + ] + } + } + + # 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 = _sync_module_targets + foreach(_async_module, _async_modules) { + _all_module_targets += [ _async_module.module_target ] + } + + _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 + } + } + + # 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, + ] + + 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.system_image_locale_whitelist)) { + args += [ + "--system-image-locales=${invoker.system_image_locale_whitelist}", + ] + } + if (defined(invoker.command_line_flags_file)) { + args += [ + "--command-line-flags-file", + invoker.command_line_flags_file, + ] + } + + # TODO(crbug.com/938635): Combine async module mapping paths with the sync one. + if (_proguard_enabled) { + args += [ + "--proguard-mapping-path", + rebase_path(_proguard_mapping_path, root_build_dir), + ] + } + } + + group(target_name) { + public_deps = [ + ":${target_name}__bundle", + ":${target_name}__wrapper_script", + ] + if (defined(_size_info_target)) { + public_deps += [ ":$_size_info_target" ] + } + } + } + + # 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, + [ + "deps", + "testonly", + ]) + script = "//build/android/gyp/create_app_bundle_minimal_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, + ] + } + } +} + +# 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" + + _locales = invoker.ui_locales + _depfile = "$target_gen_dir/$target_name.d" + + action(_generating_target_name) { + script = "//build/android/gyp/create_ui_locale_resources.py" + depfile = _depfile + outputs = [ + _output_zip, + ] + args = [ + "--locale-list=$_locales", + "--depfile", + rebase_path(_depfile, root_build_dir), + "--output-zip", + rebase_path(_output_zip, root_build_dir), + ] + } + + android_generated_resources(target_name) { + generating_target_name = ":$_generating_target_name" + generated_resources_zip = _output_zip + } +} diff --git a/deps/v8/build/config/android/sdk.gni b/deps/v8/build/config/android/sdk.gni new file mode 100644 index 0000000000..1f1ebc5d3f --- /dev/null +++ b/deps/v8/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 = "p" + +# SDK releases against which public builds are supported. +public_sdk_releases = [ "p" ] diff --git a/deps/v8/build/config/arm.gni b/deps/v8/build/config/arm.gni new file mode 100644 index 0000000000..29434eba92 --- /dev/null +++ b/deps/v8/build/config/arm.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/v8_target_cpu.gni") + +# These are primarily relevant in current_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 (current_cpu == "arm" || v8_current_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 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 = "" + + # 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 + } + + 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 == "android" || target_os == "android") { + arm_float_abi = "softfp" + } else 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 == "") { + if (current_os == "android" || target_os == "android") { + 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 (current_cpu == "arm64" || v8_current_cpu == "arm64") { + # arm64 supports only "hard". + arm_float_abi = "hard" + arm_use_neon = true +} diff --git a/deps/v8/build/config/c++/BUILD.gn b/deps/v8/build/config/c++/BUILD.gn new file mode 100644 index 0000000000..226e89dc4a --- /dev/null +++ b/deps/v8/build/config/c++/BUILD.gn @@ -0,0 +1,117 @@ +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.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_mac || is_ios) && 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 && 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 = [] + ldflags = [] + libs = [] + + if (libcxx_abi_unstable) { + defines += [ "_LIBCPP_ABI_UNSTABLE" ] + } + + if (is_component_build) { + # In component builds, 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" ] + + 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" ] + + configs = [ "//tools/win/DebugVisualizers:libc++" ] + } else { + cflags_cc += [ + "-nostdinc++", + "-isystem" + rebase_path("$libcxx_prefix/include", root_build_dir), + "-isystem" + rebase_path("$libcxxabi_prefix/include", root_build_dir), + ] + + defines += [ "CR_LIBCXX_REVISION=$libcxx_svn_revision" ] + + # Make sure we don't link against the system libstdc++ or libc++. + if (is_clang) { + # //build/config/android:runtime_library adds -nostdlib, which suppresses + # linking against all system libraries. -nostdlib++ would be redundant, + # and would generate an unused warning in this case. + if (!is_android) { + 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/deps/v8/build/config/c++/c++.gni b/deps/v8/build/config/c++/c++.gni new file mode 100644 index 0000000000..4deaf03575 --- /dev/null +++ b/deps/v8/build/config/c++/c++.gni @@ -0,0 +1,64 @@ +# 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") + +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_ios || + (is_linux && + (!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 +} + +use_custom_libcxx = + use_custom_libcxx || (use_custom_libcxx_for_host && current_cpu == host_cpu) +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_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/deps/v8/build/config/chrome_build.gni b/deps/v8/build/config/chrome_build.gni new file mode 100644 index 0000000000..4bb4a043cb --- /dev/null +++ b/deps/v8/build/config/chrome_build.gni @@ -0,0 +1,26 @@ +# 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 + + # Break chrome.dll into multple pieces based on process type. Only available + # on Windows. + is_multi_dll_chrome = is_win && !is_component_build + + # Turn this on to generate order files. See + # https://chromium.googlesource.com/chromium/src/+/master/docs/win_order_files.md + generate_order_files = false +} + +# 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" +} diff --git a/deps/v8/build/config/chromecast/BUILD.gn b/deps/v8/build/config/chromecast/BUILD.gn new file mode 100644 index 0000000000..c8b2989c42 --- /dev/null +++ b/deps/v8/build/config/chromecast/BUILD.gn @@ -0,0 +1,85 @@ +# 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 = [ ":*" ] + + # 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. + ldflags = [ + "-Wl,-rpath=/oem_cast_shlib", + "-Wl,-rpath=\$ORIGIN/lib", + "-Wl,-rpath=\$ORIGIN", + ] + + # 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 && current_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 (current_cpu == "arm") { + configs = [ ":static_config" ] + } +} diff --git a/deps/v8/build/config/chromecast_build.gni b/deps/v8/build/config/chromecast_build.gni new file mode 100644 index 0000000000..f93f40b1a1 --- /dev/null +++ b/deps/v8/build/config/chromecast_build.gni @@ -0,0 +1,79 @@ +# 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 true, use cast CMA backend instead of default chromium media pipeline. + # TODO(sanfin): Remove this flag when all builds enable CMA. + is_cast_using_cma_backend = true +} + +# 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") +} + +declare_args() { + # True to enable the cast renderer. It is enabled by default for non-android + # builds. + enable_cast_renderer = + is_chromecast && is_cast_using_cma_backend && !is_android +} + +# Configures media options for cast. See media/media_options.gni +cast_mojo_media_services = [] +cast_mojo_media_host = "none" + +if (enable_cast_renderer) { + cast_mojo_media_services = [ + "cdm", + "renderer", + ] + cast_mojo_media_host = "browser" +} else if (is_android) { + cast_mojo_media_services = [ + "cdm", + "audio_decoder", + ] + if (is_cast_audio_only) { + cast_mojo_media_host = "browser" + } else { + cast_mojo_media_services += [ "video_decoder" ] + cast_mojo_media_host = "gpu" + } +} + +# Assert that Chromecast is being built for a supported platform. +assert(is_linux || 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/deps/v8/build/config/chromeos/rules.gni b/deps/v8/build/config/chromeos/rules.gni new file mode 100644 index 0000000000..0132d02cf4 --- /dev/null +++ b/deps/v8/build/config/chromeos/rules.gni @@ -0,0 +1,235 @@ +# 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_chromeos) + +declare_args() { + cros_board = "" + cros_sdk_version = "" +} +declare_args() { + # Determines if we're running tests on VMs or on devices. + # TODO(crbug.com/866062): Is there a better way to do this? + cros_is_vm = cros_board == "amd64-generic" +} + +# Ensure that if one is set, the other is as well. +assert(cros_board == "" == (cros_sdk_version == "")) + +# The build is using the Simple Chrome "cros chrome-sdk" to target real hardware +# or a VM, not 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/+/master/docs/chromeos_build_instructions.md +# https://chromium.googlesource.com/chromiumos/docs/+/master/simple_chrome_workflow.md +is_cros_chrome_sdk = cros_board != "" + +# 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 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. +template("generate_runner_script") { + forward_variables_from(invoker, + [ + "deploy_chrome", + "generated_script", + "runtime_deps_file", + "tast_attr_expr", + "tast_tests", + "testonly", + "test_exe", + ]) + if (!defined(deploy_chrome)) { + deploy_chrome = false + } + + # These are the only 2 conditions when ${_cache_path_prefix} is used, so + # initialize it in a conditional. + if (deploy_chrome || cros_is_vm) { + _cache_path_prefix = "//build/cros_cache/chrome-sdk/tarballs/${cros_board}+${cros_sdk_version}" + } + + assert(defined(generated_script), + "Must specify where to place generated test launcher script via " + + "'generated_script'") + 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.") + + action(target_name) { + if (defined(runtime_deps_file)) { + write_runtime_deps = runtime_deps_file + } + script = "//build/chromeos/create_test_runner_script.py" + + outputs = [ + generated_script, + ] + + deps = [ + "//testing/buildbot/filters:chromeos_filters", + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + data = [ + # 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/", + generated_script, + "//build/chromeos/", + "//build/cros_cache/chrome-sdk/misc/", + + # We use luci-py's subprocess42 to launch test processes. + "//tools/swarming_client/utils/", + + # 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/", + ] + + # Add the VM/QEMU-launching bits if needed. + if (cros_is_vm) { + assert(defined(_cache_path_prefix)) + _vm_image_path = "${_cache_path_prefix}+chromiumos_qemu_image.tar.xz/" + _qemu_dir = "${_cache_path_prefix}+app-emulation/" + _firmware_dir = "${_cache_path_prefix}+sys-firmware/" + data += [ + _firmware_dir, + _vm_image_path, + _qemu_dir, + ] + } + if (is_tast) { + data += [ + "${_cache_path_prefix}+chromeos-base/tast-cmd/", + "${_cache_path_prefix}+chromeos-base/tast-remote-tests-cros/", + ] + } + if (defined(invoker.data)) { + deps += invoker.data + } + + if (defined(invoker.data_deps)) { + data_deps = invoker.data_deps + } + + # Required arguments used at build time by the runner script generator. + args = [ + "--script-output-path", + rebase_path(generated_script, root_build_dir), + "--cros-cache", + rebase_path("//build/cros_cache/", root_build_dir), + "--board", + cros_board, + "--output-directory", + rebase_path(root_out_dir, root_build_dir), + ] + + if (cros_is_vm) { + args += [ "--use-vm" ] + } + + if (deploy_chrome) { + args += [ "--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. + assert(defined(_cache_path_prefix)) + data += [ + "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz", + "${_cache_path_prefix}+target_toolchain/", + ] + } + + # When --test-exe is specified, test_runner.py will push the exe to the VM + # and execute it. Otherwise it wraps a host-side command and just takes care + # launching & tearing-down the VM. + if (defined(test_exe)) { + args += [ + "--test-exe", + test_exe, + ] + if (defined(runtime_deps_file)) { + 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. + args += [ + "--suite-name", + target_name, + ] + if (defined(tast_attr_expr)) { + args += [ + "--tast-attr-expr", + tast_attr_expr, + ] + } else { + foreach(test, tast_tests) { + args += [ + "--tast-tests", + test, + ] + } + } + } + } +} + +template("tast_test") { + forward_variables_from(invoker, "*") + + # Default the expression to match any chrome-related test. + if (!defined(tast_attr_expr) && !defined(tast_tests)) { + tast_attr_expr = "!disabled && !\"group:*\" && !informational" + + " && (\"dep:chrome\" || \"dep:chrome_login\")" + } 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. + ] + } +} diff --git a/deps/v8/build/config/clang/BUILD.gn b/deps/v8/build/config/clang/BUILD.gn new file mode 100644 index 0000000000..960726e1e5 --- /dev/null +++ b/deps/v8/build/config/clang/BUILD.gn @@ -0,0 +1,42 @@ +# 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", + ] + + if (is_linux || 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", + ] +} diff --git a/deps/v8/build/config/clang/clang.gni b/deps/v8/build/config/clang/clang.gni new file mode 100644 index 0000000000..2c2d76fd4b --- /dev/null +++ b/deps/v8/build/config/clang/clang.gni @@ -0,0 +1,15 @@ +# 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 Clang. + clang_use_chrome_plugins = is_clang && !is_nacl && !use_xcode_clang + + clang_base_path = default_clang_base_path +} diff --git a/deps/v8/build/config/compiler/BUILD.gn b/deps/v8/build/config/compiler/BUILD.gn new file mode 100644 index 0000000000..4b24c762b6 --- /dev/null +++ b/deps/v8/build/config/compiler/BUILD.gn @@ -0,0 +1,2423 @@ +# 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/android/config.gni") +import("//build/config/c++/c++.gni") +import("//build/config/chrome_build.gni") +import("//build/config/chromecast_build.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/host_byteorder.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/toolchain.gni") +import("//build_overrides/build.gni") + +if (current_cpu == "arm" || current_cpu == "arm64") { + import("//build/config/arm.gni") +} +if (current_cpu == "mipsel" || current_cpu == "mips64el" || + current_cpu == "mips" || current_cpu == "mips64") { + import("//build/config/mips.gni") +} +if (is_mac) { + import("//build/config/mac/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") +} + +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 + + # 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 + + # Whether to use the binary binutils checked into third_party/binutils. + # These are not multi-arch so cannot be used except on x86 and x86-64 (the + # only two architectures that are currently checked in). Turn this off when + # you are using a custom toolchain and need to control -B in cflags. + linux_use_bundled_binutils = + linux_use_bundled_binutils_override && is_linux && + (current_cpu == "x64" || current_cpu == "x86") + binutils_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", + root_build_dir) + + # 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 = false + + if (is_win) { + # Whether the VS xtree header has been patched to disable warning 4702. If + # it has, then we don't need to disable 4702 (unreachable code warning). + # The patch is preapplied to the internal toolchain and hence all bots. + msvs_xtree_patched = false + } + + # Enable fatal linker warnings. Building Chromium with certain versions + # of binutils can cause linker warning. + # See: https://bugs.chromium.org/p/chromium/issues/detail?id=457359 + 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 = build_with_chromium && is_official_build && + (is_android || is_desktop_linux) + + # Turn this on to have the compiler output extra timing information. + compiler_timing = false + + # Set to true to pass --no-rosegment to lld. This is a workaround + # for a KI issue in Valgrind, + # https://bugs.kde.org/show_bug.cgi?id=384727 + ro_segment_workaround_for_valgrind = 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 || is_android || is_win) && is_official_build + + # By default only the binaries in official builds get build IDs. + force_local_build_id = 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 + # See also https://crbug.com/663886 + # `linux_use_bundled_binutils` is to avoid breaking Linux distros which may + # still have a buggy gold. + # 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_android && linux_use_bundled_binutils) || is_chromeos || + !(current_cpu == "x86" || current_cpu == "x64")))) +} + +# Apply the default logic for these values if they were not set explicitly. +if (gold_path == false) { + if (use_gold) { + gold_path = rebase_path("//third_party/binutils/Linux_x64/Release/bin", + root_build_dir) + } else { + gold_path = "" + } +} + +if (use_debug_fission == "default") { + use_debug_fission = + is_debug && !is_android && !is_fuchsia && !is_ios && !is_mac && !is_win && + (use_gold || use_lld) && cc_wrapper == "" +} + +# 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 --------------------------------------------------------------------- +# +# 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) { + configs += [ "//build/config/linux: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", + ] + + # In general, Windows is totally different, but all the other builds share + # some common GCC 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 && !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 && current_cpu == "x86") { + cflags += [ "-fno-stack-protector" ] + } else if (current_os != "aix") { + # Not available on aix. + cflags += [ "-fstack-protector" ] + } + } + + # Linker warnings. + if (fatal_linker_warnings && !(is_chromeos && current_cpu == "arm") && + !(is_android && use_order_profiling) && !is_mac && !is_ios && + current_os != "aix") { + # TODO(jochen): Enable this on chromeos on arm. http://crbug.com/356580 + # TODO(lizeb,pasko): Fix link errors when linking with order_profiling=1 + # crbug.com/485542 + ldflags += [ "-Wl,--fatal-warnings" ] + } + } else { + } + + 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_mac || is_ios)) || is_fuchsia) { + if (enable_profiling) { + if (!is_debug) { + cflags += [ "-g" ] + + if (enable_full_stack_frames_for_profiling) { + cflags += [ + "-fno-inline", + "-fno-optimize-sibling-calls", + ] + } + } + } + + if (is_official_build || force_local_build_id) { + # 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). The crash infrastructure does need a build + # id, so explicitly enable it in official builds. It's not needed in + # unofficial builds and computing it does slow down the link, so go with + # faster links in unofficial builds. + ldflags += [ "-Wl,--build-id=sha1" ] + } + + 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_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" ] + } + + # Compiler instrumentation can introduce dependencies in DSOs to symbols in + # the executable they are loaded into, so they are unresolved at link-time. + if (!using_sanitizer) { + ldflags += [ + "-Wl,-z,defs", + "-Wl,--as-needed", + ] + } + } + + # Linux-specific compiler flags setup. + # ------------------------------------ + if (is_android && is_clang) { + _rebased_android_toolchain_root = + rebase_path(android_toolchain_root, root_build_dir) + + # Let clang find the linker in the NDK. + ldflags += [ "--gcc-toolchain=$_rebased_android_toolchain_root" ] + } + + if (((is_posix || is_fuchsia) && use_lld) || + (target_os == "chromeos" && is_android)) { + # NOTE: Some Chrome OS builds globally disable LLD, but they also build some + # targets against Android toolchains which should use LLD. Therefore we + # explicitly select LLD in these cases. + # + # TODO(https://crbug.com/837095): This should be cleaned up if/when LLD can + # work properly for Chrome OS builds. + ldflags += [ "-fuse-ld=lld" ] + if (current_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. + ldflags += [ "-B$gold_path" ] + + if (linux_use_bundled_binutils) { + 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", + # ] + #} + } else if (linux_use_bundled_binutils) { + # Gold is the default linker for the bundled binutils so we explicitly + # enable the bfd linker when use_gold is not set. + ldflags += [ "-fuse-ld=bfd" ] + } + + if (use_icf) { + ldflags += [ "-Wl,--icf=all" ] + } + + if (linux_use_bundled_binutils) { + cflags += [ "-B$binutils_path" ] + } + + if (is_linux) { + 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" ] + } + } + + if (is_clang && !is_nacl && !use_xcode_clang) { + cflags += [ "-fcrash-diagnostics-dir=" + + rebase_path("//tools/clang/crashreports", root_build_dir) ] + + cflags += [ + # TODO(hans): Remove this once Clang generates better optimized debug info + # by default. https://crbug.com/765793 + "-Xclang", + "-mllvm", + "-Xclang", + "-instcombine-lower-dbg-declare=0", + ] + } + + # C11/C++11 compiler flags setup. + # --------------------------- + if (is_linux || 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" ] + } + } + + 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 || target_os == "chromeos", + "gold plugin only supported with ChromeOS") + + cflags += [ "-flto=thin" ] + + if (target_os != "chromeos") { + cflags += [ "-fsplit-lto-unit" ] + } + + if (thin_lto_enable_optimizations) { + lto_opt_level = 2 + } else { + lto_opt_level = 0 + } + + if (is_win) { + # This is a straight translation of the non-Windows flags below, + # except we do not use the ThinLTO cache, which leaks temporary + # files on Windows (https://crbug.com/871962). + ldflags += [ + "/opt:lldlto=" + lto_opt_level, + "/opt:lldltojobs=8", + + # Experimentally determined to yield a reasonable trade-off between + # build time, run-time performance, and binary size. + "-mllvm:-import-instr-limit=10", + ] + } else { + ldflags += [ "-flto=thin" ] + + # Limit the parallelism to avoid too aggressive competition between + # linker jobs. This is still suboptimal to a potential dynamic + # resource allocation scheme, but should be good enough. + if (use_lld) { + ldflags += [ "-Wl,--thinlto-jobs=8" ] + + # Disable caching on Chrome OS temporarily (crbug.com/889967) + if (!is_chromeos) { + # Limit the size of the ThinLTO cache to the lesser of 10% of + # available disk space, 10GB and 100000 files. + cache_policy = + "cache_size=10%:cache_size_bytes=10g:cache_size_files=100000" + ldflags += [ + "-Wl,--thinlto-cache-dir=" + + rebase_path("$root_out_dir/thinlto-cache", root_build_dir), + "-Wl,--thinlto-cache-policy,$cache_policy", + ] + } + } else { + ldflags += [ "-Wl,-plugin-opt,jobs=8" ] + } + + if (use_lld) { + ldflags += [ "-Wl,--lto-O" + lto_opt_level ] + if (thin_lto_enable_optimizations) { + if (is_android) { + # TODO(gbiv): We ideally shouldn't need to specify this; ThinLTO + # should be able to better manage binary size increases on its own. + ldflags += [ + "-Wl,-mllvm", + "-Wl,-import-instr-limit=5", + ] + } + } + } else { + not_needed([ "lto_opt_level" ]) + } + } + + # TODO(pcc): Re-enable this flag on Android. This will require libc++ to be + # built with ThinLTO (see https://crbug.com/767901) as well as the GVR shim. + if (!is_android) { + cflags += [ "-fwhole-program-vtables" ] + if (!is_win) { + ldflags += [ "-fwhole-program-vtables" ] + } + } + + # Work-around for http://openradar.appspot.com/20356002 + if (is_mac) { + ldflags += [ "-Wl,-all_load" ] + } + + # 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 (current_cpu == "arm") { + ldflags += [ "-march=$arm_arch" ] + } + } + + if (compiler_timing) { + if (is_clang) { + if (is_win) { + cflags += [ "/clang:-ftime-report" ] + } else { + cflags += [ "-ftime-report" ] + } + } 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 to work around issue in Valgrind related to + # location of debug symbols. This is also enabled for Android + # builds to allow debuggerd to properly symbolize stack crashes + # on this platform (http://crbug.com/919499). + if (use_lld && (ro_segment_workaround_for_valgrind || is_android)) { + ldflags += [ "-Wl,--no-rosegment" ] + } + + # 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). + if (is_clang && !is_nacl && target_os != "chromeos" && !use_xcode_clang && + (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 + } +} + +# 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_mac || is_ios)) || 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 (current_cpu == "x64") { + cflags += [ + "-m64", + "-march=x86-64", + ] + ldflags += [ "-m64" ] + } else if (current_cpu == "x86") { + cflags += [ "-m32" ] + ldflags += [ "-m32" ] + if (!is_nacl) { + cflags += [ + "-msse2", + "-mfpmath=sse", + "-mmmx", + ] + } + } else if (current_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 (current_cpu == "arm64") { + if (is_clang && !is_android && !is_nacl && !is_fuchsia) { + cflags += [ "--target=aarch64-linux-gnu" ] + ldflags += [ "--target=aarch64-linux-gnu" ] + } + } else if (current_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 (current_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 (current_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 (current_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 (current_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 (current_cpu == "ppc64") { + if (current_os == "aix") { + cflags += [ "-maix64" ] + ldflags += [ "-maix64" ] + } else { + cflags += [ "-m64" ] + ldflags += [ "-m64" ] + } + } else if (current_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" ] + } else if (is_posix && !is_mac && !is_ios) { + if (current_cpu == "x86") { + if (is_clang) { + cflags += [ + # Else building libyuv gives clang's register allocator issues, + # see llvm.org/PR15798 / crbug.com/233709 + "-momit-leaf-frame-pointer", + ] + } + } + } + + if (current_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 (symbol_level != 0 && 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. + cflags += [ + "-Xclang", + "-fdebug-compilation-dir", + "-Xclang", + ".", + ] + + if (is_win && use_lld) { + if (symbol_level == 2 || (is_clang && using_sanitizer)) { + # Absolutize source file path for PDB. Pass the real build directory + # if the pdb contains source-level debug information. + ldflags += [ "/PDBSourcePath:" + rebase_path(root_build_dir) ] + } else { + # On Windows, (non-sanitizier) symbol_level 1 builds don't contain + # debug information in obj files; the linker just creates enough + # debug info at link time to produce symbolized stacks (without line + # numbers). In that case, there's no downside in using a fake fixed + # base directory for paths in the pdb. This makes the pdb output + # fully deterministic and independent of the build directory. + assert(symbol_level == 1 && !(is_clang && using_sanitizer)) + 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" ] + } +} + +config("clang_revision") { + if (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 (current_cpu == "arm" && !is_ios && !is_nacl) { + cflags = [ "-mfpu=$arm_fpu" ] + asmflags = cflags + } +} + +config("compiler_arm_thumb") { + if (current_cpu == "arm" && arm_use_thumb && is_posix && + !(is_mac || is_ios || is_nacl)) { + cflags = [ "-mthumb" ] + } +} + +config("compiler_arm") { + if (current_cpu == "arm" && is_chromeos) { + # 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" ] + } +} + +config("assembler_debug_dir") { + # TODO(thakis): Once openmax_dl no longer uses -fno-integrated-as, move + # this behind the -fdebug-compilation-dir cflags in the "compiler" config. + if (symbol_level != 0 && is_clang && strip_absolute_paths_from_debug_symbols) { + if (!is_win) { + # We don't use clang -cc1as on Windows (yet? https://crbug.com/762167) + asmflags = [ "-Wa,-fdebug-compilation-dir,." ] + } + } +} + +# 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) { + 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_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 + + # http://crbug.com/346399 - Unreachable code suppression waiting on Clang + # -Wunreachable-code. + "/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 (current_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", + ] + } + + # VS xtree header file needs to be patched or 4702 (unreachable code + # warning) is reported if _HAS_EXCEPTIONS=0. Disable the warning if xtree is + # not patched. + if (!msvs_xtree_patched && + exec_script("../../win_is_xtree_patched.py", [], "value") == 0) { + cflags += [ "/wd4702" ] # Unreachable code. + } + } else { + if ((is_mac || is_ios) && !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 (current_cpu == "arm" && !is_clang) { + cflags += [ "-Wno-psabi" ] + } + + if (!is_clang) { + cflags_cc += [ + # See comment for -Wno-c++11-narrowing. + "-Wno-narrowing", + ] + + # -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" ] + } + } + + # 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 += [ + # TODO(thakis): Consider -Wloop-analysis (turns on + # -Wrange-loop-analysis too). + + # This warns on using ints as initializers for floats in + # initializer lists (e.g. |int a = f(); CGSize s = { a, a };|), + # which happens in several places in chrome code. Not sure if + # this is worth fixing. + "-Wno-c++11-narrowing", + + # 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) { + cflags += [ + # TODO(thakis): https://crbug.com/604888 + "-Wno-undefined-var-template", + ] + + if (is_win) { + # TODO(thakis): https://crbug.com/617318 + # Currently goma can not handle case sensitiveness for windows well. + cflags += [ "-Wno-nonportable-include-path" ] + } + + if (current_toolchain == host_toolchain || !use_xcode_clang) { + # Flags NaCl (Clang 3.7) and Xcode 9.2 (Clang clang-900.0.39.2) do not + # recognize. + cflags += [ + # Ignore warnings about MSVC optimization pragmas. + # TODO(thakis): Only for no_chromium_code? http://crbug.com/912662 + "-Wno-ignored-pragma-optimize", + ] + if (is_fuchsia) { + cflags += [ + # TODO(hans): https://crbug.com/890307 + "-Wno-defaulted-function-deleted", + ] + } + } + } + } +} + +# 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 && current_cpu != "s390x" && + current_cpu != "s390" && current_cpu != "ppc64" && + current_cpu != "mips" && current_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_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", + + # 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_ios && use_xcode_clang) { + # TODO(thakis): Remove this branch once Xcode's clang has clang r356148. + cflags_c = [ "-Wextra-semi" ] + cflags_cc = [ "-Wextra-semi" ] + } else if (!has_dchecks && is_chromeos && 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", + ] + } + + 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") { + if (is_desktop_linux || 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") { + # Mac and iOS use the mac-specific "libtool" command, not ar, which doesn't + # have a "thin archive" mode (it does accept -T, but it means truncating + # archive names to 16 characters, which is not what we want). + if ((is_posix && !is_nacl && !is_mac && !is_ios) || 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 --------------------------------------------------------------------- + +# 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 blacklist instead, http://crbug.com/101600 +config("wexit_time_destructors") { + if (is_clang) { + cflags = [ "-Wexit-time-destructors" ] + } +} + +# On Windows compiling on x64, VC will issue a warning when converting +# size_t to int because it will truncate the value. Our code should not have +# these warnings and one should use a static_cast or a checked_cast for the +# conversion depending on the case. However, a lot of code still needs to be +# fixed. Apply this config to such targets to disable the warning. +# +# Note that this can be applied regardless of platform and architecture to +# clean up the call sites. This will only apply the flag when necessary. +# +# This config is just an alias to no_shorten_64_warnings and will +# suppress a superset of warning 4267 and any 64-bit -> 32-bit implicit +# conversions. Having both for a time means not having to go through and +# update all references to no_size_t_to_int_warning throughout the codebase +# atomically. +# +# Any new warning suppressions should use the no_shorten_64_warnings +# config below and not this. +# +# TODO(jschuh): crbug.com/167187 fix this and delete this config. +config("no_size_t_to_int_warning") { + configs = [ ":no_shorten_64_warnings" ] +} + +# As part of re-enabling -Wconversion (see issue 588506) some code +# will continue to generate warnings. +# The first warning to be enabled will be -Wshorten-64-to-32. +# +# Code that currently generates warnings for this can include this +# config to disable them. +config("no_shorten_64_warnings") { + if (current_cpu == "x64" || current_cpu == "arm64") { + if (is_clang) { + cflags = [ "-Wno-shorten-64-to-32" ] + } else { + if (is_win) { + # MSVC does not have an explicit warning equivalent to + # -Wshorten-64-to-32 but 4267 warns for size_t -> int + # on 64-bit builds, so is the closest. + cflags = [ "/wd4267" ] + } + } + } +} + +# 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 (current_cpu == "mipsel" || current_cpu == "mips64el") { + cflags += [ "-w" ] + } else if (is_chromeos && current_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. It is also incompatible with + # incremental linking, which we enable for both Debug and component builds. + 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): Remove is_clang here, https://crbug.com/598772 + if (!use_lld && !is_clang) { + common_optimize_on_ldflags += [ + # Set the number of LTCG code-gen threads to eight. The default is four. + # This gives a 5-10% link speedup. + "/cgthreads:8", + ] + if (use_incremental_wpo) { + # Incremental Link-time code generation. + common_optimize_on_ldflags += [ "/LTCG:INCREMENTAL" ] + } else { + common_optimize_on_ldflags += [ "/LTCG" ] # Link-time code generation. + } + if (full_wpo_on_official) { + if (use_incremental_wpo) { + arflags = [ "/LTCG:INCREMENTAL" ] + } else { + arflags = [ "/LTCG" ] + } + } + } + } +} 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 (current_cpu != "mipsel" && current_cpu != "mips64el") { + common_optimize_on_ldflags += [ + # Warn in case of text relocations. + "-Wl,--warn-shared-textrel", + ] + } + } + + if (is_mac || is_ios) { + if (symbol_level == 2) { + # Mac dead code stripping requires symbols. + common_optimize_on_ldflags += [ "-Wl,-dead_strip" ] + } + } else if (current_os != "aix") { + # Non-Mac Posix flags. + # Aix does not support these. + + common_optimize_on_cflags += [ + # Don't emit the GCC version ident directives, they just end up in the + # .comment section taking up binary size. + "-fno-ident", + + # 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", + ] + + 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" ] + } 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) { + # TODO(thakis): Remove is_clang here, https://crbug.com/598772 + if (is_official_build && full_wpo_on_official && !is_clang) { + common_optimize_on_cflags += [ + "/GL", # Whole program optimization. + + # Disable Warning 4702 ("Unreachable code") for the WPO/PGO builds. + # Probably anything that this would catch that wouldn't be caught in a + # normal build isn't going to actually be a bug, so the incremental + # value of C4702 for PGO builds is likely very small. + "/wd4702", + ] + } + + # Favor size over speed, /O1 must be before the common flags. The GYP + # build also specifies /Os and /GF but these are implied by /O1. + cflags = [ "/O1" ] + 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 { + cflags = [ "-O2" ] + common_optimize_on_cflags + } + ldflags = common_optimize_on_ldflags +} + +# Same config as 'optimize' but without the WPO flag. +config("optimize_no_wpo") { + if (is_win) { + # Favor size over speed, /O1 must be before the common flags. The GYP + # build also specifies /Os and /GF but these are implied by /O1. + cflags = [ "/O1" ] + 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 (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O2" ] + common_optimize_on_cflags + } + 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). + ] + } 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 + } + } 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. The GYP + # build also specifies /Ot, /Oi, and /GF, but these are implied by /O2. + cflags = [ "/O2" ] + common_optimize_on_cflags + + if (is_official_build) { + if (!is_clang) { + cflags += [ + "/GL", # Whole program optimization. + + # Disable Warning 4702 ("Unreachable code") for the WPO/PGO builds. + # Probably anything that this would catch that wouldn't be caught + # in a normal build isn't going to actually be a bug, so the + # incremental value of C4702 for PGO builds is likely very small. + "/wd4702", + ] + } + # TODO(crbug.com/598772): Enable -flto for Clang. + } + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O2" ] + common_optimize_on_cflags + } + } +} + +# 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. The GYP + # build also specifies /Ot, /Oi, and /GF, but these are implied by /O2. + cflags = [ "/O2" ] + common_optimize_on_cflags + + # TODO(thakis): Remove is_clang here, https://crbug.com/598772 + if (is_official_build && !is_clang) { + cflags += [ + "/GL", # Whole program optimization. + + # Disable Warning 4702 ("Unreachable code") for the WPO/PGO builds. + # Probably anything that this would catch that wouldn't be caught in a + # normal build isn't going to actually be a bug, so the incremental + # value of C4702 for PGO builds is likely very small. + "/wd4702", + ] + } + } else if (optimize_for_fuzzing) { + cflags = [ "-O1" ] + common_optimize_on_cflags + } else { + cflags = [ "-O3" ] + common_optimize_on_cflags + } + } +} + +config("optimize_fuzzing") { + cflags = [ "-O1" ] + common_optimize_on_cflags + 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_desktop_linux, + "The current platform has no default profile") + _clang_sample_profile = "//chrome/android/profiles/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) { + if (_clang_sample_profile != "") { + 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 = [ + ":symbols", + ":minimal_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 no downside to always using this. + ldflags = [ "/pdbaltpath:%_PDB%" ] +} + +# Full symbols. +config("symbols") { + if (is_win) { + if (use_goma || is_clang) { + # Note that with VC++ this requires is_win_fastlink, enforced elsewhere. + cflags = [ "/Z7" ] # Debug information in the .obj files. + } else { + cflags = [ "/Zi" ] # Produce PDB file, no edit and continue. + } + + if (is_win_fastlink && !use_lld) { + # TODO(hans): is_win_fastlink=true is incompatible with use_lld. However, + # some developers might have enabled it manually, so to ease the + # transition to lld, just ignore it rather than asserting. Eventually we + # want to assert instead. + + # Tell VS 2015+ to create a PDB that references debug + # information in .obj and .lib files instead of copying + # it all. This flag is incompatible with /PROFILE + ldflags = [ "/DEBUG:FASTLINK" ] + } else 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" ] + + if (is_clang) { + # /DEBUG:FASTLINK requires every object file to have standalone debug + # information. + if (is_win_fastlink && !use_lld) { + cflags += [ "-fstandalone-debug" ] + } else { + cflags += [ "-fno-standalone-debug" ] + } + } + } 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" ] + } + if (!use_debug_fission && current_cpu == "arm") { + # dump_syms has issues with dwarf4 on arm, https://crbug.com/744956 + # TODO(thakis): Remove this again once dump_syms is fixed. + # + # debug fission needs DWARF DIEs to be emitted at version 4. + # Chrome OS emits Debug Frame in DWARF2's .debug_frame v1 to make breakpad + # happy [1]. + # Unless Android needs debug fission, DWARF3 is the simplest solution. + # + # [1] crrev.com/a81d5ade0b043208e06ad71a38bcf9c348a1a52f + cflags += [ "-gdwarf-3" ] + } else if (is_mac) { + # 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" ] + } + + # 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 (use_debug_fission && !is_nacl && !is_android) { + # NOTE: Some Chrome OS builds globally set |use_debug_fission| to true, + # but they also build some targets against Android toolchains which aren't + # compatible with it. + # + # TODO(https://crbug.com/837032): See if we can clean this up by e.g. not + # setting use_debug_fission globally. + cflags += [ "-gsplit-dwarf" ] + } + asmflags = cflags + ldflags = [] + + # 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_mac && !is_ios && !is_nacl && current_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" ] + } + } +} + +# 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) { + # Linker symbols for backtraces only. + cflags = [] + ldflags = [ "/DEBUG" ] + + # All configs using /DEBUG should include this: + configs = [ ":win_pdbaltpath" ] + + # For win/asan, get stack traces with full line numbers. + # AddressSanitizerTests.TestAddressSanitizer needs this, and since + # win/asan isn't a default cq bot the build time hit is ok. + if (is_clang && using_sanitizer) { + # -gline-tables-only is the same as -g1, but clang-cl only exposes the + # former. + cflags += [ "-gline-tables-only" ] + } + } else { + cflags = [] + if (current_cpu == "arm") { + # dump_syms has issues with dwarf4 on arm, https://crbug.com/744956 + # TODO(thakis): Remove this again once dump_syms is fixed. + cflags += [ "-gdwarf-3" ] + } else if (is_mac) { + # 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" ] + } + + # 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" ] + } + 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: -gsplit-dwarf implicitly turns on -g2 with clang, so don't pass it. + asmflags = cflags + } +} + +# No symbols. +config("no_symbols") { + if (!is_win) { + 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_ios || is_mac) { + # 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 + } +} diff --git a/deps/v8/build/config/compiler/compiler.gni b/deps/v8/build/config/compiler/compiler.gni new file mode 100644 index 0000000000..3bdd85bf97 --- /dev/null +++ b/deps/v8/build/config/compiler/compiler.gni @@ -0,0 +1,286 @@ +# 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/compiler/pgo/pgo.gni") +import("//build/config/sanitizers/sanitizers.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") +import("//build_overrides/build.gni") + +if (is_chromeos) { + import("//build/config/chromeos/rules.gni") +} else { + is_cros_chrome_sdk = false +} + +if (is_android) { + import("//build/config/android/abi.gni") +} +if (current_cpu == "arm" || current_cpu == "arm64") { + import("//build/config/arm.gni") +} + +declare_args() { + # 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_thin_lto = is_cfi || (is_android && is_official_build) + + # Tell VS to create a PDB that references information in .obj files rather + # than copying it all. This should improve linker performance. mspdbcmf.exe + # can be used to convert a fastlink pdb to a normal one. + is_win_fastlink = false + + # Whether or not we should turn on incremental WPO. Only affects the VS + # Windows build. + use_incremental_wpo = 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 = current_cpu != "x64" && current_cpu != "x86" +} + +assert(!is_cfi || use_thin_lto, "CFI requires ThinLTO") + +# Exclude unwind tables for official builds as unwinding can be done from stack +# dumps produced by Crashpad at a later time "offline" in the crash server. +# 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. +exclude_unwind_tables = (is_chrome_branded && is_official_build) || + (is_chromecast && !is_cast_desktop_build && !is_debug && + !cast_is_debug && !is_fuchsia) + +# 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. +if (is_mac || is_ios || is_linux) { + enable_frame_pointers = true +} else if (is_win) { + # 64-bit Windows ABI doesn't support frame pointers. + if (current_cpu == "x64") { + enable_frame_pointers = false + } else { + enable_frame_pointers = true + } +} else if (is_chromeos) { + # 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 = current_cpu != "arm" +} else if (is_android) { + enable_frame_pointers = + enable_profiling || + # Ensure that stacks from arm64 crash dumps are usable (crbug.com/391706). + current_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. + (current_cpu == "x86" && !exclude_unwind_tables && optimize_for_size) || + using_sanitizer +} 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 (current_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 && current_cpu == "arm" + +declare_args() { + # Whether or not the official builds should be built with full WPO. Enabled by + # default for the PGO and the x64 builds. + if (chrome_pgo_phase > 0) { + full_wpo_on_official = true + } else { + full_wpo_on_official = false + } +} + +declare_args() { + # Set to true to use lld, the LLVM linker. + # https://crbug.com/911658 for using lld on 32-bit linux. + # https://crbug.com/917504 for arm chromeos + use_lld = is_clang && + (is_win || is_fuchsia || is_android || + (is_linux && target_os != "chromeos" && current_cpu != "x86") || + (target_os == "chromeos" && current_cpu != "arm")) +} + +declare_args() { + # Whether to use the gold linker from binutils instead of lld or bfd. + use_gold = + !use_lld && !(is_chromecast && is_linux && + (current_cpu == "arm" || current_cpu == "mipsel")) && + ((is_linux && (current_cpu == "x64" || current_cpu == "x86" || + current_cpu == "arm" || current_cpu == "arm64" || + current_cpu == "mipsel" || current_cpu == "mips64el")) || + (is_android && (current_cpu == "x86" || current_cpu == "x64" || + current_cpu == "arm" || current_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/+/master/docs/linux_debugging.md#Source-level-debug-with-fdebug_compilation_dir + strip_absolute_paths_from_debug_symbols = + is_android || is_fuchsia || is_nacl || (is_win && use_lld) || is_linux +} + +# 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 && + !(android_64bit_target_cpu && !build_apk_secondary_abi)) { + # 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_win && use_goma && !is_clang) { + # goma doesn't support PDB files, so we disable symbols during goma + # compilation because otherwise the redundant debug information generated + # by visual studio (repeated in every .obj file) makes linker + # memory consumption and link times unsustainable (crbug.com/630074). + # Clang on windows does not have this issue. + # If you use is_win_fastlink = true or lld or clang then you can set + # symbol_level = 2 when using goma. + symbol_level = 1 + } else if (is_cros_chrome_sdk) { + # 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_fuchsia) || 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 + } +} else if (symbol_level == 2) { + if (is_win) { + # See crbug.com/630074 + assert(is_win_fastlink || use_lld || !use_goma || is_clang, + "VC++ goma builds that use symbol_level 2 must use " + + "is_win_fastlink or use_lld.") + } +} + +# 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 (build_with_chromium) { + 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" || + (android_64bit_target_cpu && !build_apk_secondary_abi) || + is_component_build || symbol_level < 2, + "Android 32-bit non-component builds 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.") + +# This variable is true if the current toolchain is either the default +# toolchain, or, on Android, the secondary ABI toolchain. In other words, it's +# a toolchain that generates targets for the product, as opposed to the host +# OS. It can be used in situations where we wish to avoid doing work on the +# host toolchain, but we don't want to break Android's secondary ABI. +# Ie. "current_toolchain == default_toolchain" is not a good way to infer +# "not the host toolchain". +is_a_target_toolchain = + current_toolchain == default_toolchain || + (is_android && defined(android_secondary_abi_toolchain) && + current_toolchain == android_secondary_abi_toolchain) diff --git a/deps/v8/build/config/compiler/pgo/BUILD.gn b/deps/v8/build/config/compiler/pgo/BUILD.gn new file mode 100644 index 0000000000..bb147a6ecc --- /dev/null +++ b/deps/v8/build/config/compiler/pgo/BUILD.gn @@ -0,0 +1,101 @@ +# 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/clang/clang.gni") +import("//build/config/compiler/compiler.gni") +import("//build/config/compiler/pgo/pgo.gni") + +# Configuration that enables PGO instrumentation. +config("pgo_instrumentation_flags") { + visibility = [ ":default_pgo_flags" ] + cflags = [] + ldflags = [] + + # 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) { + if (is_clang) { + cflags = [ "-fprofile-instr-generate" ] + if (is_win) { + # Normally, we pass -fprofile-instr-generate to the compiler and it + # automatically passes the right flags to the linker. + # However, on Windows, we call the linker directly, without going + # through the compiler driver. This means we need to pass the right + # flags ourselves. + _clang_rt_base_path = + "$clang_base_path/lib/clang/$clang_version/lib/windows" + if (target_cpu == "x86") { + _clang_rt_suffix = "-i386.lib" + } else if (target_cpu == "x64") { + _clang_rt_suffix = "-x86_64.lib" + } + assert(_clang_rt_suffix != "", "target CPU $target_cpu not supported") + ldflags += [ "$_clang_rt_base_path/clang_rt.profile$_clang_rt_suffix" ] + } else { + ldflags += [ "-fprofile-instr-generate" ] + } + } else if (is_win) { + ldflags = [ + # In MSVC, we must use /LTCG when using PGO. + "/LTCG", + + # Make sure that enough memory gets allocated for the PGO profiling + # buffers and also cap this memory. Usually a PGI instrumented build + # of chrome_child.dll requires ~55MB of memory for storing its counter + # etc, normally the linker should automatically choose an appropriate + # amount of memory but it doesn't always do a good estimate and + # sometime allocates too little or too much (and so the instrumented + # image fails to start). Making sure that the buffer has a size in the + # [128 MB, 512 MB] range should prevent this from happening. + "/GENPROFILE:MEMMIN=134217728", + "/GENPROFILE:MEMMAX=536870912", + "/PogoSafeMode", + ] + } + } +} + +# Configuration that enables optimization using profile data. +config("pgo_optimization_flags") { + visibility = [ ":default_pgo_flags" ] + cflags = [] + ldflags = [] + + # 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) { + if (is_clang) { + 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-error=profile-instr-out-of-date", + ] + } else if (is_win) { + ldflags += [ + # In MSVC, we must use /LTCG when using PGO. + "/LTCG", + "/USEPROFILE", + ] + } + } +} + +# 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/deps/v8/build/config/compiler/pgo/pgo.gni b/deps/v8/build/config/compiler/pgo/pgo.gni new file mode 100644 index 0000000000..5da004d28f --- /dev/null +++ b/deps/v8/build/config/compiler/pgo/pgo.gni @@ -0,0 +1,17 @@ +# 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. + +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. + # + # TODO(sebmarchand): Add support for the PGU (update) phase. + chrome_pgo_phase = 0 + + # When using chrome_pgo_phase = 2, read profile data from this path. + pgo_data_path = "" +} diff --git a/deps/v8/build/config/compute_inputs_for_analyze.gni b/deps/v8/build/config/compute_inputs_for_analyze.gni new file mode 100644 index 0000000000..050ab70a3f --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/coverage/BUILD.gn b/deps/v8/build/config/coverage/BUILD.gn new file mode 100644 index 0000000000..2604411aea --- /dev/null +++ b/deps/v8/build/config/coverage/BUILD.gn @@ -0,0 +1,44 @@ +# 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) { + ldflags += [ "-fprofile-instr-generate" ] + } else { + # Windows directly calls link.exe instead of the compiler driver when + # linking. Hence, pass the runtime libraries instead of + # -fsanitize=address. + # TODO(rnk): Come up with a more uniform approach for linking against + # compiler-rt for sanitizers and coverage. + if (target_cpu == "x64") { + ldflags += [ "clang_rt.profile-x86_64.lib" ] + } else if (target_cpu == "x86") { + ldflags += [ "clang_rt.profile-i386.lib" ] + } else { + assert(false && + "use_clang_coverage=true not supported yet for this target_cpu") + } + } + + 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_win) { + cflags += [ "-fno-use-cxa-atexit" ] + } + } +} diff --git a/deps/v8/build/config/coverage/OWNERS b/deps/v8/build/config/coverage/OWNERS new file mode 100644 index 0000000000..70d27b62af --- /dev/null +++ b/deps/v8/build/config/coverage/OWNERS @@ -0,0 +1,3 @@ +inferno@chromium.org +mmoroz@chromium.org +ochang@chromium.org diff --git a/deps/v8/build/config/coverage/coverage.gni b/deps/v8/build/config/coverage/coverage.gni new file mode 100644 index 0000000000..12ab03fcd0 --- /dev/null +++ b/deps/v8/build/config/coverage/coverage.gni @@ -0,0 +1,29 @@ +# 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") + +# There are two ways to enable code coverage instrumentation: +# 1. When |use_clang_coverage| is true and |coverage_instrumentation_input_file| +# is empty, all source files are instrumented. +# 2. When |use_clang_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 are instrumented. +declare_args() { + # Enable Clang's Source-based Code Coverage. + use_clang_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'. + coverage_instrumentation_input_file = "" +} + +assert(!use_clang_coverage || is_clang, + "Clang Source-based Code Coverage requires clang.") + +assert(coverage_instrumentation_input_file == "" || use_clang_coverage, + "Instrument a subset of source files requires enabling clang coverage.") diff --git a/deps/v8/build/config/crypto.gni b/deps/v8/build/config/crypto.gni new file mode 100644 index 0000000000..a3d52deafd --- /dev/null +++ b/deps/v8/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 diff --git a/deps/v8/build/config/dcheck_always_on.gni b/deps/v8/build/config/dcheck_always_on.gni new file mode 100644 index 0000000000..e58cfced39 --- /dev/null +++ b/deps/v8/build/config/dcheck_always_on.gni @@ -0,0 +1,15 @@ +# 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. + +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 crbug.com/596231 for details on how this is used. + dcheck_is_configurable = false +} + +declare_args() { + # Set to true to enable dcheck in Release builds. + dcheck_always_on = dcheck_is_configurable +} diff --git a/deps/v8/build/config/features.gni b/deps/v8/build/config/features.gni new file mode 100644 index 0000000000..fdf05dfdd9 --- /dev/null +++ b/deps/v8/build/config/features.gni @@ -0,0 +1,59 @@ +# 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") +if (is_android) { + import("//build/config/android/config.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 + + # Variable safe_browsing is used to control the build time configuration for + # safe browsing feature. Safe browsing can be compiled in 3 different levels: + # 0 disables it, 1 enables it fully, 2 enables mobile protection via an + # external API, and 3 enables mobile protection via internal API. + if (is_ios || is_chromecast) { + safe_browsing_mode = 0 + } else if (is_android) { + if (notouch_build) { + safe_browsing_mode = 3 + } else { + safe_browsing_mode = 2 + } + } else { + safe_browsing_mode = 1 + } + + # libudev usage. This currently only affects the content layer. + use_udev = is_linux && !is_chromecast + + use_dbus = is_linux && !is_chromecast + + use_gio = is_linux && !is_chromeos && !is_chromecast +} +# +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# See comment at the top. diff --git a/deps/v8/build/config/freetype/BUILD.gn b/deps/v8/build/config/freetype/BUILD.gn new file mode 100644 index 0000000000..0ba9027167 --- /dev/null +++ b/deps/v8/build/config/freetype/BUILD.gn @@ -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. + +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/deps/v8/build/config/freetype/OWNERS b/deps/v8/build/config/freetype/OWNERS new file mode 100644 index 0000000000..3277f87312 --- /dev/null +++ b/deps/v8/build/config/freetype/OWNERS @@ -0,0 +1,2 @@ +bungeman@chromium.org +drott@chromium.org diff --git a/deps/v8/build/config/freetype/freetype.gni b/deps/v8/build/config/freetype/freetype.gni new file mode 100644 index 0000000000..b4eced2d65 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/fuchsia/BUILD.gn b/deps/v8/build/config/fuchsia/BUILD.gn new file mode 100644 index 0000000000..59da62e766 --- /dev/null +++ b/deps/v8/build/config/fuchsia/BUILD.gn @@ -0,0 +1,128 @@ +# 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/fuchsia/config.gni") +import("//build/config/fuchsia/rules.gni") +import("//build/config/sysroot.gni") + +assert(is_fuchsia) +assert(!is_posix) + +config("compiler") { + sdk_version_file = "${fuchsia_sdk}/.hash" + sdk_version = read_file(sdk_version_file, "trim string") + defines = [ + # To force full builds after SDK updates in case of ABI changes. + "FUCHSIA_SDK_VERSION=$sdk_version", + ] + cflags = [] + ldflags = [] + if (current_cpu == "arm64") { + cflags += [ "--target=aarch64-fuchsia" ] + ldflags += [ "--target=aarch64-fuchsia" ] + } else if (current_cpu == "x64") { + cflags += [ "--target=x86_64-fuchsia" ] + ldflags += [ "--target=x86_64-fuchsia" ] + } else { + assert(false, "Unsupported architecture") + } + asmflags = cflags + + ldflags += [ + # 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. + "-Wl,-z,stack-size=0x800000", + + # We always want fdio or else e.g. stdio wouldn't be initialized if fdio + # happens to not be directly referenced. The common POSIX-y compiler setup + # uses -Wl,--as-needed which drops it if it's simply "-lfdio" from a libs + # setting. Disable --as-needed, add fdio, and then set back to --as-needed. + # https://crbug.com/731217. + "-Wl,--no-as-needed", + "-lfdio", + "-Wl,--as-needed", + ] + + # Add SDK lib dir for -lfdio above. + lib_dirs = [ "${fuchsia_sdk}/arch/${current_cpu}/lib" ] + + # TODO(crbug.com/821951): Clang enables SafeStack by default when targeting + # Fuchsia, but it breaks some tests, notably in V8. + cflags += [ "-fno-sanitize=safe-stack" ] + + libs = [ "zircon" ] +} + +# Writes an extended version of fvm.blk to fvm.extended.blk. +blobstore_extended_path = "$root_out_dir/fvm.extended.blk" +action("blobstore_extended_fvm") { + # The file is grown by 1GB, which should be large enough to hold packaged + # binaries and assets. The value should be increased if the size becomes a + # limitation in the future. + _extend_size = "1073741824" # 1GB + + _target_dir = "${fuchsia_sdk}/target/${current_cpu}" + + script = "//build/config/fuchsia/extend_fvm.py" + + inputs = [ + "${fuchsia_sdk}/tools/fvm", + "${_target_dir}/fvm.blk", + ] + outputs = [ + blobstore_extended_path, + ] + + args = [ + rebase_path("${fuchsia_sdk}/tools/fvm", root_build_dir), + rebase_path("${_target_dir}/fvm.blk", root_build_dir), + rebase_path(blobstore_extended_path, root_build_dir), + _extend_size, + ] +} + +# _________________________________________ +# / Create a compressed copy-on-write (COW) \ +# \ image based on fvm.blk. / +# ----------------------------------------- +# \ ^__^ +# \ (oo)\_______ +# (__)\ )\/\ +# ||----w | +# || || +action("blobstore_extended_qcow2") { + script = "//build/gn_run_binary.py" + + deps = [ + ":blobstore_extended_fvm", + ] + inputs = [ + blobstore_extended_path, + ] + outputs = [ + blobstore_qcow_path, + ] + data = [ + blobstore_qcow_path, + ] + + args = [ + rebase_path("${qemu_root}/bin/qemu-img", root_build_dir), + "convert", + "-f", + "raw", + "-O", + "qcow2", + "-c", + rebase_path(blobstore_extended_path, root_build_dir), + rebase_path(blobstore_qcow_path, root_build_dir), + ] +} + +# Settings for executables. +config("executable_config") { + ldflags = [ "-pie" ] +} diff --git a/deps/v8/build/config/fuchsia/OWNERS b/deps/v8/build/config/fuchsia/OWNERS new file mode 100644 index 0000000000..e7034eabb1 --- /dev/null +++ b/deps/v8/build/config/fuchsia/OWNERS @@ -0,0 +1 @@ +file://build/fuchsia/OWNERS diff --git a/deps/v8/build/config/fuchsia/build_symbol_archive.py b/deps/v8/build/config/fuchsia/build_symbol_archive.py new file mode 100755 index 0000000000..264c6ddfca --- /dev/null +++ b/deps/v8/build/config/fuchsia/build_symbol_archive.py @@ -0,0 +1,76 @@ +#!/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 binary symbols derived from the unstripped +executables and libraries cataloged by "ids.txt".""" + +import argparse +import os +import subprocess +import sys +import tarfile +import tempfile + + +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('--eu-strip', required=True, type=str, + help='Path to the eu-strip tool.') + parser.add_argument('--fuchsia-build-id-dir', type=str, required=True, + help='Directory containing symbols for SDK prebuilts.') + args = parser.parse_args(args) + + stripped_tempfile = tempfile.NamedTemporaryFile() + ids_txt = args.ids_txt[0] + build_ids_archive = tarfile.open(args.output_tarball[0], 'w:bz2') + for line in open(ids_txt, 'r'): + # debug_tempfile: The path which debug symbols will be written to. + # stripped_tempfile: The path which the stripped executable will be written + # to. This file is ignored and immediately deleted. + with tempfile.NamedTemporaryFile() as debug_tempfile, \ + tempfile.NamedTemporaryFile() as stripped_tempfile: + 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): + binary_abspath = os.path.abspath( + os.path.join(os.path.dirname(ids_txt), binary_path)) + + # Extract debugging symbols from the binary into their own file. + # The stripped executable binary is written to |debug_tempfile| and + # deleted. Writing to /dev/null would be preferable, but eu-strip + # disallows writing output to /dev/null. + subprocess.check_call([args.eu_strip, '-g', binary_abspath, + '-f', debug_tempfile.name, + '-o', stripped_tempfile.name]) + + if os.path.getsize(debug_tempfile.name) == 0: + # This is a prebuilt which wasn't accompanied by SDK symbols. + continue + + symbol_source_path = debug_tempfile.name + + + # Archive the debugging symbols, placing them in a hierarchy keyed to the + # GNU build ID. The symbols reside in directories whose names are the + # first two characters of the build ID, with the symbol files themselves + # named after the remaining characters of the build ID. So, a symbol file + # with the build ID "deadbeef" would be located at the path 'de/adbeef'. + build_ids_archive.add(symbol_source_path, + '%s/%s' % (build_id[:2], build_id[2:])) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/deps/v8/build/config/fuchsia/config.gni b/deps/v8/build/config/fuchsia/config.gni new file mode 100644 index 0000000000..cdf684e259 --- /dev/null +++ b/deps/v8/build/config/fuchsia/config.gni @@ -0,0 +1,22 @@ +# 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(current_os == "fuchsia") + +declare_args() { + # Path to Fuchsia SDK. + fuchsia_sdk = "//third_party/fuchsia-sdk/sdk" +} + +# Compute the arch-specific path to packages' dynamic library dependencies. +if (current_cpu == "arm64") { + dist_libroot = fuchsia_sdk + "/arch/arm64/dist" +} else if (current_cpu == "x64") { + dist_libroot = fuchsia_sdk + "/arch/x64/dist" +} else { + assert(false, "No libraries available for architecture: $current_cpu") +} + +# Compute the qemu path. +qemu_root = "//third_party/qemu-${host_os}-${host_cpu}" diff --git a/deps/v8/build/config/fuchsia/extend_fvm.py b/deps/v8/build/config/fuchsia/extend_fvm.py new file mode 100644 index 0000000000..44e5ee30e1 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/fuchsia/fidl_library.gni b/deps/v8/build/config/fuchsia/fidl_library.gni new file mode 100644 index 0000000000..acb1132a6f --- /dev/null +++ b/deps/v8/build/config/fuchsia/fidl_library.gni @@ -0,0 +1,262 @@ +# 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/fuchsia/config.gni") + +assert(is_fuchsia) + +# Template for FIDL libraries. Following parameters can be passed when +# instantiating this template: +# sources - List of .fidl files. +# library_name - (optional) Name of the library. target_name is used if name +# is not specified explicitly. +# namespace - (optional) Namespace for the library. +# deps - (optional) List of other fidl_library() targets that this +# FIDL library depends on. +# languages - Generate bindings for the given languages, defaults to +# [ "cpp" ]. "js" also supported. +# +# $namespace.$library_name must match the the library name specified in the FIDL +# files. + +template("fidl_library") { + forward_variables_from(invoker, + [ + "languages", + "namespace", + ]) + + _library_basename = target_name + if (defined(invoker.library_name)) { + _library_basename = invoker.library_name + } + + if (defined(namespace)) { + _library_name = "${namespace}.${_library_basename}" + _namespace_path = string_replace(namespace, ".", "/") + _library_path = "${_namespace_path}/${_library_basename}" + } else { + _library_name = _library_basename + _library_path = _library_basename + } + + if (!defined(invoker.languages)) { + languages = [ "cpp" ] + } + + _define_cpp_action = false + _define_js_action = false + + foreach(language, languages) { + if (language == "cpp") { + _define_cpp_action = true + } else if (language == "js") { + _define_js_action = true + } + } + + _response_file = "$target_gen_dir/$target_name.rsp" + _json_representation = "$target_gen_dir/${_library_name}.fidl.json" + _output_gen_dir = "$target_gen_dir/fidl" + _output_base = "$_output_gen_dir/${_library_path}/cpp/fidl" + _tables_file = "$_output_gen_dir/${_library_name}.fidl-tables.cc" + + action("${target_name}_response_file") { + script = "//third_party/fuchsia-sdk/gen_fidl_response_file.py" + + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "sources", + "testonly", + ]) + + _libraries_file = "$target_gen_dir/${invoker.target_name}.fidl_libraries" + + outputs = [ + _response_file, + _libraries_file, + ] + + args = [ + "--out-response-file", + rebase_path(_response_file, root_build_dir), + "--out-libraries", + rebase_path(_libraries_file, root_build_dir), + "--tables", + rebase_path(_tables_file, root_build_dir), + "--json", + rebase_path(_json_representation, root_build_dir), + "--name", + _library_name, + "--sources", + ] + rebase_path(sources, root_build_dir) + + if (defined(invoker.deps) || defined(invoker.public_deps)) { + merged_deps = [] + + if (defined(invoker.deps)) { + merged_deps += invoker.deps + } + + if (defined(invoker.public_deps)) { + merged_deps += invoker.public_deps + } + + dep_libraries = [] + deps = [] + + foreach(dep, merged_deps) { + gen_dir = get_label_info(dep, "target_gen_dir") + name = get_label_info(dep, "name") + dep_libraries += [ "$gen_dir/$name.fidl_libraries" ] + deps += [ "${dep}_response_file" ] + } + + inputs = dep_libraries + + args += [ "--dep-libraries" ] + rebase_path(dep_libraries, root_build_dir) + } + } + + action("${target_name}_compile") { + forward_variables_from(invoker, [ "testonly" ]) + + visibility = [ ":*" ] + + deps = [ + ":${invoker.target_name}_response_file", + ] + + script = "//build/gn_run_binary.py" + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + _response_file, + ] + + outputs = [ + _json_representation, + _tables_file, + ] + + rebased_response_file = rebase_path(_response_file, root_build_dir) + args = [ + rebase_path("//third_party/fuchsia-sdk/sdk/tools/fidlc", root_build_dir), + "@$rebased_response_file", + ] + } + + if (_define_cpp_action) { + action("${target_name}_cpp_gen") { + visibility = [ ":${invoker.target_name}" ] + forward_variables_from(invoker, [ "testonly" ]) + + deps = [ + ":${invoker.target_name}_compile", + ] + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + _json_representation, + ] + + outputs = [ + "${_output_base}.h", + "${_output_base}.cc", + ] + + script = "//build/gn_run_binary.py" + args = [ + rebase_path("//third_party/fuchsia-sdk/sdk/tools/fidlgen", + root_build_dir), + "-generators", + "cpp", + "-json", + rebase_path(_json_representation, root_build_dir), + "-include-base", + rebase_path(_output_gen_dir, root_build_dir), + "-output-base", + rebase_path("${_output_base}", root_build_dir), + ] + } + } + + if (_define_js_action) { + _output_js_path = "$_output_gen_dir/${_library_path}/js/fidl.js" + action("${target_name}_js_gen") { + visibility = [ ":${invoker.target_name}" ] + forward_variables_from(invoker, [ "testonly" ]) + + deps = [ + ":${invoker.target_name}_compile", + ] + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + _json_representation, + "//build/fuchsia/fidlgen_js/fidl.py", # The schema helper file. + ] + + outputs = [ + _output_js_path, + ] + + script = "//build/fuchsia/fidlgen_js/gen.py" + + args = [ + rebase_path(_json_representation, root_build_dir), + "--output", + rebase_path("${_output_js_path}", root_build_dir), + ] + + data = [] + foreach(o, outputs) { + data += [ o ] + } + } + } + + config("${target_name}_config") { + visibility = [ ":${invoker.target_name}" ] + include_dirs = [ _output_gen_dir ] + } + + source_set("${target_name}") { + forward_variables_from(invoker, + [ + "deps", + "public_deps", + "testonly", + "visibility", + ]) + + sources = [ + "${_output_base}.cc", + "${_output_base}.h", + _tables_file, + ] + + if (!defined(deps)) { + deps = [] + } + deps += [ ":${invoker.target_name}_compile" ] + + foreach(language, languages) { + deps += [ ":${invoker.target_name}_${language}_gen" ] + } + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ "//third_party/fuchsia-sdk/sdk:fidl" ] + public_deps += [ "//third_party/fuchsia-sdk/sdk:fidl_cpp" ] + + public_configs = [ ":${invoker.target_name}_config" ] + } +} diff --git a/deps/v8/build/config/fuchsia/package.gni b/deps/v8/build/config/fuchsia/package.gni new file mode 100644 index 0000000000..55b43c05a5 --- /dev/null +++ b/deps/v8/build/config/fuchsia/package.gni @@ -0,0 +1,239 @@ +# 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/fuchsia/config.gni") +import("//build/config/sysroot.gni") + +# Creates a Fuchsia .far package file. +# +# 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. +# sandbox_policy: A path to the sandbox_policy that will be used. +# "testonly" targets default to using +# //build/config/fuchsia/testing_sandbox_policy by default. +# Non-test targets must explicitly specify a |sandbox_policy|. +# deps: Additional targets to build and include in the package (optional). +template("fuchsia_package") { + pkg = { + forward_variables_from(invoker, "*") + + if (defined(package_name_override)) { + package_name = package_name_override + } else { + package_name = invoker.target_name + } + + if (!defined(sandbox_policy)) { + assert(testonly == true) + sandbox_policy = "//build/config/fuchsia/testing_sandbox_policy" + } + } + assert(defined(pkg.binary)) + + _pm_tool_path = "${fuchsia_sdk}/tools/pm" + + _pkg_out_dir = "${target_gen_dir}/${pkg.package_name}" + _runtime_deps_file = "$_pkg_out_dir/${pkg.package_name}.runtime_deps" + _archive_manifest = "$_pkg_out_dir/${pkg.package_name}.archive_manifest" + _build_ids_file = "$_pkg_out_dir/ids.txt" + _component_manifest = "$_pkg_out_dir/${pkg.package_name}.cmx" + _key_file = "$_pkg_out_dir/signing-key" + _meta_far_file = "$_pkg_out_dir/meta.far" + _combined_far_file = "$_pkg_out_dir/${pkg.package_name}-0.far" + _final_far_file = "$_pkg_out_dir/${pkg.package_name}.far" + _package_info_path = "$_pkg_out_dir/package" + + _write_manifest_target = "${pkg.package_name}__write_manifest" + _generate_key_target = "${pkg.package_name}__genkey" + _package_target = "${pkg.package_name}__pkg" + _bundle_target = "${pkg.package_name}__bundle" + + # Generates a manifest file based on the GN runtime deps + # suitable for "pm" tool consumption. + action(_write_manifest_target) { + _depfile = "${target_gen_dir}/${target_name}_stamp.d" + + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + + script = "//build/config/fuchsia/prepare_package_inputs.py" + + inputs = [ + _runtime_deps_file, + pkg.sandbox_policy, + ] + + outputs = [ + _archive_manifest, + _build_ids_file, + _component_manifest, + ] + + if (!defined(deps)) { + deps = [] + } + deps += [ pkg.binary ] + data_deps = deps + + # Use a depfile to trigger package rebuilds if any of the files (static + # assets, shared libraries, etc.) included by the package have changed. + depfile = _depfile + + args = [ + "--root-dir", + rebase_path("//", root_build_dir), + "--out-dir", + rebase_path(root_out_dir, root_build_dir), + "--app-name", + pkg.package_name, + "--app-filename", + get_label_info(pkg.binary, "name"), + "--sandbox-policy-path", + rebase_path(pkg.sandbox_policy, root_build_dir), + "--runtime-deps-file", + rebase_path(_runtime_deps_file, root_build_dir), + "--depfile-path", + rebase_path(_depfile, root_build_dir), + "--manifest-path", + rebase_path(_archive_manifest, root_build_dir), + "--build-ids-file", + rebase_path(_build_ids_file, root_build_dir), + ] + + if (defined(pkg.excluded_files)) { + foreach(filename, pkg.excluded_files) { + args += [ + "--exclude-file", + filename, + ] + } + } + + write_runtime_deps = _runtime_deps_file + } + + # Generates a signing key to use for building the package. + action(_generate_key_target) { + forward_variables_from(invoker, [ "testonly" ]) + + script = "//build/gn_run_binary.py" + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + ] + + outputs = [ + _key_file, + ] + + args = [ + rebase_path(_pm_tool_path, root_build_dir), + "-k", + rebase_path(_key_file, root_build_dir), + "genkey", + ] + } + + # Creates a signed Fuchsia metadata package. + action(_package_target) { + forward_variables_from(invoker, [ "testonly" ]) + + script = "//build/gn_run_binary.py" + + deps = [ + ":$_generate_key_target", + ":$_write_manifest_target", + ] + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + _key_file, + ] + + outputs = [ + _meta_far_file, + ] + + args = [ + rebase_path(_pm_tool_path, root_build_dir), + "-o", + rebase_path(_pkg_out_dir, root_build_dir), + "-k", + rebase_path(_key_file, root_build_dir), + "-m", + rebase_path(_archive_manifest, root_build_dir), + "build", + ] + } + + # Creates a package containing the metadata archive and blob data. + action(_bundle_target) { + forward_variables_from(invoker, [ "testonly" ]) + + script = "//build/gn_run_binary.py" + + deps = [ + ":$_package_target", + ":$_write_manifest_target", + ] + + inputs = [ + # Depend on the SDK hash, to ensure rebuild if the SDK tools change. + "${fuchsia_sdk}/.hash", + _meta_far_file, + _archive_manifest, + ] + + outputs = [ + _combined_far_file, + ] + + args = [ + rebase_path(_pm_tool_path, root_build_dir), + "-o", + rebase_path(_pkg_out_dir, root_build_dir), + "-m", + rebase_path(_archive_manifest, root_build_dir), + "archive", + ] + } + + # Copies the archive to a well-known path. + # TODO(kmarshall): Use a 'pm' output flag to write directly to the desired + # file path instead. + copy(target_name) { + forward_variables_from(invoker, [ "testonly" ]) + + # Allows dependent targets to make use of "ids.txt". + public_deps = [ + ":$_write_manifest_target", + ] + + deps = [ + ":$_bundle_target", + ] + + data = [ + _final_far_file, + + # Files specified here so that they can be read by isolated testbots. + _package_info_path, + _build_ids_file, + ] + + sources = [ + _combined_far_file, + ] + outputs = [ + _final_far_file, + ] + } +} diff --git a/deps/v8/build/config/fuchsia/prepare_package_inputs.py b/deps/v8/build/config/fuchsia/prepare_package_inputs.py new file mode 100644 index 0000000000..078c3cb266 --- /dev/null +++ b/deps/v8/build/config/fuchsia/prepare_package_inputs.py @@ -0,0 +1,220 @@ +# 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 archive manifest used for Fuchsia package generation.""" + +import argparse +import json +import os +import re +import subprocess +import sys +import tempfile + + +def MakePackagePath(file_path, roots): + """Computes a path for |file_path| that is relative to one of the directory + paths in |roots|. + + file_path: The file path to relativize. + roots: A list of directory paths which may serve as a relative root + for |file_path|. + + Examples: + + >>> MakePackagePath('/foo/bar.txt', ['/foo/']) + 'bar.txt' + + >>> MakePackagePath('/foo/dir/bar.txt', ['/foo/']) + 'dir/bar.txt' + + >>> MakePackagePath('/foo/out/Debug/bar.exe', ['/foo/', '/foo/out/Debug/']) + 'bar.exe' + """ + + # Prevents greedily matching against a shallow path when a deeper, better + # matching path exists. + roots.sort(key=len, reverse=True) + + for next_root in roots: + if not next_root.endswith(os.sep): + next_root += os.sep + + if file_path.startswith(next_root): + relative_path = file_path[len(next_root):] + + return relative_path + + return file_path + + +def _GetStrippedPath(bin_path): + """Finds the stripped version of the binary |bin_path| in the build + output directory.""" + + return bin_path.replace('lib.unstripped/', 'lib/').replace( + 'exe.unstripped/', '') + + +def _IsBinary(path): + """Checks if the file at |path| is an ELF executable by inspecting its FourCC + header.""" + + with open(path, 'rb') as f: + file_tag = f.read(4) + return file_tag == '\x7fELF' + + +def _WriteBuildIdsTxt(binary_paths, ids_txt_path): + """Writes an index text file that maps build IDs to the paths of unstripped + binaries.""" + + READELF_FILE_PREFIX = 'File: ' + READELF_BUILD_ID_PREFIX = 'Build ID: ' + + # List of binaries whose build IDs are awaiting processing by readelf. + # Entries are removed as readelf's output is parsed. + unprocessed_binary_paths = {os.path.basename(p): p for p in binary_paths} + + with open(ids_txt_path, 'w') as ids_file: + readelf_stdout = subprocess.check_output( + ['readelf', '-n'] + map(_GetStrippedPath, binary_paths)) + + if len(binary_paths) == 1: + # Readelf won't report a binary's path if only one was provided to the + # tool. + binary_shortname = os.path.basename(binary_paths[0]) + else: + binary_shortname = None + + for line in readelf_stdout.split('\n'): + line = line.strip() + + if line.startswith(READELF_FILE_PREFIX): + binary_shortname = os.path.basename(line[len(READELF_FILE_PREFIX):]) + assert binary_shortname in unprocessed_binary_paths + + elif line.startswith(READELF_BUILD_ID_PREFIX): + # Paths to the unstripped executables listed in "ids.txt" are specified + # as relative paths to that file. + unstripped_rel_path = os.path.relpath( + os.path.abspath(unprocessed_binary_paths[binary_shortname]), + os.path.dirname(os.path.abspath(ids_txt_path))) + + build_id = line[len(READELF_BUILD_ID_PREFIX):] + ids_file.write(build_id + ' ' + unstripped_rel_path + '\n') + del unprocessed_binary_paths[binary_shortname] + + # Did readelf forget anything? Make sure that all binaries are accounted for. + assert not unprocessed_binary_paths + + +def BuildManifest(args): + binaries = [] + with open(args.manifest_path, 'w') as manifest, \ + open(args.depfile_path, 'w') as depfile: + # Process the runtime deps file for file paths, recursively walking + # directories as needed. + # MakePackagePath() may relativize to either the source root or output + # directory. + # runtime_deps may contain duplicate paths, so use a set for + # de-duplication. + expanded_files = set() + for next_path in open(args.runtime_deps_file, 'r'): + next_path = next_path.strip() + if os.path.isdir(next_path): + for root, _, files in os.walk(next_path): + for current_file in files: + if current_file.startswith('.'): + continue + expanded_files.add( + os.path.join(root, current_file)) + else: + expanded_files.add(next_path) + + # Format and write out the manifest contents. + gen_dir = os.path.normpath(os.path.join(args.out_dir, "gen")) + app_found = False + excluded_files_set = set(args.exclude_file) + for current_file in expanded_files: + if _IsBinary(current_file): + binaries.append(current_file) + current_file = _GetStrippedPath(current_file) + + in_package_path = MakePackagePath(current_file, + [gen_dir, args.root_dir, args.out_dir]) + if in_package_path == args.app_filename: + app_found = True + + if in_package_path in excluded_files_set: + excluded_files_set.remove(in_package_path) + continue + + manifest.write('%s=%s\n' % (in_package_path, current_file)) + + if len(excluded_files_set) > 0: + raise Exception('Some files were excluded with --exclude-file, but ' + 'not found in the deps list: %s' % + ', '.join(excluded_files_set)); + + if not app_found: + raise Exception('Could not locate executable inside runtime_deps.') + + # Write meta/package manifest file. + with open(os.path.join(os.path.dirname(args.manifest_path), 'package'), + 'w') as package_json: + json.dump({'version': '0', 'name': args.app_name}, package_json) + manifest.write('meta/package=%s\n' % + os.path.relpath(package_json.name, args.out_dir)) + + # Write component manifest file. + cmx_file_path = os.path.join(os.path.dirname(args.manifest_path), + args.app_name + '.cmx') + with open(cmx_file_path, 'w') as component_manifest_file: + component_manifest = { + 'program': { 'binary': args.app_filename }, + 'sandbox': json.load(open(args.sandbox_policy_path, 'r')), + } + json.dump(component_manifest, component_manifest_file) + + manifest.write('meta/%s=%s\n' % + (os.path.basename(component_manifest_file.name), + os.path.relpath(cmx_file_path, args.out_dir))) + + depfile.write( + "%s: %s" % (os.path.relpath(args.manifest_path, args.out_dir), + " ".join([os.path.relpath(f, args.out_dir) + for f in expanded_files]))) + + _WriteBuildIdsTxt(binaries, args.build_ids_file) + + return 0 + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--root-dir', required=True, help='Build root directory') + parser.add_argument('--out-dir', required=True, help='Build output directory') + parser.add_argument('--app-name', required=True, help='Package name') + parser.add_argument('--app-filename', required=True, + help='Path to the main application binary relative to the output dir.') + parser.add_argument('--sandbox-policy-path', required=True, + help='Path to the sandbox policy file relative to the output dir.') + parser.add_argument('--runtime-deps-file', required=True, + help='File with the list of runtime dependencies.') + parser.add_argument('--depfile-path', required=True, + help='Path to write GN deps file.') + parser.add_argument('--exclude-file', action='append', default=[], + help='Package-relative file path to exclude from the package.') + parser.add_argument('--manifest-path', required=True, + help='Manifest output path.') + parser.add_argument('--build-ids-file', required=True, + help='Debug symbol index path.') + + args = parser.parse_args() + + return BuildManifest(args) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/deps/v8/build/config/fuchsia/rules.gni b/deps/v8/build/config/fuchsia/rules.gni new file mode 100644 index 0000000000..11cb4f10ad --- /dev/null +++ b/deps/v8/build/config/fuchsia/rules.gni @@ -0,0 +1,157 @@ +# 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/sysroot.gni") +import("//build/util/generate_wrapper.gni") + +blobstore_qcow_path = "$root_out_dir/fvm.blk.qcow2" + +# Generates a script which deploys and 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 "exe_runner.py". +# install_only: If true, executing the script will only install the package +# on the device, but not run it. +template("fuchsia_package_runner") { + forward_variables_from(invoker, [ "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 + _manifest_path = "$_pkg_dir/${_pkg_shortname}.archive_manifest" + _package_path = "$_pkg_dir/${_pkg_shortname}.far" + + if (!defined(runner_script)) { + runner_script = "//build/fuchsia/exe_runner.py" + } + + 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" + _generate_template = "${target_name}__generate_template" + + # Generates a script to install and optionally run a package. + # + # Parameters: + # |install_only|: If true, builds a script that only installs a package. + # |script_path|: The path of the script to generate. + template(_generate_template) { + generate_wrapper(target_name) { + forward_variables_from(invoker, + [ + "install_only", + "script_path", + "target", + "testonly", + ]) + + executable = runner_script + wrapper_script = script_path + + deps = [ + "//build/config/fuchsia:blobstore_extended_qcow2", + invoker.package, + ] + + if (defined(invoker.deps)) { + deps += invoker.deps + } + + data = [ + _manifest_path, + "//build/fuchsia/", + "//build/util/lib/", + "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer", + "${qemu_root}/", + "${fuchsia_sdk}/", + ] + + data_deps = [ + invoker.package, + ] + + executable_args = [] + + if (defined(invoker.package_deps)) { + foreach(cur_package, invoker.package_deps) { + deps += [ cur_package[0] ] + dep_package_path = + get_label_info(cur_package[0], "target_gen_dir") + "/" + + cur_package[1] + "/" + cur_package[1] + ".far" + _rebased_dep_package_path = + rebase_path(dep_package_path, root_build_dir) + executable_args += [ + "--package-dep", + "@WrappedPath(${_rebased_dep_package_path})", + ] + } + } + + _rebased_package_path = rebase_path(_package_path, root_build_dir) + executable_args += [ + "--output-directory", + "@WrappedPath(.)", + "--target-cpu", + target_cpu, + "--package", + "@WrappedPath(${_rebased_package_path})", + "--package-name", + _pkg_shortname, + ] + + if (defined(invoker.use_test_server) && invoker.use_test_server) { + executable_args += [ "--enable-test-server" ] + } + + if (defined(install_only) && install_only) { + executable_args += [ "--install-only" ] + } + } + } + + target(_generate_template, _generate_runner_target) { + forward_variables_from(invoker, "*") + script_path = generated_run_pkg_script_path + } + + target(_generate_template, _generate_installer_target) { + forward_variables_from(invoker, "*") + script_path = generated_install_pkg_script_path + install_only = true + } + + # Build the installer script, and the runner for non-|install_only| targets. + group(target_name) { + forward_variables_from(invoker, [ "testonly" ]) + deps = [ + ":${_generate_installer_target}", + ] + + # Generate a runner script if the target is not install-only. + if (!defined(invoker.install_only)) { + deps += [ ":${_generate_runner_target}" ] + } + } +} diff --git a/deps/v8/build/config/fuchsia/symbol_archive.gni b/deps/v8/build/config/fuchsia/symbol_archive.gni new file mode 100644 index 0000000000..1415132790 --- /dev/null +++ b/deps/v8/build/config/fuchsia/symbol_archive.gni @@ -0,0 +1,46 @@ +# 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 binaries' debug data, structured according +# to the ".build_ids" convention used by the symbolizer and GNU GDB. +# +# Parameters: +# 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. +# include_prebuilt_symbols: Include symbols from SDK prebuilt libraries. +template("symbol_archive") { + assert(!is_debug) + + action(target_name) { + _ids_txt = invoker.ids_txt + _build_ids = invoker.archive_name + _eu_strip_path = "//buildtools/third_party/eu-strip/bin/eu-strip" + + script = "//build/config/fuchsia/build_symbol_archive.py" + + inputs = [ + _ids_txt, + ] + + outputs = [ + _build_ids, + ] + + deps = invoker.deps + + args = [ + rebase_path(_ids_txt), + "-o", + rebase_path(_build_ids), + "--eu-strip", + rebase_path(_eu_strip_path), + "--fuchsia-build-id-dir", + rebase_path("//third_party/fuchsia-sdk/sdk/.build-id"), + ] + } +} diff --git a/deps/v8/build/config/fuchsia/testing_sandbox_policy b/deps/v8/build/config/fuchsia/testing_sandbox_policy new file mode 100644 index 0000000000..322af44058 --- /dev/null +++ b/deps/v8/build/config/fuchsia/testing_sandbox_policy @@ -0,0 +1,25 @@ +{ + "features": [ + "isolated-persistent-storage", + "root-ssl-certificates", + "system-temp", + "vulkan" ], + "dev": ["null", "zero"], + "services": [ + "fuchsia.fonts.Provider", + "fuchsia.media.Audio", + "fuchsia.mediacodec.CodecFactory", + "fuchsia.net.SocketProvider", + "fuchsia.netstack.Netstack", + "fuchsia.process.Launcher", + "fuchsia.sys.Environment", + "fuchsia.sys.Launcher", + "fuchsia.sys.Loader", + "fuchsia.ui.input.ImeService", + "fuchsia.ui.input.ImeVisibilityService", + "fuchsia.ui.policy.Presenter", + "fuchsia.ui.scenic.Scenic", + "fuchsia.vulkan.loader.Loader", + "fuchsia.web.ContextProvider" + ] +} diff --git a/deps/v8/build/config/gcc/BUILD.gn b/deps/v8/build/config/gcc/BUILD.gn new file mode 100644 index 0000000000..747245f376 --- /dev/null +++ b/deps/v8/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_component_build) { +# configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] +# } +config("rpath_for_built_shared_libraries") { + if (!is_android) { + # Note: Android doesn'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/deps/v8/build/config/get_host_byteorder.py b/deps/v8/build/config/get_host_byteorder.py new file mode 100755 index 0000000000..c8fcf1f352 --- /dev/null +++ b/deps/v8/build/config/get_host_byteorder.py @@ -0,0 +1,11 @@ +#!/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""" + + +import sys + +print sys.byteorder diff --git a/deps/v8/build/config/host_byteorder.gni b/deps/v8/build/config/host_byteorder.gni new file mode 100644 index 0000000000..48a1a7f1e3 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/BUILD.gn b/deps/v8/build/config/ios/BUILD.gn new file mode 100644 index 0000000000..8a50ccf906 --- /dev/null +++ b/deps/v8/build/config/ios/BUILD.gn @@ -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/coverage/coverage.gni") +import("//build/config/ios/ios_sdk.gni") +import("//build/config/sysroot.gni") +import("//build/toolchain/toolchain.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. + # NOTE: This option is ignored when building versions for the iOS simulator, + # where a part of libvpx is compiled from the assembly code written using + # Intel assembly syntax; Yasm / Nasm do not support emitting bitcode parts. + # That is not a limitation for now as Xcode mandates the presence of bitcode + # only when building bitcode-enabled projects for real devices (ARM CPUs). + 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_ios_flags = [] + + # CPU architecture. + if (current_cpu == "x64") { + common_ios_flags += [ + "-arch", + "x86_64", + ] + } else if (current_cpu == "x86") { + common_ios_flags += [ + "-arch", + "i386", + ] + } else if (current_cpu == "armv7" || current_cpu == "arm") { + common_ios_flags += [ + "-arch", + "armv7", + ] + } else if (current_cpu == "arm64") { + common_ios_flags += [ + "-arch", + "arm64", + ] + } + + # 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_ios_flags + cflags = common_ios_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" ] + + # TODO(crbug.com/910200): Disable experimental isel until + # https://llvm.org/PR40887 is fixed. + if (is_debug) { + cflags += [ "-fno-experimental-isel" ] + } + + ldflags = common_ios_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") { + common_flags = [ + "-isysroot", + sysroot, + + "-stdlib=libc++", + ] + + if (use_ios_simulator) { + common_flags += [ "-mios-simulator-version-min=$ios_deployment_target" ] + } else { + common_flags += [ "-miphoneos-version-min=$ios_deployment_target" ] + } + + if (use_xcode_clang && enable_ios_bitcode && !use_ios_simulator) { + if (is_debug) { + common_flags += [ "-fembed-bitcode-marker" ] + } else { + common_flags += [ "-fembed-bitcode" ] + } + } + + asmflags = common_flags + cflags = common_flags + ldflags = common_flags + + if (use_clang_coverage) { + configs = [ "//build/config/coverage:default_coverage" ] + } +} + +config("ios_executable_flags") { +} + +config("ios_dynamic_flags") { + ldflags = [ "-Wl,-ObjC" ] # Always load Objective-C categories and class. +} + +config("xctest_config") { + common_flags = [ + "-F", + "$ios_sdk_platform_path/Developer/Library/Frameworks", + ] + + cflags = common_flags + ldflags = common_flags + + libs = [ + "Foundation.framework", + "XCTest.framework", + ] +} + +group("xctest") { + public_configs = [ ":xctest_config" ] +} diff --git a/deps/v8/build/config/ios/BuildInfo.plist b/deps/v8/build/config/ios/BuildInfo.plist new file mode 100644 index 0000000000..3595e5aefb --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/Host-Info.plist b/deps/v8/build/config/ios/Host-Info.plist new file mode 100644 index 0000000000..9f6f5deef9 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/Module-Info.plist b/deps/v8/build/config/ios/Module-Info.plist new file mode 100644 index 0000000000..13b67c473f --- /dev/null +++ b/deps/v8/build/config/ios/Module-Info.plist @@ -0,0 +1,24 @@ +<?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> +</dict> +</plist> diff --git a/deps/v8/build/config/ios/OWNERS b/deps/v8/build/config/ios/OWNERS new file mode 100644 index 0000000000..0e726c6a2c --- /dev/null +++ b/deps/v8/build/config/ios/OWNERS @@ -0,0 +1 @@ +file://build/config/mac/OWNERS diff --git a/deps/v8/build/config/ios/asset_catalog.gni b/deps/v8/build/config/ios/asset_catalog.gni new file mode 100644 index 0000000000..460cd96262 --- /dev/null +++ b/deps/v8/build/config/ios/asset_catalog.gni @@ -0,0 +1,148 @@ +# 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 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 (current_toolchain != default_toolchain) { + group(target_name) { + public_deps = [ + ":$target_name($default_toolchain)", + ] + } + } 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_out_dir), + rebase_path(_output_dir, root_out_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("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/deps/v8/build/config/ios/codesign.py b/deps/v8/build/config/ios/codesign.py new file mode 100644 index 0000000000..64bd1293a7 --- /dev/null +++ b/deps/v8/build/config/ios/codesign.py @@ -0,0 +1,534 @@ +# 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 datetime +import fnmatch +import glob +import os +import plistlib +import shutil +import subprocess +import sys +import tempfile + + +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 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. + """ + return plistlib.readPlistFromString(subprocess.check_output([ + 'xcrun', 'plutil', '-convert', 'xml1', '-o', '-', plist_path])) + + +class Bundle(object): + """Wraps a bundle.""" + + def __init__(self, bundle_path): + """Initializes the Bundle object with data from bundle Info.plist file.""" + self._path = bundle_path + self._data = LoadPlistFile(os.path.join(self._path, 'Info.plist')) + + @property + def path(self): + return self._path + + @property + def identifier(self): + return self._data['CFBundleIdentifier'] + + @property + def binary_path(self): + return os.path.join(self._path, self._data['CFBundleExecutable']) + + 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.iteritems(): + 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 = plistlib.readPlistFromString(subprocess.check_output([ + 'xcrun', 'security', 'cms', '-D', '-u', 'certUsageAnyCA', + '-i', provisioning_profile_path])) + + @property + def path(self): + return self._path + + @property + def application_identifier_pattern(self): + return self._data.get('Entitlements', {}).get('application-identifier', '') + + @property + def team_identifier(self): + return self._data.get('TeamIdentifier', [''])[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.team_identifier, 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, str): + for key, substitution in substitutions.iteritems(): + data = data.replace('$(%s)' % (key,), substitution) + return data + + if isinstance(data, dict): + for key, value in data.iteritems(): + 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.iteritems(): + if key not in self._data: + self._data[key] = value + + def WriteTo(self, target_path): + plistlib.writePlist(self._data, target_path) + + +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) + _, 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.team_identifier + '.' + else: + app_identifier_prefix = '*.' + entitlements.ExpandVariables({ + 'CFBundleIdentifier': bundle_identifier, + 'AppIdentifierPrefix': app_identifier_prefix, + }) + return entitlements + + +def GenerateBundleInfoPlist(bundle_path, plist_compiler, partial_plist): + """Generates the bundle Info.plist for a list of partial .plist files. + + Args: + bundle_path: path to the bundle + 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 include need to 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', os.path.join(bundle_path, 'Info.plist'), + ] + 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 = '-' + + if args.partial_info_plist: + GenerateBundleInfoPlist( + args.path, + args.plist_compiler_path, + args.partial_info_plist) + + bundle = Bundle(args.path) + + # 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. + signature_file = os.path.join(args.path, '_CodeSignature', 'CodeResources') + if os.path.isfile(signature_file): + shutil.rmtree(os.path.dirname(signature_file)) + + # Install system frameworks if requested. + for framework_path in args.frameworks: + InstallSystemFramework(framework_path, args.path, args) + + # Copy main binary into bundle. + if os.path.isfile(bundle.binary_path): + os.unlink(bundle.binary_path) + shutil.copy(args.binary, bundle.binary_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) + + +def Main(): + parser = argparse.ArgumentParser('codesign iOS bundles') + parser.add_argument('--developer_dir', required=False, + help='Path to Xcode.') + subparsers = parser.add_subparsers() + + actions = [ + CodeSignBundleAction, + CodeSignFileAction, + GenerateEntitlementsAction, + ] + + for action in actions: + action.Register(subparsers) + + args = parser.parse_args() + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + args.func(args) + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/deps/v8/build/config/ios/dummy.py b/deps/v8/build/config/ios/dummy.py new file mode 100644 index 0000000000..b23b7dab96 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/entitlements.plist b/deps/v8/build/config/ios/entitlements.plist new file mode 100644 index 0000000000..429762e3a3 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/find_signing_identity.py b/deps/v8/build/config/ios/find_signing_identity.py new file mode 100644 index 0000000000..7add474b9c --- /dev/null +++ b/deps/v8/build/config/ios/find_signing_identity.py @@ -0,0 +1,47 @@ +# 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. + +import argparse +import os +import subprocess +import sys +import re + +def ListIdentities(): + return subprocess.check_output([ + 'xcrun', + 'security', + 'find-identity', + '-v', + '-p', + 'codesigning', + ]) + + +def FindValidIdentity(identity_description): + lines = list(map(str.strip, ListIdentities().splitlines())) + # Look for something like "2) XYZ "iPhone Developer: Name (ABC)"" + exp = re.compile('[0-9]+\) ([A-F0-9]+) "([^"]*)"') + for line in lines: + res = exp.match(line) + if res is None: + continue + if identity_description in res.group(2): + yield res.group(1) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser('codesign iOS bundles') + parser.add_argument( + '--developer_dir', required=False, + help='Path to Xcode.') + parser.add_argument( + '--identity-description', required=True, + help='Text description used to select the code signing identity.') + args = parser.parse_args() + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + + for identity in FindValidIdentity(args.identity_description): + print identity diff --git a/deps/v8/build/config/ios/generate_umbrella_header.py b/deps/v8/build/config/ios/generate_umbrella_header.py new file mode 100644 index 0000000000..8547e18aa7 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/ios/hardlink.py b/deps/v8/build/config/ios/hardlink.py new file mode 100644 index 0000000000..91dbf62f98 --- /dev/null +++ b/deps/v8/build/config/ios/hardlink.py @@ -0,0 +1,69 @@ +# 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.exists(output): + shutil.rmtree(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/deps/v8/build/config/ios/ios_sdk.gni b/deps/v8/build/config/ios/ios_sdk.gni new file mode 100644 index 0000000000..f45629ae99 --- /dev/null +++ b/deps/v8/build/config/ios/ios_sdk.gni @@ -0,0 +1,167 @@ +# 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/ios_sdk_overrides.gni") +import("//build/toolchain/toolchain.gni") + +declare_args() { + # SDK path to use. When empty this will use the default SDK based on the + # value of use_ios_simulator. + ios_sdk_path = "" + ios_sdk_name = "" + ios_sdk_version = "" + ios_sdk_platform = "" + ios_sdk_platform_path = "" + xcode_version = "" + xcode_version_int = 0 + xcode_build = "" + machine_os_build = "" + + # The iOS Code signing identity to use + # TODO(GYP), TODO(sdfresne): Consider having a separate + # ios_enable_code_signing_flag=<bool> flag to make the invocation clearer. + ios_enable_code_signing = true + ios_code_signing_identity = "" + ios_code_signing_identity_description = "iPhone Developer" + + # 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 true, then allow using Xcode to automatically manage certificates. This + # requires loading a separate Xcode project and enable automatically managed + # certificates. When true, all test application will use the same bundle id + # to avoid running out of certificates if using a free account. + ios_automatically_manage_certs = false + + # 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 = [] +} + +assert(custom_toolchain == "" || additional_target_cpus == [], + "cannot define both custom_toolchain and additional_target_cpus") + +use_ios_simulator = current_cpu == "x86" || current_cpu == "x64" + +ios_generic_test_bundle_id_suffix = "generic-unit-test" + +# 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 != []) { + foreach(_additional_target_cpu, additional_target_cpus) { + assert(_additional_target_cpu != target_cpu, + "target_cpu must not be listed in additional_target_cpus") + + _toolchain = "//build/toolchain/mac:ios_clang_$_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 (use_ios_simulator) { + ios_sdk_name = "iphonesimulator" + ios_sdk_platform = "iPhoneSimulator" + } else { + ios_sdk_name = "iphoneos" + ios_sdk_platform = "iPhoneOS" + } + + ios_sdk_info_args = [] + if (!use_system_xcode) { + ios_sdk_info_args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + ios_sdk_info_args += [ ios_sdk_name ] + script_name = "//build/config/mac/sdk_info.py" + _ios_sdk_result = exec_script(script_name, ios_sdk_info_args, "scope") + ios_sdk_path = _ios_sdk_result.sdk_path + ios_sdk_version = _ios_sdk_result.sdk_version + ios_sdk_platform_path = _ios_sdk_result.sdk_platform_path + ios_sdk_build = _ios_sdk_result.sdk_build + 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 (use_ios_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 (ios_enable_code_signing && !use_ios_simulator) { + find_signing_identity_args = [ + "--identity-description", + ios_code_signing_identity_description, + ] + if (!use_system_xcode) { + find_signing_identity_args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + + # If an identity is not provided, look for one on the host + if (ios_code_signing_identity == "") { + _ios_identities = exec_script("find_signing_identity.py", + find_signing_identity_args, + "list lines") + if (_ios_identities == []) { + print("Automatic code signing identity selection was enabled but could") + print("not find exactly one code signing identity matching") + print("$ios_code_signing_identity_description. Check that your keychain") + print("is accessible and that there is a valid code signing identity") + print("listed by `xcrun security find-identity -v -p codesigning`") + print("TIP: Simulator builds don't require code signing...") + assert(false) + } else { + _ios_identities_len = 0 + foreach(_, _ios_identities) { + _ios_identities_len += 1 + } + + ios_code_signing_identity = _ios_identities[0] + if (_ios_identities_len != 1) { + print("Warning: Multiple codesigning identities match " + + "\"$ios_code_signing_identity_description\"") + foreach(_ios_identity, _ios_identities) { + _selected = "" + if (ios_code_signing_identity == _ios_identity) { + _selected = " (selected)" + } + print("Warning: - $_ios_identity$_selected") + } + print("Warning: Please use either ios_code_signing_identity or ") + print("Warning: ios_code_signing_identity_description variable to ") + print("Warning: control which identity is selected.") + print() + } + } + } +} diff --git a/deps/v8/build/config/ios/ios_sdk_overrides.gni b/deps/v8/build/config/ios/ios_sdk_overrides.gni new file mode 100644 index 0000000000..5699ebe06c --- /dev/null +++ b/deps/v8/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 = "11.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 == "11.0" || true) +} diff --git a/deps/v8/build/config/ios/rules.gni b/deps/v8/build/config/ios/rules.gni new file mode 100644 index 0000000000..4b5ffa02b3 --- /dev/null +++ b/deps/v8/build/config/ios/rules.gni @@ -0,0 +1,2047 @@ +# 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/ios_sdk.gni") +import("//build/config/mac/base_rules.gni") +import("//build/config/mac/symbols.gni") +import("//build/toolchain/toolchain.gni") + +# Constants corresponding to the bundle type identifier for XCTest and XCUITest +# targets. +_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") + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _all_target_cpu = [ current_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/mac/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 = [] + if (!use_system_xcode) { + args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + 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 (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. +# +# 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. +# +# 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 + } + + _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 + } + + 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" + bundle_contents_dir = bundle_root_dir + bundle_resources_dir = bundle_contents_dir + bundle_executable_dir = bundle_contents_dir + + if (!defined(public_deps)) { + public_deps = [] + } + + xcode_extra_attributes = { + IPHONEOS_DEPLOYMENT_TARGET = ios_deployment_target + + # 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_contents_dir/$_output_name" ] + if (_enable_code_signing) { + code_signing_outputs += + [ "$bundle_contents_dir/_CodeSignature/CodeResources" ] + } + if (ios_code_signing_identity != "" && !use_ios_simulator && + _enable_embedded_mobileprovision) { + code_signing_outputs += + [ "$bundle_contents_dir/embedded.mobileprovision" ] + } + + 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 = [] + if (!use_system_xcode) { + code_signing_args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + 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. + foreach(_framework, invoker.extra_system_frameworks) { + code_signing_args += [ "-F=" + _framework ] + } + } + if (defined(invoker.partial_info_plist)) { + _partial_info_plists = [ + invoker.primary_info_plist, + invoker.partial_info_plist, + ] + + _plist_compiler_path = "//build/config/mac/plist_util.py" + + code_signing_sources += _partial_info_plists + code_signing_sources += [ _plist_compiler_path ] + code_signing_outputs += [ "$bundle_contents_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] + } + + 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", + ] + 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. +# +# bundle_extension: +# (optional) bundle extension including the dot, default to ".app". +# +# product_type +# (optional) string, product type for the generated Xcode project, +# default to "com.apple.product-type.application". Should generally +# not be overridden. +# +# 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. +# +# 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 + } + + _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] + + if (current_toolchain != default_toolchain) { + # For use of _variants and _default_variant for secondary toolchain to + # avoid the "Assignment had no effect" error from gn. + assert(_variants != []) + assert(_default_variant.target_name != "") + } + + 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", + ]) + + visibility = [ ":$_arch_executable_target" ] + } + + if (current_toolchain == default_toolchain || use_ios_simulator) { + _generate_entitlements_target = _target_name + "_gen_entitlements" + _generate_entitlements_output = + get_label_info(":$_generate_entitlements_target($default_toolchain)", + "target_out_dir") + "/$_output_name.xcent" + } + + 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", + ]) + + visibility = [ ":$_lipo_executable_target($default_toolchain)" ] + if (current_toolchain != default_toolchain) { + visibility += [ ":$_target_name" ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_arch_executable_source" ] + + if (!defined(libs)) { + libs = [] + } + libs += [ "UIKit.framework" ] + + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Xlinker", + "-rpath", + "-Xlinker", + "@executable_path/Frameworks", + "-Xlinker", + "-objc_abi_version", + "-Xlinker", + "2", + ] + + if (use_ios_simulator) { + deps += [ ":$_generate_entitlements_target($default_toolchain)" ] + + if (!defined(inputs)) { + inputs = [] + } + inputs += [ _generate_entitlements_output ] + + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Xlinker", + "-sectcreate", + "-Xlinker", + "__TEXT", + "-Xlinker", + "__entitlements", + "-Xlinker", + rebase_path(_generate_entitlements_output, root_build_dir), + ] + } + + output_name = _output_name + output_prefix_override = true + output_dir = "$target_out_dir/$current_cpu" + } + + if (current_toolchain != default_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 (current_toolchain == default_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 = [] + if (!use_system_xcode) { + args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + 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) + } + } + + _app_product_type = "com.apple.product-type.application" + _product_type = _app_product_type + if (defined(invoker.product_type)) { + _product_type = invoker.product_type + } + + _app_bundle_extension = ".app" + _bundle_extension = _app_bundle_extension + if (defined(invoker.bundle_extension)) { + _bundle_extension = invoker.bundle_extension + } + + # Only write PkgInfo for real application, not application extension (they + # have the same product type but a different extension). + _write_pkg_info = _product_type == _app_product_type && + _bundle_extension == _app_bundle_extension + + if (_write_pkg_info) { + _create_pkg_info = target_name + "_pkg_info" + action(_create_pkg_info) { + forward_variables_from(invoker, [ "testonly" ]) + script = "//build/config/mac/write_pkg_info.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", + ]) + + 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 + + _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 (_write_pkg_info) { + bundle_deps += [ ":$_bundle_data_pkg_info" ] + } + bundle_deps += _variant.bundle_deps + + if (use_ios_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_out_dir) + + rebase_path(outputs, root_out_dir) + } + } + } +} + +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", + ]) + bundle_extension = ".appex" + product_type = "com.apple.product-type.app-extension" + + # Add linker flags required for an application extension (determined by + # inspecting the link command-line when using Xcode 9.0+). + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-e", + "_NSExtensionMain", + "-fapplication-extension", + ] + } +} + +set_defaults("ios_appex_bundle") { + configs = default_executable_configs +} + +# 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 != [] + + # 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($default_toolchain)", "root_out_dir") + _default_toolchain_target_gen_dir = + get_label_info("$_target_name($default_toolchain)", "target_gen_dir") + + if (_has_public_headers) { + _framework_headers_target = _target_name + "_framework_headers" + _framework_headers_config = _target_name + "_framework_headers_config" + config(_framework_headers_config) { + # The link settings are inherited from the framework_bundle config. + cflags = [ + "-F", + rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir), + ] + } + + _headers_map_config = _target_name + "_headers_map" + _header_map_filename = + "$_default_toolchain_target_gen_dir/$_output_name.headers.hmap" + config(_headers_map_config) { + visibility = [ ":$_target_name" ] + include_dirs = [ _header_map_filename ] + } + } + + _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" + + _framework_public_config = _target_name + "_public_config" + config(_framework_public_config) { + # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs + # and include_dirs to avoid duplicate values on the command-line. + visibility = [ ":$_target_name" ] + ldflags = [ + "-F", + rebase_path("$_default_toolchain_root_out_dir/.", root_build_dir), + ] + lib_dirs = [ root_out_dir ] + libs = [ "$_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", + "visibility", + ]) + + visibility = [ ":$_arch_shared_library_target" ] + + if (_has_public_headers) { + configs += [ + ":$_framework_headers_config", + ":$_headers_map_config", + ] + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_framework_headers_target($default_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", + "visibility", + ]) + + visibility = [ ":$_lipo_shared_library_target($default_toolchain)" ] + if (current_toolchain != default_toolchain) { + visibility += [ ":$_target_name" ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_arch_shared_library_source" ] + if (_has_public_headers) { + deps += [ ":$_framework_headers_target($default_toolchain)" ] + } + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Xlinker", + "-install_name", + "-Xlinker", + "@rpath/$_output_name.framework/$_output_name", + "-Xlinker", + "-objc_abi_version", + "-Xlinker", + "2", + ] + + output_extension = "" + output_name = _output_name + output_prefix_override = true + output_dir = "$target_out_dir/$current_cpu" + } + + if (current_toolchain != default_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($default_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" ] + } + + if (defined(invoker.bundle_deps)) { + assert(invoker.bundle_deps != [], "mark bundle_deps as used") + } + } else { + if (_has_public_headers) { + _public_headers = invoker.public_headers + _framework_root = "$root_out_dir/$_output_name.framework" + + _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". + set_sources_assignment_filter([ + "*.c", + "*.cc", + "*.cpp", + "*.m", + "*.mm", + ]) + sources = invoker.sources + set_sources_assignment_filter([]) + + args = [ + rebase_path(_header_map_filename), + rebase_path(_framework_root, 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_root/Modules/module.modulemap", + ] + args = [ rebase_path("$_framework_root", 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_root/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" ] + 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" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = get_target_outputs(":$_info_plist_target") + outputs = [ + "{{bundle_contents_dir}}/Info.plist", + ] + public_deps = [ + ":$_info_plist_target", + ] + } + + create_signed_bundle(_target_name) { + 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 + + # 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(_link_target_name) { + forward_variables_from(invoker, + [ + "public_configs", + "public_deps", + "testonly", + "visibility", + ]) + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ ":$_target_name" ] + + 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" ] + } + + bundle_data(_target_name + "+bundle") { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + public_deps = [ + ":$_target_name", + ] + sources = [ + "$root_out_dir/$_output_name.framework", + ] + outputs = [ + "{{bundle_resources_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. + assert(invoker.configs != []) + assert(invoker.host_target != target_name) + assert(invoker.xcode_test_application_name != target_name) + + _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" + + 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($default_toolchain)" ] + if (current_toolchain != default_toolchain) { + visibility += [ ":$_target_name" ] + } + + deps = [ + ":$_arch_loadable_module_source", + ] + configs += [ "//build/config/ios:xctest_config" ] + + output_dir = "$target_out_dir/$current_cpu" + output_name = _output_name + output_prefix_override = true + output_extension = "" + } + + if (current_toolchain != default_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", + ] + } + } 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 (ios_automatically_manage_certs) { + # Use a fixed bundle identifier for EarlGrey tests when using Xcode to + # manage the certificates as the number of free certs is limited. + extra_substitutions = [ + "MODULE_BUNDLE_ID=gtest.${ios_generic_test_bundle_id_suffix}-module", + ] + } else { + extra_substitutions = [ "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, + [ + "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 + + # Test files need to be known to Xcode for proper indexing and discovery + # of tests function for XCTest, but the compilation is done via ninja and + # thus must prevent Xcode from linking object files via this hack. + xcode_extra_attributes = { + OTHER_LDFLAGS = "-help" + ONLY_ACTIVE_ARCH = "YES" + DEBUG_INFORMATION_FORMAT = "dwarf" + + # 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) { + BUNDLE_LOADER = "\$(TEST_HOST)" + TEST_HOST = + "\$(BUILT_PRODUCTS_DIR)/${invoker.xcode_test_application_name}" + + ".app/${invoker.xcode_test_application_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 + + _xctest_shell_source_target = _xctest_target + "shell_source" + source_set(_xctest_shell_source_target) { + sources = [ + "//build/config/ios/xctest_shell.mm", + ] + + configs += [ "//build/config/ios:xctest_config" ] + } + + ios_xctest_bundle(_xctest_target) { + output_name = _xctest_output + product_type = _ios_xcode_xctest_bundle_id + host_target = _host_target + xcode_test_application_name = _host_output + + deps = [ + ":$_xctest_shell_source_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" + if (ios_automatically_manage_certs) { + # Use the same bundle identifier for EarlGrey tests as for unit tests + # when managing certificates as the number of free certs is limited. + if (!defined(extra_substitutions)) { + extra_substitutions = [] + } + extra_substitutions += + [ "EXECUTABLE_NAME=gtest.${ios_generic_test_bundle_id_suffix}" ] + } + } + + # Xcode needs those two framework installed in the application (and signed) + # for the XCTest to run, so install them using extra_system_frameworks. + _ios_platform_library = "$ios_sdk_platform_path/Developer/Library" + extra_system_frameworks = [ + "$_ios_platform_library/Frameworks/XCTest.framework", + "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib", + ] + + _xctest_bundle = _xctest_target + "_bundle" + if (current_toolchain == default_toolchain) { + if (!defined(bundle_deps)) { + bundle_deps = [] + } + bundle_deps += [ ":$_xctest_bundle" ] + } + + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Xlinker", + "-rpath", + "-Xlinker", + "@executable_path/Frameworks", + "-Xlinker", + "-rpath", + "-Xlinker", + "@loader_path/Frameworks", + ] + } +} + +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/config/mac/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". + "//ios/chrome/app/resources/XCTRunnerAddition+Info.plist", + ] + + _output_name = "$target_gen_dir/${_target_name}_merged.plist" + outputs = [ + _output_name, + ] + args = [ + "merge", + "-f=xml1", + "-o=" + rebase_path(_output_name, root_build_dir), + ] + rebase_path(sources, root_build_dir) + } + + ios_info_plist(_info_plist_target) { + testonly = true + visibility = [ ":$_info_plist_bundle" ] + + executable_name = _output_name + info_plist_target = ":$_info_plist_merge_plist" + + if (ios_automatically_manage_certs) { + # Use the same bundle identifier for XCUITest tests as for unit tests + # when managing certificates as the number of free certs is limited. + extra_substitutions = + [ "EXECUTABLE_NAME=gtest.${ios_generic_test_bundle_id_suffix}" ] + } + } + + 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", + ] + } + + _xctest_bundle = invoker.xctest_bundle + create_signed_bundle(_target_name) { + testonly = true + + bundle_binary_path = "$_xctrunner_path/XCTRunner" + bundle_extension = ".app" + product_type = "com.apple.product-type.application" + + 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", + ] + + 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 + _xcuitest_runner_target = _xcuitest_target + "_runner" + _xcuitest_module_target = _xcuitest_target + "_module" + + group(_xcuitest_target) { + 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" ]) + + 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/deps/v8/build/config/ios/write_framework_hmap.py b/deps/v8/build/config/ios/write_framework_hmap.py new file mode 100644 index 0000000000..8f6b1439d0 --- /dev/null +++ b/deps/v8/build/config/ios/write_framework_hmap.py @@ -0,0 +1,97 @@ +# 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 struct +import sys + +def Main(args): + if len(args) < 4: + print >> sys.stderr, "Usage: %s output.hmap Foo.framework header1.h..." %\ + (args[0]) + 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.items(), key=lambda (k,v):len(v))[1]) + + 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 + out.write(struct.pack('<%ds' % len(file), file)) + out.write(struct.pack('<s', '\0')) + base = os.path.dirname(path) + os.sep + out.write(struct.pack('<%ds' % len(base), base)) + out.write(struct.pack('<s', '\0')) + path = os.path.basename(path) + out.write(struct.pack('<%ds' % len(path), path)) + out.write(struct.pack('<s', '\0')) + + +if __name__ == '__main__': + sys.exit(Main(sys.argv)) diff --git a/deps/v8/build/config/ios/write_framework_modulemap.py b/deps/v8/build/config/ios/write_framework_modulemap.py new file mode 100644 index 0000000000..b6da571282 --- /dev/null +++ b/deps/v8/build/config/ios/write_framework_modulemap.py @@ -0,0 +1,26 @@ +# 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 + +def Main(framework): + # Find the name of the binary based on the part before the ".framework". + binary = os.path.basename(framework).split('.')[0] + module_path = os.path.join(framework, 'Modules'); + if not os.path.exists(module_path): + os.mkdir(module_path) + module_template = 'framework module %s {\n' \ + ' umbrella header "%s.h"\n' \ + '\n' \ + ' export *\n' \ + ' module * { export * }\n' \ + '}\n' % (binary, binary) + + module_file = open(os.path.join(module_path, 'module.modulemap'), 'w') + module_file.write(module_template) + module_file.close() + +if __name__ == '__main__': + Main(sys.argv[1]) diff --git a/deps/v8/build/config/ios/xctest_shell.mm b/deps/v8/build/config/ios/xctest_shell.mm new file mode 100644 index 0000000000..dcf5bad5e7 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/jumbo.gni b/deps/v8/build/config/jumbo.gni new file mode 100644 index 0000000000..be90a7591f --- /dev/null +++ b/deps/v8/build/config/jumbo.gni @@ -0,0 +1,313 @@ +# 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/split_static_library.gni") # When someone uses that target_type +import("//build/toolchain/goma.gni") + +declare_args() { + # If true, use a jumbo build (files compiled together) to speed up + # compilation. + use_jumbo_build = false + + # A list of build targets to exclude from jumbo builds, for optimal + # round trip time when frequently changing a set of cpp files. The + # targets can be just the short name (in which case it matches any + # target with that name), a directory prefixed with the root + # specifier //, or a full build target label. + # + # Example: + # These would all exclude the "browser" target in a file + # content/browser/BUILD.gn, and potentially more. + # + # jumbo_build_excluded = [ "browser" ] + # jumbo_build_excluded = [ "//content/browser" ] + # jumbo_build_excluded = [ "//content/browser:browser" ] + jumbo_build_excluded = [] + + # How many files to group on average. Smaller numbers give more + # parallellism, higher numbers give less total CPU usage. Higher + # numbers also give longer single-file recompilation times. + # + # Recommendations: + # Higher numbers than 100 does not reduce wall clock compile times + # even for 4 cores or less so no reason to go higher than 100. + # Going from 50 to 100 with a 4 core CPU saves about 3% CPU time and + # 3% wall clock time in a tree with blink, v8 and content + # jumbofied. At the same time it increases the compile time for the + # largest jumbo chunks by 10-20% and reduces the chance to use all + # available CPU cores. So set the default to 50 to balance between + # high and low-core build performance. -1 means do the default which + # varies depending on whether goma is enabled. + jumbo_file_merge_limit = -1 +} + +# Normal builds benefit from lots of jumbification +jumbo_file_merge_default = 50 + +# Goma builds benefit from more parallelism +jumbo_file_merge_goma = 8 + +# Use one of the targets jumbo_source_set, jumbo_static_library, +# jumbo_split_static_library or jumbo_component to generate a target +# which merges sources if possible to compile much faster. +# +# Special values. +# +# target_type +# The kind of target to build. For example the string +# "static_library". +# +# always_build_jumbo +# If set and set to true, then use jumbo compile even when it is +# globally disabled. Otherwise it has no effect. +# +# never_build_jumbo +# If set and set to true, then do not jumbo compile even if it is +# globally enabled. Otherwise it has no effect. +# +# jumbo_excluded_sources +# If set to a list of files, those files will not be merged with +# the rest. This can be necessary if merging the files causes +# compilation issues and fixing the issues is impractical. +template("internal_jumbo_target") { + use_jumbo_build_for_target = use_jumbo_build + if (defined(invoker.always_build_jumbo) && invoker.always_build_jumbo) { + use_jumbo_build_for_target = true + } + if (defined(invoker.never_build_jumbo) && invoker.never_build_jumbo) { + use_jumbo_build_for_target = false + } + + foreach(excluded_target, jumbo_build_excluded) { + if (excluded_target == target_name || + excluded_target == get_label_info(":" + target_name, "dir") || + excluded_target == + get_label_info(":" + target_name, "label_no_toolchain")) { + use_jumbo_build_for_target = false + } + } + + excluded_sources = [] + if (defined(invoker.jumbo_excluded_sources)) { + excluded_sources = invoker.jumbo_excluded_sources + } + + if (defined(invoker.sources)) { + invoker_sources = invoker.sources + } else { + invoker_sources = [] + } + + gen_target_dir = invoker.target_gen_dir + + not_needed([ "gen_target_dir" ]) # Prevent "unused variable". + + if (use_jumbo_build_for_target) { + jumbo_files = [] + + # Split the sources list into chunks that are not excessively large + current_file_index = 0 + next_chunk_start = 0 + next_chunk_number = 1 + merge_limit = jumbo_file_merge_limit + if (merge_limit == -1) { + if (use_goma) { + merge_limit = jumbo_file_merge_goma + } else { + merge_limit = jumbo_file_merge_default + } + } + has_c_file = false + has_objective_c_file = false + sources_in_jumbo_files = [] + assert(merge_limit > 0) + foreach(source_file, invoker_sources) { + source_ext = get_path_info(source_file, "extension") + is_source_file = true + if (source_ext == "c") { + has_c_file = true + } else if (source_ext == "mm") { + has_objective_c_file = true + } else if (source_ext == "cc" || source_ext == "cpp") { + if (current_file_index == next_chunk_start) { + jumbo_files += [ "$gen_target_dir/" + target_name + "_jumbo_" + + next_chunk_number + ".cc" ] + next_chunk_number += 1 + next_chunk_start += merge_limit + } + current_file_index += 1 + } else { + is_source_file = false + } + if (is_source_file) { + sources_in_jumbo_files += [ source_file ] + } + } + + if (jumbo_files == [] || current_file_index == 1) { + # Empty sources list or a sources list with only header files or + # at most one non-header file. + use_jumbo_build_for_target = false + not_needed([ + "sources_in_jumbo_files", + "current_file_index", + "next_chunk_start", + "next_chunk_number", + ]) + } + + if (has_c_file) { + jumbo_files += [ "$gen_target_dir/" + target_name + "_jumbo_c.c" ] + } + if (has_objective_c_file) { + jumbo_files += [ "$gen_target_dir/" + target_name + "_jumbo_mm.mm" ] + } + } + + if (use_jumbo_build_for_target) { + merge_action_name = target_name + "__jumbo_merge" + sources_in_jumbo_files -= excluded_sources + + # Create an action that calls a script that merges all the source files. + action(merge_action_name) { + script = "//build/config/merge_for_jumbo.py" + response_file_contents = + rebase_path(sources_in_jumbo_files, root_build_dir) + outputs = jumbo_files + args = [ "--outputs" ] + rebase_path(outputs, root_build_dir) + + [ "--file-list={{response_file_name}}" ] + + # For the "gn analyze" step to work, gn needs to know about the + # original source files. They can't be in |sources| because then + # they will be compiled, so they have to be somewhere else where + # gn analyze looks. One alternative is the |data| list but that + # will affect test packaging with known bad effects on + # distributed testing. Putting them in this action's input list + # is the least bad place. + inputs = [] + foreach(f, invoker_sources - excluded_sources) { + # Avoid generated files and non non-source files. + in_source_tree = string_replace(rebase_path(f), + rebase_path(root_out_dir), + "dummy") == rebase_path(f) + is_source_file = get_path_info(f, "extension") == "cc" || + get_path_info(f, "extension") == "cpp" || + get_path_info(f, "extension") == "c" || + get_path_info(f, "extension") == "mm" + if (in_source_tree && is_source_file) { + inputs += [ f ] + } + } + } + } else { + # If the list subtraction triggers a gn error, + # jumbo_excluded_sources lists a file that is not in sources. + sources_after_exclusion = invoker_sources - excluded_sources + not_needed([ "sources_after_exclusion" ]) + } + + target_type = invoker.target_type + if (use_jumbo_build_for_target && target_type == "split_static_library") { + # Meaningless and also impossible if split_count > len(jumbo_files) + target_type = "static_library" + not_needed(invoker, [ "split_count" ]) + } + + # Perform the actual operation, either on the original sources or + # the sources post-jumbo merging. + target(target_type, target_name) { + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + # Take everything else not handled above from the invoker. + variables_to_not_forward = [ "deps" ] + if (use_jumbo_build_for_target) { + deps += [ ":" + merge_action_name ] + variables_to_not_forward += [ "sources" ] + assert(jumbo_files != []) + set_sources_assignment_filter([]) # Prefiltered. + sources = invoker_sources - sources_in_jumbo_files + jumbo_files + + # Change include_dirs to make sure that the jumbo file can find its + # #included files. + variables_to_not_forward += [ "include_dirs" ] + include_dirs = [] + if (defined(invoker.include_dirs)) { + include_dirs = invoker.include_dirs + } + include_dirs += [ root_build_dir ] + } + forward_variables_from(invoker, "*", variables_to_not_forward) + } +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_source_set") { + internal_jumbo_target(target_name) { + target_type = "source_set" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_source_set") { + # This sets the default list of configs when the jumbo_source_set target + # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and + # is the list normally applied to static libraries and source sets. + configs = default_compiler_configs +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_static_library") { + internal_jumbo_target(target_name) { + target_type = "static_library" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_static_library") { + # This sets the default list of configs when the jumbo_static_library target + # is defined. The default_compiler_configs comes from BUILDCONFIG.gn and + # is the list normally applied to static libraries and source sets. + configs = default_compiler_configs +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_split_static_library") { + internal_jumbo_target(target_name) { + target_type = "split_static_library" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_split_static_library") { + # This sets the default list of configs when the + # jumbo_split_static_library target is defined. The + # default_compiler_configs comes from BUILDCONFIG.gn and is the list + # normally applied to static libraries and source sets. + configs = default_compiler_configs +} + +# See documentation above by "internal_jumbo_target". +template("jumbo_component") { + internal_jumbo_target(target_name) { + target_type = "component" + forward_variables_from(invoker, "*") + } +} + +set_defaults("jumbo_component") { + # This sets the default list of configs when the jumbo_component + # target is defined. This code is a clone of set_defaults for the + # ordinary "component" template. + 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/deps/v8/build/config/linux/BUILD.gn b/deps/v8/build/config/linux/BUILD.gn new file mode 100644 index 0000000000..6ca9b6a934 --- /dev/null +++ b/deps/v8/build/config/linux/BUILD.gn @@ -0,0 +1,110 @@ +# 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/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") { +} + +# 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 || default_toolchain != "//build/toolchain/cros:target") && + (!use_custom_libcxx || current_cpu == "mipsel")) { + libs = [ "atomic" ] + } +} + +config("x11") { + libs = [ + "X11", + "X11-xcb", + "xcb", + "Xcomposite", + "Xcursor", + "Xdamage", + "Xext", + "Xfixes", + "Xi", + "Xrender", + "Xtst", + ] +} + +config("xcomposite") { + libs = [ "Xcomposite" ] +} + +config("xext") { + libs = [ "Xext" ] +} + +config("xrandr") { + libs = [ "Xrandr" ] +} + +config("xscrnsaver") { + libs = [ "Xss" ] +} + +config("xfixes") { + libs = [ "Xfixes" ] +} + +config("libcap") { + libs = [ "cap" ] +} + +config("xi") { + libs = [ "Xi" ] +} + +config("xtst") { + libs = [ "Xtst" ] +} + +config("libresolv") { + libs = [ "resolv" ] +} + +if (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_32", + "GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26", + ] + } +} + +# 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/deps/v8/build/config/linux/OWNERS b/deps/v8/build/config/linux/OWNERS new file mode 100644 index 0000000000..280ba478dc --- /dev/null +++ b/deps/v8/build/config/linux/OWNERS @@ -0,0 +1 @@ +thomasanderson@chromium.org diff --git a/deps/v8/build/config/linux/atk/BUILD.gn b/deps/v8/build/config/linux/atk/BUILD.gn new file mode 100644 index 0000000000..afc811da11 --- /dev/null +++ b/deps/v8/build/config/linux/atk/BUILD.gn @@ -0,0 +1,59 @@ +# 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") +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_base") { + 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", + + # The AtkValue interface methods we implement and test have been deprecated + # in favor of new API. But that new API cannot be used until corresponding + # support has been added to AT-SPI2 and we stop supporting earlier versions + # of ATK (i.e. < 2.12). + "ATK_DISABLE_DEPRECATION_WARNINGS", + ] +} + +# gn orders flags on a target before flags from configs. The default config +# adds -Wall, and these flags have to be after -Wall -- so they need to +# come from a config and can't be on the target directly. +config("atk") { + configs = [ ":atk_base" ] + + cflags = [ + # G_DEFINE_TYPE automatically generates a *get_instance_private + # inline function after glib 2.37. That's unused. Prevent to + # complain about it. + "-Wno-unused-function", + ] + + if (is_clang) { + # glib uses the pre-c++11 typedef-as-static_assert hack. + cflags += [ "-Wno-unused-local-typedef" ] + } +} diff --git a/deps/v8/build/config/linux/atspi2/BUILD.gn b/deps/v8/build/config/linux/atspi2/BUILD.gn new file mode 100644 index 0000000000..988a995681 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/linux/dbus/BUILD.gn b/deps/v8/build/config/linux/dbus/BUILD.gn new file mode 100644 index 0000000000..f11cf7101c --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/linux/dri/BUILD.gn b/deps/v8/build/config/linux/dri/BUILD.gn new file mode 100644 index 0000000000..cad883b76d --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/linux/gtk/BUILD.gn b/deps/v8/build/config/linux/gtk/BUILD.gn new file mode 100644 index 0000000000..d78f7407c1 --- /dev/null +++ b/deps/v8/build/config/linux/gtk/BUILD.gn @@ -0,0 +1,53 @@ +# 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") + +# 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", + "gtk+-${gtk_version}.0", + "gthread-2.0", + ] +} + +# Basically no parts of Chrome should depend on GTK. To prevent accidents, the +# parts that explicitly need GTK are whitelisted on this target. +group("gtk") { + visibility = [ + "//chrome/test:interactive_ui_tests", + "//chrome/test:unit_tests", + "//examples:peerconnection_client", + "//gpu/gles2_conform_support:gles2_conform_test_windowless", + "//remoting/host/linux", + "//remoting/host/it2me:common", + "//remoting/host/it2me:remote_assistance_host", + "//remoting/host:common", + "//remoting/host/file_transfer", + "//remoting/host:remoting_me2me_host_static", + "//remoting/test:it2me_standalone_host_main", + "//webrtc/examples:peerconnection_client", + "//chrome/browser/ui/libgtkui:*", + ] + + public_configs = [ ":gtk_internal_config" ] +} + +# Depend on "gtkprint" to get this. +pkg_config("gtkprint_internal_config") { + packages = [ "gtk+-unix-print-${gtk_version}.0" ] +} + +group("gtkprint") { + visibility = [ "//chrome/browser/ui/libgtkui:*" ] + public_configs = [ ":gtkprint_internal_config" ] +} diff --git a/deps/v8/build/config/linux/gtk/gtk.gni b/deps/v8/build/config/linux/gtk/gtk.gni new file mode 100644 index 0000000000..1e0e6ace0f --- /dev/null +++ b/deps/v8/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. + +declare_args() { + # The (major) version of GTK to build against. + gtk_version = 3 +} + +assert(gtk_version >= 3 && gtk_version <= 4) diff --git a/deps/v8/build/config/linux/libdrm/BUILD.gn b/deps/v8/build/config/linux/libdrm/BUILD.gn new file mode 100644 index 0000000000..daebcfd3a4 --- /dev/null +++ b/deps/v8/build/config/linux/libdrm/BUILD.gn @@ -0,0 +1,33 @@ +# 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) + +declare_args() { + # Controls whether the build should use the version of libdrm + # library shipped with the system. In release builds of Chrome OS we + # use the system version, but when building on dev workstations we + # bundle it because Ubuntu doesn't ship a usable version. + # Chromecast will use this as well. + use_system_libdrm = false +} + +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/deps/v8/build/config/linux/libffi/BUILD.gn b/deps/v8/build/config/linux/libffi/BUILD.gn new file mode 100644 index 0000000000..a4041727b1 --- /dev/null +++ b/deps/v8/build/config/linux/libffi/BUILD.gn @@ -0,0 +1,9 @@ +# 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") + +pkg_config("libffi") { + packages = [ "libffi" ] +} diff --git a/deps/v8/build/config/linux/libva/BUILD.gn b/deps/v8/build/config/linux/libva/BUILD.gn new file mode 100644 index 0000000000..f350a0d6f1 --- /dev/null +++ b/deps/v8/build/config/linux/libva/BUILD.gn @@ -0,0 +1,13 @@ +# 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, "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. +} diff --git a/deps/v8/build/config/linux/nss/BUILD.gn b/deps/v8/build/config/linux/nss/BUILD.gn new file mode 100644 index 0000000000..5788f3e5d6 --- /dev/null +++ b/deps/v8/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) { + # 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/deps/v8/build/config/linux/pangocairo/BUILD.gn b/deps/v8/build/config/linux/pangocairo/BUILD.gn new file mode 100644 index 0000000000..ddcc754bbd --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/linux/pangocairo/pangocairo.gni b/deps/v8/build/config/linux/pangocairo/pangocairo.gni new file mode 100644 index 0000000000..ca99445b96 --- /dev/null +++ b/deps/v8/build/config/linux/pangocairo/pangocairo.gni @@ -0,0 +1,7 @@ +# 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/ui.gni") + +use_pangocairo = is_linux && !use_ozone diff --git a/deps/v8/build/config/linux/pkg-config.py b/deps/v8/build/config/linux/pkg-config.py new file mode 100755 index 0000000000..e2bf7666b2 --- /dev/null +++ b/deps/v8/build/config/linux/pkg-config.py @@ -0,0 +1,246 @@ +#!/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. + +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) + 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) + 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) + 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) + 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) + 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/deps/v8/build/config/linux/pkg_config.gni b/deps/v8/build/config/linux/pkg_config.gni new file mode 100644 index 0000000000..428e44ac0a --- /dev/null +++ b/deps/v8/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", + current_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/deps/v8/build/config/locales.gni b/deps/v8/build/config/locales.gni new file mode 100644 index 0000000000..21f06187a4 --- /dev/null +++ b/deps/v8/build/config/locales.gni @@ -0,0 +1,189 @@ +# 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. + +# Android doesn't ship all locales in order to save space (but webview does). +# http://crbug.com/369218 +android_chrome_omitted_locales = [ + "bn", + "et", + "gu", + "kn", + "ml", + "mr", + "ms", + "ta", + "te", +] + +# 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. These asserts ensure that GN doesn't complain +# about them being unused. +assert(android_chrome_omitted_locales != []) +assert(ios_unsupported_locales != []) + +# Note: keep in sync with below. +locales = [ + "am", + "ar", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "en-GB", + "en-US", + "es", + "et", + "fa", + "fi", + "fil", + "fr", + "gu", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "kn", + "ko", + "lt", + "lv", + "ml", + "mr", + "ms", + "nb", + "nl", + "pl", + "pt-PT", + "ro", + "ru", + "sk", + "sl", + "sr", + "sv", + "sw", + "ta", + "te", + "th", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW", +] + +# 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", + ] +} else { + locales += [ + "es-MX", + "pt", + ] + + ios_packed_locales = locales - ios_unsupported_locales +} + +locales_with_fake_bidi = locales + [ "fake-bidi" ] + +# 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 = [ + "am", + "ar", + "bg", + "bn", + "ca", + "cs", + "da", + "de", + "el", + "en_GB", + "en", + "es", + "et", + "fa", + "fi", + "fil", + "fr", + "gu", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "kn", + "ko", + "lt", + "lv", + "ml", + "mr", + "ms", + "nb", + "nl", + "pl", + "pt_PT", + "ro", + "ru", + "sk", + "sl", + "sr", + "sv", + "sw", + "ta", + "te", + "th", + "tr", + "uk", + "vi", + "zh_CN", + "zh_TW", +] + +# Chrome on iOS uses different names for "es-419" and "pt-BR" (called +# respectively "es-MX" and "pt" on iOS). +if (!is_ios) { + locales_as_mac_outputs += [ + "es_419", + "pt_BR", + ] +} else { + locales_as_mac_outputs += [ + "es_MX", + "pt", + ] + + ios_packed_locales_as_mac_outputs = + locales_as_mac_outputs - ios_unsupported_locales +} diff --git a/deps/v8/build/config/mac/BUILD.gn b/deps/v8/build/config/mac/BUILD.gn new file mode 100644 index 0000000000..780f752060 --- /dev/null +++ b/deps/v8/build/config/mac/BUILD.gn @@ -0,0 +1,109 @@ +# 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/mac/mac_sdk.gni") +import("//build/config/mac/symbols.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 (current_cpu == "x64") { + common_mac_flags += [ + "-arch", + "x86_64", + ] + } else if (current_cpu == "x86") { + common_mac_flags += [ + "-arch", + "i386", + ] + } + + # 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 + + # Create a new read-only segment for protected memory. The default segments + # (__TEXT and __DATA) are mapped read-execute and read-write by default. + ldflags += [ + "-segprot", + "PROTECTED_MEMORY", + "rw", + "r", + ] + + 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_UNDERSCORE=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/mac/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" ] + } +} diff --git a/deps/v8/build/config/mac/BuildInfo.plist b/deps/v8/build/config/mac/BuildInfo.plist new file mode 100644 index 0000000000..d32bf2ea7f --- /dev/null +++ b/deps/v8/build/config/mac/BuildInfo.plist @@ -0,0 +1,18 @@ +<?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>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/deps/v8/build/config/mac/OWNERS b/deps/v8/build/config/mac/OWNERS new file mode 100644 index 0000000000..14747a0025 --- /dev/null +++ b/deps/v8/build/config/mac/OWNERS @@ -0,0 +1,4 @@ +rsesek@chromium.org +sdefresne@chromium.org + +# COMPONENT: Build diff --git a/deps/v8/build/config/mac/base_rules.gni b/deps/v8/build/config/mac/base_rules.gni new file mode 100644 index 0000000000..bcb34a166d --- /dev/null +++ b/deps/v8/build/config/mac/base_rules.gni @@ -0,0 +1,308 @@ +# 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 file contains rules that are shared between Mac and iOS. + +import("//build/toolchain/toolchain.gni") +import("//build/config/mac/symbols.gni") + +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") +} else if (is_ios) { + import("//build/config/ios/ios_sdk.gni") +} + +# Convert plist file to given format. +# +# Arguments +# +# source: +# string, path to the plist file to convert +# +# output: +# string, path to the converted plist, must be under $root_build_dir +# +# format: +# string, the format to `plutil -convert` the plist to. +template("convert_plist") { + assert(defined(invoker.source), "source must be defined for $target_name") + assert(defined(invoker.output), "output must be defined for $target_name") + assert(defined(invoker.format), "format must be defined for $target_name") + + action(target_name) { + forward_variables_from(invoker, + [ + "visibility", + "testonly", + "deps", + ]) + + script = "//build/config/mac/xcrun.py" + sources = [ + invoker.source, + ] + outputs = [ + invoker.output, + ] + args = [] + if (!use_system_xcode) { + args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + args += [ + "plutil", + "-convert", + invoker.format, + "-o", + rebase_path(invoker.output, root_build_dir), + rebase_path(invoker.source, root_build_dir), + ] + } +} + +# Template to merge multiple plist files and perform variable substitutions. +# +# Arguments +# +# plist_templates: +# string array, paths to plist files which will be used for the bundle. +# +# format: +# string, the format to `plutil -convert` the plist to when +# generating the output. +# +# substitutions: +# string array, 'key=value' pairs used to replace ${key} by value +# when generating the output plist file. +# +# output_name: +# string, name of the generated plist file. +template("compile_plist") { + assert(defined(invoker.plist_templates), + "A list of template plist files must be specified for $target_name") + assert(defined(invoker.format), + "The plist format must be specified for $target_name") + assert(defined(invoker.substitutions), + "A list of key=value pairs must be specified for $target_name") + assert(defined(invoker.output_name), + "The name of the output file must be specified for $target_name") + + _output_name = invoker.output_name + _merged_name = get_path_info(_output_name, "dir") + "/" + + get_path_info(_output_name, "name") + "_merged." + + get_path_info(_output_name, "extension") + + _merge_target = target_name + "_merge" + + action(_merge_target) { + forward_variables_from(invoker, + [ + "deps", + "testonly", + ]) + + script = "//build/config/mac/plist_util.py" + sources = invoker.plist_templates + outputs = [ + _merged_name, + ] + args = [ + "merge", + "-f=" + invoker.format, + "-o=" + rebase_path(_merged_name, root_build_dir), + ] + rebase_path(invoker.plist_templates, root_build_dir) + } + + action(target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + script = "//build/config/mac/plist_util.py" + sources = [ + _merged_name, + ] + outputs = [ + _output_name, + ] + args = [ + "substitute", + "-f=" + invoker.format, + "-o=" + rebase_path(_output_name, root_build_dir), + "-t=" + rebase_path(_merged_name, root_build_dir), + ] + foreach(_substitution, invoker.substitutions) { + args += [ "-s=$_substitution" ] + } + deps = [ + ":$_merge_target", + ] + } +} + +# Template to merge multiple .entitlements files performing variable +# substitutions. +# +# Arguments +# +# entitlements_templates: +# string array, paths to entitlements files which will be used for the +# bundle. +# +# substitutions: +# string array, 'key=value' pairs used to replace ${key} by value +# when generating the output plist file. +# +# output_name: +# string, name of the generated entitlements file. +template("compile_entitlements") { + assert(defined(invoker.entitlements_templates), + "A list of template plist files must be specified for $target_name") + + compile_plist(target_name) { + forward_variables_from(invoker, + "*", + [ + "entitlements_templates", + "format", + "plist_templates", + ]) + + plist_templates = invoker.entitlements_templates + + # Entitlements files are always encoded in xml1. + format = "xml1" + + # Entitlements files use unsubstitued variables, so define substitutions + # to leave those variables untouched. + if (!defined(substitutions)) { + substitutions = [] + } + + substitutions += [ + "AppIdentifierPrefix=\$(AppIdentifierPrefix)", + "CFBundleIdentifier=\$(CFBundleIdentifier)", + ] + } +} + +# The base template used to generate Info.plist files for iOS and Mac apps and +# frameworks. +# +# Arguments +# +# plist_templates: +# string array, paths to plist files which will be used for the bundle. +# +# executable_name: +# string, name of the generated target used for the product +# and executable name as specified in the output Info.plist. +# +# format: +# string, the format to `plutil -convert` the plist to when +# generating the output. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +# +# output_name: +# (optional) string, name of the generated plist file, default to +# "$target_gen_dir/$target_name.plist". +template("info_plist") { + assert(defined(invoker.executable_name), + "The executable_name must be specified for $target_name") + executable_name = invoker.executable_name + + compile_plist(target_name) { + forward_variables_from(invoker, + [ + "plist_templates", + "testonly", + "deps", + "visibility", + "format", + ]) + + if (defined(invoker.output_name)) { + output_name = invoker.output_name + } else { + output_name = "$target_gen_dir/$target_name.plist" + } + + substitutions = [ + "BUILD_MACHINE_OS_BUILD=$machine_os_build", + "EXECUTABLE_NAME=$executable_name", + "GCC_VERSION=com.apple.compilers.llvm.clang.1_0", + "PRODUCT_NAME=$executable_name", + "XCODE_BUILD=$xcode_build", + "XCODE_VERSION=$xcode_version", + ] + if (is_mac) { + substitutions += [ + "MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target", + "CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version", + ] + } else if (is_ios) { + substitutions += [ "IOS_DEPLOYMENT_TARGET=$ios_deployment_target" ] + } + if (defined(invoker.extra_substitutions)) { + substitutions += invoker.extra_substitutions + } + } +} + +# 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/mac/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), + ] + if (!use_system_xcode) { + args += [ + "--developer_dir", + hermetic_xcode_path, + ] + } + args += ibtool_flags + } +} diff --git a/deps/v8/build/config/mac/compile_ib_files.py b/deps/v8/build/config/mac/compile_ib_files.py new file mode 100644 index 0000000000..281e554e1d --- /dev/null +++ b/deps/v8/build/config/mac/compile_ib_files.py @@ -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 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.') + parser.add_argument('--developer_dir', required=False, + help='Path to Xcode.') + args, unknown_args = parser.parse_known_args() + + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + + 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/deps/v8/build/config/mac/mac_sdk.gni b/deps/v8/build/config/mac/mac_sdk.gni new file mode 100644 index 0000000000..1a6d170a7e --- /dev/null +++ b/deps/v8/build/config/mac/mac_sdk.gni @@ -0,0 +1,112 @@ +# 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/mac/mac_sdk_overrides.gni") +import("//build/toolchain/toolchain.gni") + +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.10.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.10.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" +} + +# 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. +_verify_sdk = is_chrome_branded && is_official_build && target_os != "ios" + +find_sdk_args = [ "--print_sdk_path" ] +if (!use_system_xcode) { + find_sdk_args += [ + "--developer_dir", + hermetic_xcode_path, + ] +} +if (_verify_sdk) { + find_sdk_args += [ + "--verify", + mac_sdk_min, + "--sdk_path=" + mac_sdk_path, + ] +} else { + find_sdk_args += [ mac_sdk_min ] +} + +# The tool will print the SDK path on the first line, and the version on the +# second line. +find_sdk_lines = + exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines") +mac_sdk_version = find_sdk_lines[1] +if (mac_sdk_path == "") { + mac_sdk_path = find_sdk_lines[0] +} + +script_name = "//build/config/mac/sdk_info.py" +sdk_info_args = [] +if (!use_system_xcode) { + sdk_info_args += [ + "--developer_dir", + hermetic_xcode_path, + ] +} +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 +machine_os_build = _mac_sdk_result.machine_os_build + +if (mac_sdk_version != mac_sdk_min && + exec_script("//build/check_return_value.py", + [ + "test", + xcode_version, + "-ge", + "0730", + ], + "value") != 1) { + print( + "********************************************************************************") + print( + " WARNING: The Mac OS X SDK is incompatible with the version of Xcode. To fix,") + print( + " either upgrade Xcode to the latest version or install the Mac OS X") + print( + " $mac_sdk_min SDK. For more information, see https://crbug.com/620127.") + print() + print(" Current SDK Version: $mac_sdk_version") + print(" Current Xcode Version: $xcode_version ($xcode_build)") + print( + "********************************************************************************") + assert(false, "SDK is incompatible with Xcode") +} diff --git a/deps/v8/build/config/mac/mac_sdk_overrides.gni b/deps/v8/build/config/mac/mac_sdk_overrides.gni new file mode 100644 index 0000000000..55451f043f --- /dev/null +++ b/deps/v8/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.13" + } else { + mac_sdk_min = _sdk_min_from_env + } +} diff --git a/deps/v8/build/config/mac/package_framework.py b/deps/v8/build/config/mac/package_framework.py new file mode 100644 index 0000000000..75604094e4 --- /dev/null +++ b/deps/v8/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), 0755) + 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/deps/v8/build/config/mac/plist_util.py b/deps/v8/build/config/mac/plist_util.py new file mode 100644 index 0000000000..bba0208a5b --- /dev/null +++ b/deps/v8/build/config/mac/plist_util.py @@ -0,0 +1,226 @@ +# 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 plistlib +import os +import re +import subprocess +import sys +import tempfile +import shlex + + +# Xcode substitutes variables like ${PRODUCT_NAME} or $(PRODUCT_NAME) when +# compiling Info.plist. It also supports supports modifiers like :identifier +# or :rfc1034identifier. SUBSTITUTION_REGEXP_LIST is a list of regular +# expressions matching a variable substitution pattern with an optional +# modifier, while INVALID_CHARACTER_REGEXP matches all characters that are +# not valid in an "identifier" value (used when applying the modifier). +INVALID_CHARACTER_REGEXP = re.compile(r'[_/\s]') +SUBSTITUTION_REGEXP_LIST = ( + re.compile(r'\$\{(?P<id>[^}]*?)(?P<modifier>:[^}]*)?\}'), + re.compile(r'\$\((?P<id>[^}]*?)(?P<modifier>:[^}]*)?\)'), +) + + +class SubstitutionError(Exception): + def __init__(self, key): + super(SubstitutionError, self).__init__() + self.key = key + + def __str__(self): + return "SubstitutionError: {}".format(self.key) + + +def InterpolateString(value, substitutions): + """Interpolates variable references into |value| using |substitutions|. + + Inputs: + value: a string + substitutions: a mapping of variable names to values + + Returns: + A new string with all variables references ${VARIABLES} replaced by their + value in |substitutions|. Raises SubstitutionError if a variable has no + substitution. + """ + def repl(match): + variable = match.group('id') + if variable not in substitutions: + raise SubstitutionError(variable) + # Some values need to be identifier and thus the variables references may + # contains :modifier attributes to indicate how they should be converted + # to identifiers ("identifier" replaces all invalid characters by '_' and + # "rfc1034identifier" replaces them by "-" to make valid URI too). + modifier = match.group('modifier') + if modifier == ':identifier': + return INVALID_CHARACTER_REGEXP.sub('_', substitutions[variable]) + elif modifier == ':rfc1034identifier': + return INVALID_CHARACTER_REGEXP.sub('-', substitutions[variable]) + else: + return substitutions[variable] + for substitution_regexp in SUBSTITUTION_REGEXP_LIST: + value = substitution_regexp.sub(repl, value) + return value + + +def Interpolate(value, substitutions): + """Interpolates variable references into |value| using |substitutions|. + + Inputs: + value: a value, can be a dictionary, list, string or other + substitutions: a mapping of variable names to values + + Returns: + A new value with all variables references ${VARIABLES} replaced by their + value in |substitutions|. Raises SubstitutionError if a variable has no + substitution. + """ + if isinstance(value, dict): + return {k: Interpolate(v, substitutions) for k, v in value.iteritems()} + if isinstance(value, list): + return [Interpolate(v, substitutions) for v in value] + if isinstance(value, str): + return InterpolateString(value, substitutions) + return value + + +def LoadPList(path): + """Loads Plist at |path| and returns it as a dictionary.""" + fd, name = tempfile.mkstemp() + try: + subprocess.check_call(['plutil', '-convert', 'xml1', '-o', name, path]) + with os.fdopen(fd, 'r') as f: + return plistlib.readPlist(f) + finally: + os.unlink(name) + + +def SavePList(path, format, data): + """Saves |data| as a Plist to |path| in the specified |format|.""" + fd, name = tempfile.mkstemp() + try: + # "plutil" does not replace the destination file but update it in place, + # so if more than one hardlink points to destination all of them will be + # modified. This is not what is expected, so delete destination file if + # it does exist. + if os.path.exists(path): + os.unlink(path) + with os.fdopen(fd, 'w') as f: + plistlib.writePlist(data, f) + subprocess.check_call(['plutil', '-convert', format, '-o', path, name]) + finally: + os.unlink(name) + + +def MergePList(plist1, plist2): + """Merges |plist1| with |plist2| recursively. + + Creates a new dictionary representing a Property List (.plist) files by + merging the two dictionary |plist1| and |plist2| recursively (only for + dictionary values). List value will be concatenated. + + Args: + plist1: a dictionary representing a Property List (.plist) file + plist2: a dictionary representing a Property List (.plist) file + + Returns: + A new dictionary representing a Property List (.plist) file by merging + |plist1| with |plist2|. If any value is a dictionary, they are merged + recursively, otherwise |plist2| value is used. If values are list, they + are concatenated. + """ + result = plist1.copy() + for key, value in plist2.iteritems(): + if isinstance(value, dict): + old_value = result.get(key) + if isinstance(old_value, dict): + value = MergePList(old_value, value) + if isinstance(value, list): + value = plist1.get(key, []) + plist2.get(key, []) + result[key] = value + return result + + +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 MergeAction(Action): + """Class to merge multiple plist files.""" + + name = 'merge' + help = 'merge multiple plist files' + + @staticmethod + def _Register(parser): + parser.add_argument( + '-o', '--output', required=True, + help='path to the output plist file') + parser.add_argument( + '-f', '--format', required=True, choices=('xml1', 'binary1', 'json'), + help='format of the plist file to generate') + parser.add_argument( + 'path', nargs="+", + help='path to plist files to merge') + + @staticmethod + def _Execute(args): + data = {} + for filename in args.path: + data = MergePList(data, LoadPList(filename)) + SavePList(args.output, args.format, data) + + +class SubstituteAction(Action): + """Class implementing the variable substitution in a plist file.""" + + name = 'substitute' + help = 'perform pattern substitution in a plist file' + + @staticmethod + def _Register(parser): + parser.add_argument( + '-o', '--output', required=True, + help='path to the output plist file') + parser.add_argument( + '-t', '--template', required=True, + help='path to the template file') + parser.add_argument( + '-s', '--substitution', action='append', default=[], + help='substitution rule in the format key=value') + parser.add_argument( + '-f', '--format', required=True, choices=('xml1', 'binary1', 'json'), + help='format of the plist file to generate') + + @staticmethod + def _Execute(args): + substitutions = {} + for substitution in args.substitution: + key, value = substitution.split('=', 1) + substitutions[key] = value + data = Interpolate(LoadPList(args.template), substitutions) + SavePList(args.output, args.format, data) + + +def Main(): + parser = argparse.ArgumentParser(description='manipulate plist files') + subparsers = parser.add_subparsers() + + for action in [MergeAction, SubstituteAction]: + action.Register(subparsers) + + args = parser.parse_args() + args.func(args) + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/deps/v8/build/config/mac/prepare_framework_version.py b/deps/v8/build/config/mac/prepare_framework_version.py new file mode 100644 index 0000000000..5e8a53f20a --- /dev/null +++ b/deps/v8/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, 0700) + + 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/deps/v8/build/config/mac/rules.gni b/deps/v8/build/config/mac/rules.gni new file mode 100644 index 0000000000..d9f4b6e673 --- /dev/null +++ b/deps/v8/build/config/mac/rules.gni @@ -0,0 +1,676 @@ +# 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/mac/base_rules.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] + } + + 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", + ] + 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 compile and package Mac XIB files as bundle data. +# +# Arguments +# +# sources: +# list of string, sources to comiple +# +# output_path: +# (optional) string, the path to use for the outputs list in the +# bundle_data step. If unspecified, defaults to bundle_resources_dir. +template("mac_xib_bundle_data") { + _target_name = target_name + _compile_target_name = _target_name + "_compile_ibtool" + + compile_ib_files(_compile_target_name) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = invoker.sources + output_extension = "nib" + ibtool_flags = [ + "--minimum-deployment-target", + mac_deployment_target, + + # TODO(rsesek): Enable this once all the bots are on Xcode 7+. + # "--target-device", + # "mac", + ] + } + + bundle_data(_target_name) { + forward_variables_from(invoker, + [ + "testonly", + "visibility", + ]) + + public_deps = [ + ":$_compile_target_name", + ] + sources = get_target_outputs(":$_compile_target_name") + + _output_path = "{{bundle_resources_dir}}" + if (defined(invoker.output_path)) { + _output_path = invoker.output_path + } + + outputs = [ + "$_output_path/{{source_file_part}}", + ] + } +} + +# 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 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: +# +# 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), + "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" ] + 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) { + # TODO(sdefresne): should we have a framework_dirs similar to lib_dirs + # and include_dirs to avoid duplicate values on the command-line. + visibility = [ ":$_framework_target" ] + cflags = [ + "-F", + rebase_path("$root_out_dir/.", root_build_dir), + ] + ldflags = [ + "-F", + rebase_path("$root_out_dir/.", root_build_dir), + ] + lib_dirs = [ root_out_dir ] + libs = [ _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", + ] + + 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" ] + } +} + +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 { + 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/config/mac/write_pkg_info.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" ] + } + 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" ] + + 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/deps/v8/build/config/mac/sdk_info.py b/deps/v8/build/config/mac/sdk_info.py new file mode 100644 index 0000000000..46dcec870c --- /dev/null +++ b/deps/v8/build/config/mac/sdk_info.py @@ -0,0 +1,97 @@ +# 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 argparse +import doctest +import itertools +import os +import subprocess +import sys + +# 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 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): + """Fills the Xcode version and build number into |settings|.""" + lines = subprocess.check_output(['xcodebuild', '-version']).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|.""" + settings['machine_os_build'] = subprocess.check_output( + ['sw_vers', '-buildVersion']).strip() + + +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']).strip() + settings['sdk_version'] = subprocess.check_output([ + 'xcrun', '-sdk', platform, '--show-sdk-version']).strip() + settings['sdk_platform_path'] = subprocess.check_output([ + 'xcrun', '-sdk', platform, '--show-sdk-platform-path']).strip() + # TODO: unconditionally use --show-sdk-build-version once Xcode 7.2 or + # higher is required to build Chrome for iOS or OS X. + if xcode_version >= '0720': + settings['sdk_build'] = subprocess.check_output([ + 'xcrun', '-sdk', platform, '--show-sdk-build-version']).strip() + else: + settings['sdk_build'] = settings['sdk_version'] + + +if __name__ == '__main__': + doctest.testmod() + + parser = argparse.ArgumentParser() + parser.add_argument("--developer_dir", required=False) + 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 = {} + FillMachineOSBuild(settings) + FillXcodeVersion(settings) + FillSDKPathAndVersion(settings, unknownargs[0], settings['xcode_version']) + + for key in sorted(settings): + value = settings[key] + if isinstance(value, str): + value = '"%s"' % value + print '%s=%s' % (key, value) diff --git a/deps/v8/build/config/mac/symbols.gni b/deps/v8/build/config/mac/symbols.gni new file mode 100644 index 0000000000..6166b123d1 --- /dev/null +++ b/deps/v8/build/config/mac/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/mac/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/mac/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/deps/v8/build/config/mac/write_pkg_info.py b/deps/v8/build/config/mac/write_pkg_info.py new file mode 100644 index 0000000000..3e2c3c930e --- /dev/null +++ b/deps/v8/build/config/mac/write_pkg_info.py @@ -0,0 +1,47 @@ +# 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 os +import plist_util +import sys + +# This script creates a PkgInfo file for an OS X .app bundle's plist. +# Usage: python write_pkg_info.py --plist Foo.app/Contents/Info.plist \ +# --output Foo.app/Contents/PkgInfo + +def Main(): + parser = argparse.ArgumentParser( + description='A script to write PkgInfo files for .app bundles.') + parser.add_argument('--plist', required=True, + help='Path to the Info.plist for the .app.') + parser.add_argument('--output', required=True, + help='Path to the desired output file.') + args = parser.parse_args() + + # Remove the output if it exists already. + if os.path.exists(args.output): + os.unlink(args.output) + + plist = plist_util.LoadPList(args.plist) + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + raise ValueError('Expected CFBundlePackageType to be %s, got %s' % \ + ('AAPL', package_type)) + + # The format of PkgInfo is eight characters, representing the bundle type + # and bundle signature, each four characters. If that is missing, four + # '?' characters are used instead. + signature_code = plist.get('CFBundleSignature', '????') + if len(signature_code) != 4: + raise ValueError('CFBundleSignature should be exactly four characters, ' + + 'got %s' % signature_code) + + with open(args.output, 'w') as fp: + fp.write('%s%s' % (package_type, signature_code)) + return 0 + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/deps/v8/build/config/mac/xcrun.py b/deps/v8/build/config/mac/xcrun.py new file mode 100644 index 0000000000..1f8dc203b6 --- /dev/null +++ b/deps/v8/build/config/mac/xcrun.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 argparse +import os +import subprocess +import sys + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='A script to execute a command via xcrun.') + parser.add_argument('--stamp', action='store', type=str, + help='Write a stamp file to this path on success.') + parser.add_argument('--developer_dir', required=False, + help='Path to Xcode.') + args, unknown_args = parser.parse_known_args() + + if args.developer_dir: + os.environ['DEVELOPER_DIR'] = args.developer_dir + + rv = subprocess.check_call(['xcrun'] + unknown_args) + if rv == 0 and args.stamp: + if os.path.exists(args.stamp): + os.unlink(args.stamp) + open(args.stamp, 'w+').close() + + sys.exit(rv) diff --git a/deps/v8/build/config/merge_for_jumbo.py b/deps/v8/build/config/merge_for_jumbo.py new file mode 100755 index 0000000000..6d037a80eb --- /dev/null +++ b/deps/v8/build/config/merge_for_jumbo.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python +# +# 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 script creates a "jumbo" file which merges all incoming files +for compiling. + +""" + +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import hashlib +import io +import os + +def cut_ranges(boundaries): + # Given an increasing sequence of boundary indices, generate a sequence of + # non-overlapping ranges. The total range is inclusive of the first index + # and exclusive of the last index from the given sequence. + for start, stop in zip(boundaries, boundaries[1:]): + yield range(start, stop) + + +def generate_chunk_stops(inputs, output_count, smart_merge=True): + # Note: In the comments below, unique numeric labels are assigned to files. + # Consider them as the sorted rank of the hash of each file path. + # Simple jumbo chunking generates uniformly sized chunks with the ceiling of: + # (output_index + 1) * input_count / output_count + input_count = len(inputs) + stops = [((i + 1) * input_count + output_count - 1) // output_count + for i in range(output_count)] + # This is disruptive at times because file insertions and removals can + # invalidate many chunks as all files are offset by one. + # For example, say we have 12 files in 4 uniformly sized chunks: + # 9, 4, 0; 7, 1, 11; 5, 10, 2; 6, 3, 8 + # If we delete the first file we get: + # 4, 0, 7; 1, 11, 5; 10, 2, 6; 3, 8 + # All of the chunks have new sets of inputs. + + # With path-aware chunking, we start with the uniformly sized chunks: + # 9, 4, 0; 7, 1, 11; 5, 10, 2; 6, 3, 8 + # First we find the smallest rank in each of the chunks. Their indices are + # stored in the |centers| list and in this example the ranks would be: + # 0, 1, 2, 3 + # Then we find the largest rank between the centers. Their indices are stored + # in the |stops| list and in this example the ranks would be: + # 7, 11, 6 + # These files mark the boundaries between chunks and these boundary files are + # often maintained even as files are added or deleted. + # In this example, 7, 11, and 6 are the first files in each chunk: + # 9, 4, 0; 7, 1; 11, 5, 10, 2; 6, 3, 8 + # If we delete the first file and repeat the process we get: + # 4, 0; 7, 1; 11, 5, 10, 2; 6, 3, 8 + # Only the first chunk has a new set of inputs. + if smart_merge: + # Starting with the simple chunks, every file is assigned a rank. + # This requires a hash function that is stable across runs. + hasher = lambda n: hashlib.md5(inputs[n].encode()).hexdigest() + # In each chunk there is a key file with lowest rank; mark them. + # Note that they will not easily change. + centers = [min(indices, key=hasher) for indices in cut_ranges([0] + stops)] + # Between each pair of key files there is a file with highest rank. + # Mark these to be used as border files. They also will not easily change. + # Forget the inital chunks and create new chunks by splitting the list at + # every border file. + stops = [max(indices, key=hasher) for indices in cut_ranges(centers)] + stops.append(input_count) + return stops + + +def write_jumbo_files(inputs, outputs, written_input_set, written_output_set): + chunk_stops = generate_chunk_stops(inputs, len(outputs)) + + written_inputs = 0 + for output_index, output_file in enumerate(outputs): + written_output_set.add(output_file) + if os.path.isfile(output_file): + with open(output_file, "r") as current: + current_jumbo_file = current.read() + else: + current_jumbo_file = None + + out = io.StringIO() + out.write("/* This is a Jumbo file. Don't edit. */\n\n") + out.write("/* Generated with merge_for_jumbo.py. */\n\n") + input_limit = chunk_stops[output_index] + while written_inputs < input_limit: + filename = inputs[written_inputs] + written_inputs += 1 + out.write("#include \"%s\"\n" % filename) + written_input_set.add(filename) + new_jumbo_file = out.getvalue() + out.close() + + if new_jumbo_file != current_jumbo_file: + with open(output_file, "w") as out: + out.write(new_jumbo_file) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--outputs", nargs="+", required=True, + help='List of output files to split input into') + parser.add_argument("--file-list", required=True) + parser.add_argument("--verbose", action="store_true") + args = parser.parse_args() + + lines = [] + # If written with gn |write_file| each file is on its own line. + with open(args.file_list) as file_list_file: + lines = [line.strip() for line in file_list_file if line.strip()] + # If written with gn |response_file_contents| the files are space separated. + all_inputs = [] + for line in lines: + all_inputs.extend(line.split()) + + written_output_set = set() # Just for double checking + written_input_set = set() # Just for double checking + for language_ext in (".cc", ".c", ".mm",): + if language_ext == ".cc": + ext_pattern = (".cc", ".cpp") + else: + ext_pattern = tuple([language_ext]) + + outputs = [x for x in args.outputs if x.endswith(ext_pattern)] + inputs = [x for x in all_inputs if x.endswith(ext_pattern)] + + if not outputs: + assert not inputs + continue + + write_jumbo_files(inputs, outputs, written_input_set, written_output_set) + + assert set(args.outputs) == written_output_set, "Did not fill all outputs" + assert set(all_inputs) == written_input_set, "Did not use all inputs" + if args.verbose: + print("Generated %s (%d files) based on %s" % ( + str(args.outputs), len(written_input_set), args.file_list)) + +if __name__ == "__main__": + main() diff --git a/deps/v8/build/config/mips.gni b/deps/v8/build/config/mips.gni new file mode 100644 index 0000000000..6365088b14 --- /dev/null +++ b/deps/v8/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 current_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 (current_cpu == "mipsel" || v8_current_cpu == "mipsel" || + current_cpu == "mips" || v8_current_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 (current_cpu == "mips64el" || v8_current_cpu == "mips64el" || + current_cpu == "mips64" || v8_current_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/deps/v8/build/config/nacl/BUILD.gn b/deps/v8/build/config/nacl/BUILD.gn new file mode 100644 index 0000000000..d7b22ecf2c --- /dev/null +++ b/deps/v8/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_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 (current_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 && current_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 (current_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/deps/v8/build/config/nacl/config.gni b/deps/v8/build/config/nacl/config.gni new file mode 100644 index 0000000000..77e15fc51c --- /dev/null +++ b/deps/v8/build/config/nacl/config.gni @@ -0,0 +1,55 @@ +# 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 both Newlib and Glibc C libraries where Newlib + # is assumed to be the default one; use this to determine whether Glibc + # is being used instead. + is_nacl_glibc = false +} + +is_nacl_irt = false +is_nacl_nonsfi = false + +nacl_toolchain_dir = "//native_client/toolchain/${host_os}_x86" + +if (is_nacl_glibc) { + if (current_cpu == "x86" || current_cpu == "x64") { + nacl_toolchain_package = "nacl_x86_glibc" + } else if (current_cpu == "arm") { + nacl_toolchain_package = "nacl_arm_glibc" + } +} else { + nacl_toolchain_package = "pnacl_newlib" +} + +if (current_cpu == "pnacl") { + _nacl_tuple = "pnacl" +} else if (current_cpu == "x86" || current_cpu == "x64") { + _nacl_tuple = "x86_64-nacl" +} else if (current_cpu == "arm") { + _nacl_tuple = "arm-nacl" +} else if (current_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/deps/v8/build/config/nacl/rules.gni b/deps/v8/build/config/nacl/rules.gni new file mode 100644 index 0000000000..9bb4ede89c --- /dev/null +++ b/deps/v8/build/config/nacl/rules.gni @@ -0,0 +1,188 @@ +# 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 (current_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 (current_cpu != "x86" && current_cpu != "x64") { + nmfflags += + [ "--library-path=" + + rebase_path("${nacl_toolchain_tooldir}/lib", root_build_dir) ] + if (current_cpu == "arm") { + data += [ "${lib_path}/libarm/" ] + } else { + data += [ "${lib_path}/lib/" ] + } + } else { + # For x86-32, the lib/ directory is called lib32/ instead. + if (current_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 (current_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}_${current_cpu}") + if (current_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 && current_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 current_cpu on purpose because + # current_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/deps/v8/build/config/pch.gni b/deps/v8/build/config/pch.gni new file mode 100644 index 0000000000..93bd2fedc3 --- /dev/null +++ b/deps/v8/build/config/pch.gni @@ -0,0 +1,12 @@ +# 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") + +declare_args() { + # Precompiled header file support is by default available, + # but for distributed build system uses (like goma) or when + # doing official builds. + enable_precompiled_headers = !is_official_build && !use_goma +} diff --git a/deps/v8/build/config/posix/BUILD.gn b/deps/v8/build/config/posix/BUILD.gn new file mode 100644 index 0000000000..ee42d421b2 --- /dev/null +++ b/deps/v8/build/config/posix/BUILD.gn @@ -0,0 +1,75 @@ +# 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_mac && !is_ios && 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) { + # 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=$current_cpu" ], + "trim string", + [ "//build/linux/sysroot_scripts/sysroots.json" ]) + defines += [ "CR_SYSROOT_HASH=$sysroot_hash" ] + } + asmflags += sysroot_flags + + link_sysroot_flags = + [ "--sysroot=" + rebase_path(link_sysroot, root_build_dir) ] + ldflags += link_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 + + # Need to get some linker flags out of the sysroot. + ld_paths = exec_script("sysroot_ld_path.py", + [ + rebase_path("//build/linux/sysroot_ld_path.sh", + root_build_dir), + rebase_path(link_sysroot), + ], + "list lines") + foreach(ld_path, ld_paths) { + ld_path = rebase_path(ld_path, root_build_dir) + ldflags += [ "-L" + ld_path ] + } + } +} diff --git a/deps/v8/build/config/posix/sysroot_ld_path.py b/deps/v8/build/config/posix/sysroot_ld_path.py new file mode 100644 index 0000000000..7056207a23 --- /dev/null +++ b/deps/v8/build/config/posix/sysroot_ld_path.py @@ -0,0 +1,21 @@ +# 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 takes two arguments, the relative location of the shell script that +# does the checking, and the name of the sysroot. + +# TODO(brettw) the build/linux/sysroot_ld_path.sh script should be rewritten in +# Python in this file. + +import subprocess +import sys + +if len(sys.argv) != 3: + print "Need two arguments" + sys.exit(1) + +result = subprocess.check_output([sys.argv[1], sys.argv[2]]).strip() +result = result.replace(" ", "\n") +if result != "": + print result diff --git a/deps/v8/build/config/python.gni b/deps/v8/build/config/python.gni new file mode 100644 index 0000000000..81a1690076 --- /dev/null +++ b/deps/v8/build/config/python.gni @@ -0,0 +1,165 @@ +# 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)) { + _py_files = read_file(invoker.pydeps_file, "list lines") + + # Filter out comments. + set_sources_assignment_filter([ "#*" ]) + sources = _py_files + + # 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 = sources + [ 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") { + # Read the .pydeps file now. Note that this is done everytime this + # template is called, but benchmarking doesn't show any impact on overall + # 'gn gen' speed anyway. + _pydeps_file = invoker.script + "deps" + _pydeps_raw = read_file(_pydeps_file, "list lines") + + # Filter out comments. + set_sources_assignment_filter([ "#*" ]) + sources = _pydeps_raw + _pydeps = sources + sources = [] + + action(target_name) { + # Forward all variables. 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", + ]) + + 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, ".", _script_dir) + } +} + +template("action_foreach_with_pydeps") { + _pydeps_file = invoker.script + "deps" + _pydeps_raw = read_file(_pydeps_file, "list lines") + + # Filter out comments. + # This is a bit convoluted to preserve the value of sources if defined. + _old_sources = [] + if (defined(sources)) { + _old_sources = sources + } + set_sources_assignment_filter([ "#*" ]) + sources = _pydeps_raw + _pydeps = sources + set_sources_assignment_filter([]) + sources = _old_sources + + action_foreach(target_name) { + # Forward all variables. 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", + ]) + + 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, ".", _script_dir) + } +} diff --git a/deps/v8/build/config/sanitizers/BUILD.gn b/deps/v8/build/config/sanitizers/BUILD.gn new file mode 100644 index 0000000000..fd54262251 --- /dev/null +++ b/deps/v8/build/config/sanitizers/BUILD.gn @@ -0,0 +1,650 @@ +# 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" ] + } + + # 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", + ] + } + } +} + +if ((is_mac || is_win || (is_ios && !use_xcode_clang)) && using_sanitizer) { + 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 == "x86") { + _clang_rt_dso_path = "windows/clang_rt.asan_dynamic-i386.dll" + } 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_mac || is_ios) { + 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_mac || is_ios) { + 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", + ] + + if (is_posix || is_fuchsia) { + ldflags = [] + if (is_asan) { + ldflags += [ "-fsanitize=address" ] + if (is_mac) { + # https://crbug.com/708707 + ldflags += [ "-fno-sanitize-address-use-after-scope" ] + } else { + ldflags += [ "-fsanitize-address-use-after-scope" ] + } + } + 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") + assert(!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_mac) { + cflags += [ "-fsanitize-address-use-after-scope" ] + } else { + # https://crbug.com/708707 + cflags += [ "-fno-sanitize-address-use-after-scope" ] + } + if (!asan_globals) { + cflags += [ + "-mllvm", + "-asan-globals=0", + ] + } + if (asan_use_blacklist) { + if (is_win) { + if (!defined(asan_win_blacklist_path)) { + asan_win_blacklist_path = + rebase_path("//tools/memory/asan/blacklist_win.txt", + root_build_dir) + } + cflags += [ "-fsanitize-blacklist=$asan_win_blacklist_path" ] + } else { + # TODO(rnk): Remove this as discussed in http://crbug.com/427202. + if (!defined(asan_blacklist_path)) { + asan_blacklist_path = + rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir) + } + cflags += [ "-fsanitize-blacklist=$asan_blacklist_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_blacklist_path)) { + cfi_blacklist_path = + rebase_path("//tools/cfi/blacklist.txt", root_build_dir) + } + cflags += [ + "-fsanitize=cfi-vcall", + "-fsanitize-blacklist=$cfi_blacklist_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 (current_cpu == "arm") { + # http://crbug.com/517105 + cflags += [ + "-mllvm", + "-sanitizer-coverage-block-threshold=0", + ] + } + } + } +} + +config("hwasan_flags") { + if (is_hwasan) { + cflags = [ "-fsanitize=hwaddress" ] + } +} + +config("lsan_flags") { + if (is_lsan) { + cflags = [ "-fsanitize=leak" ] + } +} + +config("msan_flags") { + if (is_msan) { + assert(is_linux, "msan only supported on linux x86_64") + if (!defined(msan_blacklist_path)) { + msan_blacklist_path = + rebase_path("//tools/msan/blacklist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=memory", + "-fsanitize-memory-track-origins=$msan_track_origins", + "-fsanitize-blacklist=$msan_blacklist_path", + ] + } +} + +config("tsan_flags") { + if (is_tsan) { + assert(is_linux, "tsan only supported on linux x86_64") + if (!defined(tsan_blacklist_path)) { + tsan_blacklist_path = + rebase_path("//tools/memory/tsan_v2/ignores.txt", root_build_dir) + } + cflags = [ + "-fsanitize=thread", + "-fsanitize-blacklist=$tsan_blacklist_path", + ] + } +} + +config("ubsan_flags") { + cflags = [] + if (is_ubsan) { + if (!defined(ubsan_blacklist_path)) { + ubsan_blacklist_path = + rebase_path("//tools/ubsan/blacklist.txt", root_build_dir) + } + cflags += [ + # Yasm dies with an "Illegal instruction" error when bounds checking is + # enabled. See http://crbug.com/489901 + # "-fsanitize=bounds", + "-fsanitize=float-divide-by-zero", + "-fsanitize=integer-divide-by-zero", + "-fsanitize=null", + "-fsanitize=object-size", + "-fsanitize=pointer-overflow", + "-fsanitize=return", + "-fsanitize=returns-nonnull-attribute", + "-fsanitize=shift-exponent", + "-fsanitize=signed-integer-overflow", + "-fsanitize=unreachable", + "-fsanitize=vla-bound", + "-fsanitize-blacklist=$ubsan_blacklist_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_blacklist_path)) { + ubsan_security_blacklist_path = + rebase_path("//tools/ubsan/security_blacklist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=function", + "-fsanitize=pointer-overflow", + "-fsanitize=shift", + "-fsanitize=signed-integer-overflow", + "-fsanitize=vla-bound", + "-fsanitize=vptr", + "-fsanitize-blacklist=$ubsan_security_blacklist_path", + ] + } +} + +config("ubsan_null_flags") { + if (is_ubsan_null) { + cflags = [ "-fsanitize=null" ] + } +} + +config("ubsan_vptr_flags") { + if (is_ubsan_vptr) { + if (!defined(ubsan_vptr_blacklist_path)) { + ubsan_vptr_blacklist_path = + rebase_path("//tools/ubsan/vptr_blacklist.txt", root_build_dir) + } + cflags = [ + "-fsanitize=vptr", + "-fsanitize-blacklist=$ubsan_vptr_blacklist_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/deps/v8/build/config/sanitizers/OWNERS b/deps/v8/build/config/sanitizers/OWNERS new file mode 100644 index 0000000000..0a25a01040 --- /dev/null +++ b/deps/v8/build/config/sanitizers/OWNERS @@ -0,0 +1,4 @@ +inferno@chromium.org +metzman@chromium.org +mmoroz@chromium.org +ochang@chromium.org diff --git a/deps/v8/build/config/sanitizers/sanitizers.gni b/deps/v8/build/config/sanitizers/sanitizers.gni new file mode 100644 index 0000000000..8cff727191 --- /dev/null +++ b/deps/v8/build/config/sanitizers/sanitizers.gni @@ -0,0 +1,277 @@ +# 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/coverage/coverage.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 + + # Compile for Undefined Behaviour Sanitizer's vptr checks. + is_ubsan_vptr = 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 download prebuilt binaries from + # GCS. + use_prebuilt_instrumented_libraries = false + + # 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. + is_cfi = target_os == "linux" && !is_chromeos && target_cpu == "x64" && + is_official_build + + # 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 = false + + # 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 + use_cfi_icall = target_os == "linux" && !is_chromeos && 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 + + # 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 = "" + + # Use blacklists from tools/memory/asan when compiling with asan. + asan_use_blacklist = true + + # 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 +} + +# Disable sanitizers for non-default toolchains. +if (current_toolchain != default_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_prebuilt_instrumented_libraries = false + use_locally_built_instrumented_libraries = false + use_sanitizer_coverage = false +} + +# 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 + +# 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() { + use_sanitizer_coverage = + !use_clang_coverage && + (use_fuzzing_engine || sanitizer_coverage_flags != "") + + # Detect overflow/underflow for global objects. + # + # Mac: http://crbug.com/352073 + asan_globals = !is_mac +} + +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) { + 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 + } + if (is_msan) { + use_prebuilt_instrumented_libraries = 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_hwasan || (is_android && current_cpu == "arm64"), + "HWASan only supported on Android ARM64 builds.") + +assert(!is_msan || (is_linux && current_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/deps/v8/build/config/sysroot.gni b/deps/v8/build/config/sysroot.gni new file mode 100644 index 0000000000..701c66082e --- /dev/null +++ b/deps/v8/build/config/sysroot.gni @@ -0,0 +1,101 @@ +# 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 absolute path of the sysroot that is applied when compiling using + # the target toolchain. + target_sysroot = "" + + # The absolute path to directory containing linux sysroot images + target_sysroot_dir = "//build/linux" + + use_sysroot = current_cpu == "x86" || current_cpu == "x64" || + current_cpu == "arm" || current_cpu == "arm64" || + current_cpu == "mipsel" || current_cpu == "mips64el" +} + +if (current_os == target_os && current_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_ndk_root/sysroot" +} else if (is_linux && use_sysroot) { + # By default build against a sysroot image downloaded from Cloud Storage + # during gclient runhooks. + if (current_cpu == "x64") { + sysroot = "$target_sysroot_dir/debian_sid_amd64-sysroot" + } else if (current_cpu == "x86") { + sysroot = "$target_sysroot_dir/debian_sid_i386-sysroot" + } else if (current_cpu == "mipsel") { + sysroot = "$target_sysroot_dir/debian_sid_mips-sysroot" + } else if (current_cpu == "mips64el") { + sysroot = "$target_sysroot_dir/debian_sid_mips64el-sysroot" + } else if (current_cpu == "arm") { + sysroot = "$target_sysroot_dir/debian_sid_arm-sysroot" + } else if (current_cpu == "arm64") { + sysroot = "$target_sysroot_dir/debian_sid_arm64-sysroot" + } else { + assert(false, "No linux sysroot for cpu: $target_cpu") + } + + if (sysroot != "") { + _script_arch = current_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) { + import("//build/config/fuchsia/config.gni") + if (current_cpu == "arm64" || current_cpu == "x64") { + sysroot = fuchsia_sdk + "/arch/$current_cpu/sysroot" + } else { + sysroot = "" + } +} else { + sysroot = "" +} + +if (is_android) { + # Android uses unified headers in NDK r16 and later, meaning that the + # compile time sysroot and link time sysroot are different + link_sysroot = sysroot + if (current_cpu == "arm") { + link_sysroot = "$android_ndk_root/$arm_android_sysroot_subdir" + } else if (current_cpu == "arm64") { + link_sysroot = "$android_ndk_root/$arm64_android_sysroot_subdir" + } else if (current_cpu == "x86") { + link_sysroot = "$android_ndk_root/$x86_android_sysroot_subdir" + } else if (current_cpu == "x64") { + link_sysroot = "$android_ndk_root/$x86_64_android_sysroot_subdir" + } else if (current_cpu == "mipsel") { + link_sysroot = "$android_ndk_root/$mips_android_sysroot_subdir" + } else if (current_cpu == "mips64el") { + link_sysroot = "$android_ndk_root/$mips64_android_sysroot_subdir" + } else { + assert(false, "No android link sysroot for cpu: $target_cpu") + } +} else { + link_sysroot = sysroot +} diff --git a/deps/v8/build/config/ui.gni b/deps/v8/build/config/ui.gni new file mode 100644 index 0000000000..547b42fb5c --- /dev/null +++ b/deps/v8/build/config/ui.gni @@ -0,0 +1,60 @@ +# 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") + +declare_args() { + # Indicates if Ozone is enabled. Ozone is a low-level library layer for Linux + # that does not require X11. Enabling this feature disables use of glib, x11, + # Pango, and Cairo. + use_ozone = is_chromeos || (is_chromecast && !is_android) || is_fuchsia + + # 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_fuchsia + + # Whether we should use glib, a low level C utility library. + use_glib = is_linux +} + +declare_args() { + # True means the UI is built using the "views" framework. + toolkit_views = (is_mac || is_win || is_chromeos || use_aura) && + !is_chromecast && !is_fuchsia +} + +# Additional dependent variables ----------------------------------------------- +# +# These variables depend on other variables and can't be set externally. + +# Indicates if the UI toolkit depends on X11. +use_x11 = is_linux && !use_ozone + +# Turn off glib if Ozone is enabled. +if (use_ozone) { + use_glib = false +} + +# Whether to use atk, the Accessibility ToolKit library +use_atk = is_desktop_linux && use_x11 +# ============================================= +# PLEASE DO NOT ADD MORE FLAGS TO THIS FILE +# ============================================= +# +# See comment at the top. diff --git a/deps/v8/build/config/v8_target_cpu.gni b/deps/v8/build/config/v8_target_cpu.gni new file mode 100644 index 0000000000..305981f3fa --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/win/BUILD.gn b/deps/v8/build/config/win/BUILD.gn new file mode 100644 index 0000000000..b5a58459ac --- /dev/null +++ b/deps/v8/build/config/win/BUILD.gn @@ -0,0 +1,558 @@ +# 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/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/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 + + # Use absolute file paths in the compiler diagnostics and (for non-clang) + # __FILE__ macro if needed. Note that enabling this makes your build + # dependent your checkout's path, which means you won't get to use goma's + # global cache, and without clang your builds won't be deterministic. + msvc_use_absolute_paths = 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 (current_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. + ] + + # 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 (msvc_use_absolute_paths) { + # Pass /FC flag to the compiler if needed. + cflags += [ "/FC" ] + + # Print absolute paths in diagnostics. There is no precedent for doing this + # on Linux/Mac (GCC doesn't support it), but MSVC does this with /FC and + # Windows developers rely on it (crbug.com/636109) so only do this on + # Windows. + # TODO(thakis): This comment no longer really make sense after + # https://chromium-review.googlesource.com/c/chromium/src/+/558871/ + # See if we can remove msvc_use_absolute_paths. See also discussion in + # https://reviews.llvm.org/D23816 + if (is_clang) { + cflags += [ "-fdiagnostics-absolute-paths" ] + } + } + + if (is_clang) { + # Don't look for includes in %INCLUDE%. + cflags += [ "/X" ] + + # Tell clang which version of MSVC to emulate. + cflags += [ "-fmsc-version=1911" ] + + # Emit table of address-taken functions for Control-Flow Guard (CFG). We + # don't emit the CFG checks themselves, but this enables the functions to + # be called by code that is built with those checks enabled, such as system + # libraries. + cflags += [ "/guard:cf,nochecks" ] + + 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 (current_cpu == "x86") { + cflags += [ "-m32" ] + } else if (current_cpu == "x64") { + cflags += [ "-m64" ] + } else if (current_cpu == "arm64") { + cflags += [ "--target=arm64-windows" ] + } else { + assert(false, "unknown current_cpu " + current_cpu) + } + + 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" ] + } + + # Clang runtime libraries, such as the sanitizer runtimes, live here. + lib_dirs = [ "$clang_base_path/lib/clang/$clang_version/lib/windows" ] + } + + if (use_lld && !use_thin_lto && (is_clang || !use_goma)) { + # /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 ] + } + + if (!is_debug && !is_component_build) { + # Enable standard linker optimizations like GC (/OPT:REF) and ICF in static + # release builds. These are implied by /PROFILE below, but /PROFILE is + # incompatible with /debug:fastlink. + # 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). + if (!is_win_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", + ] + + # This is required for ATL to use XP-safe versions of its functions. + # TODO(thakis): We no longer support XP; try removing this. + defines += [ "_USING_V110_SDK71_" ] + + 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 += [ + "/ZW", + "/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=NTDDI_WIN10_RS2", + + # 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(current_cpu == "x64" || current_cpu == "x86" || current_cpu == "arm" || + current_cpu == "arm64", + "Only supports x64, x86, arm and arm64 CPUs") + if (current_cpu == "x64") { + ldflags = [ "/MACHINE:X64" ] + } else if (current_cpu == "x86") { + ldflags = [ + "/MACHINE:X86", + "/SAFESEH", # Not compatible with x64 so use only for x86. + "/largeaddressaware", + ] + } else if (current_cpu == "arm") { + ldflags = [ "/MACHINE:ARM" ] + } else if (current_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, + current_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("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 can’t be + # turned on either. + # CFG seems to lead to random corruption with incremental linking so turn off + # CFG in component builds. https://crbug.com/812421 + # 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_component_build && !is_asan) { + # Turn on CFG, except for longjmp because it relies on compiler support + # which clang doesn't have yet. + ldflags = [ "/guard:cf,nolongjmp" ] + } +} + +# 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" ] + } else { + cflags = [ "/MT" ] + } +} + +config("dynamic_crt") { + if (is_debug) { + # This pulls in the DLL debug CRT and defines _DEBUG + cflags = [ "/MDd" ] + } else { + cflags = [ "/MD" ] + } +} + +config("static_crt") { + if (is_debug) { + # This pulls in the static debug CRT and defines _DEBUG + cflags = [ "/MTd" ] + } else { + cflags = [ "/MT" ] + } +} + +# Subsystem -------------------------------------------------------------------- + +# This is appended to the subsystem to specify a minimum version. +if (current_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 (current_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 ---------------------------------------------------------- + +incremental_linking_on_switch = [ "/INCREMENTAL" ] +if ((!is_debug && !is_component_build) || !use_lld) { + incremental_linking_off_switch = [ "/INCREMENTAL:NO" ] +} +if (use_lld) { + incremental_linking_on_switch += [ "/OPT:NOREF" ] +} + +# Enable incremental linking for debug builds and all component builds - any +# builds where performance is not job one. +if (is_debug || is_component_build) { + default_incremental_linking_switch = incremental_linking_on_switch +} else { + default_incremental_linking_switch = incremental_linking_off_switch +} + +# Applies incremental linking or not depending on the current configuration. +config("default_incremental_linking") { + ldflags = default_incremental_linking_switch +} + +# Explicitly on or off incremental linking +config("incremental_linking") { + ldflags = incremental_linking_on_switch +} +config("no_incremental_linking") { + # Projects disable incremental linking to work around ilk file issues with + # link.exe. 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. + if (!use_lld) { + ldflags = incremental_linking_off_switch + } +} + +# Some large modules can't handle incremental linking in some situations. This +# config should be applied to large modules to turn off incremental linking +# when it won't work. +config("default_large_module_incremental_linking") { + if (use_lld || symbol_level == 0 || + (current_cpu == "x86" && is_component_build)) { + # In these configurations, ilk file sizes stay low enough that we can + # link incrementally. + ldflags = default_incremental_linking_switch + } else { + ldflags = incremental_linking_off_switch + } +} + +# 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" ] +} + +# Generating order files ------------------------------------------------------- + +config("default_cygprofile_instrumentation") { + if (generate_order_files) { + assert(is_clang, "cygprofile instrumentation only works with clang") + assert(is_official_build, "order files should be made w/ official builds") + assert(!is_chrome_branded, "order files could leak internal symbol names") + configs = [ ":cygprofile_instrumentation" ] + } +} + +config("cygprofile_instrumentation") { + cflags = [ + "-Xclang", + "-finstrument-functions-after-inlining", + ] +} diff --git a/deps/v8/build/config/win/console_app.gni b/deps/v8/build/config/win/console_app.gni new file mode 100644 index 0000000000..cac2ef5d73 --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/win/manifest.gni b/deps/v8/build/config/win/manifest.gni new file mode 100644 index 0000000000..b18a4a1412 --- /dev/null +++ b/deps/v8/build/config/win/manifest.gni @@ -0,0 +1,112 @@ +# 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" + +# 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/deps/v8/build/config/win/visual_studio_version.gni b/deps/v8/build/config/win/visual_studio_version.gni new file mode 100644 index 0000000000..982fbe8d3f --- /dev/null +++ b/deps/v8/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/deps/v8/build/config/zip.gni b/deps/v8/build/config/zip.gni new file mode 100644 index 0000000000..58cb692f71 --- /dev/null +++ b/deps/v8/build/config/zip.gni @@ -0,0 +1,50 @@ +# 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), + ] + } + } +} |