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.
This commit is contained in:
Andrew Kelley
2020-11-30 20:18:40 -07:00
parent 57ac835a03
commit a9b7d8fa07
3 changed files with 30 additions and 41 deletions

View File

@@ -506,8 +506,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
{
break :dl true;
}
if (options.system_libs.len != 0) {
// when creating a executable that links to system libraries,
const any_dyn_libs: bool = x: {
if (options.system_libs.len != 0)
break :x true;
for (options.link_objects) |obj| {
switch (classifyFileExt(obj)) {
.shared_library => break :x true,
else => continue,
}
}
break :x false;
};
if (any_dyn_libs) {
// When creating a executable that links to system libraries,
// we require dynamic linking, but we must not link static libraries
// or object files dynamically!
break :dl (options.output_mode == .Exe);

View File

@@ -3,37 +3,40 @@ const io = std.io;
const process = std.process;
const fs = std.fs;
const mem = std.mem;
const warn = std.debug.warn;
const allocator = std.testing.allocator;
const warn = std.log.warn;
pub fn main() !void {
var args_it = process.args();
const exe = try unwrapArg(args_it.next(allocator).?);
var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena_instance.deinit();
const arena = &arena_instance.allocator;
const args = try process.argsAlloc(arena);
const exe = args[0];
var catted_anything = false;
const stdout_file = io.getStdOut();
const cwd = fs.cwd();
while (args_it.next(allocator)) |arg_or_err| {
const arg = try unwrapArg(arg_or_err);
for (args[1..]) |arg| {
if (mem.eql(u8, arg, "-")) {
catted_anything = true;
try cat_file(stdout_file, io.getStdIn());
} else if (arg[0] == '-') {
try stdout_file.writeFileAll(io.getStdIn(), .{});
} else if (mem.startsWith(u8, arg, "-")) {
return usage(exe);
} else {
const file = cwd.openFile(arg, .{}) catch |err| {
warn("Unable to open file: {}\n", .{@errorName(err)});
warn("Unable to open file: {s}\n", .{@errorName(err)});
return err;
};
defer file.close();
catted_anything = true;
try cat_file(stdout_file, file);
try stdout_file.writeFileAll(file, .{});
}
}
if (!catted_anything) {
try cat_file(stdout_file, io.getStdIn());
try stdout_file.writeFileAll(io.getStdIn(), .{});
}
}
@@ -41,31 +44,3 @@ fn usage(exe: []const u8) !void {
warn("Usage: {} [FILE]...\n", .{exe});
return error.Invalid;
}
// TODO use copy_file_range
fn cat_file(stdout: fs.File, file: fs.File) !void {
var buf: [1024 * 4]u8 = undefined;
while (true) {
const bytes_read = file.read(buf[0..]) catch |err| {
warn("Unable to read from stream: {}\n", .{@errorName(err)});
return err;
};
if (bytes_read == 0) {
break;
}
stdout.writeAll(buf[0..bytes_read]) catch |err| {
warn("Unable to write to stdout: {}\n", .{@errorName(err)});
return err;
};
}
}
fn unwrapArg(arg: anyerror![]u8) ![]u8 {
return arg catch |err| {
warn("Unable to parse command line: {}\n", .{err});
return err;
};
}

View File

@@ -1,9 +1,12 @@
const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const target = b.standardTargetOptions(.{});
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
lib.setTarget(target);
const exe = b.addExecutable("test", null);
exe.setTarget(target);
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
exe.linkLibrary(lib);
exe.linkSystemLibrary("c");