`--locked` status at compile time

I'm including build metadata in my binaries --version output to help with debugging. The vergen crate(s) have been very helpful with this.

What I haven't figured out is how to know whether the binary was built with or without --locked. Is there some env variable that rustc/cargo sets? I have tried searching but clearly I don't know the correct words to use to find what I need.

The closest approximation I have so far is using the git dirty status as a proxy, under the assumption that the lockfile gets updated if run without --locked.

You can find all the environment variables cargo reads or sets here:

https://doc.rust-lang.org/cargo/reference/environment-variables.html

I don't see an environment variable that'd contain the information whether Cargo built with --locked or not.

Thanks, yeah it seems that none of those contain that information unfortunately.

You might be interested in
https://crates.io/crates/cargo-auditable

1 Like

Why exactly do you need to know of --locked-ness?

By the time the build is running, the resulting .lock file must, by definition, be a working one, which you can and probably should encode in this metadata.

The only other usage I can see would be to perform the "compression" of just storing a commit revision, and hoping the .lock file at that revision is indeed the one you are using. In which case, your "closest approximation" of looking for a clean git status is rather exactly what you need to do.

1 Like

I think it would be useful to know when evaluating a bug report. Ideally I want the users to run with --locked but it would be nice to know for sure they have or haven't. One could even go a step further and abort compilation without it set, or warn loudly on startup.

With the git status I'm also unsure of the order of operations - will that diff be available by the time my build script runs? Probably; but it seems rather hacky. It also doesn't test for the absence/presence of --locked, only the potential side-effect of leaving it out.

I'm mostly just surprised this isn't exposed at all.

If someone runs without --locked and then after the error runs again with --locked, the lockfile would still have been updated if it was outdated and thus the second build would succeed even if the lockfile was originally outdated, which would have the same result as the initial build not erroring out when --locked misses.

The thing is, as bjorn mentioned, that --locked is a guarantee that applies only to the very latest cargo invocation:

So, for instance, one of your users could run:

  1. cargo update -w after having updated their .toml constraints;

    or even just cargo update directly to bump the .lock file versions as high as possible.

  2. and only then run the cargo check/build --locked command, which is the (only) context that your build.rs gets to see.

As shown in the diagram, this means that your build.rs would witness a --locked invocation, but without this guaranteeing that the .lock file state matches the expected one / that of the reference point.


Hence the question about said "reference point": what is it in your case? You mention checking for git status, so I am tempted to think it's indeed a specific git revision, rather than just a specific file value, checksum or whatnot.

Be it as it may, the only way to ensure the .lock file hasn't been mutated since is then, well, by checking that directly; do not try to rely on --locked. So if it was a given file value, checksum, or whatnot, check that the new checksum matches the expected one, for instance, and if it is a specific git revision, checking for git status —if the build environment is that of said git repository!— is then indeed the right thing to do :slightly_smiling_face:

1 Like

Thanks I understand its pretty much impossible to guarantee anything here. However I am surprised that its this cumbersome to get at least some information out in a uniform manner.

Local builds one can handle using some variation of git describe --tags --dirty. This however falls apart for cargo install where all you can access is the SHA from the vcs json file. In particular --locked would be helpful here.

I know fully reproducible builds aren't really there yet for rust, but I was hoping one could at least confirm source and dependency versions.

Ah, that was my missing context! Yeah, for cargo install it is sensible to want to know whether the install was done with --locked or not. You could try running cargo metadata, but I don't know what its behavior is when used from the build.rs of a cargo installed package :person_shrugging:

cargo metadata requires --locked to be passed in so its essentially going to re-evaluate the dependency graph independently from the build process if I were to guess.

Could be useful to extract the dep graph but that would require somehow passing in the exact same configuration as the build received.

One way to detect the locked, or more generally lock file, status of a project would be to publish a library which exports a constant that varies with version:

  • 1.0.0: pub const LOCKED: bool = false;
  • 1.0.10: pub const LOCKED: bool = true;
  • 1.0.20: pub const LOCKED: bool = false;

Then publish your binary package with a lockfile pointing to version "1.0.10" of this, and if it sees anything else, it knows it wasn't built with an unaltered lock file.

The disadvantage of this strategy is that you have to revert the dependency in your own project after every cargo update.

1 Like

This is going to sound a little silly, but what if you include_str! the lock file and then add a cli option to dump that for a bug report?

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.