Skip to content

Commit 10a187d

Browse files
committed
[Autolink Extract] Keep a set of linker flags instead of vector
Otherwise we can duplicate linker flags across input binaries, which can result in very large linkerr invocation commands. Resolves #58380
1 parent 415c5c1 commit 10a187d

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

lib/DriverTool/autolink_extract_main.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <string>
2020
#include <vector>
21+
#include <unordered_set>
2122

2223
#include "swift/AST/DiagnosticsFrontend.h"
2324
#include "swift/Frontend/Frontend.h"
@@ -112,6 +113,7 @@ class AutolinkExtractInvocation {
112113
/// Return 'true' if there was an error, and 'false' otherwise.
113114
static bool
114115
extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
116+
std::unordered_set<std::string> &SeenLinkerLibraryFlags,
115117
std::vector<std::string> &LinkerFlags,
116118
CompilerInstance &Instance) {
117119
// Search for the section we hold autolink entries in
@@ -140,8 +142,15 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
140142
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
141143
SectionData->split(SplitFlags, llvm::StringRef("\0", 1), -1,
142144
/*KeepEmpty=*/false);
143-
for (const auto &Flag : SplitFlags)
144-
LinkerFlags.push_back(Flag.str());
145+
for (const auto &Flag : SplitFlags) {
146+
// If this is a library '-lxxx' flag, only add it if we have not seen it before
147+
if (Flag.str().rfind("-l", 0) == 0) {
148+
auto SeenFlagsInsertResult = SeenLinkerLibraryFlags.insert(Flag.str());
149+
if (SeenFlagsInsertResult.second == true)
150+
LinkerFlags.push_back(Flag.str());
151+
} else
152+
LinkerFlags.push_back(Flag.str());
153+
}
145154
}
146155
}
147156
return false;
@@ -152,6 +161,7 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
152161
/// 'true' if there was an error, and 'false' otherwise.
153162
static bool
154163
extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
164+
std::unordered_set<std::string> &SeenLinkerLibraryFlags,
155165
std::vector<std::string> &LinkerFlags,
156166
CompilerInstance &Instance) {
157167
// Search for the data segment we hold autolink entries in
@@ -164,8 +174,15 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
164174
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
165175
SegmentData.split(SplitFlags, llvm::StringRef("\0", 1), -1,
166176
/*KeepEmpty=*/false);
167-
for (const auto &Flag : SplitFlags)
168-
LinkerFlags.push_back(Flag.str());
177+
for (const auto &Flag : SplitFlags) {
178+
// If this is a library '-lxxx' flag, only add it if we have not seen it before
179+
if (Flag.str().rfind("-l", 0) == 0) {
180+
auto SeenFlagsInsertResult = SeenLinkerLibraryFlags.insert(Flag.str());
181+
if (SeenFlagsInsertResult.second == true)
182+
LinkerFlags.push_back(Flag.str());
183+
} else
184+
LinkerFlags.push_back(Flag.str());
185+
}
169186
}
170187
}
171188
return false;
@@ -178,12 +195,13 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
178195
static bool extractLinkerFlags(const llvm::object::Binary *Bin,
179196
CompilerInstance &Instance,
180197
StringRef BinaryFileName,
198+
std::unordered_set<std::string> &SeenLinkerLibraryFlags,
181199
std::vector<std::string> &LinkerFlags) {
182200
if (auto *ObjectFile = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Bin)) {
183-
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
201+
return extractLinkerFlagsFromObjectFile(ObjectFile, SeenLinkerLibraryFlags, LinkerFlags, Instance);
184202
} else if (auto *ObjectFile =
185203
llvm::dyn_cast<llvm::object::WasmObjectFile>(Bin)) {
186-
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
204+
return extractLinkerFlagsFromObjectFile(ObjectFile, SeenLinkerLibraryFlags, LinkerFlags, Instance);
187205
} else if (auto *Archive = llvm::dyn_cast<llvm::object::Archive>(Bin)) {
188206
llvm::Error Error = llvm::Error::success();
189207
for (const auto &Child : Archive->children(Error)) {
@@ -197,7 +215,7 @@ static bool extractLinkerFlags(const llvm::object::Binary *Bin,
197215
return true;
198216
}
199217
if (extractLinkerFlags(ChildBinary->get(), Instance, BinaryFileName,
200-
LinkerFlags)) {
218+
SeenLinkerLibraryFlags, LinkerFlags)) {
201219
return true;
202220
}
203221
}
@@ -228,6 +246,8 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
228246
}
229247

230248
std::vector<std::string> LinkerFlags;
249+
// Flags of the form '-lxxx' seen so far
250+
std::unordered_set<std::string> SeenLinkerLibraryFlags;
231251

232252
// Extract the linker flags from the objects.
233253
for (const auto &BinaryFileName : Invocation.getInputFilenames()) {
@@ -245,7 +265,7 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
245265
}
246266

247267
if (extractLinkerFlags(BinaryOwner->getBinary(), Instance, BinaryFileName,
248-
LinkerFlags)) {
268+
SeenLinkerLibraryFlags, LinkerFlags)) {
249269
return 1;
250270
}
251271
}

test/AutolinkExtract/import.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swiftc_driver -emit-module -emit-module-path %t/empty.swiftmodule -module-name empty -module-link-name empty %S/empty.swift
33
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental.o
4-
// RUN: %target-swift-autolink-extract %t/import_experimental.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
4+
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental_again.o
5+
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
6+
7+
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix UNIQUE %s
58

69
// REQUIRES: autolink-extract
710

11+
// UNIQUE-COUNT-1: -lempty
12+
// UNIQUE-COUNT-1: -lswiftCore
13+
814
// CHECK-elf-DAG: -lswiftCore
915
// CHECK-elf-DAG: -lempty
1016

0 commit comments

Comments
 (0)