diff options
Diffstat (limited to 'third_party/libwebrtc/build/config/mac')
8 files changed, 1026 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/config/mac/BUILD.gn b/third_party/libwebrtc/build/config/mac/BUILD.gn new file mode 100644 index 0000000000..032c77ee34 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/BUILD.gn @@ -0,0 +1,136 @@ +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/apple/symbols.gni") +import("//build/config/c++/c++.gni") +import("//build/config/mac/mac_sdk.gni") +import("//build/config/sysroot.gni") + +# This is included by reference in the //build/config/compiler config that +# is applied to all targets. It is here to separate out the logic. +config("compiler") { + # These flags are shared between the C compiler and linker. + common_mac_flags = [] + + # CPU architecture. + if (target_cpu == "x64") { + clang_arch = "x86_64" + } else if (target_cpu == "x86") { + clang_arch = "i386" + } else if (target_cpu == "arm64") { + clang_arch = target_cpu + } else { + assert(false, "unknown target_cpu $target_cpu") + } + if (host_os == "mac") { + common_mac_flags += [ + "-arch", + clang_arch, + ] + } else { + common_mac_flags += [ "--target=$clang_arch-apple-macos" ] + } + + # This is here so that all files get recompiled after an Xcode update. + # (defines are passed via the command line, and build system rebuild things + # when their commandline changes). Nothing should ever read this define. + defines = [ "CR_XCODE_VERSION=$xcode_version" ] + + asmflags = common_mac_flags + cflags = common_mac_flags + + # Without this, the constructors and destructors of a C++ object inside + # an Objective C struct won't be called, which is very bad. + cflags_objcc = [ "-fobjc-call-cxx-cdtors" ] + + ldflags = common_mac_flags + + if (save_unstripped_output) { + ldflags += [ "-Wcrl,unstripped," + rebase_path(root_out_dir) ] + } + + if (export_libcxxabi_from_executables) { + ldflags += [ "-Wl,-undefined,dynamic_lookup" ] + } +} + +# This is included by reference in the //build/config/compiler:runtime_library +# config that is applied to all targets. It is here to separate out the logic +# that is Mac-only. Please see that target for advice on what should go in +# :runtime_library vs. :compiler. +config("runtime_library") { + common_flags = [ + "-isysroot", + rebase_path(sysroot, root_build_dir), + "-mmacosx-version-min=$mac_deployment_target", + ] + + asmflags = common_flags + cflags = common_flags + ldflags = common_flags + + # Prevent Mac OS X AssertMacros.h (included by system header) from defining + # macros that collide with common names, like 'check', 'require', and + # 'verify'. + # http://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/AssertMacros.h + defines = [ "__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0" ] +} + +# On Mac, this is used for everything except static libraries. +config("mac_dynamic_flags") { + ldflags = [ "-Wl,-ObjC" ] # Always load Objective-C categories and classes. + + if (is_component_build) { + ldflags += [ + # Path for loading shared libraries for unbundled binaries. + "-Wl,-rpath,@loader_path/.", + + # Path for loading shared libraries for bundled binaries. Get back from + # Binary.app/Contents/MacOS. + "-Wl,-rpath,@loader_path/../../..", + ] + } +} + +# The ldflags referenced below are handled by +# //build/toolchain/apple/linker_driver.py. +# Remove this config if a target wishes to change the arguments passed to the +# strip command during linking. This config by default strips all symbols +# from a binary, but some targets may wish to specify an exports file to +# preserve specific symbols. +config("strip_all") { + if (enable_stripping) { + ldflags = [ "-Wcrl,strip,-x,-S" ] + } +} + +# When building with Goma, all inputs must be relative to the build directory. +# If using the system Xcode, which typically resides outside the build root, a +# symlink to the SDK is created in the build directory, and the path to that +# link is stored in $mac_sdk_path. If an action references a file in the SDK as +# an input, GN will complain that no target generates the file because it is +# below the $root_build_dir. The below action lists as outputs the files in the +# SDK that are referenced as inputs to actions, so that GN thinks a target has +# generated them. The list is centralized here, as multiple targets need to +# reference the same files, and an output can only be generated once. +# +# The symbolic link for $mac_sdk_path is set up by +# //build/config/apple/sdk_info.py in //build/config/mac/mac_sdk.gni. +if (use_system_xcode && use_goma && target_os == "mac" && + current_toolchain == default_toolchain) { + action("sdk_inputs") { + script = "//build/noop.py" + outputs = [ + "$mac_sdk_path/usr/include/mach/exc.defs", + "$mac_sdk_path/usr/include/mach/mach_exc.defs", + "$mac_sdk_path/usr/include/mach/notify.defs", + ] + } +} else { + group("sdk_inputs") { + if (current_toolchain != default_toolchain) { + public_deps = [ ":sdk_inputs($default_toolchain)" ] + } + } +} diff --git a/third_party/libwebrtc/build/config/mac/BuildInfo.plist b/third_party/libwebrtc/build/config/mac/BuildInfo.plist new file mode 100644 index 0000000000..bfa3b8d573 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/BuildInfo.plist @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DTCompiler</key> + <string>${GCC_VERSION}</string> + <key>DTSDKBuild</key> + <string>${MAC_SDK_BUILD}</string> + <key>DTSDKName</key> + <string>${MAC_SDK_NAME}</string> + <key>DTXcode</key> + <string>${XCODE_VERSION}</string> + <key>DTXcodeBuild</key> + <string>${XCODE_BUILD}</string> +</dict> +</plist> diff --git a/third_party/libwebrtc/build/config/mac/OWNERS b/third_party/libwebrtc/build/config/mac/OWNERS new file mode 100644 index 0000000000..6f3324f07c --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/OWNERS @@ -0,0 +1 @@ +file://build/apple/OWNERS diff --git a/third_party/libwebrtc/build/config/mac/mac_sdk.gni b/third_party/libwebrtc/build/config/mac/mac_sdk.gni new file mode 100644 index 0000000000..6671893ae8 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/mac_sdk.gni @@ -0,0 +1,127 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/chrome_build.gni") +import("//build/config/gclient_args.gni") +import("//build/config/mac/mac_sdk_overrides.gni") +import("//build/toolchain/goma.gni") +import("//build/toolchain/toolchain.gni") + +assert(current_os == "mac" || current_toolchain == default_toolchain) + +declare_args() { + # The MACOSX_DEPLOYMENT_TARGET variable used when compiling. This partially + # controls the minimum supported version of macOS for Chromium by + # affecting the symbol availability rules. This may differ from + # mac_min_system_version when dropping support for older macOSes but where + # additional code changes are required to be compliant with the availability + # rules. + # Must be of the form x.x.x for Info.plist files. + mac_deployment_target = "10.11.0" + + # The value of the LSMinimmumSystemVersion in Info.plist files. This partially + # controls the minimum supported version of macOS for Chromium by + # affecting the Info.plist. This may differ from mac_deployment_target when + # dropping support for older macOSes. This should be greater than or equal to + # the mac_deployment_target version. + # Must be of the form x.x.x for Info.plist files. + mac_min_system_version = "10.11.0" + + # Path to a specific version of the Mac SDK, not including a slash at the end. + # If empty, the path to the lowest version greater than or equal to + # mac_sdk_min is used. + mac_sdk_path = "" + + # The SDK name as accepted by xcodebuild. + mac_sdk_name = "macosx" + + # The SDK version used when making official builds. This is a single exact + # version, not a minimum. If this version isn't available official builds + # will fail. + mac_sdk_official_version = "11.3" + + # Production builds should use hermetic Xcode. If you want to do production + # builds with system Xcode to test new SDKs, set this. + # Don't set this on any bots. + mac_allow_system_xcode_for_official_builds_for_testing = false +} + +# Check that the version of macOS SDK used is the one requested when building +# a version of Chrome shipped to the users. Disable the check if building for +# iOS as the version macOS SDK used is not relevant for the tool build for the +# host (they are not shipped) --- this is required as Chrome on iOS is usually +# build with the latest version of Xcode that may not ship with the version of +# the macOS SDK used to build Chrome on mac. +# TODO(crbug.com/635745): the check for target_os should be replaced by a +# check that current_toolchain is default_toolchain, and the file should +# assert that current_os is "mac" once this file is no longer included by +# iOS toolchains. +if (is_chrome_branded && is_official_build && target_os != "ios") { + assert(!use_system_xcode || + mac_allow_system_xcode_for_official_builds_for_testing, + "official branded builds should use hermetic xcode") +} + +# The path to the hermetic install of Xcode. Only relevant when +# use_system_xcode = false. +if (!use_system_xcode) { + _hermetic_xcode_path = "//build/mac_files/xcode_binaries" +} + +script_name = "//build/config/apple/sdk_info.py" +sdk_info_args = [] +if (!use_system_xcode) { + sdk_info_args += [ + "--developer_dir", + rebase_path(_hermetic_xcode_path, "", root_build_dir), + ] +} + +# Goma RBE requires paths relative to source directory. When using system +# Xcode, this is done by creating symbolic links in root_build_dir. +if (use_system_xcode && use_goma) { + sdk_info_args += [ + "--get_sdk_info", + "--create_symlink_at", + "sdk/xcode_links", + ] +} +sdk_info_args += [ mac_sdk_name ] + +#_mac_sdk_result = exec_script(script_name, sdk_info_args, "scope") +#xcode_version = _mac_sdk_result.xcode_version +#xcode_build = _mac_sdk_result.xcode_build +if (mac_sdk_path == "" && use_system_xcode && use_goma) { + mac_sdk_path = _mac_sdk_result.sdk_path +} + +if (use_system_xcode) { + # The tool will print the SDK path on the first line, and the version on the + # second line. + find_sdk_args = [ + "--print_sdk_path", + "--print_bin_path", + mac_sdk_min, + ] + find_sdk_lines = + exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines") + mac_sdk_version = find_sdk_lines[2] + if (mac_sdk_path == "") { + mac_sdk_path = find_sdk_lines[0] + mac_bin_path = find_sdk_lines[1] + } else { + mac_bin_path = find_sdk_lines[1] + } +} else { + mac_sdk_version = mac_sdk_official_version + _dev = _hermetic_xcode_path + "/Contents/Developer" + _sdk = "MacOSX${mac_sdk_version}.sdk" + mac_sdk_path = _dev + "/Platforms/MacOSX.platform/Developer/SDKs/$_sdk" + mac_bin_path = _dev + "/Toolchains/XcodeDefault.xctoolchain/usr/bin/" + + # If we're using hermetic Xcode, then we want the paths to be relative so that + # generated ninja files are independent of the directory location. + # TODO(thakis): Do this at the uses of this variable instead. + mac_bin_path = rebase_path(mac_bin_path, root_build_dir) +} diff --git a/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni b/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni new file mode 100644 index 0000000000..17eb3d9f62 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/mac_sdk_overrides.gni @@ -0,0 +1,16 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file contains arguments that subprojects may choose to override. It +# asserts that those overrides are used, to prevent unused args warnings. + +_sdk_min_from_env = getenv("FORCE_MAC_SDK_MIN") +declare_args() { + # Minimum supported version of the Mac SDK. + if (_sdk_min_from_env == "") { + mac_sdk_min = "10.15" + } else { + mac_sdk_min = _sdk_min_from_env + } +} diff --git a/third_party/libwebrtc/build/config/mac/package_framework.py b/third_party/libwebrtc/build/config/mac/package_framework.py new file mode 100644 index 0000000000..0026f466b4 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/package_framework.py @@ -0,0 +1,60 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import argparse +import errno +import os +import shutil +import sys + +def Main(): + parser = argparse.ArgumentParser(description='Create Mac Framework symlinks') + parser.add_argument('--framework', action='store', type=str, required=True) + parser.add_argument('--version', action='store', type=str) + parser.add_argument('--contents', action='store', type=str, nargs='+') + parser.add_argument('--stamp', action='store', type=str, required=True) + args = parser.parse_args() + + VERSIONS = 'Versions' + CURRENT = 'Current' + + # Ensure the Foo.framework/Versions/A/ directory exists and create the + # Foo.framework/Versions/Current symlink to it. + if args.version: + try: + os.makedirs(os.path.join(args.framework, VERSIONS, args.version), 0o755) + except OSError as e: + if e.errno != errno.EEXIST: + raise e + _Relink(os.path.join(args.version), + os.path.join(args.framework, VERSIONS, CURRENT)) + + # Establish the top-level symlinks in the framework bundle. The dest of + # the symlinks may not exist yet. + if args.contents: + for item in args.contents: + _Relink(os.path.join(VERSIONS, CURRENT, item), + os.path.join(args.framework, item)) + + # Write out a stamp file. + if args.stamp: + with open(args.stamp, 'w') as f: + f.write(str(args)) + + return 0 + + +def _Relink(dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + try: + os.remove(link) + except OSError as e: + if e.errno != errno.ENOENT: + shutil.rmtree(link) + os.symlink(dest, link) + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/third_party/libwebrtc/build/config/mac/prepare_framework_version.py b/third_party/libwebrtc/build/config/mac/prepare_framework_version.py new file mode 100644 index 0000000000..db92150698 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/prepare_framework_version.py @@ -0,0 +1,42 @@ +# Copyright 2016 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import shutil +import sys + +# Ensures that the current version matches the last-produced version, which is +# stored in the version_file. If it does not, then the framework_root_dir is +# obliterated. +# Usage: python prepare_framework_version.py out/obj/version_file \ +# out/Framework.framework \ +# 'A' + +def PrepareFrameworkVersion(version_file, framework_root_dir, version): + # Test what the current framework version is. Stop if it is up-to-date. + try: + with open(version_file, 'r') as f: + current_version = f.read() + if current_version == version: + return + except IOError: + pass + + # The framework version has changed, so clobber the framework. + if os.path.exists(framework_root_dir): + shutil.rmtree(framework_root_dir) + + # Write out the new framework version file, making sure its containing + # directory exists. + dirname = os.path.dirname(version_file) + if not os.path.isdir(dirname): + os.makedirs(dirname, 0o700) + + with open(version_file, 'w+') as f: + f.write(version) + + +if __name__ == '__main__': + PrepareFrameworkVersion(sys.argv[1], sys.argv[2], sys.argv[3]) + sys.exit(0) diff --git a/third_party/libwebrtc/build/config/mac/rules.gni b/third_party/libwebrtc/build/config/mac/rules.gni new file mode 100644 index 0000000000..7753a97fe7 --- /dev/null +++ b/third_party/libwebrtc/build/config/mac/rules.gni @@ -0,0 +1,628 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/apple/apple_info_plist.gni") +import("//build/config/apple/symbols.gni") +import("//build/config/mac/mac_sdk.gni") + +# Generates Info.plist files for Mac apps and frameworks. +# +# Arguments +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# executable_name: +# string, name of the generated target used for the product +# and executable name as specified in the output Info.plist. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +template("mac_info_plist") { + assert(defined(invoker.info_plist) != defined(invoker.info_plist_target), + "Only one of info_plist or info_plist_target may be specified in " + + target_name) + + if (defined(invoker.info_plist)) { + _info_plist = invoker.info_plist + } else { + _info_plist_target_output = get_target_outputs(invoker.info_plist_target) + _info_plist = _info_plist_target_output[0] + } + + apple_info_plist(target_name) { + format = "xml1" + extra_substitutions = [] + if (defined(invoker.extra_substitutions)) { + extra_substitutions = invoker.extra_substitutions + } + extra_substitutions += [ + "MAC_SDK_BUILD=$mac_sdk_version", + "MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version", + "MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target", + "CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version", + "XCODE_BUILD=$xcode_build", + "XCODE_VERSION=$xcode_version", + ] + plist_templates = [ + "//build/config/mac/BuildInfo.plist", + _info_plist, + ] + if (defined(invoker.info_plist_target)) { + deps = [ invoker.info_plist_target ] + } + forward_variables_from(invoker, + [ + "testonly", + "executable_name", + ]) + } +} + +# Template to package a shared library into a Mac framework bundle. +# +# By default, the bundle target this template generates does not link the +# resulting framework into anything that depends on it. If a dependency wants +# a link-time (as well as build-time) dependency on the framework bundle, +# depend against "$target_name+link". If only the build-time dependency is +# required (e.g., for copying into another bundle), then use "$target_name". +# +# Arguments +# +# framework_version: +# string, version of the framework. Typically this is a +# single letter, like "A". +# +# framework_contents: +# list of string, top-level items in the framework. This is +# the list of symlinks to create in the .framework directory that link +# into Versions/Current/. +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# output_name: +# (optional) string, name of the generated framework without the +# .framework suffix. If omitted, defaults to target_name. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +# +# This template provides three targets for the resulting framework bundle. The +# link-time behavior varies depending on which of the two targets below is +# added as a dependency: +# - $target_name only adds a build-time dependency. Targets that depend on +# it will not link against the framework. +# - $target_name+link adds a build-time and link-time dependency. Targets +# that depend on it will link against the framework. +# - $target_name+link_nested adds a build-time and link-time dependency, but +# only on the shared library and not the fully-assembled framework bundle. +# This should only be used for other nested binary components of the +# framework bundle (e.g. Helpers) that themselves depend on the main shared +# library of the framework bundle. +# +# The build-time-only dependency is used for when a target needs to use the +# framework either only for resources, or because the target loads it at run- +# time, via dlopen() or NSBundle. The link-time dependency will cause the +# dependee to have the framework loaded by dyld at launch. +# +# Example of build-time only dependency: +# +# mac_framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# The GoatTeleporter.app will not directly link against +# CoreTeleportation.framework, but it will be included in the bundle's +# Frameworks directory. +# +# Example of link-time dependency: +# +# mac_framework_bundle("CoreTeleportation") { +# sources = [ ... ] +# ldflags = [ +# "-install_name", +# "@executable_path/../Frameworks/$target_name.framework" +# ] +# } +# +# bundle_data("core_teleportation_bundle_data") { +# deps = [ ":CoreTeleportation+link" ] +# sources = [ "$root_out_dir/CoreTeleportation.framework" ] +# outputs = [ "{{bundle_contents_dir}}/Frameworks/{{source_file_part}}" ] +# } +# +# app_bundle("GoatTeleporter") { +# sources = [ ... ] +# deps = [ +# ":core_teleportation_bundle_data", +# ] +# } +# +# Note that the framework is still copied to the app's bundle, but dyld will +# load this library when the app is launched because it uses the "+link" +# target as a dependency. This also requires that the framework set its +# install_name so that dyld can locate it. +# +# See "gn help shared_library" for more information on arguments supported +# by shared library target. +template("mac_framework_bundle") { + assert(defined(invoker.deps) || defined(invoker.public_deps), + "Dependencies must be specified for $target_name") + assert(invoker.framework_version != "", "framework_version is required") + assert(defined(invoker.framework_contents), "framework_contents is required") + + _info_plist_target = target_name + "_info_plist" + + mac_info_plist(_info_plist_target) { + executable_name = target_name + if (defined(invoker.output_name)) { + executable_name = invoker.output_name + } + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + "testonly", + ]) + } + + _info_plist_bundle_data = _info_plist_target + "_bundle_data" + + bundle_data(_info_plist_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_resources_dir}}/Info.plist" ] + public_deps = [ ":$_info_plist_target" ] + } + + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + # Create a file to track the build dependency on the framework_version and + # framework_contents variables. + _framework_toc = [ + "Version=" + invoker.framework_version, + _output_name, + ] + invoker.framework_contents + _framework_contents = [ _output_name ] + invoker.framework_contents + _framework_toc_file = "$target_out_dir/${target_name}.toc" + write_file(_framework_toc_file, _framework_toc) + + # Create local variables for referencing different parts of the bundle. + _framework_target = _target_name + _framework_name = _output_name + ".framework" + _framework_base_dir = "$root_out_dir/$_framework_name" + _framework_root_dir = + _framework_base_dir + "/Versions/${invoker.framework_version}" + + # Clean the entire framework if the framework_version changes. + _version_file = "$target_out_dir/${target_name}_version" + exec_script("//build/config/mac/prepare_framework_version.py", + [ + rebase_path(_version_file), + rebase_path(_framework_base_dir), + invoker.framework_version, + ]) + + # Create the symlinks. + _framework_package_target = target_name + "_package" + action(_framework_package_target) { + script = "//build/config/mac/package_framework.py" + + # The TOC file never needs to be read, since its contents are the values + # of GN variables. It is only used to trigger this rule when the values + # change. + inputs = [ _framework_toc_file ] + + _stamp_file = "$target_out_dir/run_${_framework_package_target}.stamp" + outputs = [ _stamp_file ] + + visibility = [ ":$_framework_target" ] + + args = [ + "--framework", + rebase_path(_framework_base_dir, root_build_dir), + "--stamp", + rebase_path(_stamp_file, root_build_dir), + "--version", + invoker.framework_version, + "--contents", + ] + _framework_contents + + # It is not possible to list _framework_contents as outputs, since + # ninja does not properly stat symbolic links. + # https://github.com/ninja-build/ninja/issues/1186 + } + + _link_shared_library_target = target_name + "_shared_library" + _shared_library_bundle_data = target_name + "_shared_library_bundle_data" + + shared_library(_link_shared_library_target) { + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "bundle_deps", + "code_signing_enabled", + "data_deps", + "info_plist", + "info_plist_target", + "output_name", + "visibility", + ]) + visibility = [ + ":$_shared_library_bundle_data", + ":${_framework_target}+link_nested", + ] + output_name = _output_name + output_prefix_override = true + output_extension = "" + output_dir = "$target_out_dir/$_link_shared_library_target" + } + + bundle_data(_shared_library_bundle_data) { + visibility = [ ":$_framework_target" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = [ "$target_out_dir/$_link_shared_library_target/$_output_name" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_link_shared_library_target" ] + } + + _framework_public_config = _target_name + "_public_config" + config(_framework_public_config) { + visibility = [ ":$_framework_target+link" ] + framework_dirs = [ root_out_dir ] + frameworks = [ _framework_name ] + } + + create_bundle(_framework_target) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + ]) + + if (defined(invoker.visibility)) { + visibility = invoker.visibility + visibility += [ ":$_target_name+link" ] + } + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_info_plist_bundle_data" ] + + if (defined(invoker.bundle_deps)) { + deps += invoker.bundle_deps + } + + if (!defined(public_deps)) { + public_deps = [] + } + public_deps += [ + ":$_framework_package_target", + ":$_shared_library_bundle_data", + ] + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name", + ] + } + + bundle_root_dir = _framework_base_dir + bundle_contents_dir = _framework_root_dir + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = bundle_contents_dir + } + + group(_target_name + "+link") { + forward_variables_from(invoker, + [ + "public_configs", + "testonly", + "visibility", + ]) + public_deps = [ ":$_target_name" ] + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":$_framework_public_config" ] + } + + group(_target_name + "+link_nested") { + forward_variables_from(invoker, + [ + "public_configs", + "testonly", + "visibility", + ]) + + # Depend only on the shared library. Nested code will be a dependency of + # the create_bundle target, which would be cyclic with depending on the + # framework itself. This is sufficient to link; for loading, a proper + # install_name should be set. + public_deps = [ ":$_link_shared_library_target" ] + } +} + +set_defaults("mac_framework_bundle") { + configs = default_shared_library_configs +} + +# Template to create a Mac executable application bundle. +# +# Arguments +# +# package_type: +# (optional) string, the product package type to create. Options are: +# "app" to create a .app bundle (default) +# "xpc" to create an .xpc service bundle +# +# info_plist: +# (optional) string, path to the Info.plist file that will be used for +# the bundle. +# +# info_plist_target: +# (optional) string, if the info_plist is generated from an action, +# rather than a regular source file, specify the target name in lieu +# of info_plist. The two arguments are mutually exclusive. +# +# output_name: +# (optional) string, name of the generated app without the +# .app suffix. If omitted, defaults to target_name. +# +# extra_configs: +# (optional) list of label, additional configs to apply to the +# executable target. +# +# remove_configs: +# (optional) list of label, default configs to remove from the target. +# +# extra_substitutions: +# (optional) string array, 'key=value' pairs for extra fields which are +# specified in a source Info.plist template. +template("mac_app_bundle") { + _target_name = target_name + _output_name = target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _package_type = "app" + if (defined(invoker.package_type)) { + _package_type = invoker.package_type + } + + if (_package_type == "app") { + _output_extension = "app" + _product_type = "com.apple.product-type.application" + _write_pkg_info = true + } else if (_package_type == "xpc") { + _output_extension = "xpc" + _product_type = "com.apple.product-type.xpc-service" + _write_pkg_info = false + } else if (_package_type == "bundle") { + _output_extension = "bundle" + _product_type = "com.apple.product-type.bundle" + _write_pkg_info = false + } else { + assert(false, "Unsupported packge_type: " + packge_type) + } + + _executable_target = target_name + "_executable" + _executable_bundle_data = _executable_target + "_bundle_data" + + _info_plist_target = target_name + "_info_plist" + + mac_info_plist(_info_plist_target) { + executable_name = _output_name + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + "testonly", + ]) + } + + if (_write_pkg_info) { + _pkg_info_target = target_name + "_pkg_info" + + action(_pkg_info_target) { + forward_variables_from(invoker, [ "testonly" ]) + script = "//build/apple/write_pkg_info.py" + inputs = [ "//build/apple/plist_util.py" ] + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "$target_gen_dir/$_pkg_info_target" ] + args = [ "--plist" ] + rebase_path(sources, root_build_dir) + + [ "--output" ] + rebase_path(outputs, root_build_dir) + deps = [ ":$_info_plist_target" ] + } + } + + executable(_executable_target) { + visibility = [ ":$_executable_bundle_data" ] + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "data_deps", + "info_plist", + "output_name", + "visibility", + ]) + if (defined(extra_configs)) { + configs += extra_configs + } + if (defined(remove_configs)) { + configs -= remove_configs + } + output_name = _output_name + output_dir = "$target_out_dir/$_executable_target" + } + + bundle_data(_executable_bundle_data) { + visibility = [ ":$_target_name" ] + forward_variables_from(invoker, [ "testonly" ]) + sources = [ "$target_out_dir/$_executable_target/$_output_name" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_executable_target" ] + } + + _info_plist_bundle_data = _info_plist_target + "_bundle_data" + + bundle_data(_info_plist_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = get_target_outputs(":$_info_plist_target") + outputs = [ "{{bundle_contents_dir}}/Info.plist" ] + public_deps = [ ":$_info_plist_target" ] + } + + if (_write_pkg_info) { + _pkg_info_bundle_data = _pkg_info_target + "_bundle_data" + + bundle_data(_pkg_info_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = get_target_outputs(":$_pkg_info_target") + outputs = [ "{{bundle_contents_dir}}/PkgInfo" ] + public_deps = [ ":$_pkg_info_target" ] + } + } + + create_bundle(_target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + ]) + if (!defined(deps)) { + deps = [] + } + deps += [ + ":$_executable_bundle_data", + ":$_info_plist_bundle_data", + ] + if (_write_pkg_info) { + deps += [ ":$_pkg_info_bundle_data" ] + } + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.dSYM/Contents/Resources/DWARF/$_output_name", + ] + } + + product_type = _product_type + bundle_root_dir = "$root_out_dir/${_output_name}.${_output_extension}" + bundle_contents_dir = "$bundle_root_dir/Contents" + bundle_resources_dir = "$bundle_contents_dir/Resources" + bundle_executable_dir = "$bundle_contents_dir/MacOS" + } +} + +# Template to package a loadable_module into a .plugin bundle. +# +# This takes no extra arguments that differ from a loadable_module. +template("mac_plugin_bundle") { + assert(defined(invoker.deps), + "Dependencies must be specified for $target_name") + + _target_name = target_name + _loadable_module_target = _target_name + "_loadable_module" + _loadable_module_bundle_data = _loadable_module_target + "_bundle_data" + + _output_name = _target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + loadable_module(_loadable_module_target) { + visibility = [ ":$_loadable_module_bundle_data" ] + forward_variables_from(invoker, + "*", + [ + "assert_no_deps", + "data_deps", + "output_name", + "visibility", + ]) + output_dir = "$target_out_dir" + output_name = _output_name + } + + bundle_data(_loadable_module_bundle_data) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + sources = [ "$target_out_dir/$_output_name.so" ] + outputs = [ "{{bundle_executable_dir}}/$_output_name" ] + public_deps = [ ":$_loadable_module_target" ] + } + + create_bundle(_target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_loadable_module_bundle_data" ] + + if (enable_dsyms) { + data = [ + "$root_out_dir/$_output_name.so.dSYM/Contents/Info.plist", + "$root_out_dir/$_output_name.so.dSYM/Contents/Resources/DWARF/$_output_name.so", + ] + } + + bundle_root_dir = "$root_out_dir/$_output_name.plugin" + bundle_contents_dir = "$bundle_root_dir/Contents" + bundle_executable_dir = "$bundle_contents_dir/MacOS" + } +} |