Skip to content

Richer argument handling for compilers#277

Closed
aidanhs wants to merge 9 commits intomozilla:masterfrom
aidanhs:aphs-dist-sccache-rust-args
Closed

Richer argument handling for compilers#277
aidanhs wants to merge 9 commits intomozilla:masterfrom
aidanhs:aphs-dist-sccache-rust-args

Conversation

@aidanhs
Copy link
Contributor

@aidanhs aidanhs commented Aug 22, 2018

This now correctly pulls apart arguments like rustc -l static=a into their constituent parts at parse time. There should be no functional changes in this PR.

This is the majority of the major argument handling rework I mentioned, pulled out of the rust distributed work for ease of review. Each of the commits can be considered in isolation.

Should be reviewed after #274 (or just examine the commits after the scheduler auth one).

type ArgResult<T> = StdResult<T, ArgError>;

#[derive(Debug, PartialEq)]
pub enum ArgError {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we finish merging all of your work my first order of business is to switch from error-chain to failure. 😃

UnknownFlag(OsString),
/// Known flag argument ; e.g. "-bar"
Flag(&'static str),
Flag(&'static str, T),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took me a lot more code reading to figure out why Flag needed to store the additional value here. I think the comment above Argument<T> could stand an additional sentence or two explaining what the type parameter is used for.


/// Helper macro used to define ArgInfo::Flag's.
/// Variant is an enum variant, e.g. enum ArgType { Variant(()) }
/// flag!("-foo")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed the single argument macro rule below, so the comment here should be removed as well.

Coverage,
ArgData!{ pub
TooHardFlag(()),
TooHard(OsString),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little awkward, but it's not really terrible.

SplitDwarf(()),
ProfileGenerate(()),
TestCoverage(()),
Coverage(()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if it's feasible, but it would be nicer if the macro could take $x:ident without a type and handle it as ().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To answer my own question: I don't think it's possible with current stable Rust. RFC 2298 adds a ? repetition operator to macros which would make this feasible. This code works on Nightly (although I couldn't get it to work on the playground for some reason):
https://gist.github.com/luser/0284cecdec8f7a2f789e37ffc52f963e

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it needed Edition: 2018 to work on the playground. (My local nightly is a few months out of date.)


for item in ArgsIter::new(it, arg_info) {
for arg in ArgsIter::new(it, arg_info) {
let arg = try_arg!(arg.map_err(|e| e.static_description()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to have this same map_err clause in all the places you use try_arg!, so why not just bake it into the macro?

ArgData!{
TooHardFlag(()),
TooHard(OsString),
TooHardPath(PathBuf),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we don't really need the argument for TooHardPath, can we just drop this and use TooHard(OsString) for those arguments?

Further musing has me wonder if we could combine them all into TooHard(Option<OsString>) and just impl the right traits for Option<OsString>.

Ok(T),
/// Cannot cache this compilation.
CannotCache(&'static str),
CannotCache(&'static str, Option<String>),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this buy us a whole lot? Do we wind up with anything but "failed to parse argument value" in the second field? I have a WIP patch for #263 that saves counts of the CannotCache reasons in the server stats. I don't think this change will be a problem for it, but I'm not sure how I'd expose this new field.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think you're inverting the way you're looking at this - "argument parse" is the consistent value that always gets put in the first field (exactly because of the cannotcache reason counting), but it didn't seem ideal to just throw away all nuance of that. Specifically, take a look at ArgParseError - Display creates a description of what went wrong with what part of the argument, which isn't possible in the bounds of a static string. This nice description will get printed in the logs.

@@ -72,7 +72,7 @@ pub struct RustHasher {
#[derive(Debug, Clone, PartialEq)]
pub struct ParsedArguments {
/// The full commandline, with arguments and their values as pairs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the comment here to match?

let toolchain_creator = Box::new(RustCompilerPackager { sysroot: sysroot.clone() });
let mut arguments = arguments;
// Always request color output, the client will strip colors if needed.
arguments.push(Argument::WithValue("--color", ArgData::Color("always".into()), ArgDisposition::Separated));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be simpler to move this into generate_compile_commands? I don't remember exactly why I put it here in the first place.

let me = *self;
let RustHasher { executable, sysroot, compiler_shlibs_digests, parsed_args: ParsedArguments { arguments, output_dir, externs, staticlibs, crate_name, dep_info, color_mode: _ } } = me;
trace!("[{}]: generate_hash_key", crate_name);
// TODO: this doesn't produce correct arguments if they should be concatenated - should use iter_os_strings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this fixed in a followup? If not, will this cause problems in practice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will observe that this behaviour has always been the case (it's just being flagged now) so I suspect in practice it does not cause issues :)

// If no kind is specified, the default is dylib.
(name, None) => ("dylib".to_owned(), name),
};
Ok(ArgLinkLibrary { kind: kind, name: name })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this could just be { kind, name }.

}

#[derive(Clone, Debug, PartialEq)]
struct ArgLinkLibrary {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these could stand to have a one-line descriptive comment, like "Represents -l [KIND=]PATH link arguments to rustc".

// auto-added for target json discovery
return Ok(ArgTarget::Unsure(arg))
}
// The file doesn't exist so it can't be a path, safe to assume it's a name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we'd be better off running rustc --print=target-list in the initial compiler detection and matching against that?

}
Some(LinkLibrary(ArgLinkLibrary { kind, name })) => {
if kind == "static" {
static_lib_names.push(name.to_owned())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could presumably push this logic down into hash generation now, since the arguments there will have enough context. (It's not a big deal, though.)

Copy link
Contributor

@luser luser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a number of comments, but I don't think any of them need to block merging. Feel free to merge this once you rebase and merge the previous PR.

@aidanhs aidanhs force-pushed the aphs-dist-sccache-rust-args branch 2 times, most recently from 5583ead to 7127eaf Compare August 30, 2018 02:18
@aidanhs
Copy link
Contributor Author

aidanhs commented Aug 30, 2018

I suddenly felt motivated, so I implemented a better macro that allows enum variants without data. It was actually nowhere near as bad as I thought it was going to be (which was why I avoided it originally).

@aidanhs aidanhs force-pushed the aphs-dist-sccache-rust-args branch from 7127eaf to b72bccc Compare August 30, 2018 08:40
PassThrough(OsString),
PassThroughPath(PathBuf),
PreprocessorArgumentFlag(()),
PreprocessorArgumentFlag,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's much nicer! I fiddled with this for a bit but couldn't find a working solution except with the unstable ? macro repetition operator.

@luser
Copy link
Contributor

luser commented Aug 30, 2018

The AppVeyor failures look to be network failures, but the stable and beta builds were successful so I'm going to merge this anyway.

@luser
Copy link
Contributor

luser commented Aug 30, 2018

Rebased locally and merged: 105ab91...080e1a7

@luser luser closed this Aug 30, 2018
tottoto pushed a commit to tottoto/sccache that referenced this pull request Feb 6, 2026
Co-authored-by: Lucio Franco <luciofranco14@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants