Skip to content

[Driver] Add -static flag for generating static archives #25202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsDriver.def
Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand Down
27 changes: 21 additions & 6 deletions include/swift/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class Action {
ModuleWrapJob,
AutolinkExtractJob,
REPLJob,
LinkJob,
DynamicLinkJob,
StaticLinkJob,
GenerateDSYMJob,
VerifyDebugInfoJob,
GeneratePCHJob,
Expand Down Expand Up @@ -305,21 +306,35 @@ class GeneratePCHJobAction : public JobAction {
}
};

class LinkJobAction : public JobAction {
class DynamicLinkJobAction : public JobAction {
virtual void anchor();
LinkKind Kind;

public:
LinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
: JobAction(Action::Kind::LinkJob, Inputs, file_types::TY_Image),
DynamicLinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
: JobAction(Action::Kind::DynamicLinkJob, Inputs, file_types::TY_Image),
Kind(K) {
assert(Kind != LinkKind::None);
assert(Kind != LinkKind::None && Kind != LinkKind::StaticLibrary);
}

LinkKind getKind() const { return Kind; }

static bool classof(const Action *A) {
return A->getKind() == Action::Kind::LinkJob;
return A->getKind() == Action::Kind::DynamicLinkJob;
}
};

class StaticLinkJobAction : public JobAction {
virtual void anchor();

public:
StaticLinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
: JobAction(Action::Kind::StaticLinkJob, Inputs, file_types::TY_Image) {
assert(K == LinkKind::StaticLibrary);
}

static bool classof(const Action *A) {
return A->getKind() == Action::Kind::StaticLinkJob;
}
};

Expand Down
5 changes: 4 additions & 1 deletion include/swift/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,10 @@ class ToolChain {
virtual InvocationInfo
constructInvocation(const AutolinkExtractJobAction &job,
const JobContext &context) const;
virtual InvocationInfo constructInvocation(const LinkJobAction &job,
virtual InvocationInfo constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const;

virtual InvocationInfo constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const;

/// Searches for the given executable in appropriate paths relative to the
Expand Down
3 changes: 2 additions & 1 deletion include/swift/Driver/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,10 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
ArgumentIsPath]>,
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;

def static : 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]>,
HelpText<"Recognize and import CF types as class types">;
Expand Down
7 changes: 5 additions & 2 deletions lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const char *Action::getClassName(Kind AC) {
case Kind::ModuleWrapJob: return "modulewrap";
case Kind::AutolinkExtractJob: return "swift-autolink-extract";
case Kind::REPLJob: return "repl";
case Kind::LinkJob: return "link";
case Kind::DynamicLinkJob: return "link";
case Kind::StaticLinkJob: return "static-link";
case Kind::GenerateDSYMJob: return "generate-dSYM";
case Kind::VerifyDebugInfoJob: return "verify-debug-info";
case Kind::GeneratePCHJob: return "generate-pch";
Expand All @@ -55,7 +56,9 @@ void AutolinkExtractJobAction::anchor() {}

void REPLJobAction::anchor() {}

void LinkJobAction::anchor() {}
void DynamicLinkJobAction::anchor() {}

void StaticLinkJobAction::anchor() {}

void GenerateDSYMJobAction::anchor() {}

Expand Down
42 changes: 39 additions & 3 deletions lib/Driver/DarwinToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,8 @@ static bool wantsObjCRuntime(const llvm::Triple &triple) {
}

ToolChain::InvocationInfo
toolchains::Darwin::constructInvocation(const LinkJobAction &job,
const JobContext &context) const
{
toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const {
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
"Invalid linker output type.");

Expand Down Expand Up @@ -286,6 +285,8 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
case LinkKind::DynamicLibrary:
Arguments.push_back("-dylib");
break;
case LinkKind::StaticLibrary:
llvm_unreachable("the dynamic linker cannot build static libraries");
}

assert(Triple.isOSDarwin());
Expand Down Expand Up @@ -527,6 +528,41 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
return II;
}


ToolChain::InvocationInfo
toolchains::Darwin::constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const {
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
"Invalid linker output type.");

// Configure the toolchain.
const char *LibTool = "libtool";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be able to use ar to do the operation. The only time that libtool is really required is for fat libraries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have an opinion here, but from the previous review: #25088 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented on that - I think that we can safely get away with it with llvm-ar at least

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented against it. :-(

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we can get away with it using the stock Xcode tools as well (do we really care about the original AT&T Unix?).


InvocationInfo II = {LibTool};
ArgStringList &Arguments = II.Arguments;

Arguments.push_back("-static");

if (context.shouldUseInputFileList()) {
Arguments.push_back("-filelist");
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object,
FilelistInfo::WhichFiles::Input});
} else {
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
file_types::TY_Object);
}

addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);

Arguments.push_back("-o");

Arguments.push_back(
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));

return II;
}

bool toolchains::Darwin::shouldStoreInvocationInDebugInfo() const {
// This matches the behavior in Clang (see
// clang/lib/driver/ToolChains/Darwin.cpp).
Expand Down
37 changes: 32 additions & 5 deletions lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -1366,15 +1368,24 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,

switch (OutputModeArg->getOption().getID()) {
case options::OPT_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;

case options::OPT_emit_library:
OI.LinkAction = LinkKind::DynamicLibrary;
OI.LinkAction = Args.hasArg(options::OPT_static) ?
LinkKind::StaticLibrary :
LinkKind::DynamicLibrary;
OI.CompilerOutputType = file_types::TY_Object;
break;

case options::OPT_static:
break;

case options::OPT_emit_object:
OI.CompilerOutputType = file_types::TY_Object;
break;
Expand Down Expand Up @@ -1550,7 +1561,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.
Expand Down Expand Up @@ -1949,8 +1961,15 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
}

if (OI.shouldLink() && !AllLinkerInputs.empty()) {
auto *LinkAction = C.createAction<LinkJobAction>(AllLinkerInputs,
OI.LinkAction);
JobAction *LinkAction = nullptr;

if (OI.LinkAction == LinkKind::StaticLibrary) {
LinkAction = C.createAction<StaticLinkJobAction>(AllLinkerInputs,
OI.LinkAction);
} else {
LinkAction = C.createAction<DynamicLinkJobAction>(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
Expand Down Expand Up @@ -2177,7 +2196,15 @@ 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);
auto link = dyn_cast<LinkJobAction>(JA);

if (auto link = dyn_cast<StaticLinkJobAction>(JA)) {
Buffer = "lib";
Buffer.append(BaseName);
Buffer.append(Triple.isOSWindows() ? ".lib" : ".a");
return Buffer.str();
}

auto link = dyn_cast<DynamicLinkJobAction>(JA);
if (!link)
return BaseName;
if (link->getKind() != LinkKind::DynamicLibrary)
Expand Down
3 changes: 2 additions & 1 deletion lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ std::unique_ptr<Job> ToolChain::constructJob(
CASE(BackendJob)
CASE(MergeModuleJob)
CASE(ModuleWrapJob)
CASE(LinkJob)
CASE(DynamicLinkJob)
CASE(StaticLinkJob)
CASE(GenerateDSYMJob)
CASE(VerifyDebugInfoJob)
CASE(GeneratePCHJob)
Expand Down
9 changes: 8 additions & 1 deletion lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
inputArgs.AddLastArg(arguments, options::OPT_swift_version);
inputArgs.AddLastArg(arguments, options::OPT_enforce_exclusivity_EQ);
inputArgs.AddLastArg(arguments, options::OPT_stats_output_dir);
Expand Down Expand Up @@ -1086,11 +1087,17 @@ ToolChain::constructInvocation(const AutolinkExtractJobAction &job,
}

ToolChain::InvocationInfo
ToolChain::constructInvocation(const LinkJobAction &job,
ToolChain::constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const {
llvm_unreachable("linking not implemented for this toolchain");
}

ToolChain::InvocationInfo
ToolChain::constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const {
llvm_unreachable("archiving not implemented for this toolchain");
}

void ToolChain::addPathEnvironmentVariableIfNeeded(
Job::EnvironmentVector &env, const char *name, const char *separator,
options::ID optionID, const ArgList &args, StringRef extraEntry) const {
Expand Down
12 changes: 9 additions & 3 deletions lib/Driver/ToolChains.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
protected:
InvocationInfo constructInvocation(const InterpretJobAction &job,
const JobContext &context) const override;
InvocationInfo constructInvocation(const LinkJobAction &job,
InvocationInfo constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const override;
InvocationInfo constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const override;

std::string findProgramRelativeToSwiftImpl(StringRef name) const override;
Expand All @@ -41,7 +43,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {

class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
protected:
InvocationInfo constructInvocation(const LinkJobAction &job,
InvocationInfo constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const override;
InvocationInfo constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const override;

public:
Expand Down Expand Up @@ -79,7 +83,9 @@ class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain {
/// default is to return true (and so specify an -rpath).
virtual bool shouldProvideRPathToLinker() const;

InvocationInfo constructInvocation(const LinkJobAction &job,
InvocationInfo constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const override;
InvocationInfo constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const override;

public:
Expand Down
29 changes: 28 additions & 1 deletion lib/Driver/UnixToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bool toolchains::GenericUnix::shouldProvideRPathToLinker() const {
}

ToolChain::InvocationInfo
toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job,
const JobContext &context) const {
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
"Invalid linker output type.");
Expand All @@ -130,6 +130,8 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
case LinkKind::DynamicLibrary:
Arguments.push_back("-shared");
break;
case LinkKind::StaticLibrary:
llvm_unreachable("the dynamic linker cannot build static libraries");
}

// Select the linker to use.
Expand Down Expand Up @@ -320,6 +322,31 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
return II;
}


ToolChain::InvocationInfo
toolchains::GenericUnix::constructInvocation(const StaticLinkJobAction &job,
const JobContext &context) const {
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
"Invalid linker output type.");

ArgStringList Arguments;

// Configure the toolchain.
const char *AR = "ar";
Arguments.push_back("crs");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If llvm-ar is available, Please add an explicit -format GNU to the invocation.


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};

return II;
}

std::string toolchains::Android::getTargetForLinker() const {
const llvm::Triple &T = getTriple();
if (T.getArch() == llvm::Triple::arm &&
Expand Down
Loading