diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2306,6 +2306,8 @@ PosFlag, NegFlag, BothFlags<[NoXarchOption, CC1Option]>>; +def fmodule_output_EQ : Joined<["-"], "fmodule-output=">, Flags<[NoXarchOption, CC1Option]>, + HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption, CC1Option]>, HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -5554,8 +5554,12 @@ } // Calculate the output path of the module file when compiling a module unit -// with the `-fmodule-output` option specified. The behavior is: -// - If the output object file of the module unit is specified, the output path +// with the `-fmodule-output` option or `-fmodule-output=` option specified. +// The behavior is: +// - If `-fmodule-output=` is specfied, then the module file is +// writing to the value. +// - Otherwise if the output object file of the module unit is specified, the +// output path // of the module file should be the same with the output object file except // the corresponding suffix. This requires both `-o` and `-c` are specified. // - Otherwise, the output path of the module file will be the same with the @@ -5563,7 +5567,12 @@ static const char *GetModuleOutputPath(Compilation &C, const JobAction &JA, const char *BaseInput) { assert(isa(JA) && JA.getType() == types::TY_ModuleFile && - C.getArgs().hasArg(options::OPT_fmodule_output)); + (C.getArgs().hasArg(options::OPT_fmodule_output) || + C.getArgs().hasArg(options::OPT_fmodule_output_EQ))); + + if (Arg *ModuleOutputEQ = + C.getArgs().getLastArg(options::OPT_fmodule_output_EQ)) + return C.addResultFile(ModuleOutputEQ->getValue(), &JA); SmallString<64> OutputPath; Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); @@ -5633,14 +5642,16 @@ &JA); } - if (MultipleArchs && C.getArgs().hasArg(options::OPT_fmodule_output)) + bool SpecifiedModuleOutput = + C.getArgs().hasArg(options::OPT_fmodule_output) || + C.getArgs().hasArg(options::OPT_fmodule_output_EQ); + if (MultipleArchs && SpecifiedModuleOutput) Diag(clang::diag::err_drv_module_output_with_multiple_arch); // If we're emitting a module output with the specified option // `-fmodule-output`. if (!AtTopLevel && isa(JA) && - JA.getType() == types::TY_ModuleFile && - C.getArgs().hasArg(options::OPT_fmodule_output)) + JA.getType() == types::TY_ModuleFile && SpecifiedModuleOutput) return GetModuleOutputPath(C, JA, BaseInput); // Output to a temporary file? diff --git a/clang/test/Driver/module-output.cppm b/clang/test/Driver/module-output.cppm --- a/clang/test/Driver/module-output.cppm +++ b/clang/test/Driver/module-output.cppm @@ -23,6 +23,11 @@ // RUN: %clang %t/Hello.cppm -fmodule-output -arch i386 -arch x86_64 -### -target \ // RUN: x86_64-apple-darwin 2>&1 | FileCheck %t/Hello.cppm -check-prefix=MULTIPLE-ARCH +// Tests that the .pcm file will be generated in the same path with the specified one +// in the comamnd line. +// RUN: %clang -std=c++20 %t/Hello.cppm -fmodule-output=%t/pcm/Hello.pcm -o %t/Hello.o \ +// RUN: -c -### 2>&1 | FileCheck %t/Hello.cppm --check-prefix=CHECK-SPECIFIED + //--- Hello.cppm export module Hello; @@ -31,6 +36,9 @@ // MULTIPLE-ARCH: option '-fmodule-output' can't be used with multiple arch options +// CHECK-SPECIFIED: "-emit-module-interface" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/pcm/Hello.pcm" "-x" "c++" "{{.*}}/Hello.cppm" +// CHECK-SPECIFIED: "-emit-obj" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/Hello.o" "-x" "pcm" "{{.*}}/pcm/Hello.pcm" + //--- AnotherModule.cppm export module AnotherModule; // CHECK: "-emit-module-interface" {{.*}}"-main-file-name" "Hello.cppm" {{.*}}"-o" "{{.*}}/Hello.pcm" "-x" "c++" "{{.*}}/Hello.cppm"