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 {
510510 {
511511 break :dl true;
512512 }
513 if (options.system_libs.len != 0) {
514 // when creating a executable that links to system libraries,
513 const any_dyn_libs: bool = x: {
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,
515526 // we require dynamic linking, but we must not link static libraries
516527 // or object files dynamically!
517528 break :dl (options.output_mode == .Exe);
test/standalone/cat/main.zig+12-32
......@@ -5,41 +5,38 @@ const fs = std.fs;
55const mem = std.mem;
66const warn = std.log.warn;
77
8var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
9const allocator = &general_purpose_allocator.allocator;
10
118pub 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 = try unwrapArg(args_it.next(allocator).?);
16 defer allocator.free(exe);
15 const exe = args[0];
1716 var catted_anything = false;
1817 const stdout_file = io.getStdOut();
1918
2019 const cwd = fs.cwd();
2120
22 while (args_it.next(allocator)) |arg_or_err| {
23 const arg = try unwrapArg(arg_or_err);
24 defer allocator.free(arg);
21 for (args[1..]) |arg| {
2522 if (mem.eql(u8, arg, "-")) {
2623 catted_anything = true;
27 try cat_file(stdout_file, io.getStdIn());
28 } else if (arg[0] == '-') {
24 try stdout_file.writeFileAll(io.getStdIn(), .{});
25 } else if (mem.startsWith(u8, arg, "-")) {
2926 return usage(exe);
3027 } else {
3128 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)});
3330 return err;
3431 };
3532 defer file.close();
3633
3734 catted_anything = true;
38 try cat_file(stdout_file, file);
35 try stdout_file.writeFileAll(file, .{});
3936 }
4037 }
4138 if (!catted_anything) {
42 try cat_file(stdout_file, io.getStdIn());
39 try stdout_file.writeFileAll(io.getStdIn(), .{});
4340 }
4441}
4542
......@@ -47,20 +44,3 @@ fn usage(exe: []const u8) !void {
4744 warn("Usage: {} [FILE]...\n", .{exe});
4845 return error.Invalid;
4946}
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 @@
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");