mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
Compilation: handle system C compiler not found
When linking libc and compiling natively, Zig tries to integrate with the system C compiler. However, this caused Zig to fail when no system C compiler is installed, despite the fact that Zig is perfectly capable of compiling & linking libc without one. This commit makes Zig fall back to using its own ability to provide libc in the case that no C compiler is installed. For glibc, it means sometimes getting the warning "zig cannot build new glibc version abc, providing instead xyz". Ideally, Zig would do some more validation about the system libraries being linked against, and report an error in case it could not provide the exact correct libc version of the system libraries (or that the system libraries themselves conflict with each other), however, I think it is fair to call that a separate enhancement.
This commit is contained in:
parent
aec0e595f2
commit
65bea514ae
@ -508,7 +508,7 @@ pub const ChildProcess = struct {
|
||||
// it, that's the error code returned by the child process.
|
||||
_ = std.os.poll(&fd, 0) catch unreachable;
|
||||
|
||||
// According to eventfd(2) the descriptro is readable if the counter
|
||||
// According to eventfd(2) the descriptor is readable if the counter
|
||||
// has a value greater than 0
|
||||
if ((fd[0].revents & std.os.POLL.IN) != 0) {
|
||||
const err_int = try readIntFd(err_pipe[0]);
|
||||
|
@ -4549,74 +4549,29 @@ fn detectLibCIncludeDirs(
|
||||
getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target);
|
||||
}
|
||||
const libc = try arena.create(LibCInstallation);
|
||||
libc.* = try LibCInstallation.findNative(.{ .allocator = arena, .verbose = true });
|
||||
libc.* = LibCInstallation.findNative(.{ .allocator = arena }) catch |err| switch (err) {
|
||||
error.CCompilerExitCode,
|
||||
error.CCompilerCrashed,
|
||||
error.CCompilerCannotFindHeaders,
|
||||
error.UnableToSpawnCCompiler,
|
||||
=> |e| {
|
||||
// We tried to integrate with the native system C compiler,
|
||||
// however, it is not installed. So we must rely on our bundled
|
||||
// libc files.
|
||||
if (target_util.canBuildLibC(target)) {
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk);
|
||||
}
|
||||
return e;
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
return detectLibCFromLibCInstallation(arena, target, libc);
|
||||
}
|
||||
|
||||
// If not linking system libraries, build and provide our own libc by
|
||||
// default if possible.
|
||||
if (target_util.canBuildLibC(target)) {
|
||||
switch (target.os.tag) {
|
||||
.macos => return if (has_macos_sdk)
|
||||
// For Darwin/macOS, we are all set with getDarwinSDK found earlier.
|
||||
LibCDirs{
|
||||
.libc_include_dir_list = &[0][]u8{},
|
||||
.libc_installation = null,
|
||||
}
|
||||
else
|
||||
getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
|
||||
else => {
|
||||
const generic_name = target_util.libCGenericName(target);
|
||||
// Some architectures are handled by the same set of headers.
|
||||
const arch_name = if (target.abi.isMusl())
|
||||
musl.archName(target.cpu.arch)
|
||||
else if (target.cpu.arch.isThumb())
|
||||
// ARM headers are valid for Thumb too.
|
||||
switch (target.cpu.arch) {
|
||||
.thumb => "arm",
|
||||
.thumbeb => "armeb",
|
||||
else => unreachable,
|
||||
}
|
||||
else
|
||||
@tagName(target.cpu.arch);
|
||||
const os_name = @tagName(target.os.tag);
|
||||
// Musl's headers are ABI-agnostic and so they all have the "musl" ABI name.
|
||||
const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi);
|
||||
const s = std.fs.path.sep_str;
|
||||
const arch_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
|
||||
.{ zig_lib_dir, arch_name, os_name, abi_name },
|
||||
);
|
||||
const generic_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
|
||||
.{ zig_lib_dir, generic_name },
|
||||
);
|
||||
const generic_arch_name = target_util.osArchName(target);
|
||||
const arch_os_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
|
||||
.{ zig_lib_dir, generic_arch_name, os_name },
|
||||
);
|
||||
const generic_os_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
|
||||
.{ zig_lib_dir, os_name },
|
||||
);
|
||||
|
||||
const list = try arena.alloc([]const u8, 4);
|
||||
list[0] = arch_include_dir;
|
||||
list[1] = generic_include_dir;
|
||||
list[2] = arch_os_include_dir;
|
||||
list[3] = generic_os_include_dir;
|
||||
|
||||
return LibCDirs{
|
||||
.libc_include_dir_list = list,
|
||||
.libc_installation = null,
|
||||
};
|
||||
},
|
||||
}
|
||||
return detectLibCFromBuilding(arena, zig_lib_dir, target, has_macos_sdk);
|
||||
}
|
||||
|
||||
// If zig can't build the libc for the target and we are targeting the
|
||||
@ -4675,6 +4630,75 @@ fn detectLibCFromLibCInstallation(arena: Allocator, target: Target, lci: *const
|
||||
};
|
||||
}
|
||||
|
||||
fn detectLibCFromBuilding(
|
||||
arena: Allocator,
|
||||
zig_lib_dir: []const u8,
|
||||
target: std.Target,
|
||||
has_macos_sdk: bool,
|
||||
) !LibCDirs {
|
||||
switch (target.os.tag) {
|
||||
.macos => return if (has_macos_sdk)
|
||||
// For Darwin/macOS, we are all set with getDarwinSDK found earlier.
|
||||
LibCDirs{
|
||||
.libc_include_dir_list = &[0][]u8{},
|
||||
.libc_installation = null,
|
||||
}
|
||||
else
|
||||
getZigShippedLibCIncludeDirsDarwin(arena, zig_lib_dir, target),
|
||||
else => {
|
||||
const generic_name = target_util.libCGenericName(target);
|
||||
// Some architectures are handled by the same set of headers.
|
||||
const arch_name = if (target.abi.isMusl())
|
||||
musl.archName(target.cpu.arch)
|
||||
else if (target.cpu.arch.isThumb())
|
||||
// ARM headers are valid for Thumb too.
|
||||
switch (target.cpu.arch) {
|
||||
.thumb => "arm",
|
||||
.thumbeb => "armeb",
|
||||
else => unreachable,
|
||||
}
|
||||
else
|
||||
@tagName(target.cpu.arch);
|
||||
const os_name = @tagName(target.os.tag);
|
||||
// Musl's headers are ABI-agnostic and so they all have the "musl" ABI name.
|
||||
const abi_name = if (target.abi.isMusl()) "musl" else @tagName(target.abi);
|
||||
const s = std.fs.path.sep_str;
|
||||
const arch_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-{s}",
|
||||
.{ zig_lib_dir, arch_name, os_name, abi_name },
|
||||
);
|
||||
const generic_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}",
|
||||
.{ zig_lib_dir, generic_name },
|
||||
);
|
||||
const generic_arch_name = target_util.osArchName(target);
|
||||
const arch_os_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any",
|
||||
.{ zig_lib_dir, generic_arch_name, os_name },
|
||||
);
|
||||
const generic_os_include_dir = try std.fmt.allocPrint(
|
||||
arena,
|
||||
"{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "any-{s}-any",
|
||||
.{ zig_lib_dir, os_name },
|
||||
);
|
||||
|
||||
const list = try arena.alloc([]const u8, 4);
|
||||
list[0] = arch_include_dir;
|
||||
list[1] = generic_include_dir;
|
||||
list[2] = arch_os_include_dir;
|
||||
list[3] = generic_os_include_dir;
|
||||
|
||||
return LibCDirs{
|
||||
.libc_include_dir_list = list,
|
||||
.libc_installation = null,
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_libc_crt_file(comp: *Compilation, arena: Allocator, basename: []const u8) ![]const u8 {
|
||||
if (comp.wantBuildGLibCFromSource() or
|
||||
comp.wantBuildMuslFromSource() or
|
||||
|
@ -719,17 +719,16 @@ pub fn buildSharedObjects(comp: *Compilation) !void {
|
||||
.lt => continue,
|
||||
.gt => {
|
||||
// TODO Expose via compile error mechanism instead of log.
|
||||
log.err("invalid target glibc version: {}", .{target_version});
|
||||
log.warn("invalid target glibc version: {}", .{target_version});
|
||||
return error.InvalidTargetGLibCVersion;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
} else blk: {
|
||||
const latest_index = metadata.all_versions.len - 1;
|
||||
// TODO Expose via compile error mechanism instead of log.
|
||||
log.err("zig does not yet provide glibc version {}, the max provided version is {}", .{
|
||||
log.warn("zig cannot build new glibc version {}; providing instead {}", .{
|
||||
target_version, metadata.all_versions[latest_index],
|
||||
});
|
||||
return error.InvalidTargetGLibCVersion;
|
||||
break :blk latest_index;
|
||||
};
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user