diff --git a/apple/internal/aspects/docc_archive_aspect.bzl b/apple/internal/aspects/docc_archive_aspect.bzl index 78288047d3..d47b92ea04 100644 --- a/apple/internal/aspects/docc_archive_aspect.bzl +++ b/apple/internal/aspects/docc_archive_aspect.bzl @@ -40,18 +40,28 @@ def _swift_symbol_graphs(*, swift_symbol_graph_info): def _first_docc_bundle(*, target, ctx): """Returns the first .docc bundle for the target or its deps by looking in it's data.""" - docc_bundles = [] + docc_bundle_paths = {} # Find the path to the .docc directory if it exists. for data_target in ctx.rule.attr.data: for file in data_target.files.to_list(): - if file.extension == "docc": - docc_bundles.append(file) - - if len(docc_bundles) > 1: + components = file.short_path.split("/") + for index, component in enumerate(components): + if component.endswith(".docc"): + docc_bundle_path = "/".join(components[0:index + 1]) + docc_bundle_files = docc_bundle_paths[docc_bundle_path] if docc_bundle_path in docc_bundle_paths else [] + docc_bundle_files.append(file) + docc_bundle_paths[docc_bundle_path] = docc_bundle_files + break + + # Validate the docc bundle, if any. + if len(docc_bundle_paths) > 1: fail("Expected target %s to have at most one .docc bundle in its data" % target.label) + if len(docc_bundle_paths) == 0: + return None, [] - return docc_bundles[0] if docc_bundles else None + # Return the docc bundle path and files: + return docc_bundle_paths.items()[0] def _docc_symbol_graphs_aspect_impl(target, ctx): """Creates a DocCSymbolGraphsInfo provider for targets which have a SwiftInfo provider (or which bundle a target that does).""" @@ -76,18 +86,23 @@ def _docc_symbol_graphs_aspect_impl(target, ctx): if not symbol_graphs: return [] - return [DocCSymbolGraphsInfo(symbol_graphs = symbol_graphs)] + return [DocCSymbolGraphsInfo(symbol_graphs = depset(symbol_graphs))] def _docc_bundle_info_aspect_impl(target, ctx): """Creates a DocCBundleInfo provider for targets which have a .docc bundle (or which bundle a target that does)""" if hasattr(ctx.rule.attr, "data"): - first_docc_bundle = _first_docc_bundle( + docc_bundle, docc_bundle_files = _first_docc_bundle( target = target, ctx = ctx, ) - if first_docc_bundle: - return [DocCBundleInfo(bundle = first_docc_bundle)] + if docc_bundle: + return [ + DocCBundleInfo( + bundle = docc_bundle, + bundle_files = docc_bundle_files, + ), + ] if hasattr(ctx.rule.attr, "deps"): # If this target has "deps", try to find a DocCBundleInfo provider in its deps. for dep in ctx.rule.attr.deps: diff --git a/apple/internal/docc.bzl b/apple/internal/docc.bzl index 4be96b7142..46633619cb 100644 --- a/apple/internal/docc.bzl +++ b/apple/internal/docc.bzl @@ -66,6 +66,8 @@ def _docc_archive_impl(ctx): if not symbol_graphs_info and not docc_bundle_info: fail("At least one of DocCSymbolGraphsInfo or DocCBundleInfo must be provided for target %s" % ctx.attr.name) + symbol_graphs = symbol_graphs_info.symbol_graphs.to_list() if symbol_graphs_info else [] + if ctx.attr.name.endswith(".doccarchive"): doccarchive_dir = ctx.actions.declare_directory(ctx.attr.name) else: @@ -75,7 +77,6 @@ def _docc_archive_impl(ctx): arguments = ctx.actions.args() arguments.add("docc") arguments.add("convert") - arguments.add("--index") arguments.add("--fallback-display-name", fallback_display_name) arguments.add("--fallback-bundle-identifier", fallback_bundle_identifier) arguments.add("--fallback-bundle-version", fallback_bundle_version) @@ -98,11 +99,11 @@ def _docc_archive_impl(ctx): # Add symbol graphs if symbol_graphs_info: arguments.add_all( - symbol_graphs_info.symbol_graphs, + symbol_graphs, before_each = "--additional-symbol-graph-dir", expand_directories = False, ) - docc_build_inputs.extend(symbol_graphs_info.symbol_graphs) + docc_build_inputs.extend(symbol_graphs) # The .docc bundle (if provided, only one is allowed) if docc_bundle_info: @@ -111,7 +112,7 @@ def _docc_archive_impl(ctx): # TODO: no-sandbox seems to be required when running docc convert with a .docc bundle provided # in the sandbox the tool is unable to open the .docc bundle. execution_requirements["no-sandbox"] = "1" - docc_build_inputs.append(docc_bundle_info.bundle) + docc_build_inputs.extend(docc_bundle_info.bundle_files) apple_support.run( ctx, @@ -130,13 +131,13 @@ def _docc_archive_impl(ctx): output = preview_script, template = ctx.file._preview_template, substitutions = { - "{docc_bundle}": docc_bundle_info.bundle.path if docc_bundle_info else "", + "{docc_bundle}": docc_bundle_info.bundle if docc_bundle_info else "", "{fallback_bundle_identifier}": fallback_bundle_identifier, "{fallback_bundle_version}": str(fallback_bundle_version), "{fallback_display_name}": fallback_display_name, "{platform}": platform.name_in_plist, "{sdk_version}": str(xcode_config.sdk_version_for_platform(platform)), - "{symbol_graph_dirs}": ",".join([f.path for f in symbol_graphs_info.symbol_graphs]) if symbol_graphs_info else "", + "{symbol_graph_dirs}": " ".join([f.path for f in symbol_graphs]) if symbol_graphs else "", "{target_name}": ctx.attr.name, "{xcode_version}": str(xcode_config.xcode_version()), }, @@ -154,7 +155,9 @@ def _docc_archive_impl(ctx): DefaultInfo( files = depset([doccarchive_dir]), executable = preview_script, - runfiles = ctx.runfiles(files = [preview_script] + docc_build_inputs), + runfiles = ctx.runfiles(files = [ + preview_script, + ] + docc_build_inputs), ), doccarchive_binary_info, ] diff --git a/apple/internal/templates/docc_preview.template.sh b/apple/internal/templates/docc_preview.template.sh index f8a64bda60..981af14e11 100644 --- a/apple/internal/templates/docc_preview.template.sh +++ b/apple/internal/templates/docc_preview.template.sh @@ -14,25 +14,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -euo pipefail +set -exuo pipefail -if [ ! -d "{docc_bundle}" ]; then - echo "ERROR: Expected a .docc directory bundle for target: {target_name}" - echo "Previewing requires a .docc bundle to be provided in the target's resources." - exit 1 +# Collect templated variables +additional_symbol_graph_dirs=({symbol_graph_dirs}) +docc_bundle_path="{docc_bundle}" +fallback_bundle_identifier="{fallback_bundle_identifier}" +fallback_bundle_version="{fallback_bundle_version}" +fallback_display_name="{fallback_display_name}" +platform="{platform}" +sdk_version="{sdk_version}" +xcode_version="{xcode_version}" + +arguments=() +output_dir="$(mktemp -d)" + +# Add all symbol graph directories to the arguments +for additional_symbol_graph_dir in "${additional_symbol_graph_dirs[@]}"; do + arguments+=("--additional-symbol-graph-dir" "$additional_symbol_graph_dir") +done + +# Add the docc bundle path to the arguments +if [ -d "$docc_bundle_path" ]; then + arguments+=("$docc_bundle_path") fi +# Preview the docc archive cd "$BUILD_WORKSPACE_DIRECTORY" - env -i \ - APPLE_SDK_PLATFORM="{platform}" \ - APPLE_SDK_VERSION_OVERRIDE="{sdk_version}" \ - XCODE_VERSION_OVERRIDE="{xcode_version}" \ + APPLE_SDK_PLATFORM="$platform" \ + APPLE_SDK_VERSION_OVERRIDE="$sdk_version" \ + XCODE_VERSION_OVERRIDE="$xcode_version" \ /usr/bin/xcrun docc preview \ - --index \ - --fallback-display-name "{fallback_display_name}" \ - --fallback-bundle-identifier "{fallback_bundle_identifier}" \ - --fallback-bundle-version "{fallback_bundle_version}" \ - --additional-symbol-graph-dir "{symbol_graph_dirs}" \ - --output-dir "$(mktemp -d)" \ - "{docc_bundle}" + --fallback-display-name "$fallback_display_name" \ + --fallback-bundle-identifier "$fallback_bundle_identifier" \ + --fallback-bundle-version "$fallback_bundle_version" \ + --output-dir "$output_dir" \ + "${arguments[@]:-}" diff --git a/apple/providers.bzl b/apple/providers.bzl index c74a916751..3d14a33e9d 100644 --- a/apple/providers.bzl +++ b/apple/providers.bzl @@ -245,12 +245,13 @@ DocCBundleInfo = provider( doc = "Provides general information about a .docc bundle.", fields = { "bundle": "the path to the .docc bundle", + "bundle_files": "the file targets contained within the .docc bundle", }, ) DocCSymbolGraphsInfo = provider( doc = "Provides the symbol graphs required to archive a .docc bundle.", fields = { - "symbol_graphs": "the paths to the symbol graphs", + "symbol_graphs": "the depset of paths to the symbol graphs", }, ) diff --git a/doc/providers.md b/doc/providers.md index 9deae5e3f5..b398d6d791 100644 --- a/doc/providers.md +++ b/doc/providers.md @@ -472,7 +472,7 @@ requirement. ## DocCBundleInfo
-DocCBundleInfo(bundle)
+DocCBundleInfo(bundle, bundle_files)
 
Provides general information about a .docc bundle. @@ -483,6 +483,7 @@ Provides general information about a .docc bundle. | Name | Description | | :------------- | :------------- | | bundle | the path to the .docc bundle | +| bundle_files | the file targets contained within the .docc bundle | @@ -500,7 +501,7 @@ Provides the symbol graphs required to archive a .docc bundle. | Name | Description | | :------------- | :------------- | -| symbol_graphs | the paths to the symbol graphs | +| symbol_graphs | the depset of paths to the symbol graphs | diff --git a/test/BUILD b/test/BUILD index 5ae82c044f..6d5aeb0076 100644 --- a/test/BUILD +++ b/test/BUILD @@ -260,3 +260,8 @@ apple_shell_test( "//test/testdata/resources:resource_data_deps_platform_independent", ], ) + +# apple_shell_test( +# name = "docc_archive_test", +# src = "docc_archive_test.sh", +# ) diff --git a/test/docc_archive_test.sh b/test/docc_archive_test.sh new file mode 100644 index 0000000000..d1b6d1397e --- /dev/null +++ b/test/docc_archive_test.sh @@ -0,0 +1,145 @@ +#!/bin/bash + +# Copyright 2024 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. + +# Integration tests for testing `docc_archive` rules. + +set -euo pipefail + +function set_up() { + mkdir -p app +} + +function tear_down() { + rm -rf app +} + +function create_common_files() { + cat > app/BUILD < app/App.swift < app/shared.swift < app/bundle.swift < app/Info.plist < app/Resources/Docs.docc/README.md <