Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cargo prefers dynamic linking for a dylib, if in a workspace #7226

Closed
pimeys opened this issue Aug 8, 2019 · 2 comments
Closed

Cargo prefers dynamic linking for a dylib, if in a workspace #7226

pimeys opened this issue Aug 8, 2019 · 2 comments
Labels
C-bug Category: bug

Comments

@pimeys
Copy link

pimeys commented Aug 8, 2019

Problem

Having a workspace with multiple crates, libraries and binaries combined. One of the libraries should be compiled as dylib and used from an FFI context in another language. When the crate is in a workspace, it has certain libraries linked dynamically that cannot be found:

> ldd libmigration_core.so
	linux-vdso.so.1 (0x00007ffc847f0000)
	liblexical_core-306cff9771b5ea52.so => not found
	libstd-9895e8982b0a79e7.so => not found
	libssl.so.1.1 => /usr/lib/libssl.so.1.1 (0x00007f050f68f000)
	libcrypto.so.1.1 => /usr/lib/libcrypto.so.1.1 (0x00007f050f3bb000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f050f3b6000)
	librt.so.1 => /usr/lib/librt.so.1 (0x00007f050f3a9000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f050f388000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f050f36e000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f050f1ab000)
	/usr/lib64/ld-linux-x86-64.so.2 (0x00007f05106db000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007f050f065000)

The cargo build -vv --package migration-core reveals how Cargo adds an extra flag -C prefer-dynamic to the build parameters:

rustc --edition=2018 --crate-name migration_core migration-engine/core/src/lib.rs --color always --crate-type dylib -C prefer-dynamic

We can add the library in the exclude section in the workspace Cargo.toml and try compiling it again. This time it holds its own target directory and the linking works as supposed, as can be seen in the ldd output:

ldd libmigration_core.so
	linux-vdso.so.1 (0x00007f91e0427000)
	libssl.so.1.1 => /usr/lib/libssl.so.1.1 (0x00007f91dd8fc000)
	libcrypto.so.1.1 => /usr/lib/libcrypto.so.1.1 (0x00007f91dd628000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f91dd623000)
	librt.so.1 => /usr/lib/librt.so.1 (0x00007f91dd618000)
	libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f91dd5f7000)
	libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f91dd5dd000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f91dd418000)
	/usr/lib64/ld-linux-x86-64.so.2 (0x00007f91e0428000)
	libm.so.6 => /usr/lib/libm.so.6 (0x00007f91dd2d2000)

And we can see the prefer-dynamic build flag is not set:

rustc --edition=2018 --crate-name migration_core src/lib.rs --color always --crate-type dylib

Steps

  1. git clone git@github.com:prisma/prisma.git --branch lift_ffi
  2. cd prisma/server/prisma-rs
  3. cargo build -vv --package migration-core
  4. See from the last line how rustc uses -C prefer-dynamic
  5. See ldd target/debug/libmigration_core.so for missing dependencies
  6. Take the package out from the workspace.
diff --git a/server/prisma-rs/Cargo.toml b/server/prisma-rs/Cargo.toml
index d8db642dd..9f670246b 100644
--- a/server/prisma-rs/Cargo.toml
+++ b/server/prisma-rs/Cargo.toml
@@ -1,9 +1,6 @@
 [workspace]
 members = [
   "prisma-models",
-  "migration-engine/connectors/migration-connector",
-  "migration-engine/connectors/sql-migration-connector",
-  "migration-engine/core",
   "query-engine/connectors/connector",
   "query-engine/connectors/sql-connector",
   "query-engine/prisma",
@@ -14,3 +11,16 @@ members = [
   "libs/prisma-inflector",
   "libs/database-introspection",
 ]
+
+exclude = [
+  "migration-engine/connectors/migration-connector",
+  "migration-engine/connectors/sql-migration-connector",
+  "migration-engine/core",
+]
  1. cd migration-engine/core/
  2. cargo build -vv
  3. See how rustc has no -C prefer-dynamic set.
  4. ldd target/debug/libmigration_core.so and see how libstd and liblexical_core are now statically linked and not missing.

Notes

@pimeys pimeys added the C-bug Category: bug label Aug 8, 2019
@pimeys
Copy link
Author

pimeys commented Aug 9, 2019

Maybe I need to provide more information why I use dylib instead of cdylib.

This crate uses neon bindings and the resulting so is loaded using node's require that just does not work right with a cdylib, but works quite well with a statically compiled dylib:

> var addon = require('./index.node');
Thrown:
Error: Module did not self-register.
    at Object.Module._extensions..node (internal/modules/cjs/loader.js:857:18)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)

@alexcrichton
Copy link
Member

Thanks for the reports here! When compiling a Rust dynamic library though to integrate into another language you'll want to use a cdylib, not a dylib. Although an unfortunate historical accident a dylib is a different kind of artifact, so that should do the trick when implementing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

No branches or pull requests

2 participants