Summary
Allow #[link(kind = "dylib")]
without a name
.
Motivation
It is fairly common to write bare extern
blocks and fill in the library to be linked elsewhere.
E.g.
extern "C" {
fn do_stuff();
}
// elsewhere in the code...
#[link(name = "mylibrary")]
extern {}
// alternatively, the library may be passed on the command line, through a build script, etc
// or even in another crate.
This works for static libraries because a bare extern
block assumes kind = "static"
.
Unfortunately there's no way to declare that the linkage should be dynamic.
For ELF binaries this is usually papered over by the loader trying its hardest to make dynamic libraries appear as much like static libraries as possible.
Whereas on Windows this does not happen.
Windows does however have "import libraries" that contain shims which similarly papers over the difference.
So the static function do_stuff
is simply:
do_stuff:
jmp _imp__do_stuff
However, there is no such equivalent for static items so the following will just fail to link:
extern "C" {
// where "MY_STATIC" is exported by `mylibrary`
static MY_STATIC: u8;
}
#[link(name = "mylibrary", kind = "dylib")]
extern {}
Guide-level explanation
By default, functions in an extern
block use static linkage. So this:
extern C {
fn do_stuff();
}
Is equivalent to:
#[link(kind = "static")]
extern C {
fn do_stuff();
}
You can use dynamic linkage instead by adding #[link(kind = "dylib")]
#[link(kind = "dylib")]
extern "C" {
fn do_stuff();
}
Reference-level explanation
Currently #[link(kind = "...")]
will produce an error saying that name
is required.
Implementing this RFC would mean carving out an exceptional case to allow kind = "static" | "dylib"
if it's the only thing in the #[link]
attribute.
Otherwise the implementation will be the same except that no library is pushed to the list of native libs.
Drawbacks
Why should we not do this???
Rationale and alternatives
Making overrides more powerful may be an alternative. For example, allowing crates to define where a symbol comes from and how it should be linked independently of defining that symbol.
However, even if that were implemented, I think providing a simple option for the simple case is worthwhile.
Prior art
Windows MSVC (and compatible) have __declspec( dllimport )
which you can use to "import functions, data, and objects [from] a DLL" without adding an import name there.
Unresolved questions
N/A
Future possibilities
I don't expect this will need to be expanded further except perhaps to add more kind
s, if it makes sense to do so in the future.