Do you compile a dylib?


#1

Hello! Are you someone who compiles with crate-type = ["dylib"], #![crate_type = "dylib"], or --crate-type dylib? If so, I either have terrible or amazing news!

RFC 1510 has just moved into its week-long final comment period. At its core this RFC proposes changing the definition of the dylib crate type to be more tailored towards the Rust-in-other-applications use case. This is unfortunately a breaking change, however, for anyone who uses extern crate foo where foo is compiled as a dylib as that crate would now have to be compiled as an rdylib (more details in the RFC itself).

So in general, I’m curious to get a broader survey of:

  • Do you compile dynamic libraries in Rust not used for embedding Rust?
  • Do you ever specify a crate type dylib in Cargo.toml, source, or build scripts?

It’s possible to implement RFC 1510 as not a breaking change, it’d just be unfortunate to give up the name dylib!


#2

I compile a crate as a dylib that talks through JNI to Java - acting just like a normal C dylib. It’s specified as a dylib in Cargo.toml.


#3

I compile a number of crates as dylibs (specified in Cargo.toml) as part of a plugin system that has Rust code loading Rust dylibs at runtime. I also compile using -C prefer-dynamic. It used to work well, and allowed hot-loading of plugins. However, it now crashes when any of the dylibs are updated.


#4

I compile two crates both as rlib and dylib (specified in Cargo.toml), so they’re available both to other crates, and to external processes via FFI.


#5

I’m using dylib as well for dynamic (re-loadable) plugins (main app is also in Rust) I’m very much in favor of this change as that is exactly what I want to have.


#6

I have a project that uses a standard rust crate, and it drawn in by another project to build a dylib (.so) that is loaded on the fly into another major C application.

I’m in favour of this change, and it would NOT break my current application.


#8

Thanks for the responses everyone!


@awe

Interesting! So you’re compiling Rust libraries as dynamic libraries to allow reloading the Rust code at runtime? That would indeed break if we changed the definition of the dylib crate type, and is a good data point towards just adding a new crate type cdylib.


@urschrei

To clarify, when you compile crates as a dylib you don’t intend that downstream users link to the dynamic library, right? You just have dylibs with C ABI entry points?


@emoon

Do your plugins have a C ABI or are they just loading Rust code into Rust? In the former case that’d continue working, but if it’s the latter we’ll need to call the new crate type cdylib.


#9

Exactly. The dylib is solely for FFI use by non-Rust processes.


#10

Right, I am doing exactly that, but I believe it already broke because of other changes somewhere along the way (i.e. changes to the dylib crate, and earlier when it was in std, which were not well documented). The actual reloading part seems to always cause a crash on Linux. I haven’t tested recently on OS X. It sounds like @emoon might be doing something similar though. So, there’s probably already a better way to do it than how I am.


#11

redhook builds LD_PRELOAD libraries, i.e., they care about C linkage and not Rust linkage, with crate_type = ["dylib"]. So as far as I can tell, this change would be beneficial—Rust stdlib continues to be statically linked, and its symbols would stop being exported in the resulting DSO, right? +1 then, and that’s sort of what I expected from dylib all along.


#12

@alexcrichton I have a C ABI. Also I wonder will the dylib now use -C prefer-dynamic as default? This is something that I had a bit of issue with before (10 Rust plugins would have 10 copies of stdlib)


#13

minject-rs injects DLLs into other processes on Windows. These DLLs are loaded dynamically and optionally specify an extern "C" entry point for initialization. So a stand-alone C ABI dylib is what I need. Whether dylib gets replaced or a new cdylib crate type is added doesn’t matter to me.


#14

@geofft

Yeah the standard library would be statically linked and not exported in the case of a “cdylib” in the RFC, regardless of whatever we end up naming that crate type.

@emoon

Ok! Right now you can use -C prefer-dynamic to not have 10 copies of libstd, but it means everything needs to be recompiled whenever Rust is update. Also judging @awe’s experiences it may just be broken right now?


#15

Yeah I’m unable to load the lib when I use -C prefer-dynamic (I haven’t looked into it but I figured that it was just because of not finding the dynamic version of stdlib) so right now I’m not using it but I would prefer to do it.


#16

We have two scenarios where we build a dylib in Servo:

  • When targeting Android, Servo will build a dylib, which I believe corresponds to the cdylib example from your RFC. I believe that this proposal should work exactly as we like things to work - expose a C/JNI API, all Rust code is linked into it statically, etc. It’s specified via the commandline as --crate-type dylib because this same Cargo.toml is also included as an rlib in a different build configuration.

  • When building a Chromium Embedding Framework (CEF) wrapper, that same previous crate is instead built as an rlib and the result is a dylib that exposes C APIs specified by that wrapper framework.

We’ve talked in the past about possibly offering Servo as a reusable dylib with a Rust API, but have never gotten around to doing so. So I agree that, at least for us, the rdylib case would not seem to apply to us.


#17

We compile a rust library to a dylib for use in a Java based Android app via JNI.

We welcome this change, especially if it reduces code size and/or increases runtime performance.