Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion apple/internal/apple_xcframework_import.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,16 @@ def _apple_static_xcframework_import_impl(ctx):
linkopts = sdk_linkopts + linkopts,
swiftinterface_imports = [xcframework_library.swift_module_interface] if xcframework_library.swift_module_interface else [],
swiftmodule_imports = xcframework_library.swiftmodule,
includes = xcframework_library.includes + ctx.attr.includes,
# User-specified includes are relative to the platform directory inside the xcframework.
# For framework XCFrameworks, binary is inside .framework bundle, so go up one level.
# For library XCFrameworks, binary is directly in the platform directory.
includes = xcframework_library.includes + [
paths.join(
paths.dirname(xcframework_library.binary.dirname) if xcframework_library.framework_includes else xcframework_library.binary.dirname,
inc,
)
for inc in ctx.attr.includes
],
)
providers.append(cc_info)

Expand Down
32 changes: 32 additions & 0 deletions test/starlark_tests/apple_xcframework_import_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ load(
"//test/starlark_tests/rules:analysis_target_outputs_test.bzl",
"analysis_target_outputs_test",
)
load(
"//test/starlark_tests/rules:analysis_xcframework_includes_test.bzl",
"analysis_xcframework_includes_test",
)
load(
"//test/starlark_tests/rules:apple_verification_test.bzl",
"apple_verification_test",
Expand Down Expand Up @@ -249,6 +253,34 @@ def apple_xcframework_import_test_suite(name):
tags = [name],
)

# Test that includes attribute is correctly resolved for library-style static XCFrameworks.
# The expected include path should contain the xcframework's platform directory + "Headers".
analysis_xcframework_includes_test(
name = "{}_static_xcfw_library_style_includes_resolved".format(name),
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_imported_static_xcframework_old",
expected_includes = [
# The path should be: .../ios_static_xcframework/Headers
"ios_static_xcframework/Headers",
],
tags = [name],
)

# Test that includes attribute is correctly resolved for framework-style static XCFrameworks.
# Includes are relative to the platform directory, not the .framework bundle.
analysis_xcframework_includes_test(
name = "{}_static_xcfw_framework_style_includes_resolved".format(name),
target_under_test = "//test/starlark_tests/targets_under_test/apple:ios_imported_xcframework_bundling_static_fmwks_with_includes",
expected_includes = [
"ios_imported_xcframework_bundling_static_fmwks_with_includes-intermediates/Headers",
],
# The include should NOT be inside the .framework bundle - this ensures the path
# was correctly computed to go up one level from the .framework directory.
not_expected_includes = [
".framework/Headers",
],
tags = [name],
)

native.test_suite(
name = name,
tags = [name],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright 2026 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.

"""Analysis test for verifying XCFramework include paths in CcInfo provider."""

load(
"@bazel_skylib//lib:unittest.bzl",
"analysistest",
"unittest",
)
load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")

def _analysis_xcframework_includes_test_impl(ctx):
"""Implementation of analysis_xcframework_includes_test."""
env = analysistest.begin(ctx)
target_under_test = analysistest.target_under_test(env)

# Get CcInfo provider from the target
if not CcInfo in target_under_test:
unittest.fail(env, "Target does not provide CcInfo")
return analysistest.end(env)

cc_info = target_under_test[CcInfo]
compilation_context = cc_info.compilation_context

# Get all include directories as strings
includes = [inc for inc in compilation_context.includes.to_list()]
system_includes = [inc for inc in compilation_context.system_includes.to_list()]
quote_includes = [inc for inc in compilation_context.quote_includes.to_list()]

all_includes = includes + system_includes + quote_includes

# Check that expected includes are present
for expected_include in ctx.attr.expected_includes:
found = False
for inc in all_includes:
if expected_include in inc:
found = True
break
if not found:
unittest.fail(
env,
"Expected include path '{}' not found in CcInfo includes.\nActual includes: {}".format(
expected_include,
all_includes,
),
)
return analysistest.end(env)

# Check that not_expected includes are absent
for not_expected_include in ctx.attr.not_expected_includes:
for inc in all_includes:
if not_expected_include in inc:
unittest.fail(
env,
"Include path '{}' should NOT be present but was found in CcInfo includes.\nActual includes: {}".format(
not_expected_include,
all_includes,
),
)
return analysistest.end(env)

return analysistest.end(env)

analysis_xcframework_includes_test = analysistest.make(
_analysis_xcframework_includes_test_impl,
attrs = {
"expected_includes": attr.string_list(
doc = """
A list of strings that should be substrings of paths in the CcInfo includes.
Each expected include must match at least one path in the includes.""",
),
"not_expected_includes": attr.string_list(
doc = """
A list of strings that should NOT be substrings of any paths in the CcInfo includes.
If any of these are found, the test fails.""",
),
},
)
10 changes: 10 additions & 0 deletions test/starlark_tests/targets_under_test/apple/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,16 @@ apple_static_xcframework_import(
xcframework_imports = [":generated_ios_xcframework_bundling_static_fmwks"],
)

# Framework-style static xcframework with includes attribute for testing include path resolution.
# Unlike library-style xcframeworks where the binary is directly in the platform dir,
# framework-style xcframeworks have the binary inside a .framework bundle.
apple_static_xcframework_import(
name = "ios_imported_xcframework_bundling_static_fmwks_with_includes",
includes = ["Headers"],
tags = ["manual"],
xcframework_imports = [":generated_ios_xcframework_bundling_static_fmwks"],
)

apple_static_xcframework_import(
name = "ios_imported_static_xcframework_with_module_map",
tags = ["manual"],
Expand Down