Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -362,6 +362,8 @@ def sys_header_deps : Flag<["-"], "sys-header-deps">, HelpText<"Include system headers in dependency output">; +def skip_unused_modulemap_file_deps : Flag<["-"], "skip-unused-modulemap-deps">, + HelpText<"Include module map files only for imported modules in dependency output">; def module_file_deps : Flag<["-"], "module-file-deps">, HelpText<"Include module files in dependency output">; def header_include_file : Separate<["-"], "header-include-file">, Index: include/clang/Frontend/DependencyOutputOptions.h =================================================================== --- include/clang/Frontend/DependencyOutputOptions.h +++ include/clang/Frontend/DependencyOutputOptions.h @@ -30,6 +30,7 @@ unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info. unsigned IncludeModuleFiles : 1; ///< Include module file dependencies. + unsigned SkipUnusedModuleMaps : 1; ///< Skip unused module map dependencies. /// The format for the dependency file. DependencyOutputFormat OutputFormat; @@ -67,6 +68,7 @@ AddMissingHeaderDeps = 0; PrintShowIncludes = 0; IncludeModuleFiles = 0; + SkipUnusedModuleMaps = 0; OutputFormat = DependencyOutputFormat::Make; } }; Index: include/clang/Lex/ModuleMap.h =================================================================== --- include/clang/Lex/ModuleMap.h +++ include/clang/Lex/ModuleMap.h @@ -56,6 +56,14 @@ virtual void moduleMapFileRead(SourceLocation FileStart, const FileEntry &File, bool IsSystem) {} + /// Called when a module map file matches a module lookup + /// + /// \param File The file itself. + /// \param M The module found that matches this module map. + /// \param IsSystem Whether this is a module map from a system include path. + virtual void moduleMapFoundForModule(const FileEntry &File, const Module *M, + bool IsSystem) {} + /// \brief Called when a header is added during module map parsing. /// /// \param Filename The header file itself. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1070,6 +1070,7 @@ Opts.Targets = Args.getAllArgValues(OPT_MT); Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps); Opts.IncludeModuleFiles = Args.hasArg(OPT_module_file_deps); + Opts.SkipUnusedModuleMaps = Args.hasArg(OPT_skip_unused_modulemap_file_deps); Opts.UsePhonyTargets = Args.hasArg(OPT_MP); Opts.ShowHeaderIncludes = Args.hasArg(OPT_H); Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file); Index: lib/Frontend/DependencyFile.cpp =================================================================== --- lib/Frontend/DependencyFile.cpp +++ lib/Frontend/DependencyFile.cpp @@ -161,6 +161,7 @@ bool AddMissingHeaderDeps; bool SeenMissingHeader; bool IncludeModuleFiles; + bool SkipUnusedModuleMaps; DependencyOutputFormat OutputFormat; private: @@ -176,6 +177,7 @@ AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false), IncludeModuleFiles(Opts.IncludeModuleFiles), + SkipUnusedModuleMaps(Opts.SkipUnusedModuleMaps), OutputFormat(Opts.OutputFormat) { for (const auto &ExtraDep : Opts.ExtraDeps) { AddFilename(ExtraDep); @@ -198,6 +200,7 @@ void AddFilename(StringRef Filename); bool includeSystemHeaders() const { return IncludeSystemHeaders; } bool includeModuleFiles() const { return IncludeModuleFiles; } + bool skipUnusedModuleMaps() const { return SkipUnusedModuleMaps; } }; class DFGMMCallback : public ModuleMapCallbacks { @@ -206,9 +209,17 @@ DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {} void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry, bool IsSystem) override { + if (Parent.skipUnusedModuleMaps()) + return; if (!IsSystem || Parent.includeSystemHeaders()) Parent.AddFilename(Entry.getName()); } + void moduleMapFoundForModule(const FileEntry &Entry, const Module *M, + bool IsSystem) override { + if (Parent.skipUnusedModuleMaps() && + (!IsSystem || Parent.includeSystemHeaders())) + Parent.AddFilename(Entry.getName()); + } }; class DFGASTReaderListener : public ASTReaderListener { Index: lib/Lex/ModuleMap.cpp =================================================================== --- lib/Lex/ModuleMap.cpp +++ lib/Lex/ModuleMap.cpp @@ -723,8 +723,17 @@ Module *ModuleMap::findModule(StringRef Name) const { llvm::StringMap::const_iterator Known = Modules.find(Name); - if (Known != Modules.end()) - return Known->getValue(); + if (Known != Modules.end()) { + Module *M = Known->getValue(); + // Notify callbacks that we found a module map for the module. + if (!M->DefinitionLoc.isInvalid()) + for (const auto &Cb : Callbacks) + Cb->moduleMapFoundForModule( + *getContainingModuleMapFile(M), M, + SourceMgr.getFileCharacteristic(M->DefinitionLoc) == + SrcMgr::C_System_ModuleMap); + return M; + } return nullptr; } Index: test/Modules/Inputs/dependency-skip-unused/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/dependency-skip-unused/module.modulemap @@ -0,0 +1 @@ +module A {} Index: test/Modules/Inputs/dependency-skip-unused/x/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/dependency-skip-unused/x/module.modulemap @@ -0,0 +1 @@ +module X {} Index: test/Modules/Inputs/dependency-skip-unused/y/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/dependency-skip-unused/y/module.modulemap @@ -0,0 +1 @@ +module Y {} Index: test/Modules/dependency-skip-unused-modulemaps.m =================================================================== --- /dev/null +++ test/Modules/dependency-skip-unused-modulemaps.m @@ -0,0 +1,7 @@ +// RUN: rm -rf %t.cache %t.d +// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.cache -dependency-file %t.d -MT dependencies -I%S/Inputs/dependency-skip-unused/x -I%S/Inputs/dependency-skip-unused/y -I%S/Inputs/dependency-skip-unused -skip-unused-modulemap-deps %s +// RUN: FileCheck %s < %t.d +// CHECK-NOT: dependency-skip-unused{{.}}x{{.}}module.modulemap +// CHECK-NOT: dependency-skip-unused{{.}}y{{.}}module.modulemap + +@import A;