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
2 changes: 2 additions & 0 deletions Sources/SWBCore/Settings/BuiltinMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand Down
21 changes: 20 additions & 1 deletion Sources/SWBCore/SpecImplementations/Tools/CCompiler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ public class ClangCompilerSpec : CompilerSpec, SpecIdentifierType, GCCCompatible
"-fmessage-length=",
"-fmacro-backtrace-limit=",
"-fbuild-session-timestamp=",
"-fdiagnostics-add-output="
])

static let outputAgnosticCompilerArgumentsWithValues = Set<ByteString>([
Expand Down Expand Up @@ -1219,7 +1220,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?
Expand Down Expand Up @@ -1336,6 +1337,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)
Expand Down Expand Up @@ -1648,6 +1651,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 {

Expand Down
7 changes: 7 additions & 0 deletions Sources/SWBUniversalPlatform/Specs/StandardFileTypes.xcspec
Original file line number Diff line number Diff line change
Expand Up @@ -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;
},
)
76 changes: 76 additions & 0 deletions Tests/SWBTaskConstructionTests/TaskConstructionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9512,4 +9512,80 @@ 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"
])
],
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)
])
})

}
}
}
}
}
}
}
Loading