Deprecating having both `src/lib.rs` and `src/main.rs` in the same package

This could be a warning completely inside of Cargo, using the dep info files to know what files are ready by each build target.

3 Likes

I think the user confusion could have already caused a compilation error before the dep info file got emitted. And even if it can't, you did have to make sure that cargo emits the error even when there is a compilation failure.

Since lib.rs can be used for building shared libraries, which are binaries, should it be put in bin/ when the crate type is cdylib? And what about dylib?

Obviously this would be way too confusing, but is there really a point in these separations of files then?

The real issue here is that there's an overlap between the responsibilities of cargo and Rust's module system.

Instead of all of the above partial solutions, we should fully adopt cargo workspaces for a uniform approach:

  1. A workspace should be mapped to a package in crates.io and coherence should be relaxed to workspace level.
  2. Each member in the workspace woild correspond to a single artefact with a uniform folder structure regardless of its type (bin or lib)
  3. This would allow to have more than one lib in a package, removing a limitation of the current system.
2 Likes

You can have a single library be both an rlib and dylib or cdylib at the same time. This will then be compiled with a single rustc invocation. In addition only the [lib] target (of which there can only be one) allows dylibs and cdylibs. As such the dylib and cdylib crate type should be put outside bin/ IMO.

That's a clever way to detect the overlap, but I think Cargo wouldn't be able to easily associate the paths with the source code location where the mod items were.

In hindsight, I even prefer the coarse rule that warns about any mod in src/main.rs. That's because both lib.rs and main.rs will read module files from the same directory, so it's already tricky to recognize which file is used by which build. It's a messy situation even the files aren't used twice.

While I lean towards improving workspaces over more crate in one package, I feel there are still times to have multiple crates in a package that we shouldn't preclude it. Stabilizing artifact dependencies may help.

There are valid reasons to have a workspace map to multiple .crate files so it would need to be user defined. We did look into allowing multiple packages in a .crate file but it ran into issue in designing the Index entries, see https://github.com/rust-lang/rfcs/pull/3452

Hm, I do that. My main.rs usually contains a single mod cli; that had the definition of the command line parser (usually clap, but sometimes xflags to have better compile times if I don't need fancy things, e.g. for a daemon).

Everything else is a submodules of lib.rs.

Let me clarify what I've said: I believe that we should have an orthogonal design where we always have a 1-to-1 mapping between a cargo workspace to a unique listing on crates.io.

That entry could have one or more sub-artefacts - including binary artefacts like shared libs. From the language perspective though it is a single logical unit. This also aligns with the already accepted RFC for semi-open cargo namespaces. Thats why I've also included workspace level coherence in my previous post.

'src/cli/main.rs' makes sense (if not cli is a submodule of src/lib.rs)