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

Conversation

troughton
Copy link
Contributor

Add a -static flag to the driver that, when combined with -emit-library, generates a static library using the platform archiver.

In the future, this -static flag will also be used on Windows to determine whether a Swift module should have DLLImport linkage applied.

@@ -48,6 +48,7 @@ class Action {
AutolinkExtractJob,
REPLJob,
LinkJob,
ArchiveJob,
Copy link
Member

Choose a reason for hiding this comment

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

I would like to get @jrose-apple's opinion on naming these: DyamicLinkJob and StaticLinkJob

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I think I like @compnerd's names better (sans typo).

Copy link
Contributor

Choose a reason for hiding this comment

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

Doing it in a separate commit (but still the same PR) might be nice for reviewing purposes, but not necessary.

ArgStringList Arguments;

// 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?).

@@ -284,6 +284,8 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
case LinkKind::DynamicLibrary:
Arguments.push_back("-dylib");
break;
case LinkKind::StaticLibrary:
llvm_unreachable("invalid link kind");
Copy link
Member

Choose a reason for hiding this comment

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

Rather than "invalid link kind" can you clarify that cannot perform archiving with the dynamic linker?

@@ -2177,6 +2196,19 @@ 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<ArchiveJobAction>(JA)) {
Buffer = Triple.isOSWindows() ? "" : "lib";
Copy link
Member

Choose a reason for hiding this comment

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

Actually, please prepend lib on Windows for the static archives.

if (Triple.isOSWindows())
Buffer.append(".lib");
else
Buffer.append(".a");
Copy link
Member

Choose a reason for hiding this comment

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

Just use a ternary here.

}
}

if (AR == nullptr) {
Copy link
Member

Choose a reason for hiding this comment

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

You can combine this with the previous clause with an else:

  if (const char *ar = llvm::sys::findProgramByName("llvm-ar", {toolchainPath}))
    Arguments.push_back(context.Args.MakeArgString(ar));
  else if (const char *ar = llvm::sys::findProgramByName("ar", {toolchainPath}))
    Arguments.push_back(context.Args.MakeArgString(ar));

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

InvocationInfo II{AR, Arguments};
II.allowsResponseFiles = true;
Copy link
Member

Choose a reason for hiding this comment

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

mmm I don't think that the traditional archiver permits response files. This should be equivalent to whether llvm-ar is in use.

@@ -61,6 +61,8 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
case LinkKind::DynamicLibrary:
Arguments.push_back("-shared");
break;
case LinkKind::StaticLibrary:
llvm_unreachable("invalid link kind");
Copy link
Member

Choose a reason for hiding this comment

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

Similar to Darwin and Linux cases

ArgStringList Arguments;

// Configure the toolchain.
const char *Lib = "lib";
Copy link
Member

Choose a reason for hiding this comment

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

Please use llvm-ar if available, otherwise fall back to lld-link (lld-link -lib), otherwise try lib. I don't think that we need to bother with link /LIB as a means of invoking the librarian (lib).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That seems a lot of complexity – three tools with different invocations. I assume you want llvm-ar and lld-link for cross-compilation, so would it be enough to just pick one of those and say it's required for cross-compilation?

Copy link
Member

Choose a reason for hiding this comment

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

I don't want to depend on lld-link yet. Until we have swift-lld created and tracking, please do not depend on lld-link. However, lld-link and link should be compatible enough, and link -lib is the same as lib.exe. So if you want to just use link to invoke the librarian, I am fine with that for Windows. You can use either lld-link or link then to invoke lib.

// INFERRED_NAME_DARWIN: libtool -static
// INFERRED_NAME_DARWIN: -o libARCHIVER.a
// INFERRED_NAME_LINUX: libARCHIVER.a
// INFERRED_NAME_WINDOWS: ARCHIVER.lib
Copy link
Member

Choose a reason for hiding this comment

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

Please add a test case for the invalid combination (-emit-executable -static) as well as tests for the fallback path using mocked toolchains.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you clarify what you mean by "tests for the fallback path using mocked toolchains", or point to existing similar tests? I assume you mean ensure that we use the correct tools for e.g. lld-link, but I can't see where that's actually tested for the dynamic linker path – there's a line referencing config.link in lit.cfg but I'm not sure how that feeds into the tests.

@troughton troughton force-pushed the static-libraries-driver branch from cf350b2 to 4f391b4 Compare June 2, 2019 22:57
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));

InvocationInfo II{LibTool, Arguments};
II.allowsResponseFiles = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think libtool does allow response files. It does have a form of filelist, though, which you could borrow from the dynamic linking logic on Darwin.

@@ -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) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: indentation should align by the open-paren.

@troughton troughton force-pushed the static-libraries-driver branch 3 times, most recently from 19585e2 to 78b593f Compare June 17, 2019 00:46
@troughton troughton force-pushed the static-libraries-driver branch from 78b593f to e5ea42d Compare June 17, 2019 00:49
@troughton
Copy link
Contributor Author

I've removed the parts of this PR which used non-system-default linkers. @compnerd, I know that won't meet your needs, but it's probably best to get the uncontroversial parts of this PR in before dealing with the complexity of customising the choice of linker.

Provided this looks okay with you, @jrose-apple, this should be okay to merge. (I've rebased off master but can't build locally since I don't have Catalina installed – hopefully all the tests still pass CI.)

@jrose-apple
Copy link
Contributor

I'll take a look soon, but note that you shouldn't need Catalina installed to build, just Xcode 11.

@jrose-apple
Copy link
Contributor

@swift-ci Please test

@jrose-apple jrose-apple self-assigned this Jun 18, 2019
@jrose-apple
Copy link
Contributor

@compnerd, are you okay with this base thing going in, and we can discuss libtool/ar/llvm-ar later?

@compnerd
Copy link
Member

@jrose-apple - okay, lets do that. At least we have a starting point then to make improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants