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 crates.io), 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 crates.io?
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 crates.io.
Yet that's what -sys
crates usually do. You have several options for wrapping a separately built library, e.g.:
- Include the source code (usually gated under a feature, conventionally named
bundled
) - Require the library to already be present on the host system.
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: