Cargo: workspace package believes it's in a workspace when it's not

Hello all,

My new pet project is cargo-e. I implemented a work around for "loose" packages in workspaces not reporting back the examples or binaries when the package is not part of the workspace.

a more detailed account is available here:

I really don't like having to patch a Cargo.toml file to be able to query and run examples. Why do packages unaccounted for in the workspace not deserve to run as the standalone crate they are?

Is there a better work around than modifying Cargo.toml?

Thanks.
--dave

the question is, why don't you want to add the package as a member? there must be good reasons, right? if you don't want the package to be a member, then why is it surprising cargo don't include them in the runnable targets?

I don't think this is a technical issue of the tools, cargo works just as intended. instead, it's more of a project management issue, or organizational issue.

Another option would be to move the packages out of the workspace's tree.

Maybe something clever with symlinks could achieve that without modifying the original directories?

I don't think there's any cargo config for this.

the question is, why don't you want to add the package as a member?

for this example, the user is trying to record a cli demo and decided to place other people's bytes in close proximity(inside) to actual workspace code.

there must be good reasons?

yes, that's where temporarily, I'd like to work on other people's code.

is this a case of cargo just works as intended?
I'm asking what the intent of this error breaking run interface?
What's the problem with "loose" crate?
Might there be some method for getting past this via command line switch?

right, it's NOT part of the project, so it makes sense to NOT adding it as a workspace member.

this is just an opinion, but I think it does.

my use for a workspace is to share the build artifacts under a single target directory, and that all dependency are managed by a single Cargo.lock file, and their features are unified across all crates.

if I don't need these features, I don't usually put multiple packages into a single cargo workspace. I might still have multiple packages in a mono repo, but they don't need to be managed by cargo.

for example, since I use vscode to write rust code, occasionally I need to add additional folders to a vscode workspace, when there's no single top level "main" crate. rust-analyzer has no problem with such setup, I just use the rust-analyzer.linkedProjects setting.

I have no problem with "loose" crate at all, but I don't think it's best fit for cargo workspaces. and by the fact you don't add it as a workspace member, I assume would think the same?

sadly, I don't think there is, at least not in a way as you described.

the thing is, cargo run has this --manifest-path option, but if the manifest file is in a subdirectory of the root workspace, and it was not a member of the workspace, then cargo will give the error.

your method is to make the package itself a workspace, the alternative is to exclude the subdirectory explicitly in the workspace manifest, both of which need to make changes to some Cargo.toml.

another alternative is to use multiple workspace. but currently, cargo does have the limitation that workspace requires the members to be within a hierarchy of the root "Cargo.toml` manifest, (e.g. I cannot use "../../crates/foo" for a workspace member), making it tricky to create (overlapping) workspaces, but I did manage to come up with a hacky workaround (sort of):

# root directory Cargo.toml
[workspace]
members = ["crates/*"] # these are the "core" packages
exclude = ["ext"] # these are "loose" packages

# ext/Cargo.toml: this is optional
# a workspace to group all the "loose" packages
[workspace]
members = ["*"]
exclude = ["target/"] # exclude `target` from wildcard

# crates/foo/Cargo.tom: a "core" package with a library crate
[package]
name = "foo"
[lib]
path = "src/lib.rs"

# ext/bar/Cargo.toml: a "loose" package, with binary crates and more
[package]
name = "bar"
[[bin]]
name = "bar"
path = "src/main.rs"
# can use `path` dependencies just fine,
# they have nothing to do with workspace membership
[dependencies.foo]
path = "../../crates/foo"

I imagine this could work for some scenarios, but it is a ugly hack, and I don't like it at all.

project1 $ cargo run
error: a bin target must be available for `cargo run`

project1 $ cargo run --bin bar
error: no bin target named `bar`

project1 $ cargo run --manifest-path ext/Cargo.toml
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `ext/target/debug/bar`
Hello, world!

project1 $ cd ext
project1/ext $ cargo run
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/bar`
Hello, world!

note, it is OK for a package to be members of multiple wokspaces, that what I meant by "overlapping", e.g.:

# root directory Cargo.toml
[workspace]
members = ["crates/*", "ext/baz"] # explicitly add "ext/baz" although `ext` is excluded
exclude = ["ext"]

# ext/Cargo.toml
[workspace]
members = ["bar", "baz"]
P.S.

this trick is adapted from some C++ projects, where there can be multiple "project" or "build" files (e.g. .sln or .vcproj for msbuild, CMakeLists.txt for cmake, etc) for the same codebase. basically, I "abuse" the project files as a build preset or profile, the setup typically has a structure similar to:

── project_root_directory/
   ├── include/
   ├── src/
   ├── lib/
   ├── msvc/
   │   ├── winxp.vcproj
   │   ├── nolibpnet.vcproj
   │   └── wepoll.vcproj
   ├── cmake/
   │   ├── smoke/CMakeLists.txt
   │   ├── staging/CMakeLists.txt
   │   └── wepoll/CMakeLists.txt
   └── meson/...

moving the files and excluding via the parent are just as troublesome. thank you both for the replies.
I'm thinking I need to patch and refer to a patched --manifest instead of the one given.
Then I'm left with syncing or cleaning up the temporary/patched file...

It's not really a bug to file on cargo. How does one make a suggestion to not make this sort of patching required? Maybe this is correct behavior. A cmd line flag or a environment variable to allow you to use a orphan/loose crate would be nice. Why is an orphan a problem that we can't run or list its targets?

I'd appreciate understanding the reasoning behind this behavior.