Get cmd arguments from proc_macro library

I want to get the arguments that are provided to the executable that uses the proc_macro library. For example, when you run:

cargo run -- -f 69

And you want to get the -f 69 args in proc_macro library, in its sort of runtime, because you need to perform some operations at compile time with them.

When you try to get them using std::env::args(), you get the following output:

[".../bin/rustc", "--crate-name", "flag", "--edition=2021", "main.rs", "--error-format=json", "--json=diagnostic-rendered-ansi,artifacts,future-incompat", "--crate-type", "bin", "--emit=dep-info,link", "-C", "embed-bitcode=no", "-C", "debuginfo=2", "--check-cfg", "cfg(docsrs)", "--check-cfg", "cfg(feature, values())", "-C", "metadata=0da2a10f35a01285", ... and so on]

There's no -f 69.

And you can't just call std::env::args() in your main program and pass that. The context of using the library is attribute macros:
#[flag("-f", "--flag", mandatory, help("test"), type("u64"))]

The arguments after -- are passed to your executable. This implies that compilation must already have finished by the time they are even considered, and can't be accessed in a proc-macro.

You should probably set an environment variable instead.

1 Like

Yeah, probably that's the only way, thank you. Maybe I can set the env variable at comptime somehow.. I'll have to think about that.

There's nothing special about that. There's no such thing as "setting an environment variable at compile time". Once you set an env var, it's set. You just set it before building, and every process (including rustc) in the current shell will see it.

You misunderstood me, I mean get passed flags in the main program and set variable for them somehow, so you don't have to do FLAGS="-f 69" cargo run every time

Wait hold on, am I understanding the ask correctly?:

You want cargo to compile your executable differently depending on what argument you are going to send to your executable - after it's compiled?

e.g.

cargo run -- -f 69
// Compile, oh and btw f is 69
// Finish compiling, you now have an f=69 executable 
// Run executable... And pass f=69 as an argument to it

May I ask why?

Long story short: I have one runtime application that uses my flags library, and another runtime that runs my proc_macro library, that's just work it works in rustc. I have an experimental idea to parse provided flags and based on them, generate global constants in your file, therefore, allowing for more flexible usage.

I see, so you are planning on recompiling the application binary on each invocation. Presumably for your personal use and/or just an experiment.

As an end user (say if I were to use your library/application), it would be inconvenient to require recompiling each time I used it. So, in general, what you're attempting seems inflexible and basically a bad idea.

Having said that, I think a wrapper script might be simplest.

So you run your script:

wrapper -f 69

Which internally runs:

FLAG_f=69 cargo run -- -f 69

And you can access the flag at compile time via the environment variable FLAG_f

I leave the implementation as an exercise for you.

The problem with actually passing -f to cargo run is that it will reject it as an unrecognised argument (maybe, -f might happen to do something in cargo, but in general it can be a problem for arbitrary flags, let alone the issues with changing cargo's behaviour)

You could look into cargo subcommands for aesthetics, but please don't publish this to crates.io - it is unhelpful for general use.

I still don't understand why you'd want you to do this. At all. Other than to understand how it could be done.

In terms of "if only my args were globals... ???"

You should use OnceCell for that. It should not be done at compile time because arguments are inherently dynamic, and compiling is slow.

1 Like

Even if this idea is dumb as fuck, I will still be the only person to decide whether to publish it on crates.io or not. Thank you for your commitment, drmason13. Eventually, decided to redesign this whole thing and not to do that, can I now post on crates.io, mister mason, please?...

Of course you can post on crates.io, you're free to do what you like. Just as I am free to ask you not to :stuck_out_tongue_closed_eyes:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.