diff options
| author | Gabriel Schneider <[email protected]> | 2026-08-25 15:42:03 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-08-25 16:17:41 -0300 |
| commit | 6b176c598e55a48572e5e508a213491eec122bf4 (patch) | |
| tree | a4f5d5dd0cd2942469ae618d81397c8a443582fc /build.zig | |
| parent | 9ab0cbb93dd7678dcc8e86e164325e7d1b8ea7c6 (diff) | |
| download | esp32p4-6b176c598e55a48572e5e508a213491eec122bf4.tar.gz esp32p4-6b176c598e55a48572e5e508a213491eec122bf4.zip | |
Say what to do when the serial port is not readable
AccessDenied on /dev/ttyUSB0 is the first thing anyone hits, and "cannot open
/dev/ttyUSB0: AccessDenied" does not help. The steps that open the port now share
one failure path that names the group, and names the part that actually confuses
people: adding yourself with usermod -aG does NOT affect a shell that is already
running, because credentials are captured at login. So the same error greets
someone who has already fixed it. The message offers newgrp for this shell and sg
for one command.
Diffstat (limited to 'build.zig')
| -rw-r--r-- | build.zig | 36 |
1 files changed, 32 insertions, 4 deletions
@@ -1361,6 +1361,34 @@ fn readImage(step: *std.Build.Step, gpa: std.mem.Allocator, path: std.Build.Lazy return step.fail("{s} is not a usable image: {s}", .{ p, @errorName(err) }); } +/// Fail a step that could not open the serial port, and for the one error that is always the same +/// mistake, say what to do about it. +/// +/// `AccessDenied` is the first thing anyone hits: the device is owned by a group (uucp on Arch, +/// dialout on Debian) and the account is not in it. The subtlety worth printing is the SECOND half - +/// adding the group with `usermod -aG` does not affect any shell that is already running, because +/// credentials are captured at login. That produces exactly this error from a user who has already +/// "fixed" it, which is a genuinely confusing place to be. +fn failPort(step: *std.Build.Step, port: []const u8, err: anyerror) anyerror { + if (err != error.AccessDenied) return step.fail("cannot open {s}: {s}", .{ port, @errorName(err) }); + return step.fail( + \\cannot open {s}: AccessDenied + \\ + \\ {s} is owned by a group your session is not in (uucp on Arch, dialout on Debian): + \\ ls -l {s} + \\ + \\ If you are NOT in that group yet, join it and log in again: + \\ sudo usermod -aG uucp $USER + \\ + \\ If `id -nG` already lists it, this shell simply predates the change - group membership + \\ is captured at login. Either log out and back in, or take it in this shell: + \\ newgrp uucp + \\ + \\ Or run one command with the group, without touching this shell at all: + \\ sg uucp -c 'zig build ... ' + , .{ port, port, port }); +} + const FlashStep = struct { step: std.Build.Step, bin: std.Build.LazyPath, @@ -1402,7 +1430,7 @@ const FlashStep = struct { defer port_lock.unlock(b.graph.io); var port = serial.Port.open(self.port, self.baud) catch |err| - return step.fail("cannot open {s}: {s}", .{ self.port, @errorName(err) }); + return failPort(step, self.port, err); defer port.close(); const t_open = port.nowMs(); @@ -1476,7 +1504,7 @@ const MonitorStep = struct { defer port_lock.unlock(b.graph.io); var port = serial.Port.open(self.port, .b115200) catch |err| - return step.fail("cannot open {s}: {s}", .{ self.port, @errorName(err) }); + return failPort(step, self.port, err); defer port.close(); port.resetToRun(.{}) catch {}; @@ -1525,7 +1553,7 @@ const ConsoleStep = struct { defer port_lock.unlock(b.graph.io); console.attach(self.port, self.baud, .{}) catch |err| - return step.fail("console on {s}: {s}", .{ self.port, @errorName(err) }); + return failPort(step, self.port, err); } }; @@ -1550,7 +1578,7 @@ const ResetStep = struct { port_lock.lockUncancelable(b.graph.io); defer port_lock.unlock(b.graph.io); var port = serial.Port.open(self.port, .b115200) catch |err| - return step.fail("cannot open {s}: {s}", .{ self.port, @errorName(err) }); + return failPort(step, self.port, err); defer port.close(); port.resetToRun(.{}) catch |err| return step.fail("reset failed: {s}", .{@errorName(err)}); } |
