ChuanqiXu created this revision. ChuanqiXu added reviewers: iains, dblaikie, Bigcheese, vsapsai. ChuanqiXu added projects: clang, clang-modules. Herald added a project: All. ChuanqiXu requested review of this revision. Herald added subscribers: cfe-commits, MaskRay.
This patch tries to make clang to generate the BMI implicitly in the module cache, which allow the user to compile a hello world example in one command line. This also tries to fix the problem I raised a year ago: https://discourse.llvm.org/t/make-command-line-support-for-c-20-module-uniform-with-gcc/59144 More importantly, the patch ease the implementation for build system writers, which makes their initial support more easily. For example, in this branch https://github.com/ChuanqiXu9/llvm-project/tree/MyP1689, we can compile the HelloWorld examples by cmake with some little changes. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D134267 Files: clang/include/clang/Basic/DiagnosticCommonKinds.td clang/lib/Driver/Driver.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/create_module_cache.cpp clang/test/Modules/one-phase-compilation-named-modules.cppm
Index: clang/test/Modules/one-phase-compilation-named-modules.cppm =================================================================== --- /dev/null +++ clang/test/Modules/one-phase-compilation-named-modules.cppm @@ -0,0 +1,25 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: %clang -std=c++20 %t/M.cppm -c -o - -fmodules-cache-path=%t/pcm.cache +// RUN: %clang -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t/pcm.cache -Xclang -verify +// +// RUN: rm -f %t/M.pcm +// RUN: %clang -std=c++20 %t/MismatchedName.cppm -c -o - -fmodules-cache-path=%t/pcm.cache -fmodule-name=M +// RUN: %clang -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t/pcm.cache -Xclang -verify + +//--- M.cppm +export module M; +export int getValue(); + +//--- MismatchedName.cppm +export module M; +export int getValue(); + +//--- Use.cpp +// expected-no-diagnostics +import M; +int Use() { + return getValue(); +} Index: clang/test/Driver/create_module_cache.cpp =================================================================== --- /dev/null +++ clang/test/Driver/create_module_cache.cpp @@ -0,0 +1,20 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: split-file %s %t +// +// RUN: not %clang -std=c++20 %t/M.cppm -fmodules-cache-path= -c -o %t/M.tmp.o 2>&1 | FileCheck %t/M.cppm --check-prefix=ERROR +// RUN: %clang -std=c++20 %t/M.cppm -fmodules-cache-path=%t/abc -c -o - +// RUN: ls %t | FileCheck %t/M.cppm --check-prefix=CHECK-AVAILABLE +// +// RUN: %clang -std=c++20 %t/Use.cpp -fmodules-cache-path=abc -### 2>&1 | FileCheck %t/Use.cpp + +//--- M.cppm +export module M; + +// ERROR: unable to create default module cache path "": No such file or directory +// CHECK-AVAILABLE: abc + +//--- Use.cpp +import M; + +// CHECK: -fprebuilt-module-path=abc Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -3658,6 +3658,7 @@ const ArgList &Args, const InputInfo &Input, const InputInfo &Output, ArgStringList &CmdArgs, bool &HaveModules) { + bool HasCXXModules = HaveModules; // -fmodules enables the use of precompiled modules (off by default). // Users can pass -fno-cxx-modules to turn off modules support for // C++/Objective-C++ programs. @@ -3699,33 +3700,34 @@ options::OPT_fno_implicit_modules, HaveClangModules)) { if (HaveModules) CmdArgs.push_back("-fno-implicit-modules"); - } else if (HaveModules) { + } else if (HaveModules) ImplicitModules = true; - // -fmodule-cache-path specifies where our implicitly-built module files - // should be written. - SmallString<128> Path; - if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) - Path = A->getValue(); - bool HasPath = true; - if (C.isForDiagnostics()) { - // When generating crash reports, we want to emit the modules along with - // the reproduction sources, so we ignore any provided module path. - Path = Output.getFilename(); - llvm::sys::path::replace_extension(Path, ".cache"); - llvm::sys::path::append(Path, "modules"); - } else if (Path.empty()) { - // No module path was provided: use the default. - HasPath = Driver::getDefaultModuleCachePath(Path); - } - - // `HasPath` will only be false if getDefaultModuleCachePath() fails. - // That being said, that failure is unlikely and not caching is harmless. - if (HasPath) { - const char Arg[] = "-fmodules-cache-path="; - Path.insert(Path.begin(), Arg, Arg + strlen(Arg)); - CmdArgs.push_back(Args.MakeArgString(Path)); - } + // -fmodule-cache-path specifies where our implicitly-built module files + // should be written. + SmallString<128> ModulesCachePath; + if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path)) + ModulesCachePath = A->getValue(); + + bool HasModulesCachePath = true; + if (C.isForDiagnostics()) { + // When generating crash reports, we want to emit the modules along with + // the reproduction sources, so we ignore any provided module path. + ModulesCachePath = Output.getFilename(); + llvm::sys::path::replace_extension(ModulesCachePath, ".cache"); + llvm::sys::path::append(ModulesCachePath, "modules"); + } else if (ModulesCachePath.empty()) { + // No module path was provided: use the default. + HasModulesCachePath = Driver::getDefaultModuleCachePath(ModulesCachePath); + } + + // `HasModulesCachePath` will only be false if getDefaultModuleCachePath() + // fails. That being said, that failure is unlikely and not caching is + // harmless. + if (HasModulesCachePath && ImplicitModules) { + const char Arg[] = "-fmodules-cache-path="; + ModulesCachePath.insert(ModulesCachePath.begin(), Arg, Arg + strlen(Arg)); + CmdArgs.push_back(Args.MakeArgString(ModulesCachePath)); } if (HaveModules) { @@ -3735,6 +3737,11 @@ std::string("-fprebuilt-module-path=") + A->getValue())); A->claim(); } + + if (HasCXXModules) + CmdArgs.push_back(Args.MakeArgString( + std::string("-fprebuilt-module-path=") + ModulesCachePath)); + if (Args.hasFlag(options::OPT_fprebuilt_implicit_modules, options::OPT_fno_prebuilt_implicit_modules, false)) CmdArgs.push_back("-fprebuilt-implicit-modules"); Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -5499,6 +5499,31 @@ return "-"; } + if (isa<PrecompileJobAction>(JA) && JA.getType() == types::TY_ModuleFile) { + SmallString<128> Path; + if (Arg *A = C.getArgs().getLastArg(options::OPT_fmodules_cache_path)) + Path = A->getValue(); + else + Driver::getDefaultModuleCachePath(Path); + + std::error_code EC = + llvm::sys::fs::create_directories(Path, /*IgnoreExisting =*/true); + if (EC) + Diag(clang::diag::err_creating_default_module_cache_path) + << Path << EC.message(); + + if (Arg *A = C.getArgs().getLastArg(options::OPT_fmodule_name_EQ)) + llvm::sys::path::append(Path, A->getValue()); + else { + StringRef Name = llvm::sys::path::filename(BaseInput); + llvm::sys::path::append(Path, Name.rsplit('.').first); + Path += "."; + Path += types::getTypeTempSuffix(JA.getType(), IsCLMode()); + } + + return C.addResultFile(C.getArgs().MakeArgString(Path.c_str()), &JA); + } + if (IsDXCMode() && !C.getArgs().hasArg(options::OPT_o)) return "-"; Index: clang/include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticCommonKinds.td +++ clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -347,6 +347,8 @@ // Modules def err_module_format_unhandled : Error< "no handler registered for module format '%0'">, DefaultFatal; +def err_creating_default_module_cache_path : Error< + "unable to create default module cache path \"%0\": %1">; // TransformActions // TODO: Use a custom category name to distinguish rewriter errors.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits