diff options
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/build.zig | 168 | ||||
| -rw-r--r-- | lib/std/fs/file.zig | 11 | ||||
| -rw-r--r-- | lib/std/unicode.zig | 9 |
3 files changed, 131 insertions, 57 deletions
diff --git a/lib/std/build.zig b/lib/std/build.zig index f1287c7be5..ff0f36b4a8 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1600,12 +1600,26 @@ pub const LibExeObjStep = struct { pub const LinkObject = union(enum) { static_path: FileSource, other_step: *LibExeObjStep, - system_lib: []const u8, + system_lib: SystemLib, assembly_file: FileSource, c_source_file: *CSourceFile, c_source_files: *CSourceFiles, }; + pub const SystemLib = struct { + name: []const u8, + use_pkg_config: enum { + /// Don't use pkg-config, just pass -lfoo where foo is name. + no, + /// Try to get information on how to link the library from pkg-config. + /// If that fails, fall back to passing -lfoo where foo is name. + yes, + /// Try to get information on how to link the library from pkg-config. + /// If that fails, error out. + force, + }, + }; + pub const IncludeDir = union(enum) { raw_path: []const u8, raw_path_system: []const u8, @@ -1854,7 +1868,7 @@ pub const LibExeObjStep = struct { } for (self.link_objects.items) |link_object| { switch (link_object) { - .system_lib => |n| if (mem.eql(u8, n, name)) return true, + .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true, else => continue, } } @@ -1879,14 +1893,24 @@ pub const LibExeObjStep = struct { pub fn linkLibC(self: *LibExeObjStep) void { if (!self.is_linking_libc) { self.is_linking_libc = true; - self.link_objects.append(.{ .system_lib = "c" }) catch unreachable; + self.link_objects.append(.{ + .system_lib = .{ + .name = "c", + .use_pkg_config = .no, + }, + }) catch unreachable; } } pub fn linkLibCpp(self: *LibExeObjStep) void { if (!self.is_linking_libcpp) { self.is_linking_libcpp = true; - self.link_objects.append(.{ .system_lib = "c++" }) catch unreachable; + self.link_objects.append(.{ + .system_lib = .{ + .name = "c++", + .use_pkg_config = .no, + }, + }) catch unreachable; } } @@ -1905,12 +1929,28 @@ pub const LibExeObjStep = struct { /// This one has no integration with anything, it just puts -lname on the command line. /// Prefer to use `linkSystemLibrary` instead. pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void { - self.link_objects.append(.{ .system_lib = self.builder.dupe(name) }) catch unreachable; + self.link_objects.append(.{ + .system_lib = .{ + .name = self.builder.dupe(name), + .use_pkg_config = .no, + }, + }) catch unreachable; } /// This links against a system library, exclusively using pkg-config to find the library. /// Prefer to use `linkSystemLibrary` instead. - pub fn linkSystemLibraryPkgConfigOnly(self: *LibExeObjStep, lib_name: []const u8) !void { + pub fn linkSystemLibraryPkgConfigOnly(self: *LibExeObjStep, lib_name: []const u8) void { + self.link_objects.append(.{ + .system_lib = .{ + .name = self.builder.dupe(lib_name), + .use_pkg_config = .force, + }, + }) catch unreachable; + } + + /// Run pkg-config for the given library name and parse the output, returning the arguments + /// that should be passed to zig to link the given library. + fn runPkgConfig(self: *LibExeObjStep, lib_name: []const u8) ![]const []const u8 { const pkg_name = match: { // First we have to map the library name to pkg config name. Unfortunately, // there are several examples where this is not straightforward: @@ -1970,34 +2010,38 @@ pub const LibExeObjStep = struct { error.ChildExecFailed => return error.PkgConfigFailed, else => return err, }; + + var zig_args = std.ArrayList([]const u8).init(self.builder.allocator); + defer zig_args.deinit(); + var it = mem.tokenize(u8, stdout, " \r\n\t"); while (it.next()) |tok| { if (mem.eql(u8, tok, "-I")) { const dir = it.next() orelse return error.PkgConfigInvalidOutput; - self.addIncludePath(dir); + try zig_args.appendSlice(&[_][]const u8{ "-I", dir }); } else if (mem.startsWith(u8, tok, "-I")) { - self.addIncludePath(tok["-I".len..]); + try zig_args.append(tok); } else if (mem.eql(u8, tok, "-L")) { const dir = it.next() orelse return error.PkgConfigInvalidOutput; - self.addLibraryPath(dir); + try zig_args.appendSlice(&[_][]const u8{ "-L", dir }); } else if (mem.startsWith(u8, tok, "-L")) { - self.addLibraryPath(tok["-L".len..]); + try zig_args.append(tok); } else if (mem.eql(u8, tok, "-l")) { const lib = it.next() orelse return error.PkgConfigInvalidOutput; - self.linkSystemLibraryName(lib); + try zig_args.appendSlice(&[_][]const u8{ "-l", lib }); } else if (mem.startsWith(u8, tok, "-l")) { - self.linkSystemLibraryName(tok["-l".len..]); + try zig_args.append(tok); } else if (mem.eql(u8, tok, "-D")) { const macro = it.next() orelse return error.PkgConfigInvalidOutput; - self.defineCMacroRaw(macro); + try zig_args.appendSlice(&[_][]const u8{ "-D", macro }); } else if (mem.startsWith(u8, tok, "-D")) { - self.defineCMacroRaw(tok["-D".len..]); - } else if (mem.eql(u8, tok, "-pthread")) { - self.linkLibC(); + try zig_args.append(tok); } else if (self.builder.verbose) { warn("Ignoring pkg-config flag '{s}'\n", .{tok}); } } + + return zig_args.toOwnedSlice(); } pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void { @@ -2009,21 +2053,13 @@ pub const LibExeObjStep = struct { self.linkLibCpp(); return; } - if (self.linkSystemLibraryPkgConfigOnly(name)) |_| { - // pkg-config worked, so nothing further needed to do. - return; - } else |err| switch (err) { - error.PkgConfigInvalidOutput, - error.PkgConfigCrashed, - error.PkgConfigFailed, - error.PkgConfigNotInstalled, - error.PackageNotFound, - => {}, - - else => unreachable, - } - self.linkSystemLibraryName(name); + self.link_objects.append(.{ + .system_lib = .{ + .name = self.builder.dupe(name), + .use_pkg_config = .yes, + }, + }) catch unreachable; } pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void { @@ -2317,27 +2353,34 @@ pub const LibExeObjStep = struct { var prev_has_extra_flags = false; // Resolve transitive dependencies - for (self.link_objects.items) |link_object| { - switch (link_object) { - .other_step => |other| { - // Inherit dependency on system libraries - for (other.link_objects.items) |other_link_object| { - switch (other_link_object) { - .system_lib => |name| self.linkSystemLibrary(name), - else => continue, + { + var transitive_dependencies = std.ArrayList(LinkObject).init(builder.allocator); + defer transitive_dependencies.deinit(); + + for (self.link_objects.items) |link_object| { + switch (link_object) { + .other_step => |other| { + // Inherit dependency on system libraries + for (other.link_objects.items) |other_link_object| { + switch (other_link_object) { + .system_lib => try transitive_dependencies.append(other_link_object), + else => continue, + } } - } - // Inherit dependencies on darwin frameworks - if (!other.isDynamicLibrary()) { - var it = other.frameworks.iterator(); - while (it.next()) |framework| { - self.frameworks.insert(framework.*) catch unreachable; + // Inherit dependencies on darwin frameworks + if (!other.isDynamicLibrary()) { + var it = other.frameworks.iterator(); + while (it.next()) |framework| { + self.frameworks.insert(framework.*) catch unreachable; + } } - } - }, - else => continue, + }, + else => continue, + } } + + try self.link_objects.appendSlice(transitive_dependencies.items); } for (self.link_objects.items) |link_object| { @@ -2363,8 +2406,35 @@ pub const LibExeObjStep = struct { } }, }, - .system_lib => |name| { - try zig_args.append(builder.fmt("-l{s}", .{name})); + + .system_lib => |system_lib| { + switch (system_lib.use_pkg_config) { + .no => try zig_args.append(builder.fmt("-l{s}", .{system_lib.name})), + .yes, .force => { + if (self.runPkgConfig(system_lib.name)) |args| { + try zig_args.appendSlice(args); + } else |err| switch (err) { + error.PkgConfigInvalidOutput, + error.PkgConfigCrashed, + error.PkgConfigFailed, + error.PkgConfigNotInstalled, + error.PackageNotFound, + => switch (system_lib.use_pkg_config) { + .yes => { + // pkg-config failed, so fall back to linking the library + // by name directly. + try zig_args.append(builder.fmt("-l{s}", .{system_lib.name})); + }, + .force => { + panic("pkg-config failed for library {s}", .{system_lib.name}); + }, + .no => unreachable, + }, + + else => |e| return e, + } + }, + } }, .assembly_file => |asm_file| { diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 568c34e0ac..3ea8dd0285 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -200,6 +200,17 @@ pub const File = struct { } } + pub const SyncError = os.SyncError; + + /// Blocks until all pending file contents and metadata modifications + /// for the file have been synchronized with the underlying filesystem. + /// + /// Note that this does not ensure that metadata for the + /// directory containing the file has also reached disk. + pub fn sync(self: File) SyncError!void { + return os.fsync(self.handle); + } + /// Test whether the file refers to a terminal. /// See also `supportsAnsiEscapeCodes`. pub fn isTty(self: File) bool { diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index e0a000dfe5..487f3defdf 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -269,14 +269,7 @@ pub const Utf8Iterator = struct { pub fn nextCodepoint(it: *Utf8Iterator) ?u21 { const slice = it.nextCodepointSlice() orelse return null; - - switch (slice.len) { - 1 => return @as(u21, slice[0]), - 2 => return utf8Decode2(slice) catch unreachable, - 3 => return utf8Decode3(slice) catch unreachable, - 4 => return utf8Decode4(slice) catch unreachable, - else => unreachable, - } + return utf8Decode(slice) catch unreachable; } /// Look ahead at the next n codepoints without advancing the iterator. |
