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:58:15-07:00
loga9b7d8fa07ec0b85a8d13c914cfed0d4c99942b8
treec5eb3abbb4250cafde63cbb8a6a57e13c3d089a9
parent57ac835a03b77a14a218daf250d33f580cd6f484

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, 30 insertions(+), 41 deletions(-)

src/Compilation.zig+13-2
...@@ -506,8 +506,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -506,8 +506,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
506 {506 {
507 break :dl true;507 break :dl true;
508 }508 }
509 if (options.system_libs.len != 0) {509 const any_dyn_libs: bool = x: {
510 // when creating a executable that links to system libraries,510 if (options.system_libs.len != 0)
511 break :x true;
512 for (options.link_objects) |obj| {
513 switch (classifyFileExt(obj)) {
514 .shared_library => break :x true,
515 else => continue,
516 }
517 }
518 break :x false;
519 };
520 if (any_dyn_libs) {
521 // When creating a executable that links to system libraries,
511 // we require dynamic linking, but we must not link static libraries522 // we require dynamic linking, but we must not link static libraries
512 // or object files dynamically!523 // or object files dynamically!
513 break :dl (options.output_mode == .Exe);524 break :dl (options.output_mode == .Exe);
test/standalone/cat/main.zig+14-39
...@@ -3,37 +3,40 @@ const io = std.io;...@@ -3,37 +3,40 @@ const io = std.io;
3const process = std.process;3const process = std.process;
4const fs = std.fs;4const fs = std.fs;
5const mem = std.mem;5const mem = std.mem;
6const warn = std.debug.warn;6const warn = std.log.warn;
7const allocator = std.testing.allocator;
87
9pub fn main() !void {8pub fn main() !void {
10 var args_it = process.args();9 var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 const exe = try unwrapArg(args_it.next(allocator).?);10 defer arena_instance.deinit();
11 const arena = &arena_instance.allocator;
12
13 const args = try process.argsAlloc(arena);
14
15 const exe = args[0];
12 var catted_anything = false;16 var catted_anything = false;
13 const stdout_file = io.getStdOut();17 const stdout_file = io.getStdOut();
1418
15 const cwd = fs.cwd();19 const cwd = fs.cwd();
1620
17 while (args_it.next(allocator)) |arg_or_err| {21 for (args[1..]) |arg| {
18 const arg = try unwrapArg(arg_or_err);
19 if (mem.eql(u8, arg, "-")) {22 if (mem.eql(u8, arg, "-")) {
20 catted_anything = true;23 catted_anything = true;
21 try cat_file(stdout_file, io.getStdIn());24 try stdout_file.writeFileAll(io.getStdIn(), .{});
22 } else if (arg[0] == '-') {25 } else if (mem.startsWith(u8, arg, "-")) {
23 return usage(exe);26 return usage(exe);
24 } else {27 } else {
25 const file = cwd.openFile(arg, .{}) catch |err| {28 const file = cwd.openFile(arg, .{}) catch |err| {
26 warn("Unable to open file: {}\n", .{@errorName(err)});29 warn("Unable to open file: {s}\n", .{@errorName(err)});
27 return err;30 return err;
28 };31 };
29 defer file.close();32 defer file.close();
3033
31 catted_anything = true;34 catted_anything = true;
32 try cat_file(stdout_file, file);35 try stdout_file.writeFileAll(file, .{});
33 }36 }
34 }37 }
35 if (!catted_anything) {38 if (!catted_anything) {
36 try cat_file(stdout_file, io.getStdIn());39 try stdout_file.writeFileAll(io.getStdIn(), .{});
37 }40 }
38}41}
3942
...@@ -41,31 +44,3 @@ fn usage(exe: []const u8) !void {...@@ -41,31 +44,3 @@ fn usage(exe: []const u8) !void {
41 warn("Usage: {} [FILE]...\n", .{exe});44 warn("Usage: {} [FILE]...\n", .{exe});
42 return error.Invalid;45 return error.Invalid;
43}46}
44
45// TODO use copy_file_range
46fn cat_file(stdout: fs.File, file: fs.File) !void {
47 var buf: [1024 * 4]u8 = undefined;
48
49 while (true) {
50 const bytes_read = file.read(buf[0..]) catch |err| {
51 warn("Unable to read from stream: {}\n", .{@errorName(err)});
52 return err;
53 };
54
55 if (bytes_read == 0) {
56 break;
57 }
58
59 stdout.writeAll(buf[0..bytes_read]) catch |err| {
60 warn("Unable to write to stdout: {}\n", .{@errorName(err)});
61 return err;
62 };
63 }
64}
65
66fn unwrapArg(arg: anyerror![]u8) ![]u8 {
67 return arg catch |err| {
68 warn("Unable to parse command line: {}\n", .{err});
69 return err;
70 };
71}
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");