diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 86d9567553186..36fc930d589ef 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -82,6 +82,9 @@ class SearchPathOptions { /// would for a non-system header. bool DisableModulesValidateSystemDependencies = false; + /// The paths to a set of explicitly built modules from interfaces. + std::vector ExplicitSwiftModules; + private: static StringRef pathStringFromFrameworkSearchPath(const FrameworkSearchPath &next) { diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 016b16706ab3b..e894dd1855535 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -473,6 +473,7 @@ class ClangImporter final : public ClangModuleLoader { bool isSerializable(const clang::Type *type, bool checkCanonical) const override; + ArrayRef getExtraClangArgs() const; }; ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN, diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h index 14e593daf88a0..173abc210f560 100644 --- a/include/swift/ClangImporter/ClangImporterOptions.h +++ b/include/swift/ClangImporter/ClangImporterOptions.h @@ -103,6 +103,10 @@ class ClangImporterOptions { /// DWARFImporter delegate. bool DisableSourceImport = false; + /// When set, use ExtraArgs alone to configure clang instance because ExtraArgs + /// contains the full option set. + bool ExtraArgsOnly = false; + /// Return a hash code of any components from these options that should /// contribute to a Swift Bridging PCH hash. llvm::hash_code getPCHHashComponents() const { diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 710efc42f9368..201202cd983a1 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -258,6 +258,10 @@ class FrontendOptions { /// By default, we include ImplicitObjCHeaderPath directly. llvm::Optional BridgingHeaderDirForPrint; + /// Disable implicitly built Swift modules because they are explicitly + /// built and given to the compiler invocation. + bool DisableImplicitModules = false; + /// The different modes for validating TBD against the LLVM IR. enum class TBDValidationMode { Default, ///< Do the default validation for the current platform. diff --git a/include/swift/Frontend/ModuleInterfaceLoader.h b/include/swift/Frontend/ModuleInterfaceLoader.h index 61d265d3a775b..c5ba052c8ffd4 100644 --- a/include/swift/Frontend/ModuleInterfaceLoader.h +++ b/include/swift/Frontend/ModuleInterfaceLoader.h @@ -127,6 +127,16 @@ class LangOptions; class SearchPathOptions; class CompilerInvocation; +struct ModuleInterfaceLoaderOptions { + bool remarkOnRebuildFromInterface = false; + bool disableInterfaceLock = false; + bool disableImplicitSwiftModule = false; + ModuleInterfaceLoaderOptions(const FrontendOptions &Opts): + remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface), + disableInterfaceLock(Opts.DisableInterfaceFileLock), + disableImplicitSwiftModule(Opts.DisableImplicitModules) {} + ModuleInterfaceLoaderOptions() = default; +}; /// A ModuleLoader that runs a subordinate \c CompilerInvocation and /// \c CompilerInstance to convert .swiftinterface files to .swiftmodule /// files on the fly, caching the resulting .swiftmodules in the module cache @@ -137,21 +147,17 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules, - bool RemarkOnRebuildFromInterface, bool IgnoreSwiftSourceInfoFile, - bool DisableInterfaceFileLock) + bool IgnoreSwiftSourceInfoFile, ModuleInterfaceLoaderOptions Opts) : SerializedModuleLoaderBase(ctx, tracker, loadMode, IgnoreSwiftSourceInfoFile), CacheDir(cacheDir), PrebuiltCacheDir(prebuiltCacheDir), - RemarkOnRebuildFromInterface(RemarkOnRebuildFromInterface), - DisableInterfaceFileLock(DisableInterfaceFileLock), - PreferInterfaceForModules(PreferInterfaceForModules) - {} + PreferInterfaceForModules(PreferInterfaceForModules), + Opts(Opts) {} std::string CacheDir; std::string PrebuiltCacheDir; - bool RemarkOnRebuildFromInterface; - bool DisableInterfaceFileLock; ArrayRef PreferInterfaceForModules; + ModuleInterfaceLoaderOptions Opts; std::error_code findModuleFilesInDirectory( AccessPathElem ModuleID, @@ -168,16 +174,14 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir, DependencyTracker *tracker, ModuleLoadingMode loadMode, ArrayRef PreferInterfaceForModules = {}, - bool RemarkOnRebuildFromInterface = false, - bool IgnoreSwiftSourceInfoFile = false, - bool DisableInterfaceFileLock = false) { + ModuleInterfaceLoaderOptions Opts = ModuleInterfaceLoaderOptions(), + bool IgnoreSwiftSourceInfoFile = false) { return std::unique_ptr( new ModuleInterfaceLoader(ctx, cacheDir, prebuiltCacheDir, tracker, loadMode, PreferInterfaceForModules, - RemarkOnRebuildFromInterface, IgnoreSwiftSourceInfoFile, - DisableInterfaceFileLock)); + Opts)); } /// Append visible module names to \p names. Note that names are possibly @@ -192,10 +196,11 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase { static bool buildSwiftModuleFromSwiftInterface( SourceManager &SourceMgr, DiagnosticEngine &Diags, const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts, + const ClangImporterOptions &ClangOpts, StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock); + ModuleInterfaceLoaderOptions Opts); }; struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { @@ -231,14 +236,13 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { DiagnosticEngine &Diags, const SearchPathOptions &searchPathOpts, const LangOptions &langOpts, + ModuleInterfaceLoaderOptions LoaderOpts, ClangModuleLoader *clangImporter, bool buildModuleCacheDirIfAbsent, StringRef moduleCachePath, StringRef prebuiltCachePath, bool serializeDependencyHashes, - bool trackSystemDependencies, - bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock); + bool trackSystemDependencies); bool runInSubContext(StringRef moduleName, StringRef interfacePath, StringRef outputPath, @@ -258,6 +262,7 @@ struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate { llvm::SmallString<256> &OutPath, StringRef &CacheHash); std::string getCacheHash(StringRef useInterfacePath); + void addExtraClangArg(StringRef Arg); }; } diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 177f97dd5cae3..9ba2fc6ed4fe8 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -214,6 +214,12 @@ def disable_objc_attr_requires_foundation_module : def enable_resilience : Flag<["-"], "enable-resilience">, HelpText<"Deprecated, use -enable-library-evolution instead">; +def disable_implicit_swift_modules: Flag<["-"], "disable-implicit-swift-modules">, + HelpText<"Disable building Swift modules explicitly by the compiler">; + +def swift_module_file + : Separate<["-"], "swift-module-file">, MetaVarName<"">, + HelpText<"Specify Swift module explicitly built from textual interface">; } @@ -712,4 +718,6 @@ def target_sdk_version : Separate<["-"], "target-sdk-version">, def target_variant_sdk_version : Separate<["-"], "target-variant-sdk-version">, HelpText<"The version of target variant SDK used for compilation">; +def extra_clang_options_only : Flag<["-"], "only-use-extra-clang-opts">, + HelpText<"Options passed via -Xcc are sufficient for Clang configuration">; } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden] diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 6b11ca1992bd9..cf8f68afa2086 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -908,6 +908,9 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions, std::vector ClangImporter::getClangArguments(ASTContext &ctx, const ClangImporterOptions &importerOpts) { + if (importerOpts.ExtraArgsOnly) { + return importerOpts.ExtraArgs; + } std::vector invocationArgStrs; // Clang expects this to be like an actual command line. So we need to pass in // "clang" for argv[0] @@ -957,6 +960,10 @@ ClangImporter::createClangInvocation(ClangImporter *importer, nullptr, false, CC1Args); } +ArrayRef ClangImporter::getExtraClangArgs() const { + return Impl.ExtraClangArgs; +} + std::unique_ptr ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, std::string swiftPCHHash, DependencyTracker *tracker, @@ -965,7 +972,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts, new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)}; importer->Impl.ClangArgs = getClangArguments(ctx, importerOpts); ArrayRef invocationArgStrs = importer->Impl.ClangArgs; - + importer->Impl.ExtraClangArgs = importerOpts.ExtraArgs; if (importerOpts.DumpClangDiagnostics) { llvm::errs() << "'"; llvm::interleave( diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 3d2b1d256137e..739aa8444d22a 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -188,20 +188,6 @@ static ClangModuleDependenciesCacheImpl *getOrCreateClangImpl( return clangImpl; } -static std::string getModuleFilePath(StringRef moduleCacheDir, - StringRef moduleName, - StringRef contextHash) { - SmallString<128> outputPath(moduleCacheDir); - llvm::sys::path::append(outputPath, (llvm::Twine(moduleName) - + "-" + contextHash + ".pcm").str()); - return outputPath.str().str(); -} - -static std::string getModuleFilePath(StringRef moduleCacheDir, - const ModuleDeps &dep) { - return getModuleFilePath(moduleCacheDir, dep.ModuleName, dep.ContextHash); -} - /// Record the module dependencies we found by scanning Clang modules into /// the module dependencies cache. void ClangImporter::recordModuleDependencies( @@ -213,23 +199,7 @@ void ClangImporter::recordModuleDependencies( }; auto ModuleCacheDir = swift::getModuleCachePathFromClang(getClangInstance()); - // A map keyed by module name and context hash. - llvm::StringMap> moduleInfoMap; - - // Traverse all Clang modules to populate moduleInfoMap for cross - // referencing later. - for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { - moduleInfoMap[clangModuleDep.ModuleName][clangModuleDep.ContextHash] = - { - // Keep track of pcm path for output. - getModuleFilePath(ModuleCacheDir, clangModuleDep), - // Keep track of modulemap file for input. - clangModuleDep.ClangModuleMapFile - }; - } for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) { - assert(moduleInfoMap[clangModuleDep.ModuleName] - .count(clangModuleDep.ContextHash)); // If we've already cached this information, we're done. if (cache.hasDependencies(clangModuleDep.ModuleName, ModuleDependenciesKind::Clang)) @@ -241,48 +211,32 @@ void ClangImporter::recordModuleDependencies( fileDeps.push_back(fileDep.getKey().str()); } // Inherit all Clang driver args when creating the clang importer. - std::vector allArgs = Impl.ClangArgs; + ArrayRef allArgs = Impl.ClangArgs; ClangImporterOptions Opts; - std::vector cc1Args; - // Calling this to convert driver args to CC1 args. - createClangInvocation(this, Opts, allArgs, &cc1Args); + // Ensure the arguments we collected is sufficient to create a Clang + // invocation. + assert(createClangInvocation(this, Opts, allArgs)); + std::vector swiftArgs; // We are using Swift frontend mode. swiftArgs.push_back("-frontend"); + // We pass the entire argument list via -Xcc, so the invocation should + // use extra clang options alone. + swiftArgs.push_back("-only-use-extra-clang-opts"); auto addClangArg = [&](StringRef arg) { - swiftArgs.push_back("-Xcc"); - swiftArgs.push_back("-Xclang"); swiftArgs.push_back("-Xcc"); swiftArgs.push_back(arg.str()); }; // Add all args inheritted from creating the importer. - for (auto arg: cc1Args) { - addClangArg(arg); - } - // Add all args reported from the Clang dependencies scanner. - for(auto arg: clangModuleDep.NonPathCommandLine) { + for (auto arg: allArgs) { addClangArg(arg); } - - // Add -fmodule-map-file and -fmodule-file for direct dependencies. - for (auto &dep: clangModuleDep.ClangModuleDeps) { - assert(moduleInfoMap[dep.ModuleName].count(dep.ContextHash)); - addClangArg((llvm::Twine("-fmodule-map-file=") - + moduleInfoMap[dep.ModuleName][dep.ContextHash].ModuleMapPath).str()); - addClangArg((llvm::Twine("-fmodule-file=") - + moduleInfoMap[dep.ModuleName][dep.ContextHash].PCMPath).str()); - } // Swift frontend action: -emit-pcm swiftArgs.push_back("-emit-pcm"); swiftArgs.push_back("-module-name"); swiftArgs.push_back(clangModuleDep.ModuleName); - // Swift frontend option for output file path (Foo.pcm). - swiftArgs.push_back("-o"); - swiftArgs.push_back(moduleInfoMap[clangModuleDep.ModuleName] - [clangModuleDep.ContextHash].PCMPath); - // Swift frontend option for input file path (Foo.modulemap). swiftArgs.push_back(clangModuleDep.ClangModuleMapFile); // Module-level dependencies. diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 7963151dda780..1e5b433f5bf3d 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -392,6 +392,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation /// Clang arguments used to create the Clang invocation. std::vector ClangArgs; + + /// Extra clang args specified via "-Xcc" + std::vector ExtraClangArgs; public: /// Mapping of already-imported declarations. llvm::DenseMap, Decl *> ImportedDecls; diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 14f5ac00ec9cf..f5f28b1a4e793 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -83,6 +83,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.TrackSystemDeps |= Args.hasArg(OPT_track_system_dependencies); + Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules); + // Always track system dependencies when scanning dependencies. if (const Arg *ModeArg = Args.getLastArg(OPT_modes_Group)) { if (ModeArg->getOption().matches(OPT_scan_dependencies)) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 17f28871d3243..fb6db28526628 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -802,6 +802,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, Opts.DisableOverlayModules |= Args.hasArg(OPT_emit_imported_modules); + Opts.ExtraArgsOnly |= Args.hasArg(OPT_extra_clang_options_only); + if (const Arg *A = Args.getLastArg(OPT_pch_output_dir)) { Opts.PrecompiledHeaderOutputDir = A->getValue(); Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation); @@ -863,6 +865,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, Opts.DisableModulesValidateSystemDependencies |= Args.hasArg(OPT_disable_modules_validate_system_headers); + for (auto A: Args.filtered(OPT_swift_module_file)) { + Opts.ExplicitSwiftModules.push_back(resolveSearchPath(A->getValue())); + } // Opts.RuntimeIncludePath is set by calls to // setRuntimeIncludePath() or setMainExecutablePath(). // Opts.RuntimeImportPath is set by calls to diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 27827e89766b4..91a59e4907bd4 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -455,12 +455,12 @@ bool CompilerInstance::setUpModuleLoaders() { std::string ModuleCachePath = getModuleCachePathFromClang(Clang); auto &FEOpts = Invocation.getFrontendOptions(); StringRef PrebuiltModuleCachePath = FEOpts.PrebuiltModuleCachePath; + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); auto PIML = ModuleInterfaceLoader::create( *Context, ModuleCachePath, PrebuiltModuleCachePath, getDependencyTracker(), MLM, FEOpts.PreferInterfaceForModules, - FEOpts.RemarkOnRebuildFromModuleInterface, - IgnoreSourceInfoFile, - FEOpts.DisableInterfaceFileLock); + LoaderOpts, + IgnoreSourceInfoFile); Context->addModuleLoader(std::move(PIML)); } diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 884c5fa9f47bf..7b2845f3c6267 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -339,23 +339,19 @@ class ModuleInterfaceLoaderImpl { const SourceLoc diagnosticLoc; DependencyTracker *const dependencyTracker; const ModuleLoadingMode loadMode; - const bool remarkOnRebuildFromInterface; - const bool disableInterfaceLock; + ModuleInterfaceLoaderOptions Opts; ModuleInterfaceLoaderImpl( ASTContext &ctx, StringRef modulePath, StringRef interfacePath, StringRef moduleName, StringRef cacheDir, StringRef prebuiltCacheDir, - SourceLoc diagLoc, bool remarkOnRebuildFromInterface, - bool disableInterfaceLock, + SourceLoc diagLoc, ModuleInterfaceLoaderOptions Opts, DependencyTracker *dependencyTracker = nullptr, ModuleLoadingMode loadMode = ModuleLoadingMode::PreferSerialized) : ctx(ctx), fs(*ctx.SourceMgr.getFileSystem()), diags(ctx.Diags), modulePath(modulePath), interfacePath(interfacePath), moduleName(moduleName), prebuiltCacheDir(prebuiltCacheDir), cacheDir(cacheDir), diagnosticLoc(diagLoc), - dependencyTracker(dependencyTracker), loadMode(loadMode), - remarkOnRebuildFromInterface(remarkOnRebuildFromInterface), - disableInterfaceLock(disableInterfaceLock) {} + dependencyTracker(dependencyTracker), loadMode(loadMode), Opts(Opts) {} /// Constructs the full path of the dependency \p dep by prepending the SDK /// path if necessary. @@ -828,20 +824,19 @@ class ModuleInterfaceLoaderImpl { } InterfaceSubContextDelegateImpl astDelegate(ctx.SourceMgr, ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts, + Opts, ctx.getClangModuleLoader(), /*buildModuleCacheDirIfAbsent*/true, cacheDir, prebuiltCacheDir, /*serializeDependencyHashes*/false, - trackSystemDependencies, - remarkOnRebuildFromInterface, - disableInterfaceLock); + trackSystemDependencies); // Set up a builder if we need to build the module. It'll also set up // the subinvocation we'll need to use to compute the cache paths. ModuleInterfaceBuilder builder( ctx.SourceMgr, ctx.Diags, astDelegate, interfacePath, moduleName, cacheDir, prebuiltCacheDir, - disableInterfaceLock, diagnosticLoc, + Opts.disableInterfaceLock, diagnosticLoc, dependencyTracker); // Compute the output path if we're loading or emitting a cached module. @@ -904,7 +899,7 @@ class ModuleInterfaceLoaderImpl { if (builder.buildSwiftModule(cachedOutputPath, /*shouldSerializeDeps*/true, &moduleBuffer, - remarkOnRebuildFromInterface ? remarkRebuild: + Opts.remarkOnRebuildFromInterface ? remarkRebuild: llvm::function_ref())) return std::make_error_code(std::errc::invalid_argument); @@ -964,7 +959,7 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( ModuleInterfaceLoaderImpl Impl( Ctx, ModPath, InPath, ModuleName, CacheDir, PrebuiltCacheDir, ModuleID.Loc, - RemarkOnRebuildFromInterface, DisableInterfaceFileLock, + Opts, dependencyTracker, llvm::is_contained(PreferInterfaceForModules, ModuleName) ? @@ -1000,22 +995,29 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( bool ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( SourceManager &SourceMgr, DiagnosticEngine &Diags, const SearchPathOptions &SearchPathOpts, const LangOptions &LangOpts, + const ClangImporterOptions &ClangOpts, StringRef CacheDir, StringRef PrebuiltCacheDir, StringRef ModuleName, StringRef InPath, StringRef OutPath, bool SerializeDependencyHashes, bool TrackSystemDependencies, - bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock) { + ModuleInterfaceLoaderOptions LoaderOpts) { InterfaceSubContextDelegateImpl astDelegate(SourceMgr, Diags, SearchPathOpts, LangOpts, + LoaderOpts, /*clangImporter*/nullptr, /*CreateCacheDirIfAbsent*/true, CacheDir, PrebuiltCacheDir, SerializeDependencyHashes, - TrackSystemDependencies, - RemarkOnRebuildFromInterface, - DisableInterfaceFileLock); + TrackSystemDependencies); + // At this point we don't have an ClangImporter instance because the instance + // is created later when we create a new ASTContext to build the interface. + // Thus, we have to add these extra clang flags manually here to ensure explict + // module building works. + for (auto &Arg: ClangOpts.ExtraArgs) { + astDelegate.addExtraClangArg(Arg); + } ModuleInterfaceBuilder builder(SourceMgr, Diags, astDelegate, InPath, ModuleName, CacheDir, PrebuiltCacheDir, - DisableInterfaceFileLock); + LoaderOpts.disableInterfaceLock); // FIXME: We really only want to serialize 'important' dependencies here, if // we want to ship the built swiftmodules to another machine. return builder.buildSwiftModule(OutPath, /*shouldSerializeDeps*/true, @@ -1158,19 +1160,24 @@ bool InterfaceSubContextDelegateImpl::extractSwiftInterfaceVersionAndArgs( return false; } +void InterfaceSubContextDelegateImpl::addExtraClangArg(StringRef arg) { + subInvocation.getClangImporterOptions().ExtraArgs.push_back(arg); + GenericArgs.push_back("-Xcc"); + GenericArgs.push_back(ArgSaver.save(arg)); +} + InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( SourceManager &SM, DiagnosticEngine &Diags, const SearchPathOptions &searchPathOpts, const LangOptions &langOpts, + ModuleInterfaceLoaderOptions LoaderOpts, ClangModuleLoader *clangImporter, bool buildModuleCacheDirIfAbsent, StringRef moduleCachePath, StringRef prebuiltCachePath, bool serializeDependencyHashes, - bool trackSystemDependencies, - bool remarkOnRebuildFromInterface, - bool disableInterfaceFileLock): SM(SM), Diags(Diags), ArgSaver(Allocator) { + bool trackSystemDependencies): SM(SM), Diags(Diags), ArgSaver(Allocator) { inheritOptionsForBuildingInterface(searchPathOpts, langOpts); // Configure front-end input. auto &SubFEOpts = subInvocation.getFrontendOptions(); @@ -1190,10 +1197,31 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( if (trackSystemDependencies) { GenericArgs.push_back("-track-system-dependencies"); } - // Respect the detailed-record preprocessor setting of the parent context. - // This, and the "raw" clang module format it implicitly enables, are - // required by sourcekitd. + if (LoaderOpts.disableImplicitSwiftModule) { + subInvocation.getFrontendOptions().DisableImplicitModules = true; + GenericArgs.push_back("-disable-implicit-swift-modules"); + } + subInvocation.getSearchPathOptions().ExplicitSwiftModules = + searchPathOpts.ExplicitSwiftModules; + // Dependencies scanner shouldn't know any explict Swift modules to use. + // Adding these argumnets may not be necessary. + // FIXME: remove it? + for (auto EM: searchPathOpts.ExplicitSwiftModules) { + GenericArgs.push_back("-swift-module-file"); + GenericArgs.push_back(ArgSaver.save(EM)); + } if (clangImporter) { + // We need to add these extra clang flags because explict module building + // related flags are all there: -fno-implicit-modules, -fmodule-map-file=, + // and -fmodule-file=. + // If we don't add these flags, the interface will be built with implicit + // PCMs. + for (auto arg: static_cast(clangImporter)->getExtraClangArgs()) { + addExtraClangArg(arg); + } + // Respect the detailed-record preprocessor setting of the parent context. + // This, and the "raw" clang module format it implicitly enables, are + // required by sourcekitd. auto &Opts = clangImporter->getClangInstance().getPreprocessorOpts(); if (Opts.DetailedRecord) { subInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true; @@ -1211,8 +1239,8 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( // Tell the subinvocation to remark on rebuilds from an interface if asked // to do so. frontendOpts.RemarkOnRebuildFromModuleInterface = - remarkOnRebuildFromInterface; - if (remarkOnRebuildFromInterface) { + LoaderOpts.remarkOnRebuildFromInterface; + if (LoaderOpts.remarkOnRebuildFromInterface) { GenericArgs.push_back("-Rmodule-interface-rebuild"); } @@ -1335,10 +1363,6 @@ bool InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleN subInvocation.getFrontendOptions().InputsAndOutputs .setMainAndSupplementaryOutputs(outputFiles, ModuleOutputPaths); - // Add -o for building the module explicitly. - BuildArgs.push_back("-o"); - BuildArgs.push_back(outputPath); - SmallVector SubArgs; std::string CompilerVersion; // Extract compiler arguments from the interface file and use them to configure diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 48384a17a74a2..f322da4198ae4 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -778,15 +778,16 @@ static bool buildModuleFromInterface(CompilerInstance &Instance) { assert(FEOpts.InputsAndOutputs.hasSingleInput()); StringRef InputPath = FEOpts.InputsAndOutputs.getFilenameOfFirstInput(); StringRef PrebuiltCachePath = FEOpts.PrebuiltModuleCachePath; + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); return ModuleInterfaceLoader::buildSwiftModuleFromSwiftInterface( Instance.getSourceMgr(), Instance.getDiags(), Invocation.getSearchPathOptions(), Invocation.getLangOptions(), + Invocation.getClangImporterOptions(), Invocation.getClangModuleCachePath(), PrebuiltCachePath, Invocation.getModuleName(), InputPath, Invocation.getOutputFilename(), FEOpts.SerializeModuleInterfaceDependencyHashes, - FEOpts.TrackSystemDeps, FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock); + FEOpts.TrackSystemDeps, LoaderOpts); } static bool compileLLVMIR(CompilerInstance &Instance) { diff --git a/lib/FrontendTool/ScanDependencies.cpp b/lib/FrontendTool/ScanDependencies.cpp index 31ce01280bf81..f8974d96ea6f2 100644 --- a/lib/FrontendTool/ScanDependencies.cpp +++ b/lib/FrontendTool/ScanDependencies.cpp @@ -69,16 +69,16 @@ static std::vector resolveDirectDependencies( auto ModuleCachePath = getModuleCachePathFromClang(ctx .getClangModuleLoader()->getClangInstance()); auto &FEOpts = instance.getInvocation().getFrontendOptions(); + ModuleInterfaceLoaderOptions LoaderOpts(FEOpts); InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts, + LoaderOpts, ctx.getClangModuleLoader(), /*buildModuleCacheDirIfAbsent*/false, ModuleCachePath, FEOpts.PrebuiltModuleCachePath, FEOpts.SerializeModuleInterfaceDependencyHashes, - FEOpts.TrackSystemDeps, - FEOpts.RemarkOnRebuildFromModuleInterface, - FEOpts.DisableInterfaceFileLock); + FEOpts.TrackSystemDeps); // Find the dependencies of every module this module directly depends on. std::vector result; for (auto dependsOn : knownDependencies.getModuleDependencies()) { diff --git a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift index bd6e5057b9a47..f2fdefffd9a97 100644 --- a/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift +++ b/test/ScanDependencies/Inputs/BuildModulesFromGraph.swift @@ -39,6 +39,8 @@ func findModuleBuildingCommand(_ moduleName: String) -> [String]? { if let command = findModuleBuildingCommand(moduleName) { var result = swiftPath command.forEach { result += " \($0)"} + // Pass down additional args to the Swift invocation. + CommandLine.arguments.dropFirst(4).forEach { result += " \($0)"} print(result) exit(0) } else { diff --git a/test/ScanDependencies/module_deps.swift b/test/ScanDependencies/module_deps.swift index 72885e5072f9b..72f30ba975ee8 100644 --- a/test/ScanDependencies/module_deps.swift +++ b/test/ScanDependencies/module_deps.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: mkdir -p %t/clang-module-cache -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -Xcc -Xclang -Xcc -fno-implicit-modules // Check the contents of the JSON output // RUN: %FileCheck %s < %t/deps.json @@ -22,20 +22,21 @@ // RUN: %target-build-swift %S/Inputs/ModuleDependencyGraph.swift %t/BuildModules/main.swift -o %t/ModuleBuilder // RUN: %target-codesign %t/ModuleBuilder -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/A-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path B.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/B-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path C.pcm | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/C-*.pcm -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/A-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path E.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/E-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path F.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/F-*.swiftmodule -// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path G.swiftmodule | %S/Inputs/CommandRunner.py -// RUN: ls %t/clang-module-cache/G-*.swiftmodule +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path SwiftShims.pcm -o %t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/SwiftShims.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.pcm -o %t/clang-module-cache/A.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path B.pcm -o %t/clang-module-cache/B.pcm -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/A.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/B.pcm +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path C.pcm -o %t/clang-module-cache/C.pcm -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/B.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/C.pcm + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path A.swiftmodule -o %t/clang-module-cache/A.swiftmodule -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/A.pcm -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/A.swiftmodule + +// RUN: %target-run %t/ModuleBuilder %t/deps.json %swift-path E.swiftmodule -o %t/clang-module-cache/E.swiftmodule -Xcc -Xclang -Xcc -fmodule-map-file=%S/Inputs/CHeaders/module.modulemap -Xcc -Xclang -Xcc -fmodule-file=%t/clang-module-cache/SwiftShims.pcm | %S/Inputs/CommandRunner.py +// RUN: ls %t/clang-module-cache/E.swiftmodule + // REQUIRES: executable_test // REQUIRES: objc_interop @@ -105,11 +106,10 @@ import G // CHECK: "commandLine": [ // CHECK-NEXT: "-frontend" +// CHECK-NEXT: "-only-use-extra-clang-opts" // CHECK-NEXT: "-Xcc" -// CHECK-NEXT: "-Xclang" -// CHECK-NEXT: "-Xcc" -// CHECK-NEXT: "-cc1" -// CHECK: "-remove-preceeding-explicit-module-build-incompatible-options" +// CHECK-NEXT: "clang" +// CHECK: "-fno-implicit-modules" /// --------Swift module E // CHECK: "swift": "E" @@ -135,8 +135,6 @@ import G // CHECK: "-compile-module-from-interface" // CHECK: "-target" // CHECK: "-sdk" -// CHECK: "-o" -// CHECK: /clang-module-cache/G-{{.*}}.swiftmodule" // CHECK: "-module-name" // CHECK: "G" // CHECK: "-swift-version"