The exact size of the `windows` crate depends on feature flags, because parsing 2.2M lines of code is always going to be very expensive even when you immediately discard them.
The parser is shockingly fast. The slow parts come after parsing, where we process all those function definitions and structure definitions, only to end up throwing 98% of them away.
A challenging architectural problem that several of us are trying to get someone nerdsniped into: inverting the dependency tree, such that you first check what symbols exist in a large crate like windows, then go to all the crates depending on it and see what they actually consume, then go back and only compile the bits needed for those symbols.
That'd be a massive improvement to compilation time, but it's a complicated change. You'd have to either do a two-pass compilation (first to get the symbol list, then again to compile the needed symbols) or leave that instance of the compiler running and feed the list of needed symbols back into it.
Agreed, though by "parsing" I meant to include easy steps like cfg checks. In fact, cfg checks should probably be done at the same time as parsing and disabled items should be discarded as soon as possible---though I don't know whether that is already done in the current compiler, or whether it's beneficial or even possible at all.
We do some parsing "underneath" disabled cfg checks, in order to support user-friendliness features like "that function you tried to call doesn't exist, but if you enabled feature xyz then it would". But we do discard cfg-protected items before doing any subsequent heavier operations.