Multi-crate cargo repositories best practices

I ended up with quite a few Cargo.toml files while trying to cargoize zinc, and I'm looking for some ideas on what are the best options to sort out the individual crates in terms of filesystem hierarchy to keep them in one single repo.

As of now my directory structure looks like:

- src
    - ioreg
        - Cargo.toml
          # internal plugin crate used by platform/* with path=
    - platformtree
        - Cargo.toml
          # external plugin crate, should be accessible to end user
    - platform
        - $platform_name
            - Cargo.toml
              # one crate per platform, should be accessible to end user
              # sample content: https://gist.github.com/farcaller/bc22a9c32f4b713b8394
    - volatile_cell
        - Cargo.toml
          # internal library crate, extracted for code-reuse
    - zinc
        - Cargo.toml
        # primary library crate, should be accessible to end user
        - os
            - posix_sched
                - Cargo.toml
                  # single-source C file wrapping getcontext()/setcontext() POSIX api to be used in tests of zinc crate (extracted to crate at it's a dev-dependency)

I'm not exactly sure how this is expected to be useable for crates.io, as most of the crates here interlink with others via path= relative references and I see no reasonable way on how I would build an end-user app referencing platformtree and zinc crates from git unless I do a checkout. Surely, splitting all this to dedicated repos would sole all the problems, but it would introduce much worse issues with cross-repo code refactoring.

Any suggestions?

4 Likes

crates.io handles path dependencies by handling them as if they point to the crates.io version, e.g. if ioreg is version 0.1.1 and platformtree has [dependencies.ioreg] path = "../ioreg" that will effectively be rewritten to

[dependencies]
ioreg = "0.1.1"

This does mean that all have to be published on crates.io.

(I'm not sure if this is what you mean?)

1 Like

Suggestion #1: you can create one git branch in your git repository for each of your sub-crates, and in the depencies of your main Cargo.toml you can specify the right branch in the git-url. So one git repository on Github with many branches, each branch a Cargo project.

I have not actually tried this, but the Cargo manifest specifications states that the branch can be specififed in git-urls: Page Moved .

Suggestion #2: if you prefer to keep using relative paths for dependencies, you can still create a branch for each sub-crate and merge those branches and the sub-directories of the main branch using "sutbree merging", a documented git merge strategy: Git - Book .

I do not know that these represent "best" practices, just the best I could find.

That has absolutely no advantage over them being in separate repositories except that it's much, much bigger mess. Remember, in git revisions move freely between repositories. It only matters whether the things are part of the same tree or not. From configuration management perspective in this case they should be.

2 Likes

Is the requirement that local crates must be published on crates.io still in effect? I can't find anything about it on http://doc.crates.io/, and obviously I don't want to resort to empiricism :slight_smile: If so, is there any way around that requirement other than only using sub-modules, not crates?