cargo
cargo copied to clipboard
Access target triplet of artifact from proc macros
Problem
I'm writing a proc macro that generates code based on the operating system for which the library/executable is being compiled. This macro generates OS specific code for windows/linux/macos/android. Currently there is no way of finding out which operating system we are compiling for (from a proc macro).
Proposed Solution
Some way of accessing the target triplet from a proc macro.
Notes
cfg(target_os="windows") returns true on windows even if compiling for android.
A complication to exposing the target triplet is that I believe we build proc macros and build scripts once for the host, independent of which target platform is currently selected.
I think if the environment variable is only set while building a crate (which uses a proc-macro), then the proc-macro would only have access to it at runtime, and thus the concern of using env! when building the proc-macro wouldn't be a problem.
I would recommend, if possible, to generate the code for all targets, and include #[cfg(…)] attributes in the generated output to select the appropriate target.
I don't think this is a decision that should be driven just by the Cargo team in isolation. This may benefit from a broader consideration from other teams like the libs, lang, or compiler teams, as this relates to the experience for how proc-macro authors write their code.
An example of an alternate approach would be to have this as part of the proc-macro API (similar to tracked_env and tracked_path) where rustc itself could provide this information (like proc_macro::target() -> Target or whatever). rustc already knows the target information.
Another consideration is if it is a good idea to key of the target triple string. My opinion is that it is a bad idea, and code should instead use the target cfg values (family, os, arch, vendor, etc.). Triples can change over time or have unexpected naming conventions, and custom JSON targets have arbitrary names. I think matching on the cfg-specific rules is more precise and reliable. That is also something the proc_macro API could provide (like returning a struct with all this information).
I would absolutely love if the proc_macro crate provided the info about the target to the proc-macro in a structured, programatic way, rather than checking environment variables.
Cargo sets the TARGET env variable when running the build script.
It would be nice if that env variable was also set when invoking rustc.
That way the proc macro code can do something depending on the result of std::env::var("TARGET") just like build script can already do.
Is there a reason why "TARGET" is not defined when running rustc?