Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make zig cc pass -l/-L like Clang/GCC for ELF #19818

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 26 additions & 7 deletions lib/std/Build/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ dwarf_format: ?std.dwarf.Format,

c_macros: std.ArrayListUnmanaged([]const u8),
include_dirs: std.ArrayListUnmanaged(IncludeDir),
lib_paths: std.ArrayListUnmanaged(LazyPath),
lib_paths: std.ArrayListUnmanaged(LibraryPath),
rpaths: std.ArrayListUnmanaged(RPath),
frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions),
link_objects: std.ArrayListUnmanaged(LinkObject),
Expand All @@ -40,6 +40,11 @@ link_libcpp: ?bool,
/// Symbols to be exported when compiling to WebAssembly.
export_symbol_names: []const []const u8 = &.{},

pub const LibraryPath = union(enum) {
lazy_path: LazyPath,
special: []const u8,
};

pub const RPath = union(enum) {
lazy_path: LazyPath,
special: []const u8,
Expand Down Expand Up @@ -260,7 +265,10 @@ pub fn addImport(m: *Module, name: []const u8, module: *Module) void {
/// dependencies on `m`'s `depending_steps`.
fn addShallowDependencies(m: *Module, dependee: *Module) void {
if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path);
for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path);
for (dependee.lib_paths.items) |lib_path| switch (lib_path) {
.lazy_path => |lp| addLazyPathDependencies(m, dependee, lp),
.special => {},
};
for (dependee.rpaths.items) |rpath| switch (rpath) {
.lazy_path => |lp| addLazyPathDependencies(m, dependee, lp),
.special => {},
Expand Down Expand Up @@ -577,10 +585,15 @@ pub fn addFrameworkPath(m: *Module, directory_path: LazyPath) void {

pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.lib_paths.append(b.allocator, directory_path.dupe(b)) catch @panic("OOM");
m.lib_paths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}

pub fn addLibraryPathSpecial(m: *Module, bytes: []const u8) void {
const b = m.owner;
m.lib_paths.append(b.allocator, .{ .special = b.dupe(bytes) }) catch @panic("OOM");
}

pub fn addRPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.rpaths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM");
Expand Down Expand Up @@ -698,10 +711,16 @@ pub fn appendZigProcessFlags(
try zig_args.appendSlice(m.c_macros.items);

try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
for (m.lib_paths.items) |lib_path| {
zig_args.appendAssumeCapacity("-L");
zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
}
for (m.lib_paths.items) |lib_path| switch (lib_path) {
.lazy_path => |lp| {
zig_args.appendAssumeCapacity("-L");
zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step));
},
.special => |bytes| {
zig_args.appendAssumeCapacity("-L");
zig_args.appendAssumeCapacity(bytes);
},
};

try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
for (m.rpaths.items) |rpath| switch (rpath) {
Expand Down
6 changes: 4 additions & 2 deletions lib/std/Build/Step.zig
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ pub fn addError(step: *Step, comptime fmt: []const u8, args: anytype) error{OutO
/// is the zig compiler - the same version that compiled the build runner.
pub fn evalZigProcess(
s: *Step,
opt_cwd: ?[]const u8,
argv: []const []const u8,
prog_node: std.Progress.Node,
) !?[]const u8 {
Expand All @@ -310,8 +311,8 @@ pub fn evalZigProcess(
const arena = b.allocator;
const gpa = arena;

try handleChildProcUnsupported(s, null, argv);
try handleVerbose(s.owner, null, argv);
try handleChildProcUnsupported(s, opt_cwd, argv);
try handleVerbose(s.owner, opt_cwd, argv);

var child = std.process.Child.init(argv, arena);
child.env_map = &b.graph.env_map;
Expand All @@ -320,6 +321,7 @@ pub fn evalZigProcess(
child.stderr_behavior = .Pipe;
child.request_resource_usage_statistics = true;
child.progress_node = prog_node;
child.cwd = opt_cwd;

child.spawn() catch |err| return s.fail("unable to spawn {s}: {s}", .{
argv[0], @errorName(err),
Expand Down
27 changes: 26 additions & 1 deletion lib/std/Build/Step/Compile.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const builtin = @import("builtin");
const std = @import("std");
const Build = std.Build;
const mem = std.mem;
const fs = std.fs;
const assert = std.debug.assert;
Expand Down Expand Up @@ -184,6 +185,7 @@ stack_size: ?u64 = null,
want_lto: ?bool = null,
use_llvm: ?bool,
use_lld: ?bool,
omit_soname: ?bool,

/// This is an advanced setting that can change the intent of this Compile step.
/// If this value is non-null, it means that this Compile step exists to
Expand Down Expand Up @@ -211,6 +213,9 @@ is_linking_libc: bool = false,
/// Computed during make().
is_linking_libcpp: bool = false,

/// Use `setCwd` to set the initial current working directory
cwd: ?Build.LazyPath = null,

pub const ExpectedCompileErrors = union(enum) {
contains: []const u8,
exact: []const []const u8,
Expand Down Expand Up @@ -239,6 +244,7 @@ pub const Options = struct {
test_runner: ?LazyPath = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
omit_soname: ?bool = null,
zig_lib_dir: ?LazyPath = null,
/// Embed a `.manifest` file in the compilation if the object format supports it.
/// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
Expand Down Expand Up @@ -396,6 +402,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {

.use_llvm = options.use_llvm,
.use_lld = options.use_lld,
.omit_soname = options.omit_soname,
};

compile.root_module.init(owner, options.root_module, compile);
Expand Down Expand Up @@ -904,10 +911,18 @@ pub fn addLibraryPath(compile: *Compile, directory_path: LazyPath) void {
compile.root_module.addLibraryPath(directory_path);
}

pub fn addLibraryPathSpecial(compile: *Compile, bytes: []const u8) void {
compile.root_module.addLibraryPathSpecial(bytes);
}

pub fn addRPath(compile: *Compile, directory_path: LazyPath) void {
compile.root_module.addRPath(directory_path);
}

pub fn addRPathSpecial(compile: *Compile, bytes: []const u8) void {
compile.root_module.addRPathSpecial(bytes);
}

pub fn addSystemFrameworkPath(compile: *Compile, directory_path: LazyPath) void {
compile.root_module.addSystemFrameworkPath(directory_path);
}
Expand Down Expand Up @@ -1012,6 +1027,10 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
try addFlag(&zig_args, "llvm", compile.use_llvm);
try addFlag(&zig_args, "lld", compile.use_lld);

if (compile.omit_soname orelse false) {
try zig_args.append("-fno-soname");
}

if (compile.root_module.resolved_target.?.query.ofmt) |ofmt| {
try zig_args.append(try std.fmt.allocPrint(arena, "-ofmt={s}", .{@tagName(ofmt)}));
}
Expand Down Expand Up @@ -1718,7 +1737,8 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
try zig_args.append(resolved_args_file);
}

const maybe_output_bin_path = step.evalZigProcess(zig_args.items, prog_node) catch |err| switch (err) {
const cwd: ?[]const u8 = if (compile.cwd) |lazy_cwd| lazy_cwd.getPath(b) else null;
const maybe_output_bin_path = step.evalZigProcess(cwd, zig_args.items, prog_node) catch |err| switch (err) {
error.NeedCompileErrorCheck => {
assert(compile.expect_errors != null);
try checkCompileErrors(compile);
Expand Down Expand Up @@ -1961,3 +1981,8 @@ fn moduleNeedsCliArg(mod: *const Module) bool {
else => continue,
} else false;
}

pub fn setCwd(self: *Compile, cwd: Build.LazyPath) void {
cwd.addStepDependencies(&self.step);
self.cwd = cwd;
}
2 changes: 1 addition & 1 deletion lib/std/Build/Step/ObjCopy.zig
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {
try argv.appendSlice(&.{ full_src_path, full_dest_path });

try argv.append("--listen=-");
_ = try step.evalZigProcess(argv.items, prog_node);
_ = try step.evalZigProcess(null, argv.items, prog_node);

objcopy.output_file.path = full_dest_path;
if (objcopy.output_file_debug) |*file| file.path = full_dest_path_debug;
Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build/Step/TranslateC.zig
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn make(step: *Step, prog_node: std.Progress.Node) !void {

try argv_list.append(translate_c.source.getPath2(b, step));

const output_path = try step.evalZigProcess(argv_list.items, prog_node);
const output_path = try step.evalZigProcess(null, argv_list.items, prog_node);

translate_c.out_basename = fs.path.basename(output_path.?);
const output_dir = fs.path.dirname(output_path.?).?;
Expand Down
22 changes: 18 additions & 4 deletions src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1584,10 +1584,17 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
}

if (obj.loption) {
assert(obj.path[0] == ':');
try argv.append("-l");
if (obj.path[0] == ':') {
try argv.append(obj.path);
} else {
const stem = fs.path.stem(obj.path);
assert(mem.startsWith(u8, stem, "lib"));
try argv.append(stem[3..]);
}
} else {
try argv.append(obj.path);
}
try argv.append(obj.path);
}
if (whole_archive) {
try argv.append("-no-whole-archive");
Expand Down Expand Up @@ -2591,10 +2598,17 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: std.Progress.Node) !void
}

if (obj.loption) {
assert(obj.path[0] == ':');
try argv.append("-l");
if (obj.path[0] == ':') {
try argv.append(obj.path);
} else {
const stem = fs.path.stem(obj.path);
assert(mem.startsWith(u8, stem, "lib"));
try argv.append(stem[3..]);
}
} else {
try argv.append(obj.path);
}
try argv.append(obj.path);
}
if (whole_archive) {
try argv.append("-no-whole-archive");
Expand Down
80 changes: 52 additions & 28 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3806,14 +3806,20 @@ fn createModule(
const path = try arena.dupe(u8, test_path.items);
switch (info.preferred_mode) {
.static => try create_module.link_objects.append(arena, .{ .path = path }),
.dynamic => try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.dynamic => if (info.needed or target.isDarwin())
try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.path = path,
},
})
else
try create_module.link_objects.append(arena, .{
.path = path,
},
}),
.loption = true,
}),
}
continue :syslib;
}
Expand All @@ -3840,14 +3846,20 @@ fn createModule(
const path = try arena.dupe(u8, test_path.items);
switch (info.fallbackMode()) {
.static => try create_module.link_objects.append(arena, .{ .path = path }),
.dynamic => try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.dynamic => if (info.needed or target.isDarwin())
try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.path = path,
},
})
else
try create_module.link_objects.append(arena, .{
.path = path,
},
}),
.loption = true,
}),
}
continue :syslib;
}
Expand All @@ -3874,14 +3886,20 @@ fn createModule(
const path = try arena.dupe(u8, test_path.items);
switch (info.preferred_mode) {
.static => try create_module.link_objects.append(arena, .{ .path = path }),
.dynamic => try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.dynamic => if (info.needed or target.isDarwin())
try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.path = path,
},
})
else
try create_module.link_objects.append(arena, .{
.path = path,
},
}),
.loption = true,
}),
}
continue :syslib;
}
Expand All @@ -3898,14 +3916,20 @@ fn createModule(
const path = try arena.dupe(u8, test_path.items);
switch (info.fallbackMode()) {
.static => try create_module.link_objects.append(arena, .{ .path = path }),
.dynamic => try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.dynamic => if (info.needed or target.isDarwin())
try create_module.resolved_system_libs.append(arena, .{
.name = lib_name,
.lib = .{
.needed = info.needed,
.weak = info.weak,
.path = path,
},
})
else
try create_module.link_objects.append(arena, .{
.path = path,
},
}),
.loption = true,
}),
}
continue :syslib;
}
Expand Down