elf: add incomplete handling of build-obj -fllvm -fno-lld
This commit is contained in:
@@ -1069,10 +1069,11 @@ pub fn flush(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link
|
||||
if (use_lld) {
|
||||
return self.linkWithLLD(comp, prog_node);
|
||||
}
|
||||
switch (self.base.options.output_mode) {
|
||||
.Exe, .Obj => return self.flushModule(comp, prog_node),
|
||||
.Lib => return error.TODOImplementWritingLibFiles,
|
||||
if (self.base.options.output_mode == .Lib and self.isStatic()) {
|
||||
// TODO writing static library files
|
||||
return error.TODOImplementWritingLibFiles;
|
||||
}
|
||||
try self.flushModule(comp, prog_node);
|
||||
}
|
||||
|
||||
pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
|
||||
@@ -1098,21 +1099,44 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
const target = self.base.options.target;
|
||||
const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
break :blk try fs.path.join(arena, &.{ dirname, path });
|
||||
} else {
|
||||
break :blk path;
|
||||
}
|
||||
} else null;
|
||||
|
||||
if (self.base.options.output_mode == .Obj and self.zig_module_index == null) {
|
||||
// TODO this will become -r route I guess. For now, just copy the object file.
|
||||
const the_object_path = blk: {
|
||||
if (self.base.options.objects.len != 0) {
|
||||
break :blk self.base.options.objects[0].path;
|
||||
}
|
||||
|
||||
if (comp.c_object_table.count() != 0)
|
||||
break :blk comp.c_object_table.keys()[0].status.success.object_path;
|
||||
|
||||
if (module_obj_path) |p|
|
||||
break :blk p;
|
||||
|
||||
// TODO I think this is unreachable. Audit this situation when solving the above TODO
|
||||
// regarding eliding redundant object -> object transformations.
|
||||
return error.NoObjectsToLink;
|
||||
};
|
||||
// This can happen when using --enable-cache and using the stage1 backend. In this case
|
||||
// we can skip the file copy.
|
||||
if (!mem.eql(u8, the_object_path, full_out_path)) {
|
||||
try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Here we will parse input positional and library files (if referenced).
|
||||
// This will roughly match in any linker backend we support.
|
||||
var positionals = std.ArrayList(Compilation.LinkObject).init(arena);
|
||||
|
||||
if (self.base.intermediary_basename) |path| {
|
||||
const full_path = blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
break :blk try fs.path.join(arena, &.{ dirname, path });
|
||||
} else {
|
||||
break :blk path;
|
||||
}
|
||||
};
|
||||
try positionals.append(.{ .path = full_path });
|
||||
}
|
||||
if (module_obj_path) |path| try positionals.append(.{ .path = path });
|
||||
|
||||
try positionals.ensureUnusedCapacity(self.base.options.objects.len);
|
||||
positionals.appendSliceAssumeCapacity(self.base.options.objects);
|
||||
|
||||
@@ -17,6 +17,7 @@ pub fn build(b: *Build) void {
|
||||
|
||||
// Exercise linker with LLVM backend
|
||||
elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target }));
|
||||
elf_step.dependOn(testGcSections(b, .{ .target = musl_target }));
|
||||
elf_step.dependOn(testLinkingC(b, .{ .target = musl_target }));
|
||||
elf_step.dependOn(testLinkingCpp(b, .{ .target = musl_target }));
|
||||
elf_step.dependOn(testLinkingZig(b, .{ .target = musl_target }));
|
||||
@@ -38,6 +39,93 @@ fn testEmptyObject(b: *Build, opts: Options) *Step {
|
||||
return test_step;
|
||||
}
|
||||
|
||||
fn testGcSections(b: *Build, opts: Options) *Step {
|
||||
const test_step = addTestStep(b, "gc-sections", opts);
|
||||
|
||||
const obj = addObject(b, opts);
|
||||
addCppSourceBytes(obj,
|
||||
\\#include <stdio.h>
|
||||
\\int two() { return 2; }
|
||||
\\int live_var1 = 1;
|
||||
\\int live_var2 = two();
|
||||
\\int dead_var1 = 3;
|
||||
\\int dead_var2 = 4;
|
||||
\\void live_fn1() {}
|
||||
\\void live_fn2() { live_fn1(); }
|
||||
\\void dead_fn1() {}
|
||||
\\void dead_fn2() { dead_fn1(); }
|
||||
\\int main() {
|
||||
\\ printf("%d %d\n", live_var1, live_var2);
|
||||
\\ live_fn2();
|
||||
\\}
|
||||
);
|
||||
obj.link_function_sections = true;
|
||||
obj.is_linking_libc = true;
|
||||
obj.is_linking_libcpp = true;
|
||||
|
||||
{
|
||||
const exe = addExecutable(b, opts);
|
||||
exe.addObject(obj);
|
||||
exe.link_gc_sections = false;
|
||||
exe.is_linking_libc = true;
|
||||
exe.is_linking_libcpp = true;
|
||||
|
||||
const run = addRunArtifact(exe);
|
||||
run.expectStdOutEqual("1 2\n");
|
||||
test_step.dependOn(&run.step);
|
||||
|
||||
const check = exe.checkObject();
|
||||
check.checkInSymtab();
|
||||
check.checkContains("live_var1");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("live_var2");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("dead_var1");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("dead_var2");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("live_fn1");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("live_fn2");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("dead_fn1");
|
||||
check.checkInSymtab();
|
||||
check.checkContains("dead_fn2");
|
||||
test_step.dependOn(&check.step);
|
||||
}
|
||||
|
||||
// {
|
||||
// const exe = cc(b, opts);
|
||||
// exe.addFileSource(obj_out.file);
|
||||
// exe.addArg("-Wl,-gc-sections");
|
||||
|
||||
// const run = exe.run();
|
||||
// run.expectStdOutEqual("1 2\n");
|
||||
// test_step.dependOn(run.step());
|
||||
|
||||
// const check = exe.check();
|
||||
// check.checkInSymtab();
|
||||
// check.checkContains("live_var1");
|
||||
// check.checkInSymtab();
|
||||
// check.checkContains("live_var2");
|
||||
// check.checkInSymtab();
|
||||
// check.checkNotPresent("dead_var1");
|
||||
// check.checkInSymtab();
|
||||
// check.checkNotPresent("dead_var2");
|
||||
// check.checkInSymtab();
|
||||
// check.checkContains("live_fn1");
|
||||
// check.checkInSymtab();
|
||||
// check.checkContains("live_fn2");
|
||||
// check.checkInSymtab();
|
||||
// check.checkNotPresent("dead_fn1");
|
||||
// check.checkInSymtab();
|
||||
// check.checkNotPresent("dead_fn2");
|
||||
// test_step.dependOn(&check.step);
|
||||
// }
|
||||
|
||||
return test_step;
|
||||
}
|
||||
|
||||
fn testLinkingC(b: *Build, opts: Options) *Step {
|
||||
const test_step = addTestStep(b, "linking-c", opts);
|
||||
|
||||
@@ -182,6 +270,16 @@ fn addExecutable(b: *Build, opts: Options) *Compile {
|
||||
});
|
||||
}
|
||||
|
||||
fn addObject(b: *Build, opts: Options) *Compile {
|
||||
return b.addObject(.{
|
||||
.name = "a.o",
|
||||
.target = opts.target,
|
||||
.optimize = opts.optimize,
|
||||
.use_llvm = opts.use_llvm,
|
||||
.use_lld = false,
|
||||
});
|
||||
}
|
||||
|
||||
fn addRunArtifact(comp: *Compile) *Run {
|
||||
const b = comp.step.owner;
|
||||
const run = b.addRunArtifact(comp);
|
||||
|
||||
Reference in New Issue
Block a user