wrapc
A zero-fuss, type-safe parser for rustc arguments, designed specifically for RUSTC_WRAPPER tools.
Overview
Building tools that intercept Rust compilation (such as compilation caches, custom profilers, static analyzers, or linker-flag injectors) requires parsing rustc's command-line arguments.
However, rustc's CLI is notoriously complex. It mixes = and space-separated values, features intricate sub-syntaxes for linking (-l kind:+modifiers=name:rename), and constantly evolves with new nightly flags. Standard CLI parsers like clap are too rigid and bloated for this specific use case.
wrapc solves this by providing a comprehensive, strongly-typed, and easily extensible parser that perfectly understands the RUSTC_WRAPPER protocol, guaranteeing flawless round-trip reconstruction of arguments.
Features
- Wrapper Protocol: handles Cargo's
<wrapper> - <rustc> <args...>invocation format. - Type-Safe & Comprehensive: Parses complex flags like
--emit,--extern,-L, and-linto structured Rust types instead of raw strings. - Flawless Round-Tripping: The
Info::to_args()method perfectly reconstructs the parsed arguments, ensuring zero data loss when passing them down to the actualrustc. - Lightweight: No heavy macro dependencies or
clap. Just fast, predictable, and extensible string parsing. - Panic-Free: Gracefully handles missing values, unrecognized/nightly flags, and the
--separator without crashing your build pipeline.
Quick Start
Add wrapc to your wrapper tool's dependencies:
The Canonical Wrapper Skeleton
use Command;
use fetch;
Deep Dive: Complex Flags
rustc's linking flags are highly structured. wrapc parses modifiers, kinds, and renames automatically so you don't have to write regexes.
use ;
// Example invocation:
// rustc -L native=/opt/lib -l static:+bundle,+whole-archive=mylib:renamed
for lib_path in &info.libpaths
for link in &info.links
The RUSTC_WRAPPER Protocol & Edge Cases
When Cargo invokes a wrapper, it uses a specific protocol:
<wrapper_binary> - <actual_rustc_path> <rustc_args...>
wrapc automatically strips the first three arguments and stores the real compiler path in info.rustc.
The stdin Edge Case
Tools like cargo or IDEs sometimes pass - as the input file to tell rustc to read source code from stdin. Because Cargo's wrapper protocol also uses - as a separator, naive parsers break here. wrapc handles this contextually:
// Invocation: `my_wrapper - rustc -`
let info = fetch.unwrap;
assert_eq!;
assert_eq!; // Correctly identified!
Unrecognized / Nightly Flags
If a user passes a brand-new nightly flag that wrapc hasn't explicitly modeled yet, it won't crash. It safely buckets it into info.unknown and perfectly preserves it during to_args() reconstruction.
Testing Your Wrapper
To test your wrapper locally without publishing it, use the RUSTC_WRAPPER environment variable:
# Build your wrapper
# Point Cargo to your wrapper
# Run a standard cargo command
Contributing
Contributions, issues, and feature requests are welcome!
If you notice a missing rustc flag that should be explicitly modeled rather than falling back to unknown, please open an Issue or Merge Request on GitLab.
License
This project is licensed under the MIT License.
Made with ❤️ for Rust community.