From ff839fb3d8e9fd247113ac20c5bafa86ebb7d012 Mon Sep 17 00:00:00 2001 From: Usama Date: Thu, 20 Nov 2025 21:27:06 -0800 Subject: [PATCH 1/4] [WIP] Add new clang build setting EMIT_COMPILER_SOURCE_METADATA that passes -fdiagnostic-add-output=sarif:file=. The flag emits a SARIF log during the compilation which contains diagnostic information. The path is currently fixed to .source-metadata.json --- .../SpecImplementations/Tools/CCompiler.swift | 17 ++-- .../SWBUniversalPlatform/Specs/Clang.xcspec | 18 +++++ .../Specs/StandardFileTypes.xcspec | 7 ++ .../TaskConstructionTests.swift | 77 +++++++++++++++++++ 4 files changed, 111 insertions(+), 8 deletions(-) diff --git a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift index ead99dcf..28a5776e 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift @@ -591,10 +591,10 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible required init() { } - func getStandardFlags(_ spec: ClangCompilerSpec, producer: any CommandProducer, scope: MacroEvaluationScope, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { + func getStandardFlags(_ spec: ClangCompilerSpec, cbc: CommandBuildContext, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { // This cache is per-producer, so it is guaranteed to be invariant based on that. - constantFlagsCache.getOrInsert(ConstantFlagsKey(scope: scope, inputFileType: inputFileType)) { - return spec.standardFlags(producer, scope: scope, optionContext: optionContext, delegate: delegate, inputFileType: inputFileType) + constantFlagsCache.getOrInsert(ConstantFlagsKey(scope: cbc.scope, inputFileType: inputFileType)) { + return spec.standardFlags(cbc, optionContext: optionContext, delegate: delegate, inputFileType: inputFileType) } } } @@ -646,8 +646,9 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible super.init(parser, basedOnSpec, isGeneric: false) } - private func standardFlags(_ producer: any CommandProducer, scope: MacroEvaluationScope, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { + private func standardFlags(_ cbc: CommandBuildContext, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { var commandLine = Array() + let producer = cbc.producer, scope = cbc.scope // Add the arguments from the specification. commandLine += self.commandLineFromOptions(producer, scope: scope, inputFileType: inputFileType, optionContext: optionContext, buildOptionsFilter: .specOnly, lookup: { declaration in @@ -657,7 +658,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible return BuiltinMacros.namespace.parseString("NO") } } - return nil + return self.lookup(declaration, cbc, delegate) }).map(\.asString) // Add the common header search paths. @@ -1136,7 +1137,8 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible // // FIXME: Eventually we should just apply this optimization to all generic specs, and then find a way to piggy back on that. let dataCache = cbc.producer.getSpecDataCache(self, cacheType: DataCache.self) - let constantFlags = dataCache.getStandardFlags(self, producer: cbc.producer, scope: cbc.scope, optionContext: clangInfo, delegate: delegate, inputFileType: resolvedInputFileType) + let cbcWithOutput = cbc.outputs.isEmpty ? cbc.appendingOutputs([outputNode.path]) : cbc + let constantFlags = dataCache.getStandardFlags(self, cbc: cbcWithOutput, optionContext: clangInfo, delegate: delegate, inputFileType: resolvedInputFileType) commandLine += constantFlags.flags let responseFileAdditionalOutput = constantFlags.responseFileMapping.keys.sorted().map({"Using response file: \($0.str)"}) additionalOutput.append(contentsOf: responseFileAdditionalOutput) @@ -1157,7 +1159,6 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible inputDeps.append(contentsOf: constantFlags.headerSearchPaths.inputPaths) #endif - let cbcWithOutput = cbc.outputs.isEmpty ? cbc.appendingOutputs([outputNode.path]) : cbc commandLine += self.commandLineFromOptions(cbc.producer, scope: cbc.scope, inputFileType: resolvedInputFileType, optionContext: clangInfo, buildOptionsFilter: .extendedOnly, lookup: { self.lookup($0, cbcWithOutput, delegate) }).map(\.asString) @@ -1681,7 +1682,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible // Add “standard flags”, which are ones that depend only on the variant, architecture, and language (in addition to the identifier, of course). let dataCache = cbc.producer.getSpecDataCache(self, cacheType: DataCache.self) - let constantFlags = dataCache.getStandardFlags(self, producer: cbc.producer, scope: cbc.scope, optionContext: clangInfo, delegate: delegate, inputFileType: inputFileType) + let constantFlags = dataCache.getStandardFlags(self, cbc: cbc, optionContext: clangInfo, delegate: delegate, inputFileType: inputFileType) let responseFileAdditionalOutput = constantFlags.responseFileMapping.keys.sorted().map({"Using response file: \($0.str)"}) commandLine += constantFlags.flags diff --git a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec index d99b24d8..a0c88bf3 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec @@ -109,6 +109,24 @@ NO = (); }; }, + { + Name = "EMIT_COMPILER_SOURCE_METADATA"; + Type = Boolean; + DefaultValue = No; + }, + { + Name = "__CLANG_SOURCE_METADATA_PATH"; + Type = Path; + Condition = "$(EMIT_COMPILER_SOURCE_METADATA)"; + DefaultValue = "$(OutputPath).source-metadata.json"; + CommandLinePrefixFlag = "-fdiagnostics-add-output=sarif:file="; + OutputDependencies = ( + { + Path = "$(__CLANG_SOURCE_METADATA_PATH)"; + FileType = "text.json.compiler-metadata.source"; + }, + ); + }, { Name = "CLANG_MACRO_BACKTRACE_LIMIT"; Type = String; diff --git a/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec index 6afa5833..81bbfdb6 100644 --- a/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec @@ -1720,4 +1720,11 @@ CanSetIncludeInIndex = YES; UTI = "public.protobuf-source"; }, + { + Identifier = text.json.compiler-metadata.source; + Type = FileType; + Name = "Source metadata emitted from compiler"; + UTI = "com.apple.compiler-metadata.source"; + BasedOn = text.json; + }, ) diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 244c4949..2e5b0757 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -9512,4 +9512,81 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } } } + + @Test(.requireSDKs(.macOS)) + func testSourceMetadata() async throws { + try await withTemporaryDirectory { (tmpDir: Path) async throws -> Void in + let sources = [ + "SourceFile0.c", + "SourceFile1.mm", + "SourceFile2.m", + "SourceFile3.cpp" + ] + + let testProject = TestProject( + "aProject", + sourceRoot: tmpDir, + groupTree: TestGroup( + "SomeFiles", path: "Sources", + children: sources.map{TestFile($0)} + ), + buildConfigurations: [ + TestBuildConfiguration("Debug") + ], + targets: [ + TestStandardTarget( + "AppTarget", + type: .application, + buildConfigurations: [ + TestBuildConfiguration("Debug", buildSettings: [ + "TARGET_BUILD_DIR": "/tmp/SomeFiles.dst", + "GENERATE_INFOPLIST_FILE": "YES", + "PRODUCT_NAME": "$(TARGET_NAME)", + "ARCHS": "x86_64 arm64", + "EMIT_COMPILER_SOURCE_METADATA": "YES", + "COMPILER_SOURCE_METADATA_LIST": "/tmp/test.json" + ]) + ], + buildPhases: [ + TestSourcesBuildPhase(sources.map{TestBuildFile($0)}) + ] + )] + ) + + let fs = PseudoFS() + + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + + await tester.checkBuild(BuildParameters(configuration: "Debug"), runDestination: .anyMac, fs: fs) { results -> Void in + results.checkTarget("AppTarget") { target -> Void in + let command = "-fdiagnostics-add-output=sarif:file=" + let buildPath = tmpDir.join("build/aProject.build/Debug/AppTarget.build/Objects-normal/") + for arch in ["x86_64", "arm64"] { + let metadataPath = buildPath.join(arch) + let inputs = sources.map{metadataPath.join(Path($0).basenameWithoutSuffix + ".o.source-metadata.json").str} + + for (source, input) in zip(sources, inputs) { + results.checkTask(.matchTarget(target), .matchRuleType("CompileC"), .matchRuleItemBasename(source), .matchRuleItem(arch), body: { task in + task.checkCommandLineContains([command + input]) + task.checkInputs([ + .path(tmpDir.join("Sources").join(source).str), + .namePattern(.and(.prefix("target-"), .suffix("-generated-headers"))), + .namePattern(.and(.prefix("target-"), .suffix("-swift-generated-headers"))), + .namePattern(.and(.prefix("target-"), .suffix("-ModuleVerifierTaskProducer"))), + .namePattern(.and(.prefix("target-"), .suffix("-begin-compiling"))), + .name("WorkspaceHeaderMapVFSFilesWritten"), + ]) + task.checkOutputs([ + .path(buildPath.join(arch).join(Path(source).basenameWithoutSuffix + ".o").str), + .path(metadataPath.join(Path(source).basenameWithoutSuffix + ".o.source-metadata.json").str) + ]) + }) + + } + } + } + } + } + } } From 721145b334dd424614ef708f2207c770590ded51 Mon Sep 17 00:00:00 2001 From: Usama Date: Tue, 9 Dec 2025 12:36:55 -0800 Subject: [PATCH 2/4] Move EMIT_COMPILER_SOURCE_METADATA to a builtin macro --- Sources/SWBCore/Settings/BuiltinMacros.swift | 2 ++ .../SpecImplementations/Tools/CCompiler.swift | 21 ++++++++++++++++++- .../SWBUniversalPlatform/Specs/Clang.xcspec | 18 ---------------- .../TaskConstructionTests.swift | 3 +-- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index 5570cc92..a87be483 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -639,6 +639,7 @@ public final class BuiltinMacros { public static let EMBEDDED_CONTENT_CONTAINS_SWIFT = BuiltinMacros.declareBooleanMacro("EMBEDDED_CONTENT_CONTAINS_SWIFT") public static let EMBEDDED_PROFILE_NAME = BuiltinMacros.declareStringMacro("EMBEDDED_PROFILE_NAME") public static let EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES = BuiltinMacros.declareStringListMacro("EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES") + public static let EMIT_COMPILER_SOURCE_METADATA = BuiltinMacros.declareBooleanMacro("EMIT_COMPILER_SOURCE_METADATA") public static let EMIT_FRONTEND_COMMAND_LINES = BuiltinMacros.declareBooleanMacro("EMIT_FRONTEND_COMMAND_LINES") public static let ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING = BuiltinMacros.declareBooleanMacro("ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING") public static let ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING = BuiltinMacros.declareBooleanMacro("ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING") @@ -1717,6 +1718,7 @@ public final class BuiltinMacros { EMBEDDED_CONTENT_CONTAINS_SWIFT, EMBEDDED_PROFILE_NAME, EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES, + EMIT_COMPILER_SOURCE_METADATA, EMIT_FRONTEND_COMMAND_LINES, ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING, ENABLE_ADDRESS_SANITIZER, diff --git a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift index 28a5776e..e8123fe1 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift @@ -836,6 +836,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible "-fmessage-length=", "-fmacro-backtrace-limit=", "-fbuild-session-timestamp=", + "-fdiagnostics-add-output=" ]) static let outputAgnosticCompilerArgumentsWithValues = Set([ @@ -1220,7 +1221,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible dependencyData = nil } - let extraOutputs: [any PlannedNode] + var extraOutputs: [any PlannedNode] let moduleDependenciesContext = cbc.producer.moduleDependenciesContext let headerDependenciesContext = cbc.producer.headerDependenciesContext let dependencyValidationOutputPath: Path? @@ -1337,6 +1338,8 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible } } + commandLine += addCompilerMetadataFlags(cbc, outputFileDir.join(outputNode.path.str + ".source-metadata.json"), delegate, &extraOutputs) + // Handle explicit modules build. let scanningOutput = delegate.createNode(outputNode.path.dirname.join(outputNode.path.basename + ".scan")) let (action, usesExecutionInputs, explicitModulesPayload, explicitModulesSignatureData) = createExplicitModulesActionAndPayload(cbc, delegate, launcher, input, resolvedInputFileType.languageDialect, commandLine: commandLine, scanningOutputPath: scanningOutput.path, isForPCHTask: false, clangInfo: clangInfo) @@ -1649,6 +1652,22 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible } } + func addCompilerMetadataFlags(_ cbc: CommandBuildContext, _ outputPath: Path, _ delegate: any TaskGenerationDelegate, _ taskOutputs: inout [any PlannedNode]) -> [String] { + guard cbc.scope.evaluate(BuiltinMacros.EMIT_COMPILER_SOURCE_METADATA) else { + return [] + } + + guard let metadatatype = cbc.producer.lookupFileType(identifier: "text.json.compiler-metadata.source") else { + return [] + } + + let securityMetadataNode = delegate.createNode(outputPath) + let ftb = FileToBuild(absolutePath: securityMetadataNode.path, fileType: metadatatype) + taskOutputs.append(securityMetadataNode) + delegate.declareOutput(ftb) + return ["-fdiagnostics-add-output=sarif:file=" + securityMetadataNode.path.str] + } + /// Specialized function that creates a task for precompiling a particular header. private func precompile(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate, headerPath: Path, language: GCCCompatibleLanguageDialect, inputFileType: FileTypeSpec, extraArgs: [String], precompPath: Path, clangInfo: DiscoveredClangToolSpecInfo?) -> ClangPrefixInfo.PCHInfo { diff --git a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec index a0c88bf3..d99b24d8 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec @@ -109,24 +109,6 @@ NO = (); }; }, - { - Name = "EMIT_COMPILER_SOURCE_METADATA"; - Type = Boolean; - DefaultValue = No; - }, - { - Name = "__CLANG_SOURCE_METADATA_PATH"; - Type = Path; - Condition = "$(EMIT_COMPILER_SOURCE_METADATA)"; - DefaultValue = "$(OutputPath).source-metadata.json"; - CommandLinePrefixFlag = "-fdiagnostics-add-output=sarif:file="; - OutputDependencies = ( - { - Path = "$(__CLANG_SOURCE_METADATA_PATH)"; - FileType = "text.json.compiler-metadata.source"; - }, - ); - }, { Name = "CLANG_MACRO_BACKTRACE_LIMIT"; Type = String; diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index 2e5b0757..e684eae6 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -9543,8 +9543,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "GENERATE_INFOPLIST_FILE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", "ARCHS": "x86_64 arm64", - "EMIT_COMPILER_SOURCE_METADATA": "YES", - "COMPILER_SOURCE_METADATA_LIST": "/tmp/test.json" + "EMIT_COMPILER_SOURCE_METADATA": "YES" ]) ], buildPhases: [ From e384676fea88a70f03dc570733f9fa1e773f9340 Mon Sep 17 00:00:00 2001 From: Usama Date: Tue, 9 Dec 2025 12:44:09 -0800 Subject: [PATCH 3/4] Revert unnecessary changes --- .../SpecImplementations/Tools/CCompiler.swift | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift index e8123fe1..f3ba1595 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift @@ -591,10 +591,10 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible required init() { } - func getStandardFlags(_ spec: ClangCompilerSpec, cbc: CommandBuildContext, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { + func getStandardFlags(_ spec: ClangCompilerSpec, producer: any CommandProducer, scope: MacroEvaluationScope, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { // This cache is per-producer, so it is guaranteed to be invariant based on that. - constantFlagsCache.getOrInsert(ConstantFlagsKey(scope: cbc.scope, inputFileType: inputFileType)) { - return spec.standardFlags(cbc, optionContext: optionContext, delegate: delegate, inputFileType: inputFileType) + constantFlagsCache.getOrInsert(ConstantFlagsKey(scope: scope, inputFileType: inputFileType)) { + return spec.standardFlags(producer, scope: scope, optionContext: optionContext, delegate: delegate, inputFileType: inputFileType) } } } @@ -646,9 +646,8 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible super.init(parser, basedOnSpec, isGeneric: false) } - private func standardFlags(_ cbc: CommandBuildContext, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { + private func standardFlags(_ producer: any CommandProducer, scope: MacroEvaluationScope, optionContext: (any BuildOptionGenerationContext)?, delegate: any TaskGenerationDelegate, inputFileType: FileTypeSpec) -> ConstantFlags { var commandLine = Array() - let producer = cbc.producer, scope = cbc.scope // Add the arguments from the specification. commandLine += self.commandLineFromOptions(producer, scope: scope, inputFileType: inputFileType, optionContext: optionContext, buildOptionsFilter: .specOnly, lookup: { declaration in @@ -658,7 +657,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible return BuiltinMacros.namespace.parseString("NO") } } - return self.lookup(declaration, cbc, delegate) + return nil }).map(\.asString) // Add the common header search paths. @@ -1138,8 +1137,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible // // FIXME: Eventually we should just apply this optimization to all generic specs, and then find a way to piggy back on that. let dataCache = cbc.producer.getSpecDataCache(self, cacheType: DataCache.self) - let cbcWithOutput = cbc.outputs.isEmpty ? cbc.appendingOutputs([outputNode.path]) : cbc - let constantFlags = dataCache.getStandardFlags(self, cbc: cbcWithOutput, optionContext: clangInfo, delegate: delegate, inputFileType: resolvedInputFileType) + let constantFlags = dataCache.getStandardFlags(self, producer: cbc.producer, scope: cbc.scope, optionContext: clangInfo, delegate: delegate, inputFileType: resolvedInputFileType) commandLine += constantFlags.flags let responseFileAdditionalOutput = constantFlags.responseFileMapping.keys.sorted().map({"Using response file: \($0.str)"}) additionalOutput.append(contentsOf: responseFileAdditionalOutput) @@ -1160,6 +1158,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible inputDeps.append(contentsOf: constantFlags.headerSearchPaths.inputPaths) #endif + let cbcWithOutput = cbc.outputs.isEmpty ? cbc.appendingOutputs([outputNode.path]) : cbc commandLine += self.commandLineFromOptions(cbc.producer, scope: cbc.scope, inputFileType: resolvedInputFileType, optionContext: clangInfo, buildOptionsFilter: .extendedOnly, lookup: { self.lookup($0, cbcWithOutput, delegate) }).map(\.asString) @@ -1701,7 +1700,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible // Add “standard flags”, which are ones that depend only on the variant, architecture, and language (in addition to the identifier, of course). let dataCache = cbc.producer.getSpecDataCache(self, cacheType: DataCache.self) - let constantFlags = dataCache.getStandardFlags(self, cbc: cbc, optionContext: clangInfo, delegate: delegate, inputFileType: inputFileType) + let constantFlags = dataCache.getStandardFlags(self, producer: cbc.producer, scope: cbc.scope, optionContext: clangInfo, delegate: delegate, inputFileType: inputFileType) let responseFileAdditionalOutput = constantFlags.responseFileMapping.keys.sorted().map({"Using response file: \($0.str)"}) commandLine += constantFlags.flags From 8d321a530fed7eca1eab0985d2a70e1a20eda7cd Mon Sep 17 00:00:00 2001 From: Usama Date: Wed, 10 Dec 2025 19:48:46 -0800 Subject: [PATCH 4/4] Address feedback --- Sources/SWBCore/Settings/BuiltinMacros.swift | 4 ++-- Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift | 8 ++++---- .../SWBUniversalPlatform/Specs/StandardFileTypes.xcspec | 6 +++--- .../SWBTaskConstructionTests/TaskConstructionTests.swift | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Sources/SWBCore/Settings/BuiltinMacros.swift b/Sources/SWBCore/Settings/BuiltinMacros.swift index a87be483..04da1fb9 100644 --- a/Sources/SWBCore/Settings/BuiltinMacros.swift +++ b/Sources/SWBCore/Settings/BuiltinMacros.swift @@ -639,7 +639,7 @@ public final class BuiltinMacros { public static let EMBEDDED_CONTENT_CONTAINS_SWIFT = BuiltinMacros.declareBooleanMacro("EMBEDDED_CONTENT_CONTAINS_SWIFT") public static let EMBEDDED_PROFILE_NAME = BuiltinMacros.declareStringMacro("EMBEDDED_PROFILE_NAME") public static let EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES = BuiltinMacros.declareStringListMacro("EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES") - public static let EMIT_COMPILER_SOURCE_METADATA = BuiltinMacros.declareBooleanMacro("EMIT_COMPILER_SOURCE_METADATA") + public static let EMIT_SARIF_DIAGNOSTICS_FILE = BuiltinMacros.declareBooleanMacro("EMIT_SARIF_DIAGNOSTICS_FILE") public static let EMIT_FRONTEND_COMMAND_LINES = BuiltinMacros.declareBooleanMacro("EMIT_FRONTEND_COMMAND_LINES") public static let ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING = BuiltinMacros.declareBooleanMacro("ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING") public static let ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING = BuiltinMacros.declareBooleanMacro("ENABLE_ADDITIONAL_CODESIGN_INPUT_TRACKING") @@ -1718,7 +1718,7 @@ public final class BuiltinMacros { EMBEDDED_CONTENT_CONTAINS_SWIFT, EMBEDDED_PROFILE_NAME, EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES, - EMIT_COMPILER_SOURCE_METADATA, + EMIT_SARIF_DIAGNOSTICS_FILE, EMIT_FRONTEND_COMMAND_LINES, ENABLE_APPINTENTS_DEPLOYMENT_AWARE_PROCESSING, ENABLE_ADDRESS_SANITIZER, diff --git a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift index f3ba1595..a031a9c2 100644 --- a/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift +++ b/Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift @@ -1337,7 +1337,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible } } - commandLine += addCompilerMetadataFlags(cbc, outputFileDir.join(outputNode.path.str + ".source-metadata.json"), delegate, &extraOutputs) + commandLine += addCompilerSarifFlags(cbc, outputFileDir.join(outputNode.path.str + ".compiled.sarif"), delegate, &extraOutputs) // Handle explicit modules build. let scanningOutput = delegate.createNode(outputNode.path.dirname.join(outputNode.path.basename + ".scan")) @@ -1651,12 +1651,12 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible } } - func addCompilerMetadataFlags(_ cbc: CommandBuildContext, _ outputPath: Path, _ delegate: any TaskGenerationDelegate, _ taskOutputs: inout [any PlannedNode]) -> [String] { - guard cbc.scope.evaluate(BuiltinMacros.EMIT_COMPILER_SOURCE_METADATA) else { + func addCompilerSarifFlags(_ cbc: CommandBuildContext, _ outputPath: Path, _ delegate: any TaskGenerationDelegate, _ taskOutputs: inout [any PlannedNode]) -> [String] { + guard cbc.scope.evaluate(BuiltinMacros.EMIT_SARIF_DIAGNOSTICS_FILE) else { return [] } - guard let metadatatype = cbc.producer.lookupFileType(identifier: "text.json.compiler-metadata.source") else { + guard let metadatatype = cbc.producer.lookupFileType(identifier: "text.json.sarif") else { return [] } diff --git a/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec b/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec index 81bbfdb6..d5f4c79c 100644 --- a/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec @@ -1721,10 +1721,10 @@ UTI = "public.protobuf-source"; }, { - Identifier = text.json.compiler-metadata.source; + Identifier = text.json.sarif; Type = FileType; - Name = "Source metadata emitted from compiler"; - UTI = "com.apple.compiler-metadata.source"; + Name = "Diagnostics log in SARIF format"; + UTI = "com.apple.sarif"; BasedOn = text.json; }, ) diff --git a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift index e684eae6..670a9361 100644 --- a/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/TaskConstructionTests.swift @@ -9514,7 +9514,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { } @Test(.requireSDKs(.macOS)) - func testSourceMetadata() async throws { + func testEmitSarif() async throws { try await withTemporaryDirectory { (tmpDir: Path) async throws -> Void in let sources = [ "SourceFile0.c", @@ -9543,7 +9543,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { "GENERATE_INFOPLIST_FILE": "YES", "PRODUCT_NAME": "$(TARGET_NAME)", "ARCHS": "x86_64 arm64", - "EMIT_COMPILER_SOURCE_METADATA": "YES" + "EMIT_SARIF_DIAGNOSTICS_FILE": "YES" ]) ], buildPhases: [ @@ -9563,7 +9563,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { let buildPath = tmpDir.join("build/aProject.build/Debug/AppTarget.build/Objects-normal/") for arch in ["x86_64", "arm64"] { let metadataPath = buildPath.join(arch) - let inputs = sources.map{metadataPath.join(Path($0).basenameWithoutSuffix + ".o.source-metadata.json").str} + let inputs = sources.map{metadataPath.join(Path($0).basenameWithoutSuffix + ".o.compiled.sarif").str} for (source, input) in zip(sources, inputs) { results.checkTask(.matchTarget(target), .matchRuleType("CompileC"), .matchRuleItemBasename(source), .matchRuleItem(arch), body: { task in @@ -9578,7 +9578,7 @@ fileprivate struct TaskConstructionTests: CoreBasedTests { ]) task.checkOutputs([ .path(buildPath.join(arch).join(Path(source).basenameWithoutSuffix + ".o").str), - .path(metadataPath.join(Path(source).basenameWithoutSuffix + ".o.source-metadata.json").str) + .path(metadataPath.join(Path(source).basenameWithoutSuffix + ".o.compiled.sarif").str) ]) })