Shared library and apllication which uses it in one workspace?

I have shared (i.e. cdylib) library libfoo written in Rust, wrapper around it foo-sys, and application foo which uses foo-sys and thus depends on the shared library. Ideally, I would like to keep all 3 crates in the same workspace, but naive approach does not work. Cargo does not know that libfoo must be compiled before foo-sys and is not able to link freshly compiled libfoo from the target folder. Do you have any suggestions which I could use here?

How are you building libfoo? You should do it in the build script for foo-sys, which is guaranteed to run before compiling foo-sys.


Right now I keep them in two separate workspaces. libfoo is built using nothing more than cargo build. I manually place the resulting so into a discoverable location (e.g. /usr/local/lib). Finally, foo-sys links to libfoo using #[link(name = "foo")] without any build scripts.

I would like keep foo-sys usable outside of the workspace (e.g. after publishing it to, so I don't think building libfoo in a build script would be a right solution.

What makes you think that using a build script would prevent the resulting library from being used elsewhere or publishing to

My understanding of the @alice suggestion is to build libfoo in foo-sys's build script. Meaning it needs access to libfoo's source code, which obviously would not work for foo-sys published to

Yet that's what -sys crates usually do. You have several options for wrapping a separately built library, e.g.:

  1. Include the source code (usually gated under a feature, conventionally named bundled)
  2. Require the library to already be present on the host system.
1 Like

I intend to support only dynamic linking of libfoo, so the bundled approach is not applicable. I effectively use the second approach right now, but during development I would like for foo-sys to link to libfoo which was built from the same workspace. I could introduce a special development-only feature or flag, but it would mean I have a slight difference between development and published versions which may cause issues. Also it requires addition of a build script, while the current version of foo-sys does not have it.

I don't get this. How can you not support static linking?

I understand, but you can't expect Cargo to be able to correctly manage dependencies completely outside of its scope.

To me this sounds like it could be solved with artifact-dependencies. Maybe you could add libfoo as an optional artifact-dependency to your foo-sys crate? I never experimented with artifact-dependencies before so I don't know if that would work, but maybe you'd consider looking into that possibility. Unfortunately artifact-dependencies are still unstable, so maybe they aren't even an option for you. Here the RFC:

1 Like