Skip to content

Commit 5ab5968

Browse files
authored
Add new clang build setting EMIT_SARIF_DIAGNOSTICS_FILE (#938)
Add new clang build setting EMIT_COMPILER_SOURCE_METADATA that passes -fdiagnostic-add-output=sarif:file=<path>. The flag emits a SARIF log during the compilation which contains diagnostic information. The path is currently fixed to <object_file_path>.compiled.sarif
1 parent 1d1fcb8 commit 5ab5968

File tree

4 files changed

+105
-1
lines changed

4 files changed

+105
-1
lines changed

Sources/SWBCore/Settings/BuiltinMacros.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ public final class BuiltinMacros {
641641
public static let EMBEDDED_CONTENT_CONTAINS_SWIFT = BuiltinMacros.declareBooleanMacro("EMBEDDED_CONTENT_CONTAINS_SWIFT")
642642
public static let EMBEDDED_PROFILE_NAME = BuiltinMacros.declareStringMacro("EMBEDDED_PROFILE_NAME")
643643
public static let EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES = BuiltinMacros.declareStringListMacro("EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES")
644+
public static let EMIT_SARIF_DIAGNOSTICS_FILE = BuiltinMacros.declareBooleanMacro("EMIT_SARIF_DIAGNOSTICS_FILE")
644645
public static let EMIT_FRONTEND_COMMAND_LINES = BuiltinMacros.declareBooleanMacro("EMIT_FRONTEND_COMMAND_LINES")
645646
public static let ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING = BuiltinMacros.declareBooleanMacro("ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING")
646647
public static let ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING = BuiltinMacros.declareBooleanMacro("ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING")
@@ -1718,6 +1719,7 @@ public final class BuiltinMacros {
17181719
EMBEDDED_CONTENT_CONTAINS_SWIFT,
17191720
EMBEDDED_PROFILE_NAME,
17201721
EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES,
1722+
EMIT_SARIF_DIAGNOSTICS_FILE,
17211723
EMIT_FRONTEND_COMMAND_LINES,
17221724
ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING,
17231725
ENABLE_ADDRESS_SANITIZER,

Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
835835
"-fmessage-length=",
836836
"-fmacro-backtrace-limit=",
837837
"-fbuild-session-timestamp=",
838+
"-fdiagnostics-add-output="
838839
])
839840

840841
static let outputAgnosticCompilerArgumentsWithValues = Set<ByteString>([
@@ -1219,7 +1220,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
12191220
dependencyData = nil
12201221
}
12211222

1222-
let extraOutputs: [any PlannedNode]
1223+
var extraOutputs: [any PlannedNode]
12231224
let moduleDependenciesContext = cbc.producer.moduleDependenciesContext
12241225
let headerDependenciesContext = cbc.producer.headerDependenciesContext
12251226
let dependencyValidationOutputPath: Path?
@@ -1336,6 +1337,8 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
13361337
}
13371338
}
13381339

1340+
commandLine += addCompilerSarifFlags(cbc, outputFileDir.join(outputNode.path.str + ".compiled.sarif"), delegate, &extraOutputs)
1341+
13391342
// Handle explicit modules build.
13401343
let scanningOutput = delegate.createNode(outputNode.path.dirname.join(outputNode.path.basename + ".scan"))
13411344
let (action, usesExecutionInputs, explicitModulesPayload, explicitModulesSignatureData) = createExplicitModulesActionAndPayload(cbc, delegate, launcher, input, resolvedInputFileType.languageDialect, commandLine: commandLine, scanningOutputPath: scanningOutput.path, isForPCHTask: false, clangInfo: clangInfo)
@@ -1648,6 +1651,22 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
16481651
}
16491652
}
16501653

1654+
func addCompilerSarifFlags(_ cbc: CommandBuildContext, _ outputPath: Path, _ delegate: any TaskGenerationDelegate, _ taskOutputs: inout [any PlannedNode]) -> [String] {
1655+
guard cbc.scope.evaluate(BuiltinMacros.EMIT_SARIF_DIAGNOSTICS_FILE) else {
1656+
return []
1657+
}
1658+
1659+
guard let metadatatype = cbc.producer.lookupFileType(identifier: "text.json.sarif") else {
1660+
return []
1661+
}
1662+
1663+
let securityMetadataNode = delegate.createNode(outputPath)
1664+
let ftb = FileToBuild(absolutePath: securityMetadataNode.path, fileType: metadatatype)
1665+
taskOutputs.append(securityMetadataNode)
1666+
delegate.declareOutput(ftb)
1667+
return ["-fdiagnostics-add-output=sarif:file=" + securityMetadataNode.path.str]
1668+
}
1669+
16511670
/// Specialized function that creates a task for precompiling a particular header.
16521671
private func precompile(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, headerPath: Path, language: GCCCompatibleLanguageDialect, inputFileType: FileTypeSpec, extraArgs: [String], precompPath: Path, clangInfo: DiscoveredClangToolSpecInfo?) -> ClangPrefixInfo.PCHInfo {
16531672

Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,4 +1720,11 @@
17201720
CanSetIncludeInIndex = YES;
17211721
UTI = "public.protobuf-source";
17221722
},
1723+
{
1724+
Identifier = text.json.sarif;
1725+
Type = FileType;
1726+
Name = "Diagnostics log in SARIF format";
1727+
UTI = "com.apple.sarif";
1728+
BasedOn = text.json;
1729+
},
17231730
)

Tests/SWBTaskConstructionTests/TaskConstructionTests.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9536,4 +9536,80 @@ fileprivate struct TaskConstructionTests: CoreBasedTests {
95369536
}
95379537
}
95389538
}
9539+
9540+
@Test(.requireSDKs(.macOS))
9541+
func testEmitSarif() async throws {
9542+
try await withTemporaryDirectory { (tmpDir: Path) async throws -> Void in
9543+
let sources = [
9544+
"SourceFile0.c",
9545+
"SourceFile1.mm",
9546+
"SourceFile2.m",
9547+
"SourceFile3.cpp"
9548+
]
9549+
9550+
let testProject = TestProject(
9551+
"aProject",
9552+
sourceRoot: tmpDir,
9553+
groupTree: TestGroup(
9554+
"SomeFiles", path: "Sources",
9555+
children: sources.map{TestFile($0)}
9556+
),
9557+
buildConfigurations: [
9558+
TestBuildConfiguration("Debug")
9559+
],
9560+
targets: [
9561+
TestStandardTarget(
9562+
"AppTarget",
9563+
type: .application,
9564+
buildConfigurations: [
9565+
TestBuildConfiguration("Debug", buildSettings: [
9566+
"TARGET_BUILD_DIR": "/tmp/SomeFiles.dst",
9567+
"GENERATE_INFOPLIST_FILE": "YES",
9568+
"PRODUCT_NAME": "$(TARGET_NAME)",
9569+
"ARCHS": "x86_64 arm64",
9570+
"EMIT_SARIF_DIAGNOSTICS_FILE": "YES"
9571+
])
9572+
],
9573+
buildPhases: [
9574+
TestSourcesBuildPhase(sources.map{TestBuildFile($0)})
9575+
]
9576+
)]
9577+
)
9578+
9579+
let fs = PseudoFS()
9580+
9581+
let core = try await getCore()
9582+
let tester = try TaskConstructionTester(core, testProject)
9583+
9584+
await tester.checkBuild(BuildParameters(configuration: "Debug"), runDestination: .anyMac, fs: fs) { results -> Void in
9585+
results.checkTarget("AppTarget") { target -> Void in
9586+
let command = "-fdiagnostics-add-output=sarif:file="
9587+
let buildPath = tmpDir.join("build/aProject.build/Debug/AppTarget.build/Objects-normal/")
9588+
for arch in ["x86_64", "arm64"] {
9589+
let metadataPath = buildPath.join(arch)
9590+
let inputs = sources.map{metadataPath.join(Path($0).basenameWithoutSuffix + ".o.compiled.sarif").str}
9591+
9592+
for (source, input) in zip(sources, inputs) {
9593+
results.checkTask(.matchTarget(target), .matchRuleType("CompileC"), .matchRuleItemBasename(source), .matchRuleItem(arch), body: { task in
9594+
task.checkCommandLineContains([command + input])
9595+
task.checkInputs([
9596+
.path(tmpDir.join("Sources").join(source).str),
9597+
.namePattern(.and(.prefix("target-"), .suffix("-generated-headers"))),
9598+
.namePattern(.and(.prefix("target-"), .suffix("-swift-generated-headers"))),
9599+
.namePattern(.and(.prefix("target-"), .suffix("-ModuleVerifierTaskProducer"))),
9600+
.namePattern(.and(.prefix("target-"), .suffix("-begin-compiling"))),
9601+
.name("WorkspaceHeaderMapVFSFilesWritten"),
9602+
])
9603+
task.checkOutputs([
9604+
.path(buildPath.join(arch).join(Path(source).basenameWithoutSuffix + ".o").str),
9605+
.path(metadataPath.join(Path(source).basenameWithoutSuffix + ".o.compiled.sarif").str)
9606+
])
9607+
})
9608+
9609+
}
9610+
}
9611+
}
9612+
}
9613+
}
9614+
}
95399615
}

0 commit comments

Comments
 (0)