diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index fa5fa5652ac7d..7718407233f5d 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -386,9 +386,25 @@ class CompilerInvocation { std::string getLdAddCFileOutputPathForWholeModule() const; +public: + /// Given the current configuration of this frontend invocation, a set of + /// supplementary output paths, and a module, compute the appropriate set of + /// serialization options. + /// + /// FIXME: The \p module parameter supports the + /// \c SerializeOptionsForDebugging hack. SerializationOptions computeSerializationOptions(const SupplementaryOutputPaths &outs, - bool moduleIsPublic) const; + const ModuleDecl *module) const; + + /// Returns an approximation of whether the given module could be + /// redistributed and consumed by external clients. + /// + /// FIXME: The scope of this computation should be limited entirely to + /// PrintAsObjC. Unfortunately, it has been co-opted to support the + /// \c SerializeOptionsForDebugging hack. Once this information can be + /// transferred from module files to the dSYMs, remove this. + bool isModuleExternallyConsumed(const ModuleDecl *mod) const; }; /// A class which manages the state and execution of the compiler. @@ -555,9 +571,7 @@ class CompilerInstance { /// Returns true if there was an error during setup. bool setup(const CompilerInvocation &Invocation); - const CompilerInvocation &getInvocation() { - return Invocation; - } + const CompilerInvocation &getInvocation() const { return Invocation; } /// If a code completion buffer has been set, returns the corresponding source /// file. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 00b37d842414b..595b0d85a86b0 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1701,3 +1701,30 @@ CompilerInvocation::setUpInputForSILTool( } return fileBufOrErr; } + +bool CompilerInvocation::isModuleExternallyConsumed( + const ModuleDecl *mod) const { + // Modules for executables aren't expected to be consumed by other modules. + // This picks up all kinds of entrypoints, including script mode, + // @UIApplicationMain and @NSApplicationMain. + if (mod->hasEntryPoint()) { + return false; + } + + // If an implicit Objective-C header was needed to construct this module, it + // must be the product of a library target. + if (!getFrontendOptions().ImplicitObjCHeaderPath.empty()) { + return false; + } + + // App extensions are special beasts because they build without entrypoints + // like library targets, but they behave like executable targets because + // their associated modules are not suitable for distribution. + if (mod->getASTContext().LangOpts.EnableAppExtensionRestrictions) { + return false; + } + + // FIXME: This is still a lousy approximation of whether the module file will + // be externally consumed. + return true; +} diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index d1ec3481d4121..b162e549d05fe 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -152,7 +152,7 @@ CompilerInvocation::getPrivateModuleInterfaceOutputPathForWholeModule() const { } SerializationOptions CompilerInvocation::computeSerializationOptions( - const SupplementaryOutputPaths &outs, bool moduleIsPublic) const { + const SupplementaryOutputPaths &outs, const ModuleDecl *module) const { const FrontendOptions &opts = getFrontendOptions(); SerializationOptions serializationOpts; @@ -171,7 +171,8 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( // so only serialize them if the module isn't going to be shipped to // the public. serializationOpts.SerializeOptionsForDebugging = - opts.SerializeOptionsForDebugging.getValueOr(!moduleIsPublic); + opts.SerializeOptionsForDebugging.getValueOr( + !isModuleExternallyConsumed(module)); return serializationOpts; } diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 316d805a5a1e3..e78174844befa 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -1074,20 +1074,19 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance, std::unique_ptr SM, ModuleOrSourceFile MSF, const PrimarySpecificPaths &PSPs, - bool moduleIsPublic, int &ReturnValue, + int &ReturnValue, FrontendObserver *observer); -static bool -performCompileStepsPostSema(const CompilerInvocation &Invocation, - CompilerInstance &Instance, - bool moduleIsPublic, int &ReturnValue, - FrontendObserver *observer) { +static bool performCompileStepsPostSema(const CompilerInvocation &Invocation, + CompilerInstance &Instance, + int &ReturnValue, + FrontendObserver *observer) { auto mod = Instance.getMainModule(); if (auto SM = Instance.takeSILModule()) { const PrimarySpecificPaths PSPs = Instance.getPrimarySpecificPathsForAtMostOnePrimary(); return performCompileStepsPostSILGen(Instance, Invocation, std::move(SM), - mod, PSPs, moduleIsPublic, + mod, PSPs, ReturnValue, observer); } @@ -1100,7 +1099,7 @@ performCompileStepsPostSema(const CompilerInvocation &Invocation, const PrimarySpecificPaths PSPs = Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode(); return performCompileStepsPostSILGen(Instance, Invocation, std::move(SM), - mod, PSPs, moduleIsPublic, + mod, PSPs, ReturnValue, observer); } // If there are primary source files, build a separate SILModule for @@ -1113,7 +1112,7 @@ performCompileStepsPostSema(const CompilerInvocation &Invocation, const PrimarySpecificPaths PSPs = Instance.getPrimarySpecificPathsForSourceFile(*PrimaryFile); result |= performCompileStepsPostSILGen(Instance, Invocation, std::move(SM), - PrimaryFile, PSPs, moduleIsPublic, + PrimaryFile, PSPs, ReturnValue, observer); } @@ -1131,7 +1130,7 @@ performCompileStepsPostSema(const CompilerInvocation &Invocation, const PrimarySpecificPaths &PSPs = Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename()); result |= performCompileStepsPostSILGen(Instance, Invocation, std::move(SM), - mod, PSPs, moduleIsPublic, + mod, PSPs, ReturnValue, observer); } } @@ -1158,8 +1157,7 @@ emitIndexData(const CompilerInvocation &Invocation, const CompilerInstance &Inst /// `-typecheck`, but skipped for any mode that runs SIL diagnostics if there's /// an error found there (to get those diagnostics back to the user faster). static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs( - CompilerInstance &Instance, const CompilerInvocation &Invocation, - bool moduleIsPublic) { + CompilerInstance &Instance, const CompilerInvocation &Invocation) { const FrontendOptions &opts = Invocation.getFrontendOptions(); // Record whether we failed to emit any of these outputs, but keep going; one @@ -1182,7 +1180,8 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs( } hadAnyError |= printAsObjCIfNeeded( Invocation.getObjCHeaderOutputPathForAtMostOnePrimary(), - Instance.getMainModule(), BridgingHeaderPathForPrint, moduleIsPublic); + Instance.getMainModule(), BridgingHeaderPathForPrint, + Invocation.isModuleExternallyConsumed(Instance.getMainModule())); } if (opts.InputsAndOutputs.hasModuleInterfaceOutputPath()) { @@ -1315,13 +1314,6 @@ static bool performCompile(CompilerInstance &Instance, (void)emitLoadedModuleTraceForAllPrimariesIfNeeded( Instance.getMainModule(), Instance.getDependencyTracker(), opts); - // FIXME: This is still a lousy approximation of whether the module file will - // be externally consumed. - bool moduleIsPublic = - !Instance.getMainModule()->hasEntryPoint() && - opts.ImplicitObjCHeaderPath.empty() && - !Context.LangOpts.EnableAppExtensionRestrictions; - // We've just been told to perform a typecheck, so we can return now. if (Action == FrontendOptions::ActionType::Typecheck) { if (emitIndexData(Invocation, Instance)) @@ -1336,8 +1328,7 @@ static bool performCompile(CompilerInstance &Instance, // guarding the emission of whole-module supplementary outputs. if (opts.InputsAndOutputs.isWholeModule()) { if (emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, - Invocation, - moduleIsPublic)) { + Invocation)) { return true; } } @@ -1347,8 +1338,8 @@ static bool performCompile(CompilerInstance &Instance, assert(FrontendOptions::doesActionGenerateSIL(Action) && "All actions not requiring SILGen must have been handled!"); - return performCompileStepsPostSema(Invocation, Instance, moduleIsPublic, - ReturnValue, observer); + return performCompileStepsPostSema(Invocation, Instance, ReturnValue, + observer); } static bool serializeSIB(SILModule *SM, const PrimarySpecificPaths &PSPs, @@ -1575,9 +1566,8 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance, std::unique_ptr SM, ModuleOrSourceFile MSF, const PrimarySpecificPaths &PSPs, - bool moduleIsPublic, int &ReturnValue, + int &ReturnValue, FrontendObserver *observer) { - FrontendOptions opts = Invocation.getFrontendOptions(); FrontendOptions::ActionType Action = opts.RequestedAction; const ASTContext &Context = Instance.getASTContext(); @@ -1618,7 +1608,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance, return; SerializationOptions serializationOpts = - Invocation.computeSerializationOptions(outs, moduleIsPublic); + Invocation.computeSerializationOptions(outs, Instance.getMainModule()); serialize(MSF, serializationOpts, SM.get()); }; @@ -1633,8 +1623,7 @@ static bool performCompileStepsPostSILGen(CompilerInstance &Instance, if (observer) observer->performedSILProcessing(*SM); - emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, Invocation, - moduleIsPublic); + emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, Invocation); if (Action == FrontendOptions::ActionType::EmitSIB) return serializeSIB(SM.get(), PSPs, Context, MSF);