I'm an experienced programmer, including about 10000 lines of Rust.
I've just discovered zig and am experimenting with it. But I'm stumped
by something as fundamental as reading command line args on a Linux
system (Arch; up to date).
The only documentation I've found is for wasi, which appears not to be
ready yet.
So I cloned the zig repository on github and in the file std/os.zig, I find
/// Populated by startup code before main().
/// Not available on Windows. See `std.process.args`
/// for obtaining the process arguments.
pub var argv: [][*]u8 = undefined;
So in my little experimental program, I've done
const std = @import("std");
and later
const argv = std.os.argv;
Trying to compile, I get
dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe
--library c composite_register.zig
/home/dca/Software/newcash_zig/composite_register/composite_register.zig:33:24:
error: container 'std.os' has no member called 'argv'
const argv = std.os.argv;
This brings up two questions:
1. How do you obtain the command line args in a simple zig program on Linux?
2. How do you identify the components of a container? As I mentioned
above, the file std/os.zig contains a public variable argv, and yet I
get the above error complaining that argv is not "member".
Thanks in advance for any assistance.
/Don Allen
On Sat, Sep 7, 2019 at 3:23 PM Donald Allen <donaldcallen@gmail.com> wrote:
>> I'm an experienced programmer, including about 10000 lines of Rust.> I've just discovered zig and am experimenting with it. But I'm stumped> by something as fundamental as reading command line args on a Linux> system (Arch; up to date).>> The only documentation I've found is for wasi, which appears not to be> ready yet.>> So I cloned the zig repository on github and in the file std/os.zig, I find>> /// Populated by startup code before main().> /// Not available on Windows. See `std.process.args`> /// for obtaining the process arguments.> pub var argv: [][*]u8 = undefined;>> So in my little experimental program, I've done>> const std = @import("std");>> and later>> const argv = std.os.argv;>> Trying to compile, I get>> dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe> --library c composite_register.zig> /home/dca/Software/newcash_zig/composite_register/composite_register.zig:33:24:> error: container 'std.os' has no member called 'argv'> const argv = std.os.argv;>> This brings up two questions:>> 1. How do you obtain the command line args in a simple zig program on Linux?> 2. How do you identify the components of a container? As I mentioned> above, the file std/os.zig contains a public variable argv, and yet I> get the above error complaining that argv is not "member".>> Thanks in advance for any assistance.>> /Don Allen
Hi Don, it sounds like you're looking for std.os.args()? You can find
a usage example here:
https://github.com/ziglang/zig/blob/9a18db8a80c96d206297e865d203b2a7d8a803ba/test/cli.zig
As to your second question, I'm not sure I fully follow but maybe the
example helps clear it up?
On Sat, 7 Sep 2019 at 09:57, Ben Noordhuis <info@bnoordhuis.nl> wrote:
>> On Sat, Sep 7, 2019 at 3:23 PM Donald Allen <donaldcallen@gmail.com> wrote:> >> > I'm an experienced programmer, including about 10000 lines of Rust.> > I've just discovered zig and am experimenting with it. But I'm stumped> > by something as fundamental as reading command line args on a Linux> > system (Arch; up to date).> >> > The only documentation I've found is for wasi, which appears not to be> > ready yet.> >> > So I cloned the zig repository on github and in the file std/os.zig, I find> >> > /// Populated by startup code before main().> > /// Not available on Windows. See `std.process.args`> > /// for obtaining the process arguments.> > pub var argv: [][*]u8 = undefined;> >> > So in my little experimental program, I've done> >> > const std = @import("std");> >> > and later> >> > const argv = std.os.argv;> >> > Trying to compile, I get> >> > dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe> > --library c composite_register.zig> > /home/dca/Software/newcash_zig/composite_register/composite_register.zig:33:24:> > error: container 'std.os' has no member called 'argv'> > const argv = std.os.argv;> >> > This brings up two questions:> >> > 1. How do you obtain the command line args in a simple zig program on Linux?> > 2. How do you identify the components of a container? As I mentioned> > above, the file std/os.zig contains a public variable argv, and yet I> > get the above error complaining that argv is not "member".> >> > Thanks in advance for any assistance.> >> > /Don Allen>> Hi Don, it sounds like you're looking for std.os.args()? You can find> a usage example here:> https://github.com/ziglang/zig/blob/9a18db8a80c96d206297e865d203b2a7d8a803ba/test/cli.zig
Thanks very much for the help.
Using your example as a guide, I modified my program like so:
const std = @import("std");
pub fn main() !void {
const TRANSACTIONS_SQL =
\\ select date(post_date), t.num, t.description, t.guid
\\ from transactions t, splits s
\\ where s.account_guid = ?1
\\ and t.guid = s.tx_guid
\\ and date(t.post_date) >= ?2
\\ and date(t.post_date) <= ?3
\\ and description like ?4
\\ order by t.post_date, t.enter_date
;
const SPLITS_SQL =
\\ select account_guid, ifnull(mnemonic,''),
\\ ifnull(memo,''), ifnull(quantity,0.0),
\\ ifnull(value/nullif(quantity,0),0.),
\\ ifnull(value,0.)
\\ from (select s.account_guid, c.mnemonic, s.memo,
\\ s.quantity as quantity, s.value as value
\\ from splits s, accounts a left outer join commodities c
on a.commodity_guid = c.guid
\\ where s.tx_guid = ?1 and a.guid = s.account_guid)
;
// Get stdout
const stdout_file = try std.io.getStdOut();
// Get the args
const process = std.process;
var arg_it = process.args();
// skip my own exe name
_ = arg_it.skip();
const start_date = try (arg_it.next(std.heap.c_allocator) orelse {
std.debug.warn("Expected first argument to be start_date\n");
return error.InvalidArgs;
});
try stdout_file.write(start_date);
}
(Ignore the sql. That's for later, if I end up making progress with this.)
Attempting to compile produces
dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe
--library c composite_register.zig
/home/dca/Software/newcash_zig/composite_register/composite_register.zig:27:24:
error: container 'std' has no member called 'process'
const process = std.process;
^
dca@franz:~/Software/newcash_zig/composite_register$
????
/Don
(Sorry, Ben. You will get two copies of this. I forgot to reply-all.)
The plot thickens.
I tried a little test program, in /tmp/testit.zig:
const std = @import("std");
const process = std.process;
pub fn main() void {
}
Compiling as I did with my experiment produces no error:
dca@franz:/tmp$ zig build-exe --library c testit.zig
dca@franz:/tmp$
I then moved the constant definition of process into the scope of the
main function:
const std = @import("std");
pub fn main() void {
const process = std.process;
}
dca@franz:/tmp$ zig build-exe --library c testit.zig
/tmp/testit.zig:4:24: error: container 'std' has no member called 'process'
const process = std.process;
^
dca@franz:/tmp$
Based on my tiny knowledge of zig, I would not think going from the
first version to the second would matter. But it does. Why?
/Don
On Sat, 7 Sep 2019 at 10:29, Donald Allen <donaldcallen@gmail.com> wrote:
>> On Sat, 7 Sep 2019 at 09:57, Ben Noordhuis <info@bnoordhuis.nl> wrote:> >> > On Sat, Sep 7, 2019 at 3:23 PM Donald Allen <donaldcallen@gmail.com> wrote:> > >> > > I'm an experienced programmer, including about 10000 lines of Rust.> > > I've just discovered zig and am experimenting with it. But I'm stumped> > > by something as fundamental as reading command line args on a Linux> > > system (Arch; up to date).> > >> > > The only documentation I've found is for wasi, which appears not to be> > > ready yet.> > >> > > So I cloned the zig repository on github and in the file std/os.zig, I find> > >> > > /// Populated by startup code before main().> > > /// Not available on Windows. See `std.process.args`> > > /// for obtaining the process arguments.> > > pub var argv: [][*]u8 = undefined;> > >> > > So in my little experimental program, I've done> > >> > > const std = @import("std");> > >> > > and later> > >> > > const argv = std.os.argv;> > >> > > Trying to compile, I get> > >> > > dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe> > > --library c composite_register.zig> > > /home/dca/Software/newcash_zig/composite_register/composite_register.zig:33:24:> > > error: container 'std.os' has no member called 'argv'> > > const argv = std.os.argv;> > >> > > This brings up two questions:> > >> > > 1. How do you obtain the command line args in a simple zig program on Linux?> > > 2. How do you identify the components of a container? As I mentioned> > > above, the file std/os.zig contains a public variable argv, and yet I> > > get the above error complaining that argv is not "member".> > >> > > Thanks in advance for any assistance.> > >> > > /Don Allen> >> > Hi Don, it sounds like you're looking for std.os.args()? You can find> > a usage example here:> > https://github.com/ziglang/zig/blob/9a18db8a80c96d206297e865d203b2a7d8a803ba/test/cli.zig>> Thanks very much for the help.>> Using your example as a guide, I modified my program like so:> const std = @import("std");>> pub fn main() !void {> const TRANSACTIONS_SQL => \\ select date(post_date), t.num, t.description, t.guid> \\ from transactions t, splits s> \\ where s.account_guid = ?1> \\ and t.guid = s.tx_guid> \\ and date(t.post_date) >= ?2> \\ and date(t.post_date) <= ?3> \\ and description like ?4> \\ order by t.post_date, t.enter_date> ;> const SPLITS_SQL => \\ select account_guid, ifnull(mnemonic,''),> \\ ifnull(memo,''), ifnull(quantity,0.0),> \\ ifnull(value/nullif(quantity,0),0.),> \\ ifnull(value,0.)> \\ from (select s.account_guid, c.mnemonic, s.memo,> \\ s.quantity as quantity, s.value as value> \\ from splits s, accounts a left outer join commodities c> on a.commodity_guid = c.guid> \\ where s.tx_guid = ?1 and a.guid = s.account_guid)> ;> // Get stdout> const stdout_file = try std.io.getStdOut();> // Get the args> const process = std.process;> var arg_it = process.args();> // skip my own exe name> _ = arg_it.skip();> const start_date = try (arg_it.next(std.heap.c_allocator) orelse {> std.debug.warn("Expected first argument to be start_date\n");> return error.InvalidArgs;> });> try stdout_file.write(start_date);> }>> (Ignore the sql. That's for later, if I end up making progress with this.)>> Attempting to compile produces>> dca@franz:~/Software/newcash_zig/composite_register$ zig build-exe> --library c composite_register.zig> /home/dca/Software/newcash_zig/composite_register/composite_register.zig:27:24:> error: container 'std' has no member called 'process'> const process = std.process;> ^> dca@franz:~/Software/newcash_zig/composite_register$>> ????>> /Don
On Saturday, September 7, 2019 4:56 PM, Donald Allen <donaldcallen@gmail.com> wrote:
> I tried a little test program, in /tmp/testit.zig:>> const std = @import("std");> const process = std.process;>> pub fn main() void {> }>> Compiling as I did with my experiment produces no error:>> dca@franz:/tmp$ zig build-exe --library c testit.zig> dca@franz:/tmp$>> I then moved the constant definition of process into the scope of the> main function:>> const std = @import("std");>> pub fn main() void {> const process = std.process;> }>> dca@franz:/tmp$ zig build-exe --library c testit.zig> /tmp/testit.zig:4:24: error: container 'std' has no member called 'process'> const process = std.process;> ^> dca@franz:/tmp$>> Based on my tiny knowledge of zig, I would not think going from the> first version to the second would matter. But it does. Why?
Seems like you are using zig 0.4.0 while looking at the standard library from the git master branch. If I put your example into the Zig Compiler Explorer it indeed fails to compile:
https://zig.godbolt.org/z/5wgHhp
But if you change the "zig 0.4.0" into "zig trunk" in the right-hand pane, it does compile. So the std.process functionality is either newer than 0.4.0 is, or it got renamed in the mean time.
Now, why does it not cause an error when you put const process outside of main? This is because zig only analyses the global declarations that are actually getting used. It sees that the const process toplevel declaration isn't used, so it won't even try to expand it. If you were to actually use the declaration inside of main, the compilation would fail again.
Hope this helps.
Cheers,
heidezomp
On Sat, 7 Sep 2019 at 11:16, heidezomp <heidezomp@protonmail.com> wrote:
>> On Saturday, September 7, 2019 4:56 PM, Donald Allen <donaldcallen@gmail.com> wrote:> > I tried a little test program, in /tmp/testit.zig:> >> > const std = @import("std");> > const process = std.process;> >> > pub fn main() void {> > }> >> > Compiling as I did with my experiment produces no error:> >> > dca@franz:/tmp$ zig build-exe --library c testit.zig> > dca@franz:/tmp$> >> > I then moved the constant definition of process into the scope of the> > main function:> >> > const std = @import("std");> >> > pub fn main() void {> > const process = std.process;> > }> >> > dca@franz:/tmp$ zig build-exe --library c testit.zig> > /tmp/testit.zig:4:24: error: container 'std' has no member called 'process'> > const process = std.process;> > ^> > dca@franz:/tmp$> >> > Based on my tiny knowledge of zig, I would not think going from the> > first version to the second would matter. But it does. Why?>> Seems like you are using zig 0.4.0 while looking at the standard library from the git master branch.
If that's the case, then the issue is with the Arch zig package
maintainer, because I simply installed zig, and the standard library
with it, with pacman.
I will have a look at building zig from the github repository, to try
to eliminate the version skew.
> If I put your example into the Zig Compiler Explorer it indeed fails to compile:>> https://zig.godbolt.org/z/5wgHhp>> But if you change the "zig 0.4.0" into "zig trunk" in the right-hand pane, it does compile. So the std.process functionality is either newer than 0.4.0 is, or it got renamed in the mean time.>> Now, why does it not cause an error when you put const process outside of main? This is because zig only analyses the global declarations that are actually getting used. It sees that the const process toplevel declaration isn't used, so it won't even try to expand it. If you were to actually use the declaration inside of main, the compilation would fail again.>> Hope this helps.
It may have been a big help. I will let you know after trying to build
zig myself.
Thanks --
/Don
>> Cheers,> heidezomp
On Sat, Sep 7, 2019 at 5:24 PM Donald Allen <donaldcallen@gmail.com> wrote:
>> On Sat, 7 Sep 2019 at 11:16, heidezomp <heidezomp@protonmail.com> wrote:> >> > Seems like you are using zig 0.4.0 while looking at the standard library from the git master branch.>> If that's the case, then the issue is with the Arch zig package> maintainer, because I simply installed zig, and the standard library> with it, with pacman.
Sorry, I see now that I linked you to the cli.zig from master (where
it's called std.process.args()) whereas I wanted to link you to the
0.4.0 version (where it's still std.os.args()).
The proper link for posterity:
https://github.com/ziglang/zig/blob/bddbbef32b4a42237ca84352a26a93bf250da918/test/cli.zig
On Sat, 7 Sep 2019 at 11:39, Ben Noordhuis <info@bnoordhuis.nl> wrote:
>> On Sat, Sep 7, 2019 at 5:24 PM Donald Allen <donaldcallen@gmail.com> wrote:> >> > On Sat, 7 Sep 2019 at 11:16, heidezomp <heidezomp@protonmail.com> wrote:> > >> > > Seems like you are using zig 0.4.0 while looking at the standard library from the git master branch.> >> > If that's the case, then the issue is with the Arch zig package> > maintainer, because I simply installed zig, and the standard library> > with it, with pacman.>> Sorry, I see now that I linked you to the cli.zig from master (where> it's called std.process.args()) whereas I wanted to link you to the> 0.4.0 version (where it's still std.os.args()).>> The proper link for posterity:> https://github.com/ziglang/zig/blob/bddbbef32b4a42237ca84352a26a93bf250da918/test/cli.zig
Ah, thanks for clearing that up. Now I understand the confusion.
Switching to std.os.args works a whole lot better with the 0.4
installed by Arch :-)
My little experiment now works.
Thanks to both of you for your help, even if we went down the wrong
road for a bit.
/Don