Skip to content

Commit 181c597

Browse files
Merge pull request #2841 from MaulingMonkey/pr/export-executable-symbols
RFC: -C export-executable-symbols
2 parents 5956896 + 804dbdd commit 181c597

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
- Feature Name: export-executable-symbols
2+
- Start Date: 2019-12-28
3+
- RFC PR: [rust-lang/rfcs#2841](https://github.com/rust-lang/rfcs/pull/2841)
4+
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Add the ability to export symbols from executables, not just dylibs, via a new
10+
compiler flag: `-C export-executable-symbols`.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
Java and C# can't statically link against C/Rust code. Both require dylib
16+
symbols for their common native interop solution. Which is fine if you let
17+
their executables call your dylib, but is a problem if you want your Rust
18+
executable to load a JVM instance, and let it call back into your executable.
19+
You might want to do this to allow you to:
20+
* Load multiple language runtimes into the same process (Rust + C# + Java + Lua anyone? Only one of them can be the entry executable...)
21+
* Display user-friendly error messages if language runtimes are missing (maybe even a download link!)
22+
* [#[test] Java/Rust interop via cargo test.](https://github.com/MaulingMonkey/jerk/blob/04250c9d1b6ccc292eb27663f70919345c31007f/example-hello-world-jar/src/Global.rs)
23+
24+
For this last case, I
25+
[manually export](https://github.com/MaulingMonkey/jerk/blob/04250c9d1b6ccc292eb27663f70919345c31007f/example-hello-world-jar/exports.def)
26+
executable symbols via
27+
[LINK](https://github.com/MaulingMonkey/jerk/blob/04250c9d1b6ccc292eb27663f70919345c31007f/example-hello-world-jar/build.rs#L4).
28+
This is ugly, brittle, and rustc
29+
[already knows](https://github.com/rust-lang/rust/blob/a916ac22b9f7f1f0f7aba0a41a789b3ecd765018/src/librustc_codegen_ssa/back/linker.rs#L706-L717)
30+
how to do this automatically, across more platforms, and better.
31+
32+
# Guide-level explanation
33+
[guide-level-explanation]: #guide-level-explanation
34+
35+
https://doc.rust-lang.org/rustc/codegen-options/index.html could gain:
36+
37+
```md
38+
## export-executable-symbols
39+
40+
This flag causes `rustc` to export symbols from executables, as if they were dynamic libraries.
41+
42+
You might use this to allow the JVM or MSCLR to call back into your executable's
43+
Rust code from Java/C# when embedding their runtimes into your Rust executable.
44+
```
45+
46+
`rustc -C help` could gain:
47+
48+
```
49+
-C export-executable-symbols -- export symbols from executables, as if they were dynamic libraries.
50+
```
51+
52+
My Java interop [Quick Start](https://github.com/MaulingMonkey/jerk/blob/master/Readme.md#quick-start)
53+
would start recommending a `.cargo/config` with:
54+
```toml
55+
[build]
56+
rustflags = ["-C", "export-executable-symbols"]
57+
```
58+
59+
# Reference-level explanation
60+
[reference-level-explanation]: #reference-level-explanation
61+
62+
On a technical level, this just involves preventing an early bailout when
63+
calling `fn export_symbols` on executables with MSVC or GNU linker backends.
64+
Other linker backends (EmLinker, WasmLd, PtxLinker) do not have this early
65+
bailout in the first place, and remain unaffected.
66+
67+
# Drawbacks
68+
[drawbacks]: #drawbacks
69+
70+
* Options bloat
71+
* The burden of supporting a niche use-case in hideously platform specific code
72+
73+
# Rationale and alternatives
74+
[rationale-and-alternatives]: #rationale-and-alternatives
75+
76+
This is *very* simple to implement, leverages existing code to enable it to do exactly what it was meant to do, and has few drawbacks.
77+
78+
Alternatives:
79+
80+
- Unconditionally export symbols from executables instead of introducing a new compiler flag.
81+
- Introduce a crate-level attribute instead of a compiler flag (`#![export_all_symbols]`? `#![export_symbols]`?)
82+
- Write *yet another* cargo subcommand to install/remember for interop testing instead of using cargo test.
83+
- Write interop tests exclusively as integration tests, in an entirely separate crate, that can load the testee as a dylib.
84+
- Continue abusing LINK, writing a tool to auto-generate .defs via build scripts - possibly by reading metadata from other tools.
85+
- Use nightly link-args instead of LINK, but still write a .def generator.
86+
- Remember to always cargo build a dylib copy of a crate manually before cargo test ing, and load that instead.
87+
(That would also add a whole second copy of all functions and static vars in the same unit test process!)
88+
89+
# Prior art
90+
[prior-art]: #prior-art
91+
92+
C and C++ compilers can already do this via `__declspec(dllexport)` annotations.
93+
Most people don't really notice it, for good or for ill.
94+
95+
# Unresolved questions
96+
[unresolved-questions]: #unresolved-questions
97+
98+
- Is this a good name for it?
99+
- Should it be more general and export when limit_rdylib_exports or crate_type == ProcMacro?
100+
101+
# Future possibilities
102+
[future-possibilities]: #future-possibilities
103+
104+
We could introduce a new source annotation, `#[export]`. For backwards
105+
compatibility with current behavior, `#[no_mangle]` symbols could be exported
106+
by default - and possibly disabled with `#[export(false)]`. This would
107+
reduce the need to hide this change to compiler/linker behavior behind a
108+
compiler flag or crate annotation.
109+
110+
Maybe other options to control what symbols get exported? Although I'd fear
111+
turning rustc into yet another linker script implementation, so maybe not.
112+
113+
My own building atop this in the wider language ecosystem would be for improved
114+
Java/Rust interop/testing, with the eventual goal of improved Android API
115+
support for Rust. Many APIs are only exposed via Java, and I'd like said APIs
116+
to be usable in a safe and sound fashion.

0 commit comments

Comments
 (0)