mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
std.zig.system.NativeTargetInfo: look for a shebang line in /usr/bin/env, if any
This commit is contained in:
parent
4055e6055b
commit
b97ae88898
@ -237,7 +237,7 @@ pub fn detect(allocator: Allocator, cross_target: CrossTarget) DetectError!Nativ
|
||||
|
||||
/// First we attempt to use the executable's own binary. If it is dynamically
|
||||
/// linked, then it should answer both the C ABI question and the dynamic linker question.
|
||||
/// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then
|
||||
/// If it is statically linked, then we try /usr/bin/env (or the file it references in shebang). If that does not provide the answer, then
|
||||
/// we fall back to the defaults.
|
||||
/// TODO Remove the Allocator requirement from this function.
|
||||
fn detectAbiAndDynamicLinker(
|
||||
@ -355,37 +355,77 @@ fn detectAbiAndDynamicLinker(
|
||||
return result;
|
||||
}
|
||||
|
||||
const env_file = std.fs.openFileAbsoluteZ("/usr/bin/env", .{}) catch |err| switch (err) {
|
||||
error.NoSpaceLeft => unreachable,
|
||||
error.NameTooLong => unreachable,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.SharingViolation => unreachable,
|
||||
error.InvalidUtf8 => unreachable,
|
||||
error.BadPathName => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.FileLocksNotSupported => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.FileBusy => unreachable, // opened without write permissions
|
||||
const elf_file = blk: {
|
||||
// This block looks for a shebang line in /usr/bin/env,
|
||||
// if it finds one, then instead of using /usr/bin/env as the ELF file to examine, it uses the file it references instead,
|
||||
// doing the same logic recursively in case it finds another shebang line.
|
||||
|
||||
error.IsDir,
|
||||
error.NotDir,
|
||||
error.InvalidHandle,
|
||||
error.AccessDenied,
|
||||
error.NoDevice,
|
||||
error.FileNotFound,
|
||||
error.FileTooBig,
|
||||
error.Unexpected,
|
||||
=> return defaultAbiAndDynamicLinker(cpu, os, cross_target),
|
||||
// Since /usr/bin/env is hard-coded into the shebang line of many portable scripts, it's a
|
||||
// reasonably reliable path to start with.
|
||||
var file_name: []const u8 = "/usr/bin/env";
|
||||
// #! (2) + 255 (max length of shebang line since Linux 5.1) + \n (1)
|
||||
var buffer: [258]u8 = undefined;
|
||||
while (true) {
|
||||
const file = std.fs.openFileAbsolute(file_name, .{}) catch |err| switch (err) {
|
||||
error.NoSpaceLeft => unreachable,
|
||||
error.NameTooLong => unreachable,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.SharingViolation => unreachable,
|
||||
error.InvalidUtf8 => unreachable,
|
||||
error.BadPathName => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.FileLocksNotSupported => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.FileBusy => unreachable, // opened without write permissions
|
||||
|
||||
else => |e| return e,
|
||||
error.IsDir,
|
||||
error.NotDir,
|
||||
error.InvalidHandle,
|
||||
error.AccessDenied,
|
||||
error.NoDevice,
|
||||
error.FileNotFound,
|
||||
error.FileTooBig,
|
||||
error.Unexpected,
|
||||
=> |e| {
|
||||
std.log.warn("Encoutered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)});
|
||||
return defaultAbiAndDynamicLinker(cpu, os, cross_target);
|
||||
},
|
||||
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const line = file.reader().readUntilDelimiter(&buffer, '\n') catch |err| switch (err) {
|
||||
error.IsDir => unreachable, // Handled before
|
||||
error.AccessDenied => unreachable,
|
||||
error.WouldBlock => unreachable, // Did not request blocking mode
|
||||
error.OperationAborted => unreachable, // Windows-only
|
||||
error.BrokenPipe => unreachable,
|
||||
error.ConnectionResetByPeer => unreachable,
|
||||
error.ConnectionTimedOut => unreachable,
|
||||
error.InputOutput => unreachable,
|
||||
error.Unexpected => unreachable,
|
||||
|
||||
error.StreamTooLong,
|
||||
error.EndOfStream,
|
||||
error.NotOpenForReading,
|
||||
=> break :blk file,
|
||||
|
||||
else => |e| {
|
||||
file.close();
|
||||
return e;
|
||||
},
|
||||
};
|
||||
if (!mem.startsWith(u8, line, "#!")) break :blk file;
|
||||
var it = std.mem.tokenize(u8, line[2..], " ");
|
||||
file.close();
|
||||
file_name = it.next() orelse return defaultAbiAndDynamicLinker(cpu, os, cross_target);
|
||||
}
|
||||
};
|
||||
defer env_file.close();
|
||||
defer elf_file.close();
|
||||
|
||||
// If Zig is statically linked, such as via distributed binary static builds, the above
|
||||
// trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
|
||||
// Since that path is hard-coded into the shebang line of many portable scripts, it's a
|
||||
// reasonably reliable path to check for.
|
||||
return abiAndDynamicLinkerFromFile(env_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
|
||||
// trick (block self_exe) won't work. The next thing we fall back to is the same thing, but for elf_file.
|
||||
return abiAndDynamicLinkerFromFile(elf_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
|
||||
error.FileSystem,
|
||||
error.SystemResources,
|
||||
error.SymLinkLoop,
|
||||
@ -403,7 +443,10 @@ fn detectAbiAndDynamicLinker(
|
||||
error.UnexpectedEndOfFile,
|
||||
error.NameTooLong,
|
||||
// Finally, we fall back on the standard path.
|
||||
=> defaultAbiAndDynamicLinker(cpu, os, cross_target),
|
||||
=> |e| {
|
||||
std.log.warn("Encoutered error: {s}, falling back to default ABI and dynamic linker.\n", .{@errorName(e)});
|
||||
return defaultAbiAndDynamicLinker(cpu, os, cross_target);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user