Detect dependency graph from build.rs?

Is there a way to detect the crate dependency graph or, at the least, which crates depend on the current crate, from a build.rs script?

Why would Cargo need to know which crates depend on the current crate rather than dependencies of the current crate?

Because Cargo doesn’t currently support internal-only crates, but I want to simulate it by having build.rs fail if a crate outside of a whitelist tries to depend on my internal crate.

What exactly do you mean by internal-only crate?

It is possible to define multiple crates in the same git repo, and to have those crates refer to one another e.g. with path dependencies.

A crate which, while published on crates.io, can only be depended on by a whitelist of crates, such that cargo would fail the build if a crate outside of that whitelist took a dependency on the internal crate.

It isn’t, unfortunately. The only way to publish on crates.io is for each crate to be published as a normal crate. There’s no way to publish a crate which packages another crate inside of itself.

That seems like an anti-pattern to me TBH. In general code units of any size (types, modules, crates) shouldn’t care what they are used by, as doing so breaks modularity and introduces tight coupling.

So I’m curious: why do you want/need that?

It is true that when publishing on crates.io, crates are not allowed to have path dependencies.
But that is no restriction, in fact it’s even more reason to keep your crates as loosely coupled as possible.
That way, you can just publish each crate and do dependency specification by version as normal, rather than by path.

We’ve been bitten in the past by us documenting that certain functionality is internal and should not be considered stable, and yet people have taken dependencies and then gotten mad when we made changes since those changes broke their code. We’d like to make it so that “internal” isn’t just a suggestion, but is enforced by the build.

True, but that doesn’t address the need that we have.

As far as I know Cargo doesn’t support this kind of tight coupling, and I will argue any day that it shouldn’t encourage workflows which are brittle.

However, to address your immediate concern, you can always add a nasty hack:
Have the build script of crate D check a certain env var (e.g. MY_SUPERLONG_FANCY_ENV_VAR_NOBODY_WILL_GUESS), which must be set by the consumer crate C in its build script. Crates that are not intended consumers won’t have the env var set, and thus crate D will fail to build.

FTR: This is awful Rustacean citizenship, so don’t post crates with this to crates.io. And that’s assuming it would even allow you to publish a crate like that in the first place.

On another note, you should consider that anything that you publish will in fact be public i.e. people can do with it whatever they want. If that is not desired, then publishing is probably not what you want.
In particular, if you specify that the crate is unstable (i.e. by making the version less than 1.0.0) then anything in terms of instability is fair game. Getting mad at you for that is as useful as getting angry at rain for raining.

AFAIK the only means for that is emitting cargo:rustc-env=..., which will only affect your own crate.

Personally, I’d just stick to a social contract. Add #[doc(hidden)] and maybe even a #[deprecated] message, and I think you have every right to push back against folks who use it anyway.

There is always the env stdlib module.

That only affects the current process and any future subprocesses.

Oh. Well, then the same idea could be executed with lockfiles I suppose :slight_smile: