Skip to content

Commit a1c9626

Browse files
committed
ModuleVerifier: Add blocklist for builtin module verifier
In hopes to migrate over to the EBM based module verifier, stage in a blocklist for existing verification violations.
1 parent 4e6e28d commit a1c9626

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

Sources/SWBCore/ToolInfo/ClangToolInfo.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ public struct ClangBlocklists : Sendable {
2727

2828
var caching: CachingBlocklistInfo? = nil
2929

30+
public struct BuiltinModuleVerifierInfo : ProjectFailuresBlockList, Codable, Sendable {
31+
/// A blocklist of project names that do not support the `MODULE_VERIFIER_KIND=builtin` build setting.
32+
let KnownFailures: [String]
33+
enum CodingKeys: String, CodingKey {
34+
case KnownFailures
35+
}
36+
}
37+
38+
var builtinModuleVerify: BuiltinModuleVerifierInfo? = nil
39+
40+
/// Helper method for determining if a given functionality is blocklisted for the active scope.
3041
func isBlocked<BlockListT: ProjectFailuresBlockList>(_ scope: MacroEvaluationScope, info: BlockListT?) -> Bool {
3142
guard let blocklistInfo = info else { return false }
3243
return blocklistInfo.isProjectListed(scope)
@@ -90,6 +101,10 @@ public struct DiscoveredClangToolSpecInfo: DiscoveredCommandLineToolSpecInfo {
90101
public func isCachingBlocked(_ scope: MacroEvaluationScope) -> Bool {
91102
return blocklists.isBlocked(scope, info: blocklists.caching)
92103
}
104+
105+
public func isBuiltinModuleVerifyBlocked(_ scope: MacroEvaluationScope) -> Bool {
106+
return blocklists.isBlocked(scope, info: blocklists.builtinModuleVerify)
107+
}
93108
}
94109

95110
private let clangVersionRe = RegEx(patternLiteral: #""(?<llvm>[0-9]+(?:\.[0-9]+){0,}) \(clang-(?<clang>[0-9]+(?:\.[0-9]+){0,})\)(?: ((\[.+\])|(\(.+\)))+)?""#)
@@ -187,6 +202,8 @@ public func discoveredClangToolInfo(
187202
}
188203
var blocklists = ClangBlocklists()
189204
blocklists.caching = getBlocklist(type: ClangBlocklists.CachingBlocklistInfo.self, toolchainFilename: "clang-caching.json", delegate: delegate)
205+
blocklists.builtinModuleVerify = getBlocklist(type: ClangBlocklists.BuiltinModuleVerifierInfo.self, toolchainFilename: "clang-builtin-module-verify.json", delegate: delegate)
206+
190207

191208
return DiscoveredClangToolSpecInfo(
192209
toolPath: toolPath,

Sources/SWBTaskConstruction/TaskProducers/OtherTaskProducers/ModuleVerifierTaskProducer.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ final class ModuleVerifierTaskProducer: PhasedTaskProducer, TaskProducer {
149149
fallbackToExternal = true
150150
return
151151
}
152+
// Fallback to external verifier if current scope is blocklisted.
153+
if clangInfo?.isBuiltinModuleVerifyBlocked(scope) == true {
154+
fallbackToExternal = true
155+
return
156+
}
152157
} catch {
153158
delegate.error(error)
154159
return

Tests/SWBTaskConstructionTests/ModuleVerifierTaskConstructionTests.swift

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,77 @@ fileprivate struct ModuleVerifierTaskConstructionTests: CoreBasedTests {
659659
}
660660
}
661661

662+
@Test(.requireSDKs(.macOS))
663+
func builtinModuleVerifyList() async throws {
664+
try await withTemporaryDirectory { tmpDirPath in
665+
let blockListFilePath = tmpDirPath.join("clang-builtin-module-verify.json")
666+
let targetName = "Orange"
667+
let testProject =
668+
TestProject(
669+
"aProject",
670+
sourceRoot: tmpDirPath.join("Test"),
671+
groupTree: TestGroup(
672+
"Group",
673+
path: "Sources",
674+
children: [
675+
TestFile("Orange.h"),
676+
TestFile("Orange.defs"),
677+
TestFile("main.m"),
678+
]),
679+
targets: [
680+
TestStandardTarget(
681+
targetName,
682+
type: .framework,
683+
buildConfigurations: [
684+
TestBuildConfiguration("Debug", buildSettings: [
685+
"ARCHS": "arm64",
686+
"DEFINES_MODULE": "YES",
687+
"ENABLE_MODULE_VERIFIER": "YES",
688+
"MODULE_VERIFIER_KIND": "builtin",
689+
"GENERATE_INFOPLIST_FILE": "YES",
690+
"MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS": "gnu11",
691+
"MODULE_VERIFIER_SUPPORTED_LANGUAGES": "objective-c",
692+
"MODULE_VERIFIER_VERBOSE": "YES",
693+
"PRODUCT_NAME": "$(TARGET_NAME)",
694+
"BLOCKLISTS_PATH": tmpDirPath.str,
695+
]),
696+
],
697+
buildPhases: [
698+
TestHeadersBuildPhase([
699+
TestBuildFile("Orange.h", headerVisibility: .public)
700+
]),
701+
TestSourcesBuildPhase([
702+
"main.m",
703+
]),
704+
]),
705+
])
706+
707+
let core = try await getCore()
708+
let tester = try await BuildOperationTester(core, testProject, simulated: false)
709+
let SRCROOT = tester.workspace.projects[0].sourceRoot
710+
for inputFile in ["Sources/Orange.h", "Sources/Orange.defs", "Sources/main.m"] {
711+
try await tester.fs.writeFileContents(SRCROOT.join(inputFile)) { stream in
712+
stream <<< ""
713+
}
714+
}
715+
try await tester.fs.writeFileContents(blockListFilePath) { file in
716+
file <<<
717+
"""
718+
{ "KnownFailures": ["aProject"]}
719+
"""
720+
}
721+
/// Verify that while the project has enabled `MODULE_VERIFIER_KIND=builtin` the external module verifier is invoked because the project is on the blocklist.
722+
try await tester.checkBuild(runDestination: .macOS) { results in
723+
results.checkNoDiagnostics()
724+
results.checkTask(.matchRuleType("VerifyModule")) { task in
725+
task.checkRuleInfo(["VerifyModule", "\(SRCROOT.str)/build/Debug/Orange.framework"])
726+
task.checkCommandLineMatches([.suffix("modules-verifier"), "\(SRCROOT.str)/build/Debug/Orange.framework", .anySequence, "--clang", .suffix("clang"), .anySequence])
727+
}
728+
results.checkNoErrors()
729+
}
730+
}
731+
}
732+
662733
@Test(.requireSDKs(.macOS))
663734
func externalModuleVerifier() async throws {
664735
let archs = ["arm64", "x86_64"]

0 commit comments

Comments
 (0)