Skip to content

Commit e8a8492

Browse files
authored
Merge pull request #4478 from ziglang/self-host-libc-detection
self-hosted libc and dynamic linker detection
2 parents 35f0cb0 + 99520c4 commit e8a8492

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1959
-1692
lines changed

CMakeLists.txt

+58-39
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ find_package(Threads)
434434
# CMake doesn't let us create an empty executable, so we hang on to this one separately.
435435
set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp")
436436

437-
# This is our shim which will be replaced by libuserland written in Zig.
438-
set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp")
437+
# This is our shim which will be replaced by libstage2 written in Zig.
438+
set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp")
439439

440440
if(ZIG_ENABLE_MEM_PROFILE)
441441
set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp")
@@ -457,7 +457,6 @@ set(ZIG_SOURCES
457457
"${CMAKE_SOURCE_DIR}/src/heap.cpp"
458458
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
459459
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
460-
"${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
461460
"${CMAKE_SOURCE_DIR}/src/link.cpp"
462461
"${CMAKE_SOURCE_DIR}/src/mem.cpp"
463462
"${CMAKE_SOURCE_DIR}/src/os.cpp"
@@ -566,12 +565,12 @@ set_target_properties(opt_c_util PROPERTIES
566565
COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
567566
)
568567

569-
add_library(compiler STATIC ${ZIG_SOURCES})
570-
set_target_properties(compiler PROPERTIES
568+
add_library(zigcompiler STATIC ${ZIG_SOURCES})
569+
set_target_properties(zigcompiler PROPERTIES
571570
COMPILE_FLAGS ${EXE_CFLAGS}
572571
LINK_FLAGS ${EXE_LDFLAGS}
573572
)
574-
target_link_libraries(compiler LINK_PUBLIC
573+
target_link_libraries(zigcompiler LINK_PUBLIC
575574
zig_cpp
576575
opt_c_util
577576
${SOFTFLOAT_LIBRARIES}
@@ -581,56 +580,58 @@ target_link_libraries(compiler LINK_PUBLIC
581580
${CMAKE_THREAD_LIBS_INIT}
582581
)
583582
if(NOT MSVC)
584-
target_link_libraries(compiler LINK_PUBLIC ${LIBXML2})
583+
target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2})
585584
endif()
586585

587586
if(ZIG_DIA_GUIDS_LIB)
588-
target_link_libraries(compiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
587+
target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
589588
endif()
590589

591590
if(MSVC OR MINGW)
592-
target_link_libraries(compiler LINK_PUBLIC version)
591+
target_link_libraries(zigcompiler LINK_PUBLIC version)
593592
endif()
594593

595594
add_executable(zig0 "${ZIG_MAIN_SRC}" "${ZIG0_SHIM_SRC}")
596595
set_target_properties(zig0 PROPERTIES
597596
COMPILE_FLAGS ${EXE_CFLAGS}
598597
LINK_FLAGS ${EXE_LDFLAGS}
599598
)
600-
target_link_libraries(zig0 compiler)
599+
target_link_libraries(zig0 zigcompiler)
601600

602601
if(MSVC)
603-
set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib")
602+
set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/zigstage2.lib")
604603
else()
605-
set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a")
604+
set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libzigstage2.a")
606605
endif()
607606
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
608-
set(LIBUSERLAND_RELEASE_MODE "false")
607+
set(LIBSTAGE2_RELEASE_ARG "")
609608
else()
610-
set(LIBUSERLAND_RELEASE_MODE "true")
609+
set(LIBSTAGE2_RELEASE_ARG --release-fast --strip)
610+
endif()
611+
if(WIN32)
612+
set(LIBSTAGE2_WINDOWS_ARGS "-lntdll")
613+
else()
614+
set(LIBSTAGE2_WINDOWS_ARGS "")
611615
endif()
612616

613-
set(BUILD_LIBUSERLAND_ARGS "build"
617+
set(BUILD_LIBSTAGE2_ARGS "build-lib"
618+
"src-self-hosted/stage2.zig"
619+
--name zigstage2
614620
--override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
615-
"-Doutput-dir=${CMAKE_BINARY_DIR}"
616-
"-Drelease=${LIBUSERLAND_RELEASE_MODE}"
617-
"-Dlib-files-only"
618-
--prefix "${CMAKE_INSTALL_PREFIX}"
619-
libuserland
621+
--cache on
622+
--output-dir "${CMAKE_BINARY_DIR}"
623+
${LIBSTAGE2_RELEASE_ARG}
624+
--disable-gen-h
625+
--bundle-compiler-rt
626+
-fPIC
627+
-lc
628+
${LIBSTAGE2_WINDOWS_ARGS}
620629
)
621630

622-
# When using Visual Studio build system generator we default to libuserland install.
623-
if(MSVC)
624-
set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL "Disable copying lib/ files to install prefix")
625-
if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
626-
set(BUILD_LIBUSERLAND_ARGS ${BUILD_LIBUSERLAND_ARGS} install)
627-
endif()
628-
endif()
629-
630-
add_custom_target(zig_build_libuserland ALL
631-
COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS}
631+
add_custom_target(zig_build_libstage2 ALL
632+
COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS}
632633
DEPENDS zig0
633-
BYPRODUCTS "${LIBUSERLAND}"
634+
BYPRODUCTS "${LIBSTAGE2}"
634635
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
635636
)
636637
add_executable(zig "${ZIG_MAIN_SRC}")
@@ -639,22 +640,40 @@ set_target_properties(zig PROPERTIES
639640
COMPILE_FLAGS ${EXE_CFLAGS}
640641
LINK_FLAGS ${EXE_LDFLAGS}
641642
)
642-
target_link_libraries(zig compiler "${LIBUSERLAND}")
643+
target_link_libraries(zig zigcompiler "${LIBSTAGE2}")
643644
if(MSVC)
644645
target_link_libraries(zig ntdll.lib)
645646
elseif(MINGW)
646647
target_link_libraries(zig ntdll)
647648
endif()
648-
add_dependencies(zig zig_build_libuserland)
649+
add_dependencies(zig zig_build_libstage2)
649650

650651
install(TARGETS zig DESTINATION bin)
651652

652-
# CODE has no effect with Visual Studio build system generator.
653-
if(NOT MSVC)
654-
get_target_property(zig0_BINARY_DIR zig0 BINARY_DIR)
655-
install(CODE "set(zig0_EXE \"${zig0_BINARY_DIR}/zig0\")")
656-
install(CODE "set(INSTALL_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\" install)")
657-
install(CODE "set(BUILD_LIBUSERLAND_ARGS \"${BUILD_LIBUSERLAND_ARGS}\")")
653+
set(ZIG_INSTALL_ARGS "build"
654+
--override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
655+
"-Dlib-files-only"
656+
--prefix "${CMAKE_INSTALL_PREFIX}"
657+
install
658+
)
659+
660+
# CODE has no effect with Visual Studio build system generator, therefore
661+
# when using Visual Studio build system generator we resort to running
662+
# `zig build install` during the build phase.
663+
if(MSVC)
664+
set(ZIG_SKIP_INSTALL_LIB_FILES off CACHE BOOL
665+
"Windows-only: Disable copying lib/ files to install prefix during the build phase")
666+
if(NOT ZIG_SKIP_INSTALL_LIB_FILES)
667+
add_custom_target(zig_install_lib_files ALL
668+
COMMAND zig ${ZIG_INSTALL_ARGS}
669+
DEPENDS zig
670+
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
671+
)
672+
endif()
673+
else()
674+
get_target_property(zig_BINARY_DIR zig BINARY_DIR)
675+
install(CODE "set(zig_EXE \"${zig_BINARY_DIR}/zig\")")
676+
install(CODE "set(ZIG_INSTALL_ARGS \"${ZIG_INSTALL_ARGS}\")")
658677
install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")")
659678
install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/cmake/install.cmake)
660679
endif()

build.zig

+1-28
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ pub fn build(b: *Builder) !void {
6464
try configureStage2(b, test_stage2, ctx);
6565
try configureStage2(b, exe, ctx);
6666

67-
addLibUserlandStep(b, mode);
68-
6967
const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
7068
const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
7169
const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release;
@@ -175,7 +173,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
175173
}
176174

177175
fn fileExists(filename: []const u8) !bool {
178-
fs.File.access(filename) catch |err| switch (err) {
176+
fs.cwd().access(filename, .{}) catch |err| switch (err) {
179177
error.FileNotFound => return false,
180178
else => return err,
181179
};
@@ -366,28 +364,3 @@ const Context = struct {
366364
dia_guids_lib: []const u8,
367365
llvm: LibraryDep,
368366
};
369-
370-
fn addLibUserlandStep(b: *Builder, mode: builtin.Mode) void {
371-
const artifact = b.addStaticLibrary("userland", "src-self-hosted/stage1.zig");
372-
artifact.disable_gen_h = true;
373-
artifact.bundle_compiler_rt = true;
374-
artifact.setTarget(builtin.arch, builtin.os, builtin.abi);
375-
artifact.setBuildMode(mode);
376-
artifact.force_pic = true;
377-
if (mode != .Debug) {
378-
artifact.strip = true;
379-
}
380-
artifact.linkSystemLibrary("c");
381-
if (builtin.os == .windows) {
382-
artifact.linkSystemLibrary("ntdll");
383-
}
384-
const libuserland_step = b.step("libuserland", "Build the userland compiler library for use in stage1");
385-
libuserland_step.dependOn(&artifact.step);
386-
387-
const output_dir = b.option(
388-
[]const u8,
389-
"output-dir",
390-
"For libuserland step, where to put the output",
391-
) orelse return;
392-
artifact.setOutputDir(output_dir);
393-
}

cmake/install.cmake

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
message("-- Installing: ${CMAKE_INSTALL_PREFIX}/lib")
22

3-
if(NOT EXISTS ${zig0_EXE})
3+
if(NOT EXISTS ${zig_EXE})
44
message("::")
55
message(":: ERROR: Executable not found")
66
message(":: (execute_process)")
77
message("::")
8-
message(":: executable: ${zig0_EXE}")
8+
message(":: executable: ${zig_EXE}")
99
message("::")
1010
message(FATAL_ERROR)
1111
endif()
1212

13-
execute_process(COMMAND ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS}
13+
execute_process(COMMAND ${zig_EXE} ${ZIG_INSTALL_ARGS}
1414
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
1515
RESULT_VARIABLE _result
1616
)
@@ -19,11 +19,11 @@ if(_result)
1919
message(":: ERROR: ${_result}")
2020
message(":: (execute_process)")
2121

22-
string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${INSTALL_LIBUSERLAND_ARGS}")
22+
string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}")
2323
message("::")
24-
message(":: argv: ${zig0_EXE} ${s_INSTALL_LIBUSERLAND_ARGS} install")
24+
message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}")
2525

26-
set(_args ${zig0_EXE} ${INSTALL_LIBUSERLAND_ARGS})
26+
set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS})
2727
list(LENGTH _args _len)
2828
math(EXPR _len "${_len} - 1")
2929
message("::")

lib/std/c.zig

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
9696
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_uint, options: c_uint) c_int;
9797
pub extern "c" fn fork() c_int;
9898
pub extern "c" fn access(path: [*:0]const u8, mode: c_uint) c_int;
99+
pub extern "c" fn faccessat(dirfd: fd_t, path: [*:0]const u8, mode: c_uint, flags: c_uint) c_int;
99100
pub extern "c" fn pipe(fds: *[2]fd_t) c_int;
100101
pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
101102
pub extern "c" fn mkdir(path: [*:0]const u8, mode: c_uint) c_int;

lib/std/child_process.zig

+39-15
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ pub const ChildProcess = struct {
4848
cwd: ?[]const u8,
4949

5050
err_pipe: if (builtin.os == .windows) void else [2]os.fd_t,
51-
llnode: if (builtin.os == .windows) void else TailQueue(*ChildProcess).Node,
51+
52+
expand_arg0: Arg0Expand,
53+
54+
pub const Arg0Expand = os.Arg0Expand;
5255

5356
pub const SpawnError = error{
5457
OutOfMemory,
@@ -90,7 +93,6 @@ pub const ChildProcess = struct {
9093
.handle = undefined,
9194
.thread_handle = undefined,
9295
.err_pipe = undefined,
93-
.llnode = undefined,
9496
.term = null,
9597
.env_map = null,
9698
.cwd = null,
@@ -102,6 +104,7 @@ pub const ChildProcess = struct {
102104
.stdin_behavior = StdIo.Inherit,
103105
.stdout_behavior = StdIo.Inherit,
104106
.stderr_behavior = StdIo.Inherit,
107+
.expand_arg0 = .no_expand,
105108
};
106109
errdefer allocator.destroy(child);
107110
return child;
@@ -174,34 +177,56 @@ pub const ChildProcess = struct {
174177

175178
/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
176179
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
180+
/// TODO deprecate in favor of exec2
177181
pub fn exec(
178182
allocator: *mem.Allocator,
179183
argv: []const []const u8,
180184
cwd: ?[]const u8,
181185
env_map: ?*const BufMap,
182-
max_output_size: usize,
186+
max_output_bytes: usize,
183187
) !ExecResult {
184-
const child = try ChildProcess.init(argv, allocator);
188+
return exec2(.{
189+
.allocator = allocator,
190+
.argv = argv,
191+
.cwd = cwd,
192+
.env_map = env_map,
193+
.max_output_bytes = max_output_bytes,
194+
});
195+
}
196+
197+
/// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
198+
/// If it succeeds, the caller owns result.stdout and result.stderr memory.
199+
/// TODO rename to exec
200+
pub fn exec2(args: struct {
201+
allocator: *mem.Allocator,
202+
argv: []const []const u8,
203+
cwd: ?[]const u8 = null,
204+
env_map: ?*const BufMap = null,
205+
max_output_bytes: usize = 50 * 1024,
206+
expand_arg0: Arg0Expand = .no_expand,
207+
}) !ExecResult {
208+
const child = try ChildProcess.init(args.argv, args.allocator);
185209
defer child.deinit();
186210

187-
child.stdin_behavior = ChildProcess.StdIo.Ignore;
188-
child.stdout_behavior = ChildProcess.StdIo.Pipe;
189-
child.stderr_behavior = ChildProcess.StdIo.Pipe;
190-
child.cwd = cwd;
191-
child.env_map = env_map;
211+
child.stdin_behavior = .Ignore;
212+
child.stdout_behavior = .Pipe;
213+
child.stderr_behavior = .Pipe;
214+
child.cwd = args.cwd;
215+
child.env_map = args.env_map;
216+
child.expand_arg0 = args.expand_arg0;
192217

193218
try child.spawn();
194219

195-
var stdout = Buffer.initNull(allocator);
196-
var stderr = Buffer.initNull(allocator);
220+
var stdout = Buffer.initNull(args.allocator);
221+
var stderr = Buffer.initNull(args.allocator);
197222
defer Buffer.deinit(&stdout);
198223
defer Buffer.deinit(&stderr);
199224

200225
var stdout_file_in_stream = child.stdout.?.inStream();
201226
var stderr_file_in_stream = child.stderr.?.inStream();
202227

203-
try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
204-
try stderr_file_in_stream.stream.readAllBuffer(&stderr, max_output_size);
228+
try stdout_file_in_stream.stream.readAllBuffer(&stdout, args.max_output_bytes);
229+
try stderr_file_in_stream.stream.readAllBuffer(&stderr, args.max_output_bytes);
205230

206231
return ExecResult{
207232
.term = try child.wait(),
@@ -420,7 +445,7 @@ pub const ChildProcess = struct {
420445
os.setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
421446
}
422447

423-
const err = os.execvpe(self.allocator, self.argv, env_map);
448+
const err = os.execvpe_expandArg0(self.allocator, self.expand_arg0, self.argv, env_map);
424449
forkChildErrReport(err_pipe[1], err);
425450
}
426451

@@ -453,7 +478,6 @@ pub const ChildProcess = struct {
453478

454479
self.pid = pid;
455480
self.err_pipe = err_pipe;
456-
self.llnode = TailQueue(*ChildProcess).Node.init(self);
457481
self.term = null;
458482

459483
if (self.stdin_behavior == StdIo.Pipe) {

lib/std/event.zig

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub const Channel = @import("event/channel.zig").Channel;
22
pub const Future = @import("event/future.zig").Future;
33
pub const Group = @import("event/group.zig").Group;
4+
pub const Batch = @import("event/batch.zig").Batch;
45
pub const Lock = @import("event/lock.zig").Lock;
56
pub const Locked = @import("event/locked.zig").Locked;
67
pub const RwLock = @import("event/rwlock.zig").RwLock;
@@ -11,6 +12,7 @@ test "import event tests" {
1112
_ = @import("event/channel.zig");
1213
_ = @import("event/future.zig");
1314
_ = @import("event/group.zig");
15+
_ = @import("event/batch.zig");
1416
_ = @import("event/lock.zig");
1517
_ = @import("event/locked.zig");
1618
_ = @import("event/rwlock.zig");

0 commit comments

Comments
 (0)