# External dependencies in declarative format

**URL:** <https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372>\
**Category:** cargo\
**Created:** [February 5, 2019, 9:11pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372 "2019-02-05T21:11:36Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![ignatenkobrain](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ignatenkobrain/32/3140_2.png) [@ignatenkobrain](https://internals.rust-lang.org/u/ignatenkobrain)\
**Post date:** [February 5, 2019, 9:11pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/1 "2019-02-05T21:11:36Z")

</div>

Hello from Fedora maintainer of over 500 crates!

We are working on a way to generate our RPM packages more automatically. The only problem (hopefully) which persists from cargo side is external dependencies.

For example, there is glib-sys crate which checks for the glib on the system using pkg-config. Depending on a activated feature, different version of it.

There was a project [https://github.com/joshtriplett/metadeps](https://github.com/joshtriplett/metadeps), but it seems to be pretty much dead.

It would be cool if that info could be stored inside Cargo.toml in some standardized way. How can we help with that?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 5, 2019, 11:40pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/2 "2019-02-05T23:40:34Z")

</div>

The way to do it would be to write up and submit a Cargo [RFC](https://github.com/rust-lang/rfcs) for the feature. Bonus points if you have a working prototype.

A more quickly actionable solution is to build a [Cargo subcommand](https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands) and petition some of the packages you package to use it. If it’s better than what they’re doing currently, they’ll probably consider using it. And if it gains popularity, that’s some weight behind adding it to Cargo directly.

IIRC (can’t find the reference to it), the `[package.metadata]` table in `Cargo.toml` is free to be whatever, and Cargo-integrated tools are encouraged to put package metadata there.

Cargo’s future is [a little rough](https://www.ncameron.org/blog/cargos-next-few-years/) right now. But if you build something good and properly useful (and that works at least on all tier-1 platforms), people will (hopefully) use it.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 5, 2019, 11:48pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/3 "2019-02-05T23:48:17Z")

</div>

Cargo-deb has an interesting hack for this problem: it runs `ldd` on the produced executables to find which dynamic libraries they actually use, and queries dpkg to find which packages provide these libraries. This bypasses Cargo entirely and doesn’t require knowing anything about any build scripts, configurations, features, etc.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [February 6, 2019, 6:48am UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/4 "2019-02-06T06:48:35Z")

</div>

> [@CAD97](#):
>
> The way to do it would be to write up and submit a Cargo [RFC](https://github.com/rust-lang/rfcs) for the feature. Bonus points if you have a working prototype.

The metabuild RFC/project is exactly that: [Unstable Features - The Cargo Book](https://doc.rust-lang.org/cargo/reference/unstable.html#metabuild)

I think the idea behind it is great: instead of many build scripts for various projects, you have a single build script parametrized by information from Cargo.toml.

The way forward is perhaps making the metabuild ready for the use, and sending PRs to a couple of projects, replacing their custom build scripts with metabuild.

If the approach is proven to work, Cargo docs could officially recommend using a metabuild.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [February 6, 2019, 6:51am UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/5 "2019-02-06T06:51:26Z")

</div>

One clarification: the metabuild feature in Cargo is absolutely not required for using metabuild project. The feature is a cosmetic thing, which allows you to not write build.rs at all. Without it, need a trivial build.rs file which just calls metabuild::main()

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 6, 2019, 8:52am UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/6 "2019-02-06T08:52:30Z")

</div>

metadeps isn’t dead so much as done in its current state, dormant and waiting on metabuild to improve further. With metabuild now available in cargo, we should start writing metabuild-enabled crates that incorporate metadata from `Cargo.toml`.

Another option: with [https://github.com/rust-lang/rfcs/pull/2627](https://github.com/rust-lang/rfcs/pull/2627) we could have crates that build against shared libraries without needing those libraries installed at build time. (We’d still need to generate the runtime dependencies for the package, though.)

---

<div class="post-metadata">

**Author:** ![ignatenkobrain](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ignatenkobrain/32/3140_2.png) [@ignatenkobrain](https://internals.rust-lang.org/u/ignatenkobrain)\
**Post date:** [February 6, 2019, 8:55am UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/7 "2019-02-06T08:55:49Z")

</div>

> [@josh](#):
>
> metadeps isn’t dead so much as done in its current state, dormant and waiting on metabuild to improve further. With metabuild now available in cargo, we should start writing metabuild-enabled crates that incorporate metadata from `Cargo.toml` .

Can you merge Pull Requests and fix Issues then? I probably don't fully understand how this metabuild thing works. Do you have some example how it would be potentially integrated with pkg-config dependencies?

> [@josh](#):
>
> Another option: with [#[link(kind="raw-dylib")] by retep998 · Pull Request #2627 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/2627) we could have crates that build against shared libraries without needing those libraries installed at build time. (We’d still need to generate the runtime dependencies for the package, though.)

That would be awful because it would be impossible to do any checking for undefined symbols or so during build.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 6, 2019, 9:38am UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/8 "2019-02-06T09:38:00Z")

</div>

> [@ignatenkobrain](#):
>
> Can you merge Pull Requests and fix Issues then?

Working on that now, thank you. Sorry that I lost track of those.

> [@ignatenkobrain](#):
>
> I probably don’t fully understand how this metabuild thing works. Do you have some example how it would be potentially integrated with pkg-config dependencies?

metabuild would let you use crates like metadeps without writing a `build.rs` at all. The goal is to standardize almost every common use of `build.rs` into a crate that reads declarative metadata.

> [@ignatenkobrain](#):
>
> That would be awful because it would be impossible to do any checking for undefined symbols or so during build.

The linker can check for undefined symbols, but it can't (for instance) check for defined symbols with different interfaces, or any number of other issues.

The idea would be that the _test suite_ needs the library present, but building the crate doesn't.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 6, 2019, 5:09pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/9 "2019-02-06T17:09:36Z")

</div>

There’s a problem semi-related to this I’m interested in: many `*-sys` crates look for if the system dependency is available in `build.rs`, and if it’s not, do wacky things like use `git2` to clone a repo.

It’d be nice to have a reproducible, declarative alternative to that for optional build artifacts, e.g. “fetch this tarball over HTTPS and ensure its SHA-256 digest is X, or clone this get repo and set HEAD to commit Y”

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 6, 2019, 5:30pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/10 "2019-02-06T17:30:35Z")

</div>

I usually recommend crates to bundle the source instead of downloading it. The sources usually aren’t that big, and having them in the crate solves all the problems of matching versions, downloading, verifying, cleaning up, etc.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 6, 2019, 6:41pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/11 "2019-02-06T18:41:27Z")

</div>

Then whatever tool it is should probably provide a guide on adding a simple submodule for the bundled source (and/or best practices for just having the source in `/vendor` or smth).

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [February 8, 2019, 8:53pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/12 "2019-02-08T20:53:15Z")

</div>

> [@kornel](#):
>
> I usually recommend crates to bundle the source instead of downloading it.

Yeah, that's a great point. One alternative to having the build script use `git2` to fetch the code is using a git submodule in the original project (for easy updates), but when the crate is published, it can include the sources from the submodule directly in the published crate.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 8, 2019, 11:20pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/13 "2019-02-08T23:20:47Z")

</div>

Yes. Fortunately git submodules work out of the box and automatically become regular directories in the published package.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [May 9, 2019, 11:20pm UTC](https://internals.rust-lang.org/t/external-dependencies-in-declarative-format/9372/14 "2019-05-09T23:20:50Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
