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 {
506506 {
507507 break :dl true;
508508 }
509 if (options.system_libs.len != 0) {
510 // when creating a executable that links to system libraries,
509 const any_dyn_libs: bool = x: {
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,
511522 // we require dynamic linking, but we must not link static libraries
512523 // or object files dynamically!
513524 break :dl (options.output_mode == .Exe);
test/standalone/cat/main.zig+14-39
......@@ -3,37 +3,40 @@ const io = std.io;
33const process = std.process;
44const fs = std.fs;
55const mem = std.mem;
6const warn = std.debug.warn;
7const allocator = std.testing.allocator;
6const warn = std.log.warn;
87
98pub fn main() !void {
10 var args_it = process.args();
11 const exe = try unwrapArg(args_it.next(allocator).?);
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);
14
15 const exe = args[0];
1216 var catted_anything = false;
1317 const stdout_file = io.getStdOut();
1418
1519 const cwd = fs.cwd();
1620
17 while (args_it.next(allocator)) |arg_or_err| {
18 const arg = try unwrapArg(arg_or_err);
21 for (args[1..]) |arg| {
1922 if (mem.eql(u8, arg, "-")) {
2023 catted_anything = true;
21 try cat_file(stdout_file, io.getStdIn());
22 } else if (arg[0] == '-') {
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
2326 return usage(exe);
2427 } else {
2528 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)});
2730 return err;
2831 };
2932 defer file.close();
3033
3134 catted_anything = true;
32 try cat_file(stdout_file, file);
35 try stdout_file.writeFileAll(file, .{});
3336 }
3437 }
3538 if (!catted_anything) {
36 try cat_file(stdout_file, io.getStdIn());
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
3740 }
3841}
3942
......@@ -41,31 +44,3 @@ fn usage(exe: []const u8) !void {
4144 warn("Usage: {} [FILE]...\n", .{exe});
4245 return error.Invalid;
4346}
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 @@
11const Builder = @import("std").build.Builder;
22
33pub fn build(b: *Builder) void {
4 const target = b.standardTargetOptions(.{});
45 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
6 lib.setTarget(target);
57
68 const exe = b.addExecutable("test", null);
9 exe.setTarget(target);
710 exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
811 exe.linkLibrary(lib);
912 exe.linkSystemLibrary("c");