Skip to content

Commit eec825c

Browse files
committed
zig cc: support -Bdynamic and -Bstatic parameters
Related: #10050
1 parent b196dd1 commit eec825c

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

src/link/Elf.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
15531553
defer test_path.deinit();
15541554
for (self.base.options.lib_dirs) |lib_dir_path| {
15551555
for (self.base.options.system_libs.keys()) |link_lib| {
1556-
test_path.shrinkRetainingCapacity(0);
1556+
test_path.clearRetainingCapacity();
15571557
const sep = fs.path.sep_str;
15581558
try test_path.writer().print("{s}" ++ sep ++ "lib{s}.so", .{
15591559
lib_dir_path, link_lib,

src/main.zig

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,9 @@ fn buildOutputType(
668668
var system_libs = std.StringArrayHashMap(Compilation.SystemLib).init(gpa);
669669
defer system_libs.deinit();
670670

671+
var static_libs = std.ArrayList([]const u8).init(gpa);
672+
defer static_libs.deinit();
673+
671674
var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa);
672675
defer wasi_emulated_libs.deinit();
673676

@@ -1253,6 +1256,7 @@ fn buildOutputType(
12531256
var it = ClangArgIterator.init(arena, all_args);
12541257
var emit_llvm = false;
12551258
var needed = false;
1259+
var force_static_libs = false;
12561260
while (it.has_next) {
12571261
it.next() catch |err| {
12581262
fatal("unable to parse command line parameters: {s}", .{@errorName(err)});
@@ -1287,7 +1291,11 @@ fn buildOutputType(
12871291
// -l
12881292
// We don't know whether this library is part of libc or libc++ until
12891293
// we resolve the target, so we simply append to the list for now.
1290-
try system_libs.put(it.only_arg, .{ .needed = needed });
1294+
if (force_static_libs) {
1295+
try static_libs.append(it.only_arg);
1296+
} else {
1297+
try system_libs.put(it.only_arg, .{ .needed = needed });
1298+
}
12911299
},
12921300
.ignore => {},
12931301
.driver_punt => {
@@ -1333,6 +1341,17 @@ fn buildOutputType(
13331341
needed = false;
13341342
} else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
13351343
needed = true;
1344+
} else if (mem.eql(u8, linker_arg, "-Bdynamic") or
1345+
mem.eql(u8, linker_arg, "-dy") or
1346+
mem.eql(u8, linker_arg, "-call_shared"))
1347+
{
1348+
force_static_libs = false;
1349+
} else if (mem.eql(u8, linker_arg, "-Bstatic") or
1350+
mem.eql(u8, linker_arg, "-dn") or
1351+
mem.eql(u8, linker_arg, "-non_shared") or
1352+
mem.eql(u8, linker_arg, "-static"))
1353+
{
1354+
force_static_libs = true;
13361355
} else {
13371356
try linker_args.append(linker_arg);
13381357
}
@@ -1893,6 +1912,48 @@ fn buildOutputType(
18931912
}
18941913
}
18951914

1915+
{
1916+
// Resolve static libraries into full paths.
1917+
const sep = fs.path.sep_str;
1918+
1919+
var test_path = std.ArrayList(u8).init(gpa);
1920+
defer test_path.deinit();
1921+
1922+
for (static_libs.items) |static_lib| {
1923+
for (lib_dirs.items) |lib_dir_path| {
1924+
test_path.clearRetainingCapacity();
1925+
try test_path.writer().print("{s}" ++ sep ++ "{s}{s}{s}", .{
1926+
lib_dir_path,
1927+
target_info.target.libPrefix(),
1928+
static_lib,
1929+
target_info.target.staticLibSuffix(),
1930+
});
1931+
fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
1932+
error.FileNotFound => continue,
1933+
else => |e| fatal("unable to search for static library '{s}': {s}", .{
1934+
test_path.items, @errorName(e),
1935+
}),
1936+
};
1937+
try link_objects.append(try arena.dupe(u8, test_path.items));
1938+
break;
1939+
} else {
1940+
var search_paths = std.ArrayList(u8).init(arena);
1941+
for (lib_dirs.items) |lib_dir_path| {
1942+
try search_paths.writer().print("\n {s}" ++ sep ++ "{s}{s}{s}", .{
1943+
lib_dir_path,
1944+
target_info.target.libPrefix(),
1945+
static_lib,
1946+
target_info.target.staticLibSuffix(),
1947+
});
1948+
}
1949+
try search_paths.appendSlice("\n suggestion: use full paths to static libraries on the command line rather than using -l and -L arguments");
1950+
fatal("static library '{s}' not found. search paths: {s}", .{
1951+
static_lib, search_paths.items,
1952+
});
1953+
}
1954+
}
1955+
}
1956+
18961957
const object_format: std.Target.ObjectFormat = blk: {
18971958
const ofmt = target_ofmt orelse break :blk target_info.target.getObjectFormat();
18981959
if (mem.eql(u8, ofmt, "elf")) {

0 commit comments

Comments
 (0)