Skip to content

Commit

Permalink
build: clean up after Zig 0.11.0 update
Browse files Browse the repository at this point in the history
- Assorted cleanups after the previous update commit
- Upgrade the flags.zig snippet to the new Zig 0.11 API.
  • Loading branch information
ifreund committed Oct 25, 2023
1 parent d9db2ce commit 4ad16ca
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 155 deletions.
15 changes: 8 additions & 7 deletions PACKAGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,18 @@ in the first place. For greatest effect, both may be used.
- `--libc my_libc.txt`: Set system libc paths for cross compilation. Run
`zig libc` to see a documented template for what this file should contain.

- Enable compiler optimizations with `-Doptimize`:
- Enable compiler optimizations:

- `ReleaseSafe`: Keep all assertions and runtime safety checks active.
- `-Doptimize=ReleaseSafe`: Optimize for execution speed,
keep all assertions and runtime safety checks active.

- `ReleaseFast`: Optimize for execution speed, disable all assertions
and runtime safety checks.
- `-Doptimize=ReleaseFast`: Optimize for execution speed,
disable all assertions and runtime safety checks.

- `ReleaseSmall`: Optimize for binary size, disable all assertions and
runtime safety checks.
- `-Doptimize=ReleaseSmall`: Optimize for binary size,
disable all assertions and runtime safety checks.

Please use `ReleaseSafe` when building waylock for general use. This
Please use `-Doptimize=ReleaseSafe` when building waylock for general
software is not at all demanding when it comes to CPU execution speed and the
increased safety is more than worth the binary size trade-off in my opinion.

Expand Down
71 changes: 22 additions & 49 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const std = @import("std");
const assert = std.debug.assert;
const Build = std.Build;
const Step = std.Build.Step;
const fs = std.fs;
const mem = std.mem;

Expand Down Expand Up @@ -33,21 +32,18 @@ pub fn build(b: *Build) !void {
};

if (man_pages) {
inline for (.{"waylock"}) |page| {
// Taken from river. The rationale is of the following:
// Workaround for https://github.com/ziglang/zig/issues/16369
// Even passing a buffer to std.Build.Step.Run appears to be racy and occasionally deadlocks.
const scdoc = b.addSystemCommand(&.{ "sh", "-c", "scdoc < doc/" ++ page ++ ".1.scd" });

scdoc.addFileArg(.{ .path = "doc/" ++ page ++ ".1.scd" });

const stdout = scdoc.captureStdOut();
b.getInstallStep().dependOn(&b.addInstallFile(stdout, "share/man/man1/" ++ page ++ ".1").step);
}
// Workaround for https://github.com/ziglang/zig/issues/16369
// Even passing a buffer to std.Build.Step.Run appears to be racy and occasionally deadlocks.
const scdoc = b.addSystemCommand(&.{ "sh", "-c", "scdoc < doc/waylock.1.scd" });
// This makes the caching work for the Workaround, and the extra argument is ignored by /bin/sh.
scdoc.addFileArg(.{ .path = "doc/waylock.1.scd" });

const stdout = scdoc.captureStdOut();
b.getInstallStep().dependOn(&b.addInstallFile(stdout, "share/man/man1/waylock.1").step);
}

const install_prefix = try std.fs.path.resolve(b.allocator, &[_][]const u8{b.install_prefix});
if (std.mem.eql(u8, install_prefix, "/usr")) {
const install_prefix = try std.fs.path.resolve(b.allocator, &.{b.install_prefix});
if (mem.eql(u8, install_prefix, "/usr")) {
b.installFile("pam.d/waylock", "../etc/pam.d/waylock");
} else {
b.installFile("pam.d/waylock", "etc/pam.d/waylock");
Expand All @@ -71,10 +67,7 @@ pub fn build(b: *Build) !void {
assert(commit_hash[0] == 'g');

// Follow semantic versioning, e.g. 0.2.0-dev.42+d1cf95b
break :blk try std.fmt.allocPrintZ(b.allocator, version ++ ".{s}+{s}", .{
commit_count,
commit_hash[1..],
});
break :blk b.fmt(version ++ ".{s}+{s}", .{ commit_count, commit_hash[1..] });
} else {
break :blk version;
}
Expand All @@ -95,6 +88,11 @@ pub fn build(b: *Build) !void {
scanner.generate("wp_viewporter", 1);
scanner.generate("wp_single_pixel_buffer_manager_v1", 1);

const wayland = b.createModule(.{ .source_file = scanner.result });
const xkbcommon = b.createModule(
.{ .source_file = .{ .path = "deps/zig-xkbcommon/src/xkbcommon.zig" } },
);

const waylock = b.addExecutable(.{
.name = "waylock",
.root_source_file = .{ .path = "src/main.zig" },
Expand All @@ -103,44 +101,19 @@ pub fn build(b: *Build) !void {
});
waylock.addOptions("build_options", options);

const wayland = b.createModule(.{ .source_file = scanner.result });
waylock.addModule("wayland", wayland);
const xkbcommon = b.createModule(.{ .source_file = .{ .path = "deps/zig-xkbcommon/src/xkbcommon.zig" } });
waylock.addModule("xkbcommon", xkbcommon);
waylock.linkLibC();
waylock.linkSystemLibrary("pam");

waylock.addModule("wayland", wayland);
waylock.linkSystemLibrary("wayland-client");

waylock.addModule("xkbcommon", xkbcommon);
waylock.linkSystemLibrary("xkbcommon");
waylock.linkSystemLibrary("pam");

// TODO: remove when zig issue #131 is implemented
scanner.addCSource(waylock);

waylock.strip = strip;
waylock.pie = pie;
b.installArtifact(waylock);
}

const ScdocStep = struct {
builder: *Build,
step: *Step,

fn create(builder: *Build) !*ScdocStep {
const self = try builder.allocator.create(ScdocStep);
self.* = .{
.builder = builder,
.step = Step.init(.custom, "Generate man pages", builder.allocator, make),
};
return self;
}

fn make(step: *Step) !void {
const self = @fieldParentPtr(ScdocStep, "step", step);
_ = try self.builder.exec(
&[_][]const u8{ "sh", "-c", "scdoc < doc/waylock.1.scd > doc/waylock.1" },
);
}

fn install(self: *ScdocStep) !void {
self.builder.getInstallStep().dependOn(&self.step);
self.builder.installFile("doc/waylock.1", "share/man/man1/waylock.1");
}
};
4 changes: 2 additions & 2 deletions src/Output.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ fn lock_surface_listener(
const lock = output.lock;
switch (event) {
.configure => |ev| {
output.width = @as(u31, @truncate(ev.width));
output.height = @as(u31, @truncate(ev.height));
output.width = @min(std.math.maxInt(u31), ev.width);
output.height = @min(std.math.maxInt(u31), ev.height);
output.lock_surface.?.ackConfigure(ev.serial);
output.attach_buffer(lock.buffers[@intFromEnum(lock.color)]);
},
Expand Down
2 changes: 1 addition & 1 deletion src/Seat.zig
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ fn keyboard_listener(_: *wl.Keyboard, event: wl.Keyboard.Event, seat: *Seat) voi
const Component = xkb.State.Component;
const ctrl_active = xkb_state.modNameIsActive(
xkb.names.mod.ctrl,
@as(Component, @enumFromInt(Component.mods_depressed | Component.mods_latched)),
@enumFromInt(Component.mods_depressed | Component.mods_latched),
) == 1;

if (ctrl_active) {
Expand Down
7 changes: 3 additions & 4 deletions src/auth.zig
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,17 @@ fn converse(
) callconv(.C) pam.Result {
const ally = std.heap.raw_c_allocator;

const count = @as(usize, @intCast(num_msg));
const responses = ally.alloc(pam.Response, count) catch {
const responses = ally.alloc(pam.Response, @intCast(num_msg)) catch {
return .buf_err;
};

@memset(responses, .{});
resp.* = responses.ptr;

for (msg[0..count], 0..) |message, i| {
for (msg, responses) |message, *response| {
switch (message.msg_style) {
.prompt_echo_off => {
responses[i] = .{
response.* = .{
.resp = ally.dupeZ(u8, password.buffer) catch {
return .buf_err;
},
Expand Down
163 changes: 91 additions & 72 deletions src/flags.zig
Original file line number Diff line number Diff line change
@@ -1,89 +1,108 @@
// Zero allocation argument parsing for unix-like systems.
// Released under the Zero Clause BSD (0BSD) license:
//
// Copyright 2023 Isaac Freund
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

const std = @import("std");
const mem = std.mem;

pub const Flag = struct {
name: [*:0]const u8,
name: []const u8,
kind: enum { boolean, arg },
};

pub fn ParseResult(comptime flags: []const Flag) type {
pub fn parser(comptime Arg: type, comptime flags: []const Flag) type {
switch (Arg) {
// TODO consider allowing []const u8
[:0]const u8, [*:0]const u8 => {}, // ok
else => @compileError("invalid argument type: " ++ @typeName(Arg)),
}
return struct {
const Self = @This();

const FlagData = struct {
name: [*:0]const u8,
value: union {
boolean: bool,
arg: ?[*:0]const u8,
},
};
pub const Result = struct {
/// Remaining args after the recognized flags
args: []const Arg,
/// Data obtained from parsed flags
flags: Flags,

/// Remaining args after the recognized flags
args: [][*:0]const u8,
/// Data obtained from parsed flags
flag_data: [flags.len]FlagData = blk: {
// Init all flags to false/null
var flag_data: [flags.len]FlagData = undefined;
inline for (flags, 0..) |flag, i| {
flag_data[i] = switch (flag.kind) {
.boolean => .{
.name = flag.name,
.value = .{ .boolean = false },
},
.arg => .{
.name = flag.name,
.value = .{ .arg = null },
},
};
}
break :blk flag_data;
},

pub fn boolFlag(self: Self, flag_name: [*:0]const u8) bool {
for (self.flag_data) |flag_data| {
if (mem.orderZ(u8, flag_data.name, flag_name) == .eq) return flag_data.value.boolean;
}
unreachable; // Invalid flag_name
}

pub fn argFlag(self: Self, flag_name: [*:0]const u8) ?[:0]const u8 {
for (self.flag_data) |flag_data| {
if (mem.orderZ(u8, flag_data.name, flag_name) == .eq) {
return std.mem.span(flag_data.value.arg);
pub const Flags = flags_type: {
var fields: []const std.builtin.Type.StructField = &.{};
inline for (flags) |flag| {
const field: std.builtin.Type.StructField = switch (flag.kind) {
.boolean => .{
.name = flag.name,
.type = bool,
.default_value = &false,
.is_comptime = false,
.alignment = @alignOf(bool),
},
.arg => .{
.name = flag.name,
.type = ?[:0]const u8,
.default_value = &@as(?[:0]const u8, null),
.is_comptime = false,
.alignment = @alignOf(?[:0]const u8),
},
};
fields = fields ++ [_]std.builtin.Type.StructField{field};
}
}
unreachable; // Invalid flag_name
}
};
}
break :flags_type @Type(.{ .Struct = .{
.layout = .Auto,
.fields = fields,
.decls = &.{},
.is_tuple = false,
} });
};
};

pub fn parse(args: [][*:0]const u8, comptime flags: []const Flag) !ParseResult(flags) {
var ret: ParseResult(flags) = .{ .args = undefined };
pub fn parse(args: []const Arg) !Result {
var result_flags: Result.Flags = .{};

var arg_idx: usize = 0;
while (arg_idx < args.len) : (arg_idx += 1) {
var parsed_flag = false;
inline for (flags, 0..) |flag, flag_idx| {
if (mem.orderZ(u8, flag.name, args[arg_idx]) == .eq) {
switch (flag.kind) {
.boolean => ret.flag_data[flag_idx].value.boolean = true,
.arg => {
arg_idx += 1;
if (arg_idx == args.len) {
std.log.err("option '" ++ flag.name ++
"' requires an argument but none was provided!", .{});
return error.MissingFlagArgument;
var i: usize = 0;
outer: while (i < args.len) : (i += 1) {
const arg = switch (Arg) {
[*:0]const u8 => mem.sliceTo(args[i], 0),
[:0]const u8 => args[i],
else => unreachable,
};
inline for (flags) |flag| {
if (mem.eql(u8, "-" ++ flag.name, arg)) {
switch (flag.kind) {
.boolean => @field(result_flags, flag.name) = true,
.arg => {
i += 1;
if (i == args.len) {
std.log.err("option '-" ++ flag.name ++
"' requires an argument but none was provided!", .{});
return error.MissingFlagArgument;
}
@field(result_flags, flag.name) = switch (Arg) {
[*:0]const u8 => mem.sliceTo(args[i], 0),
[:0]const u8 => args[i],
else => unreachable,
};
},
}
ret.flag_data[flag_idx].value.arg = args[arg_idx];
},
continue :outer;
}
}
parsed_flag = true;
break;
}
}
if (!parsed_flag) break;
}

ret.args = args[arg_idx..];

return ret;
return Result{
.args = args[i..],
.flags = result_flags,
};
}
};
}
Loading

0 comments on commit 4ad16ca

Please sign in to comment.