From 0d3e3613211126c61e19f799ddaa9e893fc2cc52 Mon Sep 17 00:00:00 2001 From: Alex Hoppen Date: Tue, 23 Sep 2025 14:31:44 +0200 Subject: [PATCH] Add build settings to control the emission of the Index Store Add build settings that allow fine-tuning how the index store is being emitted during index-while-building. --- .../Specs/MetalCompiler.xcspec | 14 ++++ Sources/SWBCore/Specs/CoreBuildSystem.xcspec | 14 ++++ .../SWBUniversalPlatform/Specs/Clang.xcspec | 40 ++++++++++ .../SWBUniversalPlatform/Specs/Swift.xcspec | 27 +++++++ .../SWBTaskConstructionTests/ClangTests.swift | 58 ++++++++++++++ .../SWBTaskConstructionTests/MetalTests.swift | 75 +++++++++++++++++++ .../SwiftTaskConstructionTests.swift | 56 ++++++++++++++ 7 files changed, 284 insertions(+) create mode 100644 Tests/SWBTaskConstructionTests/MetalTests.swift diff --git a/Sources/SWBApplePlatform/Specs/MetalCompiler.xcspec b/Sources/SWBApplePlatform/Specs/MetalCompiler.xcspec index 67c10a8e..97b73fa9 100644 --- a/Sources/SWBApplePlatform/Specs/MetalCompiler.xcspec +++ b/Sources/SWBApplePlatform/Specs/MetalCompiler.xcspec @@ -235,6 +235,20 @@ NO = (); }; }, + { + Name = "METAL_INDEX_STORE_ONLY_PROJECT_FILES"; + Type = Boolean; + DefaultValue = "$(INDEX_STORE_ONLY_PROJECT_FILES)"; + Condition = "$(MTL_ENABLE_INDEX_STORE)"; + CommandLineArgs = { + YES = ( + // See corresponding definition in Clang.xcspec + "-index-ignore-system-symbols", + "-index-ignore-pcms", + ); + NO = (); + }; + }, { Name = "MTL_LANGUAGE_REVISION"; Type = Enumeration; diff --git a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec index e2c35411..d637d308 100644 --- a/Sources/SWBCore/Specs/CoreBuildSystem.xcspec +++ b/Sources/SWBCore/Specs/CoreBuildSystem.xcspec @@ -3505,6 +3505,20 @@ For more information on mergeable libraries, see [Configuring your project to us DisplayName = "Enable Index-While-Building Functionality"; Description = "Control whether the compiler should emit index data while building."; }, + { + Name = "INDEX_STORE_ONLY_PROJECT_FILES"; + Type = Boolean; + DefaultValue = NO; + DisplayName = "Index only project files"; + Description = "Only index the source files that are being compiled within this project. Do not emit data into the index store for system modules."; + }, + { + Name = "INDEX_STORE_COMPRESS"; + Type = Boolean; + DefaultValue = NO; + DisplayName = "Compress Index Store"; + Description = "Compress the index store, reducing its size on disk."; + }, { Name = TOOLCHAINS; Type = StringList; diff --git a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec index d954fdd3..c1fc1295 100644 --- a/Sources/SWBUniversalPlatform/Specs/Clang.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Clang.xcspec @@ -3116,6 +3116,46 @@ NO = (); }; }, + { + Name = "CLANG_INDEX_STORE_ONLY_PROJECT_FILES"; + Type = Boolean; + DefaultValue = "$(INDEX_STORE_ONLY_PROJECT_FILES)"; + Condition = "$(CLANG_INDEX_STORE_ENABLE)"; + CommandLineArgs = { + YES = ( + "-index-ignore-system-symbols", + // If the PCM covers files generated within the project, we should have indexed them in the task that compiles them, otherwise it's a system module that we don't want to index. + "-index-ignore-pcms", + ); + NO = (); + }; + }, + { + Name = "CLANG_INDEX_STORE_COMPRESS"; + Type = Boolean; + DefaultValue = "$(INDEX_STORE_COMPRESS)"; + Condition = "$(CLANG_INDEX_STORE_ENABLE)"; + CommandLineArgs = { + YES = ( + "-index-store-compress", + ); + NO = (); + }; + }, + { + Name = "CLANG_INDEX_STORE_IGNORE_MACROS"; + Type = Boolean; + DefaultValue = NO; + Condition = "$(CLANG_INDEX_STORE_ENABLE)"; + DisplayName = "Do not index C macros"; + Description = "Do not emit entries for C macros into the Index Store."; + CommandLineArgs = { + YES = ( + "-index-ignore-macros", + ); + NO = (); + }; + }, { Name = "CLANG_ENABLE_COMPILE_CACHE"; diff --git a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec index bbd26e45..6d51c94d 100644 --- a/Sources/SWBUniversalPlatform/Specs/Swift.xcspec +++ b/Sources/SWBUniversalPlatform/Specs/Swift.xcspec @@ -1319,6 +1319,33 @@ NO = (); }; }, + { + Name = "SWIFT_INDEX_STORE_ONLY_PROJECT_FILES"; + Type = Boolean; + DefaultValue = "$(INDEX_STORE_ONLY_PROJECT_FILES)"; + Condition = "$(SWIFT_INDEX_STORE_ENABLE)"; + CommandLineArgs = { + YES = ( + // Assume that clang modules are getting indexed by a clang file within them. While this is technically not correct, since you could have a clang module that only consists of header files and is only included from Swift, such scenarios are rare. + "-index-ignore-clang-modules", + "-index-ignore-system-modules", + ); + NO = (); + }; + }, + { + Name = "SWIFT_INDEX_STORE_COMPRESS"; + Type = Boolean; + DefaultValue = "$(INDEX_STORE_COMPRESS)"; + Condition = "$(SWIFT_INDEX_STORE_ENABLE)"; + CommandLineArgs = { + YES = ( + "-Xfrontend", + "-index-store-compress", + ); + NO = (); + }; + }, // Swift caching options. { diff --git a/Tests/SWBTaskConstructionTests/ClangTests.swift b/Tests/SWBTaskConstructionTests/ClangTests.swift index 20010d33..0d2c0bc0 100644 --- a/Tests/SWBTaskConstructionTests/ClangTests.swift +++ b/Tests/SWBTaskConstructionTests/ClangTests.swift @@ -330,4 +330,62 @@ fileprivate struct ClangTests: CoreBasedTests { } } } + + + @Test(.requireSDKs(.host)) + func indexOptions() async throws { + try await withTemporaryDirectory { tmpDir in + let testProject = TestProject( + "ProjectName", + sourceRoot: tmpDir, + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("File1.c") + ]), + targets: [ + TestStandardTarget( + "Test", + type: .dynamicLibrary, + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "COMPILER_INDEX_STORE_ENABLE": "YES", + "INDEX_DATA_STORE_DIR": tmpDir.join("index").str, + "INDEX_STORE_COMPRESS": "YES", + "INDEX_STORE_ONLY_PROJECT_FILES": "YES", + "CLANG_INDEX_STORE_IGNORE_MACROS": "YES", + ] + ), + ], + buildPhases: [ + TestSourcesBuildPhase(["File1.c"]), + ] + ) + ]) + + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: ["INDEX_ENABLE_DATA_STORE": "YES"]), runDestination: .host) { results in + results.checkTask(.matchRuleType("CompileC")) { compileTask in + compileTask.checkCommandLineContains(["-index-store-path"]) + compileTask.checkCommandLineContains(["-index-store-compress"]) + compileTask.checkCommandLineContains(["-index-ignore-system-symbols"]) + compileTask.checkCommandLineContains(["-index-ignore-pcms"]) + compileTask.checkCommandLineContains(["-index-ignore-macros"]) + } + } + // Check that we don't emit any index-related options when INDEX_ENABLE_DATA_STORE is not enabled + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: [:]), runDestination: .host) { results in + results.checkTask(.matchRuleType("CompileC")) { compileTask in + compileTask.checkCommandLineDoesNotContain("-index-store-path") + compileTask.checkCommandLineDoesNotContain("-index-store-compress") + compileTask.checkCommandLineDoesNotContain("-index-ignore-system-symbols") + compileTask.checkCommandLineDoesNotContain("-index-ignore-pcms") + compileTask.checkCommandLineDoesNotContain("-index-ignore-macros") + } + } + } + } } diff --git a/Tests/SWBTaskConstructionTests/MetalTests.swift b/Tests/SWBTaskConstructionTests/MetalTests.swift new file mode 100644 index 00000000..5d22e07b --- /dev/null +++ b/Tests/SWBTaskConstructionTests/MetalTests.swift @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import Testing +import SWBTestSupport +import SWBCore +import SWBUtil + +@Suite +fileprivate struct MetalTests: CoreBasedTests { + @Test(.requireSDKs(.macOS), .skipInGitHubActions("Metal toolchain is not installed on GitHub runners")) + func indexOptions() async throws { + try await withTemporaryDirectory { tmpDir in + let testProject = TestProject( + "ProjectName", + sourceRoot: tmpDir, + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("File1.metal") + ]), + targets: [ + TestStandardTarget( + "Test", + type: .staticLibrary, + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "COMPILER_INDEX_STORE_ENABLE": "YES", + "INDEX_DATA_STORE_DIR": tmpDir.join("index").str, + "INDEX_STORE_COMPRESS": "YES", + "INDEX_STORE_ONLY_PROJECT_FILES": "YES", + "CLANG_INDEX_STORE_IGNORE_MACROS": "YES", + ] + ), + ], + buildPhases: [ + TestSourcesBuildPhase(["File1.metal"]), + ] + ) + ]) + + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: ["INDEX_ENABLE_DATA_STORE": "YES"]), runDestination: .macOS) { results in + results.checkTask(.matchRuleType("CompileMetalFile")) { compileTask in + compileTask.checkCommandLineContains(["-index-store-path"]) + compileTask.checkCommandLineContains(["-index-ignore-system-symbols"]) + compileTask.checkCommandLineContains(["-index-ignore-pcms"]) + // metal doesn't support index store compression at the moment. + compileTask.checkCommandLineDoesNotContain("-index-store-compress") + } + } + // Check that we don't emit any index-related options when INDEX_ENABLE_DATA_STORE is not enabled + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: [:]), runDestination: .macOS) { results in + results.checkTask(.matchRuleType("CompileMetalFile")) { compileTask in + compileTask.checkCommandLineDoesNotContain("-index-store-path") + compileTask.checkCommandLineDoesNotContain("-index-store-compress") + compileTask.checkCommandLineDoesNotContain("-index-ignore-system-symbols") + compileTask.checkCommandLineDoesNotContain("-index-ignore-pcms") + } + } + } + } +} diff --git a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift index f568b54a..76b28c05 100644 --- a/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift +++ b/Tests/SWBTaskConstructionTests/SwiftTaskConstructionTests.swift @@ -4507,6 +4507,62 @@ fileprivate struct SwiftTaskConstructionTests: CoreBasedTests { } } } + + @Test(.requireSDKs(.host)) + func indexOptions() async throws { + try await withTemporaryDirectory { tmpDir in + let testProject = try await TestProject( + "ProjectName", + sourceRoot: tmpDir, + groupTree: TestGroup( + "SomeFiles", + children: [ + TestFile("File1.swift") + ]), + targets: [ + TestStandardTarget( + "Test", + type: .dynamicLibrary, + buildConfigurations: [ + TestBuildConfiguration( + "Debug", + buildSettings: [ + "SWIFT_EXEC": swiftCompilerPath.str, + "SWIFT_VERSION": swiftVersion, + "COMPILER_INDEX_STORE_ENABLE": "YES", + "INDEX_DATA_STORE_DIR": tmpDir.join("index").str, + "INDEX_STORE_COMPRESS": "YES", + "INDEX_STORE_ONLY_PROJECT_FILES": "YES" + ] + ), + ], + buildPhases: [ + TestSourcesBuildPhase(["File1.swift"]), + ] + ) + ]) + + let core = try await getCore() + let tester = try TaskConstructionTester(core, testProject) + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: ["INDEX_ENABLE_DATA_STORE": "YES"]), runDestination: .host) { results in + results.checkTask(.matchRuleType("SwiftDriver Compilation")) { compileTask in + compileTask.checkCommandLineContains(["-index-store-path"]) + compileTask.checkCommandLineContains(["-Xfrontend", "-index-store-compress"]) + compileTask.checkCommandLineContains(["-index-ignore-clang-modules"]) + compileTask.checkCommandLineContains(["-index-ignore-system-modules"]) + } + } + // Check that we don't emit any index-related options when INDEX_ENABLE_DATA_STORE is not enabled + await tester.checkBuild(BuildParameters(configuration: "Debug", commandLineOverrides: [:]), runDestination: .host) { results in + results.checkTask(.matchRuleType("SwiftDriver Compilation")) { compileTask in + compileTask.checkCommandLineDoesNotContain("-index-store-path") + compileTask.checkCommandLineDoesNotContain("-index-store-compress") + compileTask.checkCommandLineDoesNotContain("-index-ignore-clang-modules") + compileTask.checkCommandLineDoesNotContain("-index-ignore-system-modules") + } + } + } + } } private func XCTAssertEqual(_ lhs: EnvironmentBindings, _ rhs: [String: String], file: StaticString = #filePath, line: UInt = #line) {