# How about changing \[lib\] to \[\[lib\]\], to allow multiple library in a crate?

**URL:** <https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022>\
**Category:** cargo\
**Created:** [May 13, 2015, 3:20am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022 "2015-05-13T03:20:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ceram1](https://avatars.discourse-cdn.com/v4/letter/c/ecd19e/32.png) [@ceram1](https://internals.rust-lang.org/u/ceram1)\
**Post date:** [May 13, 2015, 3:20am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/1 "2015-05-13T03:20:52Z")

</div>

Currently cargo does not support multiple library in a crate. So… you need to create a new project like [Subproject: regex\_macros](https://github.com/rust-lang/regex/tree/master/regex_macros)[Subproject: phf](https://github.com/sfackler/rust-phf)[Other repo: postgres\_macros](https://github.com/sfackler/rust-postgres-macros)

and use with

```rust
[dependencies]
regex = "*"
regex_macros = "*"

```

But what if cargo supports multi-lib crate, you can do like this

```rust
# in regex crate
[[lib]]
name = "regex"

[[lib]]
name = "regex_macros"
path = "src/syntax_ext/lib.rs"

```

and use with

```rust
[dependencies]
regex = "*"

```

```rust
#![plugin(regex_macros)]

extern crate regex;

```

---

<div class="post-metadata">

**Author:** ![alexcrichton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alexcrichton/32/4501_2.png) [@alexcrichton](https://internals.rust-lang.org/u/alexcrichton)\
**Post date:** [May 13, 2015, 4:13am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/2 "2015-05-13T04:13:21Z")

</div>

This was initially considered when designing cargo, but we chose to only allow one for a variety of reasons:

- If there are two libraries, how do you select only one to build if you don’t want both?
- Encouraging separate projects for each crate means dependencies are generally more re-usable than if they were bundled together. Crates which want to provide multiple libraries almost always end up getting large enough that they should be separated anyway as well.
- With multiple libraries in one package there would need to be a method of specifying dependencies amongst them.
- A number of features have been added after-the-fact which have made multiple libraries tricky. For example, if a package has a build script, how does it know which crate to link the native libraries into?

I think I may be forgetting some reasons as well, and @wycats may be able to add some in too.

---

<div class="post-metadata">

**Author:** ![wycats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/wycats/32/473_2.png) [@wycats](https://internals.rust-lang.org/u/wycats)\
**Post date:** [May 14, 2015, 5:28am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/3 "2015-05-14T05:28:20Z")

</div>

> [@alexcrichton](#):
>
> I think I may be forgetting some reasons as well, and @wycats may be able to add some in too.

You got the crux of it in your list. For me, mapping `extern crate` declarations directly (in most cases) to a crate in [crates.io](https://crates.io) won the day.

If [crates.io](http://crates.io) crates had multiple Rust crates, we would have to (1) educate people about the semantic gap, and (2) provide a way to do the mapping in the `Cargo.toml`, which every user of the crate would need to do.

The alternative, having package authors break up their libraries into multiple [crates.io](https://crates.io) crates, which we made very ergonomic by supporting multiple crates in a single git repo, seems like a small price to pay to maintain the simplicity of `extern crate` mapping.

---

<div class="post-metadata">

**Author:** ![gsingh93](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gsingh93/32/6884_2.png) [@gsingh93](https://internals.rust-lang.org/u/gsingh93)\
**Post date:** [May 17, 2015, 4:39am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/4 "2015-05-17T04:39:50Z")

</div>

What if we added package groups, where adding a dependency on the group adds a dependency on all the packages in the group. I’m thinking of something similar to Arch Linux’s package system (i.e. you can install individual packages in a group or the entire group itself).

---

<div class="post-metadata">

**Author:** ![ceram1](https://avatars.discourse-cdn.com/v4/letter/c/ecd19e/32.png) [@ceram1](https://internals.rust-lang.org/u/ceram1)\
**Post date:** [May 17, 2015, 1:35pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/5 "2015-05-17T13:35:25Z")

</div>

If there are two libraries, how do you select only one to build if you don’t want both?

- Build only `extern crate`ed library

Encouraging separate projects for each crate means dependencies are generally more re-usable than if they were bundled together. Crates which want to provide multiple libraries almost always end up getting large enough that they should be separated anyway as well.

- Please see [rust\_postgres\_macros](https://github.com/sfackler/rust-postgres-macros) and [rust-peg](https://github.com/kevinmehall/rust-peg).
- rust-peg use

` [[bin]] name= “peg”

[lib] name = “peg\_syntax\_ext” `

With multiple libraries in one package there would need to be a method of specifying dependencies amongst them.

- Proposal usage: `#![plugin(plugin1)] extern crate lib1; extern crate lib2;`
- OR limit max one ‘runtime library’ per crate,

A number of features have been added after-the-fact which have made multiple libraries tricky. For example, if a package has a build script, how does it know which crate to link the native libraries into?

- By using ‘build’ attribute in ‘lib’ & ‘bin’?
- But as this can break project structure, maybe ‘/build\_src/scriptname.rs’?

---

<div class="post-metadata">

**Author:** ![brson](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/brson/32/5197_2.png) [@brson](https://internals.rust-lang.org/u/brson)\
**Post date:** [May 18, 2015, 10:46pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/6 "2015-05-18T22:46:42Z")

</div>

I would like for bins and libs to behave the same. I don’t see any particular reason the restrictions and rules around both are different, and I find it frustrating that I have to contort my build setup around them.

Right now my multi-lib, multi-bin project is set up very awkwardly, with all bins sharing deps and being in my top-level project, and all libs being sub-projects. This feels very unnatural.

---

<div class="post-metadata">

**Author:** ![mitsuhiko](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mitsuhiko/32/379_2.png) [@mitsuhiko](https://internals.rust-lang.org/u/mitsuhiko)\
**Post date:** [May 19, 2015, 10:38am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/7 "2015-05-19T10:38:26Z")

</div>

I have to agree with brson here. There are legitimate reasons to have multiple libs in a crate and it’s generally something that is supported by other systems out there as well.

---

<div class="post-metadata">

**Author:** ![alexcrichton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alexcrichton/32/4501_2.png) [@alexcrichton](https://internals.rust-lang.org/u/alexcrichton)\
**Post date:** [May 19, 2015, 5:07pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/8 "2015-05-19T17:07:03Z")

</div>

@brson and @mitsuhiko, I definitely agree that there are use cases for having multiple libraries, but what I and @wycats were saying is that there are also good reasons to split them up across projects and maintain them separately. This gets the benefit of simplifying `Cargo.toml`, dependency structure within a package, and a 1:1 mapping of `extern crate` to “crate on [crates.io](http://crates.io)”. As @wycats pointed out we also made it quite nice to have multiple libraries in a repository.

Do you two feel that these benefits of requiring only one library are outweighed by the desire to have more than one library in a package?

---

<div class="post-metadata">

**Author:** ![brson](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/brson/32/5197_2.png) [@brson](https://internals.rust-lang.org/u/brson)\
**Post date:** [May 19, 2015, 10:27pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/9 "2015-05-19T22:27:24Z")

</div>

@alexcrichton If maintaining a 1:1 mapping between libraries and packages is important, than I would like to at least be able to use _that same strategy_ for mapping my bins to Cargo.toml. As it is I have to manage my libs by putting them in their own projects and my bins by putting them in one single project. If I could just put _every artifact_ in its own project, and so treat them consistently, I would be happier. I would be doubly-happier if the metadata for those subprojects could be inferred instead of typed explicitly.

---

<div class="post-metadata">

**Author:** ![huon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/huon/32/3698_2.png) [@huon](https://internals.rust-lang.org/u/huon)\
**Post date:** [May 20, 2015, 6:26am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/10 "2015-05-20T06:26:48Z")

</div>

You can put every artifact in its own project; AFAIK, there’s nothing stopping one having a single package per binary?

---

<div class="post-metadata">

**Author:** ![mitsuhiko](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mitsuhiko/32/379_2.png) [@mitsuhiko](https://internals.rust-lang.org/u/mitsuhiko)\
**Post date:** [May 20, 2015, 6:31pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/11 "2015-05-20T18:31:26Z")

</div>

Honestly I’m not sure. The main reason this comes up are macros I think, and there it’s not quite clear what is to be gained from that being in a separate crate. However I understand the motivation.

---

<div class="post-metadata">

**Author:** ![seanmonstar](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/seanmonstar/32/36_2.png) [@seanmonstar](https://internals.rust-lang.org/u/seanmonstar)\
**Post date:** [May 20, 2015, 7:35pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/12 "2015-05-20T19:35:28Z")

</div>

Macros being in a separate crate is important. These macros (syntax extensions) require pulling in rustc and libsyntax crates, which are huge. Since they’re only used for expansion, the crate can be included for parsing via the `#[plugin]` attribute. This prevents linking the output against rustc and syntax.

---

<div class="post-metadata">

**Author:** ![alexcrichton](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alexcrichton/32/4501_2.png) [@alexcrichton](https://internals.rust-lang.org/u/alexcrichton)\
**Post date:** [May 26, 2015, 2:47pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/13 "2015-05-26T14:47:23Z")

</div>

> [@brson](#):
>
> I would be doubly-happier if the metadata for those subprojects could be inferred instead of typed explicitly.

This sounds like a fantastic idea!

> [@mitsuhiko](#):
>
> The main reason this comes up are macros I think, and there it's not quite clear what is to be gained from that being in a separate crate.

When you say macros, do you mean `macro_rules!` macros or plugins? Currently I don't believe `macro_rules!` requires a separate crate, and plugins require a separate crate for technical reasons (cross compilation).

---

<div class="post-metadata">

**Author:** ![brson](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/brson/32/5197_2.png) [@brson](https://internals.rust-lang.org/u/brson)\
**Post date:** [May 26, 2015, 8:19pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/14 "2015-05-26T20:19:52Z")

</div>

@huon When I tried creating a project that put binaries in the subprojects, Cargo would not build them. It only builds libs from subprojects. Further, Cargo will not allow you to have a project that produces no artifacts, so you have to pick one bin to be blessed.

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [November 14, 2017, 4:35am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/15 "2017-11-14T04:35:29Z")

</div>

I have a use case in favor of being able to have multiple dylib outputs in the same crate: I have a neat stack built up, in total it’s 7 project, of which 3 in Rust, 1 in Java, and 3 in Elisp. The Java and 1 of the Elisp projects each depend on 1 of the Rust crates. Thus the 3 Rust projects are built “the right way”. Now if it was at least a small team of people doing all this, all would be fine. But since it’s just me (at least for now), in practice it’s a major pain in the butt as the fixed-cost overhead of pushing through even a tiny change is basically having to spend a couple of hours tying it all together. And that’s assuming there are no mistakes. If there are, everything since the mistake needs to be redone.

The 3 Rust projects could instead (at least conceptually) live in the same repo, be built be the same `cargo build` command, and life would be so much easier and faster for people with a use case like this.

---

<div class="post-metadata">

**Author:** ![sfackler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sfackler/32/9_2.png) [@sfackler](https://internals.rust-lang.org/u/sfackler)\
**Post date:** [November 14, 2017, 4:55am UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/16 "2017-11-14T04:55:09Z")

</div>

@jjpe There’s no reason a single repo can’t contain multiple crates in a workspace. e.g. [https://github.com/sfackler/rust-openssl](https://github.com/sfackler/rust-openssl)

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [November 14, 2017, 12:48pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/17 "2017-11-14T12:48:38Z")

</div>

The effect I’m looking for is to basically have to type `cargo build` once (perhaps preceded by a `cargo update`) and have all artifacts (a binary and 2 dynamic libs) built in 1 go. No fuss, no muss.

It seems like combining multiple crates in a repo with a workspace might give that effect, but I’m not sure about that. If it is, it’s a workable solution for me. Is anyone in a position to answer this question before I sink the time into making the change?

---

<div class="post-metadata">

**Author:** ![steveklabnik](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steveklabnik/32/4524_2.png) [@steveklabnik](https://internals.rust-lang.org/u/steveklabnik)\
**Post date:** [November 14, 2017, 1:20pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/18 "2017-11-14T13:20:00Z")

</div>

`cargo build --all` does that, yes.

---

<div class="post-metadata">

**Author:** ![djc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/djc/32/1592_2.png) [@djc](https://internals.rust-lang.org/u/djc)\
**Post date:** [November 14, 2017, 8:42pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/19 "2017-11-14T20:42:15Z")

</div>

And I think `--all` is now implicit when running from a workspace, right?

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [November 14, 2017, 9:45pm UTC](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022/20 "2017-11-14T21:45:06Z")

</div>

I just tried it, and it sure doesn’t look that way.

When I omit the `--all` flag, it only builds my core crate, while with the `-all` flag it also builds the other crates in the repo.

[Next page](https://internals.rust-lang.org/t/how-about-changing-lib-to-lib-to-allow-multiple-library-in-a-crate/2022.md?page=2)
