Skip to content

Commit b34a1cb

Browse files
committed
Driver: add -static flag for generating static archives
1 parent ee6688d commit b34a1cb

File tree

14 files changed

+209
-6
lines changed

14 files changed

+209
-6
lines changed

include/swift/AST/DiagnosticsDriver.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ ERROR(error_expected_frontend_command,none,
6464
ERROR(error_cannot_specify__o_for_multiple_outputs,none,
6565
"cannot specify -o when generating multiple output files", ())
6666

67+
ERROR(error_static_emit_executable_disallowed,none,
68+
"-static may not be used with -emit-executable", ())
69+
6770
ERROR(error_unable_to_load_output_file_map, none,
6871
"unable to load output file map '%1': %0", (StringRef, StringRef))
6972

include/swift/Driver/Action.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Action {
4848
AutolinkExtractJob,
4949
REPLJob,
5050
LinkJob,
51+
ArchiveJob,
5152
GenerateDSYMJob,
5253
VerifyDebugInfoJob,
5354
GeneratePCHJob,
@@ -313,7 +314,7 @@ class LinkJobAction : public JobAction {
313314
LinkJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
314315
: JobAction(Action::Kind::LinkJob, Inputs, file_types::TY_Image),
315316
Kind(K) {
316-
assert(Kind != LinkKind::None);
317+
assert(Kind != LinkKind::None && Kind != LinkKind::StaticLibrary);
317318
}
318319

319320
LinkKind getKind() const { return Kind; }
@@ -323,6 +324,20 @@ class LinkJobAction : public JobAction {
323324
}
324325
};
325326

327+
class ArchiveJobAction : public JobAction {
328+
virtual void anchor();
329+
330+
public:
331+
ArchiveJobAction(ArrayRef<const Action *> Inputs, LinkKind K)
332+
: JobAction(Action::Kind::ArchiveJob, Inputs, file_types::TY_Image) {
333+
assert(K == LinkKind::StaticLibrary);
334+
}
335+
336+
static bool classof(const Action *A) {
337+
return A->getKind() == Action::Kind::ArchiveJob;
338+
}
339+
};
340+
326341
} // end namespace driver
327342
} // end namespace swift
328343

include/swift/Driver/ToolChain.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ class ToolChain {
161161
virtual InvocationInfo constructInvocation(const LinkJobAction &job,
162162
const JobContext &context) const;
163163

164+
virtual InvocationInfo constructInvocation(const ArchiveJobAction &job,
165+
const JobContext &context) const;
166+
164167
/// Searches for the given executable in appropriate paths relative to the
165168
/// Swift binary.
166169
///

include/swift/Driver/Util.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ namespace driver {
3434
enum class LinkKind {
3535
None,
3636
Executable,
37-
DynamicLibrary
37+
DynamicLibrary,
38+
StaticLibrary
3839
};
3940

4041
/// Used by a Job to request a "filelist": a file containing a list of all

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ def emit_objc_header_path : Separate<["-"], "emit-objc-header-path">,
368368
ArgumentIsPath]>,
369369
MetaVarName<"<path>">, HelpText<"Emit an Objective-C header file to <path>">;
370370

371+
def static : Flag<["-"], "static">,
372+
Flags<[FrontendOption, ModuleInterfaceOption, NoInteractiveOption]>,
373+
HelpText<"Make this module statically linkable and make the output of -emit-library a static library.">;
374+
371375
def import_cf_types : Flag<["-"], "import-cf-types">,
372376
Flags<[FrontendOption, HelpHidden]>,
373377
HelpText<"Recognize and import CF types as class types">;

lib/Driver/Action.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const char *Action::getClassName(Kind AC) {
2929
case Kind::AutolinkExtractJob: return "swift-autolink-extract";
3030
case Kind::REPLJob: return "repl";
3131
case Kind::LinkJob: return "link";
32+
case Kind::ArchiveJob: return "archive";
3233
case Kind::GenerateDSYMJob: return "generate-dSYM";
3334
case Kind::VerifyDebugInfoJob: return "verify-debug-info";
3435
case Kind::GeneratePCHJob: return "generate-pch";
@@ -57,6 +58,8 @@ void REPLJobAction::anchor() {}
5758

5859
void LinkJobAction::anchor() {}
5960

61+
void ArchiveJobAction::anchor() {}
62+
6063
void GenerateDSYMJobAction::anchor() {}
6164

6265
void VerifyDebugInfoJobAction::anchor() {}

lib/Driver/DarwinToolChains.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
286286
case LinkKind::DynamicLibrary:
287287
Arguments.push_back("-dylib");
288288
break;
289+
case LinkKind::StaticLibrary:
290+
llvm_unreachable("the dynamic linker cannot build static libraries");
289291
}
290292

291293
assert(Triple.isOSDarwin());
@@ -527,6 +529,41 @@ toolchains::Darwin::constructInvocation(const LinkJobAction &job,
527529
return II;
528530
}
529531

532+
533+
ToolChain::InvocationInfo
534+
toolchains::Darwin::constructInvocation(const ArchiveJobAction &job,
535+
const JobContext &context) const {
536+
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
537+
"Invalid linker output type.");
538+
539+
// Configure the toolchain.
540+
const char *LibTool = "libtool";
541+
542+
InvocationInfo II = {LibTool};
543+
ArgStringList &Arguments = II.Arguments;
544+
545+
Arguments.push_back("-static");
546+
547+
if (context.shouldUseInputFileList()) {
548+
Arguments.push_back("-filelist");
549+
Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList"));
550+
II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object,
551+
FilelistInfo::WhichFiles::Input});
552+
} else {
553+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
554+
file_types::TY_Object);
555+
}
556+
557+
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
558+
559+
Arguments.push_back("-o");
560+
561+
Arguments.push_back(
562+
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));
563+
564+
return II;
565+
}
566+
530567
bool toolchains::Darwin::shouldStoreInvocationInDebugInfo() const {
531568
// This matches the behavior in Clang (see
532569
// clang/lib/driver/ToolChains/Darwin.cpp).

lib/Driver/Driver.cpp

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,8 @@ static bool maybeBuildingExecutable(const OutputInfo &OI,
12551255
return true;
12561256
case LinkKind::DynamicLibrary:
12571257
return false;
1258+
case LinkKind::StaticLibrary:
1259+
return false;
12581260
case LinkKind::None:
12591261
break;
12601262
}
@@ -1366,15 +1368,24 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
13661368

13671369
switch (OutputModeArg->getOption().getID()) {
13681370
case options::OPT_emit_executable:
1371+
if (Args.hasArg(options::OPT_static))
1372+
Diags.diagnose(SourceLoc(),
1373+
diag::error_static_emit_executable_disallowed);
1374+
13691375
OI.LinkAction = LinkKind::Executable;
13701376
OI.CompilerOutputType = file_types::TY_Object;
13711377
break;
13721378

13731379
case options::OPT_emit_library:
1374-
OI.LinkAction = LinkKind::DynamicLibrary;
1380+
OI.LinkAction = Args.hasArg(options::OPT_static) ?
1381+
LinkKind::StaticLibrary :
1382+
LinkKind::DynamicLibrary;
13751383
OI.CompilerOutputType = file_types::TY_Object;
13761384
break;
13771385

1386+
case options::OPT_static:
1387+
break;
1388+
13781389
case options::OPT_emit_object:
13791390
OI.CompilerOutputType = file_types::TY_Object;
13801391
break;
@@ -1550,7 +1561,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
15501561
OI.ModuleName = "REPL";
15511562
} else if (const Arg *A = Args.getLastArg(options::OPT_o)) {
15521563
OI.ModuleName = llvm::sys::path::stem(A->getValue());
1553-
if (OI.LinkAction == LinkKind::DynamicLibrary &&
1564+
if ((OI.LinkAction == LinkKind::DynamicLibrary ||
1565+
OI.LinkAction == LinkKind::StaticLibrary) &&
15541566
!llvm::sys::path::extension(A->getValue()).empty() &&
15551567
StringRef(OI.ModuleName).startswith("lib")) {
15561568
// Chop off a "lib" prefix if we're building a library.
@@ -1949,8 +1961,15 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
19491961
}
19501962

19511963
if (OI.shouldLink() && !AllLinkerInputs.empty()) {
1952-
auto *LinkAction = C.createAction<LinkJobAction>(AllLinkerInputs,
1953-
OI.LinkAction);
1964+
JobAction *LinkAction = nullptr;
1965+
1966+
if (OI.LinkAction == LinkKind::StaticLibrary) {
1967+
LinkAction = C.createAction<ArchiveJobAction>(AllLinkerInputs,
1968+
OI.LinkAction);
1969+
} else {
1970+
LinkAction = C.createAction<LinkJobAction>(AllLinkerInputs,
1971+
OI.LinkAction);
1972+
}
19541973

19551974
// On ELF platforms there's no built in autolinking mechanism, so we
19561975
// pull the info we need from the .o files directly and pass them as an
@@ -2177,6 +2196,14 @@ static StringRef baseNameForImage(const JobAction *JA, const OutputInfo &OI,
21772196
StringRef BaseInput, StringRef BaseName) {
21782197
if (JA->size() == 1 && OI.ModuleNameIsFallback && BaseInput != "-")
21792198
return llvm::sys::path::stem(BaseInput);
2199+
2200+
if (auto link = dyn_cast<ArchiveJobAction>(JA)) {
2201+
Buffer = "lib";
2202+
Buffer.append(BaseName);
2203+
Buffer.append(Triple.isOSWindows() ? ".lib" : ".a");
2204+
return Buffer.str();
2205+
}
2206+
21802207
auto link = dyn_cast<LinkJobAction>(JA);
21812208
if (!link)
21822209
return BaseName;

lib/Driver/ToolChain.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ std::unique_ptr<Job> ToolChain::constructJob(
100100
CASE(MergeModuleJob)
101101
CASE(ModuleWrapJob)
102102
CASE(LinkJob)
103+
CASE(ArchiveJob)
103104
CASE(GenerateDSYMJob)
104105
CASE(VerifyDebugInfoJob)
105106
CASE(GeneratePCHJob)

lib/Driver/ToolChains.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ static void addCommonFrontendArgs(const ToolChain &TC, const OutputInfo &OI,
208208
inputArgs.AddLastArg(arguments, options::OPT_warnings_as_errors);
209209
inputArgs.AddLastArg(arguments, options::OPT_sanitize_EQ);
210210
inputArgs.AddLastArg(arguments, options::OPT_sanitize_coverage_EQ);
211+
inputArgs.AddLastArg(arguments, options::OPT_static);
211212
inputArgs.AddLastArg(arguments, options::OPT_swift_version);
212213
inputArgs.AddLastArg(arguments, options::OPT_enforce_exclusivity_EQ);
213214
inputArgs.AddLastArg(arguments, options::OPT_stats_output_dir);
@@ -1091,6 +1092,12 @@ ToolChain::constructInvocation(const LinkJobAction &job,
10911092
llvm_unreachable("linking not implemented for this toolchain");
10921093
}
10931094

1095+
ToolChain::InvocationInfo
1096+
ToolChain::constructInvocation(const ArchiveJobAction &job,
1097+
const JobContext &context) const {
1098+
llvm_unreachable("archiving not implemented for this toolchain");
1099+
}
1100+
10941101
void ToolChain::addPathEnvironmentVariableIfNeeded(
10951102
Job::EnvironmentVector &env, const char *name, const char *separator,
10961103
options::ID optionID, const ArgList &args, StringRef extraEntry) const {

lib/Driver/ToolChains.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain {
2727
const JobContext &context) const override;
2828
InvocationInfo constructInvocation(const LinkJobAction &job,
2929
const JobContext &context) const override;
30+
InvocationInfo constructInvocation(const ArchiveJobAction &job,
31+
const JobContext &context) const override;
3032

3133
std::string findProgramRelativeToSwiftImpl(StringRef name) const override;
3234

@@ -43,6 +45,8 @@ class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain {
4345
protected:
4446
InvocationInfo constructInvocation(const LinkJobAction &job,
4547
const JobContext &context) const override;
48+
InvocationInfo constructInvocation(const ArchiveJobAction &job,
49+
const JobContext &context) const override;
4650

4751
public:
4852
Windows(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {}
@@ -81,6 +85,8 @@ class LLVM_LIBRARY_VISIBILITY GenericUnix : public ToolChain {
8185

8286
InvocationInfo constructInvocation(const LinkJobAction &job,
8387
const JobContext &context) const override;
88+
InvocationInfo constructInvocation(const ArchiveJobAction &job,
89+
const JobContext &context) const override;
8490

8591
public:
8692
GenericUnix(const Driver &D, const llvm::Triple &Triple)

lib/Driver/UnixToolChains.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
130130
case LinkKind::DynamicLibrary:
131131
Arguments.push_back("-shared");
132132
break;
133+
case LinkKind::StaticLibrary:
134+
llvm_unreachable("the dynamic linker cannot build static libraries");
133135
}
134136

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

325+
326+
ToolChain::InvocationInfo
327+
toolchains::GenericUnix::constructInvocation(const ArchiveJobAction &job,
328+
const JobContext &context) const {
329+
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
330+
"Invalid linker output type.");
331+
332+
ArgStringList Arguments;
333+
334+
// Configure the toolchain.
335+
const char *AR = "ar";
336+
Arguments.push_back("crs");
337+
338+
Arguments.push_back(
339+
context.Args.MakeArgString(context.Output.getPrimaryOutputFilename()));
340+
341+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
342+
file_types::TY_Object);
343+
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
344+
345+
InvocationInfo II{AR, Arguments};
346+
347+
return II;
348+
}
349+
323350
std::string toolchains::Android::getTargetForLinker() const {
324351
const llvm::Triple &T = getTriple();
325352
if (T.getArch() == llvm::Triple::arm &&

lib/Driver/WindowsToolChains.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
6161
case LinkKind::DynamicLibrary:
6262
Arguments.push_back("-shared");
6363
break;
64+
case LinkKind::StaticLibrary:
65+
llvm_unreachable("invalid link kind");
6466
}
6567

6668
// Select the linker to use.
@@ -193,3 +195,29 @@ toolchains::Windows::constructInvocation(const LinkJobAction &job,
193195

194196
return II;
195197
}
198+
199+
ToolChain::InvocationInfo
200+
toolchains::Windows::constructInvocation(const ArchiveJobAction &job,
201+
const JobContext &context) const {
202+
assert(context.Output.getPrimaryOutputType() == file_types::TY_Image &&
203+
"Invalid linker output type.");
204+
205+
ArgStringList Arguments;
206+
207+
// Configure the toolchain.
208+
const char *Link = "link";
209+
Arguments.push_back("-lib");
210+
211+
addPrimaryInputsOfType(Arguments, context.Inputs, context.Args,
212+
file_types::TY_Object);
213+
addInputsOfType(Arguments, context.InputActions, file_types::TY_Object);
214+
215+
Arguments.push_back(
216+
context.Args.MakeArgString(Twine("/OUT:") +
217+
context.Output.getPrimaryOutputFilename()));
218+
219+
InvocationInfo II{Link, Arguments};
220+
II.allowsResponseFiles = true;
221+
222+
return II;
223+
}

0 commit comments

Comments
 (0)