Repository navigation
instead of run subcommand, treat first positional argument as the zig run target #1505
Description
Here's one use case:
#!/usr/bin/env zig
const std = @import("std");
pub fn main() !void {
// If this program is run without stdout attached, exit with an error.
var stdout_file = try std.io.getStdOut();
// If this program encounters pipe failure when printing to stdout, exit
// with an error.
try stdout_file.write("Hello, world!\n");
}Using env is the portable way to use an interpreter for a shebang line, and Linux passes everything after the space as a single argument, which means we can't do something like #!/usr/bin/env zig run.
As an example, on my home OS - NixOS - the /usr/bin directory is empty except for env:
andy@xps ~> ls /usr/bin/
env
The other use case is that Zig now enters the playing field, alongside commands like these:
python foo.py [args]node foo.js [args]ruby foo.rb [args]perl foo.pl [args]- etc
This command would be unambiguous: args would be parsed normally until the first positional argument. If the first positional argument does not have a / in it then it is treated as a subcommand. Otherwise it is treated as a zig run target, and the rest of the arguments are forwarded to the program. If the file does not exist, a helpful error message could suggest that perhaps the user meant to try one of the subcommands, or they meant to create the file and execute it.
Here is a demonstration that it would be unambiguous:
- Here we are currently printing the usage text, because it is currently not meaningful to pass a positional argument with no subcommand:
$ ./zig test.zig
Unrecognized command: test.zig
Usage: ./zig [command] [options]
...
- Here we try to make a file the same name as a subcommand, but we cannot get linux to pass us the path without the
/:
andy@xps ~/tmp> cat build-obj
#!/usr/bin/env echo
andy@xps ~/tmp> chmod +x build-obj
andy@xps ~/tmp> build-obj
build-obj: command not found
andy@xps ~/tmp> ./build-obj
./build-obj
So as long as no zig subcommands have a / in them, this would be unambiguous. This seems like a reasonable restriction.
cc @tiehuis - I think we discussed this before and ended up on status quo, but I'd like to bring it up one more time.
Activity
tgschultz commentedon Sep 12, 2018
Another option: symlink
zig-runtozig, have zig check arg[0] to see if it was called aszig-run.thejoshwolfe commentedon Sep 12, 2018
This is unambiguous in most but not all cases.
Invoking shebang scripts on the PATH uses absolute paths, so this is good:
However, we can get ambiguity by calling
execvdirectly:(I think the
./prefix to invoke a program in the current directory is just a convention that shell languages follow.)mesbahamin commentedon Nov 13, 2018
As of GNU coreutils v8.30, you can do:
#!/usr/bin/env -S zig runThis feature was added in a recent (2018-04-20) commit to
env.cin theGNU coreutils package, which added the
-Sor--split-stringoption. I'mpretty sure this feature was adopted from FreeBSD's version of
env.From the
envman page:More examples are available in the GNU coreutils manual.
Note: This only applies to shebangs that use
/usr/bin/env, as--split-stringis a feature ofenvspecifically.andrewrk commentedon Mar 31, 2019
I'm reconsidering this. It's common to have zig installed somewhere other than globally. Plus, there could be different zig versions. And what about packages? Relying on the shebang line is a weird way to distribute zig code.
hryx commentedon Mar 31, 2019
Is the use case for shebang support written down somewhere? I can't find the original proposal and am struggling to think of when I would need or even want to call
$ ./script.zigover running a precompiled executable.andrewrk commentedon Mar 31, 2019
No there is no documented use case. The original motivation was just trying to be POSIX friendly.
daurnimator commentedon Apr 1, 2019
The whole point of using
envis that it'll pick thezigin your path. If you have multiple versions of zig installed; or somewhere other than globally, then you can still add them to yourPATH.andrewrk commentedon Apr 5, 2019
See reasoning here for why this proposal is being rejected: #2165 (comment)