From 12b271f15594c897caf0ddd3e9941b6dd041997b Mon Sep 17 00:00:00 2001 From: Naveen Seth Hanig Date: Thu, 23 Apr 2026 09:35:17 +0200 Subject: [PATCH 1/2] Reapply "[clang][modules-driver] Add support for C++ named modules and `import std`" This reverts #193677 and relands #193312. This adds basic support for explicit C++ named module builds, managed natively by the Clang driver, including support for use of the Standard library modules. This follows #187606, which adds the same for Clang modules. Current limitations: - Standard library modules are still compiled to object files instead of using the provided shared library. (This will be addressed in a follow-up soon.) - Caching is not supported yet (but likely to be added during the upcoming GSoC cycle). - Importing C++ standard library modules into Clang modules is not supported (and not expected in the near term). RFC: https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system --- .../clang/Basic/DiagnosticDriverKinds.td | 2 + clang/include/clang/Driver/ModulesDriver.h | 4 + clang/lib/Driver/Driver.cpp | 2 + clang/lib/Driver/ModulesDriver.cpp | 100 ++++++++++++++-- .../modules-driver-both-modules-types.cpp | 111 ++++++++++++++++++ .../modules-driver-cxx-modules-only.cpp | 88 ++++++++++++++ .../test/Driver/modules-driver-import-std.cpp | 60 ++++++++++ .../modules-driver-incompatible-options.cpp | 10 ++ 8 files changed, 366 insertions(+), 11 deletions(-) create mode 100644 clang/test/Driver/modules-driver-both-modules-types.cpp create mode 100644 clang/test/Driver/modules-driver-cxx-modules-only.cpp create mode 100644 clang/test/Driver/modules-driver-import-std.cpp create mode 100644 clang/test/Driver/modules-driver-incompatible-options.cpp diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 469045948a47c..2e38c5f7d450f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -613,6 +613,8 @@ def err_drv_reduced_module_output_overrided : Warning< "please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">, InGroup>; +def err_drv_modules_driver_requires_reduced_bmi : Error< + "'-fmodules-driver' is currently incompatible with '-fno-modules-reduced-bmi'">; def remark_performing_driver_managed_module_build : Remark< "performing driver managed module build">, InGroup; def remark_modules_manifest_not_found : Remark< diff --git a/clang/include/clang/Driver/ModulesDriver.h b/clang/include/clang/Driver/ModulesDriver.h index 4f5fe7a7dfc1a..7146d2f6b143f 100644 --- a/clang/include/clang/Driver/ModulesDriver.h +++ b/clang/include/clang/Driver/ModulesDriver.h @@ -32,6 +32,10 @@ class Compilation; namespace clang::driver::modules { +/// Emits diagnostics for arguments incompatible with -fmodules-driver. +void diagnoseModulesDriverArgs(llvm::opt::DerivedArgList &DAL, + DiagnosticsEngine &Diags); + /// The parsed Standard library module manifest. struct StdModuleManifest { struct Module { diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index a7f8820fc991a..c98ac919f7d2a 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1837,6 +1837,8 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { if (UseModulesDriver) { Diags.Report(diag::remark_performing_driver_managed_module_build); + modules::diagnoseModulesDriverArgs(C->getArgs(), Diags); + // Read the Standard library module manifest and, if available, add all // discovered modules to this Compilation. Jobs for modules specified in // the manifest that are not required by any command-line input are pruned diff --git a/clang/lib/Driver/ModulesDriver.cpp b/clang/lib/Driver/ModulesDriver.cpp index 826ee4966a647..f439c7e733954 100644 --- a/clang/lib/Driver/ModulesDriver.cpp +++ b/clang/lib/Driver/ModulesDriver.cpp @@ -21,6 +21,7 @@ #include "clang/Driver/Job.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" +#include "clang/Driver/Types.h" #include "clang/Frontend/StandaloneDiagnostic.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" @@ -47,6 +48,14 @@ using namespace clang; using namespace driver; using namespace modules; +void driver::modules::diagnoseModulesDriverArgs(llvm::opt::DerivedArgList &DAL, + DiagnosticsEngine &Diags) { + if (!DAL.hasFlag(options::OPT_fmodules_reduced_bmi, + options::OPT_fno_modules_reduced_bmi, true)) { + Diags.Report(diag::err_drv_modules_driver_requires_reduced_bmi); + } +} + namespace clang::driver::modules { static bool fromJSON(const llvm::json::Value &Params, StdModuleManifest::Module::LocalArguments &LocalArgs, @@ -1252,6 +1261,16 @@ static SmallVector createNodesForUnusedStdlibModuleJobs( return StdlibModuleNodesToPrune; } +// Returns the derived argument list for the tool chain responsible +// for creating \p Job. +static const DerivedArgList &getToolChainArgs(Compilation &C, + const Command &Job) { + const auto &TC = Job.getCreator().getToolChain(); + const auto &SourceAction = Job.getSource(); + return C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(), + SourceAction.getOffloadingDeviceKind()); +} + /// Creates a job for the Clang module described by \p MD. static std::unique_ptr createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob, @@ -1263,9 +1282,7 @@ createClangModulePrecompileJob(Compilation &C, const Command &ImportingJob, Action *PA = C.MakeAction(IA, types::ID::TY_ModuleFile); PA->propagateOffloadInfo(&ImportingJob.getSource()); - const auto &TC = ImportingJob.getCreator().getToolChain(); - const auto &TCArgs = C.getArgsForToolChain(&TC, PA->getOffloadingArch(), - PA->getOffloadingDeviceKind()); + const auto &TCArgs = getToolChainArgs(C, ImportingJob); const auto &BuildArgs = MD.getBuildArguments(); ArgStringList JobArgs; @@ -1319,12 +1336,7 @@ installScanCommandLines(Compilation &C, ArgStringList JobArgs; JobArgs.reserve(BuildArgs.size()); - const auto &SourceAction = Job.getSource(); - const auto &TC = Job.getCreator().getToolChain(); - auto &TCArgs = - C.getArgsForToolChain(&TC, SourceAction.getOffloadingArch(), - SourceAction.getOffloadingDeviceKind()); - + auto &TCArgs = getToolChainArgs(C, Job); for (const auto &Arg : BuildArgs) JobArgs.push_back(TCArgs.MakeArgString(Arg)); @@ -1527,6 +1539,73 @@ static void createAndConnectRoot(CompilationGraph &Graph) { } } +/// Creates a temporary output path for \p ModuleName. +static std::string createModuleOutputPath(const Compilation &C, + StringRef ModuleName) { + // Sanitize the ':' included in parition names. It is illegal for filenames on + // Windows. + SmallString<32> SanitizedModuleName(ModuleName); + llvm::replace(SanitizedModuleName, ':', '-'); + auto ModuleOutputPath = C.getDriver().GetTemporaryPath( + SanitizedModuleName, types::getTypeTempSuffix(types::TY_ModuleFile)); + return ModuleOutputPath; +} + +/// Adds the '-fmodule-output=' argument for the module produced by \p Node. +static void configureNamedModuleOutputArg(Compilation &C, + NamedModuleJobNode &Node, + StringRef ModuleOutputPath) { + auto &Job = *Node.Job; + const auto &TCArgs = getToolChainArgs(C, Job); + auto JobArgs = Job.getArguments(); + JobArgs.push_back( + TCArgs.MakeArgString("-fmodule-output=" + ModuleOutputPath)); + Job.replaceArguments(std::move(JobArgs)); +} + +/// Propagates the '-fmodule-file=' mapping for the named module described by +/// \p Node to each dependent job. +static void propagateModuleFileMappingArg(Compilation &C, + NamedModuleJobNode &Node, + StringRef ModuleOutputPath) { + const StringRef ModuleName = Node.InputDeps.ModuleName; + + auto DependentNodes = llvm::drop_begin(llvm::depth_first(&Node)); + auto DependentScannedNodes = llvm::map_range( + llvm::make_filter_range(DependentNodes, llvm::IsaPred), + llvm::CastTo); + + for (ScannedJobNode *DependentNode : DependentScannedNodes) { + auto &DependentJob = *DependentNode->Job; + const auto &TCArgs = getToolChainArgs(C, DependentJob); + auto JobArgs = DependentJob.getArguments(); + JobArgs.push_back(TCArgs.MakeArgString("-fmodule-file=" + ModuleName + "=" + + ModuleOutputPath)); + DependentJob.replaceArguments(std::move(JobArgs)); + } +} + +/// Finalizes command lines for C++20 named module dependencies. +/// +/// The command lines produced by dependency scanning are only adjusted to +/// handle discovered Clang modules. For C++20 named modules, we update the +/// command-lines here. +static void fixupNamedModuleCommandLines(Compilation &C, + CompilationGraph &Graph) { + const auto NamedModuleNodes = llvm::map_range( + llvm::make_filter_range(Graph, llvm::IsaPred), + llvm::CastTo); + + for (NamedModuleJobNode *Node : NamedModuleNodes) { + const StringRef ModuleName = Node->InputDeps.ModuleName; + const auto ModuleOutputPath = createModuleOutputPath(C, ModuleName); + C.addTempFile(C.getArgs().MakeArgString(ModuleOutputPath)); + + configureNamedModuleOutputArg(C, *Node, ModuleOutputPath); + propagateModuleFileMappingArg(C, *Node, ModuleOutputPath); + } +} + /// Moves jobs from \p Graph into \p C in the graph's topological order. static void feedJobsBackIntoCompilation(Compilation &C, CompilationGraph &&Graph) { @@ -1600,7 +1679,6 @@ void driver::modules::runModulesDriver( if (!Diags.isLastDiagnosticIgnored()) llvm::WriteGraph(llvm::errs(), &Graph); - // TODO: Fix-up command-lines for named module imports. - + fixupNamedModuleCommandLines(C, Graph); feedJobsBackIntoCompilation(C, std::move(Graph)); } diff --git a/clang/test/Driver/modules-driver-both-modules-types.cpp b/clang/test/Driver/modules-driver-both-modules-types.cpp new file mode 100644 index 0000000000000..0a88917165e37 --- /dev/null +++ b/clang/test/Driver/modules-driver-both-modules-types.cpp @@ -0,0 +1,111 @@ +// Checks that -fmodules-driver correctly handles compilations using both +// Standard C++20 modules and Clang modules. +// Importing a Standard C++20 module into Clang module is not supported yet. + +// RUN: split-file %s %t +// RUN: rm -rf %t/modules-cache + +// RUN: %clang -c -std=c++23 \ +// RUN: -fmodules-driver -Rmodules-driver \ +// RUN: -fmodules -Rmodule-import \ +// RUN: -fmodule-map-file=%t/module.modulemap \ +// RUN: -fmodules-cache-path=%t/modules-cache \ +// RUN: %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t --check-prefix=CHECK-REMARKS %s + +// The scan itself will also produce [-Rmodule-import] remarks. +// Let's skip past them, we only care about the final -cc1 commands. +// CHECK-REMARKS: clang: remark: printing module dependency graph [-Rmodules-driver] +// CHECK-REMARKS-NEXT: digraph "Module Dependency Graph" { +// CHECK-REMARKS: } + +// CHECK-REMARKS: [[PREFIX]]/A-part1-impl.cppm:2:2: remark: importing module 'root' from +// CHECK-REMARKS: [[PREFIX]]/A-part1.cppm:2:2: remark: importing module 'root' from +// CHECK-REMARKS: [[PREFIX]]/A.cppm:2:2: remark: importing module 'root' from +// CHECK-REMARKS: [[PREFIX]]/A.cppm:4:8: remark: importing module 'A:part1' from +// CHECK-REMARKS: [[PREFIX]]/A.cppm:4:8: remark: importing module 'root' into 'A:part1' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'root' into 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A:part1' into 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'root' into 'A:part1' from + +// RUN: %clang -std=c++23 \ +// RUN: -fmodules-driver -Rmodules-driver \ +// RUN: -fmodules -Rmodule-import \ +// RUN: -fmodule-map-file=%t/module.modulemap \ +// RUN: -fmodules-cache-path=%t/modules-cache \ +// RUN: %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm \ +// RUN: -### 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t --check-prefix=CHECK-CC1 %s + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "-o" "[[ROOTPCM:[^"]+]]" +// CHECK-CC1-SAME: "-emit-module" +// CHECK-CC1-SAME: "[[PREFIX]]/module.modulemap" +// CHECK-CC1-SAME: "-fmodule-name=root" +// CHECK-CC1-SAME: "-fno-implicit-modules" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "[[PREFIX]]/A-part1-impl.cppm" +// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_IMPL_PCM:[^"]+]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "[[PREFIX]]/A-part1.cppm" +// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_PCM:[^"]+]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "[[PREFIX]]/A.cppm" +// CHECK-CC1-SAME: "-fmodule-file=root=[[ROOTPCM]]" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PCM:[^"]+]]" +// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "[[PREFIX]]/main.cpp" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-file=A=[[A_PCM]]" +// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]" + +//--- main.cpp +import A; + +int main() { + a(); +} + +//--- A.cppm +module; +#include "root.h" +export module A; +export import :part1; + +export int a() { + return part1() + root(); +} + +//--- A-part1.cppm +module; +#include "root.h" +export module A:part1; +export int part1(); + +//--- A-part1-impl.cppm +module; +#include "root.h" +module A:part1_impl; + +int part1() { + return root(); +} + +//--- module.modulemap +module root { header "root.h" export * } + +//--- root.h +inline int root() { return 1; } diff --git a/clang/test/Driver/modules-driver-cxx-modules-only.cpp b/clang/test/Driver/modules-driver-cxx-modules-only.cpp new file mode 100644 index 0000000000000..1206983e32f7b --- /dev/null +++ b/clang/test/Driver/modules-driver-cxx-modules-only.cpp @@ -0,0 +1,88 @@ +// Checks that -fmodules-driver correctly handles compilations using +// Standard C++20 modules. + +// RUN: split-file %s %t + +// RUN: %clang -c -std=c++23 \ +// RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm %t/B.cppm 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t --check-prefix=CHECK-REMARKS %s + +// CHECK-REMARKS: [[PREFIX]]/A.cppm:2:8: remark: importing module 'A:part1' from +// CHECK-REMARKS: [[PREFIX]]/A.cppm:3:1: remark: importing module 'B' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'A:part1' into 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:1:1: remark: importing module 'B' into 'A' from +// CHECK-REMARKS: [[PREFIX]]/main.cpp:2:1: remark: importing module 'B' from + +// RUN: %clang -std=c++23 \ +// RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: %t/main.cpp %t/A.cppm %t/A-part1.cppm %t/A-part1-impl.cppm %t/B.cppm \ +// RUN: -### 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck --check-prefix=CHECK-CC1 %s + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "{{.*}}/B.cppm" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[B_PCM:[^"]+]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "{{.*}}/A-part1-impl.cppm" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_IMPL_PCM:[^"]+]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "{{.*}}/A-part1.cppm" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PART1_PCM:[^"]+]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "{{.*}}/A.cppm" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-output=[[A_PCM:[^"]+]]" +// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]" +// CHECK-CC1-SAME: "-fmodule-file=B=[[B_PCM]]" + +// CHECK-CC1: "-cc1" +// CHECK-CC1-SAME: "{{.*}}/main.cpp" +// CHECK-CC1-SAME: "-fno-implicit-modules" +// CHECK-CC1-SAME: "-fmodule-file=A=[[A_PCM]]" +// CHECK-CC1-SAME: "-fmodule-file=A:part1=[[A_PART1_PCM]]" +// CHECK-CC1-SAME: "-fmodule-file=B=[[B_PCM]]" + +//--- main.cpp +import A; +import B; + +int main() { + return a() + b(); +} + +//--- A.cppm +export module A; +export import :part1; +import B; + +export int a() { + return part1() + b(); +} + +//--- A-part1.cppm +export module A:part1; +export int part1(); + +//--- A-part1-impl.cppm +module A:part1_impl; + +int part1() { + return 30; +} + +//--- B.cppm +export module B; + +export int b() { + return 12; +} diff --git a/clang/test/Driver/modules-driver-import-std.cpp b/clang/test/Driver/modules-driver-import-std.cpp new file mode 100644 index 0000000000000..25dc059b73ec7 --- /dev/null +++ b/clang/test/Driver/modules-driver-import-std.cpp @@ -0,0 +1,60 @@ +// Checks that -fmodules-driver correctly handles the import of Standard library +// modules. + +// The standard library modules manifest (libc++.modules.json) is discovered +// relative to the installed C++ standard library runtime libraries +// We need to create them in order for Clang to find the manifest. +// RUN: rm -rf %t && split-file %s %t +// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so +// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.a + +// RUN: sed "s|DIR|%/t|g" %t/libc++.modules.json.in > \ +// RUN: %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.modules.json + +// RUN: mkdir -p %t/Inputs/usr/lib/share/libc++/v1 +// RUN: cat %t/std.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.cppm +// RUN: cat %t/std.compat.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.compat.cppm + +//--- libc++.modules.json.in +{ + "version": 1, + "revision": 1, + "modules": [ + { + "logical-name": "std", + "source-path": "../share/libc++/v1/std.cppm", + "is-std-library": true + }, + { + "logical-name": "std.compat", + "source-path": "../share/libc++/v1/std.compat.cppm", + "is-std-library": true + } + ] +} + +//--- std.cppm +export module std; + +//--- std.compat.cppm +export module std.compat; +import std; + +//--- main.cpp +import std.compat; +import std; + +int main() {} + +// RUN: %clang -std=c++23 -c -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: -stdlib=libc++ \ +// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: --target=x86_64-linux-gnu \ +// RUN: %t/main.cpp 2>&1 \ +// RUN: | sed 's:\\\\\?:/:g' \ +// RUN: | FileCheck -DPREFIX=%/t %s + +// CHECK: [[PREFIX]]/main.cpp:1:1: remark: importing module 'std.compat' from +// CHECK: [[PREFIX]]/main.cpp:1:1: remark: importing module 'std' into 'std.compat' from +// CHECK: [[PREFIX]]/main.cpp:2:1: remark: importing module 'std' from diff --git a/clang/test/Driver/modules-driver-incompatible-options.cpp b/clang/test/Driver/modules-driver-incompatible-options.cpp new file mode 100644 index 0000000000000..88de9a6eac0e9 --- /dev/null +++ b/clang/test/Driver/modules-driver-incompatible-options.cpp @@ -0,0 +1,10 @@ +// Checks for diagnostics that report incompatibilities between +// -fmodules-driver and other options. + +// RUN: split-file %s %t +// RUN: not %clang -std=c++20 -fmodules-driver -fno-modules-reduced-bmi main.cpp -### + +// CHECK: clang: error: '-fmodules-driver' is currently incompatible with '-fno-modules-reduced-bmi' + +//--- main.cpp +int main() {} From 1389b9b4704361ecc04a9e3cd58d4c480c2ee978 Mon Sep 17 00:00:00 2001 From: Naveen Seth Hanig Date: Thu, 23 Apr 2026 20:16:18 +0200 Subject: [PATCH 2/2] Fix failing test Looking at other tests, using sysroot seems like the more robust test for this. --- .../test/Driver/modules-driver-import-std.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/clang/test/Driver/modules-driver-import-std.cpp b/clang/test/Driver/modules-driver-import-std.cpp index 25dc059b73ec7..e2a74df05fdc0 100644 --- a/clang/test/Driver/modules-driver-import-std.cpp +++ b/clang/test/Driver/modules-driver-import-std.cpp @@ -5,16 +5,16 @@ // relative to the installed C++ standard library runtime libraries // We need to create them in order for Clang to find the manifest. // RUN: rm -rf %t && split-file %s %t -// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu -// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so -// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.a +// RUN: mkdir -p %t/FakeSysroot/usr/lib/x86_64-linux-gnu +// RUN: touch %t/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.so +// RUN: touch %t/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.a // RUN: sed "s|DIR|%/t|g" %t/libc++.modules.json.in > \ -// RUN: %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.modules.json +// RUN: %t/FakeSysroot/usr/lib/x86_64-linux-gnu/libc++.modules.json -// RUN: mkdir -p %t/Inputs/usr/lib/share/libc++/v1 -// RUN: cat %t/std.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.cppm -// RUN: cat %t/std.compat.cppm > %t/Inputs/usr/lib/share/libc++/v1/std.compat.cppm +// RUN: mkdir -p %t/FakeSysroot/usr/lib/share/libc++/v1 +// RUN: cat %t/std.cppm > %t/FakeSysroot/usr/lib/share/libc++/v1/std.cppm +// RUN: cat %t/std.compat.cppm > %t/FakeSysroot/usr/lib/share/libc++/v1/std.compat.cppm //--- libc++.modules.json.in { @@ -47,11 +47,14 @@ import std; int main() {} -// RUN: %clang -std=c++23 -c -fmodules-driver -Rmodules-driver -Rmodule-import \ +// RUN: %clang -std=c++23 -stdlib=libc++ \ +// RUN: -fmodules-driver -Rmodules-driver -Rmodule-import \ // RUN: -stdlib=libc++ \ -// RUN: -resource-dir=%t/Inputs/usr/lib/x86_64-linux-gnu \ +// RUN: -resource-dir=%t/FakeSysroot/usr/lib/x86_64-linux-gnu \ +// RUN: --sysroot=%t/FakeSysroot \ +// RUN: -L%t/Inputs/usr/lib/x86_64-linux-gnu \ // RUN: --target=x86_64-linux-gnu \ -// RUN: %t/main.cpp 2>&1 \ +// RUN: -c %t/main.cpp 2>&1 \ // RUN: | sed 's:\\\\\?:/:g' \ // RUN: | FileCheck -DPREFIX=%/t %s