diff --git a/.bazelrc b/.bazelrc index 680734883..c5aa2d368 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,7 +1,7 @@ # To update these lines, execute # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages` -build --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/google_maps_example,examples/google_maps_example/GoogleMapsExample,examples/google_maps_example/third-party/google-maps-ios-sdk,examples/grpc_example,examples/grpc_example/compilers,examples/grpc_example/protos/echo_service,examples/grpc_example/protos/echo_service/requests,examples/grpc_example/protos/echo_service/responses,examples/grpc_example/sources/client,examples/grpc_example/sources/server,examples/injectionnext_example,examples/injectionnext_example/Tests,examples/interesting_deps,examples/interesting_deps/ios,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/kscrash_example,examples/kscrash_example/Sources/MyApp,examples/kscrash_example/Tests/MyAppUITests,examples/kscrash_example/swift,examples/language_modes_example,examples/lottie_ios_example,examples/lottie_ios_example/LottieExample,examples/lottie_ios_example/LottieExampleUITest,examples/messagekit_example,examples/messagekit_example/Sources/Models,examples/messagekit_example/Tests/ModelTests,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/objc_code/Tests/TrustKitTests,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/Tests/MyAppUITests,examples/resources_example/swift,examples/resources_example/third_party,examples/shake_ios_example,examples/shake_ios_example/ShakeIOSExample,examples/shake_ios_example/ShakeIOSExampleUITests,examples/skip_local_transitive_dependencies_example,examples/snapkit_example,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/sqlite_data_example,examples/stripe_example,examples/stripe_example/PaymentSheet/PaymentSheetExample,examples/stripe_example/PaymentSheet/PaymentSheetUITest,examples/swift_package_registry_example,examples/symlink_example,examples/symlink_example/Sources/ImportFramework,examples/symlink_example/Tests/ImportFrameworkTests,examples/tca_example,examples/tca_example/Sources,examples/tca_example/Tests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example -query --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/google_maps_example,examples/google_maps_example/GoogleMapsExample,examples/google_maps_example/third-party/google-maps-ios-sdk,examples/grpc_example,examples/grpc_example/compilers,examples/grpc_example/protos/echo_service,examples/grpc_example/protos/echo_service/requests,examples/grpc_example/protos/echo_service/responses,examples/grpc_example/sources/client,examples/grpc_example/sources/server,examples/injectionnext_example,examples/injectionnext_example/Tests,examples/interesting_deps,examples/interesting_deps/ios,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/kscrash_example,examples/kscrash_example/Sources/MyApp,examples/kscrash_example/Tests/MyAppUITests,examples/kscrash_example/swift,examples/language_modes_example,examples/lottie_ios_example,examples/lottie_ios_example/LottieExample,examples/lottie_ios_example/LottieExampleUITest,examples/messagekit_example,examples/messagekit_example/Sources/Models,examples/messagekit_example/Tests/ModelTests,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/objc_code/Tests/TrustKitTests,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/Tests/MyAppUITests,examples/resources_example/swift,examples/resources_example/third_party,examples/shake_ios_example,examples/shake_ios_example/ShakeIOSExample,examples/shake_ios_example/ShakeIOSExampleUITests,examples/skip_local_transitive_dependencies_example,examples/snapkit_example,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/sqlite_data_example,examples/stripe_example,examples/stripe_example/PaymentSheet/PaymentSheetExample,examples/stripe_example/PaymentSheet/PaymentSheetUITest,examples/swift_package_registry_example,examples/symlink_example,examples/symlink_example/Sources/ImportFramework,examples/symlink_example/Tests/ImportFrameworkTests,examples/tca_example,examples/tca_example/Sources,examples/tca_example/Tests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example +build --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/aws_crt_example,examples/aws_sdk_example,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/google_maps_example,examples/google_maps_example/GoogleMapsExample,examples/google_maps_example/third-party/google-maps-ios-sdk,examples/grpc_example,examples/grpc_example/compilers,examples/grpc_example/protos/echo_service,examples/grpc_example/protos/echo_service/requests,examples/grpc_example/protos/echo_service/responses,examples/grpc_example/sources/client,examples/grpc_example/sources/server,examples/injectionnext_example,examples/injectionnext_example/Tests,examples/interesting_deps,examples/interesting_deps/ios,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/kscrash_example,examples/kscrash_example/Sources/MyApp,examples/kscrash_example/Tests/MyAppUITests,examples/kscrash_example/swift,examples/language_modes_example,examples/lottie_ios_example,examples/lottie_ios_example/LottieExample,examples/lottie_ios_example/LottieExampleUITest,examples/messagekit_example,examples/messagekit_example/Sources/Models,examples/messagekit_example/Tests/ModelTests,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/objc_code/Tests/TrustKitTests,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/Tests/MyAppUITests,examples/resources_example/swift,examples/resources_example/third_party,examples/shake_ios_example,examples/shake_ios_example/ShakeIOSExample,examples/shake_ios_example/ShakeIOSExampleUITests,examples/skip_local_transitive_dependencies_example,examples/snapkit_example,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/sqlite_data_example,examples/stripe_example,examples/stripe_example/PaymentSheet/PaymentSheetExample,examples/stripe_example/PaymentSheet/PaymentSheetUITest,examples/swift_package_registry_example,examples/symlink_example,examples/symlink_example/Sources/ImportFramework,examples/symlink_example/Tests/ImportFrameworkTests,examples/tca_example,examples/tca_example/Sources,examples/tca_example/Tests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example +query --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/aws_crt_example,examples/aws_sdk_example,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/google_maps_example,examples/google_maps_example/GoogleMapsExample,examples/google_maps_example/third-party/google-maps-ios-sdk,examples/grpc_example,examples/grpc_example/compilers,examples/grpc_example/protos/echo_service,examples/grpc_example/protos/echo_service/requests,examples/grpc_example/protos/echo_service/responses,examples/grpc_example/sources/client,examples/grpc_example/sources/server,examples/injectionnext_example,examples/injectionnext_example/Tests,examples/interesting_deps,examples/interesting_deps/ios,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/kscrash_example,examples/kscrash_example/Sources/MyApp,examples/kscrash_example/Tests/MyAppUITests,examples/kscrash_example/swift,examples/language_modes_example,examples/lottie_ios_example,examples/lottie_ios_example/LottieExample,examples/lottie_ios_example/LottieExampleUITest,examples/messagekit_example,examples/messagekit_example/Sources/Models,examples/messagekit_example/Tests/ModelTests,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/objc_code/Tests/TrustKitTests,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/Tests/MyAppUITests,examples/resources_example/swift,examples/resources_example/third_party,examples/shake_ios_example,examples/shake_ios_example/ShakeIOSExample,examples/shake_ios_example/ShakeIOSExampleUITests,examples/skip_local_transitive_dependencies_example,examples/snapkit_example,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/sqlite_data_example,examples/stripe_example,examples/stripe_example/PaymentSheet/PaymentSheetExample,examples/stripe_example/PaymentSheet/PaymentSheetUITest,examples/swift_package_registry_example,examples/symlink_example,examples/symlink_example/Sources/ImportFramework,examples/symlink_example/Tests/ImportFrameworkTests,examples/tca_example,examples/tca_example/Sources,examples/tca_example/Tests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example # Import Shared settings import %workspace%/shared.bazelrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3198fef30..226686fc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,10 @@ jobs: runner: ubuntu-22.04 - test: '@@//bzlmod:e2e_test' runner: macos-15 + - test: '@@//examples:aws_crt_example_test_bazel_.bazelversion' + runner: macos-15 + - test: '@@//examples:aws_sdk_example_test_bazel_.bazelversion' + runner: macos-15 - test: '@@//examples:firebase_example_test_bazel_.bazelversion' runner: macos-15 - test: '@@//examples:google_maps_example_test_bazel_.bazelversion' diff --git a/examples/aws_crt_example/.bazelignore b/examples/aws_crt_example/.bazelignore new file mode 100644 index 000000000..24e5b0a1a --- /dev/null +++ b/examples/aws_crt_example/.bazelignore @@ -0,0 +1 @@ +.build diff --git a/examples/aws_crt_example/.bazelrc b/examples/aws_crt_example/.bazelrc new file mode 100644 index 000000000..e9769fc7b --- /dev/null +++ b/examples/aws_crt_example/.bazelrc @@ -0,0 +1,8 @@ +# Import Shared settings +import %workspace%/../../shared.bazelrc + +# Import CI settings. +import %workspace%/../../ci.bazelrc + +# Try to import a local.rc file; typically, written by CI +try-import %workspace%/../../local.bazelrc diff --git a/examples/aws_crt_example/BUILD.bazel b/examples/aws_crt_example/BUILD.bazel new file mode 100644 index 000000000..5321ab438 --- /dev/null +++ b/examples/aws_crt_example/BUILD.bazel @@ -0,0 +1,52 @@ +load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary") +load("@build_bazel_rules_swift//swift:swift_test.bzl", "swift_test") +load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy") +load("@rules_swift_package_manager//swiftpkg:defs.bzl", "swift_package_tool") + +swift_test( + name = "AwsCrtTests", + srcs = ["Tests/AwsCrtTests/AwsCrtTests.swift"], + deps = [ + "@swiftpkg_aws_crt_swift//:AwsCommonRuntimeKit", + ], +) + +tidy( + name = "tidy", + targets = [ + ":update_build_files", + ], +) + +# Purposefully am not adding this to tidy. It is expensive to run and only +# needs to be run when the Package.swift has been updated. +swift_package_tool( + name = "update_swift_packages", + cmd = "update", + package = "Package.swift", +) + +# MARK: - Gazelle + +# Ignore the Swift build folder +# gazelle:exclude .build +# gazelle:exclude Tests + +gazelle_binary( + name = "gazelle_bin", + languages = [ + "@bazel_skylib_gazelle_plugin//bzl", + "@swift_gazelle_plugin//gazelle", + ], +) + +gazelle( + name = "update_build_files", + data = [ + "@swift_deps_info//:swift_deps_index", + ], + extra_args = [ + "-swift_dependency_index=$(location @swift_deps_info//:swift_deps_index)", + ], + gazelle = ":gazelle_bin", +) diff --git a/examples/aws_crt_example/MODULE.bazel b/examples/aws_crt_example/MODULE.bazel new file mode 100644 index 000000000..6e6fde806 --- /dev/null +++ b/examples/aws_crt_example/MODULE.bazel @@ -0,0 +1,63 @@ +module(name = "aws_crt_example") + +bazel_dep( + name = "rules_swift_package_manager", + version = "0.0.0", +) +local_path_override( + module_name = "rules_swift_package_manager", + path = "../..", +) + +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.27.0") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "apple_support", version = "1.24.3") +bazel_dep( + name = "rules_swift", + version = "3.1.2", + repo_name = "build_bazel_rules_swift", +) +bazel_dep( + name = "rules_apple", + version = "4.2.0", + repo_name = "build_bazel_rules_apple", +) + +bazel_dep( + name = "bazel_skylib_gazelle_plugin", + version = "1.8.2", + dev_dependency = True, +) +bazel_dep( + name = "gazelle", + version = "0.46.0", + dev_dependency = True, + repo_name = "bazel_gazelle", +) +bazel_dep( + name = "swift_gazelle_plugin", + version = "0.2.1", + dev_dependency = True, +) + +apple_cc_configure = use_extension( + "@apple_support//crosstool:setup.bzl", + "apple_cc_configure_extension", +) +use_repo(apple_cc_configure, "local_config_apple_cc") + +swift_deps = use_extension( + "@rules_swift_package_manager//:extensions.bzl", + "swift_deps", +) +swift_deps.from_package( + declare_swift_deps_info = True, + resolved = "//:Package.resolved", + swift = "//:Package.swift", +) +use_repo( + swift_deps, + "swift_deps_info", + "swift_package", + "swiftpkg_aws_crt_swift", +) diff --git a/examples/aws_crt_example/Package.resolved b/examples/aws_crt_example/Package.resolved new file mode 100644 index 000000000..feeb37908 --- /dev/null +++ b/examples/aws_crt_example/Package.resolved @@ -0,0 +1,23 @@ +{ + "pins" : [ + { + "identity" : "aws-crt-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/awslabs/aws-crt-swift.git", + "state" : { + "revision" : "2f4f02595a25a43f9ca9acdc9f4d4a8ff6e5d3ac", + "version" : "0.54.0" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "cdd0ef3755280949551dc26dee5de9ddeda89f54", + "version" : "1.6.2" + } + } + ], + "version" : 2 +} diff --git a/examples/aws_crt_example/Package.swift b/examples/aws_crt_example/Package.swift new file mode 100644 index 000000000..2c9d24407 --- /dev/null +++ b/examples/aws_crt_example/Package.swift @@ -0,0 +1,10 @@ +// swift-tools-version: 5.9 + +import PackageDescription + +let package = Package( + name: "AwsCrtExample", + dependencies: [ + .package(url: "https://github.com/awslabs/aws-crt-swift.git", from: "0.54.0"), + ] +) diff --git a/examples/aws_crt_example/README.md b/examples/aws_crt_example/README.md new file mode 100644 index 000000000..455e5ffa2 --- /dev/null +++ b/examples/aws_crt_example/README.md @@ -0,0 +1,3 @@ +# AWS CRT Swift Example + +This example demonstrates using [aws-crt-swift](https://github.com/awslabs/aws-crt-swift) with Bazel. diff --git a/examples/aws_crt_example/Tests/AwsCrtTests/AwsCrtTests.swift b/examples/aws_crt_example/Tests/AwsCrtTests/AwsCrtTests.swift new file mode 100644 index 000000000..2128ffd57 --- /dev/null +++ b/examples/aws_crt_example/Tests/AwsCrtTests/AwsCrtTests.swift @@ -0,0 +1,10 @@ +import XCTest +import AwsCommonRuntimeKit + +final class AwsCrtTests: XCTestCase { + func testCrtTypes() throws { + // Test that we can use types from AwsCommonRuntimeKit + let logLevel = LogLevel.info + XCTAssertEqual(logLevel, LogLevel.info) + } +} diff --git a/examples/aws_crt_example/WORKSPACE b/examples/aws_crt_example/WORKSPACE new file mode 100644 index 000000000..6f47a752b --- /dev/null +++ b/examples/aws_crt_example/WORKSPACE @@ -0,0 +1 @@ +# Intentionally blank. Using bzlmod. diff --git a/examples/aws_crt_example/WORKSPACE.bzlmod b/examples/aws_crt_example/WORKSPACE.bzlmod new file mode 100644 index 000000000..4b83dbf2b --- /dev/null +++ b/examples/aws_crt_example/WORKSPACE.bzlmod @@ -0,0 +1 @@ +# Intentionally blank. The content for this workspace is generated by bzlmod. diff --git a/examples/aws_crt_example/do_test b/examples/aws_crt_example/do_test new file mode 100755 index 000000000..a4eb535e9 --- /dev/null +++ b/examples/aws_crt_example/do_test @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o pipefail + +# Use the Bazel binary specified by the integration test. Otherise, fall back +# to bazel. +bazel="${BIT_BAZEL_BINARY:-bazel}" + +# Generate Swift external deps and update build files +"${bazel}" run //:tidy + +# Ensure that it builds and tests pass +"${bazel}" test //... diff --git a/examples/aws_sdk_example/.bazelignore b/examples/aws_sdk_example/.bazelignore new file mode 100644 index 000000000..24e5b0a1a --- /dev/null +++ b/examples/aws_sdk_example/.bazelignore @@ -0,0 +1 @@ +.build diff --git a/examples/aws_sdk_example/.bazelrc b/examples/aws_sdk_example/.bazelrc new file mode 100644 index 000000000..e9769fc7b --- /dev/null +++ b/examples/aws_sdk_example/.bazelrc @@ -0,0 +1,8 @@ +# Import Shared settings +import %workspace%/../../shared.bazelrc + +# Import CI settings. +import %workspace%/../../ci.bazelrc + +# Try to import a local.rc file; typically, written by CI +try-import %workspace%/../../local.bazelrc diff --git a/examples/aws_sdk_example/BUILD.bazel b/examples/aws_sdk_example/BUILD.bazel new file mode 100644 index 000000000..aa2706627 --- /dev/null +++ b/examples/aws_sdk_example/BUILD.bazel @@ -0,0 +1,52 @@ +load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary") +load("@build_bazel_rules_swift//swift:swift_binary.bzl", "swift_binary") +load("@cgrindel_bazel_starlib//bzltidy:defs.bzl", "tidy") +load("@rules_swift_package_manager//swiftpkg:defs.bzl", "swift_package_tool") + +swift_binary( + name = "AwsSdkExample", + srcs = ["Sources/AwsSdkExample/main.swift"], + deps = [ + "@swiftpkg_aws_sdk_swift//:AWSS3", + ], +) + +tidy( + name = "tidy", + targets = [ + ":update_build_files", + ], +) + +# Puprosefully am not adding this to tidy. It is expensive to run and only +# needs to be run when the Package.swift has been updated. +swift_package_tool( + name = "update_swift_packages", + cmd = "update", + package = "Package.swift", +) + +# MARK: - Gazelle + +# Ignore the Swift build folder +# gazelle:exclude .build +# gazelle:exclude Sources + +gazelle_binary( + name = "gazelle_bin", + languages = [ + "@bazel_skylib_gazelle_plugin//bzl", + "@swift_gazelle_plugin//gazelle", + ], +) + +gazelle( + name = "update_build_files", + data = [ + "@swift_deps_info//:swift_deps_index", + ], + extra_args = [ + "-swift_dependency_index=$(location @swift_deps_info//:swift_deps_index)", + ], + gazelle = ":gazelle_bin", +) diff --git a/examples/aws_sdk_example/MODULE.bazel b/examples/aws_sdk_example/MODULE.bazel new file mode 100644 index 000000000..c3a525fbf --- /dev/null +++ b/examples/aws_sdk_example/MODULE.bazel @@ -0,0 +1,63 @@ +module(name = "aws_sdk_example") + +bazel_dep( + name = "rules_swift_package_manager", + version = "0.0.0", +) +local_path_override( + module_name = "rules_swift_package_manager", + path = "../..", +) + +bazel_dep(name = "cgrindel_bazel_starlib", version = "0.27.0") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "apple_support", version = "1.24.3") +bazel_dep( + name = "rules_swift", + version = "3.1.2", + repo_name = "build_bazel_rules_swift", +) +bazel_dep( + name = "rules_apple", + version = "4.2.0", + repo_name = "build_bazel_rules_apple", +) + +bazel_dep( + name = "bazel_skylib_gazelle_plugin", + version = "1.8.2", + dev_dependency = True, +) +bazel_dep( + name = "gazelle", + version = "0.46.0", + dev_dependency = True, + repo_name = "bazel_gazelle", +) +bazel_dep( + name = "swift_gazelle_plugin", + version = "0.2.1", + dev_dependency = True, +) + +apple_cc_configure = use_extension( + "@apple_support//crosstool:setup.bzl", + "apple_cc_configure_extension", +) +use_repo(apple_cc_configure, "local_config_apple_cc") + +swift_deps = use_extension( + "@rules_swift_package_manager//:extensions.bzl", + "swift_deps", +) +swift_deps.from_package( + declare_swift_deps_info = True, + resolved = "//:Package.resolved", + swift = "//:Package.swift", +) +use_repo( + swift_deps, + "swift_deps_info", + "swift_package", + "swiftpkg_aws_sdk_swift", +) diff --git a/examples/aws_sdk_example/Package.resolved b/examples/aws_sdk_example/Package.resolved new file mode 100644 index 000000000..a5c4c11f9 --- /dev/null +++ b/examples/aws_sdk_example/Package.resolved @@ -0,0 +1,257 @@ +{ + "pins" : [ + { + "identity" : "aws-crt-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/awslabs/aws-crt-swift", + "state" : { + "revision" : "2f4f02595a25a43f9ca9acdc9f4d4a8ff6e5d3ac", + "version" : "0.54.0" + } + }, + { + "identity" : "aws-sdk-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/awslabs/aws-sdk-swift", + "state" : { + "revision" : "c1eef6225b0ee29a1c0494e1b5691bd51e0ca571", + "version" : "1.5.75" + } + }, + { + "identity" : "grpc-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/grpc/grpc-swift.git", + "state" : { + "revision" : "a56a157218877ef3e9625f7e1f7b2cb7e46ead1b", + "version" : "1.26.1" + } + }, + { + "identity" : "opentelemetry-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/open-telemetry/opentelemetry-swift", + "state" : { + "revision" : "ef63c346d05f4fa7c9ca883f92631fd139eb2cfe", + "version" : "1.17.1" + } + }, + { + "identity" : "opentracing-objc", + "kind" : "remoteSourceControl", + "location" : "https://github.com/undefinedlabs/opentracing-objc", + "state" : { + "revision" : "18c1a35ca966236cee0c5a714a51a73ff33384c1", + "version" : "0.5.2" + } + }, + { + "identity" : "smithy-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/smithy-lang/smithy-swift", + "state" : { + "revision" : "825beae9be4a2518f457a4930d8969dc598d8c0c", + "version" : "0.168.0" + } + }, + { + "identity" : "swift-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-algorithms.git", + "state" : { + "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023", + "version" : "1.2.1" + } + }, + { + "identity" : "swift-argument-parser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-argument-parser.git", + "state" : { + "revision" : "cdd0ef3755280949551dc26dee5de9ddeda89f54", + "version" : "1.6.2" + } + }, + { + "identity" : "swift-asn1", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-asn1.git", + "state" : { + "revision" : "40d25bbb2fc5b557a9aa8512210bded327c0f60d", + "version" : "1.5.0" + } + }, + { + "identity" : "swift-async-algorithms", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-async-algorithms.git", + "state" : { + "revision" : "042e1c4d9d19748c9c228f8d4ebc97bb1e339b0b", + "version" : "1.0.4" + } + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "b601256eab081c0f92f059e12818ac1d4f178ff7", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-certificates", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-certificates.git", + "state" : { + "revision" : "c399f90e7bbe8874f6cbfda1d5f9023d1f5ce122", + "version" : "1.15.1" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections.git", + "state" : { + "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-crypto", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-crypto.git", + "state" : { + "revision" : "e8ed8867ec23bccf5f3bb9342148fa8deaff9b49", + "version" : "4.1.0" + } + }, + { + "identity" : "swift-http-structured-headers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-structured-headers.git", + "state" : { + "revision" : "a9f3c352f4d46afd155e00b3c6e85decae6bcbeb", + "version" : "1.5.0" + } + }, + { + "identity" : "swift-http-types", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-http-types.git", + "state" : { + "revision" : "45eb0224913ea070ec4fba17291b9e7ecf4749ca", + "version" : "1.5.1" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2", + "version" : "1.6.4" + } + }, + { + "identity" : "swift-metrics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-metrics.git", + "state" : { + "revision" : "0743a9364382629da3bf5677b46a2c4b1ce5d2a6", + "version" : "2.7.1" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "a24771a4c228ff116df343c85fcf3dcfae31a06c", + "version" : "2.88.0" + } + }, + { + "identity" : "swift-nio-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-extras.git", + "state" : { + "revision" : "b87fdbf492c8fd5ac860e642c714d2d24156990a", + "version" : "1.30.0" + } + }, + { + "identity" : "swift-nio-http2", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-http2.git", + "state" : { + "revision" : "5e9e99ec96c53bc2c18ddd10c1e25a3cd97c55e5", + "version" : "1.38.0" + } + }, + { + "identity" : "swift-nio-ssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-ssl.git", + "state" : { + "revision" : "173cc69a058623525a58ae6710e2f5727c663793", + "version" : "2.36.0" + } + }, + { + "identity" : "swift-nio-transport-services", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio-transport-services.git", + "state" : { + "revision" : "df6c28355051c72c884574a6c858bc54f7311ff9", + "version" : "1.25.2" + } + }, + { + "identity" : "swift-numerics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-numerics.git", + "state" : { + "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "c169a5744230951031770e27e475ff6eefe51f9d", + "version" : "1.33.3" + } + }, + { + "identity" : "swift-service-lifecycle", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swift-server/swift-service-lifecycle.git", + "state" : { + "revision" : "0fcc4c9c2d58dd98504c06f7308c86de775396ff", + "version" : "2.9.0" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "395a77f0aa927f0ff73941d7ac35f2b46d47c9db", + "version" : "1.6.3" + } + }, + { + "identity" : "thrift-swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/undefinedlabs/Thrift-Swift", + "state" : { + "revision" : "18ff09e6b30e589ed38f90a1af23e193b8ecef8e", + "version" : "1.1.2" + } + } + ], + "version" : 2 +} diff --git a/examples/aws_sdk_example/Package.swift b/examples/aws_sdk_example/Package.swift new file mode 100644 index 000000000..ec8c2865d --- /dev/null +++ b/examples/aws_sdk_example/Package.swift @@ -0,0 +1,10 @@ +// swift-tools-version: 5.9 + +import PackageDescription + +let package = Package( + name: "AwsSdkExample", + dependencies: [ + .package(url: "https://github.com/awslabs/aws-sdk-swift", from: "1.0.0"), + ] +) diff --git a/examples/aws_sdk_example/README.md b/examples/aws_sdk_example/README.md new file mode 100644 index 000000000..0147772ed --- /dev/null +++ b/examples/aws_sdk_example/README.md @@ -0,0 +1,29 @@ +# AWS SDK Swift Example + +This example demonstrates building a Swift application that uses the AWS SDK for Swift. + +## Building + +```bash +bazel build //:AwsSdkExample +``` + +## Running + +```bash +bazel run //:AwsSdkExample +``` + +Expected output: +``` +AWS SDK Swift S3 client created successfully +``` + +## What This Tests + +This example verifies that rules_swift_package_manager can successfully build aws-sdk-swift, which depends on: +- aws-crt-swift (complex C dependencies with inline headers, excluded directories, and system frameworks) +- Multiple Swift packages with various dependency patterns +- Transitive C library dependencies with framework auto-detection + +The successful build demonstrates that all the fixes for complex C dependencies work correctly with a real-world, complex Swift package. diff --git a/examples/aws_sdk_example/Sources/AwsSdkExample/main.swift b/examples/aws_sdk_example/Sources/AwsSdkExample/main.swift new file mode 100644 index 000000000..03cae5c99 --- /dev/null +++ b/examples/aws_sdk_example/Sources/AwsSdkExample/main.swift @@ -0,0 +1,11 @@ +import AWSS3 + +struct AwsSdkExample { + static func main() async throws { + // Simple example that creates an S3 client + _ = try await S3Client() + print("AWS SDK Swift S3 client created successfully") + } +} + +try await AwsSdkExample.main() diff --git a/examples/aws_sdk_example/WORKSPACE b/examples/aws_sdk_example/WORKSPACE new file mode 100644 index 000000000..e69de29bb diff --git a/examples/aws_sdk_example/WORKSPACE.bzlmod b/examples/aws_sdk_example/WORKSPACE.bzlmod new file mode 100644 index 000000000..e69de29bb diff --git a/examples/aws_sdk_example/do_test b/examples/aws_sdk_example/do_test new file mode 100755 index 000000000..f99357224 --- /dev/null +++ b/examples/aws_sdk_example/do_test @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -o errexit -o nounset -o pipefail + +# Use the Bazel binary specified by the integration test. Otherise, fall back +# to bazel. +bazel="${BIT_BAZEL_BINARY:-bazel}" + +# Generate Swift external deps and update build files +"${bazel}" run //:tidy + +# Ensure that it builds and runs +"${bazel}" run //:AwsSdkExample + + diff --git a/examples/example_infos.bzl b/examples/example_infos.bzl index e24fede67..e311d8b37 100644 --- a/examples/example_infos.bzl +++ b/examples/example_infos.bzl @@ -132,6 +132,8 @@ _all_os_single_bazel_version_test_examples = [ ] _macos_single_bazel_version_test_examples = [ + "aws_crt_example", + "aws_sdk_example", "firebase_example", "google_maps_example", "interesting_deps", diff --git a/swiftpkg/internal/generate_modulemap.bzl b/swiftpkg/internal/generate_modulemap.bzl index b9669e836..6dac16e36 100644 --- a/swiftpkg/internal/generate_modulemap.bzl +++ b/swiftpkg/internal/generate_modulemap.bzl @@ -38,12 +38,32 @@ def _generate_modulemap_impl(ctx): if len(hdrs) == 0: fail("No header files were provided.") + # Use umbrella directory if all headers share a common root + umbrella_dir = None + if len(hdrs) > 0: + # Find the longest common directory prefix + dirs = [h.dirname for h in hdrs] + if len(dirs) > 0: + common_parts = dirs[0].split("/") + for d in dirs[1:]: + d_parts = d.split("/") + new_common = [] + for i in range(min(len(common_parts), len(d_parts))): + if common_parts[i] == d_parts[i]: + new_common.append(common_parts[i]) + else: + break + common_parts = new_common + if len(common_parts) > 0: + umbrella_dir = "/".join(common_parts) + write_module_map( actions = ctx.actions, module_map_file = modulemap_file, module_name = module_name, dependent_module_names = uses, - public_headers = hdrs, + umbrella_directory = umbrella_dir, + public_headers = hdrs if not umbrella_dir else [], ) provider_hdr = [modulemap_file] diff --git a/swiftpkg/internal/module_maps.bzl b/swiftpkg/internal/module_maps.bzl index fe7088fca..5aaf3c29d 100644 --- a/swiftpkg/internal/module_maps.bzl +++ b/swiftpkg/internal/module_maps.bzl @@ -32,6 +32,7 @@ def write_module_map( private_headers = [], private_textual_headers = [], umbrella_header = None, + umbrella_directory = None, workspace_relative = False): """Writes the content of the module map to a file. @@ -60,6 +61,8 @@ def write_module_map( umbrella_header: A `File` representing an umbrella header that, if present, will be written into the module map instead of the list of headers in the compilation context. + umbrella_directory: A path string representing an umbrella directory that, if + present, will be written into the module map instead of individual headers. workspace_relative: A Boolean value indicating whether the header paths written in the module map file should be relative to the workspace or relative to the module map file. @@ -105,6 +108,12 @@ def write_module_map( if umbrella_header: _add_headers(headers = [umbrella_header], kind = "umbrella header") + elif umbrella_directory: + # Umbrella directory must be absolute path + abs_umbrella = ( + back_to_root_path + umbrella_directory if back_to_root_path else umbrella_directory + ) + content.add(abs_umbrella, format = ' umbrella "%s"') else: _add_headers(headers = public_headers, kind = "header") _add_headers(headers = private_headers, kind = "private header") diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl index 3ea8b3e12..03da79209 100644 --- a/swiftpkg/internal/pkginfos.bzl +++ b/swiftpkg/internal/pkginfos.bzl @@ -11,6 +11,7 @@ load( "//config_settings/spm/platform:platforms.bzl", spm_platforms = "platforms", ) +load(":apple_builtin.bzl", "apple_builtin") load(":clang_files.bzl", "clang_files") load(":objc_files.bzl", "objc_files") load(":pkginfo_dependencies.bzl", "pkginfo_dependencies") @@ -1173,6 +1174,51 @@ def _new_swift_src_info( # MARK: - Clang Source Info +_FRAMEWORK_SRC_EXTS = [".c", ".cc", ".cpp", ".m", ".mm", ".h", ".hpp"] +_HEADER_EXTS = [".h", ".hpp", ".hh", ".hxx", ".inc", ".inl", ".modulemap"] + +def _is_framework_src(path): + _root, ext = paths.split_extension(path) + return lists.contains(_FRAMEWORK_SRC_EXTS, ext) + +def _detect_frameworks_from_sources(repository_ctx, srcs): + """Detect Apple frameworks from #include patterns in \ + C source files.""" + frameworks_set = sets.make() + + for src in srcs: + # Only scan C/C++/ObjC source and header files + if not _is_framework_src(src): + continue + + # Read the file and look for framework includes + content = repository_ctx.read(src) + lines = content.split("\n") + for line in lines: + line = line.strip() + + # Look for #include or + # #import + if not line.startswith("#include") and \ + not line.startswith("#import"): + continue + + # Extract the include path + if "<" in line and ">" in line: + start = line.index("<") + 1 + end = line.index(">") + include_path = line[start:end] + + # Check if it's a framework include (has a slash) + if "/" in include_path: + framework = include_path.split("/")[0] + + # Check if it's a known Apple framework + if sets.contains(apple_builtin.frameworks.all, framework): + sets.insert(frameworks_set, framework) + + return sorted(sets.to_list(frameworks_set)) + def _new_clang_src_info_from_sources( repository_ctx, pkg_path, @@ -1188,6 +1234,24 @@ def _new_clang_src_info_from_sources( paths.join(pkg_path, target_path), ) + # If no explicit public headers path is specified, default to "include" + # if it exists. This matches Swift Package Manager's behavior for C targets. + # Also remove any exclude patterns that would exclude the include directory, + # since SPM doesn't exclude public headers even if they're in the exclude list. + if public_hdrs_path == None: + default_include_path = paths.normalize( + paths.join(abs_target_path, "include"), + ) + if repository_files.is_directory(repository_ctx, default_include_path): + public_hdrs_path = "include" + + # Remove any exclude paths that start with "include/" + exclude_paths = [ + ep + for ep in exclude_paths + if not ep.startswith("include/") and ep != "include" + ] + public_includes = [] if public_hdrs_path != None: public_includes.append( @@ -1234,6 +1298,26 @@ def _new_clang_src_info_from_sources( exclude_paths = abs_exclude_paths, )) + # SPM's exclude list only excludes files from being compiled as sources, + # but headers in excluded directories are still available for inclusion. + # We need to find all header files in excluded directories and add them + # to all_srcs so they can be discovered and added to the BUILD file. + for ep in exclude_paths: + abs_exclude_path = paths.normalize(paths.join(abs_target_path, ep)) + if repository_files.is_directory(repository_ctx, abs_exclude_path): + # Get all files in the excluded directory + excluded_files = repository_files.list_files_under( + repository_ctx, + abs_exclude_path, + exclude_paths = [], + ) + + # Filter to only header files + for f in excluded_files: + _, ext = paths.split_extension(f) + if ext in _HEADER_EXTS: + all_srcs.append(f) + # Organize the source files # Be sure that the all_srcs and the public_includes that are passed to # `collect_files` are all absolute paths. The relative_to option will @@ -1304,6 +1388,9 @@ def _new_clang_src_info_from_sources( # GH1290: Can I remove explicit_srcs? I believe that it is obsolete. + # Detect Apple frameworks used by C source files + frameworks = _detect_frameworks_from_sources(repository_ctx, all_srcs) + return _new_clang_src_info( srcs = srcs, explicit_srcs = explicit_srcs, @@ -1312,6 +1399,7 @@ def _new_clang_src_info_from_sources( public_includes = public_includes, private_includes = private_includes, modulemap_path = organized_files.modulemap, + frameworks = frameworks, ) def _new_clang_src_info( @@ -1321,7 +1409,8 @@ def _new_clang_src_info( textual_hdrs = [], public_includes = [], private_includes = [], - modulemap_path = None): + modulemap_path = None, + frameworks = []): return struct( organized_srcs = clang_files.organize_srcs(srcs), explicit_srcs = explicit_srcs, @@ -1330,6 +1419,7 @@ def _new_clang_src_info( public_includes = public_includes, private_includes = private_includes, modulemap_path = modulemap_path, + frameworks = frameworks, ) # MARK: - Objc Source Info diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl index 735ec2e91..2a2b5b567 100644 --- a/swiftpkg/internal/swiftpkg_build_files.bzl +++ b/swiftpkg/internal/swiftpkg_build_files.bzl @@ -395,6 +395,19 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target): for bs in target.linker_settings.linked_frameworks ])) + # Add frameworks detected from source files as linkopts + # cc_library doesn't support sdk_frameworks, so we use -framework flags + if clang_src_info.frameworks: + for framework in clang_src_info.frameworks: + platform_conditions = bazel_apple_platforms.for_framework(framework) + for pc in platform_conditions: + linkopts.append( + bzl_selects.new( + value = "-framework {}".format(framework), + condition = pc, + ), + ) + # Assemble attributes attrs = {