# 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") 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 = [ "plutil", "-convert", invoker.format, "-o", rebase_path(invoker.output, root_out_dir), rebase_path(invoker.source, root_out_dir), ] } } # 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. template("info_plist") { assert(defined(invoker.plist_templates), "A list of template plist files must be specified for $target_name") assert(defined(invoker.executable_name), "The executable_name must be specified for $target_name") assert(defined(invoker.format), "The plist format must be specified for $target_name") executable_name = invoker.executable_name action(target_name) { script = "//build/config/mac/gen_plist.py" sources = invoker.plist_templates outputs = [ "$target_gen_dir/$target_name.plist", ] extra_args = [] if (defined(invoker.extra_substitutions)) { foreach(substitution, invoker.extra_substitutions) { extra_args += [ "-s=$substitution" ] } } response_file_contents = extra_args + [ "-s=BUILD_MACHINE_OS_BUILD=$machine_os_build", "-s=EXECUTABLE_NAME=$executable_name", "-s=GCC_VERSION=com.apple.compilers.llvm.clang.1_0", "-s=PRODUCT_NAME=$executable_name", "-s=XCODE_BUILD=$xcode_build", "-s=XCODE_VERSION=$xcode_version", "-o=" + rebase_path(outputs[0], root_build_dir), "-f=" + invoker.format, ] + rebase_path(sources, root_build_dir) args = [ "@{{response_file_name}}" ] forward_variables_from(invoker, [ "deps", "testonly", "visibility", ]) } } # This is used as the base template for both iOS and Mac frameworks. # # 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. # # framework_version: # (optional) string, version of the framework. Typically this is a # single letter, like "A". If omitted, the Versions/ subdirectory # structure will not be created, and build output will go directly # into the framework subdirectory. # # 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_root_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_root_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("framework_bundle") { _target_name = target_name _output_name = target_name if (defined(invoker.output_name)) { _output_name = invoker.output_name } # If the framework is unversioned, the final _target_name will be the # create_bundle(_framework_target), otherwise an action with the name # _target_name will depends on the the create_bundle() in order to prepare # the versioned directory structure. _framework_target = _target_name _framework_name = _output_name + ".framework" _framework_root_dir = "$root_out_dir/$_framework_name" if (defined(invoker.framework_version) && invoker.framework_version != "") { _framework_version = invoker.framework_version _framework_root_dir += "/Versions/$_framework_version" _framework_target = _target_name + "_create_bundle" } _shared_library_target = target_name + "_shared_library" _shared_library_bundle_data = _shared_library_target + "_bundle_data" shared_library(_shared_library_target) { visibility = [ ":$_shared_library_bundle_data" ] forward_variables_from(invoker, "*", [ "assert_no_deps", "data_deps", "info_plist", "output_name", "visibility", ]) output_name = _output_name output_prefix_override = true output_extension = "" output_dir = "$target_out_dir/$_shared_library_target" } bundle_data(_shared_library_bundle_data) { visibility = [ ":$_framework_target" ] forward_variables_from(invoker, [ "testonly" ]) sources = [ "$target_out_dir/$_shared_library_target/$_output_name", ] outputs = [ "{{bundle_executable_dir}}/$_output_name", ] public_deps = [ ":$_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" ] ldflags = [ "-F" + rebase_path("$root_out_dir/.", root_out_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(_framework_version)) { visibility = [ ":$_target_name" ] } else { if (defined(invoker.visibility)) { visibility = invoker.visibility visibility += [ ":$_target_name+link" ] } } if (!defined(public_deps)) { public_deps = [] } public_deps += [ ":$_shared_library_bundle_data" ] bundle_root_dir = _framework_root_dir bundle_resources_dir = "$bundle_root_dir/Resources" bundle_executable_dir = "$bundle_root_dir" } if (defined(_framework_version)) { action(_target_name) { forward_variables_from(invoker, [ "testonly" ]) if (defined(invoker.visibility)) { visibility = invoker.visibility visibility += [ ":$_target_name+link" ] } script = "$root_out_dir/gyp-mac-tool" outputs = [ "$root_out_dir/$_framework_name/Versions/Current", ] args = [ "package-framework", "$_framework_name", "$_framework_version", ] public_deps = [ ":$_framework_target", ] } } group(_target_name + "+link") { forward_variables_from(invoker, [ "visibility", "testonly", ]) public_deps = [ ":$_target_name", ] public_configs = [ ":$_framework_public_config" ] } } # Template to combile .xib or .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_xibs") { action_foreach(target_name) { forward_variables_from(invoker, [ "testonly", "visibility", ]) assert(defined(invoker.sources), "Sources must be specified for $target_name") ibtool_flags = [] if (defined(invoker.ibtool_flags)) { ibtool_flags = invoker.ibtool_flags } script = "//build/config/mac/compile_xib.py" sources = invoker.sources outputs = [ "$target_gen_dir/{{source_name_part}}.nib", ] args = [ "--input", "{{source}}", "--output", rebase_path("$target_gen_dir/{{source_name_part}}.nib"), ] + ibtool_flags } }