Skip to content

Commit 5b1014e

Browse files
authored
Merge pull request #852 from cyndyishida/eng/PR-156935289
Disable modular builds when compiling for >= c++20 modes
2 parents 320e518 + 18c8c31 commit 5b1014e

File tree

2 files changed

+118
-1
lines changed

2 files changed

+118
-1
lines changed

Sources/SWBUniversalPlatform/Specs/Clang.xcspec

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,18 @@
365365
"sourcecode.cpp.cpp",
366366
"sourcecode.cpp.objcpp"
367367
);
368-
Condition = "$(CLANG_ENABLE_MODULES)";
368+
// Disable c++ modules if it was set by CLANG_ENABLE_MODULES or
369+
// when using a c++ language mode that implicitly enables it.
370+
Condition = "$(CLANG_ENABLE_MODULES) ||
371+
!($(CLANG_CXX_LANGUAGE_STANDARD) == 'c++98' ||
372+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'gnu++98' ||
373+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'c++0x' ||
374+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'gnu++0x' ||
375+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'c++14' ||
376+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'gnu++14' ||
377+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'c++17' ||
378+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'gnu++17'||
379+
$(CLANG_CXX_LANGUAGE_STANDARD) == 'compiler-default')";
369380
// Intentionally hidden.
370381
},
371382
{

Tests/SWBCoreTests/CommandLineSpecTests.swift

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,112 @@ import SWBMacro
10751075
}
10761076
}
10771077

1078+
@Test
1079+
func clangCompileTaskConstructionWithCXX20ModulesDisabled() async throws {
1080+
let core = try await getCore()
1081+
let clangSpec = try core.specRegistry.getSpec("com.apple.compilers.llvm.clang.1_0") as CommandLineToolSpec
1082+
1083+
// Create the dummy table. We include all the defaults for the tool specification.
1084+
var table = MacroValueAssignmentTable(namespace: core.specRegistry.internalMacroNamespace)
1085+
for option in clangSpec.flattenedOrderedBuildOptions {
1086+
guard let value = option.defaultValue else { continue }
1087+
table.push(option.macro, value)
1088+
}
1089+
// We also add some other settings that are more contextual in nature.
1090+
table.push(BuiltinMacros.CURRENT_ARCH, literal: "x86_64")
1091+
table.push(BuiltinMacros.arch, literal: "x86_64")
1092+
table.push(BuiltinMacros.LLVM_TARGET_TRIPLE_VENDOR, literal: "apple")
1093+
table.push(BuiltinMacros.LLVM_TARGET_TRIPLE_OS_VERSION, BuiltinMacros.namespace.parseString("$(SWIFT_PLATFORM_TARGET_PREFIX)$($(DEPLOYMENT_TARGET_SETTING_NAME))"))
1094+
table.push(BuiltinMacros.SWIFT_PLATFORM_TARGET_PREFIX, literal: "macos")
1095+
table.push(BuiltinMacros.DEPLOYMENT_TARGET_SETTING_NAME, literal: "MACOSX_DEPLOYMENT_TARGET")
1096+
table.push(BuiltinMacros.MACOSX_DEPLOYMENT_TARGET, literal: "13.0")
1097+
table.push(BuiltinMacros.CURRENT_VARIANT, literal: "normal")
1098+
table.push(BuiltinMacros.PRODUCT_NAME, literal: "Product")
1099+
table.push(BuiltinMacros.TEMP_DIR, literal: Path.root.join("tmp").str)
1100+
table.push(BuiltinMacros.OBJECT_FILE_DIR, literal: Path.root.join("tmp/output/obj").str)
1101+
table.push(BuiltinMacros.PER_ARCH_OBJECT_FILE_DIR, BuiltinMacros.namespace.parseString("$(OBJECT_FILE_DIR)-$(CURRENT_VARIANT)/$(CURRENT_ARCH)"))
1102+
table.push(BuiltinMacros.BUILT_PRODUCTS_DIR, literal: Path.root.join("tmp/output/sym").str)
1103+
table.push(BuiltinMacros.ENABLE_DEFAULT_SEARCH_PATHS, literal: true)
1104+
table.push(BuiltinMacros.CLANG_ENABLE_MODULES, literal: false)
1105+
1106+
// Turn off response files, so we can directly check arguments
1107+
table.push(BuiltinMacros.CLANG_USE_RESPONSE_FILE, literal: false)
1108+
1109+
/// Utility method to create a task and pass it to a checker block.
1110+
func createTask(with table: MacroValueAssignmentTable, cxxLangMode: String , spec: String, _ checkTask: ((inout PlannedTaskBuilder) -> Void),
1111+
sourceLocation: SourceLocation = #_sourceLocation) async throws {
1112+
var configTable = table
1113+
configTable.push(BuiltinMacros.CLANG_CXX_LANGUAGE_STANDARD, literal: cxxLangMode)
1114+
// Create the delegate, scope, file type, etc.
1115+
let producer = try MockCommandProducer(core: core, productTypeIdentifier: "com.apple.product-type.framework", platform: "macosx")
1116+
let delegate = try CapturingTaskGenerationDelegate(producer: producer, userPreferences: .defaultForTesting)
1117+
let dummyScope = MacroEvaluationScope(table: configTable)
1118+
let dummyFileType = try core.specRegistry.getSpec(spec) as FileTypeSpec
1119+
1120+
// Create the build context for the command.
1121+
let cbc = CommandBuildContext(producer: producer, scope: dummyScope, inputs: [FileToBuild(absolutePath: Path.root.join("tmp/input.mm"), fileType: dummyFileType)], output: nil)
1122+
1123+
// Ask the specification to construct the tasks.
1124+
await clangSpec.constructTasks(cbc, delegate)
1125+
1126+
guard var task = delegate.shellTasks.last, task.ruleInfo.first == "CompileC" else {
1127+
Issue.record("Failed to find compile task")
1128+
return
1129+
}
1130+
checkTask(&task)
1131+
}
1132+
1133+
for cxxLangMode in ["c++20", "c++23", "gnu++20", "gnu++23"] {
1134+
try await createTask(with: table, cxxLangMode: cxxLangMode, spec: "sourcecode.cpp.objcpp") { task in
1135+
#expect(task.ruleInfo == ["CompileC", Path.root.join("tmp/output/obj-normal/x86_64/input.o").str, Path.root.join("tmp/input.mm").str, "normal", "x86_64", "objective-c++", "com.apple.compilers.llvm.clang.1_0"])
1136+
#expect(task.execDescription == "Compile input.mm (x86_64)")
1137+
#expect(clangSpec.interestingPath(for: Task(&task))?.str == Path.root.join("tmp/input.mm").str)
1138+
task.checkCommandLineMatches(["-std=\(cxxLangMode)", .anySequence, "-fno-cxx-modules", .anySequence])
1139+
task.checkCommandLineDoesNotContain("-fmodules")
1140+
task.checkCommandLineDoesNotContain("-fcxx-modules")
1141+
1142+
task.checkInputs([
1143+
.path(Path.root.join("tmp/input.mm").str)
1144+
])
1145+
task.checkOutputs([
1146+
.path(Path.root.join("tmp/output/obj-normal/x86_64/input.o").str)
1147+
])
1148+
#expect(task.dependencyData != nil)
1149+
#expect(task.payload != nil)
1150+
}
1151+
}
1152+
1153+
// Validate that the presence of -fcxx-modules shows up **after** the disablement flag.
1154+
table.push(BuiltinMacros.OTHER_CPLUSPLUSFLAGS, literal: ["-fcxx-modules"])
1155+
try await createTask(with: table, cxxLangMode: "c++20", spec: "sourcecode.cpp.objcpp") { task in
1156+
#expect(task.ruleInfo == ["CompileC", Path.root.join("tmp/output/obj-normal/x86_64/input.o").str, Path.root.join("tmp/input.mm").str, "normal", "x86_64", "objective-c++", "com.apple.compilers.llvm.clang.1_0"])
1157+
#expect(task.execDescription == "Compile input.mm (x86_64)")
1158+
task.checkCommandLineMatches(["-fno-cxx-modules", .anySequence, "-fcxx-modules"])
1159+
}
1160+
1161+
// Validate that no explicit module options are passed on language modes less than c++20.
1162+
// Note, the current compiler default is c++14.
1163+
for cxxLangMode in ["c++98", "gnu++0x", "c++17", "gnu++14", "compiler-default"] {
1164+
try await createTask(with: table, cxxLangMode: cxxLangMode, spec: "sourcecode.cpp.objcpp") { task in
1165+
#expect(task.ruleInfo == ["CompileC", Path.root.join("tmp/output/obj-normal/x86_64/input.o").str, Path.root.join("tmp/input.mm").str, "normal", "x86_64", "objective-c++", "com.apple.compilers.llvm.clang.1_0"])
1166+
#expect(task.execDescription == "Compile input.mm (x86_64)")
1167+
#expect(clangSpec.interestingPath(for: Task(&task))?.str == Path.root.join("tmp/input.mm").str)
1168+
task.checkCommandLineDoesNotContain("-fno-cxx-modules")
1169+
1170+
task.checkInputs([
1171+
.path(Path.root.join("tmp/input.mm").str)
1172+
])
1173+
task.checkOutputs([
1174+
.path(Path.root.join("tmp/output/obj-normal/x86_64/input.o").str)
1175+
])
1176+
#expect(task.dependencyData != nil)
1177+
#expect(task.payload != nil)
1178+
}
1179+
}
1180+
1181+
1182+
}
1183+
10781184

10791185
/// Check that C_COMPILER_LAUNCHER is honored.
10801186
@Test(.skipHostOS(.windows, "output file is coming out as tmp\\input.o (non-absolute)"))

0 commit comments

Comments
 (0)