authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-30 20:18:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-30 20:25:28-07:00
log429a219f42c93957dee41021a22547549a8c54a2
tree43cd5f8a742d0d936e4f09cf9d31af344b7b0444
parentc55984b58f6a235893556f0b906e1ba3d301ec12

stage2: fix not detecting all dynamic libraries

Positional shared library arguments were not being detected as causing dynamic linking, resulting in invalid linker lines. LLD did not have an error message for this when targeting x86_64-linux but it did emit an error message when targeting aarch64-linux, which is how I noticed the problem. This surfaced an error having to do with fifo.pipe() in the cat example which I did not diagnose but solved the issue by doing the revamp that was already overdue for that example. It appears that the zig-window project was exploiting the previous behavior for it to function properly, so this prompts the question, is there some kind of static/dynamic executable hybrid that the compiler should recognize? Unclear - but we can discuss that in #7240.

3 files changed, 28 insertions(+), 34 deletions(-)

src/Compilation.zig+13-2
...@@ -510,8 +510,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -510,8 +510,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
510 {510 {
511 break :dl true;511 break :dl true;
512 }512 }
513 if (options.system_libs.len != 0) {513 const any_dyn_libs: bool = x: {
514 // when creating a executable that links to system libraries,514 if (options.system_libs.len != 0)
515 break :x true;
516 for (options.link_objects) |obj| {
517 switch (classifyFileExt(obj)) {
518 .shared_library => break :x true,
519 else => continue,
520 }
521 }
522 break :x false;
523 };
524 if (any_dyn_libs) {
525 // When creating a executable that links to system libraries,
515 // we require dynamic linking, but we must not link static libraries526 // we require dynamic linking, but we must not link static libraries
516 // or object files dynamically!527 // or object files dynamically!
517 break :dl (options.output_mode == .Exe);528 break :dl (options.output_mode == .Exe);
test/standalone/cat/main.zig+12-32
...@@ -5,41 +5,38 @@ const fs = std.fs;...@@ -5,41 +5,38 @@ const fs = std.fs;
5const mem = std.mem;5const mem = std.mem;
6const warn = std.log.warn;6const warn = std.log.warn;
77
8var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
9const allocator = &general_purpose_allocator.allocator;
10
11pub fn main() !void {8pub fn main() !void {
12 defer _ = general_purpose_allocator.deinit();9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
10 defer arena_instance.deinit();
11 const arena = &arena_instance.allocator;
12
13 const args = try process.argsAlloc(arena);
1314
14 var args_it = process.args();15 const exe = args[0];
15 const exe = try unwrapArg(args_it.next(allocator).?);
16 defer allocator.free(exe);
17 var catted_anything = false;16 var catted_anything = false;
18 const stdout_file = io.getStdOut();17 const stdout_file = io.getStdOut();
1918
20 const cwd = fs.cwd();19 const cwd = fs.cwd();
2120
22 while (args_it.next(allocator)) |arg_or_err| {21 for (args[1..]) |arg| {
23 const arg = try unwrapArg(arg_or_err);
24 defer allocator.free(arg);
25 if (mem.eql(u8, arg, "-")) {22 if (mem.eql(u8, arg, "-")) {
26 catted_anything = true;23 catted_anything = true;
27 try cat_file(stdout_file, io.getStdIn());24 try stdout_file.writeFileAll(io.getStdIn(), .{});
28 } else if (arg[0] == '-') {25 } else if (mem.startsWith(u8, arg, "-")) {
29 return usage(exe);26 return usage(exe);
30 } else {27 } else {
31 const file = cwd.openFile(arg, .{}) catch |err| {28 const file = cwd.openFile(arg, .{}) catch |err| {
32 warn("Unable to open file: {}\n", .{@errorName(err)});29 warn("Unable to open file: {s}\n", .{@errorName(err)});
33 return err;30 return err;
34 };31 };
35 defer file.close();32 defer file.close();
3633
37 catted_anything = true;34 catted_anything = true;
38 try cat_file(stdout_file, file);35 try stdout_file.writeFileAll(file, .{});
39 }36 }
40 }37 }
41 if (!catted_anything) {38 if (!catted_anything) {
42 try cat_file(stdout_file, io.getStdIn());39 try stdout_file.writeFileAll(io.getStdIn(), .{});
43 }40 }
44}41}
4542
...@@ -47,20 +44,3 @@ fn usage(exe: []const u8) !void {...@@ -47,20 +44,3 @@ fn usage(exe: []const u8) !void {
47 warn("Usage: {} [FILE]...\n", .{exe});44 warn("Usage: {} [FILE]...\n", .{exe});
48 return error.Invalid;45 return error.Invalid;
49}46}
50
51// TODO use copy_file_range
52fn cat_file(stdout: fs.File, file: fs.File) !void {
53 var fifo = std.fifo.LinearFifo(u8, .{ .Static = 1024 * 4 }).init();
54
55 fifo.pump(file.reader(), stdout.writer()) catch |err| {
56 warn("Unable to read from stream or write to stdout: {}\n", .{@errorName(err)});
57 return err;
58 };
59}
60
61fn unwrapArg(arg: anyerror![]u8) ![]u8 {
62 return arg catch |err| {
63 warn("Unable to parse command line: {}\n", .{err});
64 return err;
65 };
66}
test/standalone/shared_library/build.zig+3
...@@ -1,9 +1,12 @@...@@ -1,9 +1,12 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: *Builder) void {3pub fn build(b: *Builder) void {
4 const target = b.standardTargetOptions(.{});
4 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));5 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
6 lib.setTarget(target);
57
6 const exe = b.addExecutable("test", null);8 const exe = b.addExecutable("test", null);
9 exe.setTarget(target);
7 exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});10 exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
8 exe.linkLibrary(lib);11 exe.linkLibrary(lib);
9 exe.linkSystemLibrary("c");12 exe.linkSystemLibrary("c");