diff --git a/apple/internal/ios_rules.bzl b/apple/internal/ios_rules.bzl index 1754d3413..7bd36d2b3 100644 --- a/apple/internal/ios_rules.bzl +++ b/apple/internal/ios_rules.bzl @@ -20,6 +20,7 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "SwiftInfo") load( "//apple:providers.bzl", "AppleBundleInfo", + "AppleBundleVersionInfo", "AppleFrameworkImportInfo", "ApplePlatformInfo", "IosAppClipBundleInfo", @@ -86,6 +87,7 @@ load( load( "//apple/internal:providers.bzl", "merge_apple_framework_import_info", + "new_applebinaryinfo", "new_appleexecutablebinaryinfo", "new_appleframeworkbundleinfo", "new_iosappclipbundleinfo", @@ -1438,6 +1440,125 @@ def _ios_extension_impl(ctx): link_result.debug_outputs_provider, ] + processor_result.providers +def _ios_dylib_impl(ctx): + """Implementation of the ios_dylib rule.""" + rule_descriptor = rule_support.rule_descriptor( + platform_type = ctx.attr.platform_type, + product_type = apple_product_type.dylib, + ) + + actions = ctx.actions + apple_mac_toolchain_info = ctx.attr._mac_toolchain[AppleMacToolsToolchainInfo] + apple_xplat_toolchain_info = ctx.attr._xplat_toolchain[AppleXPlatToolsToolchainInfo] + + bundle_name, bundle_extension = bundling_support.bundle_full_name( + custom_bundle_name = None, # ios_dylib doesn't support this override. + label_name = ctx.label.name, + rule_descriptor = rule_descriptor, + ) + cc_toolchain_forwarder = ctx.split_attr._cc_toolchain_forwarder + features = features_support.compute_enabled_features( + requested_features = ctx.features, + unsupported_features = ctx.disabled_features, + ) + label = ctx.label + platform_prerequisites = platform_support.platform_prerequisites( + apple_fragment = ctx.fragments.apple, + build_settings = apple_xplat_toolchain_info.build_settings, + config_vars = ctx.var, + cpp_fragment = ctx.fragments.cpp, + device_families = rule_descriptor.allowed_device_families, + explicit_minimum_deployment_os = ctx.attr.minimum_deployment_os_version, + explicit_minimum_os = ctx.attr.minimum_os_version, + features = features, + objc_fragment = ctx.fragments.objc, + platform_type_string = ctx.attr.platform_type, + uses_swift = swift_support.uses_swift(ctx.attr.deps), + xcode_version_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig], + ) + predeclared_outputs = ctx.outputs + provisioning_profile = ctx.file.provisioning_profile + + link_result = linking_support.register_binary_linking_action( + ctx, + cc_toolchains = cc_toolchain_forwarder, + # dylibs do not have entitlements. + entitlements = None, + exported_symbols_lists = ctx.files.exported_symbols_lists, + extra_linkopts = ["-dynamiclib"], + platform_prerequisites = platform_prerequisites, + rule_descriptor = rule_descriptor, + stamp = ctx.attr.stamp, + ) + binary_artifact = link_result.binary + debug_outputs = linking_support.debug_outputs_by_architecture(link_result.outputs) + + debug_outputs_partial = partials.debug_symbols_partial( + actions = actions, + bundle_extension = bundle_extension, + bundle_name = bundle_name, + dsym_binaries = debug_outputs.dsym_binaries, + dsym_info_plist_template = apple_mac_toolchain_info.dsym_info_plist_template, + label_name = label.name, + linkmaps = debug_outputs.linkmaps, + platform_prerequisites = platform_prerequisites, + plisttool = apple_mac_toolchain_info.plisttool, + rule_label = label, + version = ctx.attr.version, + ) + + processor_result = processor.process( + actions = actions, + apple_mac_toolchain_info = apple_mac_toolchain_info, + apple_xplat_toolchain_info = apple_xplat_toolchain_info, + bundle_extension = bundle_extension, + bundle_name = bundle_name, + bundle_post_process_and_sign = False, + codesign_inputs = ctx.files.codesign_inputs, + codesignopts = codesigning_support.codesignopts_from_rule_ctx(ctx), + features = features, + ipa_post_processor = None, + partials = [debug_outputs_partial], + platform_prerequisites = platform_prerequisites, + predeclared_outputs = predeclared_outputs, + process_and_sign_template = apple_mac_toolchain_info.process_and_sign_template, + provisioning_profile = provisioning_profile, + rule_descriptor = rule_descriptor, + rule_label = label, + ) + output_file = actions.declare_file(label.name + ".dylib") + codesigning_support.sign_binary_action( + actions = actions, + codesign_inputs = ctx.files.codesign_inputs, + codesigningtool = apple_mac_toolchain_info.codesigningtool, + codesignopts = codesigning_support.codesignopts_from_rule_ctx(ctx), + input_binary = binary_artifact, + output_binary = output_file, + platform_prerequisites = platform_prerequisites, + provisioning_profile = provisioning_profile, + rule_descriptor = rule_descriptor, + ) + + return [ + new_applebinaryinfo( + binary = output_file, + product_type = rule_descriptor.product_type, + ), + DefaultInfo(files = depset(transitive = [ + depset([output_file]), + processor_result.output_files, + ])), + OutputGroupInfo( + **outputs.merge_output_groups( + link_result.output_groups, + processor_result.output_groups, + {"dylib": depset(direct = [output_file])}, + ) + ), + # TODO(b/228856372): Remove when downstream users are migrated off this provider. + link_result.debug_outputs_provider, + ] + processor_result.providers + def _ios_dynamic_framework_impl(ctx): """Experimental implementation of ios_dynamic_framework.""" rule_descriptor = rule_support.rule_descriptor( @@ -2881,6 +3002,44 @@ use only extension-safe APIs. ], ) +ios_dylib = rule_factory.create_apple_rule( + doc = "Builds a iOS Dylib binary.", + implementation = _ios_dylib_impl, + attrs = [ + rule_attrs.binary_linking_attrs( + deps_cfg = transition_support.apple_platform_split_transition, + extra_deps_aspects = [ + apple_resource_aspect, + framework_provider_aspect, + ], + is_test_supporting_rule = False, + requires_legacy_cc_toolchain = True, + ), + rule_attrs.common_tool_attrs(), + rule_attrs.device_family_attrs( + allowed_families = rule_attrs.defaults.allowed_families.ios, + ), + rule_attrs.custom_transition_allowlist_attr(), + rule_attrs.platform_attrs( + add_environment_plist = True, + platform_type = "ios", + ), + rule_attrs.signing_attrs( + supports_capabilities = False, + profile_extension = ".provisionprofile", + ), + { + "version": attr.label( + providers = [[AppleBundleVersionInfo]], + doc = """ +An `apple_bundle_version` target that represents the version for this target. See +[`apple_bundle_version`](https://github.com/bazelbuild/rules_apple/blob/master/doc/rules-general.md?cl=head#apple_bundle_version). +""", + ), + }, + ], +) + ios_dynamic_framework = rule_factory.create_apple_rule( doc = "Builds and bundles an iOS dynamic framework that is consumable by Xcode.", implementation = _ios_dynamic_framework_impl, diff --git a/apple/internal/rule_support.bzl b/apple/internal/rule_support.bzl index 5d9ed05f3..a905084b0 100644 --- a/apple/internal/rule_support.bzl +++ b/apple/internal/rule_support.bzl @@ -176,6 +176,12 @@ _RULE_TYPE_DESCRIPTORS = { "@executable_path/Frameworks", ], ), + apple_product_type.dylib: _describe_rule_type( + allowed_device_families = ["iphone", "ipad"], + bundle_extension = "", + product_type = apple_product_type.dylib, + requires_signing_for_device = True, + ), # ios_extension (NSExtension) apple_product_type.app_extension: _describe_rule_type( allowed_device_families = ["iphone", "ipad"], diff --git a/apple/ios.bzl b/apple/ios.bzl index 2e922ed5f..467f37dd6 100644 --- a/apple/ios.bzl +++ b/apple/ios.bzl @@ -18,6 +18,7 @@ load( "//apple/internal:ios_rules.bzl", _ios_app_clip = "ios_app_clip", _ios_application = "ios_application", + _ios_dylib = "ios_dylib", _ios_dynamic_framework = "ios_dynamic_framework", _ios_extension = "ios_extension", _ios_framework = "ios_framework", @@ -47,6 +48,7 @@ ios_application = _ios_application ios_app_clip = _ios_app_clip ios_dynamic_framework = _ios_dynamic_framework ios_extension = _ios_extension +ios_dylib = _ios_dylib ios_framework = _ios_framework ios_imessage_application = _ios_imessage_application ios_sticker_pack_extension = _ios_sticker_pack_extension diff --git a/apple/ios.doc.bzl b/apple/ios.doc.bzl index f54e6bb9d..e82358ec0 100644 --- a/apple/ios.doc.bzl +++ b/apple/ios.doc.bzl @@ -21,6 +21,7 @@ load( "//apple/internal:ios_rules.bzl", _ios_app_clip = "ios_app_clip", _ios_application = "ios_application", + _ios_dylib = "ios_dylib", _ios_dynamic_framework = "ios_dynamic_framework", _ios_extension = "ios_extension", _ios_framework = "ios_framework", @@ -52,6 +53,7 @@ load( ios_app_clip = _ios_app_clip ios_application = _ios_application ios_build_test = _ios_build_test +ios_dylib = _ios_dylib ios_dynamic_framework = _ios_dynamic_framework ios_extension = _ios_extension ios_framework = _ios_framework diff --git a/doc/rules-ios.md b/doc/rules-ios.md index 3c9905fbd..42907e913 100644 --- a/doc/rules-ios.md +++ b/doc/rules-ios.md @@ -151,6 +151,43 @@ ios_build_test( | targets | The targets to check for successful build. | List of labels | optional | `[]` | + + +## ios_dylib + +
+ios_dylib(name, deps, additional_linker_inputs, base_bundle_id, bundle_id, bundle_id_suffix,
+          codesign_inputs, codesignopts, exported_symbols_lists, families, linkopts,
+          minimum_deployment_os_version, minimum_os_version, platform_type, provisioning_profile,
+          stamp, version)
+
+ +Builds a iOS Dylib binary. + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| deps | A list of dependent targets that will be linked into this target's binary(s). Any resources, such as asset catalogs, that are referenced by those targets will also be transitively included in the final bundle(s). | List of labels | optional | `[]` | +| additional_linker_inputs | A list of input files to be passed to the linker. | List of labels | optional | `[]` | +| base_bundle_id | The base bundle ID rule to dictate the form that a given bundle rule's bundle ID prefix should take. | Label | optional | `None` | +| bundle_id | The bundle ID (reverse-DNS path followed by app name) for this target. Only use this attribute if the bundle ID is not intended to be composed through an assigned base bundle ID referenced by `base_bundle_id`. | String | optional | `""` | +| bundle_id_suffix | A string to act as the suffix of the composed bundle ID. If this target's bundle ID is composed from the base bundle ID rule referenced by `base_bundle_id`, then this string will be appended to the end of the bundle ID following a "." separator. | String | optional | `"_"` | +| codesign_inputs | A list of dependencies targets that provide inputs that will be used by `codesign` (referenced with `codesignopts`). | List of labels | optional | `[]` | +| codesignopts | A list of strings representing extra flags that should be passed to `codesign`. | List of strings | optional | `[]` | +| exported_symbols_lists | A list of targets containing exported symbols lists files for the linker to control symbol resolution.

Each file is expected to have a list of global symbol names that will remain as global symbols in the compiled binary owned by this framework. All other global symbols will be treated as if they were marked as `__private_extern__` (aka `visibility=hidden`) and will not be global in the output file.

See the man page documentation for `ld(1)` on macOS for more details. | List of labels | optional | `[]` | +| families | A list of device families supported by this rule. At least one must be specified. | List of strings | optional | `["iphone", "ipad"]` | +| linkopts | A list of strings representing extra flags that should be passed to the linker. | List of strings | optional | `[]` | +| minimum_deployment_os_version | A required string indicating the minimum deployment OS version supported by the target, represented as a dotted version number (for example, "9.0"). This is different from `minimum_os_version`, which is effective at compile time. Ensure version specific APIs are guarded with `available` clauses. | String | optional | `""` | +| minimum_os_version | A required string indicating the minimum OS version supported by the target, represented as a dotted version number (for example, "9.0"). | String | required | | +| platform_type | - | String | optional | `"ios"` | +| provisioning_profile | The provisioning profile (`.provisionprofile` file) to use when creating the bundle. This value is optional for simulator builds as the simulator doesn't fully enforce entitlements, but is required for device builds. | Label | optional | `None` | +| stamp | Enable link stamping. Whether to encode build information into the binary. Possible values:

* `stamp = 1`: Stamp the build information into the binary. Stamped binaries are only rebuilt when their dependencies change. Use this if there are tests that depend on the build information. * `stamp = 0`: Always replace build information by constant values. This gives good build result caching. * `stamp = -1`: Embedding of build information is controlled by the `--[no]stamp` flag. | Integer | optional | `-1` | +| version | An `apple_bundle_version` target that represents the version for this target. See [`apple_bundle_version`](https://github.com/bazelbuild/rules_apple/blob/master/doc/rules-general.md?cl=head#apple_bundle_version). | Label | optional | `None` | + + ## ios_dynamic_framework diff --git a/test/starlark_tests/BUILD b/test/starlark_tests/BUILD index f18ef9a4d..9e78fe49f 100644 --- a/test/starlark_tests/BUILD +++ b/test/starlark_tests/BUILD @@ -18,6 +18,7 @@ load(":generate_import_framework_tests.bzl", "generate_import_framework_test_sui load(":ios_app_clip_tests.bzl", "ios_app_clip_test_suite") load(":ios_application_resources_test.bzl", "ios_application_resources_test_suite") load(":ios_application_tests.bzl", "ios_application_test_suite") +load(":ios_dylib_tests.bzl", "ios_dylib_test_suite") load(":ios_dynamic_framework_tests.bzl", "ios_dynamic_framework_test_suite") load(":ios_extension_tests.bzl", "ios_extension_test_suite") load(":ios_framework_tests.bzl", "ios_framework_test_suite") @@ -103,6 +104,8 @@ ios_extension_test_suite(name = "ios_extension") ios_framework_test_suite(name = "ios_framework") +ios_dylib_test_suite(name = "ios_dylib") + ios_dynamic_framework_test_suite(name = "ios_dynamic_framework") ios_imessage_application_test_suite(name = "ios_imessage_application") diff --git a/test/starlark_tests/ios_dylib_tests.bzl b/test/starlark_tests/ios_dylib_tests.bzl new file mode 100644 index 000000000..4235c86ba --- /dev/null +++ b/test/starlark_tests/ios_dylib_tests.bzl @@ -0,0 +1,91 @@ +# Copyright 2020 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""ios_dylib Starlark tests.""" + +load( + "//test/starlark_tests/rules:analysis_output_group_info_files_test.bzl", + "analysis_output_group_info_files_test", +) +load( + "//test/starlark_tests/rules:apple_dsym_bundle_info_test.bzl", + "apple_dsym_bundle_info_test", +) +load( + "//test/starlark_tests/rules:apple_verification_test.bzl", + "apple_verification_test", +) +load( + "//test/starlark_tests/rules:common_verification_tests.bzl", + "binary_contents_test", +) +load( + "//test/starlark_tests/rules:output_group_test.bzl", + "output_group_test", +) + +def ios_dylib_test_suite(name): + """Test suite for ios_dylib. + + Args: + name: the base name to be used in things created by this macro + """ + apple_verification_test( + name = "{}_codesign_test".format(name), + build_type = "simulator", + target_under_test = "//test/starlark_tests/targets_under_test/ios:dylib", + verifier_script = "verifier_scripts/codesign_verifier.sh", + tags = [name], + ) + + binary_contents_test( + name = "{}_exported_symbols_list_test".format(name), + build_type = "simulator", + target_under_test = "//test/starlark_tests/targets_under_test/ios:dylib_dead_stripped", + binary_test_file = "$BINARY", + compilation_mode = "opt", + binary_test_architecture = "x86_64", + binary_contains_symbols = ["_anotherFunctionShared"], + binary_not_contains_symbols = ["_dontCallMeShared"], + tags = [name], + ) + + analysis_output_group_info_files_test( + name = "{}_dsyms_output_group_files_test".format(name), + target_under_test = "//test/starlark_tests/targets_under_test/ios:dylib", + output_group_name = "dsyms", + expected_outputs = [ + "dylib.dSYM/Contents/Resources/DWARF/dylib", + ], + tags = [name], + ) + apple_dsym_bundle_info_test( + name = "{}_dsym_bundle_info_files_test".format(name), + target_under_test = "//test/starlark_tests/targets_under_test/ios:dylib", + expected_direct_dsyms = ["dSYMs/dylib.dSYM"], + expected_transitive_dsyms = ["dSYMs/dylib.dSYM"], + tags = [name], + ) + + output_group_test( + name = "{}_output_group_test".format(name), + target_under_test = "//test/starlark_tests/targets_under_test/ios:dylib", + expected_output_groups = ["dylib"], + tags = [name], + ) + + native.test_suite( + name = name, + tags = [name], + ) diff --git a/test/starlark_tests/targets_under_test/ios/BUILD b/test/starlark_tests/targets_under_test/ios/BUILD index a1056efa9..a9ccbeaa3 100644 --- a/test/starlark_tests/targets_under_test/ios/BUILD +++ b/test/starlark_tests/targets_under_test/ios/BUILD @@ -18,6 +18,7 @@ load( "//apple:ios.bzl", "ios_app_clip", "ios_application", + "ios_dylib", "ios_dynamic_framework", "ios_extension", "ios_framework", @@ -3719,6 +3720,44 @@ ios_unit_test( ], ) +# --------------------------------------------------------------------------------------- +# Targets for iOS dylib tests. + +ios_dylib( + name = "dylib", + bundle_id = "com.google.example", + minimum_os_version = common.min_os_ios.baseline, + tags = common.fixture_tags, + deps = [ + "//test/starlark_tests/resources:objc_shared_lib", + ], +) + +ios_dylib( + name = "dylib_dead_stripped", + bundle_id = "com.google.example", + exported_symbols_lists = [ + "//test/starlark_tests/resources:ExportAnotherFunctionShared.exp", + ], + linkopts = ["-dead_strip"], + minimum_os_version = common.min_os_ios.baseline, + tags = common.fixture_tags, + deps = [ + "//test/starlark_tests/resources:objc_shared_lib", + ], +) + +ios_dylib( + name = "dylib_with_base_bundle_id_derived_bundle_id", + base_bundle_id = "//test/starlark_tests/targets_under_test/apple/capabilities:base_bundle_id", + bundle_id_suffix = "dylib-with-base-bundle-id-derived-bundle-id", + minimum_os_version = common.min_os_ios.baseline, + tags = common.fixture_tags, + deps = [ + "//test/starlark_tests/resources:objc_shared_lib", + ], +) + # --------------------------------------------------------------------------------------- # Targets for iOS dynamic framework tests.