Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
bazel-rules-swift
bazel-rules-swift-0.13.0.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bazel-rules-swift-0.13.0.obscpio of Package bazel-rules-swift
07070100000000000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002200000000bazel-rules-swift-0.13.0/.bazelci07070100000001000081A4000003E800000064000000015D9E34630000088E000000000000000000000000000000000000003000000000bazel-rules-swift-0.13.0/.bazelci/presubmit.yml--- x_defaults: # YAML has a feature for "repeated nodes", BazelCI is fine with extra nodes # it doesn't know about; so that is used to avoid repeating common subparts. mac_common: &mac_common platform: macos build_targets: - "//examples/..." test_targets: - "//examples/..." linux_common: &linux_common platform: ubuntu1804 environment: CC: clang build_flags: &linux_flags # On Linux, we look for Swift toolchain binaries on the path. We may be # able to change this when we start auto-downloading toolchains (see # https://github.com/bazelbuild/rules_swift/issues/4). - "--action_env=PATH" build_targets: &linux_targets - "--" - "//examples/..." - "-//examples/apple/..." test_flags: *linux_flags test_targets: *linux_targets tasks: macos_latest: name: "Latest Bazel" bazel: latest <<: *mac_common macos_last_green: name: "Last Green Bazel" bazel: last_green <<: *mac_common macos_latest_head_deps: name: "Latest Bazel with Head Deps" bazel: latest shell_commands: # Update the WORKSPACE to use head versions of some deps to ensure nothing # has landed on them breaking this project. - .bazelci/update_workspace_to_deps_heads.sh <<: *mac_common ubuntu1804_latest: name: "Latest Bazel" bazel: latest <<: *linux_common ubuntu1804_last_green: name: "Last Green Bazel" bazel: last_green <<: *linux_common ubuntu1804_latest_head_deps: name: "Latest Bazel with Head Deps" bazel: latest shell_commands: # Update the WORKSPACE to use head versions of some deps to ensure nothing # has landed on them breaking this project. - .bazelci/update_workspace_to_deps_heads.sh <<: *linux_common buildifier: version: latest # Disable 'bzl-visibility' since it doesn't work properly. # https://github.com/bazelbuild/buildtools/issues/718 # TODO(b/140761855): Remove native-cc from this list. # TODO(b/140761855): Remove native-proto from this list. # TODO(b/140761855): Remove native-py from this list. warnings: -bzl-visibility,-native-cc,-native-proto,-native-py 07070100000002000081ED000003E800000064000000015D9E3463000004C6000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/.bazelci/update_workspace_to_deps_heads.sh#!/bin/bash # Copyright 2019 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. set -eu if [[ "$(uname -s)" == "Darwin" ]] ; then INPLACE=("-i" "") else INPLACE=("-i") fi # Modify the WORKSPACE to pull in the master branches of some deps. sed \ "${INPLACE[@]}" \ -e \ '/^workspace.*/a \ \ load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")\ \ git_repository(\ \ name = "bazel_skylib",\ \ remote = "https://github.com/bazelbuild/bazel-skylib.git",\ \ branch = "master",\ )\ \ git_repository(\ \ name = "build_bazel_apple_support",\ \ remote = "https://github.com/bazelbuild/apple_support.git",\ \ branch = "master",\ )\ ' \ WORKSPACE 07070100000003000081A4000003E800000064000000015D9E346300000131000000000000000000000000000000000000002100000000bazel-rules-swift-0.13.0/AUTHORS# This the official list of Bazel authors for copyright purposes. # This file is distinct from the CONTRIBUTORS files. # See the latter for an explanation. # Names should be added to this file as: # Name or Organization <email address> # The email address is not required for organizations. Google Inc. 07070100000004000081A4000003E800000064000000015D9E346300000163000000000000000000000000000000000000001F00000000bazel-rules-swift-0.13.0/BUILDpackage(default_visibility = ["//visibility:public"]) licenses(["notice"]) exports_files(["LICENSE"]) # Consumed by Bazel integration tests (such as those defined in rules_apple). filegroup( name = "for_bazel_tests", testonly = 1, srcs = [ "WORKSPACE", "//swift:for_bazel_tests", "//tools:for_bazel_tests", ], ) 07070100000005000081A4000003E800000064000000015D9E34630000099A000000000000000000000000000000000000002900000000bazel-rules-swift-0.13.0/CONTRIBUTING.md# How to Contribute We'd love to accept your patches and contributions to this project. There are just a few small guidelines you need to follow. ## File or claim an issue Please let us know what you're working on if you want to change or add to the project. Before undertaking something, please file an issue or claim an existing issue. All significant changes/additions should also be discussed before they can be accepted. This gives all participants a chance to validate the design and to avoid duplication of effort. Ensuring that there is an issue for discussion before working on a PR helps everyone provide input/discussion/advice and avoid a PR having to get restarted based on useful feedback. We use [labels](https://github.com/bazelbuild/rules_swift/labels) for the issues and pull requests to help track priorities, things being considered, deferred, etc. A project owner will try to update labels every week or so, as workloads permit. ## Contributor License Agreement Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to <https://cla.developers.google.com/> to see your current agreements on file or to sign a new one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. ## Setting up your development environment To enforce a consistent code style through our code base, we use `buildifier` from the [bazelbuild/buildtools](https://github.com/bazelbuild/buildtools) to format `BUILD` and `*.bzl` files. We also use `buildifier --lint=warn` to check for common issues. You can download `buildifier` from [bazelbuild/buildtools Releases Page](https://github.com/bazelbuild/buildtools/releases). Bazel's CI is configured to ensure that files in pull requests are formatted correctly and that there are no lint issues. ## Code reviews All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. ## Community Guidelines This project follows [Google's Open Source Community Guidelines](https://opensource.google.com/conduct/). 07070100000006000081A4000003E800000064000000015D9E3463000001DD000000000000000000000000000000000000002600000000bazel-rules-swift-0.13.0/CONTRIBUTORS# People who have agreed to one of the CLAs and can contribute patches. # The AUTHORS file lists the copyright holders; this file # lists people. For example, Google employees are listed here # but not in AUTHORS, because Google holds the copyright. # # https://developers.google.com/open-source/cla/individual # https://developers.google.com/open-source/cla/corporate # # Names should be added to this file as: # Name <email address> Tony Allevato <allevato@google.com> 07070100000007000081A4000003E800000064000000015D9E346300002C5E000000000000000000000000000000000000002100000000bazel-rules-swift-0.13.0/LICENSE Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. 07070100000008000081A4000003E800000064000000015D9E346300001364000000000000000000000000000000000000002300000000bazel-rules-swift-0.13.0/README.md# Swift Rules for [Bazel](https://bazel.build) [![Build status](https://badge.buildkite.com/d562b11425e192a8f6ba9c43715bc8364985bccf54e4b9194a.svg?branch=master)](https://buildkite.com/bazel/rules-swift-swift) This repository contains rules for [Bazel](https://bazel.build) that can be used to build Swift libraries, tests, and executables for macOS and Linux. To build applications for all of Apple's platforms (macOS, iOS, tvOS, and watchOS), they can be combined with the [Apple Rules](https://github.com/bazelbuild/rules_apple). If you run into any problems with these rules, please [file an issue!](https://github.com/bazelbuild/rules_swift/issues/new) ## Reference Documentation [Click here](https://github.com/bazelbuild/rules_swift/tree/master/doc) for the reference documentation for the rules and other definitions in this repository. ## Compatibility Please refer to the [release notes](https://github.com/bazelbuild/rules_swift/releases) for a given release to see which version of Bazel it is compatible with. ## Quick Setup ### 1. Install Swift Before getting started, make sure that you have a Swift toolchain installed. **Apple users:** Install [Xcode](https://developer.apple.com/xcode/downloads/). If this is your first time installing it, make sure to open it once after installing so that the command line tools are correctly configured. **Linux users:** Follow the instructions on the [Swift download page](https://swift.org/download/) to download and install the appropriate Swift toolchain for your platform. Take care to ensure that you have all of Swift's dependencies installed (such as ICU, Clang, and so forth), and also ensure that the Swift compiler is available on your system path. ### 2. Configure your workspace Add the following to your `WORKSPACE` file to add the external repositories, replacing the `urls` and `sha256` attributes with the values from the release you wish to depend on: ```python load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "build_bazel_rules_swift", sha256 = "96a86afcbdab215f8363e65a10cf023b752e90b23abf02272c4fc668fcb70311", urls = [ "https://github.com/bazelbuild/rules_swift/releases/download/0.11.1/rules_swift.0.11.1.tar.gz", ], ) load( "@build_bazel_rules_swift//swift:repositories.bzl", "swift_rules_dependencies", ) swift_rules_dependencies() load( "@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies", ) apple_support_dependencies() load( "@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps", ) protobuf_deps() ``` The `swift_rules_dependencies` macro creates a toolchain appropriate for your platform (either by locating an installation of Xcode on macOS, or looking for `swiftc` on the system path on Linux). ### 3. Additional configuration (Linux only) The `swift_binary` and `swift_test` rules expect to use `clang` as the driver for linking, and they query the Bazel C++ API and CROSSTOOL to determine which arguments should be passed to the linker. By default, the C++ toolchain used by Bazel is `gcc`, so Swift users on Linux need to override this by setting the environment variable `CC=clang` when invoking Bazel. This step is not necessary for macOS users because the Xcode toolchain always uses `clang`. ## Building with Custom Toolchains **macOS hosts:** You can build with a custom toolchain installed in `/Library/Developer/Toolchains` instead of Xcode's default. To do so, pass the following flag to Bazel: ``` --define=SWIFT_CUSTOM_TOOLCHAIN=toolchain.id ``` where `toolchain.id` is the value of the `CFBundleIdentifier` key in the toolchain's Info.plist file. To list the available toolchains and their bundle identifiers, you can run: ``` bazel run @build_bazel_rules_swift//tools/dump_toolchains ``` **Linux hosts:** At this time, Bazel uses whichever `swift` executable is encountered first on your `PATH`. ## Future Work * Support for building and linking to shared libraries (`.dylib`/`.so`) written in Swift. * Interoperability with Swift Package Manager. * Migration to the Bazel platforms/toolchains APIs. * Support for multiple toolchains, and support for non-Xcode toolchains on macOS. * Automatically download a Linux toolchain from [swift.org](https://swift.org) if one is not already installed. ## Acknowledgments We gratefully acknowledge the following external packages that rules_swift depends on: * [Apple Support for Bazel](https://github.com/bazelbuild/apple_support) (Google) * [Bazel Skylib](https://github.com/bazelbuild/bazel-skylib) (Google) * [JSON for Modern C++](https://github.com/nlohmann/json) (Niels Lohmann) * [Protocol Buffers](https://github.com/protocolbuffers/protobuf) (Google) * [Swift gRPC](https://github.com/grpc/grpc-swift) (Google) * [Swift Protobuf](https://github.com/apple/swift-protobuf) (Apple) * [zlib](https://www.zlib.net) (Jean-loup Gailly and Mark Adler) 07070100000009000081A4000003E800000064000000015D9E346300000189000000000000000000000000000000000000002300000000bazel-rules-swift-0.13.0/WORKSPACEworkspace(name = "build_bazel_rules_swift") load( "@build_bazel_rules_swift//swift:repositories.bzl", "swift_rules_dependencies", ) swift_rules_dependencies() load( "@build_bazel_apple_support//lib:repositories.bzl", "apple_support_dependencies", ) apple_support_dependencies() load( "@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps", ) protobuf_deps() 0707010000000A000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000001D00000000bazel-rules-swift-0.13.0/doc0707010000000B000081A4000003E800000064000000015D9E346300000265000000000000000000000000000000000000002700000000bazel-rules-swift-0.13.0/doc/README.md# Swift Build Definitions ## BUILD Rules * [swift_binary](rules.md#swift_binary) * [swift_c_module](rules.md#swift_c_module) * [swift_import](rules.md#swift_import) * [swift_library](rules.md#swift_library) * [swift_module_alias](rules.md#swift_module_alias) * [swift_proto_library](rules.md#swift_proto_library) * [swift_test](rules.md#swift_test) ## Repository Setup * [swift_rules_dependencies](setup.md#swift_rules_dependencies) ## Low-level Skylark API * [swift_common](api.md) module ## Skylark Providers * [SwiftInfo](providers.md#SwiftInfo) * [SwiftToolchainInfo](providers.md#SwiftToolchainInfo) 0707010000000C000081A4000003E800000064000000015D9E346300007CAB000000000000000000000000000000000000002400000000bazel-rules-swift-0.13.0/doc/api.md# Build API <!-- Generated file, do not edit directly. --> The `swift_common` module provides API access to the behavior implemented by the Swift build rules, so that other custom rules can invoke Swift compilation and/or linking as part of their implementation. On this page: * [swift_common.cc_feature_configuration](#swift_common.cc_feature_configuration) * [swift_common.compilation_attrs](#swift_common.compilation_attrs) * [swift_common.compile](#swift_common.compile) * [swift_common.configure_features](#swift_common.configure_features) * [swift_common.create_swift_info](#swift_common.create_swift_info) * [swift_common.derive_module_name](#swift_common.derive_module_name) * [swift_common.is_enabled](#swift_common.is_enabled) * [swift_common.library_rule_attrs](#swift_common.library_rule_attrs) * [swift_common.swift_runtime_linkopts](#swift_common.swift_runtime_linkopts) * [swift_common.swiftc_command_line_and_inputs](#swift_common.swiftc_command_line_and_inputs) * [swift_common.toolchain_attrs](#swift_common.toolchain_attrs) <a name="swift_common.cc_feature_configuration"></a> ## swift_common.cc_feature_configuration <pre style="white-space: normal"> swift_common.cc_feature_configuration(<a href="#swift_common.cc_feature_configuration.feature_configuration">feature_configuration</a>) </pre> Returns the C++ feature configuration nested inside the given Swift feature configuration. <a name="swift_common.cc_feature_configuration.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.cc_feature_configuration.feature_configuration"> <td><code>feature_configuration</code></td> <td><p><code>Required</code></p><p>The Swift feature configuration, as returned from <code>swift_common.configure_features</code>.</p></td> </tr> </tbody> </table> <a name="swift_common.cc_feature_configuration.returns"></a> ### Returns A C++ `FeatureConfiguration` value (see `cc_common` for more information). <a name="swift_common.compilation_attrs"></a> ## swift_common.compilation_attrs <pre style="white-space: normal"> swift_common.compilation_attrs(<a href="#swift_common.compilation_attrs.additional_deps_aspects">additional_deps_aspects</a>=[]) </pre> Returns an attribute dictionary for rules that compile Swift into objects. The returned dictionary contains the subset of attributes that are shared by the `swift_binary`, `swift_library`, and `swift_test` rules that deal with inputs and options for compilation. Users who are authoring custom rules that compile Swift code but not as a library can add this dictionary to their own rule's attributes to give it a familiar API. Do note, however, that it is the responsibility of the rule implementation to retrieve the values of those attributes and pass them correctly to the other `swift_common` APIs. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. <a name="swift_common.compilation_attrs.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.compilation_attrs.additional_deps_aspects"> <td><code>additional_deps_aspects</code></td> <td><p><code>Optional; default is []</code></p><p>A list of additional aspects that should be applied to <code>deps</code>. Defaults to the empty list. These must be passed by the individual rules to avoid potential circular dependencies between the API and the aspects; the API loaded the aspects directly, then those aspects would not be able to load the API.</p></td> </tr> </tbody> </table> <a name="swift_common.compilation_attrs.returns"></a> ### Returns A new attribute dictionary that can be added to the attributes of a custom build rule to provide a similar interface to `swift_binary`, `swift_library`, and `swift_test`. <a name="swift_common.compile"></a> ## swift_common.compile <pre style="white-space: normal"> swift_common.compile(<a href="#swift_common.compile.actions">actions</a>, <a href="#swift_common.compile.feature_configuration">feature_configuration</a>, <a href="#swift_common.compile.module_name">module_name</a>, <a href="#swift_common.compile.srcs">srcs</a>, <a href="#swift_common.compile.swift_toolchain">swift_toolchain</a>, <a href="#swift_common.compile.target_name">target_name</a>, <a href="#swift_common.compile.additional_inputs">additional_inputs</a>=[], <a href="#swift_common.compile.bin_dir">bin_dir</a>=None, <a href="#swift_common.compile.copts">copts</a>=[], <a href="#swift_common.compile.defines">defines</a>=[], <a href="#swift_common.compile.deps">deps</a>=[], <a href="#swift_common.compile.genfiles_dir">genfiles_dir</a>=None) </pre> Compiles a Swift module. <a name="swift_common.compile.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.compile.actions"> <td><code>actions</code></td> <td><p><code>Required</code></p><p>The context's <code>actions</code> object.</p></td> </tr> <tr id="swift_common.compile.feature_configuration"> <td><code>feature_configuration</code></td> <td><p><code>Required</code></p><p>A feature configuration obtained from <code>swift_common.configure_features</code>.</p></td> </tr> <tr id="swift_common.compile.module_name"> <td><code>module_name</code></td> <td><p><code>Required</code></p><p>The name of the Swift module being compiled. This must be present and valid; use <code>swift_common.derive_module_name</code> to generate a default from the target's label if needed.</p></td> </tr> <tr id="swift_common.compile.srcs"> <td><code>srcs</code></td> <td><p><code>Required</code></p><p>The Swift source files to compile.</p></td> </tr> <tr id="swift_common.compile.swift_toolchain"> <td><code>swift_toolchain</code></td> <td><p><code>Required</code></p><p>The <code>SwiftToolchainInfo</code> provider of the toolchain.</p></td> </tr> <tr id="swift_common.compile.target_name"> <td><code>target_name</code></td> <td><p><code>Required</code></p><p>The name of the target for which the code is being compiled, which is used to determine unique file paths for the outputs.</p></td> </tr> <tr id="swift_common.compile.additional_inputs"> <td><code>additional_inputs</code></td> <td><p><code>Optional; default is []</code></p><p>A list of <code>File</code>s representing additional input files that need to be passed to the Swift compile action because they are referenced by compiler flags.</p></td> </tr> <tr id="swift_common.compile.bin_dir"> <td><code>bin_dir</code></td> <td><p><code>Optional; default is None</code></p><p>The Bazel <code>*-bin</code> directory root. If provided, its path is used to store the cache for modules precompiled by Swift's ClangImporter.</p></td> </tr> <tr id="swift_common.compile.copts"> <td><code>copts</code></td> <td><p><code>Optional; default is []</code></p><p>A list of compiler flags that apply to the target being built. These flags, along with those from Bazel's Swift configuration fragment (i.e., <code>--swiftcopt</code> command line flags) are scanned to determine whether whole module optimization is being requested, which affects the nature of the output files.</p></td> </tr> <tr id="swift_common.compile.defines"> <td><code>defines</code></td> <td><p><code>Optional; default is []</code></p><p>Symbols that should be defined by passing <code>-D</code> to the compiler.</p></td> </tr> <tr id="swift_common.compile.deps"> <td><code>deps</code></td> <td><p><code>Optional; default is []</code></p><p>Dependencies of the target being compiled. These targets must propagate one of the following providers: <code>CcInfo</code>, <code>SwiftInfo</code>, or <code>apple_common.Objc</code>.</p></td> </tr> <tr id="swift_common.compile.genfiles_dir"> <td><code>genfiles_dir</code></td> <td><p><code>Optional; default is None</code></p><p>The Bazel <code>*-genfiles</code> directory root. If provided, its path is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support inclusions of generated headers from that location.</p></td> </tr> </tbody> </table> <a name="swift_common.compile.returns"></a> ### Returns A `struct` containing the following fields: * `generated_header`: A `File` representing the Objective-C header that was generated for the compiled module. If no header was generated, this field will be None. * `generated_header_module_map`: A `File` representing the module map that was generated to correspond to the generated Objective-C header. If no module map was generated, this field will be None. * `indexstore`: A `File` representing the directory that contains the index store data generated by the compiler if index-while-building is enabled. May be None if no indexing was requested. * `linker_flags`: A list of strings representing additional flags that should be passed to the linker when linking these objects into a binary. If there are none, this field will always be an empty list, never None. * `linker_inputs`: A list of `File`s representing additional input files (such as those referenced in `linker_flags`) that need to be available to the link action when linking these objects into a binary. If there are none, this field will always be an empty list, never None. * `object_files`: A list of `.o` files that were produced by the compiler. * `stats_directory`: A `File` representing the directory that contains the timing statistics emitted by the compiler. If no stats were requested, this field will be None. * `swiftdoc`: The `.swiftdoc` file that was produced by the compiler. * `swiftmodule`: The `.swiftmodule` file that was produced by the compiler. <a name="swift_common.configure_features"></a> ## swift_common.configure_features <pre style="white-space: normal"> swift_common.configure_features(<a href="#swift_common.configure_features.ctx">ctx</a>, <a href="#swift_common.configure_features.swift_toolchain">swift_toolchain</a>, <a href="#swift_common.configure_features.requested_features">requested_features</a>=[], <a href="#swift_common.configure_features.unsupported_features">unsupported_features</a>=[]) </pre> Creates a feature configuration that should be passed to other Swift build APIs. This function calls through to `cc_common.configure_features` to configure underlying C++ features as well, and nests the C++ feature configuration inside the Swift one. Users who need to call C++ APIs that require a feature configuration can extract it by calling `swift_common.cc_feature_configuration(feature_configuration)`. <a name="swift_common.configure_features.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.configure_features.ctx"> <td><code>ctx</code></td> <td><p><code>Required</code></p><p>The rule context.</p></td> </tr> <tr id="swift_common.configure_features.swift_toolchain"> <td><code>swift_toolchain</code></td> <td><p><code>Required</code></p><p>The <code>SwiftToolchainInfo</code> provider of the toolchain being used to build. The C++ toolchain associated with the Swift toolchain is used to create the underlying C++ feature configuration.</p></td> </tr> <tr id="swift_common.configure_features.requested_features"> <td><code>requested_features</code></td> <td><p><code>Optional; default is []</code></p><p>The list of features to be enabled. This is typically obtained using the <code>ctx.features</code> field in a rule implementation function.</p></td> </tr> <tr id="swift_common.configure_features.unsupported_features"> <td><code>unsupported_features</code></td> <td><p><code>Optional; default is []</code></p><p>The list of features that are unsupported by the current rule. This is typically obtained using the <code>ctx.disabled_features</code> field in a rule implementation function.</p></td> </tr> </tbody> </table> <a name="swift_common.configure_features.returns"></a> ### Returns An opaque value representing the feature configuration that can be passed to other `swift_common` functions. <a name="swift_common.create_swift_info"></a> ## swift_common.create_swift_info <pre style="white-space: normal"> swift_common.create_swift_info(<a href="#swift_common.create_swift_info.defines">defines</a>=[], <a href="#swift_common.create_swift_info.modulemaps">modulemaps</a>=[], <a href="#swift_common.create_swift_info.module_name">module_name</a>=None, <a href="#swift_common.create_swift_info.swiftdocs">swiftdocs</a>=[], <a href="#swift_common.create_swift_info.swiftmodules">swiftmodules</a>=[], <a href="#swift_common.create_swift_info.swift_infos">swift_infos</a>=[], <a href="#swift_common.create_swift_info.swift_version">swift_version</a>=None) </pre> Creates a new `SwiftInfo` provider with the given values. This function is recommended instead of directly creating a `SwiftInfo` provider because it encodes reasonable defaults for fields that some rules may not be interested in and ensures that the direct and transitive fields are set consistently. This function can also be used to do a simple merge of `SwiftInfo` providers, by leaving all of the arguments except for `swift_infos` as their empty defaults. In that case, the returned provider will not represent a true Swift module; it is merely a "collector" for other dependencies. <a name="swift_common.create_swift_info.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.create_swift_info.defines"> <td><code>defines</code></td> <td><p><code>Optional; default is []</code></p><p>A list of defines that will be provided as <code>copts</code> of the target being built.</p></td> </tr> <tr id="swift_common.create_swift_info.modulemaps"> <td><code>modulemaps</code></td> <td><p><code>Optional; default is []</code></p><p>A list of module maps that should be passed to ClangImporter by any target that depends on the one propagating this provider.</p></td> </tr> <tr id="swift_common.create_swift_info.module_name"> <td><code>module_name</code></td> <td><p><code>Optional; default is None</code></p><p>A string containing the name of the Swift module. If this is <code>None</code>, the provider does not represent a compiled module but rather a collection of modules (this happens, for example, with <code>proto_library</code> targets that have no sources of their own but depend on others that do).</p></td> </tr> <tr id="swift_common.create_swift_info.swiftdocs"> <td><code>swiftdocs</code></td> <td><p><code>Optional; default is []</code></p><p>A list of <code>.swiftdoc</code> files that are the direct outputs of the target being built. If omitted, an empty list is used.</p></td> </tr> <tr id="swift_common.create_swift_info.swiftmodules"> <td><code>swiftmodules</code></td> <td><p><code>Optional; default is []</code></p><p>A list of <code>.swiftmodule</code> files that are the direct outputs of the target being built. If omitted, an empty list is used.</p></td> </tr> <tr id="swift_common.create_swift_info.swift_infos"> <td><code>swift_infos</code></td> <td><p><code>Optional; default is []</code></p><p>A list of <code>SwiftInfo</code> providers from dependencies, whose transitive fields should be merged into the new one. If omitted, no transitive data is collected.</p></td> </tr> <tr id="swift_common.create_swift_info.swift_version"> <td><code>swift_version</code></td> <td><p><code>Optional; default is None</code></p><p>A string containing the value of the <code>-swift-version</code> flag used when compiling this target, or <code>None</code> (the default) if it was not set or is not relevant.</p></td> </tr> </tbody> </table> <a name="swift_common.create_swift_info.returns"></a> ### Returns A new `SwiftInfo` provider with the given values. <a name="swift_common.derive_module_name"></a> ## swift_common.derive_module_name <pre style="white-space: normal"> swift_common.derive_module_name(<a href="#swift_common.derive_module_name.*args">*args</a>) </pre> Returns a derived module name from the given build label. For targets whose module name is not explicitly specified, the module name is computed by creating an underscore-delimited string from the components of the label, replacing any non-identifier characters also with underscores. This mapping is not intended to be reversible. <a name="swift_common.derive_module_name.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.derive_module_name.*args"> <td><code>*args</code></td> <td><p>Either a single argument of type <code>Label</code>, or two arguments of type <code>str</code> where the first argument is the package name and the second argument is the target name.</p></td> </tr> </tbody> </table> <a name="swift_common.derive_module_name.returns"></a> ### Returns The module name derived from the label. <a name="swift_common.is_enabled"></a> ## swift_common.is_enabled <pre style="white-space: normal"> swift_common.is_enabled(<a href="#swift_common.is_enabled.feature_configuration">feature_configuration</a>, <a href="#swift_common.is_enabled.feature_name">feature_name</a>) </pre> Returns `True` if the given feature is enabled in the feature configuration. This function handles both Swift-specific features and C++ features so that users do not have to manually extract the C++ configuration in order to check it. <a name="swift_common.is_enabled.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.is_enabled.feature_configuration"> <td><code>feature_configuration</code></td> <td><p><code>Required</code></p><p>The Swift feature configuration, as returned by <code>swift_common.configure_features</code>.</p></td> </tr> <tr id="swift_common.is_enabled.feature_name"> <td><code>feature_name</code></td> <td><p><code>Required</code></p><p>The name of the feature to check.</p></td> </tr> </tbody> </table> <a name="swift_common.is_enabled.returns"></a> ### Returns `True` if the given feature is enabled in the feature configuration. <a name="swift_common.library_rule_attrs"></a> ## swift_common.library_rule_attrs <pre style="white-space: normal"> swift_common.library_rule_attrs(<a href="#swift_common.library_rule_attrs.additional_deps_aspects">additional_deps_aspects</a>=[]) </pre> Returns an attribute dictionary for `swift_library`-like rules. The returned dictionary contains the same attributes that are defined by the `swift_library` rule (including the private `_toolchain` attribute that specifies the toolchain dependency). Users who are authoring custom rules can use this dictionary verbatim or add other custom attributes to it in order to make their rule a drop-in replacement for `swift_library` (for example, if writing a custom rule that does some preprocessing or generation of sources and then compiles them). Do note, however, that it is the responsibility of the rule implementation to retrieve the values of those attributes and pass them correctly to the other `swift_common` APIs. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. <a name="swift_common.library_rule_attrs.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.library_rule_attrs.additional_deps_aspects"> <td><code>additional_deps_aspects</code></td> <td><p><code>Optional; default is []</code></p><p>A list of additional aspects that should be applied to <code>deps</code>. Defaults to the empty list. These must be passed by the individual rules to avoid potential circular dependencies between the API and the aspects; the API loaded the aspects directly, then those aspects would not be able to load the API.</p></td> </tr> </tbody> </table> <a name="swift_common.library_rule_attrs.returns"></a> ### Returns A new attribute dictionary that can be added to the attributes of a custom build rule to provide the same interface as `swift_library`. <a name="swift_common.swift_runtime_linkopts"></a> ## swift_common.swift_runtime_linkopts <pre style="white-space: normal"> swift_common.swift_runtime_linkopts(<a href="#swift_common.swift_runtime_linkopts.is_static">is_static</a>, <a href="#swift_common.swift_runtime_linkopts.toolchain">toolchain</a>, <a href="#swift_common.swift_runtime_linkopts.is_test">is_test</a>=False) </pre> Returns the flags that should be passed to `clang` when linking a binary. This function provides the appropriate linker arguments to callers who need to link a binary using something other than `swift_binary` (for example, an application bundle containing a universal `apple_binary`). <a name="swift_common.swift_runtime_linkopts.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.swift_runtime_linkopts.is_static"> <td><code>is_static</code></td> <td><p><code>Required</code></p><p>A <code>Boolean</code> value indicating whether the binary should be linked against the static (rather than the dynamic) Swift runtime libraries.</p></td> </tr> <tr id="swift_common.swift_runtime_linkopts.toolchain"> <td><code>toolchain</code></td> <td><p><code>Required</code></p><p>The <code>SwiftToolchainInfo</code> provider of the toolchain whose linker options are desired.</p></td> </tr> <tr id="swift_common.swift_runtime_linkopts.is_test"> <td><code>is_test</code></td> <td><p><code>Optional; default is False</code></p><p>A <code>Boolean</code> value indicating whether the target being linked is a test target.</p></td> </tr> </tbody> </table> <a name="swift_common.swift_runtime_linkopts.returns"></a> ### Returns A `list` of command-line flags that should be passed to `clang` to link against the Swift runtime libraries. <a name="swift_common.swiftc_command_line_and_inputs"></a> ## swift_common.swiftc_command_line_and_inputs <pre style="white-space: normal"> swift_common.swiftc_command_line_and_inputs(<a href="#swift_common.swiftc_command_line_and_inputs.args">args</a>, <a href="#swift_common.swiftc_command_line_and_inputs.feature_configuration">feature_configuration</a>, <a href="#swift_common.swiftc_command_line_and_inputs.module_name">module_name</a>, <a href="#swift_common.swiftc_command_line_and_inputs.srcs">srcs</a>, <a href="#swift_common.swiftc_command_line_and_inputs.toolchain">toolchain</a>, <a href="#swift_common.swiftc_command_line_and_inputs.additional_input_depsets">additional_input_depsets</a>=[], <a href="#swift_common.swiftc_command_line_and_inputs.copts">copts</a>=[], <a href="#swift_common.swiftc_command_line_and_inputs.defines">defines</a>=[], <a href="#swift_common.swiftc_command_line_and_inputs.deps">deps</a>=[], <a href="#swift_common.swiftc_command_line_and_inputs.genfiles_dir">genfiles_dir</a>=None) </pre> Computes command line arguments and inputs needed to invoke `swiftc`. The command line arguments computed by this function are any that do *not* require the declaration of new output files. For example, it includes the list of frameworks, defines, source files, and other copts, but not flags like the output objects or `.swiftmodule` files. The purpose of this is to allow (nearly) the same command line that would be passed to the compiler to be passed to other tools that require it; the most common application of this is for tools that use SourceKit, which need to know the command line in order to gather information about dependencies for indexing and code completion. <a name="swift_common.swiftc_command_line_and_inputs.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.swiftc_command_line_and_inputs.args"> <td><code>args</code></td> <td><p><code>Required</code></p><p>An <code>Args</code> object into which the command line arguments will be added.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.feature_configuration"> <td><code>feature_configuration</code></td> <td><p><code>Required</code></p><p>A feature configuration obtained from <code>swift_common.configure_features</code>.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.module_name"> <td><code>module_name</code></td> <td><p><code>Required</code></p><p>The name of the Swift module being compiled. This must be present and valid; use <code>swift_common.derive_module_name</code> to generate a default from the target's label if needed.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.srcs"> <td><code>srcs</code></td> <td><p><code>Required</code></p><p>The Swift source files to compile.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.toolchain"> <td><code>toolchain</code></td> <td><p><code>Required</code></p><p>The <code>SwiftToolchainInfo</code> provider of the toolchain.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.additional_input_depsets"> <td><code>additional_input_depsets</code></td> <td><p><code>Optional; default is []</code></p><p>A list of <code>depset</code>s of <code>File</code>s representing additional input files that need to be passed to the Swift compile action because they are referenced by compiler flags.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.copts"> <td><code>copts</code></td> <td><p><code>Optional; default is []</code></p><p>A list (<strong>not</strong> an <code>Args</code> object) of compiler flags that apply to the target being built. These flags, along with those from Bazel's Swift configuration fragment (i.e., <code>--swiftcopt</code> command line flags) are scanned to determine whether whole module optimization is being requested, which affects the nature of the output files.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.defines"> <td><code>defines</code></td> <td><p><code>Optional; default is []</code></p><p>Symbols that should be defined by passing <code>-D</code> to the compiler.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.deps"> <td><code>deps</code></td> <td><p><code>Optional; default is []</code></p><p>Dependencies of the target being compiled. These targets must propagate one of the following providers: <code>CcInfo</code>, <code>SwiftInfo</code>, or <code>apple_common.Objc</code>.</p></td> </tr> <tr id="swift_common.swiftc_command_line_and_inputs.genfiles_dir"> <td><code>genfiles_dir</code></td> <td><p><code>Optional; default is None</code></p><p>The Bazel <code>*-genfiles</code> directory root. If provided, its path is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support inclusions of generated headers from that location.</p></td> </tr> </tbody> </table> <a name="swift_common.swiftc_command_line_and_inputs.returns"></a> ### Returns A `depset` containing the full set of files that need to be passed as inputs of the Bazel action that spawns a tool with the computed command line (i.e., any source files, referenced module maps and headers, and so forth.) <a name="swift_common.toolchain_attrs"></a> ## swift_common.toolchain_attrs <pre style="white-space: normal"> swift_common.toolchain_attrs(<a href="#swift_common.toolchain_attrs.toolchain_attr_name">toolchain_attr_name</a>=_toolchain) </pre> Returns an attribute dictionary for toolchain users. The returned dictionary contains a key with the name specified by the argument `toolchain_attr_name` (which defaults to the value `"_toolchain"`), the value of which is a BUILD API `attr.label` that references the default Swift toolchain. Users who are authoring custom rules can add this dictionary to the attributes of their own rule in order to depend on the toolchain and access its `SwiftToolchainInfo` provider to pass it to other `swift_common` functions. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. <a name="swift_common.toolchain_attrs.arguments"></a> ### Arguments <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_common.toolchain_attrs.toolchain_attr_name"> <td><code>toolchain_attr_name</code></td> <td><p><code>Optional; default is _toolchain</code></p><p>The name of the attribute that should be created that points to the toolchain. This defaults to <code>_toolchain</code>, which is sufficient for most rules; it is customizable for certain aspects where having an attribute with the same name but different values applied to a particular target causes a build crash.</p></td> </tr> </tbody> </table> <a name="swift_common.toolchain_attrs.returns"></a> ### Returns A new attribute dictionary that can be added to the attributes of a custom build rule to provide access to the Swift toolchain. 0707010000000D000081A4000003E800000064000000015D9E34630000069C000000000000000000000000000000000000002800000000bazel-rules-swift-0.13.0/doc/aspects.md# Aspects <!-- Generated file, do not edit directly. --> The aspects described below are used within the build rule implementations. Clients interested in writing custom rules that interface with the rules/provides in this package might needs them to provide some of the same information. On this page: * [swift_usage_aspect](#swift_usage_aspect) <a name="swift_usage_aspect"></a> ## swift_usage_aspect <pre style="white-space: normal"> swift_usage_aspect() </pre> Collects information about how Swift is used in a dependency tree. When attached to an attribute, this aspect will propagate a `SwiftUsageInfo` provider for any target found in that attribute that uses Swift, either directly or deeper in its dependency tree. Conversely, if neither a target nor its transitive dependencies use Swift, the `SwiftUsageInfo` provider will not be propagated. Specifically, the aspect propagates which toolchain was used to build those dependencies. This information is typically always the same for any Swift targets built in the same configuration, but this allows upstream targets that may not be *strictly* Swift-related and thus don't want to depend directly on the Swift toolchain (such as Apple universal binary linking rules) to avoid doing so but still get access to information derived from the toolchain (like which linker flags to pass to link to the runtime). We use an aspect (as opposed to propagating this information through normal providers returned by `swift_library`) because the information is needed if Swift is used _anywhere_ in a dependency graph, even as dependencies of other language rules that wouldn't know how to propagate the Swift-specific providers. 0707010000000E000081A4000003E800000064000000015D9E346300002E41000000000000000000000000000000000000002A00000000bazel-rules-swift-0.13.0/doc/providers.md# Providers <!-- Generated file, do not edit directly. --> The providers described below are propagated and required by various Swift build rules. Clients interested in writing custom rules that interface with the rules in this package should use these providers to communicate with the Swift build rules as needed. On this page: * [SwiftInfo](#SwiftInfo) * [SwiftToolchainInfo](#SwiftToolchainInfo) * [SwiftProtoInfo](#SwiftProtoInfo) * [SwiftUsageInfo](#SwiftUsageInfo) <a name="SwiftInfo"></a> ## SwiftInfo Contains information about the compiled artifacts of a Swift module. This provider contains a large number of fields and many custom rules may not need to set all of them. Instead of constructing a `SwiftInfo` provider directly, consider using the `swift_common.create_swift_info` function, which has reasonable defaults for any fields not explicitly set. <table class="fields-table"> <colgroup> <col class="col-field" /> <col class="col-description" /> </colgroup> <tbody> <tr id="SwiftInfo.direct_defines"> <td><code>direct_defines</code></td> <td><p><code>List</code> of <code>string</code>s. The values specified by the <code>defines</code> attribute of the library that directly propagated this provider.</p></td> </tr> <tr id="SwiftInfo.direct_swiftdocs"> <td><code>direct_swiftdocs</code></td> <td><p><code>List</code> of <code>File</code>s. The Swift documentation (<code>.swiftdoc</code>) files for the library that directly propagated this provider.</p></td> </tr> <tr id="SwiftInfo.direct_swiftmodules"> <td><code>direct_swiftmodules</code></td> <td><p><code>List</code> of <code>File</code>s. The Swift modules (<code>.swiftmodule</code>) for the library that directly propagated this provider.</p></td> </tr> <tr id="SwiftInfo.module_name"> <td><code>module_name</code></td> <td><p><code>String</code>. The name of the Swift module represented by the target that directly propagated this provider.</p> <p>This field will be equal to the explicitly assigned module name (if present); otherwise, it will be equal to the autogenerated module name.</p></td> </tr> <tr id="SwiftInfo.swift_version"> <td><code>swift_version</code></td> <td><p><code>String</code>. The version of the Swift language that was used when compiling the propagating target; that is, the value passed via the <code>-swift-version</code> compiler flag. This will be <code>None</code> if the flag was not set.</p></td> </tr> <tr id="SwiftInfo.transitive_defines"> <td><code>transitive_defines</code></td> <td><p><code>Depset</code> of <code>string</code>s. The transitive <code>defines</code> specified for the library that propagated this provider and all of its dependencies.</p></td> </tr> <tr id="SwiftInfo.transitive_modulemaps"> <td><code>transitive_modulemaps</code></td> <td><p><code>Depset</code> of <code>File</code>s. The transitive module map files that will be passed to Clang using the <code>-fmodule-map-file</code> option.</p></td> </tr> <tr id="SwiftInfo.transitive_swiftdocs"> <td><code>transitive_swiftdocs</code></td> <td><p><code>Depset</code> of <code>File</code>s. The transitive Swift documentation (<code>.swiftdoc</code>) files emitted by the library that propagated this provider and all of its dependencies.</p></td> </tr> <tr id="SwiftInfo.transitive_swiftmodules"> <td><code>transitive_swiftmodules</code></td> <td><p><code>Depset</code> of <code>File</code>s. The transitive Swift modules (<code>.swiftmodule</code>) emitted by the library that propagated this provider and all of its dependencies.</p></td> </tr> </tbody> </table> <a name="SwiftToolchainInfo"></a> ## SwiftToolchainInfo Propagates information about a Swift toolchain to compilation and linking rules that use the toolchain. <table class="fields-table"> <colgroup> <col class="col-field" /> <col class="col-description" /> </colgroup> <tbody> <tr id="SwiftToolchainInfo.action_environment"> <td><code>action_environment</code></td> <td><p><code>Dict</code>. Environment variables that should be set during any actions spawned to compile or link Swift code.</p></td> </tr> <tr id="SwiftToolchainInfo.all_files"> <td><code>all_files</code></td> <td><p>A <code>depset</code> of <code>File</code>s containing all the Swift toolchain files (tools, libraries, and other resource files) so they can be passed as <code>tools</code> to actions using this toolchain.</p></td> </tr> <tr id="SwiftToolchainInfo.cc_toolchain_info"> <td><code>cc_toolchain_info</code></td> <td><p>The <code>cc_common.CcToolchainInfo</code> provider from the Bazel C++ toolchain that this Swift toolchain depends on.</p></td> </tr> <tr id="SwiftToolchainInfo.clang_executable"> <td><code>clang_executable</code></td> <td><p><code>String</code>. The path to the <code>clang</code> executable, which is used to link binaries.</p></td> </tr> <tr id="SwiftToolchainInfo.command_line_copts"> <td><code>command_line_copts</code></td> <td><p><code>List</code> of <code>strings</code>. Flags that were passed to Bazel using the <code>--swiftcopt</code> command line flag. These flags have the highest precedence; they are added to compilation command lines after the toolchain default flags (<code>SwiftToolchainInfo.swiftc_copts</code>) and after flags specified in the <code>copts</code> attributes of Swift targets.</p></td> </tr> <tr id="SwiftToolchainInfo.cpu"> <td><code>cpu</code></td> <td><p><code>String</code>. The CPU architecture that the toolchain is targeting.</p></td> </tr> <tr id="SwiftToolchainInfo.execution_requirements"> <td><code>execution_requirements</code></td> <td><p><code>Dict</code>. Execution requirements that should be passed to any actions spawned to compile or link Swift code.</p> <p>For example, when using an Xcode toolchain, the execution requirements should be such that running on Darwin is required.</p></td> </tr> <tr id="SwiftToolchainInfo.implicit_deps"> <td><code>implicit_deps</code></td> <td><p><code>List</code> of <code>Target</code>s. Library targets that should be added as implicit dependencies of any <code>swift_library</code>, <code>swift_binary</code>, or <code>swift_test</code> target.</p></td> </tr> <tr id="SwiftToolchainInfo.linker_opts_producer"> <td><code>linker_opts_producer</code></td> <td><p>Skylib <code>partial</code>. A partial function that returns the flags that should be passed to Clang to link a binary or test target with the Swift runtime libraries.</p> <p>The partial should be called with two arguments:</p> <ul> <li><code>is_static</code>: A <code>Boolean</code> value indicating whether to link against the static or dynamic runtime libraries.</li> <li><code>is_test</code>: A <code>Boolean</code> value indicating whether the target being linked is a test target.</li> </ul></td> </tr> <tr id="SwiftToolchainInfo.object_format"> <td><code>object_format</code></td> <td><p><code>String</code>. The object file format of the platform that the toolchain is targeting. The currently supported values are <code>"elf"</code> and <code>"macho"</code>.</p></td> </tr> <tr id="SwiftToolchainInfo.requested_features"> <td><code>requested_features</code></td> <td><p><code>List</code> of <code>string</code>s. Features that should be implicitly enabled by default for targets built using this toolchain, unless overridden by the user by listing their negation in the <code>features</code> attribute of a target/package or in the <code>--features</code> command line flag.</p> <p>These features determine various compilation and debugging behaviors of the Swift build rules, and they are also passed to the C++ APIs used when linking (so features defined in CROSSTOOL may be used here).</p></td> </tr> <tr id="SwiftToolchainInfo.root_dir"> <td><code>root_dir</code></td> <td><p><code>String</code>. The workspace-relative root directory of the toolchain.</p></td> </tr> <tr id="SwiftToolchainInfo.stamp"> <td><code>stamp</code></td> <td><p><code>Target</code>. A <code>CcInfo</code>-providing target that should be linked into any binaries that are built with stamping enabled.</p></td> </tr> <tr id="SwiftToolchainInfo.supports_objc_interop"> <td><code>supports_objc_interop</code></td> <td><p><code>Boolean</code>. Indicates whether or not the toolchain supports Objective-C interop.</p></td> </tr> <tr id="SwiftToolchainInfo.swift_worker"> <td><code>swift_worker</code></td> <td><p><code>File</code>. The executable representing the worker executable used to invoke the compiler and other Swift tools (for both incremental and non-incremental compiles).</p></td> </tr> <tr id="SwiftToolchainInfo.swiftc_copts"> <td><code>swiftc_copts</code></td> <td><p><code>List</code> of <code>strings</code>. Additional flags that should be passed to <code>swiftc</code> when compiling libraries or binaries with this toolchain. These flags will come first in compilation command lines, allowing them to be overridden by <code>copts</code> attributes and <code>--swiftcopt</code> flags.</p></td> </tr> <tr id="SwiftToolchainInfo.system_name"> <td><code>system_name</code></td> <td><p><code>String</code>. The name of the operating system that the toolchain is targeting.</p></td> </tr> <tr id="SwiftToolchainInfo.unsupported_features"> <td><code>unsupported_features</code></td> <td><p><code>List</code> of <code>string</code>s. Features that should be implicitly disabled by default for targets built using this toolchain, unless overridden by the user by listing them in the <code>features</code> attribute of a target/package or in the <code>--features</code> command line flag.</p> <p>These features determine various compilation and debugging behaviors of the Swift build rules, and they are also passed to the C++ APIs used when linking (so features defined in CROSSTOOL may be used here).</p></td> </tr> </tbody> </table> <a name="SwiftProtoInfo"></a> ## SwiftProtoInfo Propagates Swift-specific information about a `proto_library`. <table class="fields-table"> <colgroup> <col class="col-field" /> <col class="col-description" /> </colgroup> <tbody> <tr id="SwiftProtoInfo.module_mappings"> <td><code>module_mappings</code></td> <td><p><code>Sequence</code> of <code>struct</code>s. Each struct contains <code>module_name</code> and <code>proto_file_paths</code> fields that denote the transitive mappings from <code>.proto</code> files to Swift modules. This allows messages that reference messages in other libraries to import those modules in generated code.</p></td> </tr> <tr id="SwiftProtoInfo.pbswift_files"> <td><code>pbswift_files</code></td> <td><p><code>Depset</code> of <code>File</code>s. The transitive Swift source files (<code>.pb.swift</code>) generated from the <code>.proto</code> files.</p></td> </tr> </tbody> </table> <a name="SwiftUsageInfo"></a> ## SwiftUsageInfo A provider that indicates that Swift was used by a target or any target that it depends on, and specifically which toolchain was used. <table class="fields-table"> <colgroup> <col class="col-field" /> <col class="col-description" /> </colgroup> <tbody> <tr id="SwiftUsageInfo.toolchain"> <td><code>toolchain</code></td> <td><p>The Swift toolchain that was used to build the targets propagating this provider.</p></td> </tr> </tbody> </table> 0707010000000F000081A4000003E800000064000000015D9E34630000B2BB000000000000000000000000000000000000002600000000bazel-rules-swift-0.13.0/doc/rules.md# BUILD Rule Reference <!-- Generated file, do not edit directly. --> To use the Swift build rules in your BUILD files, load them from `@build_bazel_rules_swift//swift:swift.bzl`. For example: ```build load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") ``` On this page: * [swift_binary](#swift_binary) * [swift_c_module](#swift_c_module) * [swift_grpc_library](#swift_grpc_library) * [swift_import](#swift_import) * [swift_library](#swift_library) * [swift_module_alias](#swift_module_alias) * [swift_proto_library](#swift_proto_library) * [swift_test](#swift_test) <a name="swift_binary"></a> ## swift_binary <pre style="white-space: normal"> swift_binary(<a href="#swift_binary.name">name</a>, <a href="#swift_binary.deps">deps</a>, <a href="#swift_binary.srcs">srcs</a>, <a href="#swift_binary.data">data</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="#swift_binary.copts">copts</a>, <a href="#swift_binary.defines">defines</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="#swift_binary.linkopts">linkopts</a>, <a href="#swift_binary.malloc">malloc</a>, <a href="#swift_binary.module_name">module_name</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="#swift_binary.swiftc_inputs">swiftc_inputs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Compiles and links Swift code into an executable binary. On Linux, this rule produces an executable binary for the desired target architecture. On Apple platforms, this rule produces a _single-architecture_ binary; it does not produce fat binaries. As such, this rule is mainly useful for creating Swift tools intended to run on the local build machine. However, for historical reasons, the default Apple platform in Bazel is **iOS** instead of macOS. Therefore, if you wish to build a simple single-architecture Swift binary that can run on macOS, you must specify the correct CPU and platform on the command line as follows: ```shell $ bazel build //package:target ``` If you want to create a multi-architecture binary or a bundled application, please use one of the platform-specific application rules in [rules_apple](https://github.com/bazelbuild/rules_apple) instead of `swift_binary`. <a name="swift_binary.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_binary.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_binary.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds of dependencies are:</p> <ul> <li><code>swift_c_module</code>, <code>swift_import</code> and <code>swift_library</code> (or anything propagating <code>SwiftInfo</code>)</li> <li><code>cc_library</code> (or anything propagating <code>CcInfo</code>)</li> </ul> <p>Additionally, on platforms that support Objective-C interop, <code>objc_library</code> targets (or anything propagating the <code>apple_common.Objc</code> provider) are allowed as dependencies. On platforms that do not support Objective-C interop (such as Linux), those dependencies will be <strong>ignored.</strong></p></td> </tr> <tr id="swift_binary.srcs"> <td><code>srcs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of <code>.swift</code> source files that will be compiled into the library.</p></td> </tr> <tr id="swift_binary.data"> <td><code>data</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>The list of files needed by this target at runtime.</p> <p>Files and targets named in the <code>data</code> attribute will appear in the <code>*.runfiles</code> area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it.</p></td> </tr> <tr id="swift_binary.copts"> <td><code>copts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional compiler options that should be passed to <code>swiftc</code>. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_binary.defines"> <td><code>defines</code></td> <td> <p><code>List of strings; optional</code></p><p>A list of defines to add to the compilation command line.</p> <p>Note that unlike C-family languages, Swift defines do not have values; they are simply identifiers that are either defined or undefined. So strings in this list should be simple identifiers, <strong>not</strong> <code>name=value</code> pairs.</p> <p>Each string is prepended with <code>-D</code> and added to the command line. Unlike <code>copts</code>, these flags are added for the target and every target that depends on it, so use this attribute with caution. It is preferred that you add defines directly to <code>copts</code>, only using this feature in the rare case that a library needs to propagate a symbol up to those that depend on it.</p></td> </tr> <tr id="swift_binary.linkopts"> <td><code>linkopts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional linker options that should be passed to <code>clang</code>. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_binary.malloc"> <td><code>malloc</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#labels">Label</a>; optional; default is @bazel_tools//tools/cpp:malloc</code></p><p>Override the default dependency on <code>malloc</code>.</p> <p>By default, Swift binaries are linked against <code>@bazel_tools//tools/cpp:malloc"</code>, which is an empty library and the resulting binary will use libc's <code>malloc</code>. This label must refer to a <code>cc_library</code> rule.</p></td> </tr> <tr id="swift_binary.module_name"> <td><code>module_name</code></td> <td> <p><code>String; optional</code></p><p>The name of the Swift module being built.</p> <p>If left unspecified, the module name will be computed based on the target's build label, by stripping the leading <code>//</code> and replacing <code>/</code>, <code>:</code>, and other non-identifier characters with underscores.</p></td> </tr> <tr id="swift_binary.swiftc_inputs"> <td><code>swiftc_inputs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Additional files that are referenced using <code>$(location ...)</code> in attributes that support location expansion.</p></td> </tr> </tbody> </table> <a name="swift_c_module"></a> ## swift_c_module <pre style="white-space: normal"> swift_c_module(<a href="#swift_c_module.name">name</a>, <a href="#swift_c_module.deps">deps</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="#swift_c_module.module_map">module_map</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Wraps a `cc_library` in a new module map that allows it to be imported into Swift to access its C interfaces. NOTE: Swift at this time does not support interop directly with C++. Any headers referenced by a module map that is imported into Swift must have only C features visible, often by using preprocessor conditions like `#if __cplusplus` to hide any C++ declarations. The `cc_library` rule in Bazel does not produce module maps that are compatible with Swift. In order to make interop between Swift and C possible, users can write their own module map that includes any of the transitive public headers of the `cc_library` dependency of this target and has a module name that is a valid Swift identifier. Then, write a `swift_{binary,library,test}` target that depends on this `swift_c_module` target and the Swift sources will be able to import the module with the name given in the module map. <a name="swift_c_module.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_c_module.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_c_module.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; required</code></p><p>A list containing at most one <code>cc_library</code> target that is being wrapped with a new module map.</p> <p>If you need to create a <code>swift_c_module</code> to that pulls headers from multiple <code>cc_library</code> targets into a single module, create a new <code>cc_library</code> target that wraps them in its <code>deps</code> and has no other <code>srcs</code> or <code>hdrs</code>, and have the module target depend on that.</p></td> </tr> <tr id="swift_c_module.module_map"> <td><code>module_map</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#labels">Label</a>; required</code></p><p>The module map file that should be loaded to import the C library dependency into Swift.</p></td> </tr> </tbody> </table> <a name="swift_grpc_library"></a> ## swift_grpc_library <pre style="white-space: normal"> swift_grpc_library(<a href="#swift_grpc_library.name">name</a>, <a href="#swift_grpc_library.deps">deps</a>, <a href="#swift_grpc_library.srcs">srcs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="#swift_grpc_library.flavor">flavor</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Generates a Swift library from the gRPC services defined in protocol buffer sources. There should be one `swift_grpc_library` for any `proto_library` that defines services. A target based on this rule can be used as a dependency anywhere that a `swift_library` can be used. We recommend that `swift_grpc_library` targets be located in the same package as the `proto_library` and `swift_proto_library` targets they depend on. For more best practices around the use of Swift protocol buffer build rules, see the documentation for `swift_proto_library`. #### Defining Build Targets for Services Note that `swift_grpc_library` only generates the gRPC service interfaces (the `service` definitions) from the `.proto` files. Any messages defined in the same `.proto` file must be generated using a `swift_proto_library` target. Thus, the typical structure of a Swift gRPC library is similar to the following: ```python proto_library( name = "my_protos", srcs = ["my_protos.proto"], ) # Generate Swift types from the protos. swift_proto_library( name = "my_protos_swift", deps = [":my_protos"], ) # Generate Swift types from the services. swift_grpc_library( name = "my_protos_client_services_swift", # The `srcs` attribute points to the `proto_library` containing the service definitions... srcs = [":my_protos"], # ...the `flavor` attribute specifies what kind of definitions to generate... flavor = "client", # ...and the `deps` attribute points to the `swift_proto_library` that was generated from # the same `proto_library` and which contains the messages used by those services. deps = [":my_protos_swift"], ) # Generate test stubs from swift services. swift_grpc_library( name = "my_protos_client_stubs_swift", # The `srcs` attribute points to the `proto_library` containing the service definitions... srcs = [":my_protos"], # ...the `flavor` attribute specifies what kind of definitions to generate... flavor = "client_stubs", # ...and the `deps` attribute points to the `swift_grpc_library` that was generated from # the same `proto_library` and which contains the service implementation. deps = [":my_protos_client_services_swift"], ) ``` <a name="swift_grpc_library.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_grpc_library.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_grpc_library.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Exactly one <code>swift_proto_library</code> or <code>swift_grpc_library</code> target that contains the Swift protos used by the services being generated. Test stubs should depend on the <code>swift_grpc_library</code> implementing the service.</p></td> </tr> <tr id="swift_grpc_library.srcs"> <td><code>srcs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Exactly one <code>proto_library</code> target that defines the services being generated.</p></td> </tr> <tr id="swift_grpc_library.flavor"> <td><code>flavor</code></td> <td> <p><code>String; required; valid values are ['client', 'client_stubs', 'server']</code></p><p>The kind of definitions that should be generated:</p> <ul> <li><code>"client"</code> to generate client definitions.</li> <li><code>"client_stubs"</code> to generate client test stubs.</li> <li><code>"server"</code> to generate server definitions.</li> </ul></td> </tr> </tbody> </table> <a name="swift_import"></a> ## swift_import <pre style="white-space: normal"> swift_import(<a href="#swift_import.name">name</a>, <a href="#swift_import.deps">deps</a>, <a href="#swift_import.data">data</a>, <a href="#swift_import.archives">archives</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="#swift_import.swiftdocs">swiftdocs</a>, <a href="#swift_import.swiftmodules">swiftmodules</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Allows for the use of precompiled Swift modules as dependencies in other `swift_library` and `swift_binary` targets. <a name="swift_import.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_import.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_import.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds of dependencies are:</p> <ul> <li><code>swift_c_module</code>, <code>swift_import</code> and <code>swift_library</code> (or anything propagating <code>SwiftInfo</code>)</li> <li><code>cc_library</code> (or anything propagating <code>CcInfo</code>)</li> </ul> <p>Additionally, on platforms that support Objective-C interop, <code>objc_library</code> targets (or anything propagating the <code>apple_common.Objc</code> provider) are allowed as dependencies. On platforms that do not support Objective-C interop (such as Linux), those dependencies will be <strong>ignored.</strong></p></td> </tr> <tr id="swift_import.data"> <td><code>data</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>The list of files needed by this target at runtime.</p> <p>Files and targets named in the <code>data</code> attribute will appear in the <code>*.runfiles</code> area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it.</p></td> </tr> <tr id="swift_import.archives"> <td><code>archives</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; required</code></p><p>The list of <code>.a</code> files provided to Swift targets that depend on this target.</p></td> </tr> <tr id="swift_import.swiftdocs"> <td><code>swiftdocs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>The list of <code>.swiftdoc</code> files provided to Swift targets that depend on this target.</p></td> </tr> <tr id="swift_import.swiftmodules"> <td><code>swiftmodules</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; required</code></p><p>The list of <code>.swiftmodule</code> files provided to Swift targets that depend on this target.</p></td> </tr> </tbody> </table> <a name="swift_library"></a> ## swift_library <pre style="white-space: normal"> swift_library(<a href="#swift_library.name">name</a>, <a href="#swift_library.deps">deps</a>, <a href="#swift_library.srcs">srcs</a>, <a href="#swift_library.data">data</a>, <a href="#swift_library.alwayslink">alwayslink</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="#swift_library.copts">copts</a>, <a href="#swift_library.defines">defines</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="#swift_library.linkopts">linkopts</a>, <a href="#swift_library.module_name">module_name</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="#swift_library.swiftc_inputs">swiftc_inputs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Compiles and links Swift code into a static library and Swift module. <a name="swift_library.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_library.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_library.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds of dependencies are:</p> <ul> <li><code>swift_c_module</code>, <code>swift_import</code> and <code>swift_library</code> (or anything propagating <code>SwiftInfo</code>)</li> <li><code>cc_library</code> (or anything propagating <code>CcInfo</code>)</li> </ul> <p>Additionally, on platforms that support Objective-C interop, <code>objc_library</code> targets (or anything propagating the <code>apple_common.Objc</code> provider) are allowed as dependencies. On platforms that do not support Objective-C interop (such as Linux), those dependencies will be <strong>ignored.</strong></p></td> </tr> <tr id="swift_library.srcs"> <td><code>srcs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of <code>.swift</code> source files that will be compiled into the library.</p></td> </tr> <tr id="swift_library.data"> <td><code>data</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>The list of files needed by this target at runtime.</p> <p>Files and targets named in the <code>data</code> attribute will appear in the <code>*.runfiles</code> area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it.</p></td> </tr> <tr id="swift_library.alwayslink"> <td><code>alwayslink</code></td> <td> <p><code>Boolean; optional</code></p><p>If true, any binary that depends (directly or indirectly) on this Swift module will link in all the object files for the files listed in <code>srcs</code>, even if some contain no symbols referenced by the binary. This is useful if your code isn't explicitly called by code in the binary; for example, if you rely on runtime checks for protocol conformances added in extensions in the library but do not directly reference any other symbols in the object file that adds that conformance.</p></td> </tr> <tr id="swift_library.copts"> <td><code>copts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional compiler options that should be passed to <code>swiftc</code>. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_library.defines"> <td><code>defines</code></td> <td> <p><code>List of strings; optional</code></p><p>A list of defines to add to the compilation command line.</p> <p>Note that unlike C-family languages, Swift defines do not have values; they are simply identifiers that are either defined or undefined. So strings in this list should be simple identifiers, <strong>not</strong> <code>name=value</code> pairs.</p> <p>Each string is prepended with <code>-D</code> and added to the command line. Unlike <code>copts</code>, these flags are added for the target and every target that depends on it, so use this attribute with caution. It is preferred that you add defines directly to <code>copts</code>, only using this feature in the rare case that a library needs to propagate a symbol up to those that depend on it.</p></td> </tr> <tr id="swift_library.linkopts"> <td><code>linkopts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional linker options that should be passed to the linker for the binary that depends on this target. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_library.module_name"> <td><code>module_name</code></td> <td> <p><code>String; optional</code></p><p>The name of the Swift module being built.</p> <p>If left unspecified, the module name will be computed based on the target's build label, by stripping the leading <code>//</code> and replacing <code>/</code>, <code>:</code>, and other non-identifier characters with underscores.</p></td> </tr> <tr id="swift_library.swiftc_inputs"> <td><code>swiftc_inputs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Additional files that are referenced using <code>$(location ...)</code> in attributes that support location expansion.</p></td> </tr> </tbody> </table> <a name="swift_module_alias"></a> ## swift_module_alias <pre style="white-space: normal"> swift_module_alias(<a href="#swift_module_alias.name">name</a>, <a href="#swift_module_alias.deps">deps</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="#swift_module_alias.module_name">module_name</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Creates a Swift module that re-exports other modules. This rule effectively creates an "alias" for one or more modules such that a client can import the alias module and it will implicitly import those dependencies. It should be used primarily as a way to migrate users when a module name is being changed. An alias that depends on more than one module can be used to split a large module into smaller, more targeted modules. Symbols in the original modules can be accessed through either the original module name or the alias module name, so callers can be migrated separately after moving the physical build target as needed. (An exception to this is runtime type metadata, which only encodes the module name of the type where the symbol is defined; it is not repeated by the alias module.) > Caution: This rule uses the undocumented `@_exported` feature to re-export the > `deps` in the new module. You depend on undocumented features at your own > risk, as they may change in a future version of Swift. <a name="swift_module_alias.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_module_alias.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_module_alias.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds are <code>swift_import</code> and <code>swift_library</code> (or anything else propagating <code>SwiftInfo</code>).</p></td> </tr> <tr id="swift_module_alias.module_name"> <td><code>module_name</code></td> <td> <p><code>String; optional</code></p><p>The name of the Swift module being built.</p> <p>If left unspecified, the module name will be computed based on the target's build label, by stripping the leading <code>//</code> and replacing <code>/</code>, <code>:</code>, and other non-identifier characters with underscores.</p></td> </tr> </tbody> </table> <a name="swift_proto_library"></a> ## swift_proto_library <pre style="white-space: normal"> swift_proto_library(<a href="#swift_proto_library.name">name</a>, <a href="#swift_proto_library.deps">deps</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Generates a Swift library from protocol buffer sources. There should be one `swift_proto_library` for any `proto_library` that you wish to depend on. A target based on this rule can be used as a dependency anywhere that a `swift_library` can be used. A `swift_proto_library` target only creates a Swift module if the `proto_library` on which it depends has a non-empty `srcs` attribute. If the `proto_library` does not contain `srcs`, then no module is produced, but the `swift_proto_library` still propagates the modules of its non-empty dependencies so that those generated protos can be used by depending on the `swift_proto_library` of the "collector" target. Note that the module name of the Swift library produced by this rule (if any) is based on the name of the `proto_library` target, *not* the name of the `swift_proto_library` target. In other words, if the following BUILD file were located in `//my/pkg`, the target would create a Swift module named `my_pkg_foo`: ```python proto_library( name = "foo", srcs = ["foo.proto"], ) swift_proto_library( name = "foo_swift", deps = [":foo"], ) ``` Because the Swift modules are generated from an aspect that is applied to the `proto_library` targets, the module name and other compilation flags for the resulting Swift modules cannot be changed. #### Tip: Where to locate `swift_proto_library` targets Convention is to put the `swift_proto_library` in the same `BUILD` file as the `proto_library` it is generating for (just like all the other `LANG_proto_library` rules). This lets anyone needing the protos in Swift share the single rule as well as making it easier to realize what proto files are in use in what contexts. This is not a requirement, however, as it may not be possible for Bazel workspaces that create `swift_proto_library` targets that depend on `proto_library` targets from different repositories. #### Tip: Avoid `import` only `.proto` files Avoid creating a `.proto` file that just contains `import` directives of all the other `.proto` files you need. While this does _group_ the protos into this new target, it comes with some high costs. This causes the proto compiler to parse all those files and invoke the generator for an otherwise empty source file. That empty source file then has to get compiled, but it will have dependencies on the full deps chain of the imports (recursively). The Swift compiler must load all of these module dependencies, which can be fairly slow if there are many of them, so this method of grouping via a `.proto` file actually ends up creating build steps that slow down the build. #### Tip: Resolving unused import warnings If you see warnings like the following during your build: ``` path/file.proto: warning: Import other/path/file.proto but not used. ``` The proto compiler is letting you know that you have an `import` statement loading a file from which nothing is used, so it is wasted work. The `import` can be removed (in this case, `import other/path/file.proto` could be removed from `path/file.proto`). These warnings can also mean that the `proto_library` has `deps` that aren't needed. Removing those along with the `import` statement(s) will speed up downstream Swift compilation actions, because it prevents unused modules from being loaded by `swiftc`. <a name="swift_proto_library.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_proto_library.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_proto_library.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Exactly one <code>proto_library</code> target (or any target that propagates a <code>proto</code> provider) from which the Swift library should be generated.</p></td> </tr> </tbody> </table> <a name="swift_test"></a> ## swift_test <pre style="white-space: normal"> swift_test(<a href="#swift_test.name">name</a>, <a href="#swift_test.deps">deps</a>, <a href="#swift_test.srcs">srcs</a>, <a href="#swift_test.data">data</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.args">args</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.compatible_with">compatible_with</a>, <a href="#swift_test.copts">copts</a>, <a href="#swift_test.defines">defines</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.deprecation">deprecation</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.distribs">distribs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.features">features</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.flaky">flaky</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.licenses">licenses</a>, <a href="#swift_test.linkopts">linkopts</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.local">local</a>, <a href="#swift_test.malloc">malloc</a>, <a href="#swift_test.module_name">module_name</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.restricted_to">restricted_to</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.shardcount">shardcount</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.size">size</a>, <a href="#swift_test.swiftc_inputs">swiftc_inputs</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.tags">tags</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly">testonly</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#test.timeout">timeout</a>, <a href="https://docs.bazel.build/versions/master/be/common-definitions.html#common.visibility">visibility</a>) </pre> Compiles and links Swift code into an executable test target. The behavior of `swift_test` differs slightly for macOS targets, in order to provide seamless integration with Apple's XCTest framework. The output of the rule is still a binary, but one whose Mach-O type is `MH_BUNDLE` (a loadable bundle). Thus, the binary cannot be launched directly. Instead, running `bazel test` on the target will launch a test runner script that copies it into an `.xctest` bundle directory and then launches the `xctest` helper tool from Xcode, which uses Objective-C runtime reflection to locate the tests. On Linux, the output of a `swift_test` is a standard executable binary, because the implementation of XCTest on that platform currently requires authors to explicitly list the tests that are present and run them from their main program. Test bundling on macOS can be disabled on a per-target basis, if desired. You may wish to do this if you are not using XCTest, but rather a different test framework (or no framework at all) where the pass/fail outcome is represented as a zero/non-zero exit code (as is the case with other Bazel test rules like `cc_test`). To do so, disable the `"swift.bundled_xctests"` feature on the target: ```python swift_test( name = "MyTests", srcs = [...], features = ["-swift.bundled_xctests"], ) ``` You can also disable this feature for all the tests in a package by applying it to your BUILD file's `package()` declaration instead of the individual targets. <a name="swift_test.attributes"></a> ### Attributes <table class="params-table"> <colgroup> <col class="col-param" /> <col class="col-description" /> </colgroup> <tbody> <tr id="swift_test.name"> <td><code>name</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#name">Name</a>; required</code></p><p>A unique name for this target.</p></td> </tr> <tr id="swift_test.deps"> <td><code>deps</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds of dependencies are:</p> <ul> <li><code>swift_c_module</code>, <code>swift_import</code> and <code>swift_library</code> (or anything propagating <code>SwiftInfo</code>)</li> <li><code>cc_library</code> (or anything propagating <code>CcInfo</code>)</li> </ul> <p>Additionally, on platforms that support Objective-C interop, <code>objc_library</code> targets (or anything propagating the <code>apple_common.Objc</code> provider) are allowed as dependencies. On platforms that do not support Objective-C interop (such as Linux), those dependencies will be <strong>ignored.</strong></p></td> </tr> <tr id="swift_test.srcs"> <td><code>srcs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>A list of <code>.swift</code> source files that will be compiled into the library.</p></td> </tr> <tr id="swift_test.data"> <td><code>data</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>The list of files needed by this target at runtime.</p> <p>Files and targets named in the <code>data</code> attribute will appear in the <code>*.runfiles</code> area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it.</p></td> </tr> <tr id="swift_test.copts"> <td><code>copts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional compiler options that should be passed to <code>swiftc</code>. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_test.defines"> <td><code>defines</code></td> <td> <p><code>List of strings; optional</code></p><p>A list of defines to add to the compilation command line.</p> <p>Note that unlike C-family languages, Swift defines do not have values; they are simply identifiers that are either defined or undefined. So strings in this list should be simple identifiers, <strong>not</strong> <code>name=value</code> pairs.</p> <p>Each string is prepended with <code>-D</code> and added to the command line. Unlike <code>copts</code>, these flags are added for the target and every target that depends on it, so use this attribute with caution. It is preferred that you add defines directly to <code>copts</code>, only using this feature in the rare case that a library needs to propagate a symbol up to those that depend on it.</p></td> </tr> <tr id="swift_test.linkopts"> <td><code>linkopts</code></td> <td> <p><code>List of strings; optional</code></p><p>Additional linker options that should be passed to <code>clang</code>. These strings are subject to <code>$(location ...)</code> expansion.</p></td> </tr> <tr id="swift_test.malloc"> <td><code>malloc</code></td> <td> <p><code><a href="https://docs.bazel.build/versions/master/build-ref.html#labels">Label</a>; optional; default is @bazel_tools//tools/cpp:malloc</code></p><p>Override the default dependency on <code>malloc</code>.</p> <p>By default, Swift binaries are linked against <code>@bazel_tools//tools/cpp:malloc"</code>, which is an empty library and the resulting binary will use libc's <code>malloc</code>. This label must refer to a <code>cc_library</code> rule.</p></td> </tr> <tr id="swift_test.module_name"> <td><code>module_name</code></td> <td> <p><code>String; optional</code></p><p>The name of the Swift module being built.</p> <p>If left unspecified, the module name will be computed based on the target's build label, by stripping the leading <code>//</code> and replacing <code>/</code>, <code>:</code>, and other non-identifier characters with underscores.</p></td> </tr> <tr id="swift_test.swiftc_inputs"> <td><code>swiftc_inputs</code></td> <td> <p><code>List of <a hef="https://docs.bazel.build/versions/master/build-ref.html#labels">labels</a>; optional</code></p><p>Additional files that are referenced using <code>$(location ...)</code> in attributes that support location expansion.</p></td> </tr> </tbody> </table> 07070100000010000081A4000003E800000064000000015D9E3463000001A7000000000000000000000000000000000000002600000000bazel-rules-swift-0.13.0/doc/setup.md# Workspace Setup <a href="swift_rules_dependencies"></a> ## swift_rules_dependencies <pre style="white-space: pre-wrap"> swift_rules_dependencies() </pre> Fetches repositories that are dependencies of the `rules_swift` workspace. Users should call this macro in their `WORKSPACE` to ensure that all of the dependencies of the Swift rules are downloaded and that they are isolated from changes to those dependencies. 07070100000011000041ED000003E800000064000000045D9E346300000000000000000000000000000000000000000000002200000000bazel-rules-swift-0.13.0/examples07070100000012000041ED000003E800000064000000035D9E346300000000000000000000000000000000000000000000002800000000bazel-rules-swift-0.13.0/examples/apple07070100000013000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/examples/apple/objc_interop07070100000014000081A4000003E800000064000000015D9E34630000026F000000000000000000000000000000000000003B00000000bazel-rules-swift-0.13.0/examples/apple/objc_interop/BUILD# This example tests that Swift code can be called from Objective-C code and # vice versa when it is linked into the existing native linking rules for Apple # platforms. load( "//swift:swift.bzl", "swift_binary", "swift_library", ) licenses(["notice"]) objc_library( name = "PrintStream", srcs = ["OIPrintStream.m"], hdrs = ["OIPrintStream.h"], ) swift_library( name = "Printer", srcs = ["Printer.swift"], deps = [":PrintStream"], ) objc_library( name = "main", srcs = ["main.m"], deps = [":Printer"], ) swift_binary( name = "objc_interop", deps = [":main"], ) 07070100000015000081A4000003E800000064000000015D9E34630000037E000000000000000000000000000000000000004500000000bazel-rules-swift-0.13.0/examples/apple/objc_interop/OIPrintStream.h// Copyright 2018 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. #import <Foundation/Foundation.h> /** A very contrived interface for writing strings to a file handle. */ @interface OIPrintStream: NSObject - (nonnull instancetype)initWithFileHandle:(nonnull NSFileHandle *)fileHandle; - (void)printString:(nonnull NSString *)message; @end 07070100000016000081A4000003E800000064000000015D9E346300000472000000000000000000000000000000000000004500000000bazel-rules-swift-0.13.0/examples/apple/objc_interop/OIPrintStream.m// Copyright 2018 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. #import "examples/apple/objc_interop/OIPrintStream.h" @implementation OIPrintStream { NSFileHandle *_fileHandle; } - (instancetype)initWithFileHandle:(nonnull NSFileHandle *)fileHandle { if (self = [super init]) { _fileHandle = fileHandle; } return self; } - (void)printString:(nonnull NSString *)message { NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding]; [_fileHandle writeData:data]; NSData *newline = [NSData dataWithBytes:"\n" length:1]; [_fileHandle writeData:newline]; } @end 07070100000017000081A4000003E800000064000000015D9E34630000040B000000000000000000000000000000000000004300000000bazel-rules-swift-0.13.0/examples/apple/objc_interop/Printer.swift// Copyright 2018 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. import Foundation import examples_apple_objc_interop_PrintStream @objc(OIPrinter) public class Printer: NSObject { private let stream: OIPrintStream private let prefix: String @objc public init(prefix: NSString) { self.stream = OIPrintStream(fileHandle: .standardOutput) self.prefix = prefix as String } @objc public func print(_ message: NSString) { stream.print("\(prefix)\(message)") } } 07070100000018000081A4000003E800000064000000015D9E34630000049E000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/examples/apple/objc_interop/main.m// Copyright 2018 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. // The Swift compiler generates an Objective-C header at a path of the form // "bazel-genfiles/<target_package>/<target_name>-Swift.h". Since the Obj-C // rules automatically add "bazel-genfiles" to the include path, the file should // be imported using a workspace-relative path to access the Obj-C interface for // the Swift code. #import "examples/apple/objc_interop/Printer-Swift.h" int main(int argc, char **argv) { @autoreleasepool { OIPrinter *printer = [[OIPrinter alloc] initWithPrefix:@"*** "]; [printer print:@"Hello world"]; } return 0; } 07070100000019000041ED000003E800000064000000085D9E346300000000000000000000000000000000000000000000002C00000000bazel-rules-swift-0.13.0/examples/xplatform0707010000001A000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003900000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift0707010000001B000081A4000003E800000064000000015D9E346300000418000000000000000000000000000000000000003F00000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/BUILDload("//swift:swift.bzl", "swift_binary", "swift_library") licenses(["notice"]) # 1. This library has some C++ code that you want to interact with from Swift... cc_library( name = "counter", srcs = ["counter.cc"], hdrs = ["counter.h"], ) # 2. ...but Swift can't import C++ yet, so we implement a wrapper API in C. cc_library( name = "c_counter", srcs = ["c_counter.cc"], hdrs = ["c_counter.h"], tags = ["swift_module=CCounter"], deps = [":counter"], ) # 3. The Swift library then depends on the `cc_library`. This causes a # Swift-compatible module map to be created for the `cc_library` so that the # Swift code can import it. swift_library( name = "swift_counter", srcs = ["Counter.swift"], module_name = "Counter", deps = [":c_counter"], ) # 4. Finally, this binary is a straightforward target with no surprises. It just # imports the Swift `Counter` module above. swift_binary( name = "c_from_swift", srcs = ["main.swift"], module_name = "main", deps = [":swift_counter"], ) 0707010000001C000081A4000003E800000064000000015D9E346300000438000000000000000000000000000000000000004700000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/Counter.swift// Copyright 2018 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. // Import the C interface. import CCounter /// Wraps the C interface in a Swift interface. public class Counter { private let counter: counter_t public var value: Int { // The cast is required because C `int` is imported to Swift as `Int32`. return Int(counter_get(counter)) } public init() { self.counter = counter_create() } deinit { counter_release(counter) } public func increment() { counter_increment(counter) } } 0707010000001D000081A4000003E800000064000000015D9E3463000004A7000000000000000000000000000000000000004600000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/c_counter.cc// Copyright 2018 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. #include "examples/xplatform/c_from_swift/c_counter.h" #include "examples/xplatform/c_from_swift/counter.h" using ::swiftexample::Counter; counter_t counter_create() { Counter *counter = new Counter(); return static_cast<counter_t>(counter); } void counter_release(counter_t c) { Counter *counter = static_cast<Counter *>(c); delete counter; } int counter_get(counter_t c) { Counter *counter = static_cast<Counter *>(c); return counter->Get(); } void counter_increment(counter_t c) { Counter *counter = static_cast<Counter *>(c); counter->Increment(); } 0707010000001E000081A4000003E800000064000000015D9E3463000003C7000000000000000000000000000000000000004500000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/c_counter.h// Copyright 2018 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. #if __cplusplus extern "C" { #endif // An opaque type that represents a pointer to the C++ Counter type in C APIs. typedef void *counter_t; // C functions that correspond to the C++ interface. counter_t counter_create(); void counter_release(counter_t c); int counter_get(counter_t c); void counter_increment(counter_t c); #if __cplusplus } #endif 0707010000001F000081A4000003E800000064000000015D9E34630000032B000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/counter.cc// Copyright 2018 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. #include "examples/xplatform/c_from_swift/counter.h" namespace swiftexample { int Counter::Get() const { return count_; } void Counter::Increment() { ++count_; } } // namespace swiftexample 07070100000020000081A4000003E800000064000000015D9E346300000300000000000000000000000000000000000000004300000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/counter.h// Copyright 2018 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. namespace swiftexample { class Counter { public: int Get() const; void Increment(); private: int count_ = 0; }; } // namespace swiftexample 07070100000021000081A4000003E800000064000000015D9E346300000308000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/examples/xplatform/c_from_swift/main.swift// Copyright 2018 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. // Import the Swift interface. import Counter let counter = Counter() for _ in 1...10 { counter.increment() } // This should print 10. print(counter.value) 07070100000022000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/examples/xplatform/dispatch07070100000023000081A4000003E800000064000000015D9E346300000083000000000000000000000000000000000000003B00000000bazel-rules-swift-0.13.0/examples/xplatform/dispatch/BUILDload("//swift:swift.bzl", "swift_binary") licenses(["notice"]) swift_binary( name = "dispatch", srcs = ["main.swift"], ) 07070100000024000081A4000003E800000064000000015D9E346300000A41000000000000000000000000000000000000004000000000bazel-rules-swift-0.13.0/examples/xplatform/dispatch/main.swift// Copyright 2018 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. // This example prints the contents of `CommandLine.arguments` (so, the invoking // command followed by any other arguments) one after the other in one-second // intervals. // // NOTE: Do not run this target using "bazel run". Instead, build it and then // run the resulting executable manually. Bazel adds additional output buffering // that interferes with the timed nature of this example. import Dispatch #if os(Linux) import Glibc #else import Darwin #endif extension DispatchQueue { /// Enqueues a block to execute asynchronously after a deadline in a given /// dispatch group. /// /// This is a handy helper function that was written because the existing /// `DispatchQueue` APIs only support async after a deadline or async in a /// group, but not both at the same time. /// /// - Parameters: /// - deadline: The time after which the block should execute. /// - group: The dispatch group with which the block should enter and leave. /// - work: The block to execute. func asyncAfter( deadline: DispatchTime, group: DispatchGroup, execute work: @escaping () -> Void ) { group.enter() asyncAfter(deadline: deadline) { work() group.leave() } } } let mainQueue = DispatchQueue.main let group = DispatchGroup() // Print each of the arguments in one-second intervals. Use a dispatch group to // collect the tasks so that we can wait on their full completion below. for (index, argument) in CommandLine.arguments.enumerated() { mainQueue.asyncAfter(deadline: .now() + .seconds(index), group: group) { print("Hello, \(argument)!") } } // Wait for all of the enqueued tasks in the group to end, then print a final // message and exit. Note that the explicit call to `exit` is required to end // the process because `dispatchMain` never returns. group.notify(queue: mainQueue) { print("Goodbye!") exit(0) } // Park the main thread, waiting for blocks to be submitted to the main queue // and executing them. dispatchMain() 07070100000025000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003100000000bazel-rules-swift-0.13.0/examples/xplatform/grpc07070100000026000081A4000003E800000064000000015D9E346300000713000000000000000000000000000000000000003700000000bazel-rules-swift-0.13.0/examples/xplatform/grpc/BUILD# This example illustrates how to use `swift_grpc_library` along with # `swift_proto_library` to build Swift binaries for a gRPC server and # client. # # To explore this example: # # 1. Build both the `:echo_server` and `:echo_client` targets in this package. # 2. Run the `echo_server` binary in the background of a terminal. It should # print a message indicating that the service has started. # 3. Run the `echo_client` binary in the same terminal. It will send a request # to this service and then print the response that it received. load( "//swift:swift.bzl", "swift_binary", "swift_grpc_library", "swift_proto_library", "swift_test", ) licenses(["notice"]) proto_library( name = "echo_proto", srcs = ["echo.proto"], deps = [ "@com_google_protobuf//:any_proto", ], ) swift_proto_library( name = "echo_proto_swift", deps = [":echo_proto"], ) swift_grpc_library( name = "echo_client_services_swift", srcs = [":echo_proto"], flavor = "client", deps = [":echo_proto_swift"], ) swift_grpc_library( name = "echo_client_test_stubs_swift", srcs = [":echo_proto"], flavor = "client_stubs", deps = [":echo_client_services_swift"], ) swift_grpc_library( name = "echo_server_services_swift", srcs = [":echo_proto"], flavor = "server", deps = [":echo_proto_swift"], ) swift_binary( name = "echo_server", srcs = ["server_main.swift"], deps = [":echo_server_services_swift"], ) swift_test( name = "echo_client_unit_test", srcs = ["client_unit_test.swift"], deps = [ ":echo_client_services_swift", ":echo_client_test_stubs_swift", ], ) swift_binary( name = "echo_client", srcs = ["client_main.swift"], deps = [":echo_client_services_swift"], ) 07070100000027000081A4000003E800000064000000015D9E3463000004F1000000000000000000000000000000000000004300000000bazel-rules-swift-0.13.0/examples/xplatform/grpc/client_main.swift// Copyright 2019 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. import Foundation import SwiftProtobuf import examples_xplatform_grpc_echo_proto import examples_xplatform_grpc_echo_client_services_swift // Initialize the client using the same address the server is started on. let client = EchoServiceServiceClient(address: "0.0.0.0:9000", secure: false) // Construct a request to the echo service. var request = EchoRequest() request.contents = "Hello, world!" let timestamp = Google_Protobuf_Timestamp(date: Date()) request.extra = try! Google_Protobuf_Any(message: timestamp) // Make the remote method call and print the response we receive. let response = try client.echo(request) print(response.contents) 07070100000028000081A4000003E800000064000000015D9E3463000004A0000000000000000000000000000000000000004800000000bazel-rules-swift-0.13.0/examples/xplatform/grpc/client_unit_test.swift// Copyright 2019 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. import XCTest import examples_xplatform_grpc_echo_client_services_swift import examples_xplatform_grpc_echo_proto @testable import examples_xplatform_grpc_echo_client_test_stubs_swift class ClientUnitTest { func testSynchronousCall() throws { let client: EchoServiceService = { let stub = EchoServiceServiceTestStub() stub.echoResponses.append(EchoResponse.with { response in response.contents = "Hello" }) return stub }() let response = try client.echo(EchoRequest()) XCTAssertEqual(response.contents, "Hello") } } 07070100000029000081A4000003E800000064000000015D9E34630000036B000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/examples/xplatform/grpc/echo.proto// Copyright 2019 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. syntax = "proto3"; import "google/protobuf/any.proto"; service EchoService { rpc Echo(EchoRequest) returns (EchoResponse); } message EchoRequest { string contents = 1; google.protobuf.Any extra = 2; } message EchoResponse { string contents = 1; } 0707010000002A000081A4000003E800000064000000015D9E3463000006CB000000000000000000000000000000000000004300000000bazel-rules-swift-0.13.0/examples/xplatform/grpc/server_main.swift// Copyright 2019 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. import Dispatch import SwiftGRPC import examples_xplatform_grpc_echo_proto import examples_xplatform_grpc_echo_server_services_swift /// Concrete implementation of the `EchoService` service definition. class EchoProvider: EchoServiceProvider { /// Called when the server receives a request for the `EchoService.Echo` method. /// /// - Parameters: /// - request: The message containing the request parameters. /// - session: Information about the current session. /// - Returns: The response that will be sent back to the client. /// - Throws: If an error occurs while processing the request. func echo(request: EchoRequest, session: EchoServiceEchoSession) throws -> EchoResponse { var response = EchoResponse() response.contents = "You sent: \(request.contents)" return response } } // Initialize and start the service. let address = "0.0.0.0:9000" let server = ServiceServer(address: address, serviceProviders: [EchoProvider()]) print("Starting server in \(address)") server.start() // Park the main thread so that the server continues to run and listen for requests. dispatchMain() 0707010000002B000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/examples/xplatform/hello_world0707010000002C000081A4000003E800000064000000015D9E346300000086000000000000000000000000000000000000003E00000000bazel-rules-swift-0.13.0/examples/xplatform/hello_world/BUILDload("//swift:swift.bzl", "swift_binary") licenses(["notice"]) swift_binary( name = "hello_world", srcs = ["main.swift"], ) 0707010000002D000081A4000003E800000064000000015D9E34630000027F000000000000000000000000000000000000004300000000bazel-rules-swift-0.13.0/examples/xplatform/hello_world/main.swift// Copyright 2018 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. print("Hello, world!") 0707010000002E000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003200000000bazel-rules-swift-0.13.0/examples/xplatform/proto0707010000002F000081A4000003E800000064000000015D9E3463000001B0000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/examples/xplatform/proto/BUILDload( "//swift:swift.bzl", "swift_binary", "swift_proto_library", ) licenses(["notice"]) proto_library( name = "example_proto", srcs = ["example.proto"], deps = [ "@com_google_protobuf//:api_proto", ], ) swift_proto_library( name = "example_proto_swift", deps = [":example_proto"], ) swift_binary( name = "proto", srcs = ["main.swift"], deps = [":example_proto_swift"], ) 07070100000030000081A4000003E800000064000000015D9E34630000031E000000000000000000000000000000000000004000000000bazel-rules-swift-0.13.0/examples/xplatform/proto/example.proto// Copyright 2018 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. syntax = "proto3"; import "google/protobuf/api.proto"; message Person { string name = 1; int32 age = 2; } message Server { string name = 1; google.protobuf.Api api = 2; } 07070100000031000081A4000003E800000064000000015D9E34630000049E000000000000000000000000000000000000003D00000000bazel-rules-swift-0.13.0/examples/xplatform/proto/main.swift// Copyright 2018 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. import Foundation import SwiftProtobuf import examples_xplatform_proto_example_proto let person = Person.with { $0.name = "Firstname Lastname" $0.age = 30 } let data = try! person.serializedData() print(Array(data)) let server = Server.with { $0.name = "My Server" $0.api.name = "My API" let option = Google_Protobuf_Option.with { $0.name = "Person Option" if let value = try? Google_Protobuf_Any(message: person) { $0.value = value } } $0.api.options.append(option) } let data2 = try! server.serializedData() print(Array(data2)) 07070100000032000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003300000000bazel-rules-swift-0.13.0/examples/xplatform/xctest07070100000033000081A4000003E800000064000000015D9E3463000000A9000000000000000000000000000000000000003900000000bazel-rules-swift-0.13.0/examples/xplatform/xctest/BUILDload("//swift:swift.bzl", "swift_test") licenses(["notice"]) swift_test( name = "xctest", srcs = [ "SimpleTests.swift", "main.swift", ], ) 07070100000034000081A4000003E800000064000000015D9E3463000004BE000000000000000000000000000000000000004500000000bazel-rules-swift-0.13.0/examples/xplatform/xctest/SimpleTests.swift// Copyright 2018 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. import XCTest class SimpleTests: XCTestCase { var value: Int = 0 override func setUp() { value = 4 } func testThatWillSucceed() { XCTAssertEqual(value, 4) } func testThatWillFailIfChanged() { // Change the second argument from 4 to something else to see this test // fail. We don't make it fail in the submitted code because we don't want // TAP to go red for an intentional failure. XCTAssertEqual(value, 4) } static var allTests = [ ("testThatWillSucceed", testThatWillSucceed), ("testThatWillFailIfChanged", testThatWillFailIfChanged), ] } 07070100000035000081A4000003E800000064000000015D9E3463000002BB000000000000000000000000000000000000003E00000000bazel-rules-swift-0.13.0/examples/xplatform/xctest/main.swift// Copyright 2018 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. #if os(Linux) import XCTest XCTMain([ testCase(SimpleTests.allTests), ]) #endif 07070100000036000041ED000003E800000064000000035D9E346300000000000000000000000000000000000000000000001F00000000bazel-rules-swift-0.13.0/swift07070100000037000081A4000003E800000064000000015D9E34630000023A000000000000000000000000000000000000002500000000bazel-rules-swift-0.13.0/swift/BUILDpackage(default_visibility = ["//visibility:public"]) licenses(["notice"]) load("@bazel_skylib//rules:common_settings.bzl", "bool_setting") exports_files([ "swift.bzl", ]) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]) + [ "//swift/internal:for_bazel_tests", ], visibility = [ "//:__pkg__", ], ) # Configuration setting for enabling the generation of swiftinterface files. bool_setting( name = "emit_swiftinterface", build_setting_default = False, ) 07070100000038000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002800000000bazel-rules-swift-0.13.0/swift/internal07070100000039000081A4000003E800000064000000015D9E34630000020D000000000000000000000000000000000000002E00000000bazel-rules-swift-0.13.0/swift/internal/BUILDpackage(default_visibility = ["//:__subpackages__"]) licenses(["notice"]) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]) + [ # We should be depending on a filegroup here that represents this file # and its dependencies, but it doesn't exist yet. "@bazel_tools//tools/cpp:toolchain_utils.bzl", "@bazel_tools//tools/build_defs/cc:action_names_test_files", ], visibility = [ "//swift:__pkg__", ], ) 0707010000003A000081A4000003E800000064000000015D9E346300000F9D000000000000000000000000000000000000003400000000bazel-rules-swift-0.13.0/swift/internal/actions.bzl# Copyright 2018 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. """Functions for registering actions that invoke Swift tools.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//lib:types.bzl", "types") def get_swift_tool(swift_toolchain, tool): """Gets the path to the given Swift toolchain tool. Args: swift_toolchain: The Swift toolchain being used to register actions. tool: The name of a tool in the Swift toolchain (i.e., in the `bin` directory). Returns: The path to the tool. If the toolchain provides a root directory, then the path will include the `bin` directory of that toolchain. If the toolchain does not provide a root, then it is assumed that the tool will be available by invoking just its name (e.g., found on the system path or by another delegating tool like `xcrun` from Xcode). """ if ("/" not in tool and swift_toolchain.root_dir): return paths.join(swift_toolchain.root_dir, "bin", tool) return tool def run_swift_action(actions, swift_toolchain, **kwargs): """Executes a Swift toolchain tool using the worker. This function applies the toolchain's environment and execution requirements and wraps the invocation in the worker tool that handles platform-specific requirements (for example, `xcrun` on Darwin) and in additional pre- and post-processing to handle certain tasks like debug prefix remapping and module cache health. Since this function uses the worker as the `executable` of the underlying action, it is an error to pass `executable` into this function. Instead, the tool to run should be the first item in the `arguments` list (or in the first `Args` object). This tool should be obtained using `get_swift_tool` in order to correctly handle toolchains with explicit root directories. Args: actions: The `Actions` object with which to register actions. swift_toolchain: The Swift toolchain being used to register actions. **kwargs: Additional arguments to `actions.run`. """ if "executable" in kwargs: fail("run_swift_action does not support 'executable'. " + "The tool to run should be the first item in 'arguments'.") remaining_args = dict(kwargs) # Note that we add the toolchain values second; we do not want the caller to # ever be able to override those values. env = dicts.add( remaining_args.pop("env", None) or {}, swift_toolchain.action_environment or {}, ) execution_requirements = dicts.add( remaining_args.pop("execution_requirements", None) or {}, swift_toolchain.execution_requirements or {}, ) # Add the toolchain's files to the `tools` argument of the action. user_tools = remaining_args.pop("tools", None) toolchain_files = swift_toolchain.all_files if types.is_list(user_tools): tools = depset(user_tools, transitive = [toolchain_files]) elif type(user_tools) == type(depset()): tools = depset(transitive = [user_tools, toolchain_files]) elif user_tools: fail("'tools' argument must be a sequence or depset.") else: tools = toolchain_files actions.run( env = env, executable = swift_toolchain.swift_worker, execution_requirements = execution_requirements, tools = tools, **remaining_args ) 0707010000003B000081A4000003E800000064000000015D9E34630000C800000000000000000000000000000000000000003000000000bazel-rules-swift-0.13.0/swift/internal/api.bzl# Copyright 2018 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. """A resilient API layer wrapping compilation and other logic for Swift. This module is meant to be used by custom rules that need to compile Swift code and cannot simply rely on writing a macro that wraps `swift_library`. For example, `swift_proto_library` generates Swift source code from `.proto` files and then needs to compile them. This module provides that lower-level interface. Do not load this file directly; instead, load the top-level `swift.bzl` file, which exports the `swift_common` module. """ load("@bazel_skylib//lib:collections.bzl", "collections") load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:new_sets.bzl", "sets") load("@bazel_skylib//lib:partial.bzl", "partial") load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_skylib//lib:types.bzl", "types") load(":actions.bzl", "get_swift_tool", "run_swift_action") load(":attrs.bzl", "swift_common_rule_attrs") load( ":compiling.bzl", "collect_transitive_compile_inputs", "declare_compile_outputs", "objc_compile_requirements", "register_autolink_extract_action", "write_objc_header_module_map", ) load(":debugging.bzl", "ensure_swiftmodule_is_embedded") load(":derived_files.bzl", "derived_files") load( ":features.bzl", "SWIFT_FEATURE_AUTOLINK_EXTRACT", "SWIFT_FEATURE_CACHEABLE_SWIFTMODULES", "SWIFT_FEATURE_COMPILE_STATS", "SWIFT_FEATURE_COVERAGE", "SWIFT_FEATURE_DBG", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_EMIT_SWIFTINTERFACE", "SWIFT_FEATURE_ENABLE_BATCH_MODE", "SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION", "SWIFT_FEATURE_ENABLE_TESTING", "SWIFT_FEATURE_FASTBUILD", "SWIFT_FEATURE_FULL_DEBUG_INFO", "SWIFT_FEATURE_INDEX_WHILE_BUILDING", "SWIFT_FEATURE_MINIMAL_DEPS", "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD", "SWIFT_FEATURE_NO_GENERATED_HEADER", "SWIFT_FEATURE_NO_GENERATED_MODULE_MAP", "SWIFT_FEATURE_OPT", "SWIFT_FEATURE_OPT_USES_WMO", "SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION", "SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE", "SWIFT_FEATURE_USE_RESPONSE_FILES", ) load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo") # The Swift copts to pass for various sanitizer features. _SANITIZER_FEATURE_FLAG_MAP = { "asan": ["-sanitize=address"], "tsan": ["-sanitize=thread"], } def _create_swift_info( defines = [], generated_headers = [], modulemaps = [], module_name = None, swiftdocs = [], swiftmodules = [], swiftinterfaces = [], swift_infos = [], swift_version = None): """Creates a new `SwiftInfo` provider with the given values. This function is recommended instead of directly creating a `SwiftInfo` provider because it encodes reasonable defaults for fields that some rules may not be interested in and ensures that the direct and transitive fields are set consistently. This function can also be used to do a simple merge of `SwiftInfo` providers, by leaving all of the arguments except for `swift_infos` as their empty defaults. In that case, the returned provider will not represent a true Swift module; it is merely a "collector" for other dependencies. Args: defines: A list of defines that will be provided as `copts` of the target being built. generated_headers: A list of headers generated by Swift for Objective-C interop for the target being built. modulemaps: A list of module maps that should be passed to ClangImporter by any target that depends on the one propagating this provider. module_name: A string containing the name of the Swift module. If this is `None`, the provider does not represent a compiled module but rather a collection of modules (this happens, for example, with `proto_library` targets that have no sources of their own but depend on others that do). swiftdocs: A list of `.swiftdoc` files that are the direct outputs of the target being built. If omitted, an empty list is used. swiftinterfaces: A list of `.swiftinterface` files that are the direct outputs of the target built. If omitted, an empty list is used. swiftmodules: A list of `.swiftmodule` files that are the direct outputs of the target being built. If omitted, an empty list is used. swift_infos: A list of `SwiftInfo` providers from dependencies, whose transitive fields should be merged into the new one. If omitted, no transitive data is collected. swift_version: A string containing the value of the `-swift-version` flag used when compiling this target, or `None` (the default) if it was not set or is not relevant. Returns: A new `SwiftInfo` provider with the given values. """ transitive_defines = [] transitive_generated_headers = [] transitive_modulemaps = [] transitive_swiftdocs = [] transitive_swiftinterfaces = [] transitive_swiftmodules = [] for swift_info in swift_infos: transitive_defines.append(swift_info.transitive_defines) transitive_generated_headers.append(swift_info.transitive_generated_headers) transitive_modulemaps.append(swift_info.transitive_modulemaps) transitive_swiftdocs.append(swift_info.transitive_swiftdocs) transitive_swiftinterfaces.append(swift_info.transitive_swiftinterfaces) transitive_swiftmodules.append(swift_info.transitive_swiftmodules) return SwiftInfo( direct_defines = defines, direct_swiftdocs = swiftdocs, direct_swiftmodules = swiftmodules, module_name = module_name, swift_version = swift_version, transitive_defines = depset(defines, transitive = transitive_defines), transitive_generated_headers = depset( generated_headers, transitive = transitive_generated_headers, ), transitive_modulemaps = depset(modulemaps, transitive = transitive_modulemaps), transitive_swiftdocs = depset(swiftdocs, transitive = transitive_swiftdocs), transitive_swiftinterfaces = depset( swiftinterfaces, transitive = transitive_swiftinterfaces, ), transitive_swiftmodules = depset(swiftmodules, transitive = transitive_swiftmodules), ) def _compilation_attrs(additional_deps_aspects = []): """Returns an attribute dictionary for rules that compile Swift into objects. The returned dictionary contains the subset of attributes that are shared by the `swift_binary`, `swift_library`, and `swift_test` rules that deal with inputs and options for compilation. Users who are authoring custom rules that compile Swift code but not as a library can add this dictionary to their own rule's attributes to give it a familiar API. Do note, however, that it is the responsibility of the rule implementation to retrieve the values of those attributes and pass them correctly to the other `swift_common` APIs. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. Args: additional_deps_aspects: A list of additional aspects that should be applied to `deps`. Defaults to the empty list. These must be passed by the individual rules to avoid potential circular dependencies between the API and the aspects; the API loaded the aspects directly, then those aspects would not be able to load the API. Returns: A new attribute dictionary that can be added to the attributes of a custom build rule to provide a similar interface to `swift_binary`, `swift_library`, and `swift_test`. """ return dicts.add( swift_common_rule_attrs(additional_deps_aspects = additional_deps_aspects), _toolchain_attrs(), { "srcs": attr.label_list( flags = ["DIRECT_COMPILE_TIME_INPUT"], allow_files = ["swift"], doc = """ A list of `.swift` source files that will be compiled into the library. """, ), "copts": attr.string_list( doc = """ Additional compiler options that should be passed to `swiftc`. These strings are subject to `$(location ...)` expansion. """, ), "defines": attr.string_list( doc = """ A list of defines to add to the compilation command line. Note that unlike C-family languages, Swift defines do not have values; they are simply identifiers that are either defined or undefined. So strings in this list should be simple identifiers, **not** `name=value` pairs. Each string is prepended with `-D` and added to the command line. Unlike `copts`, these flags are added for the target and every target that depends on it, so use this attribute with caution. It is preferred that you add defines directly to `copts`, only using this feature in the rare case that a library needs to propagate a symbol up to those that depend on it. """, ), "module_name": attr.string( doc = """ The name of the Swift module being built. If left unspecified, the module name will be computed based on the target's build label, by stripping the leading `//` and replacing `/`, `:`, and other non-identifier characters with underscores. """, ), "swiftc_inputs": attr.label_list( allow_files = True, doc = """ Additional files that are referenced using `$(location ...)` in attributes that support location expansion. """, ), }, ) def _compilation_mode_copts(feature_configuration): """Returns `swiftc` compilation flags that match the current compilation mode. Args: feature_configuration: A feature configuration obtained from `swift_common.configure_features`. Returns: A list of strings containing copts that should be passed to Swift. """ is_dbg = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_DBG, ) is_fastbuild = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_FASTBUILD, ) is_opt = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_OPT, ) wants_full_debug_info = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_FULL_DEBUG_INFO, ) # Safety check that exactly one of these features is set; the user shouldn't mess with them. if int(is_dbg) + int(is_fastbuild) + int(is_opt) != 1: fail("Exactly one of the features `swift.{dbg,fastbuild,opt}` must be enabled.") # The combinations of flags used here mirror the descriptions of these # compilation modes given in the Bazel documentation: # https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode flags = [] if is_opt: flags.extend(["-O", "-DNDEBUG"]) if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_OPT_USES_WMO, ): flags.append("-whole-module-optimization") elif is_dbg or is_fastbuild: flags.extend(["-Onone", "-DDEBUG"]) if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_CACHEABLE_SWIFTMODULES, ): # For a swiftmodule to be usable from cache, it must not contain embedded paths. This # behavior must be explicitly disabled, because swiftc will enable this by default under # some circumstances. flags.extend(["-Xfrontend", "-no-serialize-debugging-options"]) else: # The Swift compiler only serializes debugging options in narrow # circumstances (for example, for application binaries). Since we almost # exclusively just compile to object files directly, we need to manually # pass the following frontend option to ensure that LLDB has the necessary # import search paths to find definitions during debugging. flags.extend(["-Xfrontend", "-serialize-debugging-options"]) if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_ENABLE_TESTING, ): flags.append("-enable-testing") # The combination of dsymutil and -gline-tables-only appears to cause # spurious warnings about symbols in the debug map, so if the caller is # requesting dSYMs, then force `-g` regardless of compilation mode. if is_dbg or wants_full_debug_info: flags.append("-g") elif is_fastbuild: flags.append("-gline-tables-only") return flags def _coverage_copts(feature_configuration): """Returns `swiftc` compilation flags for code converage if enabled. Args: feature_configuration: The feature configuration. Returns: A list of compiler flags that enable code coverage if requested. """ if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_COVERAGE, ): return ["-profile-generate", "-profile-coverage-mapping"] return [] def _is_debugging(feature_configuration): """Returns `True` if the current compilation mode produces debug info. We replicate the behavior of the C++ build rules for Swift, which are described here: https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode Args: feature_configuration: The feature configuration. Returns: `True` if the current compilation mode produces debug info. """ return ( _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_DBG, ) or _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_FASTBUILD, ) ) def _sanitizer_copts(feature_configuration): """Returns `swiftc` compilation flags for any requested sanitizer features. Args: feature_configuration: The feature configuration. Returns: A list of compiler flags that enable the requested sanitizers for a Swift compilation action. """ copts = [] for (feature_name, flags) in _SANITIZER_FEATURE_FLAG_MAP.items(): if swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = feature_name, ): copts.extend(flags) return copts def _global_module_cache_path(bin_dir): """Returns the path to the location where the Swift compiler should cache modules. Note that the use of this cache is non-hermetic; the cached modules are not declared inputs or outputs and they are not wiped between builds. The cache is purely a build performance optimization that reduces the need for large dependency graphs to repeatedly parse the same content multiple times. Args: bin_dir: The Bazel `*-bin` directory root where the module cache directory should be created. By placing it in `*-bin` (instead of the default, a path based on `/tmp/*`), the cache will be reliably cleaned when invoking `bazel clean`. Returns: The path to the module cache. """ # This path explicitly differs from the one used for Objective-C. This is because the # Clang invocation for Objective-C does not produce the same hashes as the invocation used # internally by Swift's ClangImporter. This means that the cached modules will never actually # be shared, and making the paths the same would be at best useless and at worse actively # harmful if there ever were to be a collision. We can revisit this decision if it ever # becomes possible to reliably share module caches between Clang and Swift. return paths.join(bin_dir.path, "_swift_module_cache") def _is_wmo(copts, feature_configuration): """Returns a value indicating whether a compilation will use whole module optimization. Args: copts: A list of compiler flags to scan for WMO usage. feature_configuration: The Swift feature configuration, as returned from `swift_common.configure_features`. Returns: True if WMO is enabled in the given list of flags. """ # First, check the feature configuration to see if the current compilation mode implies # whole-module-optimization. is_opt = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_OPT, ) opt_uses_wmo = _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_OPT_USES_WMO, ) if is_opt and opt_uses_wmo: return True # Otherwise, check any explicit copts the user may have set on the target or command line. return ("-wmo" in copts or "-whole-module-optimization" in copts or "-force-single-frontend-invocation" in copts) def _cc_feature_configuration(feature_configuration): """Returns the C++ feature configuration nested inside the given Swift feature configuration. Args: feature_configuration: The Swift feature configuration, as returned from `swift_common.configure_features`. Returns: A C++ `FeatureConfiguration` value (see `cc_common` for more information). """ return feature_configuration.cc_feature_configuration def _compile( actions, feature_configuration, module_name, srcs, swift_toolchain, target_name, additional_inputs = [], bin_dir = None, copts = [], defines = [], deps = [], genfiles_dir = None): """Compiles a Swift module. Args: actions: The context's `actions` object. feature_configuration: A feature configuration obtained from `swift_common.configure_features`. module_name: The name of the Swift module being compiled. This must be present and valid; use `swift_common.derive_module_name` to generate a default from the target's label if needed. srcs: The Swift source files to compile. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. target_name: The name of the target for which the code is being compiled, which is used to determine unique file paths for the outputs. additional_inputs: A list of `File`s representing additional input files that need to be passed to the Swift compile action because they are referenced by compiler flags. bin_dir: The Bazel `*-bin` directory root. If provided, its path is used to store the cache for modules precompiled by Swift's ClangImporter, and it is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support includes of generated headers from that location. copts: A list of compiler flags that apply to the target being built. These flags, along with those from Bazel's Swift configuration fragment (i.e., `--swiftcopt` command line flags) are scanned to determine whether whole module optimization is being requested, which affects the nature of the output files. defines: Symbols that should be defined by passing `-D` to the compiler. deps: Dependencies of the target being compiled. These targets must propagate one of the following providers: `CcInfo`, `SwiftInfo`, or `apple_common.Objc`. genfiles_dir: The Bazel `*-genfiles` directory root. If provided, its path is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support inclusions of generated headers from that location. Returns: A `struct` containing the following fields: * `generated_header`: A `File` representing the Objective-C header that was generated for the compiled module. If no header was generated, this field will be None. * `generated_header_module_map`: A `File` representing the module map that was generated to correspond to the generated Objective-C header. If no module map was generated, this field will be None. * `indexstore`: A `File` representing the directory that contains the index store data generated by the compiler if index-while-building is enabled. May be None if no indexing was requested. * `linker_flags`: A list of strings representing additional flags that should be passed to the linker when linking these objects into a binary. If there are none, this field will always be an empty list, never None. * `linker_inputs`: A list of `File`s representing additional input files (such as those referenced in `linker_flags`) that need to be available to the link action when linking these objects into a binary. If there are none, this field will always be an empty list, never None. * `object_files`: A list of `.o` files that were produced by the compiler. * `stats_directory`: A `File` representing the directory that contains the timing statistics emitted by the compiler. If no stats were requested, this field will be None. * `swiftdoc`: The `.swiftdoc` file that was produced by the compiler. * `swiftmodule`: The `.swiftmodule` file that was produced by the compiler. """ # Force threaded mode for WMO builds, using the same number of cores that is # on a Mac Pro for historical reasons. # TODO(b/32571265): Generalize this based on platform and core count when an # API to obtain this is available. is_wmo = _is_wmo(copts + swift_toolchain.command_line_copts, feature_configuration) if is_wmo: # We intentionally don't use `+=` or `extend` here to ensure that a # copy is made instead of extending the original. copts = copts + ["-num-threads", "12"] compile_reqs = declare_compile_outputs( actions = actions, copts = copts + swift_toolchain.command_line_copts, is_wmo = is_wmo, srcs = srcs, target_name = target_name, index_while_building = swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_INDEX_WHILE_BUILDING, ), ) output_objects = compile_reqs.output_objects swiftmodule = derived_files.swiftmodule(actions, module_name = module_name) swiftdoc = derived_files.swiftdoc(actions, module_name = module_name) additional_outputs = [] # Since all actions go through the worker (whether in persistent mode or not), the actual tool # we want to run (swiftc) should be the first "argument". tool_args = actions.args() tool_args.add(get_swift_tool(swift_toolchain = swift_toolchain, tool = "swiftc")) args = actions.args() if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE, ): # If bin_dir is not provided, then we don't pass any special flags to the compiler, # letting it decide where the cache should live. This is usually somewhere in the system # temporary directory. if bin_dir: args.add("-module-cache-path", _global_module_cache_path(bin_dir)) else: args.add("-Xwrapped-swift=-ephemeral-module-cache") if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_DEBUG_PREFIX_MAP, ): args.add("-Xwrapped-swift=-debug-prefix-pwd-is-dot") if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_USE_RESPONSE_FILES, ): args.set_param_file_format("multiline") args.use_param_file("@%s", use_always = True) # Only enable persistent workers if the toolchain supports response files, because the # worker unconditionally writes its arguments into one to prevent command line overflow. execution_requirements = {"supports-workers": "1"} else: execution_requirements = {} # Emit compilation timing statistics if the user enabled that feature. if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_COMPILE_STATS, ): stats_directory = derived_files.stats_directory(actions, target_name) additional_outputs.append(stats_directory) args.add("-stats-output-dir", stats_directory.path) else: stats_directory = None args.add("-emit-object") args.add_all(compile_reqs.args) args.add("-emit-module-path") args.add(swiftmodule) swiftinterface = None # Check and enabled features related to the library evolution compilation mode as requested. if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION, ): if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION, ): args.add("-enable-library-evolution") # swiftinterface generation requires the library evolution feature to be available and # enabled. if _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_EMIT_SWIFTINTERFACE, ): swiftinterface = derived_files.swiftinterface(actions, module_name = module_name) args.add("-emit-module-interface-path") args.add(swiftinterface) additional_outputs.append(swiftinterface) # Add any command line arguments that do *not* have to do with emitting outputs. basic_inputs = _swiftc_command_line_and_inputs( # TODO(allevato): Make this argument a list of files instead. additional_input_depsets = [depset(additional_inputs)], args = args, bin_dir = bin_dir, copts = copts, defines = defines, deps = deps, feature_configuration = feature_configuration, genfiles_dir = genfiles_dir, module_name = module_name, srcs = srcs, toolchain = swift_toolchain, ) # If the toolchain supports Objective-C interop, generate a Swift header for this library so # that it can be included by Objective-C code that depends on it. generates_header = not _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_NO_GENERATED_HEADER, ) if generates_header and swift_toolchain.supports_objc_interop: generated_header = derived_files.objc_header(actions = actions, target_name = target_name) args.add("-emit-objc-header-path") args.add(generated_header) additional_outputs.append(generated_header) # Create a module map for the generated header file. This ensures that inclusions of it are # treated modularly, not textually. # # Caveat: Generated module maps are incompatible with the hack that some folks are using to # support mixed Objective-C and Swift modules. This trap door lets them escape the module # redefinition error, with the caveat that certain import scenarios could lead to incorrect # behavior because a header can be imported textually instead of modularly. if not _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_NO_GENERATED_MODULE_MAP, ): generated_module_map = derived_files.module_map( actions = actions, target_name = target_name, ) write_objc_header_module_map( actions = actions, module_name = module_name, objc_header = generated_header, output = generated_module_map, ) else: generated_module_map = None else: generated_header = None generated_module_map = None all_inputs = depset( transitive = [ basic_inputs, swift_toolchain.cc_toolchain_info.all_files, depset(compile_reqs.compile_inputs), ], ) compile_outputs = ([swiftmodule, swiftdoc] + output_objects + compile_reqs.other_outputs) + additional_outputs run_swift_action( actions = actions, arguments = [tool_args, args], execution_requirements = execution_requirements, inputs = all_inputs, mnemonic = "SwiftCompile", outputs = compile_outputs, progress_message = "Compiling Swift module {}".format(module_name), swift_toolchain = swift_toolchain, ) linker_flags = [] linker_inputs = [] # Ensure that the .swiftmodule file is embedded in the final library or binary # for debugging purposes. if _is_debugging(feature_configuration = feature_configuration): module_embed_results = ensure_swiftmodule_is_embedded( actions = actions, swiftmodule = swiftmodule, target_name = target_name, toolchain = swift_toolchain, ) linker_flags.extend(module_embed_results.linker_flags) linker_inputs.extend(module_embed_results.linker_inputs) output_objects.extend(module_embed_results.objects_to_link) # Invoke an autolink-extract action for toolchains that require it. if swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_AUTOLINK_EXTRACT, ): autolink_file = derived_files.autolink_flags( actions, target_name = target_name, ) register_autolink_extract_action( actions = actions, module_name = module_name, objects = output_objects, output = autolink_file, toolchain = swift_toolchain, ) linker_flags.append("@{}".format(autolink_file.path)) linker_inputs.append(autolink_file) return struct( generated_header = generated_header, generated_module_map = generated_module_map, indexstore = compile_reqs.indexstore, linker_flags = linker_flags, linker_inputs = linker_inputs, object_files = output_objects, stats_directory = stats_directory, swiftdoc = swiftdoc, swiftinterface = swiftinterface, swiftmodule = swiftmodule, ) def _configure_features(ctx, swift_toolchain, requested_features = [], unsupported_features = []): """Creates a feature configuration that should be passed to other Swift build APIs. This function calls through to `cc_common.configure_features` to configure underlying C++ features as well, and nests the C++ feature configuration inside the Swift one. Users who need to call C++ APIs that require a feature configuration can extract it by calling `swift_common.cc_feature_configuration(feature_configuration)`. Args: ctx: The rule context. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain being used to build. The C++ toolchain associated with the Swift toolchain is used to create the underlying C++ feature configuration. requested_features: The list of features to be enabled. This is typically obtained using the `ctx.features` field in a rule implementation function. unsupported_features: The list of features that are unsupported by the current rule. This is typically obtained using the `ctx.disabled_features` field in a rule implementation function. Returns: An opaque value representing the feature configuration that can be passed to other `swift_common` functions. """ # The features to enable for a particular rule/target are the ones requested by the toolchain, # plus the ones requested by the target itself, *minus* any that are explicitly disabled on the # target itself. requested_features_set = sets.make(swift_toolchain.requested_features) requested_features_set = sets.union(requested_features_set, sets.make(requested_features)) requested_features_set = sets.difference( requested_features_set, sets.make(unsupported_features), ) all_requested_features = sets.to_list(requested_features_set) all_unsupported_features = collections.uniq( swift_toolchain.unsupported_features + unsupported_features, ) # Verify the consistency of Swift features requested vs. those that are not supported by the # toolchain. We don't need to do this for C++ features because `cc_common.configure_features` # handles verifying those. for feature in requested_features: if feature.startswith("swift.") and feature in all_unsupported_features: fail("Feature '{}' was requested, ".format(feature) + "but it is not supported by the current toolchain or rule.") cc_feature_configuration = cc_common.configure_features( ctx = ctx, cc_toolchain = swift_toolchain.cc_toolchain_info, requested_features = all_requested_features, unsupported_features = all_unsupported_features, ) return struct( cc_feature_configuration = cc_feature_configuration, requested_features = all_requested_features, unsupported_features = all_unsupported_features, ) def _derive_module_name(*args): """Returns a derived module name from the given build label. For targets whose module name is not explicitly specified, the module name is computed by creating an underscore-delimited string from the components of the label, replacing any non-identifier characters also with underscores. This mapping is not intended to be reversible. Args: *args: Either a single argument of type `Label`, or two arguments of type `str` where the first argument is the package name and the second argument is the target name. Returns: The module name derived from the label. """ if (len(args) == 1 and hasattr(args[0], "package") and hasattr(args[0], "name")): label = args[0] package = label.package name = label.name elif (len(args) == 2 and types.is_string(args[0]) and types.is_string(args[1])): package = args[0] name = args[1] else: fail("derive_module_name may only be called with a single argument of " + "type 'Label' or two arguments of type 'str'") package_part = (package.lstrip("//").replace("/", "_").replace("-", "_").replace(".", "_")) name_part = name.replace("-", "_") if package_part: return package_part + "_" + name_part return name_part def _config_attrs(): """Returns the Starlark configuration flags and settings attributes. Returns: A dictionary of configuration attributes to be added to rules that read configuration settings. """ return { "_config_emit_swiftinterface": attr.label( default = "@build_bazel_rules_swift//swift:emit_swiftinterface", ), } def _get_implicit_deps(feature_configuration, swift_toolchain): """Gets the list of implicit dependencies from the toolchain. Args: feature_configuration: The feature configuration, which determines whether optional implicit dependencies are included. swift_toolchain: The Swift toolchain. Returns: A list of targets that should be treated as implicit dependencies of the toolchain under the given feature configuration. """ deps = list(swift_toolchain.required_implicit_deps) if not _is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_MINIMAL_DEPS, ): deps.extend(swift_toolchain.optional_implicit_deps) return deps def _is_enabled(feature_configuration, feature_name): """Returns `True` if the given feature is enabled in the feature configuration. This function handles both Swift-specific features and C++ features so that users do not have to manually extract the C++ configuration in order to check it. Args: feature_configuration: The Swift feature configuration, as returned by `swift_common.configure_features`. feature_name: The name of the feature to check. Returns: `True` if the given feature is enabled in the feature configuration. """ if feature_name.startswith("swift."): return feature_name in feature_configuration.requested_features else: return cc_common.is_enabled( feature_configuration = _cc_feature_configuration(feature_configuration), feature_name = feature_name, ) def _library_rule_attrs(additional_deps_aspects = []): """Returns an attribute dictionary for `swift_library`-like rules. The returned dictionary contains the same attributes that are defined by the `swift_library` rule (including the private `_toolchain` attribute that specifies the toolchain dependency). Users who are authoring custom rules can use this dictionary verbatim or add other custom attributes to it in order to make their rule a drop-in replacement for `swift_library` (for example, if writing a custom rule that does some preprocessing or generation of sources and then compiles them). Do note, however, that it is the responsibility of the rule implementation to retrieve the values of those attributes and pass them correctly to the other `swift_common` APIs. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. Args: additional_deps_aspects: A list of additional aspects that should be applied to `deps`. Defaults to the empty list. These must be passed by the individual rules to avoid potential circular dependencies between the API and the aspects; the API loaded the aspects directly, then those aspects would not be able to load the API. Returns: A new attribute dictionary that can be added to the attributes of a custom build rule to provide the same interface as `swift_library`. """ return dicts.add( _compilation_attrs(additional_deps_aspects = additional_deps_aspects), _config_attrs(), { "linkopts": attr.string_list( doc = """ Additional linker options that should be passed to the linker for the binary that depends on this target. These strings are subject to `$(location ...)` expansion. """, ), "alwayslink": attr.bool( default = False, doc = """ If true, any binary that depends (directly or indirectly) on this Swift module will link in all the object files for the files listed in `srcs`, even if some contain no symbols referenced by the binary. This is useful if your code isn't explicitly called by code in the binary; for example, if you rely on runtime checks for protocol conformances added in extensions in the library but do not directly reference any other symbols in the object file that adds that conformance. """, ), }, ) def _swift_runtime_linkopts(is_static, toolchain, is_test = False): """Returns the flags that should be passed to `clang` when linking a binary. This function provides the appropriate linker arguments to callers who need to link a binary using something other than `swift_binary` (for example, an application bundle containing a universal `apple_binary`). Args: is_static: A `Boolean` value indicating whether the binary should be linked against the static (rather than the dynamic) Swift runtime libraries. toolchain: The `SwiftToolchainInfo` provider of the toolchain whose linker options are desired. is_test: A `Boolean` value indicating whether the target being linked is a test target. Returns: A `list` of command-line flags that should be passed to `clang` to link against the Swift runtime libraries. """ return partial.call( toolchain.linker_opts_producer, is_static = is_static, is_test = is_test, ) def _swiftc_command_line_and_inputs( args, feature_configuration, module_name, srcs, toolchain, additional_input_depsets = [], bin_dir = None, copts = [], defines = [], deps = [], genfiles_dir = None): """Computes command line arguments and inputs needed to invoke `swiftc`. The command line arguments computed by this function are any that do *not* require the declaration of new output files. For example, it includes the list of frameworks, defines, source files, and other copts, but not flags like the output objects or `.swiftmodule` files. The purpose of this is to allow (nearly) the same command line that would be passed to the compiler to be passed to other tools that require it; the most common application of this is for tools that use SourceKit, which need to know the command line in order to gather information about dependencies for indexing and code completion. Args: args: An `Args` object into which the command line arguments will be added. feature_configuration: A feature configuration obtained from `swift_common.configure_features`. module_name: The name of the Swift module being compiled. This must be present and valid; use `swift_common.derive_module_name` to generate a default from the target's label if needed. srcs: The Swift source files to compile. toolchain: The `SwiftToolchainInfo` provider of the toolchain. additional_input_depsets: A list of `depset`s of `File`s representing additional input files that need to be passed to the Swift compile action because they are referenced by compiler flags. bin_dir: The Bazel `*-bin` directory root. If provided, its path is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support inclusions of generated headers from that location. copts: A list (**not** an `Args` object) of compiler flags that apply to the target being built. These flags, along with those from Bazel's Swift configuration fragment (i.e., `--swiftcopt` command line flags) are scanned to determine whether whole module optimization is being requested, which affects the nature of the output files. defines: Symbols that should be defined by passing `-D` to the compiler. deps: Dependencies of the target being compiled. These targets must propagate one of the following providers: `CcInfo`, `SwiftInfo`, or `apple_common.Objc`. genfiles_dir: The Bazel `*-genfiles` directory root. If provided, its path is added to ClangImporter's header search paths for compatibility with Bazel's C++ and Objective-C rules which support inclusions of generated headers from that location. Returns: A `depset` containing the full set of files that need to be passed as inputs of the Bazel action that spawns a tool with the computed command line (i.e., any source files, referenced module maps and headers, and so forth.) """ all_deps = deps + _get_implicit_deps( feature_configuration = feature_configuration, swift_toolchain = toolchain, ) args.add("-module-name") args.add(module_name) args.add_all(_compilation_mode_copts(feature_configuration = feature_configuration)) args.add_all(_coverage_copts(feature_configuration = feature_configuration)) args.add_all(_sanitizer_copts(feature_configuration = feature_configuration)) args.add_all(["-Xfrontend", "-color-diagnostics"]) if swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD, ): args.add_all(collections.before_each( "-Xcc", ["-Xclang", "-fmodule-map-file-home-is-cwd"], )) # Do not enable batch mode if the user requested WMO; this silences an "ignoring # '-enable-batch-mode' because '-whole-module-optimization' was also specified" warning. if ( not _is_wmo(copts + toolchain.command_line_copts, feature_configuration) and swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_ENABLE_BATCH_MODE, ) ): args.add("-enable-batch-mode") # Add the bin and genfiles directories to ClangImporter's header search # paths for compatibility with rules that generate headers there. if bin_dir: args.add_all(["-Xcc", "-iquote{}".format(bin_dir.path)]) if genfiles_dir: args.add_all(["-Xcc", "-iquote{}".format(genfiles_dir.path)]) input_depsets = list(additional_input_depsets) transitive_inputs = collect_transitive_compile_inputs( args = args, deps = all_deps, direct_defines = defines, ) input_depsets.extend(transitive_inputs) input_depsets.append(depset(direct = srcs)) if toolchain.supports_objc_interop: # Collect any additional inputs and flags needed to pull in Objective-C # dependencies. input_depsets.append(objc_compile_requirements( args = args, deps = all_deps, )) # Add toolchain copts, target copts, and command-line `--swiftcopt` flags, # in that order, so that more targeted usages can override more general # uses if needed. args.add_all(toolchain.swiftc_copts) args.add_all(copts) args.add_all(toolchain.command_line_copts) args.add_all(srcs) return depset(transitive = input_depsets) def _toolchain_attrs(toolchain_attr_name = "_toolchain"): """Returns an attribute dictionary for toolchain users. The returned dictionary contains a key with the name specified by the argument `toolchain_attr_name` (which defaults to the value `"_toolchain"`), the value of which is a BUILD API `attr.label` that references the default Swift toolchain. Users who are authoring custom rules can add this dictionary to the attributes of their own rule in order to depend on the toolchain and access its `SwiftToolchainInfo` provider to pass it to other `swift_common` functions. There is a hierarchy to the attribute sets offered by the `swift_common` API: 1. If you only need access to the toolchain for its tools and libraries but are not doing any compilation, use `toolchain_attrs`. 2. If you need to invoke compilation actions but are not making the resulting object files into a static or shared library, use `compilation_attrs`. 3. If you want to provide a rule interface that is suitable as a drop-in replacement for `swift_library`, use `library_rule_attrs`. Each of the attribute functions in the list above also contains the attributes from the earlier items in the list. Args: toolchain_attr_name: The name of the attribute that should be created that points to the toolchain. This defaults to `_toolchain`, which is sufficient for most rules; it is customizable for certain aspects where having an attribute with the same name but different values applied to a particular target causes a build crash. Returns: A new attribute dictionary that can be added to the attributes of a custom build rule to provide access to the Swift toolchain. """ return { toolchain_attr_name: attr.label( default = Label("@build_bazel_rules_swift_local_config//:toolchain"), providers = [[SwiftToolchainInfo]], ), } # The exported `swift_common` module, which defines the public API for directly # invoking actions that compile Swift code from other rules. swift_common = struct( cc_feature_configuration = _cc_feature_configuration, compilation_attrs = _compilation_attrs, compile = _compile, configure_features = _configure_features, create_swift_info = _create_swift_info, derive_module_name = _derive_module_name, get_implicit_deps = _get_implicit_deps, is_enabled = _is_enabled, library_rule_attrs = _library_rule_attrs, swift_runtime_linkopts = _swift_runtime_linkopts, swiftc_command_line_and_inputs = _swiftc_command_line_and_inputs, toolchain_attrs = _toolchain_attrs, ) 0707010000003C000081A4000003E800000064000000015D9E3463000007AD000000000000000000000000000000000000003200000000bazel-rules-swift-0.13.0/swift/internal/attrs.bzl# Copyright 2018 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. """Common attributes used by multiple Swift build rules.""" load(":providers.bzl", "SwiftInfo") def swift_common_rule_attrs(additional_deps_aspects = []): return { "data": attr.label_list( allow_files = True, doc = """ The list of files needed by this target at runtime. Files and targets named in the `data` attribute will appear in the `*.runfiles` area of this target, if it has one. This may include data files needed by a binary or library, or other programs needed by it. """, ), "deps": attr.label_list( aspects = additional_deps_aspects, doc = """ A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds of dependencies are: * `swift_c_module`, `swift_import` and `swift_library` (or anything propagating `SwiftInfo`) * `cc_library` (or anything propagating `CcInfo`) Additionally, on platforms that support Objective-C interop, `objc_library` targets (or anything propagating the `apple_common.Objc` provider) are allowed as dependencies. On platforms that do not support Objective-C interop (such as Linux), those dependencies will be **ignored.** """, providers = [ [CcInfo], [SwiftInfo], [apple_common.Objc], ], ), } 0707010000003D000081A4000003E800000064000000015D9E346300006650000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/swift/internal/compiling.bzl# Copyright 2018 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. """Implementation of compilation logic for Swift.""" load("@bazel_skylib//lib:collections.bzl", "collections") load("@bazel_skylib//lib:paths.bzl", "paths") load( "@build_bazel_apple_support//lib:framework_migration.bzl", "framework_migration", ) load(":actions.bzl", "get_swift_tool", "run_swift_action") load(":derived_files.bzl", "derived_files") load(":providers.bzl", "SwiftInfo") load( ":utils.bzl", "collect_cc_libraries", "get_providers", "objc_provider_framework_name", ) def collect_transitive_compile_inputs(args, deps, direct_defines = []): """Collect transitive inputs and flags from Swift providers. Args: args: An `Args` object to which deps: The dependencies for which the inputs should be gathered. direct_defines: The list of defines for the target being built, which are merged with the transitive defines before they are added to `args` in order to prevent duplication. Returns: A list of `depset`s representing files that must be passed as inputs to the Swift compilation action. """ input_depsets = [] # Collect all the search paths, module maps, flags, and so forth from transitive dependencies. transitive_cc_defines = [] transitive_cc_headers = [] transitive_cc_includes = [] transitive_cc_quote_includes = [] transitive_cc_system_includes = [] transitive_defines = [] transitive_modulemaps = [] transitive_swiftmodules = [] for dep in deps: if SwiftInfo in dep: swift_info = dep[SwiftInfo] transitive_defines.append(swift_info.transitive_defines) transitive_modulemaps.append(swift_info.transitive_modulemaps) transitive_swiftmodules.append(swift_info.transitive_swiftmodules) if CcInfo in dep: compilation_context = dep[CcInfo].compilation_context transitive_cc_defines.append(compilation_context.defines) transitive_cc_headers.append(compilation_context.headers) transitive_cc_includes.append(compilation_context.includes) transitive_cc_quote_includes.append(compilation_context.quote_includes) transitive_cc_system_includes.append(compilation_context.system_includes) # Add import paths for the directories containing dependencies' swiftmodules. all_swiftmodules = depset(transitive = transitive_swiftmodules) args.add_all(all_swiftmodules, format_each = "-I%s", map_each = _dirname_map_fn) input_depsets.append(all_swiftmodules) # Pass Swift defines propagated by dependencies. all_defines = depset(direct_defines, transitive = transitive_defines) args.add_all(all_defines, format_each = "-D%s") # Pass module maps from C/C++ dependencies to ClangImporter. # TODO(allevato): Will `CcInfo` eventually keep these in its compilation context? all_modulemaps = depset(transitive = transitive_modulemaps) input_depsets.append(all_modulemaps) args.add_all(all_modulemaps, before_each = "-Xcc", format_each = "-fmodule-map-file=%s") # Add C++ headers from dependencies to the action inputs so the compiler can read them. input_depsets.append(depset(transitive = transitive_cc_headers)) # Pass any C++ defines and include search paths to ClangImporter. args.add_all( depset(transitive = transitive_cc_defines), before_each = "-Xcc", format_each = "-D%s", ) args.add_all( depset(transitive = transitive_cc_includes), before_each = "-Xcc", format_each = "-I%s", ) args.add_all( depset(transitive = transitive_cc_quote_includes), before_each = "-Xcc", format_each = "-iquote%s", ) args.add_all( depset(transitive = transitive_cc_system_includes), before_each = "-Xcc", format_each = "-isystem%s", ) return input_depsets def declare_compile_outputs( actions, copts, is_wmo, srcs, target_name, index_while_building = False): """Declares output files (and optional output file map) for a compile action. Args: actions: The object used to register actions. copts: The flags that will be passed to the compile action, which are scanned to determine whether a single frontend invocation will be used or not. is_wmo: Whether the compilation is happening with whole module optimization. srcs: The list of source files that will be compiled. target_name: The name (excluding package path) of the target being built. index_while_building: If `True`, a tree artifact will be declared to hold Clang index store data and the relevant option will be added during compilation to generate the indexes. Returns: A `struct` containing the following fields: * `args`: A list of values that should be added to the `Args` of the compile action. * `compile_inputs`: Additional input files that should be passed to the compile action. * `indexstore`: A `File` representing the index store directory that was generated if index-while-building was enabled, or None. * `other_outputs`: Additional output files that should be declared by the compile action, but which are not processed further. * `output_groups`: A dictionary of additional output groups that should be propagated by the calling rule using the `OutputGroupInfo` provider. * `output_objects`: A list of object (.o) files that will be the result of the compile action and which should be archived afterward. """ output_nature = _emitted_output_nature(copts, is_wmo) if not output_nature.emits_multiple_objects: # If we're emitting a single object, we don't use an object map; we just declare the output # file that the compiler will generate and there are no other partial outputs. out_obj = derived_files.whole_module_object_file(actions, target_name = target_name) return struct( args = ["-o", out_obj], compile_inputs = [], # TODO(allevato): We need to handle indexing here too. indexstore = None, other_outputs = [], output_groups = { "compilation_outputs": depset(items = [out_obj]), }, output_objects = [out_obj], ) # Otherwise, we need to create an output map that lists the individual object files so that we # can pass them all to the archive action. output_map_file = derived_files.swiftc_output_file_map(actions, target_name = target_name) # The output map data, which is keyed by source path and will be written to `output_map_file`. output_map = {} # Object files that will be used to build the archive. output_objs = [] # Additional files, such as partial Swift modules, that must be declared as action outputs # although they are not processed further. other_outputs = [] for src in srcs: src_output_map = {} # Declare the object file (there is one per source file). obj = derived_files.intermediate_object_file(actions, target_name = target_name, src = src) output_objs.append(obj) src_output_map["object"] = obj.path # Multi-threaded WMO compiles still produce a single .swiftmodule file, despite producing # multiple object files, so we have to check explicitly for that case. if output_nature.emits_partial_modules: partial_module = derived_files.partial_swiftmodule( actions, target_name = target_name, src = src, ) other_outputs.append(partial_module) src_output_map["swiftmodule"] = partial_module.path output_map[src.path] = struct(**src_output_map) # Output the module-wide `.swiftdeps` file, which is used for incremental builds. swiftdeps = derived_files.swift_dependencies_file(actions, target_name = target_name) other_outputs.append(swiftdeps) output_map[""] = {"swift-dependencies": swiftdeps.path} actions.write( content = struct(**output_map).to_json(), output = output_map_file, ) args = ["-output-file-map", output_map_file] output_groups = { "compilation_outputs": depset(items = output_objs), } # Configure index-while-building if requested. IDEs and other indexing tools can enable this # feature on the command line during a build and then access the index store artifacts that are # produced. if index_while_building and not _index_store_path_overridden(copts): index_store_dir = derived_files.indexstore_directory(actions, target_name = target_name) other_outputs.append(index_store_dir) args.extend(["-index-store-path", index_store_dir.path]) output_groups["swift_index_store"] = depset(direct = [index_store_dir]) else: index_store_dir = None return struct( args = args, compile_inputs = [output_map_file], indexstore = index_store_dir, other_outputs = other_outputs, output_groups = output_groups, output_objects = output_objs, ) def find_swift_version_copt_value(copts): """Returns the value of the `-swift-version` argument, if found. Args: copts: The list of copts to be scanned. Returns: The value of the `-swift-version` argument, or None if it was not found in the copt list. """ # Note that the argument can occur multiple times, and the last one wins. last_swift_version = None count = len(copts) for i in range(count): copt = copts[i] if copt == "-swift-version" and i + 1 < count: last_swift_version = copts[i + 1] return last_swift_version def new_objc_provider( deps, include_path, link_inputs, linkopts, module_map, static_archives, swiftmodules, defines = [], objc_header = None): """Creates an `apple_common.Objc` provider for a Swift target. Args: deps: The dependencies of the target being built, whose `Objc` providers will be passed to the new one in order to propagate the correct transitive fields. include_path: A header search path that should be propagated to dependents. link_inputs: Additional linker input files that should be propagated to dependents. linkopts: Linker options that should be propagated to dependents. module_map: The module map generated for the Swift target's Objective-C header, if any. static_archives: A list (typically of one element) of the static archives (`.a` files) containing the target's compiled code. swiftmodules: A list (typically of one element) of the `.swiftmodule` files for the compiled target. defines: A list of `defines` from the propagating `swift_library` that should also be defined for `objc_library` targets that depend on it. objc_header: The generated Objective-C header for the Swift target. If `None`, no headers will be propagated. This header is only needed for Swift code that defines classes that should be exposed to Objective-C. Returns: An `apple_common.Objc` provider that should be returned by the calling rule. """ objc_providers = get_providers(deps, apple_common.Objc) objc_provider_args = { "link_inputs": depset(direct = swiftmodules + link_inputs), "providers": objc_providers, "uses_swift": True, } # The link action registered by `apple_binary` only looks at `Objc` providers, not `CcInfo`, # for libraries to link. Until that rule is migrated over, we need to collect libraries from # `CcInfo` (which will include Swift and C++) and put them into the new `Objc` provider. transitive_cc_libs = [] for cc_info in get_providers(deps, CcInfo): static_libs = collect_cc_libraries(cc_info = cc_info, include_static = True) transitive_cc_libs.append(depset(static_libs, order = "topological")) objc_provider_args["library"] = depset( static_archives, transitive = transitive_cc_libs, order = "topological", ) if include_path: objc_provider_args["include"] = depset(direct = [include_path]) if defines: objc_provider_args["define"] = depset(direct = defines) if objc_header: objc_provider_args["header"] = depset(direct = [objc_header]) if linkopts: objc_provider_args["linkopt"] = depset(direct = linkopts) force_loaded_libraries = [ archive for archive in static_archives if archive.basename.endswith(".lo") ] if force_loaded_libraries: objc_provider_args["force_load_library"] = depset(direct = force_loaded_libraries) # In addition to the generated header's module map, we must re-propagate the direct deps' # Objective-C module maps to dependents, because those Swift modules still need to see them. We # need to construct a new transitive objc provider to get the correct strict propagation # behavior. transitive_objc_provider_args = {"providers": objc_providers} if module_map: transitive_objc_provider_args["module_map"] = depset(direct = [module_map]) transitive_objc = apple_common.new_objc_provider(**transitive_objc_provider_args) objc_provider_args["module_map"] = transitive_objc.module_map return apple_common.new_objc_provider(**objc_provider_args) def objc_compile_requirements(args, deps): """Collects compilation requirements for Objective-C dependencies. Args: args: An `Args` object to which compile options will be added. deps: The `deps` of the target being built. Returns: A `depset` of files that should be included among the inputs of the compile action. """ defines = [] includes = [] inputs = [] module_maps = [] static_framework_names = [] all_frameworks = [] objc_providers = get_providers(deps, apple_common.Objc) post_framework_cleanup = framework_migration.is_post_framework_migration() for objc in objc_providers: inputs.append(objc.header) inputs.append(objc.umbrella_header) defines.append(objc.define) includes.append(objc.include) if post_framework_cleanup: static_framework_names.append(objc.static_framework_names) all_frameworks.append(objc.framework_search_path_only) else: inputs.append(objc.static_framework_file) inputs.append(objc.dynamic_framework_file) static_framework_names.append(depset( [objc_provider_framework_name(fdir) for fdir in objc.framework_dir.to_list()], )) all_frameworks.append(objc.framework_dir) all_frameworks.append(objc.dynamic_framework_dir) # Collect module maps for dependencies. These must be pulled from a combined transitive # provider to get the correct strict propagation behavior that we use to workaround command-line # length issues until Swift 4.2 is available. transitive_objc_provider = apple_common.new_objc_provider(providers = objc_providers) module_maps = transitive_objc_provider.module_map inputs.append(module_maps) # Add the objc dependencies' header search paths so that imported modules can find their # headers. args.add_all(depset(transitive = includes), format_each = "-I%s") # Add framework search paths for any prebuilt frameworks. args.add_all( depset(transitive = all_frameworks), format_each = "-F%s", map_each = paths.dirname, ) # Disable the `LC_LINKER_OPTION` load commands for static framework automatic linking. This is # needed to correctly deduplicate static frameworks from also being linked into test binaries # where it is also linked into the app binary. args.add_all( depset(transitive = static_framework_names), map_each = _disable_autolink_framework_copts, ) # Swift's ClangImporter does not include the current directory by default in its search paths, # so we must add it to find workspace-relative imports in headers imported by module maps. args.add_all(["-Xcc", "-iquote."]) # Ensure that headers imported by Swift modules have the correct defines propagated from # dependencies. args.add_all(depset(transitive = defines), before_each = "-Xcc", format_each = "-D%s") # Take any Swift-compatible defines from Objective-C dependencies and define them for Swift. args.add_all( depset(transitive = defines), map_each = _exclude_swift_incompatible_define, format_each = "-D%s", ) # Load module maps explicitly instead of letting Clang discover them in the search paths. This # is needed to avoid a case where Clang may load the same header in modular and non-modular # contexts, leading to duplicate definitions in the same file. # <https://llvm.org/bugs/show_bug.cgi?id=19501> args.add_all(module_maps, before_each = "-Xcc", format_each = "-fmodule-map-file=%s") return depset(transitive = inputs) def output_groups_from_compilation_outputs(compilation_outputs): """Returns a dictionary of output groups from Swift compilation outputs. Args: compilation_outputs: The result of calling `swift_common.compile`. Returns: A `dict` whose keys are the names of output groups and values are `depset`s of `File`s, which can be splatted as keyword arguments to the `OutputGroupInfo` constructor. """ output_groups = {} if compilation_outputs.indexstore: output_groups["swift_index_store"] = depset([ compilation_outputs.indexstore, ]) if compilation_outputs.stats_directory: output_groups["swift_compile_stats_direct"] = depset([ compilation_outputs.stats_directory, ]) if compilation_outputs.swiftinterface: output_groups["swiftinterface"] = depset([ compilation_outputs.swiftinterface, ]) return output_groups def register_autolink_extract_action( actions, module_name, objects, output, toolchain): """Extracts autolink information from Swift `.o` files. For some platforms (such as Linux), autolinking of imported frameworks is achieved by extracting the information about which libraries are needed from the `.o` files and producing a text file with the necessary linker flags. That file can then be passed to the linker as a response file (i.e., `@flags.txt`). Args: actions: The object used to register actions. module_name: The name of the module to which the `.o` files belong (used when generating the progress message). objects: The list of object files whose autolink information will be extracted. output: A `File` into which the autolink information will be written. toolchain: The `SwiftToolchainInfo` provider of the toolchain. """ args = actions.args() args.add(get_swift_tool(swift_toolchain = toolchain, tool = "swift-autolink-extract")) args.add_all(objects) args.add("-o", output) run_swift_action( actions = actions, arguments = [args], inputs = objects, mnemonic = "SwiftAutolinkExtract", outputs = [output], progress_message = "Extracting autolink data for Swift module {}".format(module_name), swift_toolchain = toolchain, ) def swift_library_output_map(name, alwayslink): """Returns the dictionary of implicit outputs for a `swift_library`. This function is used to specify the `outputs` of the `swift_library` rule; as such, its arguments must be named exactly the same as the attributes to which they refer. Args: name: The name of the target being built. alwayslink: Indicates whether the object files in the library should always be always be linked into any binaries that depend on it, even if some contain no symbols referenced by the binary. Returns: The implicit outputs dictionary for a `swift_library`. """ extension = "lo" if alwayslink else "a" return { "archive": "lib{}.{}".format(name, extension), } def write_objc_header_module_map( actions, module_name, objc_header, output): """Writes a module map for a generated Swift header to a file. Args: actions: The context's actions object. module_name: The name of the Swift module. objc_header: The `File` representing the generated header. output: The `File` to which the module map should be written. """ actions.write( content = ('module "{module_name}" {{\n' + ' header "../{header_name}"\n' + "}}\n").format( header_name = objc_header.basename, module_name = module_name, ), output = output, ) def _index_store_path_overridden(copts): """Checks if index_while_building must be disabled. Index while building is disabled when the copts include a custom -index-store-path. Args: copts: The list of copts to be scanned. Returns: True if the index_while_building must be disabled, otherwise False. """ for opt in copts: if opt == "-index-store-path": return True return False def _dirname_map_fn(f): """Returns the dir name of a file. This function is intended to be used as a mapping function for file passed into `Args.add`. Args: f: The file. Returns: The dirname of the file. """ return f.dirname def _disable_autolink_framework_copts(framework_name): """A `map_each` helper that disables autolinking for the given framework. Args: framework_name: The name of the framework. Returns: The list of `swiftc` flags needed to disable autolinking for the given framework. """ return collections.before_each( "-Xfrontend", [ "-disable-autolink-framework", framework_name, ], ) def _emitted_output_nature(copts, is_wmo): """Returns a `struct` with information about the nature of emitted outputs for the given flags. The compiler emits a single object if it is invoked with whole-module optimization enabled and is single-threaded (`-num-threads` is not present or is equal to 1); otherwise, it emits one object file per source file. It also emits a single `.swiftmodule` file for WMO builds, _regardless of thread count,_ so we have to treat that case separately. Args: copts: The options passed into the compile action. is_wmo: Whether the compilation is happening with whole module optimization. Returns: A struct containing the following fields: * `emits_multiple_objects`: `True` if the Swift frontend emits an object file per source file, instead of a single object file for the whole module, in a compilation action with the given flags. * `emits_partial_modules`: `True` if the Swift frontend emits partial `.swiftmodule` files for the individual source files in a compilation action with the given flags. """ saw_space_separated_num_threads = False num_threads = 1 for copt in copts: if saw_space_separated_num_threads: saw_space_separated_num_threads = False num_threads = _safe_int(copt) elif copt == "-num-threads": saw_space_separated_num_threads = True elif copt.startswith("-num-threads="): num_threads = _safe_int(copt.split("=")[1]) if not num_threads: fail("The value of '-num-threads' must be a positive integer.") return struct( emits_multiple_objects = not (is_wmo and num_threads == 1), emits_partial_modules = not is_wmo, ) def _exclude_swift_incompatible_define(define): """A `map_each` helper that excludes the given define if it is not Swift-compatible. This function rejects any defines that are not of the form `FOO=1` or `FOO`. Note that in C-family languages, the option `-DFOO` is equivalent to `-DFOO=1` so we must preserve both. Args: define: A string of the form `FOO` or `FOO=BAR` that represents an Objective-C define. Returns: The token portion of the define it is Swift-compatible, or `None` otherwise. """ token, equal, value = define.partition("=") if (not equal and not value) or (equal == "=" and value == "1"): return token return None def _safe_int(s): """Returns the integer value of `s` when interpreted as base 10, or `None` if it is invalid. This function is needed because `int()` fails the build when passed a string that isn't a valid integer, with no way to recover (https://github.com/bazelbuild/bazel/issues/5940). Args: s: The string to be converted to an integer. Returns: The integer value of `s`, or `None` if was not a valid base 10 integer. """ for i in range(len(s)): if s[i] < "0" or s[i] > "9": return None return int(s) 0707010000003E000081A4000003E800000064000000015D9E346300001138000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/swift/internal/debugging.bzl# Copyright 2018 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. """Functions relating to debugging support during compilation and linking.""" load(":actions.bzl", "get_swift_tool", "run_swift_action") load(":derived_files.bzl", "derived_files") def ensure_swiftmodule_is_embedded( actions, swiftmodule, target_name, toolchain): """Ensures that a `.swiftmodule` file is embedded in a library or binary. This function handles the distinctions between how different object file formats (i.e., Mach-O vs. ELF) have to embed the module AST for debugging purposes. Args: actions: The object used to register actions. swiftmodule: The `.swiftmodule` file to be wrapped. target_name: The name of the target being built. toolchain: The `SwiftToolchainInfo` provider of the toolchain. Returns: A `struct` containing three fields: * `linker_flags`: A list of additional flags that should be propagated to the linker. * `linker_inputs`: A list of additional inputs that are not necessarily object files, but which are referenced in `linker_flags` and should therefore be passed to the linker. * `objects_to_link`: A list of `.o` files that should be included in the static archive or binary that represents the module. """ linker_flags = [] linker_inputs = [] objects_to_link = [] if toolchain.object_format == "elf": # For ELF-format binaries, we need to invoke a Swift modulewrap action to # wrap the .swiftmodule file in a .o file that gets propagated to the # linker. modulewrap_obj = derived_files.modulewrap_object( actions, target_name = target_name, ) objects_to_link.append(modulewrap_obj) _register_modulewrap_action( actions = actions, object = modulewrap_obj, swiftmodule = swiftmodule, toolchain = toolchain, ) elif toolchain.object_format == "macho": linker_flags.append("-Wl,-add_ast_path,{}".format(swiftmodule.path)) linker_inputs.append(swiftmodule) else: fail("Internal error: Unexpected object format '{}'.".format( toolchain.object_format, )) return struct( linker_flags = linker_flags, linker_inputs = linker_inputs, objects_to_link = objects_to_link, ) def _register_modulewrap_action( actions, object, swiftmodule, toolchain): """Wraps a Swift module in a `.o` file that can be linked into a binary. This step (invoking `swift -modulewrap`) is required for the `.swiftmodule` of the main module of an executable on platforms with ELF-format object files; otherwise, debuggers will not be able to see those symbols. Args: actions: The object used to register actions. object: The object file that will be produced by the modulewrap task. swiftmodule: The `.swiftmodule` file to be wrapped. toolchain: The `SwiftToolchainInfo` provider of the toolchain. """ args = actions.args() args.add(get_swift_tool(swift_toolchain = toolchain, tool = "swift")) args.add("-modulewrap") args.add(swiftmodule) # Workaround because bazel's c++ toolchain returns "local" instead of a # real triple. if toolchain.cc_toolchain_info.target_gnu_system_name != "local": args.add("-target", toolchain.cc_toolchain_info.target_gnu_system_name) args.add("-o", object) run_swift_action( actions = actions, arguments = [args], inputs = [swiftmodule], mnemonic = "SwiftModuleWrap", outputs = [object], progress_message = "Wrapping {} for debugging".format(swiftmodule.short_path), swift_toolchain = toolchain, ) 0707010000003F000081A4000003E800000064000000015D9E346300002C8D000000000000000000000000000000000000003A00000000bazel-rules-swift-0.13.0/swift/internal/derived_files.bzl# Copyright 2018 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. """Factory functions for declaring derived files and directories.""" load("@bazel_skylib//lib:paths.bzl", "paths") load(":utils.bzl", "owner_relative_path") def _autolink_flags(actions, target_name): """Declares the response file into which autolink flags will be extracted. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}.autolink".format(target_name)) def _executable(actions, target_name): """Declares a file for the executable created by a binary or test rule. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file(target_name) def _indexstore_directory(actions, target_name): """Declares a directory in which the compiler's indexstore will be written. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_directory("{}.indexstore".format(target_name)) def _intermediate_frontend_file_path(target_name, src): """Returns the path to the directory for intermediate compile outputs. This is a helper function and is not exported in the `derived_files` module. Args: target_name: The name of hte target being built. src: A `File` representing the source file whose intermediate frontend artifacts path should be returned. Returns: The path to the directory where intermediate artifacts for the given target and source file should be stored. """ objs_dir = "{}_objs".format(target_name) owner_rel_path = owner_relative_path(src) # TODO(b/131185317): Remove this once ar_wrapper handles filenames with spaces correctly. safe_name = src.basename.replace(" ", "__SPACE__") return paths.join(objs_dir, paths.dirname(owner_rel_path)), safe_name def _intermediate_object_file(actions, target_name, src): """Declares a file for an intermediate object file during compilation. These files are produced when the compiler is invoked with multiple frontend invocations (i.e., whole module optimization disabled); in that case, there is a `.o` file produced for each source file, rather than a single `.o` for the entire module. Args: actions: The context's actions object. target_name: The name of the target being built. src: A `File` representing the source file being compiled. Returns: The declared `File`. """ dirname, basename = _intermediate_frontend_file_path(target_name, src) return actions.declare_file( paths.join(dirname, "{}.o".format(basename)), ) def _module_map(actions, target_name): """Declares the module map for the generated C or Objective-C header of a target. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file( "{}.modulemaps/module.modulemap".format(target_name), ) def _modulewrap_object(actions, target_name): """Declares the object file used to wrap Swift modules for ELF binaries. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}.modulewrap.o".format(target_name)) def _objc_header(actions, target_name): """Declares the generated header file exposing Swift APIs to Objective-C. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}-Swift.h".format(target_name)) def _partial_swiftmodule(actions, target_name, src): """Declares a file for a partial Swift module created during compilation. These files are produced when the compiler is invoked with multiple frontend invocations (i.e., whole module optimization disabled); in that case, there is a partial `.swiftmodule` file produced for each source file, which are then merged by another frontend invocation to produce the single `.swiftmodule` file for the entire module. Args: actions: The context's actions object. target_name: The name of the target being built. src: A `File` representing the source file being compiled. Returns: The declared `File`. """ dirname, basename = _intermediate_frontend_file_path(target_name, src) return actions.declare_file( paths.join(dirname, "{}.partial_swiftmodule".format(basename)), ) def _reexport_modules_src(actions, target_name): """Declares a source file used to re-export other Swift modules. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}_exports.swift".format(target_name)) def _static_archive(actions, alwayslink, link_name): """Declares a file for the static archive created by a compilation rule. Args: actions: The context's actions object. alwayslink: Indicates whether the object files in the library should always be always be linked into any binaries that depend on it, even if some contain no symbols referenced by the binary. link_name: The name of the library being built, without a `lib` prefix or file extension. Returns: The declared `File`. """ extension = "lo" if alwayslink else "a" return actions.declare_file("lib{}.{}".format(link_name, extension)) def _stats_directory(actions, target_name): """Declares a directory that will contain timing statistics for a compile. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_directory("{}.compile-stats".format(target_name)) def _swiftc_output_file_map(actions, target_name): """Declares a file for the JSON-formatted output map for a compilation action. This output map file allows us to supply our own paths and filenames for the intermediate artifacts produced by multiple frontend invocation, rather than using the temporary defaults Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}.output_file_map.json".format(target_name)) def _swiftdoc(actions, module_name): """Declares a file for the Swift doc file created by a compilation rule. Args: actions: The context's actions object. module_name: The name of the module being built. Returns: The declared `File`. """ return actions.declare_file("{}.swiftdoc".format(module_name)) def _swiftinterface(actions, module_name): """Declares a file for the Swift interface created by a compilation rule. Args: actions: The context's actions object. module_name: The name of the module being built. Returns: The declared `File`. """ return actions.declare_file("{}.swiftinterface".format(module_name)) def _swiftmodule(actions, module_name): """Declares a file for the Swift module created by a compilation rule. Args: actions: The context's actions object. module_name: The name of the module being built. Returns: The declared `File`. """ return actions.declare_file("{}.swiftmodule".format(module_name)) def _swift_dependencies_file(actions, target_name, src = None): """Declares a file containing the compiler-generated Swift dependencies for a target. This file is used during incremental compilation to determine which object files and partial modules need to be rebuilt when a particular source file changes. Args: actions: The context's actions object. target_name: The name of the target being built. src: An optional `File` representing the source file being compiled. Returns: The declared `File`. """ if src: dirname, basename = _intermediate_frontend_file_path(target_name, src) return actions.declare_file( paths.join(dirname, "{}.swiftdeps".format(basename)), ) return actions.declare_file("{}.swiftdeps".format(target_name)) def _whole_module_object_file(actions, target_name): """Declares a file for the object file created with whole module optimization. This is the output of a compile action when whole module optimization is enabled, which means that the driver produces a single frontend invocation that compiles all the source files at once. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}.o".format(target_name)) def _xctest_bundle(actions, target_name): """Declares a directory representing the `.xctest` bundle of a Darwin `swift_test`. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_directory("{}.xctest".format(target_name)) def _xctest_runner_script(actions, target_name): """Declares a file for the script that runs an `.xctest` bundle on Darwin. Args: actions: The context's actions object. target_name: The name of the target being built. Returns: The declared `File`. """ return actions.declare_file("{}.test-runner.sh".format(target_name)) derived_files = struct( autolink_flags = _autolink_flags, executable = _executable, indexstore_directory = _indexstore_directory, intermediate_object_file = _intermediate_object_file, module_map = _module_map, modulewrap_object = _modulewrap_object, objc_header = _objc_header, partial_swiftmodule = _partial_swiftmodule, reexport_modules_src = _reexport_modules_src, static_archive = _static_archive, stats_directory = _stats_directory, swiftc_output_file_map = _swiftc_output_file_map, swiftdoc = _swiftdoc, swiftinterface = _swiftinterface, swiftmodule = _swiftmodule, swift_dependencies_file = _swift_dependencies_file, whole_module_object_file = _whole_module_object_file, xctest_bundle = _xctest_bundle, xctest_runner_script = _xctest_runner_script, ) 07070100000040000081A4000003E800000064000000015D9E3463000023D5000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/swift/internal/features.bzl# Copyright 2018 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. """Helper functions for working with Bazel features.""" # We use the following constants within the rule definitions to prevent the possibility of typos # when referring to them as part of the implementation, but we explicitly do not export them since # it's not a common practice to use them that way in BUILD files; the expectation is that the actual # string literals would be used there. (There is also no good way to generate documentation yet for # constants since they don't have "doc" attributes, so exposing them in a more structured way # doesn't provide a benefit there either.) # These features correspond to the current Bazel compilation mode. Exactly one of them will be # enabled by the toolchain. (We define our own because we cannot depend on the equivalent C++ # features being enabled if the toolchain does not require them for any of its behavior.) SWIFT_FEATURE_DBG = "swift.dbg" SWIFT_FEATURE_FASTBUILD = "swift.fastbuild" SWIFT_FEATURE_OPT = "swift.opt" # This feature is enabled if coverage collection is enabled for the build. (See the note above # about not depending on the C++ features.) SWIFT_FEATURE_COVERAGE = "swift.coverage" # If enabled, `swift-autolink-extract` will be invoked on the object files generated for a library # or binary, generating a response file that will be passed automatically to the linker containing # the libraries corresponding to modules that were imported. This is used to simulate the # autolinking behavior of Mach-O on platforms with different binary formats. SWIFT_FEATURE_AUTOLINK_EXTRACT = "swift.autolink_extract" # If enabled, the `swift_test` rule will output an `.xctest` bundle for Darwin targets instead of a # standalone binary. This is necessary for XCTest-based tests that use runtime reflection to locate # test methods. This feature can be explicitly disabled on a per-target or per-package basis if # needed to make `swift_test` output just a binary. SWIFT_FEATURE_BUNDLED_XCTESTS = "swift.bundled_xctests" # If enabled, the Swift compiler will emit a directory containing JSON files with timing # information about the driver/frontend's actions. This directory will be emitted as a default # output when a Swift target is built directly, and it will also be propagated in an output # group named `swift_compile_stats_direct". Typically this output group will not be accessed # directly, but used by the `collect_swift_compile_stats` aspect to gather the transitive stats # for the entire build. SWIFT_FEATURE_COMPILE_STATS = "swift.compile_stats" # If enabled, debug builds will use the `-debug-prefix-map` feature to remap the current working # directory to `.`, which permits debugging remote or sandboxed builds. SWIFT_FEATURE_DEBUG_PREFIX_MAP = "swift.debug_prefix_map" # If enabled, Swift compilation actions will use batch mode by passing `-enable-batch-mode` to # `swiftc`. This is a new compilation mode as of Swift 4.2 that is intended to speed up # non-incremental non-WMO builds by invoking a smaller number of frontend processes and passing # them batches of source files. SWIFT_FEATURE_ENABLE_BATCH_MODE = "swift.enable_batch_mode" # If enabled, Swift compilation actions will pass the `-enable-testing` flag that modifies # visibility controls to let a module be imported with the `@testable` attribute. This feature # will be enabled by default for dbg/fastbuild builds and disabled by default for opt builds. SWIFT_FEATURE_ENABLE_TESTING = "swift.enable_testing" # If enabled, full debug info should be generated instead of line-tables-only. This is required # when dSYMs are requested via the `--apple_generate_dsym` flag but the compilation mode is # `fastbuild`, because `dsymutil` emits spurious warnings otherwise. SWIFT_FEATURE_FULL_DEBUG_INFO = "swift.full_debug_info" # If enabled, the compilation action for a target will produce an index store. SWIFT_FEATURE_INDEX_WHILE_BUILDING = "swift.index_while_building" # If enabled, Swift libraries, binaries, and tests will only have automatic dependencies on the # targets provided by the toolchain's `required_implicit_deps` field but not those in the # `optional_implicit_deps` field. Users may still explicitly list the latter in the `deps` of # their targets if they are needed. SWIFT_FEATURE_MINIMAL_DEPS = "swift.minimal_deps" # If enabled, compilation actions and module map generation will assume that the header paths in # module maps are relative to the current working directory (i.e., the workspace root); if disabled, # header paths in module maps are relative to the location of the module map file. SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD = "swift.module_map_home_is_cwd" # If enabled, the compilation action for a library target will not generate an Objective-C header # for the module. This feature also implies `swift.no_generated_module_map`. SWIFT_FEATURE_NO_GENERATED_HEADER = "swift.no_generated_header" # If enabled, the compilation action for a library target will not generate a module map for the # Objective-C generated header. This feature is ignored if `swift.no_generated_header` is not # present. SWIFT_FEATURE_NO_GENERATED_MODULE_MAP = "swift.no_generated_module_map" # If enabled, builds using the "opt" compilation mode will invoke `swiftc` with the # `-whole-module-optimization` flag (in addition to `-O`). SWIFT_FEATURE_OPT_USES_WMO = "swift.opt_uses_wmo" # If enabled, Swift compilation actions will use the same global Clang module cache used by # Objective-C compilation actions. This is disabled by default because under some circumstances # Clang module cache corruption can cause the Swift compiler to crash (sometimes when switching # configurations or syncing a repository), but disabling it also causes a noticeable build time # regression so it can be explicitly re-enabled by users who are not affected by those crashes. SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE = "swift.use_global_module_cache" # If enabled, actions invoking the Swift driver or frontend may write argument lists into response # files (i.e., "@args.txt") to avoid passing command lines that exceed the system limit. Toolchains # typically set this automatically if using a sufficiently recent version of Swift (4.2 or higher). SWIFT_FEATURE_USE_RESPONSE_FILES = "swift.use_response_files" # If enabled, builds using the "dbg" compilation mode will explicitly disable swiftc from producing # swiftmodules containing embedded file paths, which are inherently non-portable across machines. # # To used these modules from lldb, target settings must be correctly populated. For example: # target.swift-module-search-paths # target.swift-framework-search-paths # target.swift-extra-clang-flags SWIFT_FEATURE_CACHEABLE_SWIFTMODULES = "swift.cacheable_swiftmodules" # If enabled, enables features that require the library evolution compilation mode. If disabled, # features that require library evolution mode are noops. SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION = "swift.supports_library_evolution" # If enabled, requests the `-enable-library-evolution` swiftc flag which is required for newer # features like swiftinterface file generation. # If the SWIFT_FEATURES_SUPPORTS_LIBRARY_EVOLUTION feature is not enabled, this feature is a noop. SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION = "swift.enable_library_evolution" # If enabled, requests the swiftinterface file to be built on the swiftc invocation. # If the SWIFT_FEATURES_SUPPORTS_LIBRARY_EVOLUTION feature is not enabled, this feature is a noop. SWIFT_FEATURE_EMIT_SWIFTINTERFACE = "swift.emit_swiftinterface" def features_for_build_modes(ctx, objc_fragment = None): """Returns a list of Swift toolchain features corresponding to current build modes. This function explicitly breaks the "don't pass `ctx` as an argument" rule-of-thumb because it is internal and only called from the toolchain rules, so there is no concern about supporting differing call sites. Args: ctx: The current rule context. objc_fragment: The Objective-C configuration fragment, if available. Returns: A list of Swift toolchain features to enable. """ compilation_mode = ctx.var["COMPILATION_MODE"] features = [] features.append("swift.{}".format(compilation_mode)) if ctx.configuration.coverage_enabled: features.append(SWIFT_FEATURE_COVERAGE) if compilation_mode in ("dbg", "fastbuild"): features.append(SWIFT_FEATURE_ENABLE_TESTING) if objc_fragment and objc_fragment.generate_dsym: features.append(SWIFT_FEATURE_FULL_DEBUG_INFO) return features 07070100000041000081A4000003E800000064000000015D9E346300003B3B000000000000000000000000000000000000003400000000bazel-rules-swift-0.13.0/swift/internal/linking.bzl# Copyright 2018 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. """Implementation of linking logic for Swift.""" load("@bazel_skylib//lib:paths.bzl", "paths") load( "@build_bazel_apple_support//lib:framework_migration.bzl", "framework_migration", ) load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME") load(":actions.bzl", "run_swift_action") load(":derived_files.bzl", "derived_files") load(":utils.bzl", "collect_cc_libraries", "objc_provider_framework_name") def _register_static_library_link_action( actions, cc_feature_configuration, objects, output, swift_toolchain): """Registers an action that creates a static library. Args: actions: The object used to register actions. cc_feature_configuration: The C++ feature configuration to use when constructing the action. objects: A list of `File`s denoting object (`.o`) files that will be linked. output: A `File` to which the output library will be written. swift_toolchain: The Swift toolchain provider to use when constructing the action. """ archiver_path = cc_common.get_tool_for_action( action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, feature_configuration = cc_feature_configuration, ) archiver_variables = cc_common.create_link_variables( cc_toolchain = swift_toolchain.cc_toolchain_info, feature_configuration = cc_feature_configuration, is_using_linker = False, output_file = output.path, ) command_line = cc_common.get_memory_inefficient_command_line( action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, feature_configuration = cc_feature_configuration, variables = archiver_variables, ) args = actions.args() args.add_all(command_line) args.add_all(objects) env = cc_common.get_environment_variables( action_name = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, feature_configuration = cc_feature_configuration, variables = archiver_variables, ) actions.run( executable = archiver_path, arguments = [args], env = env, # TODO(allevato): It seems like the `cc_common` APIs should have a way to get this value # so that it can be handled consistently for the toolchain in use. execution_requirements = swift_toolchain.execution_requirements, inputs = depset( direct = objects, transitive = [swift_toolchain.cc_toolchain_info.all_files], ), mnemonic = "SwiftArchive", outputs = [output], progress_message = "Linking {}".format(output.short_path), ) def register_libraries_to_link( actions, alwayslink, cc_feature_configuration, is_dynamic, is_static, library_name, objects, swift_toolchain): """Declares files for the requested libraries and registers actions to link them. Args: actions: The object used to register actions. alwayslink: If True, create a static library that should be always-linked (having a `.lo` extension instead of `.a`). This argument is ignored if `is_static` is False. cc_feature_configuration: The C++ feature configuration to use when constructing the action. is_dynamic: If True, declare and link a dynamic library. is_static: If True, declare and link a static library. library_name: The basename (without extension) of the libraries to declare. objects: A list of `File`s denoting object (`.o`) files that will be linked. swift_toolchain: The Swift toolchain provider to use when constructing the action. Returns: A `LibraryToLink` object containing the libraries that were created. """ dynamic_library = None if is_dynamic: # TODO(b/70228246): Implement this. pass if is_static: static_library = derived_files.static_archive( actions = actions, alwayslink = alwayslink, link_name = library_name, ) _register_static_library_link_action( actions = actions, cc_feature_configuration = cc_feature_configuration, objects = objects, output = static_library, swift_toolchain = swift_toolchain, ) else: static_library = None return cc_common.create_library_to_link( actions = actions, alwayslink = alwayslink, cc_toolchain = swift_toolchain.cc_toolchain_info, feature_configuration = cc_feature_configuration, pic_static_library = static_library, dynamic_library = dynamic_library, ) def register_link_executable_action( actions, action_environment, additional_linking_contexts, cc_feature_configuration, clang_executable, deps, expanded_linkopts, inputs, mnemonic, objects, outputs, progress_message, rule_specific_args, swift_toolchain): """Registers an action that invokes `clang` to link object files. Args: actions: The object used to register actions. action_environment: A `dict` of environment variables that should be set for the compile action. additional_linking_contexts: Additional linking contexts that provide libraries or flags that should be linked into the executable. cc_feature_configuration: The C++ feature configuration to use when constructing the action. clang_executable: The path to the `clang` executable that will be invoked to link, which is assumed to be present among the tools that the toolchain passes to its action registrars. If this is `None`, then simply `clang` will be used with the assumption that the registrar knows where and how to find it. deps: A list of `deps` representing additional libraries that will be passed to the linker. expanded_linkopts: A list of strings representing options passed to the linker. Any `$(location ...)` placeholders are assumed to have already been expanded. inputs: A `depset` containing additional inputs to the link action, such as those used in `$(location ...)` substitution, or libraries that need to be linked. mnemonic: The mnemonic printed by Bazel when the action executes. objects: A list of object (.o) files that will be passed to the linker. outputs: A list of `File`s that should be passed as the outputs of the link action. progress_message: The progress message printed by Bazel when the action executes. rule_specific_args: Additional arguments that are rule-specific that will be passed to `clang`. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain. """ if not clang_executable: clang_executable = "clang" common_args = actions.args() # TODO(b/133833674): Remove this and get the executable from CROSSTOOL (see the comment at # the end of the function for more information). common_args.add(clang_executable) deps_libraries = [] additional_input_depsets = [] all_linkopts = list(expanded_linkopts) deps_dynamic_framework_names = [] deps_dynamic_framework_paths = [] deps_static_framework_files = [] deps_sdk_dylibs = [] deps_sdk_frameworks = [] for dep in deps: if CcInfo in dep: cc_info = dep[CcInfo] additional_input_depsets.append(cc_info.linking_context.additional_inputs) all_linkopts.extend(cc_info.linking_context.user_link_flags) deps_libraries.extend( collect_cc_libraries(cc_info = cc_info, include_pic_static = True), ) if apple_common.Objc in dep: objc = dep[apple_common.Objc] if framework_migration.is_post_framework_migration(): deps_dynamic_framework_names.append(objc.dynamic_framework_names) deps_dynamic_framework_paths.append(objc.dynamic_framework_paths) deps_static_framework_files.append(objc.static_framework_file) else: deps_dynamic_framework_names.append(depset( [ objc_provider_framework_name(fdir) for fdir in objc.dynamic_framework_dir.to_list() ], )) deps_dynamic_framework_paths.append(depset( [fdir.dirname for fdir in objc.dynamic_framework_dir.to_list()], )) deps_static_framework_files.append(depset( [ paths.join(fdir, objc_provider_framework_name(fdir)) for fdir in objc.framework_dir.to_list() ], )) deps_sdk_dylibs.append(objc.sdk_dylib) deps_sdk_frameworks.append(objc.sdk_framework) for linking_context in additional_linking_contexts: additional_input_depsets.append(linking_context.additional_inputs) all_linkopts.extend(linking_context.user_link_flags) for library in linking_context.libraries_to_link: if library.pic_static_library: deps_libraries.append(library.pic_static_library) elif library.static_library: deps_libraries.append(library.static_library) libraries = depset(deps_libraries, order = "topological") link_input_depsets = [ libraries, inputs, ] + additional_input_depsets link_input_args = actions.args() link_input_args.set_param_file_format("multiline") link_input_args.use_param_file("@%s", use_always = True) link_input_args.add_all(objects) is_darwin = swift_toolchain.system_name == "darwin" link_input_args.add_all(libraries, map_each = ( _link_library_darwin_map_fn if is_darwin else _link_library_linux_map_fn )) # Add various requirements from propagated Objective-C frameworks: # * Static prebuilt framework binaries are passed as regular arguments. link_input_args.add_all( depset(transitive = deps_static_framework_files), ) # * `sdk_dylibs` values are passed with `-l`. link_input_args.add_all(depset(transitive = deps_sdk_dylibs), format_each = "-l%s") # * `sdk_frameworks` values are passed with `-framework`. link_input_args.add_all(depset(transitive = deps_sdk_frameworks), before_each = "-framework") # * Dynamic prebuilt frameworks are passed by providing their parent directory as a search path # using `-F` and the framework name as `-framework`. link_input_args.add_all( depset(transitive = deps_dynamic_framework_paths), format_each = "-F%s", ) link_input_args.add_all( depset(transitive = deps_dynamic_framework_names), before_each = "-framework", ) # If the C++ toolchain provides an embedded runtime, include it. See the documentation for # `CcToolchainInfo.{dynamic,static}_runtime_lib` for an explanation of the feature check: # https://docs.bazel.build/versions/master/skylark/lib/CcToolchainInfo.html#static_runtime_lib if cc_common.is_enabled( feature_configuration = cc_feature_configuration, feature_name = "static_link_cpp_runtimes", ): # TODO(b/70228246): Call dynamic_runtime_lib if dynamic linking. cc_runtime_libs = swift_toolchain.cc_toolchain_info.static_runtime_lib( feature_configuration = cc_feature_configuration, ) link_input_args.add_all(cc_runtime_libs) link_input_depsets.append(cc_runtime_libs) user_args = actions.args() user_args.add_all(all_linkopts) execution_requirements = swift_toolchain.execution_requirements # TODO(b/133833674): Even though we're invoking clang, not swift, we do so through the # worker (in non-persistent mode) to get the necessary `xcrun` wrapping and placeholder # substitution on macOS. This shouldn't actually be necessary; we should be able to query # CROSSTOOL for the linker tool and that should include the correct wrapping. However, the # Bazel OSX CROSSTOOL currently uses `cc_wrapper.sh` instead of `wrapped_clang` for C++ # linking actions (it properly uses `wrapped_clang` for Objective-C linking), so until that # is resolved (https://github.com/bazelbuild/bazel/pull/8495), we have to use this workaround. # This also means that, until we migrate to `wrapped_clang`, we're missing out on other # features like dSYM extraction, but that's actually not any different that the situation # today. run_swift_action( actions = actions, arguments = [ common_args, link_input_args, rule_specific_args, user_args, ], env = action_environment, execution_requirements = execution_requirements, inputs = depset( objects, transitive = link_input_depsets + [ swift_toolchain.cc_toolchain_info.all_files, ], ), mnemonic = mnemonic, outputs = outputs, progress_message = progress_message, swift_toolchain = swift_toolchain, ) def _link_library_darwin_map_fn(lib): """Maps a library to the appropriate flags to link them. This function handles `alwayslink` (.lo) libraries correctly by passing them with `-force_load`. Args: lib: A `File`, passed in when the calling `Args` object is ready to map it to an argument. Returns: A list of command-line arguments (strings) that link the library correctly. """ if lib.basename.endswith(".lo"): return "-Wl,-force_load,{lib}".format(lib = lib.path) else: return lib.path def _link_library_linux_map_fn(lib): """Maps a library to the appropriate flags to link them. This function handles `alwayslink` (.lo) libraries correctly by surrounding them with `--(no-)whole-archive`. Args: lib: A `File`, passed in when the calling `Args` object is ready to map it to an argument. Returns: A list of command-line arguments (strings) that link the library correctly. """ if lib.basename.endswith(".lo"): return "-Wl,--whole-archive,{lib},--no-whole-archive".format(lib = lib.path) else: return lib.path 07070100000042000081A4000003E800000064000000015D9E34630000241C000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/swift/internal/non_swift_target_aspect.bzl# Copyright 2018 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. """Attaches `SwiftInfo` providers as needed to non-Swift targets in the dependency graph. There are two reasons to attach a `SwiftInfo` provider to non-Swift targets: * For a `cc_library`, we want to generate a module map so that it can be imported directly by Swift, as well as propagate the merged `SwiftInfo`s of its children so that information from those dependencies isn't lost. (For example, consider a `swift_library` that depends on an `objc_library` that depends on a `swift_library`.) The modules generated by this aspect have names that are automatically derived from the label of the `cc_library` target, using the same logic used to derive the module names for Swift targets. * For any other target, we want to propagate the merged `SwiftInfo`s of its children so that types defined in those modules are available to the parent modules. For example, if a Swift target indirectly depends on another Swift target through an Objective-C target, the Objective-C target's implementation doesn't know that it needs to propagate the Swift info, so the aspect handles that. The exception to this is C++ dependencies, where we explicitly discard indirect dependencies because we don't have a good way to handle some of the targets that show up in those graphs yet. This aspect is an implementation detail of the Swift build rules and is not meant to be attached to other rules or run independently. """ load("@bazel_skylib//lib:paths.bzl", "paths") load(":api.bzl", "swift_common") load(":derived_files.bzl", "derived_files") load(":features.bzl", "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD") load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo") load(":utils.bzl", "get_providers") def _explicit_module_name(tags): """Returns an explicit module name specified by a tag of the form `"swift_module=Foo"`. Since tags are unprocessed strings, nothing prevents the `swift_module` tag from being listed multiple times on the same target with different values. For this reason, the aspect uses the _last_ occurrence that it finds in the list. Args: tags: The list of tags from the `cc_library` target to which the aspect is being applied. Returns: The desired module name if it was present in `tags`, or `None`. """ module_name = None for tag in tags: if tag.startswith("swift_module="): _, _, module_name = tag.partition("=") return module_name def _header_path(file, module_map, workspace_relative): """Returns the path to a header file as it should be written into the module map. Args: file: A `File` representing the header whose path should be returned. module_map: A `File` representing the module map being written, which is used during path relativization if necessary. workspace_relative: A Boolean value indicating whether the path should be workspace-relative or module-map-relative. Returns: The path to the header file, relative to either the workspace or the module map as requested. """ # If the module map is workspace-relative, then the file's path is what we want. if workspace_relative: return file.path # Otherwise, since the module map is generated, we need to get the full path to it rather than # just its short path (that is, the path starting with bazel-out/). Then, we can simply walk up # the same number of parent directories as there are path segments, and append the header # file's path to that. num_segments = len(paths.dirname(module_map.path).split("/")) return ("../" * num_segments) + file.path def _write_module_map( actions, module_map, module_name, hdrs = [], textual_hdrs = [], workspace_relative = False): """Writes the content of the module map to a file. Args: actions: The actions object from the aspect context. module_map: A `File` representing the module map being written. module_name: The name of the module being generated. hdrs: The value of `attr.hdrs` for the target being written (which is a list of targets that are either source files or generated files). textual_hdrs: The value of `attr.textual_hdrs` for the target being written (which is a list of targets that are either source files or generated files). workspace_relative: A Boolean value indicating whether the path should be workspace-relative or module-map-relative. """ content = "module {} {{\n".format(module_name) # TODO(allevato): Should we consider moving this to an external tool to avoid the analysis time # expansion of these depsets? We're doing this in the initial version because these sets tend # to be very small. for target in hdrs: content += "".join([ ' header "{}"\n'.format(_header_path(header, module_map, workspace_relative)) for header in target.files.to_list() ]) for target in textual_hdrs: content += "".join([ ' textual header "{}"\n'.format(_header_path(header, module_map, workspace_relative)) for header in target.files.to_list() ]) content += " export *\n" content += "}\n" actions.write(output = module_map, content = content) def _non_swift_target_aspect_impl(target, aspect_ctx): # Do nothing if the target already propagates `SwiftInfo`. if SwiftInfo in target: return [] attr = aspect_ctx.rule.attr # It's not great to depend on the rule name directly, but we need to access the exact `hdrs` # and `textual_hdrs` attributes (which may not be propagated distinctly by a provider) and # also make sure that we don't pick up rules like `objc_library` which already handle module # map generation. # TODO(allevato): Can `CcInfo.compilation_context` propagate these headers distinctly? if aspect_ctx.rule.kind == "cc_library": # If there's an explicit module name, use it; otherwise, auto-derive one using the usual # derivation logic for Swift targets. module_name = _explicit_module_name(attr.tags) if not module_name: if "/" in target.label.name or "+" in target.label.name: return [] module_name = swift_common.derive_module_name(target.label) # Determine if the toolchain requires module maps to use workspace-relative paths or not. toolchain = aspect_ctx.attr._toolchain_for_aspect[SwiftToolchainInfo] feature_configuration = swift_common.configure_features( ctx = aspect_ctx, requested_features = aspect_ctx.features, swift_toolchain = toolchain, unsupported_features = aspect_ctx.disabled_features, ) workspace_relative = swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD, ) module_map = derived_files.module_map(aspect_ctx.actions, target.label.name) _write_module_map( actions = aspect_ctx.actions, hdrs = attr.hdrs, module_map = module_map, module_name = module_name, textual_hdrs = attr.textual_hdrs, workspace_relative = workspace_relative, ) # TODO(b/118311259): Figure out how to handle transitive dependencies, in case a C-only # module incldues headers from another C-only module. We currently have a lot of targets # with labels that clash when mangled into a Swift module name, so we need to figure out # how to handle those (either by adding the `swift_module` tag to them, or opting them in # some other way). So for now, when we hit a `cc_library` target, we explicitly discard any # of the Swift info from its dependencies. return [swift_common.create_swift_info( modulemaps = [module_map], module_name = module_name, )] # If it's any other rule, just merge the `SwiftInfo` providers from its deps. deps = getattr(attr, "deps", []) swift_infos = get_providers(deps, SwiftInfo) if swift_infos: return [swift_common.create_swift_info(swift_infos = swift_infos)] return [] non_swift_target_aspect = aspect( attrs = swift_common.toolchain_attrs(toolchain_attr_name = "_toolchain_for_aspect"), attr_aspects = ["deps"], fragments = ["cpp"], implementation = _non_swift_target_aspect_impl, ) 07070100000043000081A4000003E800000064000000015D9E346300001A45000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/swift/internal/proto_gen_utils.bzl# Copyright 2019 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. """Utility functions shared by rules/aspects that generate sources from .proto files.""" load("@bazel_skylib//lib:paths.bzl", "paths") load(":utils.bzl", "proto_import_path") def declare_generated_files(name, actions, extension_fragment, proto_source_root, proto_srcs): """Declares generated `.swift` files that correspond to a list of `.proto` files. Args: name: The name of the target currently being analyzed. actions: The context's actions object. extension_fragment: An extension fragment that precedes `.swift` on the end of the generated files. In other words, the file `foo.proto` will generate a file named `foo.{extension_fragment}.swift`. proto_source_root: the source root of the `.proto` files in `proto_srcs`. proto_srcs: A list of `.proto` files. Returns: A list of files that map one-to-one to `proto_srcs` but with `.{extension_fragment}.swift` extensions instead of `.proto`. """ return [ actions.declare_file(_generated_file_path(name, extension_fragment, proto_source_root, f)) for f in proto_srcs ] def extract_generated_dir_path(name, extension_fragment, proto_source_root, generated_files): """Extracts the full path to the directory where `.swift` files are generated. This dance is required because we cannot get the full (repository-relative) path to the directory that we need to pass to `protoc` unless we either create the directory as a tree artifact or extract it from a file within that directory. We cannot do the former because we also want to declare individual outputs for the files we generate, and we can't declare a directory that has the same prefix as any of the files we generate. So, we assume we have at least one file and we extract the path from it. Args: name: The name of the target currently being analyzed. extension_fragment: An extension fragment that precedes `.swift` on the end of the generated files. In other words, the file `foo.proto` will generate a file named `foo.{extension_fragment}.swift`. proto_source_root: the source root for the `.proto` files `generated_files` are generated from. generated_files: A list of generated `.swift` files, one of which will be used to extract the directory path. Returns: The repository-relative path to the directory where the `.swift` files are being generated. """ if not generated_files: return None first_path = generated_files[0].path dir_name = _generated_file_path(name, extension_fragment, proto_source_root) offset = first_path.find(dir_name) return first_path[:offset + len(dir_name)] def register_module_mapping_write_action(name, actions, module_mappings): """Registers an action that generates a module mapping for a proto library. Args: name: The name of the target being analyzed. actions: The context's actions object. module_mappings: The sequence of module mapping `struct`s to be rendered. This sequence should already have duplicates removed. Returns: The `File` representing the module mapping that will be generated in protobuf text format. """ mapping_file = actions.declare_file("{}.protoc_gen_swift_modules.asciipb".format(name)) content = "".join([_render_text_module_mapping(m) for m in module_mappings]) actions.write( content = content, output = mapping_file, ) return mapping_file def _generated_file_path(name, extension_fragment, proto_source_root, proto_file = None): """Returns the short path of a generated `.swift` file corresponding to a `.proto` file. The returned workspace-relative path should be used to declare output files so that they are generated relative to the target's package in the output directory tree. If `proto_file` is `None` (or unspecified), then this function returns the workspace-relative path to the directory where the `.swift` files would be generated. Args: name: The name of the target currently being analyzed. extension_fragment: An extension fragment that precedes `.swift` on the end of the generated files. In other words, the file `foo.proto` will generate a file named `foo.{extension_fragment}.swift`. proto_source_root: The source root for the `.proto` file. proto_file: The `.proto` file whose generated `.swift` path should be computed. Returns: The workspace-relative path of the `.swift` file that will be generated for the given `.proto` file, or the workspace-relative path to the directory that contains the declared `.swift` files if `proto_file` is `None`. """ dir_path = "{name}.protoc_gen_{extension}_swift".format( name = name, extension = extension_fragment, ) if proto_file: generated_file_path = paths.replace_extension( proto_import_path(proto_file, proto_source_root), ".{}.swift".format(extension_fragment), ) return paths.join(dir_path, generated_file_path) return dir_path def _render_text_module_mapping(mapping): """Renders the text format proto for a module mapping. Args: mapping: A single module mapping `struct`. Returns: A string containing the module mapping for the target in protobuf text format. """ module_name = mapping.module_name proto_file_paths = mapping.proto_file_paths content = "mapping {\n" content += ' module_name: "%s"\n' % module_name if len(proto_file_paths) == 1: content += ' proto_file_path: "%s"\n' % proto_file_paths[0] else: # Use list form to avoid parsing and looking up the field name for each entry. content += ' proto_file_path: [\n "%s"' % proto_file_paths[0] for path in proto_file_paths[1:]: content += ',\n "%s"' % path content += "\n ]\n" content += "}\n" return content 07070100000044000081A4000003E800000064000000015D9E3463000025EE000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/swift/internal/providers.bzl# Copyright 2018 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. """Defines Skylark providers that propagated by the Swift BUILD rules.""" SwiftInfo = provider( doc = """ Contains information about the compiled artifacts of a Swift module. This provider contains a large number of fields and many custom rules may not need to set all of them. Instead of constructing a `SwiftInfo` provider directly, consider using the `swift_common.create_swift_info` function, which has reasonable defaults for any fields not explicitly set. """, fields = { "direct_defines": """ `List` of `string`s. The values specified by the `defines` attribute of the library that directly propagated this provider. """, "direct_swiftdocs": """ `List` of `File`s. The Swift documentation (`.swiftdoc`) files for the library that directly propagated this provider. """, "direct_swiftmodules": """ `List` of `File`s. The Swift modules (`.swiftmodule`) for the library that directly propagated this provider. """, "module_name": """ `String`. The name of the Swift module represented by the target that directly propagated this provider. This field will be equal to the explicitly assigned module name (if present); otherwise, it will be equal to the autogenerated module name. """, "swift_version": """ `String`. The version of the Swift language that was used when compiling the propagating target; that is, the value passed via the `-swift-version` compiler flag. This will be `None` if the flag was not set. """, "transitive_defines": """ `Depset` of `string`s. The transitive `defines` specified for the library that propagated this provider and all of its dependencies. """, "transitive_generated_headers": """ `Depset` of `File`s. The transitive generated header files that can be used by Objective-C sources to interop with the transitive Swift libraries. """, "transitive_modulemaps": """ `Depset` of `File`s. The transitive module map files that will be passed to Clang using the `-fmodule-map-file` option. """, "transitive_swiftdocs": """ `Depset` of `File`s. The transitive Swift documentation (`.swiftdoc`) files emitted by the library that propagated this provider and all of its dependencies. """, "transitive_swiftinterfaces": """ `Depset` of `File`s. The transitive Swift interface (`.swiftinterface`) files emitted by the library that propagated this provider and all of its dependencies. """, "transitive_swiftmodules": """ `Depset` of `File`s. The transitive Swift modules (`.swiftmodule`) emitted by the library that propagated this provider and all of its dependencies. """, }, ) SwiftProtoInfo = provider( doc = "Propagates Swift-specific information about a `proto_library`.", fields = { "module_mappings": """ `Sequence` of `struct`s. Each struct contains `module_name` and `proto_file_paths` fields that denote the transitive mappings from `.proto` files to Swift modules. This allows messages that reference messages in other libraries to import those modules in generated code. """, "pbswift_files": """ `Depset` of `File`s. The transitive Swift source files (`.pb.swift`) generated from the `.proto` files. """, }, ) SwiftToolchainInfo = provider( doc = """ Propagates information about a Swift toolchain to compilation and linking rules that use the toolchain. """, fields = { "action_environment": """ `Dict`. Environment variables that should be set during any actions spawned to compile or link Swift code. """, "all_files": """ A `depset` of `File`s containing all the Swift toolchain files (tools, libraries, and other resource files) so they can be passed as `tools` to actions using this toolchain. """, "cc_toolchain_info": """ The `cc_common.CcToolchainInfo` provider from the Bazel C++ toolchain that this Swift toolchain depends on. """, "clang_executable": """ `String`. The path to the `clang` executable, which is used to link binaries. """, "command_line_copts": """ `List` of `strings`. Flags that were passed to Bazel using the `--swiftcopt` command line flag. These flags have the highest precedence; they are added to compilation command lines after the toolchain default flags (`SwiftToolchainInfo.swiftc_copts`) and after flags specified in the `copts` attributes of Swift targets. """, "cpu": "`String`. The CPU architecture that the toolchain is targeting.", "execution_requirements": """ `Dict`. Execution requirements that should be passed to any actions spawned to compile or link Swift code. For example, when using an Xcode toolchain, the execution requirements should be such that running on Darwin is required. """, "linker_opts_producer": """ Skylib `partial`. A partial function that returns the flags that should be passed to Clang to link a binary or test target with the Swift runtime libraries. The partial should be called with two arguments: * `is_static`: A `Boolean` value indicating whether to link against the static or dynamic runtime libraries. * `is_test`: A `Boolean` value indicating whether the target being linked is a test target. """, "object_format": """ `String`. The object file format of the platform that the toolchain is targeting. The currently supported values are `"elf"` and `"macho"`. """, "optional_implicit_deps": """ `List` of `Target`s. Library targets that should be added as implicit dependencies of any `swift_library`, `swift_binary`, or `swift_test` target that does not have the feature `swift.minimal_deps` applied. """, "requested_features": """ `List` of `string`s. Features that should be implicitly enabled by default for targets built using this toolchain, unless overridden by the user by listing their negation in the `features` attribute of a target/package or in the `--features` command line flag. These features determine various compilation and debugging behaviors of the Swift build rules, and they are also passed to the C++ APIs used when linking (so features defined in CROSSTOOL may be used here). """, "required_implicit_deps": """ `List` of `Target`s. Library targets that should be unconditionally added as implicit dependencies of any `swift_library`, `swift_binary`, or `swift_test` target. """, "root_dir": "`String`. The workspace-relative root directory of the toolchain.", "stamp_producer": """ Skylib `partial`. A partial function that compiles build data that should be stamped into binaries. This value may be `None` if the toolchain does not support link stamping. The `swift_binary` and `swift_test` rules call this function _whether or not_ link stamping is enabled for that target. This provides toolchains the option of still linking fixed placeholder data into the binary if desired, instead of linking nothing at all. Whether stamping is enabled can be checked by inspecting `ctx.attr.stamp` inside the partial's implementation. The rule implementation will call this partial and pass it the following four arguments: * `ctx`: The rule context of the target being built. * `cc_feature_configuration`: The C++ feature configuration to use when compiling the stamp code. * `cc_toolchain`: The C++ toolchain (`CcToolchainInfo` provider) to use when compiling the stamp code. * `binary`: The `File` object representing the binary being linked. The partial should return a `CcLinkingContext` containing the data (such as object files) to be linked into the binary, or `None` if nothing should be linked into the binary. """, "supports_objc_interop": """ `Boolean`. Indicates whether or not the toolchain supports Objective-C interop. """, "swiftc_copts": """ `List` of `strings`. Additional flags that should be passed to `swiftc` when compiling libraries or binaries with this toolchain. These flags will come first in compilation command lines, allowing them to be overridden by `copts` attributes and `--swiftcopt` flags. """, "swift_worker": """ `File`. The executable representing the worker executable used to invoke the compiler and other Swift tools (for both incremental and non-incremental compiles). """, "system_name": """ `String`. The name of the operating system that the toolchain is targeting. """, "unsupported_features": """ `List` of `string`s. Features that should be implicitly disabled by default for targets built using this toolchain, unless overridden by the user by listing them in the `features` attribute of a target/package or in the `--features` command line flag. These features determine various compilation and debugging behaviors of the Swift build rules, and they are also passed to the C++ APIs used when linking (so features defined in CROSSTOOL may be used here). """, }, ) SwiftUsageInfo = provider( doc = """ A provider that indicates that Swift was used by a target or any target that it depends on, and specifically which toolchain was used. """, fields = { "toolchain": """ The Swift toolchain that was used to build the targets propagating this provider. """, }, ) 07070100000045000081A4000003E800000064000000015D9E346300001DC9000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/swift/internal/swift_autoconfiguration.bzl# Copyright 2019 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. """Definitions for autoconfiguring Swift toolchains. At this time, only the Linux toolchain uses this capability. The Xcode toolchain determines which features are supported using Xcode version checks in xcode_toolchain.bzl. NOTE: This file is loaded from repositories.bzl, before any workspace dependencies have been downloaded. Therefore, only files within this repository should be loaded here. Do not load anything else, even common libraries like Skylib. """ load( "@build_bazel_rules_swift//swift/internal:features.bzl", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_ENABLE_BATCH_MODE", "SWIFT_FEATURE_USE_RESPONSE_FILES", ) def _scratch_file(repository_ctx, temp_dir, name, content = ""): """Creates and returns a scratch file with the given name and content. Args: repository_ctx: The repository context. temp_dir: The `path` to the temporary directory where the file should be created. name: The name of the scratch file. content: The text to write into the scratch file. Returns: The `path` to the file that was created. """ path = temp_dir.get_child(name) repository_ctx.file(path, content) return path def _swift_succeeds(repository_ctx, swiftc_path, *args): """Returns True if an invocation of the Swift compiler is successful. Args: repository_ctx: The repository context. swiftc_path: The `path` to the `swiftc` executable to spawn. *args: Zero or more arguments to pass to `swiftc` on the command line. Returns: True if the invocation was successful (a zero exit code); otherwise, False. """ swift_result = repository_ctx.execute([swiftc_path] + list(args)) return swift_result.return_code == 0 def _check_enable_batch_mode(repository_ctx, swiftc_path, temp_dir): """Returns True if `swiftc` supports batch mode.""" return _swift_succeeds(repository_ctx, swiftc_path, "-version", "-enable-batch-mode") def _check_debug_prefix_map(repository_ctx, swiftc_path, temp_dir): """Returns True if `swiftc` supports debug prefix mapping.""" return _swift_succeeds(repository_ctx, swiftc_path, "-version", "-debug-prefix-map", "foo=bar") def _check_use_response_files(repository_ctx, swiftc_path, temp_dir): """Returns True if `swiftc` supports the use of response files.""" param_file = _scratch_file(repository_ctx, temp_dir, "check-response-files.params", "-version") return _swift_succeeds(repository_ctx, swiftc_path, "@{}".format(param_file)) def _compute_feature_values(repository_ctx, swiftc_path): """Computes a list of supported and unsupported features by running a sequence of checks. The result of this function is a list of feature names that can be provided as the `features` attribute of a toolchain rule. That is, enabled features are represented by the feature name itself, and unsupported features are represented as a hyphen ("-") followed by the feature name. Args: repository_ctx: The repository context. swiftc_path: The `path` to the `swiftc` executable. Returns: A list of feature strings that can be provided as the `features` attribute of a toolchain rule. """ feature_values = [] for feature, checker in _FEATURE_CHECKS.items(): # Create a scratch directory in which the check function can write any files that it needs # to pass to `swiftc`. mktemp_result = repository_ctx.execute([ "mktemp", "-d", "tmp.autoconfiguration.XXXXXXXXXX", ]) temp_dir = repository_ctx.path(mktemp_result.stdout.strip()) if checker(repository_ctx, swiftc_path, temp_dir): feature_values.append(feature) else: feature_values.append("-{}".format(feature)) # Clean up the scratch directory. # TODO(allevato): Replace with `repository_ctx.delete` once it's released. repository_ctx.execute(["rm", "-r", temp_dir]) return feature_values # Features whose support should be checked and the functions used to check them. A check # function has the following signature: # # def <function_name>(repository_ctx, swiftc_path, temp_dir) # # Where `swiftc_path` and `temp_dir` are `path` structures denoting the path to the `swiftc` # executable and a scratch directory, respectively. The function should return True if the # feature is supported. _FEATURE_CHECKS = { SWIFT_FEATURE_DEBUG_PREFIX_MAP: _check_debug_prefix_map, SWIFT_FEATURE_ENABLE_BATCH_MODE: _check_enable_batch_mode, SWIFT_FEATURE_USE_RESPONSE_FILES: _check_use_response_files, } def _create_linux_toolchain(repository_ctx): """Creates BUILD targets for the Swift toolchain on Linux. Args: repository_ctx: The repository rule context. """ if repository_ctx.os.environ.get("CC") != "clang": fail("ERROR: rules_swift uses Bazel's CROSSTOOL to link, but Swift " + "requires that the driver used is clang. Please set `CC=clang` in " + "your environment before invoking Bazel.") path_to_swiftc = repository_ctx.which("swiftc") path_to_clang = repository_ctx.which("clang") root = path_to_swiftc.dirname.dirname feature_values = _compute_feature_values(repository_ctx, path_to_swiftc) repository_ctx.file( "BUILD", """ load( "@build_bazel_rules_swift//swift/internal:swift_toolchain.bzl", "swift_toolchain", ) package(default_visibility = ["//visibility:public"]) swift_toolchain( name = "toolchain", arch = "x86_64", clang_executable = "{path_to_clang}", features = [{feature_list}], os = "linux", root = "{root}", ) """.format( feature_list = ", ".join(['"{}"'.format(feature) for feature in feature_values]), path_to_clang = path_to_clang, root = root, ), ) def _create_xcode_toolchain(repository_ctx): """Creates BUILD targets for the Swift toolchain on macOS using Xcode. Args: repository_ctx: The repository rule context. """ path_to_swiftc = repository_ctx.which("swiftc") repository_ctx.file( "BUILD", """ load( "@build_bazel_rules_swift//swift/internal:xcode_swift_toolchain.bzl", "xcode_swift_toolchain", ) package(default_visibility = ["//visibility:public"]) xcode_swift_toolchain( name = "toolchain", ) """, ) def _swift_autoconfiguration_impl(repository_ctx): # TODO(allevato): This is expedient and fragile. Use the platforms/toolchains # APIs instead to define proper toolchains, and make it possible to support # non-Xcode toolchains on macOS as well. os_name = repository_ctx.os.name.lower() if os_name.startswith("mac os"): _create_xcode_toolchain(repository_ctx) else: _create_linux_toolchain(repository_ctx) swift_autoconfiguration = repository_rule( environ = ["CC", "PATH"], implementation = _swift_autoconfiguration_impl, ) 07070100000046000081A4000003E800000064000000015D9E346300004412000000000000000000000000000000000000003E00000000bazel-rules-swift-0.13.0/swift/internal/swift_binary_test.bzl# Copyright 2018 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. """Implementation of the `swift_binary` and `swift_test` rules.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:partial.bzl", "partial") load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "CPP_LINK_EXECUTABLE_ACTION_NAME") load(":api.bzl", "swift_common") load(":compiling.bzl", "output_groups_from_compilation_outputs") load(":derived_files.bzl", "derived_files") load(":features.bzl", "SWIFT_FEATURE_BUNDLED_XCTESTS") load(":linking.bzl", "register_link_executable_action") load(":non_swift_target_aspect.bzl", "non_swift_target_aspect") load(":providers.bzl", "SwiftToolchainInfo") load(":utils.bzl", "expand_locations") def _binary_rule_attrs(stamp_default): """Returns the dictionary of attributes common to both `swift_binary` and `swift_test`. Args: stamp_default: The default value of the `stamp` attribute. Returns: A `dict` of attributes for a binary or test rule. """ return dicts.add( swift_common.compilation_attrs(additional_deps_aspects = [non_swift_target_aspect]), { "linkopts": attr.string_list( doc = """ Additional linker options that should be passed to `clang`. These strings are subject to `$(location ...)` expansion. """, mandatory = False, ), "malloc": attr.label( default = Label("@bazel_tools//tools/cpp:malloc"), doc = """ Override the default dependency on `malloc`. By default, Swift binaries are linked against `@bazel_tools//tools/cpp:malloc"`, which is an empty library and the resulting binary will use libc's `malloc`. This label must refer to a `cc_library` rule. """, mandatory = False, providers = [[CcInfo]], ), "stamp": attr.bool( default = stamp_default, doc = """ Enable or disable link stamping. If this value is true (and if the toolchain supports link stamping), then the toolchain's stamping logic will be invoked to link additional identifying information into the binary. This information typically comes from the stable and volatile build information written by Bazel in the output directory, but could be anything that the toolchain wishes to link into binaries. If false, no stamp information will be linked into the binary, which improves build caching. """, mandatory = False, ), # Do not add references; temporary attribute for C++ toolchain Skylark migration. "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")), }, ) def _configure_features_for_binary(ctx, requested_features = [], unsupported_features = []): """Creates and returns the feature configuration for binary linking. This helper automatically handles common features for all Swift binary-creating targets, like code coverage. Args: ctx: The rule context. requested_features: Additional features that are requested for a particular rule/target. unsupported_features: Additional features that are unsupported for a particular rule/target. Returns: The `FeatureConfiguration` that was created. """ swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] # Combine the features from the rule context with those passed into this function. requested_features = ctx.features + requested_features unsupported_features = ctx.disabled_features + unsupported_features # Enable LLVM coverage in CROSSTOOL if this is a coverage build. Note that we explicitly enable # LLVM format and disable GCC format because the former is the only one that Swift supports. if ctx.configuration.coverage_enabled: requested_features.append("llvm_coverage_map_format") unsupported_features.append("gcc_coverage_map_format") return swift_common.configure_features( ctx = ctx, requested_features = requested_features, swift_toolchain = swift_toolchain, unsupported_features = unsupported_features, ) def _swift_linking_rule_impl( ctx, feature_configuration, is_test, swift_toolchain, linkopts = []): """The shared implementation function for `swift_{binary,test}`. Args: ctx: The rule context. feature_configuration: A feature configuration obtained from `swift_common.configure_features`. is_test: A `Boolean` value indicating whether the binary is a test target. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain being used to build the target. linkopts: Additional rule-specific flags that should be passed to the linker. Returns: A tuple with two values: the `File` representing the binary that was linked, and a list of providers to be propagated by the target being built. """ copts = expand_locations(ctx, ctx.attr.copts, ctx.attr.swiftc_inputs) linkopts = list(linkopts) + expand_locations(ctx, ctx.attr.linkopts, ctx.attr.swiftc_inputs) linkopts += ctx.fragments.cpp.linkopts additional_inputs = ctx.files.swiftc_inputs srcs = ctx.files.srcs out_bin = derived_files.executable(ctx.actions, target_name = ctx.label.name) compilation_outputs = None objects_to_link = [] output_groups = {} link_args = ctx.actions.args() link_args.add("-o", out_bin) if not srcs: additional_inputs_to_linker = depset(direct = additional_inputs) else: module_name = ctx.attr.module_name if not module_name: module_name = swift_common.derive_module_name(ctx.label) compilation_outputs = swift_common.compile( actions = ctx.actions, additional_inputs = additional_inputs, bin_dir = ctx.bin_dir, copts = copts, defines = ctx.attr.defines, deps = ctx.attr.deps, feature_configuration = feature_configuration, genfiles_dir = ctx.genfiles_dir, module_name = module_name, srcs = srcs, swift_toolchain = swift_toolchain, target_name = ctx.label.name, ) link_args.add_all(compilation_outputs.linker_flags) objects_to_link.extend(compilation_outputs.object_files) additional_inputs_to_linker = depset(compilation_outputs.linker_inputs) output_groups = output_groups_from_compilation_outputs( compilation_outputs = compilation_outputs, ) # TODO(b/70228246): Also support mostly-static and fully-dynamic modes, here and for the C++ # toolchain args below. toolchain_linker_flags = partial.call( swift_toolchain.linker_opts_producer, is_static = True, is_test = is_test, ) link_args.add_all(toolchain_linker_flags) # Get additional linker flags from the C++ toolchain. cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ) variables = cc_common.create_link_variables( cc_toolchain = swift_toolchain.cc_toolchain_info, feature_configuration = cc_feature_configuration, is_static_linking_mode = True, ) link_cpp_toolchain_flags = cc_common.get_memory_inefficient_command_line( action_name = CPP_LINK_EXECUTABLE_ACTION_NAME, feature_configuration = cc_feature_configuration, variables = variables, ) link_args.add_all(link_cpp_toolchain_flags) deps_to_link = ctx.attr.deps + swift_common.get_implicit_deps( feature_configuration = feature_configuration, swift_toolchain = swift_toolchain, ) if ctx.attr.malloc: deps_to_link.append(ctx.attr.malloc) additional_linking_contexts = [] if swift_toolchain.stamp_producer: stamp_context = partial.call( swift_toolchain.stamp_producer, ctx, cc_feature_configuration, swift_toolchain.cc_toolchain_info, out_bin, ) if stamp_context: additional_linking_contexts.append(stamp_context) register_link_executable_action( actions = ctx.actions, action_environment = swift_toolchain.action_environment, additional_linking_contexts = additional_linking_contexts, cc_feature_configuration = cc_feature_configuration, clang_executable = swift_toolchain.clang_executable, deps = deps_to_link, expanded_linkopts = linkopts, inputs = additional_inputs_to_linker, mnemonic = "SwiftLinkExecutable", objects = objects_to_link, outputs = [out_bin], progress_message = "Linking {}".format(out_bin.short_path), rule_specific_args = link_args, swift_toolchain = swift_toolchain, ) providers = [OutputGroupInfo(**output_groups)] return out_bin, providers def _create_xctest_runner(name, actions, binary, xctest_runner_template): """Creates a shell script that will bundle a test binary and launch the `xctest` helper tool. Args: name: The name of the target being built, which will be used as the basename of the bundle (followed by the `.xctest` bundle extension). actions: The context's actions object. binary: The `File` representing the test binary that should be bundled and executed. xctest_runner_template: The `File` that will be used as a template to generate the test runner shell script. Returns: A `File` representing the shell script that will launch the test bundle with the `xctest` tool. """ xctest_runner = derived_files.xctest_runner_script(actions, name) actions.expand_template( is_executable = True, output = xctest_runner, template = xctest_runner_template, substitutions = { "%binary%": binary.short_path, }, ) return xctest_runner def _swift_binary_impl(ctx): swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] feature_configuration = _configure_features_for_binary( ctx = ctx, requested_features = ["static_linking_mode"], ) binary, providers = _swift_linking_rule_impl( ctx, feature_configuration = feature_configuration, is_test = False, swift_toolchain = swift_toolchain, ) return providers + [ DefaultInfo( executable = binary, runfiles = ctx.runfiles( collect_data = True, collect_default = True, files = ctx.files.data, ), ), ] def _swift_test_impl(ctx): swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] feature_configuration = _configure_features_for_binary( ctx = ctx, requested_features = ["static_linking_mode"], ) is_bundled = (swift_toolchain.supports_objc_interop and swift_common.is_enabled( feature_configuration = feature_configuration, feature_name = SWIFT_FEATURE_BUNDLED_XCTESTS, )) # If we need to run the test in an .xctest bundle, the binary must have Mach-O type `MH_BUNDLE` # instead of `MH_EXECUTE`. # TODO(allevato): This should really be done in the toolchain's linker_opts_producer partial, # but it doesn't take the feature_configuration as an argument. We should update it to do so. linkopts = ["-Wl,-bundle"] if is_bundled else [] binary, providers = _swift_linking_rule_impl( ctx, feature_configuration = feature_configuration, is_test = True, linkopts = linkopts, swift_toolchain = swift_toolchain, ) # If the tests are to be bundled, create the test runner script as the rule's executable and # place the binary in runfiles so that it can be copied into place. Otherwise, just use the # binary itself as the executable to launch. # TODO(b/65413470): Make the output of the rule _itself_ an `.xctest` bundle once some # limitations of directory artifacts are resolved. if is_bundled: xctest_runner = _create_xctest_runner( name = ctx.label.name, actions = ctx.actions, binary = binary, xctest_runner_template = ctx.file._xctest_runner_template, ) additional_test_outputs = [binary] executable = xctest_runner else: additional_test_outputs = [] executable = binary test_environment = dicts.add( swift_toolchain.action_environment, {"TEST_BINARIES_FOR_LLVM_COV": binary.short_path}, ) return providers + [ DefaultInfo( executable = executable, files = depset(direct = [executable] + additional_test_outputs), runfiles = ctx.runfiles( collect_data = True, collect_default = True, files = ctx.files.data + additional_test_outputs, transitive_files = ctx.attr._apple_coverage_support.files, ), ), coverage_common.instrumented_files_info( ctx, dependency_attributes = ["deps"], extensions = ["swift"], source_attributes = ["srcs"], ), testing.ExecutionInfo(swift_toolchain.execution_requirements), testing.TestEnvironment(test_environment), ] swift_binary = rule( attrs = _binary_rule_attrs(stamp_default = True), doc = """ Compiles and links Swift code into an executable binary. On Linux, this rule produces an executable binary for the desired target architecture. On Apple platforms, this rule produces a _single-architecture_ binary; it does not produce fat binaries. As such, this rule is mainly useful for creating Swift tools intended to run on the local build machine. However, for historical reasons, the default Apple platform in Bazel is **iOS** instead of macOS. Therefore, if you wish to build a simple single-architecture Swift binary that can run on macOS, you must specify the correct CPU and platform on the command line as follows: ```shell $ bazel build //package:target ``` If you want to create a multi-architecture binary or a bundled application, please use one of the platform-specific application rules in [rules_apple](https://github.com/bazelbuild/rules_apple) instead of `swift_binary`. """, executable = True, fragments = ["cpp"], implementation = _swift_binary_impl, ) swift_test = rule( attrs = dicts.add( _binary_rule_attrs(stamp_default = False), { "_apple_coverage_support": attr.label( cfg = "host", default = Label("@build_bazel_apple_support//tools:coverage_support"), ), "_xctest_runner_template": attr.label( allow_single_file = True, default = Label( "@build_bazel_rules_swift//tools/xctest_runner:xctest_runner_template", ), ), }, ), doc = """ Compiles and links Swift code into an executable test target. The behavior of `swift_test` differs slightly for macOS targets, in order to provide seamless integration with Apple's XCTest framework. The output of the rule is still a binary, but one whose Mach-O type is `MH_BUNDLE` (a loadable bundle). Thus, the binary cannot be launched directly. Instead, running `bazel test` on the target will launch a test runner script that copies it into an `.xctest` bundle directory and then launches the `xctest` helper tool from Xcode, which uses Objective-C runtime reflection to locate the tests. On Linux, the output of a `swift_test` is a standard executable binary, because the implementation of XCTest on that platform currently requires authors to explicitly list the tests that are present and run them from their main program. Test bundling on macOS can be disabled on a per-target basis, if desired. You may wish to do this if you are not using XCTest, but rather a different test framework (or no framework at all) where the pass/fail outcome is represented as a zero/non-zero exit code (as is the case with other Bazel test rules like `cc_test`). To do so, disable the `"swift.bundled_xctests"` feature on the target: ```python swift_test( name = "MyTests", srcs = [...], features = ["-swift.bundled_xctests"], ) ``` You can also disable this feature for all the tests in a package by applying it to your BUILD file's `package()` declaration instead of the individual targets. """, executable = True, fragments = ["cpp"], test = True, implementation = _swift_test_impl, ) 07070100000047000081A4000003E800000064000000015D9E346300000F77000000000000000000000000000000000000003B00000000bazel-rules-swift-0.13.0/swift/internal/swift_c_module.bzl# Copyright 2018 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. """Implementation of the `swift_c_module` rule.""" load(":api.bzl", "swift_common") load(":utils.bzl", "merge_runfiles") def _swift_c_module_impl(ctx): module_map = ctx.file.module_map deps = ctx.attr.deps cc_infos = [dep[CcInfo] for dep in deps] data_runfiles = [dep[DefaultInfo].data_runfiles for dep in deps] default_runfiles = [dep[DefaultInfo].default_runfiles for dep in deps] return [ cc_common.merge_cc_infos(cc_infos = cc_infos), # We must repropagate the dependencies' DefaultInfos, otherwise we # will lose runtime dependencies that the library expects to be # there during a test (or a regular `bazel run`). DefaultInfo( data_runfiles = merge_runfiles(data_runfiles), default_runfiles = merge_runfiles(default_runfiles), files = depset([module_map]), ), swift_common.create_swift_info(modulemaps = [module_map]), ] swift_c_module = rule( attrs = { "module_map": attr.label( allow_single_file = True, doc = """ The module map file that should be loaded to import the C library dependency into Swift. """, mandatory = True, ), "deps": attr.label_list( allow_empty = False, doc = """ A list of C targets (or anything propagating `CcInfo`) that are dependencies of this target and whose headers may be referenced by the module map. """, mandatory = True, providers = [[CcInfo]], ), }, doc = """ Wraps one or more C targets in a new module map that allows it to be imported into Swift to access its C interfaces. The `cc_library` rule in Bazel does not produce module maps that are compatible with Swift. In order to make interop between Swift and C possible, users have one of two options: 1. **Use an auto-generated module map.** In this case, the `swift_c_module` rule is not needed. If a `cc_library` is a direct dependency of a `swift_{binary,library,test}` target, a module map will be automatically generated for it and the module's name will be derived from the Bazel target label (in the same fashion that module names for Swift targets are derived). The module name can be overridden by setting the `swift_module` tag on the `cc_library`; e.g., `tags = ["swift_module=MyModule"]`. 2. **Use a custom module map.** For finer control over the headers that are exported by the module, use the `swift_c_module` rule to provide a custom module map that specifies the name of the module, its headers, and any other module information. The `cc_library` targets that contain the headers that you wish to expose to Swift should be listed in the `deps` of your `swift_c_module` (and by listing multiple targets, you can export multiple libraries under a single module if desired). Then, your `swift_{binary,library,test}` targets should depend on the `swift_c_module` target, not on the underlying `cc_library` target(s). NOTE: Swift at this time does not support interop directly with C++. Any headers referenced by a module map that is imported into Swift must have only C features visible, often by using preprocessor conditions like `#if __cplusplus` to hide any C++ declarations. """, implementation = _swift_c_module_impl, ) 07070100000048000081A4000003E800000064000000015D9E346300003B96000000000000000000000000000000000000003F00000000bazel-rules-swift-0.13.0/swift/internal/swift_grpc_library.bzl# Copyright 2019 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. """A rule that generates a Swift library from gRPC services defined in protobuf sources.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load(":api.bzl", "swift_common") load( ":compiling.bzl", "new_objc_provider", "output_groups_from_compilation_outputs", ) load(":features.bzl", "SWIFT_FEATURE_ENABLE_TESTING", "SWIFT_FEATURE_NO_GENERATED_HEADER") load(":linking.bzl", "register_libraries_to_link") load( ":proto_gen_utils.bzl", "declare_generated_files", "extract_generated_dir_path", "register_module_mapping_write_action", ) load(":providers.bzl", "SwiftInfo", "SwiftProtoInfo", "SwiftToolchainInfo") load( ":utils.bzl", "compact", "create_cc_info", "get_providers", "proto_import_path", ) def _register_grpcswift_generate_action( label, actions, direct_srcs, proto_source_root, transitive_descriptor_sets, module_mapping_file, mkdir_and_run, protoc_executable, protoc_plugin_executable, flavor, extra_module_imports): """Registers the actions that generate `.grpc.swift` files from `.proto` files. Args: label: The label of the target being analyzed. actions: The context's actions object. direct_srcs: The direct `.proto` sources belonging to the target being analyzed, which will be passed to `protoc`. proto_source_root: the source root for `direct_srcs`. transitive_descriptor_sets: The transitive `DescriptorSet`s from the `proto_library` being analyzed. module_mapping_file: The `File` containing the mapping between `.proto` files and Swift modules for the transitive dependencies of the target being analyzed. May be `None`, in which case no module mapping will be passed (the case for leaf nodes in the dependency graph). mkdir_and_run: The `File` representing the `mkdir_and_run` executable. protoc_executable: The `File` representing the `protoc` executable. protoc_plugin_executable: The `File` representing the `protoc` plugin executable. flavor: The library flavor to generate. extra_module_imports: Additional modules to import. Returns: A list of generated `.grpc.swift` files corresponding to the `.proto` sources. """ generated_files = declare_generated_files( label.name, actions, "grpc", proto_source_root, direct_srcs, ) generated_dir_path = extract_generated_dir_path( label.name, "grpc", proto_source_root, generated_files, ) mkdir_args = actions.args() mkdir_args.add(generated_dir_path) protoc_executable_args = actions.args() protoc_executable_args.add(protoc_executable) protoc_args = actions.args() # protoc takes an arg of @NAME as something to read, and expects one # arg per line in that file. protoc_args.set_param_file_format("multiline") protoc_args.use_param_file("@%s") protoc_args.add( protoc_plugin_executable, format = "--plugin=protoc-gen-swiftgrpc=%s", ) protoc_args.add(generated_dir_path, format = "--swiftgrpc_out=%s") protoc_args.add("--swiftgrpc_opt=Visibility=Public") if flavor == "client": protoc_args.add("--swiftgrpc_opt=Client=true") protoc_args.add("--swiftgrpc_opt=Server=false") elif flavor == "client_stubs": protoc_args.add("--swiftgrpc_opt=Client=true") protoc_args.add("--swiftgrpc_opt=Server=false") protoc_args.add("--swiftgrpc_opt=TestStubs=true") protoc_args.add("--swiftgrpc_opt=Implementations=false") elif flavor == "server": protoc_args.add("--swiftgrpc_opt=Client=false") protoc_args.add("--swiftgrpc_opt=Server=true") else: fail("Unsupported swift_grpc_library flavor", attr = "flavor") protoc_args.add_all( extra_module_imports, format_each = "--swiftgrpc_opt=ExtraModuleImports=%s", ) if module_mapping_file: protoc_args.add( module_mapping_file, format = "--swiftgrpc_opt=ProtoPathModuleMappings=%s", ) protoc_args.add("--descriptor_set_in") protoc_args.add_joined(transitive_descriptor_sets, join_with = ":") protoc_args.add_all([proto_import_path(f, proto_source_root) for f in direct_srcs]) additional_command_inputs = [] if module_mapping_file: additional_command_inputs.append(module_mapping_file) # TODO(b/23975430): This should be a simple `actions.run_shell`, but until the # cited bug is fixed, we have to use the wrapper script. actions.run( arguments = [mkdir_args, protoc_executable_args, protoc_args], executable = mkdir_and_run, inputs = depset( direct = additional_command_inputs, transitive = [transitive_descriptor_sets], ), tools = [ mkdir_and_run, protoc_executable, protoc_plugin_executable, ], mnemonic = "ProtocGenSwiftGRPC", outputs = generated_files, progress_message = "Generating Swift sources for {}".format(label), ) return generated_files def _swift_grpc_library_impl(ctx): if len(ctx.attr.deps) != 1: fail("You must list exactly one target in the deps attribute.", attr = "deps") if len(ctx.attr.srcs) != 1: fail("You must list exactly one target in the srcs attribute.", attr = "srcs") swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] # Direct sources are passed as arguments to protoc to generate *only* the # files in this target, but we need to pass the transitive sources as inputs # to the generating action so that all the dependent files are available for # protoc to parse. # Instead of providing all those files and opening/reading them, we use # protoc's support for reading descriptor sets to resolve things. direct_srcs = ctx.attr.srcs[0][ProtoInfo].direct_sources transitive_descriptor_sets = ctx.attr.srcs[0][ProtoInfo].transitive_descriptor_sets deps = ctx.attr.deps minimal_module_mappings = deps[0][SwiftProtoInfo].module_mappings transitive_module_mapping_file = register_module_mapping_write_action( ctx.label.name, ctx.actions, minimal_module_mappings, ) extra_module_imports = [] if ctx.attr.flavor == "client_stubs": extra_module_imports += [swift_common.derive_module_name(deps[0].label)] # Generate the Swift sources from the .proto files. generated_files = _register_grpcswift_generate_action( ctx.label, ctx.actions, direct_srcs, ctx.attr.srcs[0][ProtoInfo].proto_source_root, transitive_descriptor_sets, transitive_module_mapping_file, ctx.executable._mkdir_and_run, ctx.executable._protoc, ctx.executable._protoc_gen_swiftgrpc, ctx.attr.flavor, extra_module_imports, ) # Compile the generated Swift sources and produce a static library and a # .swiftmodule as outputs. In addition to the other proto deps, we also pass # support libraries like the SwiftProtobuf runtime as deps to the compile # action. compile_deps = deps + ctx.attr._proto_support unsupported_features = ctx.disabled_features if ctx.attr.flavor != "client_stubs": unsupported_features.append(SWIFT_FEATURE_ENABLE_TESTING) feature_configuration = swift_common.configure_features( ctx = ctx, requested_features = ctx.features + [SWIFT_FEATURE_NO_GENERATED_HEADER], swift_toolchain = swift_toolchain, unsupported_features = unsupported_features, ) module_name = swift_common.derive_module_name(ctx.label) compilation_outputs = swift_common.compile( actions = ctx.actions, bin_dir = ctx.bin_dir, copts = ["-parse-as-library"], deps = compile_deps, feature_configuration = feature_configuration, genfiles_dir = ctx.genfiles_dir, module_name = module_name, srcs = generated_files, swift_toolchain = swift_toolchain, target_name = ctx.label.name, ) library_to_link = register_libraries_to_link( actions = ctx.actions, alwayslink = False, cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ), is_dynamic = False, is_static = True, library_name = ctx.label.name, objects = compilation_outputs.object_files, swift_toolchain = swift_toolchain, ) providers = [ DefaultInfo( files = depset(direct = generated_files + compact([ compilation_outputs.swiftdoc, compilation_outputs.swiftmodule, library_to_link.pic_static_library, ])), ), OutputGroupInfo(**output_groups_from_compilation_outputs( compilation_outputs = compilation_outputs, )), create_cc_info( cc_infos = get_providers(compile_deps, CcInfo), compilation_outputs = compilation_outputs, libraries_to_link = [library_to_link], ), deps[0][SwiftProtoInfo], swift_common.create_swift_info( module_name = module_name, swiftdocs = [compilation_outputs.swiftdoc], swiftmodules = [compilation_outputs.swiftmodule], swift_infos = get_providers(compile_deps, SwiftInfo), ), ] # Propagate an `objc` provider if the toolchain supports Objective-C interop, which ensures # that the libraries get linked into `apple_binary` targets properly. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( deps = compile_deps, include_path = ctx.bin_dir.path, link_inputs = compilation_outputs.linker_inputs, linkopts = compilation_outputs.linker_flags, module_map = compilation_outputs.generated_module_map, static_archives = compact([library_to_link.pic_static_library]), swiftmodules = [compilation_outputs.swiftmodule], objc_header = compilation_outputs.generated_header, )) return providers swift_grpc_library = rule( attrs = dicts.add( swift_common.toolchain_attrs(), { "srcs": attr.label_list( doc = """ Exactly one `proto_library` target that defines the services being generated. """, providers = [ProtoInfo], ), "deps": attr.label_list( doc = """ Exactly one `swift_proto_library` or `swift_grpc_library` target that contains the Swift protos used by the services being generated. Test stubs should depend on the `swift_grpc_library` implementing the service. """, providers = [[SwiftInfo, SwiftProtoInfo]], ), "flavor": attr.string( values = [ "client", "client_stubs", "server", ], mandatory = True, doc = """ The kind of definitions that should be generated: * `"client"` to generate client definitions. * `"client_stubs"` to generate client test stubs. * `"server"` to generate server definitions. """, ), "_mkdir_and_run": attr.label( cfg = "host", default = Label("@build_bazel_rules_swift//tools/mkdir_and_run"), executable = True, ), # TODO(b/63389580): Migrate to proto_lang_toolchain. "_proto_support": attr.label_list( default = [Label("@com_github_grpc_grpc_swift//:SwiftGRPC")], ), "_protoc": attr.label( cfg = "host", default = Label("@com_google_protobuf//:protoc"), executable = True, ), "_protoc_gen_swiftgrpc": attr.label( cfg = "host", default = Label("@com_github_grpc_grpc_swift//:protoc-gen-swiftgrpc"), executable = True, ), }, ), doc = """ Generates a Swift library from the gRPC services defined in protocol buffer sources. There should be one `swift_grpc_library` for any `proto_library` that defines services. A target based on this rule can be used as a dependency anywhere that a `swift_library` can be used. We recommend that `swift_grpc_library` targets be located in the same package as the `proto_library` and `swift_proto_library` targets they depend on. For more best practices around the use of Swift protocol buffer build rules, see the documentation for `swift_proto_library`. #### Defining Build Targets for Services Note that `swift_grpc_library` only generates the gRPC service interfaces (the `service` definitions) from the `.proto` files. Any messages defined in the same `.proto` file must be generated using a `swift_proto_library` target. Thus, the typical structure of a Swift gRPC library is similar to the following: ```python proto_library( name = "my_protos", srcs = ["my_protos.proto"], ) # Generate Swift types from the protos. swift_proto_library( name = "my_protos_swift", deps = [":my_protos"], ) # Generate Swift types from the services. swift_grpc_library( name = "my_protos_client_services_swift", # The `srcs` attribute points to the `proto_library` containing the service definitions... srcs = [":my_protos"], # ...the `flavor` attribute specifies what kind of definitions to generate... flavor = "client", # ...and the `deps` attribute points to the `swift_proto_library` that was generated from # the same `proto_library` and which contains the messages used by those services. deps = [":my_protos_swift"], ) # Generate test stubs from swift services. swift_grpc_library( name = "my_protos_client_stubs_swift", # The `srcs` attribute points to the `proto_library` containing the service definitions... srcs = [":my_protos"], # ...the `flavor` attribute specifies what kind of definitions to generate... flavor = "client_stubs", # ...and the `deps` attribute points to the `swift_grpc_library` that was generated from # the same `proto_library` and which contains the service implementation. deps = [":my_protos_client_services_swift"], ) ``` """, fragments = ["cpp"], implementation = _swift_grpc_library_impl, ) 07070100000049000081A4000003E800000064000000015D9E346300001277000000000000000000000000000000000000003900000000bazel-rules-swift-0.13.0/swift/internal/swift_import.bzl# Copyright 2018 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. """Implementation of the `swift_import` rule.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load(":api.bzl", "swift_common") load(":attrs.bzl", "swift_common_rule_attrs") load(":compiling.bzl", "new_objc_provider") load(":providers.bzl", "SwiftInfo") load(":utils.bzl", "create_cc_info", "get_providers") def _swift_import_impl(ctx): archives = ctx.files.archives deps = ctx.attr.deps swiftdocs = ctx.files.swiftdocs swiftmodules = ctx.files.swiftmodules # We have to depend on the C++ toolchain directly here to create the libraries to link. # Depending on the Swift toolchain causes a problematic cyclic dependency for built-from-source # toolchains. cc_toolchain = ctx.attr._cc_toolchain[cc_common.CcToolchainInfo] cc_feature_configuration = cc_common.configure_features( ctx = ctx, cc_toolchain = cc_toolchain, requested_features = ctx.features, unsupported_features = ctx.disabled_features, ) libraries_to_link = [ cc_common.create_library_to_link( actions = ctx.actions, cc_toolchain = cc_toolchain, feature_configuration = cc_feature_configuration, static_library = archive, ) for archive in archives ] providers = [ DefaultInfo( files = depset(direct = archives + swiftdocs + swiftmodules), runfiles = ctx.runfiles( collect_data = True, collect_default = True, files = ctx.files.data, ), ), create_cc_info( cc_infos = get_providers(deps, CcInfo), libraries_to_link = libraries_to_link, ), # Propagate an `Objc` provider so that Apple-specific rules like `apple_binary` will link # the imported library properly. Typically we'd want to only propagate this if the # toolchain reports that it supports Objective-C interop, but we would hit the same cyclic # dependency mentioned above, so we propagate it unconditionally; it will be ignored on # non-Apple platforms anyway. new_objc_provider( deps = deps, include_path = None, link_inputs = [], linkopts = [], module_map = None, objc_header = None, static_archives = archives, swiftmodules = swiftmodules, ), swift_common.create_swift_info( swiftdocs = swiftdocs, swiftmodules = swiftmodules, swift_infos = get_providers(deps, SwiftInfo), ), ] return providers swift_import = rule( attrs = dicts.add( swift_common_rule_attrs(), { "archives": attr.label_list( allow_empty = False, allow_files = ["a"], doc = """ The list of `.a` files provided to Swift targets that depend on this target. """, mandatory = True, ), "swiftdocs": attr.label_list( allow_empty = True, allow_files = ["swiftdoc"], doc = """ The list of `.swiftdoc` files provided to Swift targets that depend on this target. """, default = [], mandatory = False, ), "swiftmodules": attr.label_list( allow_empty = False, allow_files = ["swiftmodule"], doc = """ The list of `.swiftmodule` files provided to Swift targets that depend on this target. """, mandatory = True, ), "_cc_toolchain": attr.label( default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), doc = """ The C++ toolchain from which linking flags and other tools needed by the Swift toolchain (such as `clang`) will be retrieved. """, ), }, ), doc = """ Allows for the use of precompiled Swift modules as dependencies in other `swift_library` and `swift_binary` targets. """, fragments = ["cpp"], implementation = _swift_import_impl, ) 0707010000004A000081A4000003E800000064000000015D9E346300001CDA000000000000000000000000000000000000003A00000000bazel-rules-swift-0.13.0/swift/internal/swift_library.bzl# Copyright 2018 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. """Implementation of the `swift_library` rule.""" load(":api.bzl", "swift_common") load( ":compiling.bzl", "find_swift_version_copt_value", "new_objc_provider", "output_groups_from_compilation_outputs", "swift_library_output_map", ) load( ":features.bzl", "SWIFT_FEATURE_EMIT_SWIFTINTERFACE", "SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION", ) load(":linking.bzl", "register_libraries_to_link") load(":non_swift_target_aspect.bzl", "non_swift_target_aspect") load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo") load(":utils.bzl", "compact", "create_cc_info", "expand_locations", "get_providers") load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") def _maybe_parse_as_library_copts(srcs): """Returns a list of compiler flags depending on whether a `main.swift` file is present. Builds on Apple platforms typically don't use `swift_binary`; they use different linking logic (https://github.com/bazelbuild/rules_apple) to produce fat binaries and bundles. This means that all such application code will typically be in a `swift_library` target, and that includes a possible custom main entry point. For this reason, we need to support the creation of `swift_library` targets containing a `main.swift` file, which should *not* pass the `-parse-as-library` flag to the compiler. Args: srcs: A list of source files to check for the presence of `main.swift`. Returns: An empty list if `main.swift` was present in `srcs`, or a list containing a single element `"-parse-as-library"` if `main.swift` was not present. """ use_parse_as_library = True for src in srcs: if src.basename == "main.swift": use_parse_as_library = False break return ["-parse-as-library"] if use_parse_as_library else [] def _swift_library_impl(ctx): additional_inputs = ctx.files.swiftc_inputs # These can't use additional_inputs since expand_locations needs targets, not files. copts = expand_locations(ctx, ctx.attr.copts, ctx.attr.swiftc_inputs) linkopts = expand_locations(ctx, ctx.attr.linkopts, ctx.attr.swiftc_inputs) srcs = ctx.files.srcs extra_features = [] if ctx.attr._config_emit_swiftinterface[BuildSettingInfo].value: extra_features.append(SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION) extra_features.append(SWIFT_FEATURE_EMIT_SWIFTINTERFACE) module_name = ctx.attr.module_name if not module_name: module_name = swift_common.derive_module_name(ctx.label) swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] feature_configuration = swift_common.configure_features( ctx = ctx, requested_features = ctx.features + extra_features, swift_toolchain = swift_toolchain, unsupported_features = ctx.disabled_features, ) deps = ctx.attr.deps + swift_common.get_implicit_deps( feature_configuration = feature_configuration, swift_toolchain = swift_toolchain, ) compilation_outputs = swift_common.compile( actions = ctx.actions, additional_inputs = additional_inputs, bin_dir = ctx.bin_dir, copts = _maybe_parse_as_library_copts(srcs) + copts, defines = ctx.attr.defines, deps = deps, feature_configuration = feature_configuration, genfiles_dir = ctx.genfiles_dir, module_name = module_name, srcs = srcs, swift_toolchain = swift_toolchain, target_name = ctx.label.name, ) library_to_link = register_libraries_to_link( actions = ctx.actions, alwayslink = ctx.attr.alwayslink, cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ), is_dynamic = False, is_static = True, library_name = ctx.label.name, objects = compilation_outputs.object_files, swift_toolchain = swift_toolchain, ) direct_output_files = compact([ compilation_outputs.generated_header, compilation_outputs.swiftdoc, compilation_outputs.swiftmodule, library_to_link.pic_static_library, ]) providers = [ DefaultInfo( files = depset(direct_output_files), runfiles = ctx.runfiles( collect_data = True, collect_default = True, files = ctx.files.data, ), ), OutputGroupInfo(**output_groups_from_compilation_outputs( compilation_outputs = compilation_outputs, )), create_cc_info( additional_inputs = additional_inputs, cc_infos = get_providers(deps, CcInfo), compilation_outputs = compilation_outputs, libraries_to_link = [library_to_link], user_link_flags = linkopts, ), coverage_common.instrumented_files_info( ctx, dependency_attributes = ["deps"], extensions = ["swift"], source_attributes = ["srcs"], ), swift_common.create_swift_info( defines = ctx.attr.defines, generated_headers = compact([compilation_outputs.generated_header]), module_name = module_name, swiftdocs = [compilation_outputs.swiftdoc], swiftinterfaces = compact([compilation_outputs.swiftinterface]), swiftmodules = [compilation_outputs.swiftmodule], swift_infos = get_providers(deps, SwiftInfo), swift_version = find_swift_version_copt_value(copts), ), ] # Propagate an `objc` provider if the toolchain supports Objective-C interop, # which allows `objc_library` targets to import `swift_library` targets. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( defines = ctx.attr.defines, deps = deps, include_path = ctx.bin_dir.path, link_inputs = compilation_outputs.linker_inputs + additional_inputs, linkopts = compilation_outputs.linker_flags + linkopts, module_map = compilation_outputs.generated_module_map, static_archives = compact([library_to_link.pic_static_library]), swiftmodules = [compilation_outputs.swiftmodule], objc_header = compilation_outputs.generated_header, )) return providers swift_library = rule( attrs = swift_common.library_rule_attrs(additional_deps_aspects = [ non_swift_target_aspect, ]), doc = """ Compiles and links Swift code into a static library and Swift module. """, outputs = swift_library_output_map, implementation = _swift_library_impl, fragments = ["cpp"], ) 0707010000004B000081A4000003E800000064000000015D9E346300001915000000000000000000000000000000000000003F00000000bazel-rules-swift-0.13.0/swift/internal/swift_module_alias.bzl# Copyright 2018 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. """Implementation of the `swift_module_alias` rule.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load(":api.bzl", "swift_common") load( ":compiling.bzl", "new_objc_provider", "output_groups_from_compilation_outputs", ) load(":derived_files.bzl", "derived_files") load(":linking.bzl", "register_libraries_to_link") load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo") load(":utils.bzl", "compact", "create_cc_info", "get_providers") def _swift_module_alias_impl(ctx): deps = ctx.attr.deps module_mapping = { dep[SwiftInfo].module_name: dep.label for dep in deps if dep[SwiftInfo].module_name } module_name = ctx.attr.module_name if not module_name: module_name = swift_common.derive_module_name(ctx.label) # Generate a source file that imports each of the deps using `@_exported`. reexport_src = derived_files.reexport_modules_src(ctx.actions, ctx.label.name) ctx.actions.write( content = "\n".join([ "@_exported import {}".format(module) for module in module_mapping.keys() ]), output = reexport_src, ) swift_toolchain = ctx.attr._toolchain[SwiftToolchainInfo] feature_configuration = swift_common.configure_features( ctx = ctx, requested_features = ctx.features, swift_toolchain = swift_toolchain, unsupported_features = ctx.disabled_features, ) compilation_outputs = swift_common.compile( actions = ctx.actions, bin_dir = ctx.bin_dir, copts = ["-parse-as-library"], deps = deps, feature_configuration = feature_configuration, genfiles_dir = ctx.genfiles_dir, module_name = module_name, srcs = [reexport_src], swift_toolchain = swift_toolchain, target_name = ctx.label.name, ) library_to_link = register_libraries_to_link( actions = ctx.actions, alwayslink = False, cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ), is_dynamic = False, is_static = True, library_name = ctx.label.name, objects = compilation_outputs.object_files, swift_toolchain = swift_toolchain, ) providers = [ DefaultInfo( files = depset(compact([ compilation_outputs.swiftdoc, compilation_outputs.swiftmodule, library_to_link.dynamic_library, library_to_link.pic_static_library, ])), ), OutputGroupInfo(**output_groups_from_compilation_outputs( compilation_outputs = compilation_outputs, )), create_cc_info( cc_infos = get_providers(deps, CcInfo), compilation_outputs = compilation_outputs, libraries_to_link = [library_to_link], ), swift_common.create_swift_info( module_name = module_name, swiftdocs = [compilation_outputs.swiftdoc], swiftmodules = [compilation_outputs.swiftmodule], swift_infos = get_providers(deps, SwiftInfo), ), ] # Propagate an `objc` provider if the toolchain supports Objective-C interop, # which allows `objc_library` targets to import `swift_library` targets. if swift_toolchain.supports_objc_interop: providers.append(new_objc_provider( deps = deps, include_path = ctx.bin_dir.path, link_inputs = compilation_outputs.linker_inputs, linkopts = compilation_outputs.linker_flags, module_map = compilation_outputs.generated_module_map, static_archives = compact([library_to_link.pic_static_library]), swiftmodules = [compilation_outputs.swiftmodule], objc_header = compilation_outputs.generated_header, )) return providers swift_module_alias = rule( attrs = dicts.add( swift_common.toolchain_attrs(), { "module_name": attr.string( doc = """ The name of the Swift module being built. If left unspecified, the module name will be computed based on the target's build label, by stripping the leading `//` and replacing `/`, `:`, and other non-identifier characters with underscores. """, ), "deps": attr.label_list( doc = """ A list of targets that are dependencies of the target being built, which will be linked into that target. Allowed kinds are `swift_import` and `swift_library` (or anything else propagating `SwiftInfo`). """, providers = [[SwiftInfo]], ), }, ), doc = """ Creates a Swift module that re-exports other modules. This rule effectively creates an "alias" for one or more modules such that a client can import the alias module and it will implicitly import those dependencies. It should be used primarily as a way to migrate users when a module name is being changed. An alias that depends on more than one module can be used to split a large module into smaller, more targeted modules. Symbols in the original modules can be accessed through either the original module name or the alias module name, so callers can be migrated separately after moving the physical build target as needed. (An exception to this is runtime type metadata, which only encodes the module name of the type where the symbol is defined; it is not repeated by the alias module.) > Caution: This rule uses the undocumented `@_exported` feature to re-export the > `deps` in the new module. You depend on undocumented features at your own > risk, as they may change in a future version of Swift. """, fragments = ["cpp"], implementation = _swift_module_alias_impl, ) 0707010000004C000081A4000003E800000064000000015D9E3463000017CB000000000000000000000000000000000000004000000000bazel-rules-swift-0.13.0/swift/internal/swift_proto_library.bzl# Copyright 2018 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. """A rule that generates a Swift library from protocol buffer sources.""" load(":providers.bzl", "SwiftInfo", "SwiftProtoInfo") load(":swift_protoc_gen_aspect.bzl", "SwiftProtoCcInfo", "swift_protoc_gen_aspect") def _swift_proto_library_impl(ctx): if len(ctx.attr.deps) != 1: fail("You must list exactly one target in the deps attribute.", attr = "deps") dep = ctx.attr.deps[0] proto_cc_info = dep[SwiftProtoCcInfo] cc_info = proto_cc_info.cc_info swift_info = dep[SwiftInfo] swift_proto_info = dep[SwiftProtoInfo] providers = [ # Return the generated sources as the default outputs if the user builds this target # standalone (along with the direct .swiftmodules, to force compilation). This lets users # easily inspect those sources to determine the interfaces of the generated protos, which # have previously been a bit difficult to find. DefaultInfo( files = depset( swift_info.direct_swiftmodules, transitive = [swift_proto_info.pbswift_files], ), ), # Repropagate the Swift* and Cc* providers that the aspect attached to the `proto_library` # dependency so that the modules and link libraries are passed through correctly. cc_info, swift_info, # Repropagate the `SwiftProtoInfo` provider so that downstream rules/aspects can access the # sources if necessary. (This should typically only be used for IDE support.) swift_proto_info, ] # Propagate a nested apple_common.Objc provider if present so that apple_binary targets link # correctly. if proto_cc_info.objc_info: providers.append(proto_cc_info.objc_info) return providers swift_proto_library = rule( attrs = { "deps": attr.label_list( aspects = [swift_protoc_gen_aspect], doc = """ Exactly one `proto_library` target (or any target that propagates a `proto` provider) from which the Swift library should be generated. """, providers = [ProtoInfo], ), }, doc = """ Generates a Swift library from protocol buffer sources. There should be one `swift_proto_library` for any `proto_library` that you wish to depend on. A target based on this rule can be used as a dependency anywhere that a `swift_library` can be used. A `swift_proto_library` target only creates a Swift module if the `proto_library` on which it depends has a non-empty `srcs` attribute. If the `proto_library` does not contain `srcs`, then no module is produced, but the `swift_proto_library` still propagates the modules of its non-empty dependencies so that those generated protos can be used by depending on the `swift_proto_library` of the "collector" target. Note that the module name of the Swift library produced by this rule (if any) is based on the name of the `proto_library` target, *not* the name of the `swift_proto_library` target. In other words, if the following BUILD file were located in `//my/pkg`, the target would create a Swift module named `my_pkg_foo`: ```python proto_library( name = "foo", srcs = ["foo.proto"], ) swift_proto_library( name = "foo_swift", deps = [":foo"], ) ``` Because the Swift modules are generated from an aspect that is applied to the `proto_library` targets, the module name and other compilation flags for the resulting Swift modules cannot be changed. #### Tip: Where to locate `swift_proto_library` targets Convention is to put the `swift_proto_library` in the same `BUILD` file as the `proto_library` it is generating for (just like all the other `LANG_proto_library` rules). This lets anyone needing the protos in Swift share the single rule as well as making it easier to realize what proto files are in use in what contexts. This is not a requirement, however, as it may not be possible for Bazel workspaces that create `swift_proto_library` targets that depend on `proto_library` targets from different repositories. #### Tip: Avoid `import` only `.proto` files Avoid creating a `.proto` file that just contains `import` directives of all the other `.proto` files you need. While this does _group_ the protos into this new target, it comes with some high costs. This causes the proto compiler to parse all those files and invoke the generator for an otherwise empty source file. That empty source file then has to get compiled, but it will have dependencies on the full deps chain of the imports (recursively). The Swift compiler must load all of these module dependencies, which can be fairly slow if there are many of them, so this method of grouping via a `.proto` file actually ends up creating build steps that slow down the build. #### Tip: Resolving unused import warnings If you see warnings like the following during your build: ``` path/file.proto: warning: Import other/path/file.proto but not used. ``` The proto compiler is letting you know that you have an `import` statement loading a file from which nothing is used, so it is wasted work. The `import` can be removed (in this case, `import other/path/file.proto` could be removed from `path/file.proto`). These warnings can also mean that the `proto_library` has `deps` that aren't needed. Removing those along with the `import` statement(s) will speed up downstream Swift compilation actions, because it prevents unused modules from being loaded by `swiftc`. """, implementation = _swift_proto_library_impl, ) 0707010000004D000081A4000003E800000064000000015D9E34630000535B000000000000000000000000000000000000004400000000bazel-rules-swift-0.13.0/swift/internal/swift_protoc_gen_aspect.bzl# Copyright 2018 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. """An aspect attached to `proto_library` targets to generate Swift artifacts.""" load("@bazel_skylib//lib:dicts.bzl", "dicts") load(":api.bzl", "swift_common") load(":compiling.bzl", "output_groups_from_compilation_outputs") load(":features.bzl", "SWIFT_FEATURE_ENABLE_TESTING", "SWIFT_FEATURE_NO_GENERATED_HEADER") load(":linking.bzl", "register_libraries_to_link") load( ":proto_gen_utils.bzl", "declare_generated_files", "extract_generated_dir_path", "register_module_mapping_write_action", ) load(":providers.bzl", "SwiftInfo", "SwiftProtoInfo", "SwiftToolchainInfo") load( ":utils.bzl", "compact", "create_cc_info", "get_providers", "proto_import_path", ) # The paths of proto files bundled with the runtime. This is mainly the well # known type protos, but also includes descriptor.proto to make generation of # files that include options easier. These files should not be generated by # the aspect because they are already included in the SwiftProtobuf runtime. # The plugin provides the mapping from these protos to the SwiftProtobuf # module for us. # TODO(b/63389580): Once we migrate to proto_lang_toolchain, this information # can go in the blacklisted_protos list instead. _RUNTIME_BUNDLED_PROTO_FILES = [ "google/protobuf/any.proto", "google/protobuf/api.proto", "google/protobuf/descriptor.proto", "google/protobuf/duration.proto", "google/protobuf/empty.proto", "google/protobuf/field_mask.proto", "google/protobuf/source_context.proto", "google/protobuf/struct.proto", "google/protobuf/timestamp.proto", "google/protobuf/type.proto", "google/protobuf/wrappers.proto", ] SwiftProtoCcInfo = provider( doc = """ Wraps a `CcInfo` provider added to a `proto_library` through the Swift proto aspect. This is necessary because `proto_library` targets already propagate a `CcInfo` provider for C++ protos, so the Swift proto aspect cannot directly attach its own. (It's also not good practice to attach providers that you don't own to arbitrary targets, because you don't know how those targets might change in the future.) The `swift_proto_library` rule will pick up this provider and return the underlying `CcInfo` provider as its own. This provider is an implementation detail not meant to be used by clients. """, fields = { "cc_info": "The underlying `CcInfo` provider.", "objc_info": "The underlying `apple_common.Objc` provider.", }, ) def _filter_out_well_known_types(srcs, proto_source_root): """Returns the given list of files, excluding any well-known type protos. Args: srcs: A list of `.proto` files. proto_source_root: the source root where the `.proto` files are. Returns: The given list of files with any well-known type protos (those living under the `google.protobuf` package) removed. """ return [ f for f in srcs if proto_import_path(f, proto_source_root) not in _RUNTIME_BUNDLED_PROTO_FILES ] def _register_pbswift_generate_action( label, actions, direct_srcs, proto_source_root, transitive_descriptor_sets, module_mapping_file, mkdir_and_run, protoc_executable, protoc_plugin_executable): """Registers the actions that generate `.pb.swift` files from `.proto` files. Args: label: The label of the target being analyzed. actions: The context's actions object. direct_srcs: The direct `.proto` sources belonging to the target being analyzed, which will be passed to `protoc-gen-swift`. proto_source_root: the source root where the `.proto` files are. transitive_descriptor_sets: The transitive `DescriptorSet`s from the `proto_library` being analyzed. module_mapping_file: The `File` containing the mapping between `.proto` files and Swift modules for the transitive dependencies of the target being analyzed. May be `None`, in which case no module mapping will be passed (the case for leaf nodes in the dependency graph). mkdir_and_run: The `File` representing the `mkdir_and_run` executable. protoc_executable: The `File` representing the `protoc` executable. protoc_plugin_executable: The `File` representing the `protoc` plugin executable. Returns: A list of generated `.pb.swift` files corresponding to the `.proto` sources. """ generated_files = declare_generated_files( label.name, actions, "pb", proto_source_root, direct_srcs, ) generated_dir_path = extract_generated_dir_path( label.name, "pb", proto_source_root, generated_files, ) mkdir_args = actions.args() mkdir_args.add(generated_dir_path) protoc_executable_args = actions.args() protoc_executable_args.add(protoc_executable) protoc_args = actions.args() # protoc takes an arg of @NAME as something to read, and expects one # arg per line in that file. protoc_args.set_param_file_format("multiline") protoc_args.use_param_file("@%s") protoc_args.add( protoc_plugin_executable, format = "--plugin=protoc-gen-swift=%s", ) protoc_args.add(generated_dir_path, format = "--swift_out=%s") protoc_args.add("--swift_opt=FileNaming=FullPath") protoc_args.add("--swift_opt=Visibility=Public") if module_mapping_file: protoc_args.add( module_mapping_file, format = "--swift_opt=ProtoPathModuleMappings=%s", ) protoc_args.add("--descriptor_set_in") protoc_args.add_joined(transitive_descriptor_sets, join_with = ":") protoc_args.add_all( [proto_import_path(f, proto_source_root) for f in direct_srcs], ) additional_command_inputs = [] if module_mapping_file: additional_command_inputs.append(module_mapping_file) # TODO(b/23975430): This should be a simple `actions.run_shell`, but until the # cited bug is fixed, we have to use the wrapper script. actions.run( arguments = [mkdir_args, protoc_executable_args, protoc_args], executable = mkdir_and_run, inputs = depset( direct = additional_command_inputs, transitive = [transitive_descriptor_sets], ), mnemonic = "ProtocGenSwift", outputs = generated_files, progress_message = "Generating Swift sources for {}".format(label), tools = [ mkdir_and_run, protoc_executable, protoc_plugin_executable, ], ) return generated_files def _build_swift_proto_info_provider( pbswift_files, transitive_module_mappings, deps): """Builds the `SwiftProtoInfo` provider to propagate for a proto library. Args: pbswift_files: The `.pb.swift` files that were generated for the propagating target. This sequence should only contain the direct sources. transitive_module_mappings: A sequence of `structs` with `module_name` and `proto_file_paths` fields that denote the transitive mappings from `.proto` files to Swift modules. deps: The direct dependencies of the propagating target, from which the transitive sources will be computed. Returns: An instance of `SwiftProtoInfo`. """ return SwiftProtoInfo( module_mappings = transitive_module_mappings, pbswift_files = depset( direct = pbswift_files, transitive = [dep[SwiftProtoInfo].pbswift_files for dep in deps], ), ) def _build_module_mapping_from_srcs(target, proto_srcs, proto_source_root): """Returns the sequence of module mapping `struct`s for the given sources. Args: target: The `proto_library` target whose module mapping is being rendered. proto_srcs: The `.proto` files that belong to the target. proto_source_root: The source root for `proto_srcs`. Returns: A string containing the module mapping for the target in protobuf text format. """ # TODO(allevato): The previous use of f.short_path here caused problems with # cross-repo references; protoc-gen-swift only processes the file correctly if # the workspace-relative path is used (which is the same as the short_path for # same-repo references, so this issue had never been caught). However, this # implies that if two repos have protos with the same workspace-relative # paths, there will be a clash. Figure out what to do here; it may require an # update to protoc-gen-swift? return struct( module_name = swift_common.derive_module_name(target.label), proto_file_paths = [proto_import_path(f, proto_source_root) for f in proto_srcs], ) def _gather_transitive_module_mappings(targets): """Returns the set of transitive module mappings for the given targets. This function eliminates duplicates among the targets so that if two or more targets transitively depend on the same `proto_library`, the mapping is only present in the sequence once. Args: targets: The targets whose module mappings should be returned. Returns: A sequence containing the transitive module mappings for the given targets, without duplicates. """ unique_mappings = {} for target in targets: mappings = target[SwiftProtoInfo].module_mappings for mapping in mappings: module_name = mapping.module_name if module_name not in unique_mappings: unique_mappings[module_name] = mapping.proto_file_paths return [struct( module_name = module_name, proto_file_paths = file_paths, ) for module_name, file_paths in unique_mappings.items()] def _swift_protoc_gen_aspect_impl(target, aspect_ctx): swift_toolchain = aspect_ctx.attr._toolchain[SwiftToolchainInfo] direct_srcs = _filter_out_well_known_types( target[ProtoInfo].direct_sources, target[ProtoInfo].proto_source_root, ) # Direct sources are passed as arguments to protoc to generate *only* the # files in this target, but we need to pass the transitive sources as inputs # to the generating action so that all the dependent files are available for # protoc to parse. # Instead of providing all those files and opening/reading them, we use # protoc's support for reading descriptor sets to resolve things. transitive_descriptor_sets = target[ProtoInfo].transitive_descriptor_sets proto_deps = [dep for dep in aspect_ctx.rule.attr.deps if SwiftProtoInfo in dep] minimal_module_mappings = [] if direct_srcs: minimal_module_mappings.append( _build_module_mapping_from_srcs( target, direct_srcs, target[ProtoInfo].proto_source_root, ), ) if proto_deps: minimal_module_mappings.extend(_gather_transitive_module_mappings(proto_deps)) transitive_module_mapping_file = register_module_mapping_write_action( target.label.name, aspect_ctx.actions, minimal_module_mappings, ) support_deps = aspect_ctx.attr._proto_support if direct_srcs: # Generate the Swift sources from the .proto files. pbswift_files = _register_pbswift_generate_action( target.label, aspect_ctx.actions, direct_srcs, target[ProtoInfo].proto_source_root, transitive_descriptor_sets, transitive_module_mapping_file, aspect_ctx.executable._mkdir_and_run, aspect_ctx.executable._protoc, aspect_ctx.executable._protoc_gen_swift, ) # Compile the generated Swift sources and produce a static library and a # .swiftmodule as outputs. In addition to the other proto deps, we also pass # support libraries like the SwiftProtobuf runtime as deps to the compile # action. feature_configuration = swift_common.configure_features( ctx = aspect_ctx, requested_features = aspect_ctx.features + [SWIFT_FEATURE_NO_GENERATED_HEADER], swift_toolchain = swift_toolchain, unsupported_features = aspect_ctx.disabled_features + [SWIFT_FEATURE_ENABLE_TESTING], ) module_name = swift_common.derive_module_name(target.label) compilation_outputs = swift_common.compile( actions = aspect_ctx.actions, bin_dir = aspect_ctx.bin_dir, copts = ["-parse-as-library"], deps = proto_deps + support_deps, feature_configuration = feature_configuration, genfiles_dir = aspect_ctx.genfiles_dir, module_name = module_name, srcs = pbswift_files, swift_toolchain = swift_toolchain, target_name = target.label.name, ) library_to_link = register_libraries_to_link( actions = aspect_ctx.actions, alwayslink = False, cc_feature_configuration = swift_common.cc_feature_configuration( feature_configuration = feature_configuration, ), is_dynamic = False, is_static = True, # Prevent conflicts with C++ protos in the same output directory, which # use the `lib{name}.a` pattern. This will produce `lib{name}.swift.a` # instead. library_name = "{}.swift".format(target.label.name), objects = compilation_outputs.object_files, swift_toolchain = swift_toolchain, ) # It's bad practice to attach providers you don't own to other targets, because you can't # control how those targets might change in the future (e.g., it could introduce a # collision). This means we can't propagate a `CcInfo` from this aspect nor do we want to # merge the `CcInfo` providers from the target's deps. Instead, the aspect returns a # `SwiftProtoCcInfo` provider that wraps the `CcInfo` containing the Swift linking info. # Then, for any subgraph of `proto_library` targets, we can merge the extracted `CcInfo` # providers with the regular `CcInfo` providers of the support libraries (which are regular # `swift_library` targets), and wrap that *back* into a `SwiftProtoCcInfo`. Finally, the # `swift_proto_library` rule will extract the `CcInfo` from the `SwiftProtoCcInfo` of its # single dependency and propagate that safely up the tree. cc_infos = ( get_providers(proto_deps, SwiftProtoCcInfo, _extract_cc_info) + get_providers(support_deps, CcInfo) ) # Propagate an `objc` provider if the toolchain supports Objective-C interop, which ensures # that the libraries get linked into `apple_binary` targets properly. if swift_toolchain.supports_objc_interop: objc_infos = get_providers( proto_deps, SwiftProtoCcInfo, _extract_objc_info, ) + get_providers(support_deps, apple_common.Objc) objc_info_args = {} if compilation_outputs.generated_header: objc_info_args["header"] = depset([compilation_outputs.generated_header]) if library_to_link.pic_static_library: objc_info_args["library"] = depset( [library_to_link.pic_static_library], order = "topological", ) if compilation_outputs.linker_flags: objc_info_args["linkopt"] = depset(compilation_outputs.linker_flags) if compilation_outputs.generated_module_map: objc_info_args["module_map"] = depset([compilation_outputs.generated_module_map]) linker_inputs = ( compilation_outputs.linker_inputs + compact([compilation_outputs.swiftmodule]) ) if linker_inputs: objc_info_args["link_inputs"] = depset(linker_inputs) objc_info = apple_common.new_objc_provider( include = depset([aspect_ctx.bin_dir.path]), providers = objc_infos, uses_swift = True, **objc_info_args ) else: objc_info = None providers = [ OutputGroupInfo(**output_groups_from_compilation_outputs( compilation_outputs = compilation_outputs, )), SwiftProtoCcInfo( cc_info = create_cc_info( cc_infos = cc_infos, compilation_outputs = compilation_outputs, libraries_to_link = [library_to_link], ), objc_info = objc_info, ), swift_common.create_swift_info( module_name = module_name, swiftdocs = [compilation_outputs.swiftdoc], swiftmodules = [compilation_outputs.swiftmodule], swift_infos = get_providers(proto_deps + support_deps, SwiftInfo), ), ] else: # If there are no srcs, merge the `SwiftInfo` and `CcInfo` providers and propagate them. Do # likewise for `apple_common.Objc` providers if the toolchain supports Objective-C interop. # Note that we don't need to handle the runtime support libraries here; we can assume that # they've already been pulled in by a `proto_library` that had srcs. pbswift_files = [] if swift_toolchain.supports_objc_interop: objc_providers = get_providers(proto_deps, SwiftProtoCcInfo, _extract_objc_info) objc_provider = apple_common.new_objc_provider(providers = objc_providers) objc_info = objc_provider else: objc_info = None providers = [ SwiftProtoCcInfo( cc_info = cc_common.merge_cc_infos( cc_infos = get_providers(proto_deps, SwiftProtoCcInfo, _extract_cc_info), ), objc_info = objc_info, ), swift_common.create_swift_info( swift_infos = get_providers(proto_deps, SwiftInfo), ), ] providers.append(_build_swift_proto_info_provider( pbswift_files, minimal_module_mappings, proto_deps, )) return providers def _extract_cc_info(proto_cc_info): """A map function for `get_providers` to extract the `CcInfo` from a `SwiftProtoCcInfo`. Args: proto_cc_info: A `SwiftProtoCcInfo` provider. Returns: The `CcInfo` nested inside the `SwiftProtoCcInfo`. """ return proto_cc_info.cc_info def _extract_objc_info(proto_cc_info): """A map function for `get_providers` to extract the `Objc` provider from a `SwiftProtoCcInfo`. Args: proto_cc_info: A `SwiftProtoCcInfo` provider. Returns: The `ObjcInfo` nested inside the `SwiftProtoCcInfo`. """ return proto_cc_info.objc_info swift_protoc_gen_aspect = aspect( attr_aspects = ["deps"], attrs = dicts.add( swift_common.toolchain_attrs(), { "_mkdir_and_run": attr.label( cfg = "host", default = Label( "@build_bazel_rules_swift//tools/mkdir_and_run", ), executable = True, ), # TODO(b/63389580): Migrate to proto_lang_toolchain. "_proto_support": attr.label_list( default = [ Label("@com_github_apple_swift_protobuf//:SwiftProtobuf"), ], ), "_protoc": attr.label( cfg = "host", default = Label("@com_google_protobuf//:protoc"), executable = True, ), "_protoc_gen_swift": attr.label( cfg = "host", default = Label("@com_github_apple_swift_protobuf//:ProtoCompilerPlugin"), executable = True, ), }, ), doc = """ Generates Swift artifacts for a `proto_library` target. For each `proto_library` (more specifically, any target that propagates a `proto` provider) to which this aspect is applied, the aspect will register actions that generate Swift artifacts and propagate them in a `SwiftProtoInfo` provider. Most users should not need to use this aspect directly; it is an implementation detail of the `swift_proto_library` rule. """, fragments = ["cpp"], implementation = _swift_protoc_gen_aspect_impl, ) 0707010000004E000081A4000003E800000064000000015D9E34630000199C000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/swift/internal/swift_toolchain.bzl# Copyright 2018 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. """BUILD rules used to provide a Swift toolchain on Linux. The rules defined in this file are not intended to be used outside of the Swift toolchain package. If you are looking for rules to build Swift code using this toolchain, see `swift.bzl`. """ load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:partial.bzl", "partial") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load( ":features.bzl", "SWIFT_FEATURE_AUTOLINK_EXTRACT", "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD", "features_for_build_modes", ) load(":providers.bzl", "SwiftToolchainInfo") def _default_linker_opts( cc_toolchain, cpu, os, toolchain_root, is_static, is_test): """Returns options that should be passed by default to `clang` when linking. This function is wrapped in a `partial` that will be propagated as part of the toolchain provider. The first three arguments are pre-bound; the `is_static` and `is_test` arguments are expected to be passed by the caller. Args: cc_toolchain: The cpp toolchain from which the `ld` executable is determined. cpu: The CPU architecture, which is used as part of the library path. os: The operating system name, which is used as part of the library path. toolchain_root: The toolchain's root directory. is_static: `True` to link against the static version of the Swift runtime, or `False` to link against dynamic/shared libraries. is_test: `True` if the target being linked is a test target. Returns: The command line options to pass to `clang` to link against the desired variant of the Swift runtime libraries. """ _ignore = is_test # TODO(#8): Support statically linking the Swift runtime. platform_lib_dir = "{toolchain_root}/lib/swift/{os}".format( os = os, toolchain_root = toolchain_root, ) runtime_object_path = "{platform_lib_dir}/{cpu}/swiftrt.o".format( cpu = cpu, platform_lib_dir = platform_lib_dir, ) linkopts = [ "-pie", "-L{}".format(platform_lib_dir), "-Wl,-rpath,{}".format(platform_lib_dir), "-lm", "-lstdc++", "-lrt", "-ldl", runtime_object_path, ] if is_static: linkopts.append("-static-libgcc") return linkopts def _swift_toolchain_impl(ctx): toolchain_root = ctx.attr.root cc_toolchain = find_cpp_toolchain(ctx) linker_opts_producer = partial.make( _default_linker_opts, cc_toolchain, ctx.attr.arch, ctx.attr.os, toolchain_root, ) # Combine build mode features, autoconfigured features, and required features. requested_features = features_for_build_modes(ctx) requested_features.extend(ctx.features) requested_features.append(SWIFT_FEATURE_AUTOLINK_EXTRACT) # TODO(allevato): Move some of the remaining hardcoded values, like object format and Obj-C # interop support, to attributes so that we can remove the assumptions that are only valid on # Linux. return [ SwiftToolchainInfo( action_environment = {}, # Swift.org toolchains assume everything is just available on the # PATH and we don't try to pass the toolchain contents here. all_files = depset(), cc_toolchain_info = cc_toolchain, clang_executable = ctx.attr.clang_executable, command_line_copts = ctx.fragments.swift.copts(), cpu = ctx.attr.arch, execution_requirements = {}, linker_opts_producer = linker_opts_producer, object_format = "elf", optional_implicit_deps = [], requested_features = requested_features, required_implicit_deps = [], root_dir = toolchain_root, stamp_producer = None, supports_objc_interop = False, swiftc_copts = [], swift_worker = ctx.executable._worker, system_name = ctx.attr.os, unsupported_features = ctx.disabled_features + [ SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD, ], ), ] swift_toolchain = rule( attrs = dicts.add({ "arch": attr.string( doc = """ The name of the architecture that this toolchain targets. This name should match the name used in the toolchain's directory layout for architecture-specific content, such as "x86_64" in "lib/swift/linux/x86_64". """, mandatory = True, ), "clang_executable": attr.string( doc = """ The path to the `clang` executable, which is used for linking. """, mandatory = True, ), "os": attr.string( doc = """ The name of the operating system that this toolchain targets. This name should match the name used in the toolchain's directory layout for platform-specific content, such as "linux" in "lib/swift/linux". """, mandatory = True, ), "root": attr.string( mandatory = True, ), "_cc_toolchain": attr.label( default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), doc = """ The C++ toolchain from which other tools needed by the Swift toolchain (such as `clang` and `ar`) will be retrieved. """, ), "_worker": attr.label( cfg = "host", allow_files = True, default = Label("//tools/worker"), doc = """ An executable that wraps Swift compiler invocations and also provides support for incremental compilation using a persistent mode. """, executable = True, ), }), doc = "Represents a Swift compiler toolchain.", fragments = ["swift"], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], implementation = _swift_toolchain_impl, ) 0707010000004F000081A4000003E800000064000000015D9E346300000E90000000000000000000000000000000000000003F00000000bazel-rules-swift-0.13.0/swift/internal/swift_usage_aspect.bzl# Copyright 2018 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. """An aspect that collects information about Swift usage among dependencies.""" load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo", "SwiftUsageInfo") def _get_swift_toolchain(target, aspect_ctx): """Gets the `SwiftToolchainInfo` used to build the given target, if any. Args: target: The target being built. aspect_ctx: The aspect context. Returns: The `SwiftToolchainInfo` provider, or `None` if the target was not a Swift target. """ if SwiftInfo in target: toolchain_target = getattr(aspect_ctx.rule.attr, "_toolchain", None) if toolchain_target and SwiftToolchainInfo in toolchain_target: return toolchain_target[SwiftToolchainInfo] return None def _swift_usage_aspect_impl(target, aspect_ctx): # Targets can directly propagate their own `SwiftUsageInfo` provider. In # those case, this aspect must not propagate a `SwiftUsageInfo`, because # doing so results in a Bazel error. if SwiftUsageInfo in target: return [] # If the target itself propagates `SwiftInfo`, get the toolchain from it. found_toolchain = _get_swift_toolchain(target, aspect_ctx) if found_toolchain: return [SwiftUsageInfo(toolchain = found_toolchain)] # If one of the deps propagates `SwiftUsageInfo` provider, we can repropagate # that information. # TODO(allevato): We currently make the assumption that all Swift # dependencies are built with the same toolchain (as in Bazel toolchain, not # Swift toolchain). for dep in getattr(aspect_ctx.rule.attr, "deps", []): if SwiftUsageInfo in dep: return [dep[SwiftUsageInfo]] # Don't propagate the provider at all if the target nor its dependencies use # Swift. return [] swift_usage_aspect = aspect( attr_aspects = ["deps"], doc = """ Collects information about how Swift is used in a dependency tree. When attached to an attribute, this aspect will propagate a `SwiftUsageInfo` provider for any target found in that attribute that uses Swift, either directly or deeper in its dependency tree. Conversely, if neither a target nor its transitive dependencies use Swift, the `SwiftUsageInfo` provider will not be propagated. Specifically, the aspect propagates which toolchain was used to build those dependencies. This information is typically always the same for any Swift targets built in the same configuration, but this allows upstream targets that may not be *strictly* Swift-related and thus don't want to depend directly on the Swift toolchain (such as Apple universal binary linking rules) to avoid doing so but still get access to information derived from the toolchain (like which linker flags to pass to link to the runtime). We use an aspect (as opposed to propagating this information through normal providers returned by `swift_library`) because the information is needed if Swift is used _anywhere_ in a dependency graph, even as dependencies of other language rules that wouldn't know how to propagate the Swift-specific providers. """, implementation = _swift_usage_aspect_impl, ) 07070100000050000081A4000003E800000064000000015D9E346300002894000000000000000000000000000000000000003200000000bazel-rules-swift-0.13.0/swift/internal/utils.bzl# Copyright 2018 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. """Common utility definitions used by various BUILD rules.""" load("@bazel_skylib//lib:paths.bzl", "paths") def collect_cc_libraries( cc_info, include_dynamic = False, include_interface = False, include_pic_static = False, include_static = False): """Returns a list of link libraries referenced in the given `CcInfo` provider. Args: cc_info: The `CcInfo` provider whose libraries should be returned. include_dynamic: True if dynamic libraries should be included in the list. include_interface: True if interface libraries should be included in the list. include_pic_static: True if PIC static libraries should be included in the list. If there is no PIC library, the non-PIC library will be used instead. include_static: True if non-PIC static libraries should be included in the list. Returns: The list of libraries built or depended on by the given provier. """ libraries = [] # TODO(https://github.com/bazelbuild/bazel/issues/8118): Remove once flag is flipped libraries_to_link = cc_info.linking_context.libraries_to_link if hasattr(libraries_to_link, "to_list"): libraries_to_link = libraries_to_link.to_list() for library in libraries_to_link: if include_pic_static: if library.pic_static_library: libraries.append(library.pic_static_library) elif library.static_library: libraries.append(library.static_library) elif include_static and library.static_library: libraries.append(library.static_library) if include_dynamic and library.dynamic_library: libraries.append(library.dynamic_library) if include_interface and library.interface_library: libraries.append(library.interface_library) return libraries def compact(sequence): """Returns a copy of the sequence with any `None` items removed. Args: sequence: The sequence of items to compact. Returns: A copy of the sequence with any `None` items removed. """ return [item for item in sequence if item != None] def create_cc_info( additional_inputs = [], cc_infos = [], compilation_outputs = None, libraries_to_link = [], user_link_flags = []): """Creates a `CcInfo` provider from Swift compilation information and dependencies. Args: additional_inputs: A list of additional files that should be passed as inputs to the final link action. cc_infos: A list of `CcInfo` providers from dependencies that should be merged into the new provider. compilation_outputs: The compilation outputs from a Swift compile action, as returned by `swift_common.compile`, or None. libraries_to_link: A list of `LibraryToLink` objects that represent the libraries that should be linked into the final binary. user_link_flags: A list of flags that should be passed to the final link action. Returns: A new `CcInfo`. """ all_additional_inputs = list(additional_inputs) all_user_link_flags = list(user_link_flags) if compilation_outputs: all_additional_inputs.extend(compilation_outputs.linker_inputs) all_user_link_flags.extend(compilation_outputs.linker_flags) this_cc_info = CcInfo( linking_context = cc_common.create_linking_context( additional_inputs = all_additional_inputs, libraries_to_link = libraries_to_link, user_link_flags = all_user_link_flags, ), ) return cc_common.merge_cc_infos(cc_infos = [this_cc_info] + cc_infos) def expand_locations(ctx, values, targets = []): """Expands the `$(location)` placeholders in each of the given values. Args: ctx: The rule context. values: A list of strings, which may contain `$(location)` placeholders. targets: A list of additional targets (other than the calling rule's `deps`) that should be searched for substitutable labels. Returns: A list of strings with any `$(location)` placeholders filled in. """ return [ctx.expand_location(value, targets) for value in values] def get_output_groups(targets, group_name): """Returns a list containing the files of the given output group from each target in a list. The returned list may not be the same size as `targets` if some of the targets do not contain the requested output group. This is not an error. Args: targets: A list of targets. group_name: The name of the output group. Returns: A list of `depset`s of `File`s from the requested output group for each target. """ groups = [] for target in targets: group = getattr(target[OutputGroupInfo], group_name, None) if group: groups.append(group) return groups def get_providers(targets, provider, map_fn = None): """Returns a list containing the given provider (or a field) from each target in the list. The returned list may not be the same size as `targets` if some of the targets do not contain the requested provider. This is not an error. The main purpose of this function is to make this common operation more readable and prevent mistyping the list comprehension. Args: targets: A list of targets. provider: The provider to retrieve. map_fn: A function that takes a single argument and returns a single value. If this is present, it will be called on each provider in the list and the result will be returned in the list returned by `get_providers`. Returns: A list of the providers requested from the targets. """ if map_fn: return [map_fn(target[provider]) for target in targets if provider in target] return [target[provider] for target in targets if provider in target] def merge_runfiles(all_runfiles): """Merges a list of `runfiles` objects. Args: all_runfiles: A list containing zero or more `runfiles` objects to merge. Returns: A merged `runfiles` object, or `None` if the list was empty. """ result = None for runfiles in all_runfiles: if result == None: result = runfiles else: result = result.merge(runfiles) return result def objc_provider_framework_name(path): """Returns the name of the framework from an `objc` provider path. Args: path: A path that came from an `objc` provider. Returns: A string containing the name of the framework (e.g., `Foo` for `Foo.framework`). """ return path.rpartition("/")[2].partition(".")[0] def owner_relative_path(file): """Returns the part of the given file's path relative to its owning package. This function has extra logic to properly handle references to files in external repositoriies. Args: file: The file whose owner-relative path should be returned. Returns: The owner-relative path to the file. """ root = file.owner.workspace_root package = file.owner.package if file.is_source: # Even though the docs say a File's `short_path` doesn't include the root, # Bazel special cases anything from an external repository and includes a # relative path (`../`) to the file. On the File's `owner` we can get the # `workspace_root` to try and line things up, but it is in the form of # "external/[name]". However the File's `path` does include the root and # leaves it in the "external/" form, so we just relativize based on that # instead. return paths.relativize(file.path, paths.join(root, package)) elif root: # As above, but for generated files. The same mangling happens in # `short_path`, but since it is generated, the `path` includes the extra # output directories used by Bazel. So, we pick off the parent directory # segment that Bazel adds to the `short_path` and turn it into "external/" # so a relative path from the owner can be computed. short_path = file.short_path # Sanity check. if (not root.startswith("external/") or not short_path.startswith("../")): fail(("Generated file in a different workspace with unexpected " + "short_path ({short_path}) and owner.workspace_root " + "({root}).").format( root = root, short_path = short_path, )) return paths.relativize( paths.join("external", short_path[3:]), paths.join(root, package), ) else: return paths.relativize(file.short_path, package) def _workspace_relative_path(file): """Returns the path of a file relative to its workspace. Args: file: The `File` object. Returns: The path of the file relative to its workspace. """ workspace_path = paths.join(file.root.path, file.owner.workspace_root) return paths.relativize(file.path, workspace_path) def proto_import_path(f, proto_source_root): """ Returns the import path of a `.proto` file given its path. Args: f: The `File` object representing the `.proto` file. proto_source_root: The source root for the `.proto` file. Returns: The path the `.proto` file should be imported at. """ if f.path.startswith(proto_source_root): return f.path[len(proto_source_root) + 1:] else: # Happens before Bazel 1.0, where proto_source_root was not # guaranteed to be a parent of the .proto file return _workspace_relative_path(f) 07070100000051000081A4000003E800000064000000015D9E346300004425000000000000000000000000000000000000004200000000bazel-rules-swift-0.13.0/swift/internal/xcode_swift_toolchain.bzl# Copyright 2018 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. """BUILD rules used to provide a Swift toolchain provided by Xcode on macOS. The rules defined in this file are not intended to be used outside of the Swift toolchain package. If you are looking for rules to build Swift code using this toolchain, see `swift.bzl`. """ load("@bazel_skylib//lib:collections.bzl", "collections") load("@bazel_skylib//lib:dicts.bzl", "dicts") load("@bazel_skylib//lib:partial.bzl", "partial") load("@bazel_skylib//lib:paths.bzl", "paths") load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load( ":features.bzl", "SWIFT_FEATURE_AUTOLINK_EXTRACT", "SWIFT_FEATURE_BUNDLED_XCTESTS", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_ENABLE_BATCH_MODE", "SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD", "SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION", "SWIFT_FEATURE_USE_RESPONSE_FILES", "features_for_build_modes", ) load(":providers.bzl", "SwiftToolchainInfo") def _swift_developer_lib_dir(platform_framework_dir): """Returns the directory containing extra Swift developer libraries. Args: platform_framework_dir: The developer platform framework directory for the current platform. Returns: The directory containing extra Swift-specific development libraries and swiftmodules. """ return paths.join( paths.dirname(paths.dirname(platform_framework_dir)), "usr", "lib", ) def _command_line_objc_copts(objc_fragment): """Returns copts that should be passed to `clang` from the `objc` fragment. Args: objc_fragment: The `objc` configuration fragment. Returns: A list of `clang` copts, each of which is preceded by `-Xcc` so that they can be passed through `swiftc` to its underlying ClangImporter instance. """ # In general, every compilation mode flag from native `objc_*` rules should be passed, but `-g` # seems to break Clang module compilation. Since this flag does not make much sense for module # compilation and only touches headers, it's ok to omit. clang_copts = objc_fragment.copts + objc_fragment.copts_for_current_compilation_mode return collections.before_each("-Xcc", [copt for copt in clang_copts if copt != "-g"]) def _default_linker_opts( apple_fragment, apple_toolchain, platform, target, xcode_config, is_static, is_test): """Returns options that should be passed by default to `clang` when linking. This function is wrapped in a `partial` that will be propagated as part of the toolchain provider. The first five arguments are pre-bound; the `is_static` and `is_test` arguments are expected to be passed by the caller. Args: apple_fragment: The `apple` configuration fragment. apple_toolchain: The `apple_common.apple_toolchain()` object. platform: The `apple_platform` value describing the target platform. target: The target triple. xcode_config: The Xcode configuration. is_static: `True` to link against the static version of the Swift runtime, or `False` to link against dynamic/shared libraries. is_test: `True` if the target being linked is a test target. Returns: The command line options to pass to `clang` to link against the desired variant of the Swift runtime libraries. """ platform_framework_dir = apple_toolchain.platform_developer_framework_dir(apple_fragment) linkopts = [] uses_runtime_in_os = _is_xcode_at_least_version(xcode_config, "10.2") if uses_runtime_in_os: # Starting with Xcode 10.2, Apple forbids statically linking to the Swift runtime. The # libraries are distributed with the OS and located in /usr/lib/swift. swift_subdir = "swift" linkopts.append("-Wl,-rpath,/usr/lib/swift") elif is_static: # This branch and the branch below now only support Xcode 10.1 and below. Eventually, # once we drop support for those versions, they can be deleted. swift_subdir = "swift_static" linkopts.extend([ "-Wl,-force_load_swift_libs", "-framework", "Foundation", "-lstdc++", ]) else: swift_subdir = "swift" swift_lib_dir = ( "{developer_dir}/Toolchains/{toolchain}.xctoolchain/usr/lib/{swift_subdir}/{platform}" ).format( developer_dir = apple_toolchain.developer_dir(), platform = platform.name_in_plist.lower(), swift_subdir = swift_subdir, toolchain = "XcodeDefault", ) # TODO(b/128303533): It's possible to run Xcode 10.2 on a version of macOS 10.14.x that does # not yet include `/usr/lib/swift`. Later Xcode 10.2 betas have deleted the `swift_static` # directory, so we must manually add the dylibs to the binary's rpath or those binaries won't # be able to run at all. This is added after `/usr/lib/swift` above so the system versions # will always be preferred if they are present. # This workaround can be removed once Xcode 10.2 and macOS 10.14.4 are out of beta. if uses_runtime_in_os and platform == apple_common.platform.macos: linkopts.append("-Wl,-rpath,{}".format(swift_lib_dir)) linkopts.extend([ "-F{}".format(platform_framework_dir), "-L{}".format(swift_lib_dir), # TODO(b/112000244): These should get added by the C++ Skylark API, but we're using the # "c++-link-executable" action right now instead of "objc-executable" because the latter # requires additional variables not provided by cc_common. Figure out how to handle this # correctly. "-ObjC", "-Wl,-objc_abi_version,2", ]) use_system_swift_libs = _is_xcode_at_least_version(xcode_config, "11.0") if use_system_swift_libs: linkopts.append("-L/usr/lib/swift") # XCTest.framework only lives in the Xcode bundle (its platform framework # directory), so test binaries need to have that directory explicitly added to # their rpaths. if is_test: linkopts.append("-Wl,-rpath,{}".format(platform_framework_dir)) linkopts.append("-L{}".format(_swift_developer_lib_dir(platform_framework_dir))) return linkopts def _default_swiftc_copts( apple_fragment, apple_toolchain, target, toolchain_root): """Returns options that should be passed by default to `swiftc`. Args: apple_fragment: The `apple` configuration fragment. apple_toolchain: The `apple_common.apple_toolchain()` object. target: The target triple. toolchain_root: The optional toolchain root, if specified by the `--define=SWIFT_USE_TOOLCHAIN_ROOT=<path>` flag. Returns: A list of options that will be passed to any compile action created by this toolchain. """ platform_framework_dir = apple_toolchain.platform_developer_framework_dir(apple_fragment) copts = [ "-target", target, "-sdk", apple_toolchain.sdk_dir(), "-F", platform_framework_dir, "-I", _swift_developer_lib_dir(platform_framework_dir), ] # If we have a custom "toolchain root" (meaning a bin/ dir with a custom # compiler that we want to use in place of the original, but not a *full* # toolchain, make sure we use the resource dir of the *original* toolchain # so that libraries are still found (otherwise, by default, the compiler # will look in its parent directory for them). if toolchain_root: copts.extend([ "-resource-dir", ("{developer_dir}/Toolchains/{toolchain}.xctoolchain/" + "usr/lib/swift").format( developer_dir = apple_toolchain.developer_dir(), toolchain = "XcodeDefault", ), ]) bitcode_mode = str(apple_fragment.bitcode_mode) if bitcode_mode == "embedded": copts.append("-embed-bitcode") elif bitcode_mode == "embedded_markers": copts.append("-embed-bitcode-marker") elif bitcode_mode != "none": fail("Internal error: expected apple_fragment.bitcode_mode to be " + "one of: ['embedded', 'embedded_markers', 'none']") return copts def _is_macos(platform): """Returns `True` if the given platform is macOS. Args: platform: An `apple_platform` value describing the platform for which a target is being built. Returns: `True` if the given platform is macOS. """ return platform.platform_type == apple_common.platform_type.macos def _trim_version(version): """Trim the given version number down to a maximum of three components. Args: version: The version number to trim; either a string or a `DottedVersion` value. Returns: The trimmed version number as a `DottedVersion` value. """ version = str(version) parts = version.split(".") maxparts = min(len(parts), 3) return apple_common.dotted_version(".".join(parts[:maxparts])) def _is_xcode_at_least_version(xcode_config, desired_version): """Returns True if we are building with at least the given Xcode version. Args: xcode_config: the `apple_common.XcodeVersionConfig` provider. desired_version: The minimum desired Xcode version, as a dotted version string. Returns: True if the current target is being built with a version of Xcode at least as high as the given version. """ current_version = xcode_config.xcode_version() if not current_version: fail("Could not determine Xcode version at all. This likely means Xcode isn't " + "available; if you think this is a mistake, please file an issue.") # TODO(b/131195460): DottedVersion comparison is broken for four-component versions that are # returned by modern Xcodes. Work around it for now. desired_version_value = _trim_version(desired_version) return _trim_version(current_version) >= desired_version_value def _swift_apple_target_triple(cpu, platform, version): """Returns a target triple string for an Apple platform. Args: cpu: The CPU of the target. platform: The `apple_platform` value describing the target platform. version: The target platform version as a dotted version string. Returns: A target triple string describing the platform. """ platform_string = str(platform.platform_type) if platform_string == "macos": platform_string = "macosx" environment = "" if not platform.is_device: environment = "-simulator" return "{cpu}-apple-{platform}{version}{environment}".format( cpu = cpu, environment = environment, platform = platform_string, version = version, ) def _xcode_env(xcode_config, platform): """Returns a dictionary containing Xcode-related environment variables. Args: xcode_config: The `XcodeVersionConfig` provider that contains information about the current Xcode configuration. platform: The `apple_platform` value describing the target platform being built. Returns: A `dict` containing Xcode-related environment variables that should be passed to Swift compile and link actions. """ return dicts.add( apple_common.apple_host_system_env(xcode_config), apple_common.target_apple_env(xcode_config, platform), ) def _xcode_swift_toolchain_impl(ctx): apple_fragment = ctx.fragments.apple apple_toolchain = apple_common.apple_toolchain() cpu = apple_fragment.single_arch_cpu platform = apple_fragment.single_arch_platform xcode_config = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] target_os_version = xcode_config.minimum_os_for_platform_type(platform.platform_type) target = _swift_apple_target_triple(cpu, platform, target_os_version) linker_opts_producer = partial.make( _default_linker_opts, apple_fragment, apple_toolchain, platform, target, xcode_config, ) # `--define=SWIFT_USE_TOOLCHAIN_ROOT=<path>` is a rapid development feature # that lets you build *just* a custom `swift` driver (and `swiftc` # symlink), rather than a full toolchain, and point compilation actions at # those. Note that the files must still be in a "toolchain-like" directory # structure, meaning that the path passed here must contain a `bin` # directory and that directory contains the `swift` and `swiftc` files. # # To use a "standard" custom toolchain built using the full Swift build # script, use `--define=SWIFT_CUSTOM_TOOLCHAIN=<id>` as shown below. toolchain_root = ctx.var.get("SWIFT_USE_TOOLCHAIN_ROOT") custom_toolchain = ctx.var.get("SWIFT_CUSTOM_TOOLCHAIN") if toolchain_root and custom_toolchain: fail("Do not use SWIFT_USE_TOOLCHAIN_ROOT and SWIFT_CUSTOM_TOOLCHAIN" + "in the same build.") swiftc_copts = _default_swiftc_copts( apple_fragment, apple_toolchain, target, toolchain_root, ) # Configure the action registrars that automatically prepend xcrunwrapper to registered actions. env = _xcode_env(xcode_config, platform) swift_toolchain_env = {} if custom_toolchain: swift_toolchain_env["TOOLCHAINS"] = custom_toolchain execution_requirements = {"requires-darwin": ""} cc_toolchain = find_cpp_toolchain(ctx) # Compute the default requested features and conditional ones based on Xcode version. requested_features = features_for_build_modes(ctx, objc_fragment = ctx.fragments.objc) requested_features.extend(ctx.features) requested_features.append(SWIFT_FEATURE_BUNDLED_XCTESTS) # Xcode 10.0 implies Swift 4.2. if _is_xcode_at_least_version(xcode_config, "10.0"): requested_features.append(SWIFT_FEATURE_ENABLE_BATCH_MODE) requested_features.append(SWIFT_FEATURE_USE_RESPONSE_FILES) # Xcode 10.2 implies Swift 5.0. if _is_xcode_at_least_version(xcode_config, "10.2"): requested_features.append(SWIFT_FEATURE_DEBUG_PREFIX_MAP) # Xcode 11.0 implies Swift 5.1. if _is_xcode_at_least_version(xcode_config, "11.0"): requested_features.append(SWIFT_FEATURE_SUPPORTS_LIBRARY_EVOLUTION) command_line_copts = _command_line_objc_copts(ctx.fragments.objc) + ctx.fragments.swift.copts() return [ SwiftToolchainInfo( action_environment = env, # Xcode toolchains don't pass any files explicitly here because they're just # available as part of the Xcode bundle. all_files = depset(), cc_toolchain_info = cc_toolchain, clang_executable = None, command_line_copts = command_line_copts, cpu = cpu, execution_requirements = execution_requirements, linker_opts_producer = linker_opts_producer, object_format = "macho", optional_implicit_deps = [], requested_features = requested_features, required_implicit_deps = [], root_dir = toolchain_root, stamp_producer = None, supports_objc_interop = True, swiftc_copts = swiftc_copts, swift_worker = ctx.executable._worker, system_name = "darwin", unsupported_features = ctx.disabled_features + [ SWIFT_FEATURE_AUTOLINK_EXTRACT, SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD, ], ), ] xcode_swift_toolchain = rule( attrs = dicts.add({ "_cc_toolchain": attr.label( default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"), doc = """ The C++ toolchain from which linking flags and other tools needed by the Swift toolchain (such as `clang`) will be retrieved. """, ), "_worker": attr.label( cfg = "host", allow_files = True, default = Label( "@build_bazel_rules_swift//tools/worker", ), doc = """ An executable that wraps Swift compiler invocations and also provides support for incremental compilation using a persistent mode. """, executable = True, ), "_xcode_config": attr.label( default = configuration_field( name = "xcode_config_label", fragment = "apple", ), ), }), doc = "Represents a Swift compiler toolchain provided by Xcode.", fragments = [ "apple", "objc", "swift", ], toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], implementation = _xcode_swift_toolchain_impl, ) 07070100000052000081A4000003E800000064000000015D9E346300000F43000000000000000000000000000000000000003000000000bazel-rules-swift-0.13.0/swift/repositories.bzl# Copyright 2018 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. """Definitions for handling Bazel repositories used by the Swift rules.""" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") load( "@build_bazel_rules_swift//swift/internal:swift_autoconfiguration.bzl", "swift_autoconfiguration", ) def _maybe(repo_rule, name, **kwargs): """Executes the given repository rule if it hasn't been executed already. Args: repo_rule: The repository rule to be executed (e.g., `http_archive`.) name: The name of the repository to be defined by the rule. **kwargs: Additional arguments passed directly to the repository rule. """ if not native.existing_rule(name): repo_rule(name = name, **kwargs) def swift_rules_dependencies(): """Fetches repositories that are dependencies of the `rules_swift` workspace. Users should call this macro in their `WORKSPACE` to ensure that all of the dependencies of the Swift rules are downloaded and that they are isolated from changes to those dependencies. """ _maybe( http_archive, name = "bazel_skylib", urls = [ "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz", ], sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44", ) _maybe( http_archive, name = "build_bazel_apple_support", urls = [ "https://github.com/bazelbuild/apple_support/releases/download/0.7.2/apple_support.0.7.2.tar.gz", ], sha256 = "9114c452eee622598cf9cdc90ecb12b06af7f914f33440b26deba9a9704d450c", ) _maybe( http_archive, name = "com_github_apple_swift_protobuf", urls = ["https://github.com/apple/swift-protobuf/archive/1.7.0.zip"], sha256 = "a4546ee8e95e7f7d4cf46b5b667e824b58f3943a71c352bf1e0b91660afdf3c3", strip_prefix = "swift-protobuf-1.7.0/", type = "zip", build_file = "@build_bazel_rules_swift//third_party:com_github_apple_swift_protobuf/BUILD.overlay", ) _maybe( http_archive, name = "com_github_grpc_grpc_swift", urls = ["https://github.com/grpc/grpc-swift/archive/0.9.0.zip"], sha256 = "b9818134f497df073cb49e0df59bfeea801291230d6fc048fdc6aa76e453a3cb", strip_prefix = "grpc-swift-0.9.0/", type = "zip", build_file = "@build_bazel_rules_swift//third_party:com_github_grpc_grpc_swift/BUILD.overlay", ) _maybe( http_archive, name = "com_github_nlohmann_json", urls = ["https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip"], sha256 = "69cc88207ce91347ea530b227ff0776db82dcb8de6704e1a3d74f4841bc651cf", type = "zip", build_file = "@build_bazel_rules_swift//third_party:com_github_nlohmann_json/BUILD.overlay", ) _maybe( http_archive, name = "com_google_protobuf", # v3.8.0, latest as of 2019-05-28 urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.8.0.zip"], sha256 = "1e622ce4b84b88b6d2cdf1db38d1a634fe2392d74f0b7b74ff98f3a51838ee53", strip_prefix = "protobuf-3.8.0", type = "zip", ) _maybe( swift_autoconfiguration, name = "build_bazel_rules_swift_local_config", ) 07070100000053000081A4000003E800000064000000015D9E346300000855000000000000000000000000000000000000002900000000bazel-rules-swift-0.13.0/swift/stats.bzl# Copyright 2019 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. """An aspect that collects compilation timing statistics.""" load("@build_bazel_rules_swift//swift/internal:utils.bzl", "get_output_groups") def _collect_swift_compile_stats_impl(target, aspect_ctx): output_groups = target[OutputGroupInfo] deps = getattr(aspect_ctx.rule.attr, "deps", []) merged_stats = get_output_groups(deps, "swift_compile_stats") direct_stats = getattr(output_groups, "swift_compile_stats_direct", None) if direct_stats: merged_stats.append(direct_stats) return [OutputGroupInfo(swift_compile_stats = depset(transitive = merged_stats))] collect_swift_compile_stats = aspect( attr_aspects = ["deps"], doc = """ Collects compilation statistics reports from the entire build graph. This aspect is intended to be used from the command line to profile the Swift compiler during a build. It needs to be combined with the `swift.compile_stats` feature that asks the compiler to write out the statistics and a request for the `swift_compile_stats` output group so that the files are available at the end of the build: ``` bazel build //your/swift:target \ --features=swift.compile_stats \ --output_groups=swift_compile_stats \ --aspects=@build_bazel_rules_swift//swift:stats.bzl%collect_swift_compile_stats ``` Since this command is a bit of a mouthful, we've provided a helper script in the tools directory that wraps this up: ``` .../tools/compile_stats/build.sh <args to pass to Bazel> ``` """, implementation = _collect_swift_compile_stats_impl, ) 07070100000054000081A4000003E800000064000000015D9E346300000AA5000000000000000000000000000000000000002900000000bazel-rules-swift-0.13.0/swift/swift.bzl# Copyright 2018 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. """BUILD rules to define Swift libraries and executable binaries. This file is the public interface that users should import to use the Swift rules. Do not import definitions from the `internal` subdirectory directly. """ load( "@build_bazel_rules_swift//swift/internal:api.bzl", _swift_common = "swift_common", ) load( "@build_bazel_rules_swift//swift/internal:providers.bzl", _SwiftInfo = "SwiftInfo", _SwiftProtoInfo = "SwiftProtoInfo", _SwiftToolchainInfo = "SwiftToolchainInfo", _SwiftUsageInfo = "SwiftUsageInfo", ) load( "@build_bazel_rules_swift//swift/internal:swift_binary_test.bzl", _swift_binary = "swift_binary", _swift_test = "swift_test", ) load( "@build_bazel_rules_swift//swift/internal:swift_c_module.bzl", _swift_c_module = "swift_c_module", ) load( "@build_bazel_rules_swift//swift/internal:swift_grpc_library.bzl", _swift_grpc_library = "swift_grpc_library", ) load( "@build_bazel_rules_swift//swift/internal:swift_import.bzl", _swift_import = "swift_import", ) load( "@build_bazel_rules_swift//swift/internal:swift_library.bzl", _swift_library = "swift_library", ) load( "@build_bazel_rules_swift//swift/internal:swift_module_alias.bzl", _swift_module_alias = "swift_module_alias", ) load( "@build_bazel_rules_swift//swift/internal:swift_proto_library.bzl", _swift_proto_library = "swift_proto_library", ) load( "@build_bazel_rules_swift//swift/internal:swift_usage_aspect.bzl", _swift_usage_aspect = "swift_usage_aspect", ) # Re-export providers. SwiftInfo = _SwiftInfo SwiftProtoInfo = _SwiftProtoInfo SwiftToolchainInfo = _SwiftToolchainInfo SwiftUsageInfo = _SwiftUsageInfo # Re-export public API module. swift_common = _swift_common # Re-export rules. swift_binary = _swift_binary swift_c_module = _swift_c_module swift_grpc_library = _swift_grpc_library swift_import = _swift_import swift_library = _swift_library swift_test = _swift_test swift_module_alias = _swift_module_alias swift_proto_library = _swift_proto_library # Re-export public aspects. swift_usage_aspect = _swift_usage_aspect 07070100000055000041ED000003E800000064000000065D9E346300000000000000000000000000000000000000000000002500000000bazel-rules-swift-0.13.0/third_party07070100000056000081A4000003E800000064000000015D9E346300000000000000000000000000000000000000000000002B00000000bazel-rules-swift-0.13.0/third_party/BUILD07070100000057000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003200000000bazel-rules-swift-0.13.0/third_party/bazel_protos07070100000058000081A4000003E800000064000000015D9E346300000101000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/third_party/bazel_protos/BUILDlicenses(["notice"]) proto_library( name = "worker_protocol_proto", srcs = ["worker_protocol.proto"], ) cc_proto_library( name = "worker_protocol_cc_proto", visibility = ["//tools/worker:__pkg__"], deps = [":worker_protocol_proto"], ) 07070100000059000081A4000003E800000064000000015D9E3463000000C1000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/third_party/bazel_protos/README.mdThis directory contains protocol buffers vendored from the main Bazel repository, so that rules_swift does not need to depend on the entire `@io_bazel` workspace, which is approximately 100MB. 0707010000005A000081A4000003E800000064000000015D9E346300000713000000000000000000000000000000000000004800000000bazel-rules-swift-0.13.0/third_party/bazel_protos/worker_protocol.proto// Copyright 2015 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. syntax = "proto3"; package blaze.worker; option java_package = "com.google.devtools.build.lib.worker"; // An input file. message Input { // The path in the file system where to read this input artifact from. This is // either a path relative to the execution root (the worker process is // launched with the working directory set to the execution root), or an // absolute path. string path = 1; // A hash-value of the contents. The format of the contents is unspecified and // the digest should be treated as an opaque token. bytes digest = 2; } // This represents a single work unit that Bazel sends to the worker. message WorkRequest { repeated string arguments = 1; // The inputs that the worker is allowed to read during execution of this // request. repeated Input inputs = 2; } // The worker sends this message to Bazel when it finished its work on the // WorkRequest message. message WorkResponse { int32 exit_code = 1; // This is printed to the user after the WorkResponse has been received and is // supposed to contain compiler warnings / errors etc. - thus we'll use a // string type here, which gives us UTF-8 encoding. string output = 2; } 0707010000005B000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000004500000000bazel-rules-swift-0.13.0/third_party/com_github_apple_swift_protobuf0707010000005C000081A4000003E800000064000000015D9E3463000002F3000000000000000000000000000000000000005300000000bazel-rules-swift-0.13.0/third_party/com_github_apple_swift_protobuf/BUILD.overlayload( "@build_bazel_rules_swift//swift:swift.bzl", "swift_binary", "swift_library", ) swift_library( name = "SwiftProtobuf", srcs = glob([ "Sources/SwiftProtobuf/*.swift", ]), module_name = "SwiftProtobuf", visibility = ["//visibility:public"], ) swift_library( name = "SwiftProtobufPluginLibrary", srcs = glob([ "Sources/SwiftProtobufPluginLibrary/*.swift", ]), module_name = "SwiftProtobufPluginLibrary", visibility = ["//visibility:public"], deps = [":SwiftProtobuf"], ) swift_binary( name = "ProtoCompilerPlugin", srcs = glob([ "Sources/protoc-gen-swift/*.swift", ]), visibility = ["//visibility:public"], deps = [":SwiftProtobufPluginLibrary"], ) 0707010000005D000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000004000000000bazel-rules-swift-0.13.0/third_party/com_github_grpc_grpc_swift0707010000005E000081A4000003E800000064000000015D9E34630000077F000000000000000000000000000000000000004E00000000bazel-rules-swift-0.13.0/third_party/com_github_grpc_grpc_swift/BUILD.overlayload( "@build_bazel_rules_swift//swift:swift.bzl", "swift_binary", "swift_library", ) swift_library( name = "SwiftGRPC", srcs = glob([ "Sources/SwiftGRPC/**/*.swift", ]), copts = ["-DSWIFT_PACKAGE"], # activates CgRPC imports module_name = "SwiftGRPC", visibility = ["//visibility:public"], deps = [ ":CgRPC", "@com_github_apple_swift_protobuf//:SwiftProtobuf", ], ) cc_library( name = "BoringSSL", srcs = glob([ "Sources/BoringSSL/crypto/**/*.c", "Sources/BoringSSL/crypto/**/*.cc", "Sources/BoringSSL/crypto/**/*.h", "Sources/BoringSSL/ssl/**/*.c", "Sources/BoringSSL/ssl/**/*.cc", "Sources/BoringSSL/ssl/**/*.h", "Sources/BoringSSL/third_party/**/*.c", "Sources/BoringSSL/third_party/**/*.h", ]), hdrs = glob(["Sources/BoringSSL/include/**/*.h"]), copts = ["-Wno-unused-function"], includes = ["Sources/BoringSSL/include"], ) cc_library( name = "CgRPC", srcs = glob([ "Sources/CgRPC/include/**/*.h", "Sources/CgRPC/shim/*.c", "Sources/CgRPC/src/**/*.c", "Sources/CgRPC/src/**/*.cc", "Sources/CgRPC/src/**/*.h", "Sources/CgRPC/third_party/nanopb/**/*.c", "Sources/CgRPC/third_party/nanopb/**/*.h", ]) + ["Sources/CgRPC/shim/internal.h"], hdrs = ["Sources/CgRPC/shim/cgrpc.h"], copts = ["-DPB_NO_PACKED_STRUCTS=1"], includes = ["Sources/CgRPC/include"], tags = ["swift_module=CgRPC"], deps = [ ":BoringSSL", "@zlib//:zlib", ], ) swift_binary( name = "protoc-gen-swiftgrpc", srcs = glob([ "Sources/protoc-gen-swiftgrpc/*.swift", ]), visibility = ["//visibility:public"], deps = [ "@com_github_apple_swift_protobuf//:SwiftProtobuf", "@com_github_apple_swift_protobuf//:SwiftProtobufPluginLibrary", ], ) 0707010000005F000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000003E00000000bazel-rules-swift-0.13.0/third_party/com_github_nlohmann_json07070100000060000081A4000003E800000064000000015D9E346300000108000000000000000000000000000000000000004C00000000bazel-rules-swift-0.13.0/third_party/com_github_nlohmann_json/BUILD.overlaypackage(default_visibility = ["//visibility:public"]) cc_library( name = "json", srcs = glob( ["include/nlohmann/**/*.hpp"], exclude = ["include/nlohmann/json.hpp"]), hdrs = ["include/nlohmann/json.hpp"], includes = ["include"], ) 07070100000061000041ED000003E800000064000000085D9E346300000000000000000000000000000000000000000000001F00000000bazel-rules-swift-0.13.0/tools07070100000062000081A4000003E800000064000000015D9E346300000189000000000000000000000000000000000000002500000000bazel-rules-swift-0.13.0/tools/BUILDpackage(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]) + [ "//tools/common:for_bazel_tests", "//tools/mkdir_and_run:for_bazel_tests", "//tools/worker:for_bazel_tests", ], visibility = [ "//:__pkg__", ], ) 07070100000063000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002600000000bazel-rules-swift-0.13.0/tools/common07070100000064000081A4000003E800000064000000015D9E34630000033D000000000000000000000000000000000000002C00000000bazel-rules-swift-0.13.0/tools/common/BUILDpackage( default_visibility = [ "//tools/worker:__pkg__", ], ) licenses(["notice"]) cc_library( name = "file_system", srcs = ["file_system.cc"], hdrs = ["file_system.h"], deps = [ ":path_utils", ], ) cc_library( name = "path_utils", srcs = ["path_utils.cc"], hdrs = ["path_utils.h"], ) cc_library( name = "process", srcs = ["process.cc"], hdrs = ["process.h"], deps = [ ":path_utils", ], ) cc_library( name = "string_utils", srcs = ["string_utils.cc"], hdrs = ["string_utils.h"], ) cc_library( name = "temp_file", hdrs = ["temp_file.h"], ) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]), visibility = [ "//tools:__pkg__", ], ) 07070100000065000081A4000003E800000064000000015D9E346300000B41000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/tools/common/file_system.cc// Copyright 2019 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. #include "tools/common/file_system.h" #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <string> #ifdef __APPLE__ #include <copyfile.h> #else #include <fcntl.h> #include <sys/sendfile.h> #endif #include "tools/common/path_utils.h" std::string GetCurrentDirectory() { // Passing null,0 causes getcwd to allocate the buffer of the correct size. char *buffer = getcwd(nullptr, 0); std::string cwd(buffer); free(buffer); return cwd; } bool CopyFile(const std::string &src, const std::string &dest) { #ifdef __APPLE__ // The `copyfile` function with `COPYFILE_ALL` mode preserves permissions and // modification time. return copyfile(src.c_str(), dest.c_str(), nullptr, COPYFILE_ALL | COPYFILE_CLONE) == 0; #elif __unix__ // On Linux, we can use `sendfile` to copy it more easily than calling // `read`/`write` in a loop. struct stat stat_buf; bool success = false; int src_fd = open(src.c_str(), O_RDONLY); if (src_fd) { fstat(src_fd, &stat_buf); int dest_fd = open(dest.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode); if (dest_fd) { off_t offset = 0; if (sendfile(dest_fd, src_fd, &offset, stat_buf.st_size) != -1) { struct timespec timespecs[2] = {stat_buf.st_atim, stat_buf.st_mtim}; futimens(dest_fd, timespecs); success = true; } close(dest_fd); } close(src_fd); } return success; #else // TODO(allevato): If we want to support Windows in the future, we'll need to // use something like `CopyFileA`. #error Only macOS and Unix are supported at this time. #endif } bool MakeDirs(const std::string &path, int mode) { // If we got an empty string, we've recursed past the first segment in the // path. Assume it exists (if it doesn't, we'll fail when we try to create a // directory inside it). if (path.empty()) { return true; } struct stat dir_stats; if (stat(path.c_str(), &dir_stats) == 0) { // Return true if the directory already exists. return S_ISDIR(dir_stats.st_mode); } // Recurse to create the parent directory. if (!MakeDirs(Dirname(path).c_str(), mode)) { return false; } // Create the directory that was requested. return mkdir(path.c_str(), mode) == 0; } 07070100000066000081A4000003E800000064000000015D9E3463000004C2000000000000000000000000000000000000003400000000bazel-rules-swift-0.13.0/tools/common/file_system.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_FILE_SYSTEM_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_FILE_SYSTEM_H_ #include <string> // Gets the path to the current working directory. std::string GetCurrentDirectory(); // Copies the file at src to dest. Returns true if successful. bool CopyFile(const std::string &src, const std::string &dest); // Creates a directory at the given path, along with any parent directories that // don't already exist. Returns true if successful. bool MakeDirs(const std::string &path, int mode); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_FILE_SYSTEM_H_ 07070100000067000081A4000003E800000064000000015D9E3463000005B8000000000000000000000000000000000000003400000000bazel-rules-swift-0.13.0/tools/common/path_utils.cc// Copyright 2019 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. #include "tools/common/path_utils.h" #include <cstring> #include <string> const char *Basename(const char *path) { const char *base = strrchr(path, '/'); return base ? (base + 1) : path; } std::string Dirname(const std::string &path) { auto last_slash = path.rfind('/'); if (last_slash == std::string::npos) { return std::string(); } return path.substr(0, last_slash); } std::string ReplaceExtension(const std::string &path, const std::string &new_extension) { auto last_dot = path.rfind('.'); auto last_slash = path.rfind('/'); // If there was no dot, or if it was part of a previous path segment, append // the extension to the path. if (last_dot == std::string::npos || last_dot < last_slash) { return path + new_extension; } return path.substr(0, last_dot) + new_extension; } 07070100000068000081A4000003E800000064000000015D9E3463000005F6000000000000000000000000000000000000003300000000bazel-rules-swift-0.13.0/tools/common/path_utils.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_PATH_UTILS_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_PATH_UTILS_H_ #include <string> // Returns the base name of the given filepath. For example, given // "/foo/bar/baz.txt", returns "baz.txt". const char *Basename(const char *path); // Returns the directory name of the given filepath. For example, given // "/foo/bar/baz.txt", returns "/foo/bar". std::string Dirname(const std::string &path); // Replaces the file extension of path with new_extension. It is assumed that // new_extension starts with a dot if it is desired for a dot to precede the new // extension in the returned path. If the path does not have a file extension, // then new_extension is appended to it. std::string ReplaceExtension(const std::string &path, const std::string &new_extension); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_PATH_UTILS_H_ 07070100000069000081A4000003E800000064000000015D9E346300001828000000000000000000000000000000000000003100000000bazel-rules-swift-0.13.0/tools/common/process.cc// Copyright 2019 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. #include <fcntl.h> #include <spawn.h> #include <sys/poll.h> #include <sys/wait.h> #include <unistd.h> #include <cerrno> #include <cstring> #include <iostream> #include <memory> #include <string> #include <vector> #include "tools/common/path_utils.h" extern char **environ; namespace { // An RAII class that manages the pipes and posix_spawn state needed to redirect // subprocess I/O. Currently only supports stderr, but can be extended to handle // stdin and stdout if needed. class PosixSpawnIORedirector { public: // Create an I/O redirector that can be used with posix_spawn to capture // stderr. static std::unique_ptr<PosixSpawnIORedirector> Create(bool stdoutToStderr) { int stderr_pipe[2]; if (pipe(stderr_pipe) != 0) { return nullptr; } return std::unique_ptr<PosixSpawnIORedirector>( new PosixSpawnIORedirector(stderr_pipe, stdoutToStderr)); } // Explicitly make PosixSpawnIORedirector non-copyable and movable. PosixSpawnIORedirector(const PosixSpawnIORedirector &) = delete; PosixSpawnIORedirector &operator=(const PosixSpawnIORedirector &) = delete; PosixSpawnIORedirector(PosixSpawnIORedirector &&) = default; PosixSpawnIORedirector &operator=(PosixSpawnIORedirector &&) = default; ~PosixSpawnIORedirector() { SafeClose(&stderr_pipe_[0]); SafeClose(&stderr_pipe_[1]); posix_spawn_file_actions_destroy(&file_actions_); } // Returns the pointer to a posix_spawn_file_actions_t value that should be // passed to posix_spawn to enable this redirection. posix_spawn_file_actions_t *PosixSpawnFileActions() { return &file_actions_; } // Returns a pointer to the two-element file descriptor array for the stderr // pipe. int *StderrPipe() { return stderr_pipe_; } // Consumes all the data output to stderr by the subprocess and writes it to // the given output stream. void ConsumeAllSubprocessOutput(std::ostream *stderr_stream); private: explicit PosixSpawnIORedirector(int stderr_pipe[], bool stdoutToStderr) { memcpy(stderr_pipe_, stderr_pipe, sizeof(int) * 2); posix_spawn_file_actions_init(&file_actions_); posix_spawn_file_actions_addclose(&file_actions_, stderr_pipe_[0]); if (stdoutToStderr) { posix_spawn_file_actions_adddup2(&file_actions_, stderr_pipe_[1], STDOUT_FILENO); } posix_spawn_file_actions_adddup2(&file_actions_, stderr_pipe_[1], STDERR_FILENO); posix_spawn_file_actions_addclose(&file_actions_, stderr_pipe_[1]); } // Closes a file descriptor only if it hasn't already been closed. void SafeClose(int *fd) { if (*fd >= 0) { close(*fd); *fd = -1; } } int stderr_pipe_[2]; posix_spawn_file_actions_t file_actions_; }; void PosixSpawnIORedirector::ConsumeAllSubprocessOutput( std::ostream *stderr_stream) { SafeClose(&stderr_pipe_[1]); char stderr_buffer[1024]; pollfd stderr_poll = {stderr_pipe_[0], POLLIN}; int status; while ((status = poll(&stderr_poll, 1, -1)) > 0) { if (stderr_poll.revents) { int bytes_read = read(stderr_pipe_[0], stderr_buffer, sizeof(stderr_buffer)); if (bytes_read == 0) { break; } stderr_stream->write(stderr_buffer, bytes_read); } } } // Converts an array of string arguments to char *arguments. // The first arg is reduced to its basename as per execve conventions. // Note that the lifetime of the char* arguments in the returned array // are controlled by the lifetime of the strings in args. std::vector<const char *> ConvertToCArgs(const std::vector<std::string> &args) { std::vector<const char *> c_args; c_args.push_back(Basename(args[0].c_str())); for (int i = 1; i < args.size(); i++) { c_args.push_back(args[i].c_str()); } c_args.push_back(nullptr); return c_args; } } // namespace void ExecProcess(const std::vector<std::string> &args) { std::vector<const char *> exec_argv = ConvertToCArgs(args); execv(args[0].c_str(), const_cast<char **>(exec_argv.data())); std::cerr << "Error executing child process.'" << args[0] << "'. " << strerror(errno) << "\n"; abort(); } int RunSubProcess(const std::vector<std::string> &args, std::ostream *stderr_stream, bool stdout_to_stderr) { std::vector<const char *> exec_argv = ConvertToCArgs(args); // Set up a pipe to redirect stderr from the child process so that we can // capture it and return it in the response message. std::unique_ptr<PosixSpawnIORedirector> redirector = PosixSpawnIORedirector::Create(stdout_to_stderr); if (!redirector) { (*stderr_stream) << "Error creating stderr pipe for child process.\n"; return 254; } pid_t pid; int status = posix_spawn(&pid, args[0].c_str(), redirector->PosixSpawnFileActions(), nullptr, const_cast<char **>(exec_argv.data()), environ); redirector->ConsumeAllSubprocessOutput(stderr_stream); if (status == 0) { int wait_status; do { wait_status = waitpid(pid, &status, 0); } while ((wait_status == -1) && (errno == EINTR)); if (wait_status < 0) { std::cerr << "Error waiting on child process '" << args[0] << "'. " << strerror(errno) << "\n"; return wait_status; } int exit_status = WEXITSTATUS(status); if (exit_status != 0) { return exit_status; } return 0; } else { std::cerr << "Error forking process '" << args[0] << "'. " << strerror(status) << "\n"; return status; } } 0707010000006A000081A4000003E800000064000000015D9E346300000563000000000000000000000000000000000000003000000000bazel-rules-swift-0.13.0/tools/common/process.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WRAPPERS_PROCESS_H #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WRAPPERS_PROCESS_H #include <string> #include <vector> // Turn our current process into a new process. Avoids fork overhead. // Never returns. void ExecProcess(const std::vector<std::string> &args); // Spawns a subprocess for given arguments args and waits for it to terminate. // The first argument is used for the executable path. If stdout_to_stderr is // set, then stdout is redirected to the stderr stream as well. Returns the exit // code of the spawned process. int RunSubProcess(const std::vector<std::string> &args, std::ostream *stderr_stream, bool stdout_to_stderr = false); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WRAPPERS_PROCESS_H 0707010000006B000081A4000003E800000064000000015D9E3463000005D9000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/tools/common/string_utils.cc// Copyright 2019 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. #include <map> #include <string> // Finds and replaces all instances of oldsub with newsub, in-place on str. // Returns true if the string was changed. static bool FindAndReplace(const std::string &oldsub, const std::string &newsub, std::string *str) { int start = 0; bool changed = false; while ((start = str->find(oldsub, start)) != std::string::npos) { changed = true; str->replace(start, oldsub.length(), newsub); start += newsub.length(); } return changed; } bool MakeSubstitutions(std::string *arg, const std::map<std::string, std::string> &mappings) { bool changed = false; // Replace placeholders in the string with their actual values. for (std::pair<std::string, std::string> mapping : mappings) { changed |= FindAndReplace(mapping.first, mapping.second, arg); } return changed; } 0707010000006C000081A4000003E800000064000000015D9E346300000404000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/tools/common/string_utils.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_STRING_UTILS_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_STRING_UTILS_H_ #include <map> #include <string> // Rewrites the given argument by replacing any Bazel path placeholders. bool MakeSubstitutions(std::string *arg, const std::map<std::string, std::string> &mappings); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_STRING_UTILS_H_ 0707010000006D000081A4000003E800000064000000015D9E346300001155000000000000000000000000000000000000003200000000bazel-rules-swift-0.13.0/tools/common/temp_file.h// Copyright 2018 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TEMP_FILE_H #define BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TEMP_FILE_H #include <fts.h> #include <string.h> #include <unistd.h> #include <cerrno> #include <cstdlib> #include <iostream> #include <memory> #include <string> // An RAII temporary file. class TempFile { public: // Create a new temporary file using the given path template string (the same // form used by `mkstemp`). The file will automatically be deleted when the // object goes out of scope. static std::unique_ptr<TempFile> Create(const std::string &path_template) { const char *tmpDir = getenv("TMPDIR"); if (!tmpDir) { tmpDir = "/tmp"; } size_t size = strlen(tmpDir) + path_template.size() + 2; std::unique_ptr<char[]> path(new char[size]); snprintf(path.get(), size, "%s/%s", tmpDir, path_template.c_str()); if (mkstemp(path.get()) == -1) { std::cerr << "Failed to create temporary file '" << path.get() << "': " << strerror(errno) << "\n"; return nullptr; } return std::unique_ptr<TempFile>(new TempFile(path.get())); } // Explicitly make TempFile non-copyable and movable. TempFile(const TempFile &) = delete; TempFile &operator=(const TempFile &) = delete; TempFile(TempFile &&) = default; TempFile &operator=(TempFile &&) = default; ~TempFile() { remove(path_.c_str()); } // Gets the path to the temporary file. std::string GetPath() const { return path_; } private: explicit TempFile(const std::string &path) : path_(path) {} std::string path_; }; // An RAII temporary directory that is recursively deleted. class TempDirectory { public: // Create a new temporary directory using the given path template string (the // same form used by `mkdtemp`). The file will automatically be deleted when // the object goes out of scope. static std::unique_ptr<TempDirectory> Create( const std::string &path_template) { const char *tmpDir = getenv("TMPDIR"); if (!tmpDir) { tmpDir = "/tmp"; } size_t size = strlen(tmpDir) + path_template.size() + 2; std::unique_ptr<char[]> path(new char[size]); snprintf(path.get(), size, "%s/%s", tmpDir, path_template.c_str()); if (mkdtemp(path.get()) == nullptr) { std::cerr << "Failed to create temporary directory '" << path.get() << "': " << strerror(errno) << "\n"; return nullptr; } return std::unique_ptr<TempDirectory>(new TempDirectory(path.get())); } // Explicitly make TempDirectory non-copyable and movable. TempDirectory(const TempDirectory &) = delete; TempDirectory &operator=(const TempDirectory &) = delete; TempDirectory(TempDirectory &&) = default; TempDirectory &operator=(TempDirectory &&) = default; ~TempDirectory() { char *files[] = {(char *)path_.c_str(), nullptr}; // Don't have the walk change directories, don't traverse symlinks, and // don't cross devices. auto fts_handle = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, nullptr); if (!fts_handle) { return; } FTSENT *entry; while ((entry = fts_read(fts_handle))) { switch (entry->fts_info) { case FTS_F: // regular file case FTS_SL: // symlink case FTS_SLNONE: // symlink without target case FTS_DP: // directory, post-order (after traversing children) case FTS_DEFAULT: // other non-error conditions remove(entry->fts_accpath); break; } } fts_close(fts_handle); } // Gets the path to the temporary directory. std::string GetPath() const { return path_; } private: explicit TempDirectory(const std::string &path) : path_(path) {} std::string path_; }; #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TEMP_FILE_H 0707010000006E000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002D00000000bazel-rules-swift-0.13.0/tools/compile_stats0707010000006F000081A4000003E800000064000000015D9E346300000074000000000000000000000000000000000000003300000000bazel-rules-swift-0.13.0/tools/compile_stats/BUILDload("//swift:swift.bzl", "swift_binary") swift_binary( name = "stats_processor", srcs = ["main.swift"], ) 07070100000070000081A4000003E800000064000000015D9E34630000027F000000000000000000000000000000000000003700000000bazel-rules-swift-0.13.0/tools/compile_stats/README.md# compile_stats/build.sh helper This script conveniently wraps up the various Bazel arguments needed to collect timing statistics from the Swift compiler. ## Usage ``` build.sh [arguments] ``` where `[arguments]` is a list of arguments that should be passed directly to Bazel (such as targets to build, or additional flags). The output of this script will be a Markdown-formatted consolidated report that shows the driver and frontend timings for the jobs that were invoked across _every_ Swift target in the build, with the slowest driver invocations at the top (and the slowest frontend invocations at the top within those groups). 07070100000071000081ED000003E800000064000000015D9E3463000009FE000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/tools/compile_stats/build.sh#!/bin/bash # # Copyright 2019 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. set -euo pipefail manifest="$(mktemp "${TMPDIR:-/tmp}/compile_stats_manifest.XXXXXX")" trap "rm -f $manifest" EXIT collect_stats_flags=( --features=swift.compile_stats --output_groups=swift_compile_stats --aspects=@build_bazel_rules_swift//swift:stats.bzl%collect_swift_compile_stats ) # Build the desired targets, with stderr being output as normal. bazel build "${collect_stats_flags[@]}" "$@" # Build the targets *again*, this time with `--experimental_show_artifacts`. # This should be a null build since we just built everything above. The reason # we split this is because the artifact output also goes to stderr, so we'd have # to either capture the whole thing or redirect it to `tee` with color/curses # support disabled, which would be difficult for the user to read. # # A human-readable explanation of the code below: # # 1. Build the requested targets while collecting the stats outputs. Use the # `--experimental_show_artifacts` flag to get a scrapeable dump of the output # files at the end. # 2. Pipe stderr into a `sed` command that ignores all lines before the line # "Build artifacts:", which signifies the beginning of the listing. # 3. Pipe that into a `sed` command that ignores any lines that don't start with # ">>>" and strips that prefix off the ones that do. This is the list of # stats directories that were created for each built target. # 4. Pass those directories into `find` to print just the filenames of the # contents of those directories. bazel build --experimental_show_artifacts "${collect_stats_flags[@]}" "$@" \ 2>&1 > /dev/null \ | sed -e '/Build artifacts:/,$!d' \ | sed -e 's/^>>>//' -e 't' -e 'd' \ | while read statsdir ; do find "$statsdir" -type f done > "$manifest" # Run the report generating tool. bazel run \ --apple_platform_type=macos \ @build_bazel_rules_swift//tools/compile_stats:stats_processor -- \ "$manifest" 07070100000072000081A4000003E800000064000000015D9E3463000022A6000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/tools/compile_stats/main.swift// Copyright 2019 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. import Foundation /// Encapsulates the wall, user, and sys clock times of a process's execution. struct Timing: Comparable { /// Total wall clock time. var wall: TimeInterval /// Amount of time spent in user-mode code. var user: TimeInterval /// Amount of time spent in kernel code. var sys: TimeInterval static func < (lhs: Timing, rhs: Timing) -> Bool { return lhs.wall < rhs.wall } /// Creates a new timing with the given values. init(wall: TimeInterval = 0, user: TimeInterval = 0, sys: TimeInterval = 0) { self.wall = wall self.user = user self.sys = sys } /// Gets or sets one of the clock values in this timing. /// /// - Parameter key: The timing to update. Must be `"wall"`, `"user"`, or `"sys"`. subscript(key: String) -> Double { get { return self[keyPath: keyPath(for: key)] } set { let keyPath = self.keyPath(for: key) self[keyPath: keyPath] = newValue } } /// Gets a keypath that can be used to get or set the given timing. /// /// - Precondition: `name` must be `"wall"`, `"user"`, or `"sys"`. private func keyPath(for name: String) -> WritableKeyPath<Timing, Double> { switch name { case "wall": return \.wall case "user": return \.user case "sys": return \.sys default: fatalError("Unknown timing '\(name)'") } } } /// Statistics about an invocation of the Swift frontend. struct FrontendStats { /// The name of the Swift module being compiled. let moduleName: String /// The source file being compiled, or `"all"` if the invocation involved multiple files. let sourceFile: String /// The start time of frontend invocation. let startTime: Date /// The timings of various tasks (such as type checking, code generation, etc.) that occurred /// during compilation. private(set) var taskTimings = [String: Timing]() /// The total timing of the frontend invocation. private(set) var frontendTiming = Timing() /// The timings of various tasks sorted such that the slowest ones are first. func sortedTaskTimings(interestingOnly: Bool) -> [(String, Timing)] { var allTimings = Array(taskTimings) if interestingOnly { allTimings = allTimings.filter { switch $0.0 { case "AST verification", "Name binding", "LLVM pipeline", "Parsing", "Serialization, swiftdoc", "Serialization, swiftmodule", "SILGen", "SIL optimization", "SIL verification, post-optimization", "SIL verification, pre-optimization", "Type checking and Semantic analysis": return true default: return false } } } allTimings.sort { $0.1.wall > $1.1.wall } return allTimings } /// Creates a new `FrontendStats` with information from the given JSON report. /// /// - Parameter url: A URL to the frontend report JSON file. /// - Throws: If there was an error reading or decoding the report. init(contentsOf url: URL) throws { let reportData = try Data(contentsOf: url) let jsonDictionary = try JSONSerialization.jsonObject(with: reportData) as! [String: Any] let pathParts = url.lastPathComponent.split(separator: "-") self.moduleName = String(pathParts[4]) self.sourceFile = String(pathParts[5]) self.startTime = Date(timeIntervalSince1970: TimeInterval(pathParts[1])! / 10e9) for (key, value) in jsonDictionary { let keyParts = key.split(separator: ".") if key.hasPrefix("time.swift.") { let category = String(keyParts[2]) let timingName = String(keyParts[3]) self.taskTimings[category, default: Timing()][timingName] = value as! Double } else if key.hasPrefix("time.swift-frontend.") { // The filename and target triple embedded in this string might contain dots, which screws // up our string splitting. Instead, we can just get the last component. let timingName = String(keyParts.last!) self.frontendTiming[timingName] = value as! Double } } } } /// Statistics about an invocation of the Swift compiler driver. struct DriverStats { /// The name of the Swift module being compiled. let moduleName: String /// The start time of the driver invocation. let startTime: Date /// The total timing of the driver invocation. private(set) var driverTiming = Timing() /// Creates a new `DriverStats` with information from the given JSON report. /// /// - Parameter url: A URL to the driver report JSON file. /// - Throws: If there was an error reading or decoding the report. init(contentsOf url: URL) throws { let reportData = try Data(contentsOf: url) let jsonDictionary = try JSONSerialization.jsonObject(with: reportData) as! [String: Any] let pathParts = url.lastPathComponent.split(separator: "-") self.moduleName = String(pathParts[4]) self.startTime = Date(timeIntervalSince1970: TimeInterval(pathParts[1])! / 10e9) for (key, value) in jsonDictionary { let keyParts = key.split(separator: ".") if key.hasPrefix("time.swift-driver.") { // The filename and target triple embedded in this string might contain dots, which screws // up our string splitting. Instead, we can just get the last component. let timingName = String(keyParts.last!) self.driverTiming[timingName] = value as! Double } } } } /// Returns a formatted string for the given time interval, appropriate for tabular output. func formattedSeconds(_ value: TimeInterval) -> String { return String(format: "%8.3fs", value) } /// Processes the reports described in the manifest file and outputs formatted tables to standard /// output. func processReports(fromManifest url: URL) throws { let manifestContents = try String(contentsOf: url).trimmingCharacters(in: .whitespacesAndNewlines) let reportPaths = manifestContents.split(separator: "\n") var allDriverStats = [DriverStats]() var allFrontendStats = [String: [FrontendStats]]() for reportPath in reportPaths.lazy.map(String.init) { let reportURL = URL(fileURLWithPath: reportPath) if reportPath.contains("swift-driver") { let stats = try DriverStats(contentsOf: reportURL) allDriverStats.append(stats) } else if reportPath.contains("swift-frontend") { let stats = try FrontendStats(contentsOf: reportURL) allFrontendStats[stats.moduleName, default: []].append(stats) } } // Sort the driver stats so that the slowest compiles come first. allDriverStats.sort { $0.driverTiming.wall > $1.driverTiming.wall } for driverStats in allDriverStats { let totalDriverTime = String(format: "%0.3fs", driverStats.driverTiming.wall) print("# Driver invocation for module \(driverStats.moduleName) (\(totalDriverTime))") print() guard var frontendStatsForModule = allFrontendStats[driverStats.moduleName] else { continue } frontendStatsForModule.sort { $0.frontendTiming.wall > $1.frontendTiming.wall } for frontendStats in frontendStatsForModule { let totalFrontendTime = String(format: "%0.3fs", frontendStats.frontendTiming.wall) print( """ ## Frontend invocation for \ \(frontendStats.moduleName)/\(frontendStats.sourceFile) \ (\(totalFrontendTime)) """) print() print("| Task | Wall | User | Sys |") print("| ----------------------------------- | --------- | --------- | --------- |") for (category, taskTiming) in frontendStats.sortedTaskTimings(interestingOnly: true) { let formattedCategory = category.padding(toLength: 35, withPad: " ", startingAt: 0) let formattedWall = formattedSeconds(taskTiming.wall) let formattedUser = formattedSeconds(taskTiming.user) let formattedSys = formattedSeconds(taskTiming.sys) print("| \(formattedCategory) | \(formattedWall) | \(formattedUser) | \(formattedSys) |") } print() } } } guard CommandLine.arguments.count == 2 else { print("USAGE: stats_processor <manifest file>") exit(1) } let manifestURL = URL(fileURLWithPath: CommandLine.arguments[1]) try processReports(fromManifest: manifestURL) 07070100000073000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002F00000000bazel-rules-swift-0.13.0/tools/dump_toolchains07070100000074000081A4000003E800000064000000015D9E34630000008E000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/tools/dump_toolchains/BUILDlicenses(["notice"]) sh_binary( name = "dump_toolchains", srcs = ["dump_toolchains.sh"], visibility = ["//visibility:public"], ) 07070100000075000081ED000003E800000064000000015D9E3463000004FD000000000000000000000000000000000000004200000000bazel-rules-swift-0.13.0/tools/dump_toolchains/dump_toolchains.sh#!/bin/bash # # Copyright 2019 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. set -euo pipefail if [[ "$(uname)" != Darwin ]]; then echo "error: dumping toolchains is only supported on macOS" exit 1 fi toolchain_directory=/Library/Developer/Toolchains if [[ ! -d "$toolchain_directory" ]]; then echo "error: '$toolchain_directory' doesn't exist" exit 1 fi for toolchain in "$toolchain_directory"/*.xctoolchain do plist_path="$toolchain/Info.plist" if [[ ! -f "$plist_path" ]]; then echo "error: '$toolchain' is missing Info.plist" exit 1 fi bundle_id=$(/usr/libexec/PlistBuddy -c "print :CFBundleIdentifier" "$plist_path") toolchain_name=$(basename "$toolchain") echo "$toolchain_name -> $bundle_id" done 07070100000076000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002D00000000bazel-rules-swift-0.13.0/tools/mkdir_and_run07070100000077000081A4000003E800000064000000015D9E34630000013D000000000000000000000000000000000000003300000000bazel-rules-swift-0.13.0/tools/mkdir_and_run/BUILDlicenses(["notice"]) sh_binary( name = "mkdir_and_run", srcs = ["mkdir_and_run.sh"], visibility = ["//visibility:public"], ) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]), visibility = [ "//tools:__pkg__", ], ) 07070100000078000081ED000003E800000064000000015D9E3463000004A4000000000000000000000000000000000000003E00000000bazel-rules-swift-0.13.0/tools/mkdir_and_run/mkdir_and_run.sh#!/bin/bash # # Copyright 2018 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. # SYNOPSIS # Ensures (deeply) that a directory exists and then executes another command. # # USAGE # mkdir_and_run.sh <directory_path> <executable> <arguments...> # # ARGUMENTS # directory_path: The path to the directory that should be created if it does # not already exist. # executable: The path to the executable to invoke. # arguments...: Arguments passed directly to the invoked command. set -eu if [[ $# -lt 2 ]] ; then echo "ERROR: Need at least two arguments." 1>&2 exit 1 fi mkdir -p "$1" shift exec "$@" # Should never get here. exit 2 07070100000079000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002600000000bazel-rules-swift-0.13.0/tools/worker0707010000007A000081A4000003E800000064000000015D9E3463000008DA000000000000000000000000000000000000002C00000000bazel-rules-swift-0.13.0/tools/worker/BUILDlicenses(["notice"]) # Workaround for the rules_apple integration tests to force the use of a # "worker" that isn't actually a worker but which simply spawns `swiftc` # directly, because some of the worker dependencies are too complex to # properly mock out in the test workspace. # # This flag is incompatible with the "worker" strategy for SwiftCompile # actions because it doesn't actually start a processing loop. It merely # provides an executable with isolated dependencies that can be more easily # built. config_setting( name = "no_worker", define_values = { "RULES_SWIFT_BUILD_DUMMY_WORKER": "1", }, ) cc_library( name = "compile_with_worker", srcs = [ "compile_with_worker.cc", "output_file_map.cc", "output_file_map.h", "work_processor.cc", "work_processor.h", ], hdrs = ["compile_with_worker.h"], deps = [ ":swift_runner", "//third_party/bazel_protos:worker_protocol_cc_proto", "//tools/common:file_system", "//tools/common:path_utils", "//tools/common:string_utils", "//tools/common:temp_file", "@com_github_nlohmann_json//:json", "@com_google_protobuf//:protobuf", ], ) cc_library( name = "compile_without_worker", srcs = ["compile_without_worker.cc"], hdrs = ["compile_without_worker.h"], deps = [ ":swift_runner", ], ) cc_library( name = "swift_runner", srcs = ["swift_runner.cc"], hdrs = ["swift_runner.h"], deps = [ "//tools/common:file_system", "//tools/common:process", "//tools/common:string_utils", "//tools/common:temp_file", ], ) cc_binary( name = "worker", srcs = select({ ":no_worker": ["no_worker_main.cc"], "//conditions:default": ["worker_main.cc"], }), visibility = ["//visibility:public"], deps = select({ ":no_worker": [":compile_without_worker"], "//conditions:default": [ ":compile_without_worker", ":compile_with_worker", ], }), ) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]), visibility = [ "//tools:__pkg__", ], ) 0707010000007B000081A4000003E800000064000000015D9E34630000156F000000000000000000000000000000000000003D00000000bazel-rules-swift-0.13.0/tools/worker/compile_with_worker.cc// Copyright 2019 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. #include "tools/worker/compile_with_worker.h" #include <unistd.h> #include <iostream> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/util/delimited_message_util.h> #include "third_party/bazel_protos/worker_protocol.pb.h" #include "tools/worker/work_processor.h" // How Swift Incremental Compilation Works // ======================================= // When a Swift module is compiled, the output file map (a JSON file mapping // source files to outputs) tells the compiler where to write the object (.o) // files and partial .swiftmodule files. For incremental mode to work, the // output file map must also contain "swift-dependencies" entries; these files // contain compiler-internal data that describes how the sources in the module // are interrelated. Once all of these outputs exist on the file system, future // invocations of the compiler will use them to detect which source files // actually need to be recompiled if any of them change. // // This compilation model doesn't interact well with Bazel, which expects builds // to be hermetic (not affected by each other). In other words, outputs of build // N are traditionally not available as inputs to build N+1; the action // declaration model does not allow this. // // One could disable the sandbox to hack around this, but this should not be a // requirement of a well-designed build rule implementation. // // Bazel provides "persistent workers" to address this. A persistent worker is a // long-running "server" that waits for requests, which it can then handle // in-process or by spawning other commands (we do the latter). The important // feature here is that this worker can manage a separate file store that allows // state to persist across multiple builds. // // However, there are still some caveats that we have to address: // // - The "SwiftCompile" actions registered by the build rules must declare the // object files and partial .swiftmodules as outputs, because later actions // need those files as inputs (e.g., archiving a static library or linking a // dynamic library or executable). // // - Because those files are declared action outputs, Bazel will delete them or // otherwise make them unavailable before the action executes, which destroys // our persistent state. // // - We could avoid declaring those individual outputs if we had the persistent // worker also link them, but this is infeasible: static archiving uses // platform-dependent logic and will eventually be migrated to actions from // the C++ toolchain, and linking a dynamic library or executable also uses // the C++ toolchain. Furthermore, we may want to stop propagating .a files // for linking and instead propagate the .o files directly, avoiding an // archiving step when it isn't explicitly requested. // // So to make this work, we redirect the compiler to write its outputs to an // alternate location that isn't declared by any Bazel action -- this prevents // the files from being deleted between builds so the compiler can find them. // (We still use a descendant of `bazel-bin` so that it *will* be removed by a // `bazel clean`, as the user would expect.) Then, after the compiler is done, // we copy those outputs into the locations where Bazel declared them, so that // it can find them as well. int CompileWithWorker(const std::vector<std::string> &args) { // Set up the input and output streams used to communicate with Bazel over // stdin and stdout. google::protobuf::io::FileInputStream file_input_stream(STDIN_FILENO); file_input_stream.SetCloseOnDelete(false); google::protobuf::io::FileOutputStream file_output_stream(STDOUT_FILENO); file_output_stream.SetCloseOnDelete(false); // Pass the "universal arguments" to the Swift work processor. They will be // rewritten to replace any placeholders if necessary, and then passed at the // beginning of any process invocation. Note that these arguments include the // tool itself (i.e., "swiftc"). WorkProcessor swift_worker(args); while (true) { blaze::worker::WorkRequest request; if (!google::protobuf::util::ParseDelimitedFromZeroCopyStream( &request, &file_input_stream, nullptr)) { std::cerr << "Could not read WorkRequest from stdin. Killing worker " << "process.\n"; return 254; } blaze::worker::WorkResponse response; swift_worker.ProcessWorkRequest(request, &response); if (!google::protobuf::util::SerializeDelimitedToZeroCopyStream( response, &file_output_stream)) { std::cerr << "Could not write WorkResponse to stdout. Killing worker " << "process.\n"; return 254; } // Flush stdout after writing to ensure that Bazel doesn't hang waiting for // the response due to buffering. file_output_stream.Flush(); } return 0; } 0707010000007C000081A4000003E800000064000000015D9E3463000003F6000000000000000000000000000000000000003C00000000bazel-rules-swift-0.13.0/tools/worker/compile_with_worker.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITH_WORKER_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITH_WORKER_H_ #include <string> #include <vector> // Starts the worker processing loop and listens to stdin for work requests from // Bazel. int CompileWithWorker(const std::vector<std::string> &args); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITH_WORKER_H_ 0707010000007D000081A4000003E800000064000000015D9E346300000386000000000000000000000000000000000000004000000000bazel-rules-swift-0.13.0/tools/worker/compile_without_worker.cc// Copyright 2019 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. #include "tools/worker/compile_without_worker.h" #include <iostream> #include <string> #include <vector> #include "tools/worker/swift_runner.h" int CompileWithoutWorker(const std::vector<std::string> &args) { return SwiftRunner(args).Run(&std::cerr, /*stdout_to_stderr=*/false); } 0707010000007E000081A4000003E800000064000000015D9E34630000040E000000000000000000000000000000000000003F00000000bazel-rules-swift-0.13.0/tools/worker/compile_without_worker.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITHOUT_WORKER_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITHOUT_WORKER_H_ #include <string> #include <vector> // Directly invokes the Swift compiler and exits, without performing any // worker-related processing. int CompileWithoutWorker(const std::vector<std::string> &args); #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_COMPILE_WITHOUT_WORKER_H_ 0707010000007F000081A4000003E800000064000000015D9E346300000334000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/tools/worker/no_worker_main.cc// Copyright 2019 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. #include <string> #include <vector> #include "tools/worker/compile_without_worker.h" int main(int argc, char *argv[]) { return CompileWithoutWorker(std::vector<std::string>(argv + 1, argv + argc)); } 07070100000080000081A4000003E800000064000000015D9E34630000105E000000000000000000000000000000000000003900000000bazel-rules-swift-0.13.0/tools/worker/output_file_map.cc// Copyright 2019 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. #include "tools/worker/output_file_map.h" #include <fstream> #include <iostream> #include <map> #include <string> #include "tools/common/path_utils.h" #include <nlohmann/json.hpp> namespace { // Returns the given path transformed to point to the incremental storage area. // For example, "bazel-out/config/{genfiles,bin}/path" becomes // "bazel-out/config/{genfiles,bin}/_swift_incremental/path". static std::string MakeIncrementalOutputPath(std::string path) { auto bin_index = path.find("/bin/"); if (bin_index != std::string::npos) { path.replace(bin_index, 5, "/bin/_swift_incremental/"); return path; } auto genfiles_index = path.find("/genfiles/"); if (genfiles_index != std::string::npos) { path.replace(genfiles_index, 10, "/genfiles/_swift_incremental/"); return path; } return path; } }; // end namespace void OutputFileMap::ReadFromPath(const std::string &path) { std::ifstream stream(path); stream >> json_; UpdateForIncremental(); } void OutputFileMap::WriteToPath(const std::string &path) { std::ofstream stream(path); stream << json_; } void OutputFileMap::UpdateForIncremental() { nlohmann::json new_output_file_map; std::map<std::string, std::string> incremental_outputs; for (auto &element : json_.items()) { auto src = element.key(); auto outputs = element.value(); // The empty string key is used to represent outputs that are for the whole // module, rather than for a particular source file. if (src.empty()) { nlohmann::json empty_map = outputs; auto path = outputs["swift-dependencies"].get<std::string>(); auto new_path = MakeIncrementalOutputPath(path); empty_map["swift-dependencies"] = new_path; incremental_outputs[path] = new_path; new_output_file_map[""] = empty_map; continue; } nlohmann::json src_map; // Process the outputs for the current source file. for (auto &output : outputs.items()) { auto kind = output.key(); auto path = output.value().get<std::string>(); if (kind == "object") { // If the file kind is "object", we want to update the path to point to // the incremental storage area and then add a "swift-dependencies" // in the same location. auto new_path = MakeIncrementalOutputPath(path); src_map[kind] = new_path; incremental_outputs[path] = new_path; auto swiftdeps_path = ReplaceExtension(new_path, ".swiftdeps"); src_map["swift-dependencies"] = swiftdeps_path; } else if (kind == "swiftdoc" || kind == "swiftinterface" || kind == "swiftmodule") { // Module/interface outputs should be moved to the incremental storage // area without additional processing. auto new_path = MakeIncrementalOutputPath(path); src_map[kind] = new_path; incremental_outputs[path] = new_path; } else if (kind == "swift-dependencies") { // If there was already a "swift-dependencies" entry present, ignore it. // (This shouldn't happen because the build rules won't do this, but // check just in case.) std::cerr << "There was a 'swift-dependencies' entry for " << src << ", but the build rules should not have done this; " << "ignoring it.\n"; } else { // Otherwise, just copy the mapping over verbatim. src_map[kind] = path; } } new_output_file_map[src] = src_map; } json_ = new_output_file_map; incremental_outputs_ = incremental_outputs; } 07070100000081000081A4000003E800000064000000015D9E346300000892000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/tools/worker/output_file_map.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_OUTPUT_FILE_MAP_H #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_OUTPUT_FILE_MAP_H #include <map> #include <string> #include <nlohmann/json.hpp> // Supports loading and rewriting a `swiftc` output file map to support // incremental compilation. // // See // https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps // for more information on how the Swift driver uses this file. class OutputFileMap { public: explicit OutputFileMap() {} // The in-memory JSON-based representation of the output file map. const nlohmann::json &json() const { return json_; } // A map containing expected output files that will be generated in the // incremental storage area. The key is the original object path; the // corresponding value is its location in the incremental storage area. const std::map<std::string, std::string> incremental_outputs() const { return incremental_outputs_; } // Reads the output file map from the JSON file at the given path, and updates // it to support incremental builds. void ReadFromPath(const std::string &path); // Writes the output file map as JSON to the file at the given path. void WriteToPath(const std::string &path); private: // Modifies the output file map's JSON structure in-place to replace file // paths with equivalents in the incremental storage area. void UpdateForIncremental(); nlohmann::json json_; std::map<std::string, std::string> incremental_outputs_; }; #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_OUTPUT_FILE_MAP_H_ 07070100000082000081A4000003E800000064000000015D9E346300001FE8000000000000000000000000000000000000003600000000bazel-rules-swift-0.13.0/tools/worker/swift_runner.cc// Copyright 2019 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. #include "tools/worker/swift_runner.h" #include <fstream> #include "tools/common/file_system.h" #include "tools/common/process.h" #include "tools/common/string_utils.h" #include "tools/common/temp_file.h" namespace { #if __APPLE__ // Returns the requested environment variable in the current process's // environment. Aborts if this variable is unset. static std::string GetMandatoryEnvVar(const std::string &var_name) { char *env_value = getenv(var_name.c_str()); if (env_value == nullptr) { std::cerr << "Error: " << var_name << " not set.\n"; abort(); } return env_value; } #endif // Creates a temporary file and writes the given arguments to it, one per line. static std::unique_ptr<TempFile> WriteResponseFile( const std::vector<std::string> &args) { auto response_file = TempFile::Create("swiftc_params.XXXXXX"); std::ofstream response_file_stream(response_file->GetPath()); for (auto arg : args) { // When Clang/Swift write out a response file to communicate from driver to // frontend, they just quote every argument to be safe; we duplicate that // instead of trying to be "smarter" and only quoting when necessary. response_file_stream << '"'; for (auto ch : arg) { if (ch == '"' || ch == '\\') { response_file_stream << '\\'; } response_file_stream << ch; } response_file_stream << "\"\n"; } response_file_stream.close(); return response_file; } // Unescape and unquote an argument read from a line of a response file. static std::string Unescape(const std::string &arg) { std::string result; auto length = arg.size(); for (size_t i = 0; i < length; ++i) { auto ch = arg[i]; // If it's a backslash, consume it and append the character that follows. if (ch == '\\' && i + 1 < length) { ++i; result.push_back(arg[i]); continue; } // If it's a quote, process everything up to the matching quote, unescaping // backslashed characters as needed. if (ch == '"' || ch == '\'') { auto quote = ch; ++i; while (i != length && arg[i] != quote) { if (arg[i] == '\\' && i + 1 < length) { ++i; } result.push_back(arg[i]); ++i; } if (i == length) { break; } continue; } // It's a regular character. result.push_back(ch); } return result; } } // namespace SwiftRunner::SwiftRunner(const std::vector<std::string> &args, bool force_response_file) : force_response_file_(force_response_file) { #if __APPLE__ // On Apple platforms, replace the magic Bazel placeholders with the path // in the corresponding environment variable. std::string developer_dir = GetMandatoryEnvVar("DEVELOPER_DIR"); std::string sdk_root = GetMandatoryEnvVar("SDKROOT"); bazel_placeholder_substitutions_ = { {"__BAZEL_XCODE_DEVELOPER_DIR__", developer_dir}, {"__BAZEL_XCODE_SDKROOT__", sdk_root}, }; #else // We don't have these placeholder strings on non-Apple platforms. #endif args_ = ProcessArguments(args); } int SwiftRunner::Run(std::ostream *stderr_stream, bool stdout_to_stderr) { int exit_code = RunSubProcess(args_, stderr_stream, stdout_to_stderr); return exit_code; } bool SwiftRunner::ProcessPossibleResponseFile( const std::string &arg, std::function<void(const std::string &)> consumer) { auto path = arg.substr(1); std::ifstream original_file(path); // If we couldn't open it, maybe it's not a file; maybe it's just some other // argument that starts with "@". (Unlikely, but it's safer to check.) if (!original_file.good()) { consumer(arg); return false; } // If we're forcing response files, process and send the arguments from this // file directly to the consumer; they'll all get written to the same response // file at the end of processing all the arguments. if (force_response_file_) { std::string arg_from_file; while (std::getline(original_file, arg_from_file)) { // Arguments in response files might be quoted/escaped, so we need to // unescape them ourselves. ProcessArgument(Unescape(arg_from_file), consumer); } return true; } // Otherwise, open the file, process the arguments, and rewrite it if any of // them have changed. bool changed = false; std::string arg_from_file; std::vector<std::string> new_args; while (std::getline(original_file, arg_from_file)) { changed |= ProcessArgument(arg_from_file, [&](const std::string &processed_arg) { new_args.push_back(processed_arg); }); } if (changed) { auto new_file = WriteResponseFile(new_args); consumer("@" + new_file->GetPath()); temp_files_.push_back(std::move(new_file)); } else { // If none of the arguments changed, just keep the original response file // argument. consumer(arg); } return changed; } bool SwiftRunner::ProcessArgument( const std::string &arg, std::function<void(const std::string &)> consumer) { bool changed = false; if (arg[0] == '@') { changed = ProcessPossibleResponseFile(arg, consumer); } else if (arg == "-Xwrapped-swift=-debug-prefix-pwd-is-dot") { // Get the actual current working directory (the workspace root), which we // didn't know at analysis time. consumer("-debug-prefix-map"); consumer(GetCurrentDirectory() + "=."); changed = true; } else if (arg == "-Xwrapped-swift=-ephemeral-module-cache") { // Create a temporary directory to hold the module cache, which will be // deleted after compilation is finished. auto module_cache_dir = TempDirectory::Create("swift_module_cache.XXXXXX"); consumer("-module-cache-path"); consumer(module_cache_dir->GetPath()); temp_directories_.push_back(std::move(module_cache_dir)); changed = true; } else if (arg.find("-Xwrapped-swift=") == 0) { // TODO(allevato): Report that an unknown wrapper arg was found and give the // caller a way to exit gracefully. changed = true; } else { // Apply any other text substitutions needed in the argument (i.e., for // Apple toolchains). auto new_arg = arg; changed = MakeSubstitutions(&new_arg, bazel_placeholder_substitutions_); consumer(new_arg); } return changed; } std::vector<std::string> SwiftRunner::ProcessArguments( const std::vector<std::string> &args) { std::vector<std::string> new_args; std::vector<std::string> response_file_args; #if __APPLE__ // On Apple platforms, inject `/usr/bin/xcrun` in front of our command // invocation. new_args.push_back("/usr/bin/xcrun"); #endif // The tool is assumed to be the first argument. Push it directly. auto it = args.begin(); new_args.push_back(*it++); // If we're forcing response files, push the remaining processed args onto a // different vector that we write out below. If not, push them directly onto // the vector being returned. auto &args_destination = force_response_file_ ? response_file_args : new_args; while (it != args.end()) { ProcessArgument( *it, [&](const std::string &arg) { args_destination.push_back(arg); }); ++it; } if (force_response_file_) { // Write the processed args to the response file, and push the path to that // file (preceded by '@') onto the arg list being returned. auto new_file = WriteResponseFile(response_file_args); new_args.push_back("@" + new_file->GetPath()); temp_files_.push_back(std::move(new_file)); } return new_args; } 07070100000083000081A4000003E800000064000000015D9E346300001807000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/tools/worker/swift_runner.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_SWIFT_RUNNER_H_ #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_SWIFT_RUNNER_H_ #include <functional> #include <iostream> #include <map> #include <memory> #include <string> #include <vector> #include "tools/common/temp_file.h" // Handles spawning the Swift compiler driver, making any required substitutions // of the command line arguments (for example, Bazel's magic Xcode placeholder // strings). // // The first argument in the list passed to the spawner should be the Swift // tool that should be invoked (for example, "swiftc"). This spawner also // recognizes special arguments of the form `-Xwrapped-swift=<arg>`. Arguments // of this form are consumed entirely by this wrapper and are not passed down to // the Swift tool (however, they may add normal arguments that will be passed). // // The following spawner-specific arguments are supported: // // -Xwrapped-swift=-debug-prefix-pwd-is-dot // When specified, the Swift compiler will be directed to remap the current // directory's path to the string "." in debug info. This remapping must be // applied here because we do not know the current working directory at // analysis time when the argument list is constructed. // // -Xwrapped-swift=-ephemeral-module-cache // When specified, the spawner will create a new temporary directory, pass // that to the Swift compiler using `-module-cache-path`, and then delete // the directory afterwards. This should resolve issues where the module // cache state is not refreshed correctly in all situations, which // sometimes results in hard-to-diagnose crashes in `swiftc`. class SwiftRunner { public: // Create a new spawner that launches a Swift tool with the given arguments. // The first argument is assumed to be that tool. If force_response_file is // true, then the remaining arguments will be unconditionally written into a // response file instead of being passed on the command line. SwiftRunner(const std::vector<std::string> &args, bool force_response_file = false); // Run the Swift compiler, redirecting stderr to the specified stream. If // stdout_to_stderr is true, then stdout is also redirected to that stream. int Run(std::ostream *stderr_stream, bool stdout_to_stderr = false); private: // Processes an argument that looks like it might be a response file (i.e., it // begins with '@') and returns true if the argument(s) passed to the consumer // were different than "arg"). // // If the argument is not actually a response file (i.e., it begins with '@' // but the file cannot be read), then it is passed directly to the consumer // and this method returns false. Otherwise, if the response file could be // read, this method's behavior depends on a few factors: // // - If the spawner is forcing response files, then the arguments in this // response file are read and processed and sent directly to the consumer. // In other words, they will be rewritten into that new response file // directly, rather than being kept in their own separate response file. // This is because there is no reason to maintain the original and multiple // response files at this stage of processing. In this case, the function // returns true. // // - If the spawner is not forcing response files, then the arguments in this // response file are read and processed. If none of the arguments changed, // then this function passes the original response file argument to the // consumer and returns false. If some arguments did change, then they are // written to a new response file, a response file argument pointing to that // file is passed to the consumer, and the method returns true. bool ProcessPossibleResponseFile( const std::string &arg, std::function<void(const std::string &)> consumer); // Applies substitutions for a single argument and passes the new arguments // (or the original, if no substitution was needed) to the consumer. Returns // true if any substitutions were made (that is, if the arguments passed to // the consumer were anything different than "arg"). // // This method has file system side effects, creating temporary files and // directories as needed for a particular substitution. bool ProcessArgument(const std::string &arg, std::function<void(const std::string &)> consumer); // Applies substitutions to the given command line arguments, returning the // results in a new vector. std::vector<std::string> ProcessArguments( const std::vector<std::string> &args); // A mapping of Bazel placeholder strings to the actual paths that should be // substituted for them. Supports Xcode resolution on Apple OSes. std::map<std::string, std::string> bazel_placeholder_substitutions_; // The arguments, post-substitution, passed to the spawner. std::vector<std::string> args_; // Temporary files (e.g., rewritten response files) that should be cleaned up // after the driver has terminated. std::vector<std::unique_ptr<TempFile>> temp_files_; // Temporary directories (e.g., ephemeral module cache) that should be cleaned // up after the driver has terminated. std::vector<std::unique_ptr<TempDirectory>> temp_directories_; // Arguments will be unconditionally written into a response file and passed // to the tool that way. bool force_response_file_; }; #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_SWIFT_RUNNER_H_ 07070100000084000081A4000003E800000064000000015D9E3463000014B3000000000000000000000000000000000000003800000000bazel-rules-swift-0.13.0/tools/worker/work_processor.cc// Copyright 2019 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. #include "tools/worker/work_processor.h" #include <sys/stat.h> #include <fstream> #include <map> #include <sstream> #include <string> #include <google/protobuf/text_format.h> #include "tools/common/file_system.h" #include "tools/common/path_utils.h" #include "tools/common/string_utils.h" #include "tools/common/temp_file.h" #include "tools/worker/output_file_map.h" #include "tools/worker/swift_runner.h" #include <nlohmann/json.hpp> namespace { // Returns true if the given command line argument enables whole-module // optimization in the compiler. static bool ArgumentEnablesWMO(const std::string &arg) { return arg == "-wmo" || arg == "-whole-module-optimization" || arg == "-force-single-frontend-invocation"; } }; // end namespace WorkProcessor::WorkProcessor(const std::vector<std::string> &args) { universal_args_.insert(universal_args_.end(), args.begin(), args.end()); } void WorkProcessor::ProcessWorkRequest( const blaze::worker::WorkRequest &request, blaze::worker::WorkResponse *response) { std::vector<std::string> processed_args(universal_args_); // Bazel's worker spawning strategy reads the arguments from the params file // and inserts them into the proto. This means that if we just try to pass // them verbatim to swiftc, we might end up with a command line that's too // long. Rather than try to figure out these limits (which is very // OS-specific and easy to get wrong), we unconditionally write the processed // arguments out to a params file. auto params_file = TempFile::Create("swiftc_params.XXXXXX"); std::ofstream params_file_stream(params_file->GetPath()); OutputFileMap output_file_map; std::string output_file_map_path; bool is_wmo = false; std::string prev_arg; for (auto arg : request.arguments()) { auto original_arg = arg; // Peel off the `-output-file-map` argument, so we can rewrite it if // necessary later. if (arg == "-output-file-map") { arg.clear(); } else if (prev_arg == "-output-file-map") { output_file_map_path = arg; output_file_map.ReadFromPath(output_file_map_path); arg.clear(); } else if (ArgumentEnablesWMO(arg)) { is_wmo = true; } if (!arg.empty()) { params_file_stream << arg << '\n'; } prev_arg = original_arg; } if (!output_file_map_path.empty()) { if (!is_wmo) { // Rewrite the output file map to use the incremental storage area and // pass the compiler the path to the rewritten file. auto new_path = ReplaceExtension(output_file_map_path, ".incremental.json"); output_file_map.WriteToPath(new_path); params_file_stream << "-output-file-map\n"; params_file_stream << new_path << '\n'; // Pass the incremental flags only if WMO is disabled. WMO would overrule // incremental mode anyway, but since we control the passing of this flag, // there's no reason to pass it when it's a no-op. params_file_stream << "-incremental\n"; } else { // If WMO is forcing us out of incremental mode, just put the original // output file map back so the outputs end up where they should. params_file_stream << "-output-file-map\n"; params_file_stream << output_file_map_path << '\n'; } } processed_args.push_back("@" + params_file->GetPath()); params_file_stream.close(); if (!is_wmo) { for (auto expected_object_pair : output_file_map.incremental_outputs()) { // Bazel creates the intermediate directories for the files declared at // analysis time, but we need to manually create the ones for the // incremental storage area. auto dir_path = Dirname(expected_object_pair.second); if (!MakeDirs(dir_path, S_IRWXU)) { std::cerr << "Could not create directory " << dir_path << " (errno " << errno << ")\n"; } } } std::ostringstream stderr_stream; SwiftRunner swift_runner(processed_args, /*force_response_file=*/true); int exit_code = swift_runner.Run(&stderr_stream, /*stdout_to_stderr=*/true); if (!is_wmo) { // Copy the output files from the incremental storage area back to the // locations where Bazel declared the files. for (auto expected_object_pair : output_file_map.incremental_outputs()) { if (!CopyFile(expected_object_pair.second, expected_object_pair.first)) { std::cerr << "Could not copy " << expected_object_pair.second << " to " << expected_object_pair.first << " (errno " << errno << ")\n"; exit_code = EXIT_FAILURE; } } } response->set_exit_code(exit_code); response->set_output(stderr_stream.str()); } 07070100000085000081A4000003E800000064000000015D9E3463000005EF000000000000000000000000000000000000003700000000bazel-rules-swift-0.13.0/tools/worker/work_processor.h// Copyright 2019 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. #ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_WORK_PROCESSOR_H #define BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_WORK_PROCESSOR_H #include <map> #include <string> #include <vector> #include "third_party/bazel_protos/worker_protocol.pb.h" // Manages persistent global state for the Swift worker and processes individual // work requests. class WorkProcessor { public: // Initializes a new work processor with the given universal arguments from // the job invocation. WorkProcessor(const std::vector<std::string> &args); // Processes the given work request and writes its exit code and stderr output // (if any) into the given response. void ProcessWorkRequest(const blaze::worker::WorkRequest &request, blaze::worker::WorkResponse *response); private: std::vector<std::string> universal_args_; }; #endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_WORKER_WORK_PROCESSOR_H 07070100000086000081A4000003E800000064000000015D9E346300000607000000000000000000000000000000000000003500000000bazel-rules-swift-0.13.0/tools/worker/worker_main.cc// Copyright 2019 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. #include <algorithm> #include <iostream> #include <string> #include <vector> #include "tools/worker/compile_with_worker.h" #include "tools/worker/compile_without_worker.h" int main(int argc, char *argv[]) { auto args = std::vector<std::string>(argv + 1, argv + argc); // When Bazel invokes a tool in persistent worker mode, it includes the flag // "--persistent_worker" on the command line (typically the first argument, // but we don't want to rely on that). Since this "worker" tool also supports // a non-worker mode, we can detect the mode based on the presence of this // flag. auto persistent_worker_it = std::find(args.begin(), args.end(), "--persistent_worker"); if (persistent_worker_it == args.end()) { return CompileWithoutWorker(args); } // Remove the special flag before starting the worker processing loop. args.erase(persistent_worker_it); return CompileWithWorker(args); } 07070100000087000041ED000003E800000064000000025D9E346300000000000000000000000000000000000000000000002D00000000bazel-rules-swift-0.13.0/tools/xctest_runner07070100000088000081A4000003E800000064000000015D9E34630000014F000000000000000000000000000000000000003300000000bazel-rules-swift-0.13.0/tools/xctest_runner/BUILDlicenses(["notice"]) filegroup( name = "xctest_runner_template", srcs = ["xctest_runner.sh.template"], visibility = ["//visibility:public"], ) # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", testonly = 1, srcs = glob(["**"]), visibility = [ "//tools:__pkg__", ], ) 07070100000089000081A4000003E800000064000000015D9E346300000566000000000000000000000000000000000000004700000000bazel-rules-swift-0.13.0/tools/xctest_runner/xctest_runner.sh.template#!/usr/bin/env bash # # Copyright 2018 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. set -eu # This test script is used as the executable output of a `swift_test` rule when # building macOS targets (unless the "swift.bundled_tests" feature is disabled) # because the test binary is an `MH_BUNDLE` that needs to be loaded dynamically # and runtime reflection is used to locate the test methods. # Create the .xctest bundle and copy the binary into it (a requirement of the # `xctest` tool). BINARY="$TEST_SRCDIR/$TEST_WORKSPACE/%binary%" BUNDLE_DIR="$(dirname "$BINARY")/$(basename "$BINARY").xctest" mkdir -p "$BUNDLE_DIR/Contents/MacOS" ln -sf "$BINARY" "$BUNDLE_DIR/Contents/MacOS/" # TODO(allevato): Support Bazel's --test_filter. exec xcrun xctest -XCTest All "$BUNDLE_DIR" # We should never make it here unless `exec` failed. exit 2 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!1052 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor