forked from bazel-ios/rules_ios
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix and assert swift imported header propagation (bazel-ios#333)
* Fix and assert swift imported header propagation This PR fixes a bug in swift compilation with imported framework transitive headers. Additionally it refactors the testing rules into a package that can be used with `rules_ios` or other repositories. These tests iclude existing tests for Bazel transitions being incorrect in `rules_ios` and the new generalized header test. The headers test allows a user to assert that tests are propagated to actions For cases: 1. add a frameworks directory to the app. This represents the case of `apple_framework.vendored_static_frameworks` which is commonly used as a way to import frameworks 2. test framework import under test-imports-app. Asserts transitive headers are loaded from TensorFlow.
- Loading branch information
Showing
20 changed files
with
219 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") | ||
|
||
_TestFiles = provider( | ||
fields = { | ||
"files": "A glob of files collected for later assertions", | ||
}, | ||
) | ||
|
||
def _identical_outputs_test_impl(ctx): | ||
env = analysistest.begin(ctx) | ||
all_files = [] | ||
asserts.true(env, len(ctx.attr.deps) > 1) | ||
|
||
for dep in ctx.attr.deps: | ||
if not _TestFiles in dep: | ||
continue | ||
|
||
# The input root is the part of the file usually rooted in bazel-out. | ||
# For starlark transitions output dirs are fingerprinted by the hash of the | ||
# relevant configuration keys. | ||
# src/main/java/com/google/devtools/build/lib/analysis/starlark/FunctionTransitionUtil.java | ||
for input in dep[_TestFiles].files.to_list(): | ||
all_files.append(input.root.path) | ||
|
||
# Expect that we have received multiple swiftmodules | ||
asserts.true(env, len(all_files) > 1) | ||
|
||
# Assert all swiftmodules have identical outputs ( and most importantly an | ||
# identical output directory ) | ||
asserts.equals(env, 1, len(depset(all_files).to_list())) | ||
return analysistest.end(env) | ||
|
||
def _collect_transitive_outputs_impl(target, ctx): | ||
# Collect trans swift_library outputs | ||
out = [] | ||
if ctx.rule.kind == "swift_library": | ||
out.extend(target[DefaultInfo].files.to_list()) | ||
|
||
if _TestFiles in target: | ||
out.extend(target[_TestFiles].files.to_list()) | ||
if hasattr(ctx.rule.attr, "srcs"): | ||
for d in ctx.rule.attr.srcs: | ||
if _TestFiles in d: | ||
out.extend(d[_TestFiles].files.to_list()) | ||
if hasattr(ctx.rule.attr, "deps"): | ||
for d in ctx.rule.attr.deps: | ||
if _TestFiles in d: | ||
out.extend(d[_TestFiles].files.to_list()) | ||
return _TestFiles(files = depset(out)) | ||
|
||
_collect_transitive_outputs = aspect( | ||
implementation = _collect_transitive_outputs_impl, | ||
attr_aspects = ["deps", "srcs"], | ||
) | ||
|
||
# This test asserts that transitive dependencies have identical outputs for | ||
# different transition paths. In particular, a rules_apple ios_application and | ||
# an a apple_framework that share a swift_library, | ||
# //tests/ios/app:SwiftLib_swift. This test ensures that the actions in both | ||
# builds have functionally equal transitions applied by normalizing their output | ||
# directories into a set. | ||
# | ||
# For instance these tests will fail if there is any delta and requires both: | ||
# - adding apple_common.multi_arch_split to apple_framework.deps - #188 | ||
# - the transition yields the same result when used w/rules_apple - #196 | ||
|
||
# Note: | ||
# The gist of Bazel's configuration resolver is that it will apply | ||
# relevant transitions to keys that are used by a given action. e.g. ios_multi_cpus. | ||
# src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationResolver.java | ||
# | ||
# In order to get the same configuration for a rule, a given transition has | ||
# to produce the same values for dependent keys for all possible combinations | ||
identical_outputs_test = analysistest.make( | ||
_identical_outputs_test_impl, | ||
expect_failure = False, | ||
attrs = { | ||
"deps": attr.label_list( | ||
aspects = [_collect_transitive_outputs], | ||
), | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") | ||
|
||
def _transitive_header_test_impl(ctx): | ||
env = analysistest.begin(ctx) | ||
asserts.true(env, len(ctx.attr.deps) > 0) | ||
target_under_test = analysistest.target_under_test(env) | ||
target_headers = target_under_test[CcInfo].compilation_context.headers.to_list() | ||
for dep in ctx.attr.deps: | ||
asserts.true(env, CcInfo in dep) | ||
dep_headers = dep[CcInfo].compilation_context.headers.to_list() | ||
for dep_header in dep_headers: | ||
# Assert that all of the dep headers are in the target | ||
if not dep_header.extension == "h": | ||
continue | ||
|
||
has_header = dep_header in target_headers | ||
if not has_header: | ||
print("Missing header", dep_header, target_headers) | ||
asserts.true(env, has_header) | ||
return analysistest.end(env) | ||
|
||
# The headers test allows a user to assert that tests are propagated to actions | ||
# from arbitrary deps. Given a target_under_test, supply transitive deps or | ||
# virtually any file group. | ||
transitive_header_test = analysistest.make( | ||
_transitive_header_test_impl, | ||
expect_failure = False, | ||
attrs = { | ||
"deps": attr.label_list(allow_empty = False), | ||
}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
load("//rules/analysis_tests:transitive_header_test.bzl", "transitive_header_test") | ||
|
||
def make_tests(): | ||
transitive_header_test( | ||
name = "test_SomeFramework_SwiftCompilationHeaders", | ||
target_under_test = ":SomeFramework_swift", | ||
deps = ["//tests/ios/unit-test/test-imports-app/frameworks/Basic"], | ||
) | ||
|
||
transitive_header_test( | ||
name = "test_App_SwiftCompilationHeaders", | ||
target_under_test = ":TestImports-App_swift", | ||
deps = ["//tests/ios/unit-test/test-imports-app/frameworks/Basic", "@TensorFlowLiteC//:TensorFlowLiteC"], | ||
) | ||
|
||
native.test_suite( | ||
name = "AnalysisTests", | ||
tests = [ | ||
":test_App_SwiftCompilationHeaders", | ||
":test_SomeFramework_SwiftCompilationHeaders", | ||
], | ||
) |
Empty file.
13 changes: 13 additions & 0 deletions
13
tests/ios/unit-test/test-imports-app/frameworks/Basic/BUILD.bazel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
load("//rules:framework.bzl", "apple_framework") | ||
|
||
apple_framework( | ||
name = "Basic", | ||
# Note: it is totally possible that a user would write a glob like this.. | ||
# srcs = glob([ | ||
# "sources/Basic/**/*.h", | ||
# ]), | ||
objc_copts = ["-fmodules-disable-diagnostic-validation"], | ||
platforms = {"ios": "12.0"}, | ||
vendored_static_frameworks = ["ios/Basic.framework"], | ||
visibility = ["//visibility:public"], | ||
) |
Binary file added
BIN
+3.51 KB
tests/ios/unit-test/test-imports-app/frameworks/Basic/ios/Basic.framework/Basic
Binary file not shown.
9 changes: 9 additions & 0 deletions
9
tests/ios/unit-test/test-imports-app/frameworks/Basic/ios/Basic.framework/Headers/Basic.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@import Foundation; | ||
|
||
typedef NS_ENUM(NSInteger, BasicVal) { | ||
BasicVal_Unknown = 0, | ||
BasicVal_FinishActivating = 1, | ||
BasicVal_DownloadTheApp = 2, | ||
}; | ||
|
||
static const NSString *BasicString = @"BasicString"; |
4 changes: 4 additions & 0 deletions
4
.../unit-test/test-imports-app/frameworks/Basic/ios/Basic.framework/Modules/module.modulemap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
framework module Basic { | ||
header "Basic.h" | ||
export * | ||
} |
9 changes: 9 additions & 0 deletions
9
tests/ios/unit-test/test-imports-app/frameworks/NestedHeaders/BUILD.bazel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
load("//rules:framework.bzl", "apple_framework") | ||
|
||
apple_framework( | ||
name = "NestedHeaders", | ||
objc_copts = ["-fmodules-disable-diagnostic-validation"], | ||
platforms = {"ios": "12.0"}, | ||
vendored_static_frameworks = ["ios/NestedHeaders.framework"], | ||
visibility = ["//visibility:public"], | ||
) |
Binary file added
BIN
+3.51 KB
...ios/unit-test/test-imports-app/frameworks/NestedHeaders/ios/NestedHeaders.framework/Basic
Binary file not shown.
9 changes: 9 additions & 0 deletions
9
...t-imports-app/frameworks/NestedHeaders/ios/NestedHeaders.framework/Headers/Nested/Basic.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
@import Foundation; | ||
|
||
typedef NS_ENUM(NSInteger, NestedHeadersVal) { | ||
NestedHeadersVal_Unknown = 0, | ||
NestedHeadersVal_FinishActivating = 1, | ||
NestedHeadersVal_DownloadTheApp = 2, | ||
}; | ||
|
||
static const NSString *NestedHeadersString = @"NestedHeadersString"; |
4 changes: 4 additions & 0 deletions
4
...imports-app/frameworks/NestedHeaders/ios/NestedHeaders.framework/Modules/module.modulemap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
framework module NestedHeaders { | ||
header "NestedHeaders.h" | ||
export * | ||
} |
Oops, something went wrong.