From 0b7369c4576de47b71cb647abf15f66f090d2079 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Tue, 28 May 2019 22:21:07 +1200 Subject: [PATCH 1/9] Add support for building static libraries. --- include/swift/AST/Decl.h | 7 +++-- include/swift/AST/Module.h | 8 ++++++ include/swift/Frontend/FrontendOptions.h | 3 +++ include/swift/IRGen/Linking.h | 2 +- include/swift/Option/Options.td | 4 +++ include/swift/Serialization/ModuleFormat.h | 7 ++++- include/swift/Serialization/Validation.h | 6 +++++ .../ArgsToFrontendOptionsConverter.cpp | 2 ++ lib/Frontend/Frontend.cpp | 2 ++ lib/IRGen/GenDecl.cpp | 26 ++++++++++++------- lib/Serialization/ModuleFile.cpp | 3 +++ lib/Serialization/Serialization.cpp | 6 +++++ lib/Serialization/SerializedModuleLoader.cpp | 2 ++ 13 files changed, 64 insertions(+), 14 deletions(-) diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 4f6d153e293f3..d4d0e74725fde 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -602,7 +602,7 @@ class alignas(1 << DeclAlignInBits) Decl { HasAnyUnavailableValues : 1 ); - SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1, + SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1, /// If the module was or is being compiled with `-enable-testing`. TestingEnabled : 1, @@ -624,7 +624,10 @@ class alignas(1 << DeclAlignInBits) Decl { ImplicitDynamicEnabled : 1, // Whether the module is a system module. - IsSystemModule : 1 + IsSystemModule : 1, + + // If the module is a static library. + IsStaticLibrary : 1 ); SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2, diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 0b3daffc4fd5f..c678e9086917c 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -338,6 +338,14 @@ class ModuleDecl : public DeclContext, public TypeDecl { return getResilienceStrategy() != ResilienceStrategy::Default; } + bool isStaticLibrary() const { + return Bits.ModuleDecl.IsStaticLibrary; + } + + void setIsStaticLibrary(bool isStaticLibrary = true) { + Bits.ModuleDecl.IsStaticLibrary = isStaticLibrary; + } + /// Look up a (possibly overloaded) value set at top-level scope /// (but with the specified access path, which may come from an import decl) /// within the current module. diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 5862ccdfcc182..d9dfb2c99cfc2 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -228,6 +228,9 @@ class FrontendOptions { /// the Objective-C half should implicitly be visible to the Swift sources. bool ImportUnderlyingModule = false; + /// If set, this module should be built and linked as a static library. + bool IsStaticLibrary = false; + /// If set, the header provided in ImplicitObjCHeaderPath will be rewritten /// by the Clang importer as part of semantic analysis. bool SerializeBridgingHeader = false; diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h index c4206911720a2..be8d25b0a5fbd 100644 --- a/include/swift/IRGen/Linking.h +++ b/include/swift/IRGen/Linking.h @@ -1177,7 +1177,7 @@ class LinkInfo { static LinkInfo get(const UniversalLinkageInfo &linkInfo, StringRef name, SILLinkage linkage, ForDefinition_t isDefinition, - bool isWeakImported); + bool isWeakImported, bool isStaticLibrary); StringRef getName() const { return Name.str(); diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 1934f7db036f3..2979157467f57 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -368,6 +368,10 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">, ArgumentIsPath]>, MetaVarName<"">, HelpText<"Emit an Objective-C header file to ">; +def emit_archive : Flag<["-"], "emit-archive">, + Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>, + HelpText<"Emit module as a static archive">; + def import_cf_types : Flag<["-"], "import-cf-types">, Flags<[FrontendOption, HelpHidden]>, HelpText<"Recognize and import CF types as class types">; diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 65f32f7c0ae52..310221e7c402a 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -600,7 +600,8 @@ namespace options_block { IS_SIB, IS_TESTABLE, RESILIENCE_STRATEGY, - ARE_PRIVATE_IMPORTS_ENABLED + ARE_PRIVATE_IMPORTS_ENABLED, + IS_STATIC_LIBRARY }; using SDKPathLayout = BCRecordLayout< @@ -630,6 +631,10 @@ namespace options_block { RESILIENCE_STRATEGY, BCFixed<2> >; + + using IsStaticLibraryLayout = BCRecordLayout< + IS_STATIC_LIBRARY + >; } /// The record types within the input block. diff --git a/include/swift/Serialization/Validation.h b/include/swift/Serialization/Validation.h index 785a8e4d27158..763616675a1b8 100644 --- a/include/swift/Serialization/Validation.h +++ b/include/swift/Serialization/Validation.h @@ -98,6 +98,7 @@ class ExtendedValidationInfo { unsigned IsSIB : 1; unsigned IsTestable : 1; unsigned ResilienceStrategy : 2; + unsigned IsStaticLibrary : 1; } Bits; public: ExtendedValidationInfo() : Bits() {} @@ -135,6 +136,11 @@ class ExtendedValidationInfo { void setResilienceStrategy(ResilienceStrategy resilience) { Bits.ResilienceStrategy = unsigned(resilience); } + + bool isStaticLibrary() const { return Bits.IsStaticLibrary; } + void setIsStaticLibrary(bool isStaticLibrary) { + Bits.IsStaticLibrary = isStaticLibrary; + } }; /// Returns info about the serialized AST in the given data. diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index d2d7c8f3586f6..4e73006fdfadc 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -72,6 +72,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.EnableTesting |= Args.hasArg(OPT_enable_testing); Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports); Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution); + + Opts.IsStaticLibrary |= Args.hasArg(OPT_emit_archive); // FIXME: Remove this flag Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience); diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 4a3b147a05ece..61ae54584e56d 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -535,6 +535,8 @@ ModuleDecl *CompilerInstance::getMainModule() { MainModule->setPrivateImportsEnabled(); if (Invocation.getFrontendOptions().EnableImplicitDynamic) MainModule->setImplicitDynamicEnabled(); + if (Invocation.getFrontendOptions().IsStaticLibrary) + MainModule->setIsStaticLibrary(); if (Invocation.getFrontendOptions().EnableLibraryEvolution) MainModule->setResilienceStrategy(ResilienceStrategy::Resilient); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 5226ce832bbd3..ab144f8c7ad8d 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1605,7 +1605,8 @@ void IRGenModule::emitVTableStubs() { static IRLinkage getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage, ForDefinition_t isDefinition, - bool isWeakImported) { + bool isWeakImported, + bool isStaticLibrary) { #define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \ IRLinkage{llvm::GlobalValue::LINKAGE##Linkage, \ llvm::GlobalValue::VISIBILITY##Visibility, \ @@ -1615,15 +1616,17 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage, // doesn't support relative relocations at load time, which interferes with // our metadata formats. Default visibility should suffice for other object // formats. + bool useDLLStorage = info.UseDLLStorage && !isStaticLibrary; + llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility = info.IsELFObject ? llvm::GlobalValue::ProtectedVisibility : llvm::GlobalValue::DefaultVisibility; llvm::GlobalValue::DLLStorageClassTypes ExportedStorage = - info.UseDLLStorage ? llvm::GlobalValue::DLLExportStorageClass - : llvm::GlobalValue::DefaultStorageClass; + useDLLStorage ? llvm::GlobalValue::DLLExportStorageClass + : llvm::GlobalValue::DefaultStorageClass; llvm::GlobalValue::DLLStorageClassTypes ImportedStorage = - info.UseDLLStorage ? llvm::GlobalValue::DLLImportStorageClass - : llvm::GlobalValue::DefaultStorageClass; + (useDLLStorage && !isDefinition) ? llvm::GlobalValue::DLLImportStorageClass + : llvm::GlobalValue::DefaultStorageClass; switch (linkage) { case SILLinkage::Public: @@ -1645,7 +1648,7 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage, case SILLinkage::Private: { if (info.forcePublicDecls() && !isDefinition) return getIRLinkage(info, SILLinkage::PublicExternal, isDefinition, - isWeakImported); + isWeakImported, isStaticLibrary); auto linkage = info.needLinkerToMergeDuplicateSymbols() ? llvm::GlobalValue::LinkOnceODRLinkage : llvm::GlobalValue::InternalLinkage; @@ -1687,9 +1690,10 @@ void irgen::updateLinkageForDefinition(IRGenModule &IGM, UniversalLinkageInfo linkInfo(IGM); bool weakImported = entity.isWeakImported(IGM.getSwiftModule(), IGM.getAvailabilityContext()); + bool isStaticLibrary = IGM.getSwiftModule()->isStaticLibrary(); auto IRL = getIRLinkage(linkInfo, entity.getLinkage(ForDefinition), - ForDefinition, weakImported); + ForDefinition, weakImported, isStaticLibrary); ApplyIRLinkage(IRL).to(global); // Everything externally visible is considered used in Swift. @@ -1729,19 +1733,21 @@ LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, entity.mangle(result.Name); bool weakImported = entity.isWeakImported(swiftModule, availabilityContext); + bool isStaticLibrary = swiftModule->isStaticLibrary(); result.IRL = getIRLinkage(linkInfo, entity.getLinkage(isStdlibOrDefinition), - isDefinition, weakImported); + isDefinition, weakImported, isStaticLibrary); result.ForDefinition = isDefinition; return result; } LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name, SILLinkage linkage, ForDefinition_t isDefinition, - bool isWeakImported) { + bool isWeakImported, bool isStaticLibrary) { LinkInfo result; result.Name += name; - result.IRL = getIRLinkage(linkInfo, linkage, isDefinition, isWeakImported); + result.IRL = getIRLinkage(linkInfo, linkage, isDefinition, isWeakImported, + isStaticLibrary); result.ForDefinition = isDefinition; return result; } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index d5c4190d575ae..e83988f08875e 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -120,6 +120,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor, options_block::ResilienceStrategyLayout::readRecord(scratch, Strategy); extendedInfo.setResilienceStrategy(ResilienceStrategy(Strategy)); break; + case options_block::IS_STATIC_LIBRARY: + extendedInfo.setIsStaticLibrary(true); + break; default: // Unknown options record, possibly for use by a future version of the // module format. diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index cf2b2bc9ee9a7..13ab519fe6d88 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -828,6 +828,7 @@ void Serializer::writeBlockInfoBlock() { BLOCK_RECORD(options_block, IS_TESTABLE); BLOCK_RECORD(options_block, ARE_PRIVATE_IMPORTS_ENABLED); BLOCK_RECORD(options_block, RESILIENCE_STRATEGY); + BLOCK_RECORD(options_block, IS_STATIC_LIBRARY); BLOCK(INPUT_BLOCK); BLOCK_RECORD(input_block, IMPORTED_MODULE); @@ -993,6 +994,11 @@ void Serializer::writeHeader(const SerializationOptions &options) { Strategy.emit(ScratchRecord, unsigned(M->getResilienceStrategy())); } + if (M->isStaticLibrary()) { + options_block::IsStaticLibraryLayout IsStaticLibrary(Out); + IsStaticLibrary.emit(ScratchRecord); + } + if (options.SerializeOptionsForDebugging) { options_block::SDKPathLayout SDKPath(Out); options_block::XCCLayout XCC(Out); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 927e12aa2dc82..15806d2c004e6 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -552,6 +552,8 @@ FileUnit *SerializedModuleLoaderBase::loadAST( M.setTestingEnabled(); if (extendedInfo.arePrivateImportsEnabled()) M.setPrivateImportsEnabled(); + if (extendedInfo.isStaticLibrary()) + M.setIsStaticLibrary(); auto diagLocOrInvalid = diagLoc.getValueOr(SourceLoc()); loadInfo.status = From ff3498c258fa7e431f11ea47a1dc09a0a82ee936 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 00:06:54 +1200 Subject: [PATCH 2/9] Add driver support for LinkKind::StaticLibrary --- include/swift/Driver/Util.h | 3 ++- include/swift/Option/Options.td | 6 ++--- lib/Driver/DarwinToolChains.cpp | 3 +++ lib/Driver/Driver.cpp | 41 +++++++++++++++++++++++++------- lib/Driver/UnixToolChains.cpp | 3 +++ lib/Driver/WindowsToolChains.cpp | 3 +++ 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/include/swift/Driver/Util.h b/include/swift/Driver/Util.h index 9859f0a8387af..8f9fd30357fe1 100644 --- a/include/swift/Driver/Util.h +++ b/include/swift/Driver/Util.h @@ -34,7 +34,8 @@ namespace driver { enum class LinkKind { None, Executable, - DynamicLibrary + DynamicLibrary, + StaticLibrary }; /// Used by a Job to request a "filelist": a file containing a list of all diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 2979157467f57..cb1491b01fa0f 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -368,9 +368,9 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">, ArgumentIsPath]>, MetaVarName<"">, HelpText<"Emit an Objective-C header file to ">; -def emit_archive : Flag<["-"], "emit-archive">, - Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>, - HelpText<"Emit module as a static archive">; +def static_library : Flag<["-"], "static">, + Flags<[FrontendOption, ModuleInterfaceOption, NoInteractiveOption]>, + HelpText<"Make this module statically linkable and make the output of -emit-library a static library.">; def import_cf_types : Flag<["-"], "import-cf-types">, Flags<[FrontendOption, HelpHidden]>, diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 1e26ab873fa36..3b373b8828a9e 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -284,6 +284,9 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job, case LinkKind::DynamicLibrary: Arguments.push_back("-dylib"); break; + case LinkKind::StaticLibrary: + Arguments.push_back(".a"); + break; } assert(Triple.isOSDarwin()); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 1f588596411ee..ea25e1179372f 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1255,6 +1255,8 @@ static bool maybeBuildingExecutable(const OutputInfo &OI, return true; case LinkKind::DynamicLibrary: return false; + case LinkKind::StaticLibrary: + return false; case LinkKind::None: break; } @@ -1371,7 +1373,13 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, break; case options::OPT_emit_library: - OI.LinkAction = LinkKind::DynamicLibrary; + if (OI.LinkAction != LinkKind::StaticLibrary) + OI.LinkAction = LinkKind::DynamicLibrary; + OI.CompilerOutputType = file_types::TY_Object; + break; + + case options::OPT_emit_archive: + OI.LinkAction = LinkKind::StaticLibrary; OI.CompilerOutputType = file_types::TY_Object; break; @@ -1550,7 +1558,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, OI.ModuleName = "REPL"; } else if (const Arg *A = Args.getLastArg(options::OPT_o)) { OI.ModuleName = llvm::sys::path::stem(A->getValue()); - if (OI.LinkAction == LinkKind::DynamicLibrary && + if ((OI.LinkAction == LinkKind::DynamicLibrary || + OI.LinkAction == LinkKind::StaticLibrary) && !llvm::sys::path::extension(A->getValue()).empty() && StringRef(OI.ModuleName).startswith("lib")) { // Chop off a "lib" prefix if we're building a library. @@ -2180,18 +2189,32 @@ static StringRef baseNameForImage(const JobAction *JA, const OutputInfo &OI, auto link = dyn_cast(JA); if (!link) return BaseName; - if (link->getKind() != LinkKind::DynamicLibrary) + if (link->getKind() != LinkKind::DynamicLibrary && + link->getKind() != LinkKind::StaticLibrary) return BaseName; Buffer = Triple.isOSWindows() ? "" : "lib"; Buffer.append(BaseName); - if (Triple.isOSDarwin()) - Buffer.append(".dylib"); - else if (Triple.isOSWindows()) - Buffer.append(".dll"); - else - Buffer.append(".so"); + switch (link->getKind()) { + case LinkKind::DynamicLibrary: + if (Triple.isOSDarwin()) + Buffer.append( ".dylib"); + else if (Triple.isOSWindows()) + Buffer.append(".dll"); + else + Buffer.append(".so"); + break; + case LinkKind::StaticLibrary: + if (Triple.isOSWindows()) + Buffer.append( ".lib"); + else + Buffer.append(".a"); + break; + default: + llvm_unreachable("unhandled LinkKind"); + } + return Buffer.str(); } diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index fb3c8aa910c9e..740f98656204f 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -130,6 +130,9 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, case LinkKind::DynamicLibrary: Arguments.push_back("-shared"); break; + case LinkKind::StaticLibrary: + // Nothing extra needed. + break; } // Select the linker to use. diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 8a94f7e26540b..f14842c014aed 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -61,6 +61,9 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job, case LinkKind::DynamicLibrary: Arguments.push_back("-shared"); break; + case LinkKind::StaticLibrary: + // Nothing extra needed. + break; } // Select the linker to use. From d0eb649b4a11c7e6a22825364978aa1a9db627f0 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 14:27:30 +1200 Subject: [PATCH 3/9] emit_archive -> static_library --- lib/Driver/Driver.cpp | 9 ++++----- lib/Driver/ToolChains.cpp | 1 + lib/Frontend/ArgsToFrontendOptionsConverter.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index ea25e1179372f..67dc649bc84d5 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1373,14 +1373,13 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, break; case options::OPT_emit_library: - if (OI.LinkAction != LinkKind::StaticLibrary) - OI.LinkAction = LinkKind::DynamicLibrary; + OI.LinkAction = Args.hasArg(options::OPT_static_library) ? + LinkKind::StaticLibrary : + LinkKind::DynamicLibrary; OI.CompilerOutputType = file_types::TY_Object; break; - case options::OPT_emit_archive: - OI.LinkAction = LinkKind::StaticLibrary; - OI.CompilerOutputType = file_types::TY_Object; + case options::OPT_static_library: break; case options::OPT_emit_object: diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ad75b4b454f50..e283667f0a4e6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -208,6 +208,7 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_warnings_as_errors); inputArgs.AddLastArg(arguments, options::OPT_sanitize_EQ); inputArgs.AddLastArg(arguments, options::OPT_sanitize_coverage_EQ); + inputArgs.AddLastArg(arguments, options::OPT_static_library); inputArgs.AddLastArg(arguments, options::OPT_swift_version); inputArgs.AddLastArg(arguments, options::OPT_enforce_exclusivity_EQ); inputArgs.AddLastArg(arguments, options::OPT_stats_output_dir); diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 4e73006fdfadc..d7a37ce61347d 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -73,7 +73,7 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports); Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution); - Opts.IsStaticLibrary |= Args.hasArg(OPT_emit_archive); + Opts.IsStaticLibrary |= Args.hasArg(OPT_static_library); // FIXME: Remove this flag Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience); From 2af0bae93440b67d55608376d29fc2ea0fd2ed27 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 15:12:32 +1200 Subject: [PATCH 4/9] Add ArchiveJobAction for producing static libraries. --- include/swift/Driver/Action.h | 19 ++++++++- include/swift/Driver/ToolChain.h | 3 ++ lib/Driver/Action.cpp | 3 ++ lib/Driver/DarwinToolChains.cpp | 3 +- lib/Driver/Driver.cpp | 52 ++++++++++++++----------- lib/Driver/ToolChain.cpp | 1 + lib/Driver/ToolChains.cpp | 67 ++++++++++++++++++++++++++++++++ lib/Driver/UnixToolChains.cpp | 3 +- lib/Driver/WindowsToolChains.cpp | 3 +- 9 files changed, 125 insertions(+), 29 deletions(-) diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h index c230b0925ecc7..6fca3ae3197cc 100644 --- a/include/swift/Driver/Action.h +++ b/include/swift/Driver/Action.h @@ -48,6 +48,7 @@ class Action { AutolinkExtractJob, REPLJob, LinkJob, + ArchiveJob, GenerateDSYMJob, VerifyDebugInfoJob, GeneratePCHJob, @@ -313,7 +314,7 @@ class LinkJobAction : public JobAction { LinkJobAction(ArrayRef Inputs, LinkKind K) : JobAction(Action::Kind::LinkJob, Inputs, file_types::TY_Image), Kind(K) { - assert(Kind != LinkKind::None); + assert(Kind != LinkKind::None && Kind != LinkKind::StaticLibrary); } LinkKind getKind() const { return Kind; } @@ -323,6 +324,22 @@ class LinkJobAction : public JobAction { } }; +class ArchiveJobAction : public JobAction { + virtual void anchor(); + +public: + ArchiveJobAction(ArrayRef Inputs, LinkKind K) + : JobAction(Action::Kind::ArchiveJob, Inputs, file_types::TY_Image) { + assert(K == LinkKind::StaticLibrary); + } + + LinkKind getKind() const { return LinkKind::StaticLibrary; } + + static bool classof(const Action *A) { + return A->getKind() == Action::Kind::ArchiveJob; + } +}; + } // end namespace driver } // end namespace swift diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index c8b28c02d72e0..2d414695de55e 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -161,6 +161,9 @@ class ToolChain { virtual InvocationInfo constructInvocation(const LinkJobAction &job, const JobContext &context) const; + virtual InvocationInfo constructInvocation(const ArchiveJobAction &job, + const JobContext &context) const; + /// Searches for the given executable in appropriate paths relative to the /// Swift binary. /// diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 95df884e3530c..44421a95a7f30 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -29,6 +29,7 @@ const char *Action::getClassName(Kind AC) { case Kind::AutolinkExtractJob: return "swift-autolink-extract"; case Kind::REPLJob: return "repl"; case Kind::LinkJob: return "link"; + case Kind::ArchiveJob: return "archive"; case Kind::GenerateDSYMJob: return "generate-dSYM"; case Kind::VerifyDebugInfoJob: return "verify-debug-info"; case Kind::GeneratePCHJob: return "generate-pch"; @@ -57,6 +58,8 @@ void REPLJobAction::anchor() {} void LinkJobAction::anchor() {} +void ArchiveJobAction::anchor() {} + void GenerateDSYMJobAction::anchor() {} void VerifyDebugInfoJobAction::anchor() {} diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index 3b373b8828a9e..d8d7d73f9934b 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -285,8 +285,7 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job, Arguments.push_back("-dylib"); break; case LinkKind::StaticLibrary: - Arguments.push_back(".a"); - break; + llvm_unreachable("invalid link kind"); } assert(Triple.isOSDarwin()); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 67dc649bc84d5..245ea60e166d3 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1957,8 +1957,16 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, } if (OI.shouldLink() && !AllLinkerInputs.empty()) { - auto *LinkAction = C.createAction(AllLinkerInputs, - OI.LinkAction); + JobAction *LinkAction = nullptr; + + if (OI.LinkAction == LinkKind::StaticLibrary) { + LinkAction = C.createAction(AllLinkerInputs, + OI.LinkAction); + + llvm::errs() << "LinkAction is an ArchiveJobAction\n"; + } else + LinkAction = C.createAction(AllLinkerInputs, + OI.LinkAction); // On ELF platforms there's no built in autolinking mechanism, so we // pull the info we need from the .o files directly and pass them as an @@ -2185,34 +2193,34 @@ static StringRef baseNameForImage(const JobAction *JA, const OutputInfo &OI, StringRef BaseInput, StringRef BaseName) { if (JA->size() == 1 && OI.ModuleNameIsFallback && BaseInput != "-") return llvm::sys::path::stem(BaseInput); + + if (auto link = dyn_cast(JA)) { + Buffer = Triple.isOSWindows() ? "" : "lib"; + Buffer.append(BaseName); + + if (Triple.isOSWindows()) + Buffer.append(".lib"); + else + Buffer.append(".a"); + + return Buffer.str(); + } + auto link = dyn_cast(JA); if (!link) return BaseName; - if (link->getKind() != LinkKind::DynamicLibrary && - link->getKind() != LinkKind::StaticLibrary) + if (link->getKind() != LinkKind::DynamicLibrary) return BaseName; Buffer = Triple.isOSWindows() ? "" : "lib"; Buffer.append(BaseName); - switch (link->getKind()) { - case LinkKind::DynamicLibrary: - if (Triple.isOSDarwin()) - Buffer.append( ".dylib"); - else if (Triple.isOSWindows()) - Buffer.append(".dll"); - else - Buffer.append(".so"); - break; - case LinkKind::StaticLibrary: - if (Triple.isOSWindows()) - Buffer.append( ".lib"); - else - Buffer.append(".a"); - break; - default: - llvm_unreachable("unhandled LinkKind"); - } + if (Triple.isOSDarwin()) + Buffer.append(".dylib"); + else if (Triple.isOSWindows()) + Buffer.append(".dll"); + else + Buffer.append(".so"); return Buffer.str(); } diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index 321d9aef16b55..4fab274fa40fd 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -100,6 +100,7 @@ std::unique_ptr ToolChain::constructJob( CASE(MergeModuleJob) CASE(ModuleWrapJob) CASE(LinkJob) + CASE(ArchiveJob) CASE(GenerateDSYMJob) CASE(VerifyDebugInfoJob) CASE(GeneratePCHJob) diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index e283667f0a4e6..bb176244c7cc6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1079,6 +1079,73 @@ ToolChain::constructInvocation(const LinkJobAction &job, llvm_unreachable("linking not implemented for this toolchain"); } +ToolChain::InvocationInfo +ToolChain::constructInvocation(const ArchiveJobAction &job, + const JobContext &context) const { + assert(context.Output.getPrimaryOutputType() == file_types::TY_Image && + "Invalid linker output type."); + assert(job.getKind() == LinkKind::StaticLibrary); + + ArgStringList Arguments; + + // Configure the toolchain. + bool isLLVMAR = false; + const char *AR = nullptr; + if (const Arg *A = context.Args.getLastArg(options::OPT_tools_directory)) { + StringRef toolchainPath(A->getValue()); + + // If there is an llvm-ar in the toolchain folder, use that instead. + if (auto toolchainAR = + llvm::sys::findProgramByName("llvm-ar", {toolchainPath})) { + AR = context.Args.MakeArgString(toolchainAR.get()); + isLLVMAR = true; + } + + // Look for binutils in the toolchain folder. + Arguments.push_back("-B"); + Arguments.push_back(context.Args.MakeArgString(A->getValue())); + } + if (AR == nullptr) { + if (auto pathAR = llvm::sys::findProgramByName("llvm-ar", None)) + AR = context.Args.MakeArgString(pathAR.get()); + isLLVMAR = true; + } + if (AR == nullptr) { + if (auto pathAR = llvm::sys::findProgramByName("ar", None)) + AR = context.Args.MakeArgString(pathAR.get()); + } + + assert(AR && + "neither ar nor llvm-ar was not found in the toolchain directory or system path."); + + if (isLLVMAR) { + switch (getTriple().getOS()) { + case llvm::Triple::Darwin: + Arguments.push_back("--format=darwin"); + break; + case llvm::Triple::Linux: + Arguments.push_back("--format=gnu"); + break; + default: + break; + } + } + + Arguments.push_back("crs"); + + Arguments.push_back( + context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); + + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + + InvocationInfo II{AR, Arguments}; + II.allowsResponseFiles = true; + + return II; +} + void ToolChain::addPathEnvironmentVariableIfNeeded( Job::EnvironmentVector &env, const char *name, const char *separator, options::ID optionID, const ArgList &args, StringRef extraEntry) const { diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 740f98656204f..3b2f7481d5a52 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -131,8 +131,7 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job, Arguments.push_back("-shared"); break; case LinkKind::StaticLibrary: - // Nothing extra needed. - break; + llvm_unreachable("invalid link kind"); } // Select the linker to use. diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index f14842c014aed..b0d3f41b30f82 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -62,8 +62,7 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job, Arguments.push_back("-shared"); break; case LinkKind::StaticLibrary: - // Nothing extra needed. - break; + llvm_unreachable("invalid link kind"); } // Select the linker to use. From bdcac7f5e779af161cc920edceed2f0891f4d29b Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 15:38:29 +1200 Subject: [PATCH 5/9] Move a comment for clarity --- lib/IRGen/GenDecl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index ab144f8c7ad8d..e05f54d553767 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1612,12 +1612,12 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage, llvm::GlobalValue::VISIBILITY##Visibility, \ llvm::GlobalValue::DLL_STORAGE##StorageClass} + bool useDLLStorage = info.UseDLLStorage && !isStaticLibrary; + // Use protected visibility for public symbols we define on ELF. ld.so // doesn't support relative relocations at load time, which interferes with // our metadata formats. Default visibility should suffice for other object // formats. - bool useDLLStorage = info.UseDLLStorage && !isStaticLibrary; - llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility = info.IsELFObject ? llvm::GlobalValue::ProtectedVisibility : llvm::GlobalValue::DefaultVisibility; From 2421f3713c2a551d3011f66056edd3f7b9007fa2 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 15:52:09 +1200 Subject: [PATCH 6/9] Fix issues with the ar invocation --- lib/Driver/Driver.cpp | 6 ++---- lib/Driver/ToolChains.cpp | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 245ea60e166d3..e5177d3699b9c 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1959,12 +1959,10 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, if (OI.shouldLink() && !AllLinkerInputs.empty()) { JobAction *LinkAction = nullptr; - if (OI.LinkAction == LinkKind::StaticLibrary) { + if (OI.LinkAction == LinkKind::StaticLibrary) LinkAction = C.createAction(AllLinkerInputs, OI.LinkAction); - - llvm::errs() << "LinkAction is an ArchiveJobAction\n"; - } else + else LinkAction = C.createAction(AllLinkerInputs, OI.LinkAction); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index bb176244c7cc6..c3bebee1a2bad 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1101,14 +1101,12 @@ ToolChain::constructInvocation(const ArchiveJobAction &job, isLLVMAR = true; } - // Look for binutils in the toolchain folder. - Arguments.push_back("-B"); - Arguments.push_back(context.Args.MakeArgString(A->getValue())); } if (AR == nullptr) { - if (auto pathAR = llvm::sys::findProgramByName("llvm-ar", None)) + if (auto pathAR = llvm::sys::findProgramByName("llvm-ar", None)) { AR = context.Args.MakeArgString(pathAR.get()); isLLVMAR = true; + } } if (AR == nullptr) { if (auto pathAR = llvm::sys::findProgramByName("ar", None)) From d82e47ab7c32faf1b4f9806152d91c8619a2be75 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Wed, 29 May 2019 15:55:26 +1200 Subject: [PATCH 7/9] Add FreeBSD as an AR format --- lib/Driver/ToolChains.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index c3bebee1a2bad..e087fab4f3cf8 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1121,6 +1121,9 @@ ToolChain::constructInvocation(const ArchiveJobAction &job, case llvm::Triple::Darwin: Arguments.push_back("--format=darwin"); break; + case llvm::Triple::FreeBSD: + Arguments.push_back("--format=bsd"); + break; case llvm::Triple::Linux: Arguments.push_back("--format=gnu"); break; From 3463e5d31907bcd61e2a3212e3413f4332aad34e Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Fri, 31 May 2019 10:09:02 +1200 Subject: [PATCH 8/9] Adjust for review comments. --- include/swift/Driver/Action.h | 2 -- include/swift/Option/Options.td | 2 +- lib/Driver/Driver.cpp | 11 +++++--- lib/Driver/ToolChains.cpp | 25 +++++++++---------- .../ArgsToFrontendOptionsConverter.cpp | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h index 6fca3ae3197cc..08dcf7f96d22e 100644 --- a/include/swift/Driver/Action.h +++ b/include/swift/Driver/Action.h @@ -333,8 +333,6 @@ class ArchiveJobAction : public JobAction { assert(K == LinkKind::StaticLibrary); } - LinkKind getKind() const { return LinkKind::StaticLibrary; } - static bool classof(const Action *A) { return A->getKind() == Action::Kind::ArchiveJob; } diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index cb1491b01fa0f..3fbdf76707477 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -368,7 +368,7 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">, ArgumentIsPath]>, MetaVarName<"">, HelpText<"Emit an Objective-C header file to ">; -def static_library : Flag<["-"], "static">, +def static : Flag<["-"], "static">, Flags<[FrontendOption, ModuleInterfaceOption, NoInteractiveOption]>, HelpText<"Make this module statically linkable and make the output of -emit-library a static library.">; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index e5177d3699b9c..19a4dac78e2c1 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1368,18 +1368,20 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, switch (OutputModeArg->getOption().getID()) { case options::OPT_emit_executable: + assert(!Args.hasArg(options::OPT_static) && + "-static may not be used with -emit-executable."); OI.LinkAction = LinkKind::Executable; OI.CompilerOutputType = file_types::TY_Object; break; case options::OPT_emit_library: - OI.LinkAction = Args.hasArg(options::OPT_static_library) ? + OI.LinkAction = Args.hasArg(options::OPT_static) ? LinkKind::StaticLibrary : LinkKind::DynamicLibrary; OI.CompilerOutputType = file_types::TY_Object; break; - case options::OPT_static_library: + case options::OPT_static: break; case options::OPT_emit_object: @@ -1959,12 +1961,13 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, if (OI.shouldLink() && !AllLinkerInputs.empty()) { JobAction *LinkAction = nullptr; - if (OI.LinkAction == LinkKind::StaticLibrary) + if (OI.LinkAction == LinkKind::StaticLibrary) { LinkAction = C.createAction(AllLinkerInputs, OI.LinkAction); - else + } else { LinkAction = C.createAction(AllLinkerInputs, OI.LinkAction); + } // On ELF platforms there's no built in autolinking mechanism, so we // pull the info we need from the .o files directly and pass them as an diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index e087fab4f3cf8..dc8a8baf0d227 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -208,7 +208,7 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI, inputArgs.AddLastArg(arguments, options::OPT_warnings_as_errors); inputArgs.AddLastArg(arguments, options::OPT_sanitize_EQ); inputArgs.AddLastArg(arguments, options::OPT_sanitize_coverage_EQ); - inputArgs.AddLastArg(arguments, options::OPT_static_library); + inputArgs.AddLastArg(arguments, options::OPT_static); inputArgs.AddLastArg(arguments, options::OPT_swift_version); inputArgs.AddLastArg(arguments, options::OPT_enforce_exclusivity_EQ); inputArgs.AddLastArg(arguments, options::OPT_stats_output_dir); @@ -1084,7 +1084,6 @@ ToolChain::constructInvocation(const ArchiveJobAction &job, const JobContext &context) const { assert(context.Output.getPrimaryOutputType() == file_types::TY_Image && "Invalid linker output type."); - assert(job.getKind() == LinkKind::StaticLibrary); ArgStringList Arguments; @@ -1118,17 +1117,17 @@ ToolChain::constructInvocation(const ArchiveJobAction &job, if (isLLVMAR) { switch (getTriple().getOS()) { - case llvm::Triple::Darwin: - Arguments.push_back("--format=darwin"); - break; - case llvm::Triple::FreeBSD: - Arguments.push_back("--format=bsd"); - break; - case llvm::Triple::Linux: - Arguments.push_back("--format=gnu"); - break; - default: - break; + case llvm::Triple::Darwin: + Arguments.push_back("--format=darwin"); + break; + case llvm::Triple::FreeBSD: + Arguments.push_back("--format=bsd"); + break; + case llvm::Triple::Linux: + Arguments.push_back("--format=gnu"); + break; + default: + break; } } diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index d7a37ce61347d..e5c187a0af81d 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -73,7 +73,7 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports); Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution); - Opts.IsStaticLibrary |= Args.hasArg(OPT_static_library); + Opts.IsStaticLibrary |= Args.hasArg(OPT_static); // FIXME: Remove this flag Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience); From 248b0f7ad3c675ec022ef7e44a2e38f46efd8ec6 Mon Sep 17 00:00:00 2001 From: Thomas Roughton Date: Fri, 31 May 2019 12:41:32 +1200 Subject: [PATCH 9/9] Use a proper diagnostic for -emit-executable -static --- include/swift/AST/DiagnosticsDriver.def | 3 +++ lib/Driver/Driver.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/swift/AST/DiagnosticsDriver.def b/include/swift/AST/DiagnosticsDriver.def index 74561817ca550..3fc50d240d8e5 100644 --- a/include/swift/AST/DiagnosticsDriver.def +++ b/include/swift/AST/DiagnosticsDriver.def @@ -64,6 +64,9 @@ ERROR(error_expected_frontend_command,none, ERROR(error_cannot_specify__o_for_multiple_outputs,none, "cannot specify -o when generating multiple output files", ()) +ERROR(error_static_emit_executable_disallowed,none, + "-static may not be used with -emit-executable", ()) + ERROR(error_unable_to_load_output_file_map, none, "unable to load output file map '%1': %0", (StringRef, StringRef)) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 19a4dac78e2c1..9e3a7a23d7deb 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1368,8 +1368,10 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, switch (OutputModeArg->getOption().getID()) { case options::OPT_emit_executable: - assert(!Args.hasArg(options::OPT_static) && - "-static may not be used with -emit-executable."); + if (Args.hasArg(options::OPT_static)) + Diags.diagnose(SourceLoc(), + diag::error_static_emit_executable_disallowed); + OI.LinkAction = LinkKind::Executable; OI.CompilerOutputType = file_types::TY_Object; break;