mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-08-06 22:07:19 +02:00
201 lines
7.4 KiB
Diff
201 lines
7.4 KiB
Diff
From: Shiz <hi@shiz.me>
|
|
Date: Fri, 21 Apr 2017 01:04:46 +0200
|
|
Subject: [PATCH] Support fully static linking on *nix targets
|
|
|
|
This patch adds support for full static linking on *nix targets.
|
|
|
|
It adds `Session::fully_static()` to determine whether full static linking
|
|
should be utilised. By default, this is the case if the target is not
|
|
MSVC-like and the `crt-static` target feature is requested, as for *nix
|
|
targets this implies a fully static result. In the future, a target feature
|
|
or other compile option could perhaps be added to have the invoker decide
|
|
this more flexibly at run-time.
|
|
|
|
It also adds the proper linker argument for static result objects to `Linker`
|
|
and implements them for `GnuLinker` and `MsvcLinker`. Additionally, when
|
|
statically linking, all the objects are linked in a group (-Wl,-( and -Wl,-)
|
|
on GNU-compatible linkers) to resolve dependency and order issues that may
|
|
normally arise. For `MsvcLinker`, this is a no-op as it already exhibits
|
|
this behavior by default.
|
|
|
|
Finally, if no linking preference is given for native libraries
|
|
(`NativeLibraryKind::NativeUnknown`), they are linked statically if full
|
|
static linking is requested, instead of dynamically as before.
|
|
|
|
--- a/src/librustc/session/mod.rs
|
|
+++ b/src/librustc/session/mod.rs
|
|
@@ -409,6 +409,11 @@
|
|
return crt_static;
|
|
}
|
|
|
|
+ pub fn fully_static(&self) -> bool {
|
|
+ // TODO: figure out better semantics for this, possibly a target option?
|
|
+ return self.crt_static() && !self.target.target.options.is_like_msvc
|
|
+ }
|
|
+
|
|
pub fn must_not_eliminate_frame_pointers(&self) -> bool {
|
|
self.opts.debuginfo != DebugInfoLevel::NoDebugInfo ||
|
|
!self.target.target.options.eliminate_frame_pointer
|
|
--- a/src/librustc_trans/back/link.rs
|
|
+++ b/src/librustc_trans/back/link.rs
|
|
@@ -239,8 +239,8 @@
|
|
/// Checks if target supports crate_type as output
|
|
pub fn invalid_output_for_target(sess: &Session,
|
|
crate_type: config::CrateType) -> bool {
|
|
- match (sess.target.target.options.dynamic_linking,
|
|
- sess.target.target.options.executables, crate_type) {
|
|
+ let dynamic_linking = sess.target.target.options.dynamic_linking && !sess.fully_static();
|
|
+ match (dynamic_linking, sess.target.target.options.executables, crate_type) {
|
|
(false, _, config::CrateTypeCdylib) |
|
|
(false, _, config::CrateTypeProcMacro) |
|
|
(false, _, config::CrateTypeDylib) => true,
|
|
@@ -840,6 +840,10 @@
|
|
|
|
let used_link_args = sess.cstore.used_link_args();
|
|
|
|
+ if crate_type == config::CrateTypeExecutable && sess.fully_static() {
|
|
+ cmd.static_executable();
|
|
+ }
|
|
+
|
|
if crate_type == config::CrateTypeExecutable &&
|
|
t.options.position_independent_executables {
|
|
let empty_vec = Vec::new();
|
|
@@ -870,15 +870,8 @@
|
|
cmd.no_default_libraries();
|
|
}
|
|
|
|
- // Take careful note of the ordering of the arguments we pass to the linker
|
|
- // here. Linkers will assume that things on the left depend on things to the
|
|
- // right. Things on the right cannot depend on things on the left. This is
|
|
- // all formally implemented in terms of resolving symbols (libs on the right
|
|
- // resolve unknown symbols of libs on the left, but not vice versa).
|
|
+ // We have organized the arguments we pass to the linker as such:
|
|
//
|
|
- // For this reason, we have organized the arguments we pass to the linker as
|
|
- // such:
|
|
- //
|
|
// 1. The local object that LLVM just generated
|
|
// 2. Local native libraries
|
|
// 3. Upstream rust libraries
|
|
--- a/src/librustc_trans/back/link.rs
|
|
+++ b/src/librustc_trans/back/link.rs
|
|
@@ -951,17 +951,12 @@
|
|
// list can't depend on items higher up in the list. For example nothing can
|
|
// depend on what we just generated (e.g. that'd be a circular dependency).
|
|
// Upstream rust libraries are not allowed to depend on our local native
|
|
- // libraries as that would violate the structure of the DAG, in that
|
|
- // scenario they are required to link to them as well in a shared fashion.
|
|
- //
|
|
- // Note that upstream rust libraries may contain native dependencies as
|
|
- // well, but they also can't depend on what we just started to add to the
|
|
- // link line. And finally upstream native libraries can't depend on anything
|
|
- // in this DAG so far because they're only dylibs and dylibs can only depend
|
|
- // on other dylibs (e.g. other native deps).
|
|
+ // libraries as that would violate the structure of the DAG.
|
|
+ cmd.start_group();
|
|
add_local_native_libraries(cmd, sess);
|
|
add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
|
|
add_upstream_native_libraries(cmd, sess, crate_type);
|
|
+ cmd.end_group();
|
|
|
|
// # Telling the linker what we're doing
|
|
|
|
@@ -983,11 +983,14 @@
|
|
cmd.link_whole_staticlib(&l.name.as_str(), &search_path);
|
|
}
|
|
|
|
- cmd.hint_dynamic();
|
|
+ let fully_static = sess.fully_static();
|
|
+ if !fully_static {
|
|
+ cmd.hint_dynamic();
|
|
+ }
|
|
|
|
for lib in others {
|
|
match lib.kind {
|
|
- NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
|
|
+ NativeLibraryKind::NativeUnknown => if fully_static { cmd.link_staticlib(&lib.name.as_str()) } else { cmd.link_dylib(&lib.name.as_str()) },
|
|
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
|
|
NativeLibraryKind::NativeStatic => bug!(),
|
|
}
|
|
--- a/src/librustc_trans/back/linker.rs
|
|
+++ b/src/librustc_trans/back/linker.rs
|
|
@@ -82,6 +82,7 @@
|
|
fn add_object(&mut self, path: &Path);
|
|
fn gc_sections(&mut self, keep_metadata: bool);
|
|
fn position_independent_executable(&mut self);
|
|
+ fn static_executable(&mut self);
|
|
fn optimize(&mut self);
|
|
fn debuginfo(&mut self);
|
|
fn no_default_libraries(&mut self);
|
|
@@ -93,6 +93,8 @@
|
|
fn no_whole_archives(&mut self);
|
|
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
|
|
fn subsystem(&mut self, subsystem: &str);
|
|
+ fn start_group(&mut self);
|
|
+ fn end_group(&mut self);
|
|
}
|
|
|
|
pub struct GnuLinker<'a> {
|
|
@@ -116,6 +117,9 @@
|
|
fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
|
|
fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
|
|
fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
|
|
+ fn static_executable(&mut self) { self.cmd.arg("-static"); }
|
|
+ fn start_group(&mut self) { self.cmd.arg("-Wl,-("); }
|
|
+ fn end_group(&mut self) { self.cmd.arg("-Wl,-)"); }
|
|
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
|
|
|
|
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
|
@@ -359,6 +361,10 @@
|
|
|
|
fn position_independent_executable(&mut self) {
|
|
// noop
|
|
+ }
|
|
+
|
|
+ fn static_executable(&mut self) {
|
|
+ self.cmd.arg("-MT");
|
|
}
|
|
|
|
fn no_default_libraries(&mut self) {
|
|
@@ -484,6 +488,14 @@
|
|
if subsystem == "windows" {
|
|
self.cmd.arg("/ENTRY:mainCRTStartup");
|
|
}
|
|
+ }
|
|
+
|
|
+ fn start_group(&mut self) {
|
|
+ // Not needed
|
|
+ }
|
|
+
|
|
+ fn end_group(&mut self) {
|
|
+ // Not needed
|
|
}
|
|
}
|
|
|
|
@@ -562,6 +562,10 @@
|
|
// noop
|
|
}
|
|
|
|
+ fn static_executable(&mut self) {
|
|
+ // noop
|
|
+ }
|
|
+
|
|
fn args(&mut self, args: &[String]) {
|
|
self.cmd.args(args);
|
|
}
|
|
@@ -657,6 +661,14 @@
|
|
|
|
fn subsystem(&mut self, _subsystem: &str) {
|
|
// noop
|
|
+ }
|
|
+
|
|
+ fn start_group(&mut self) {
|
|
+ self.cmd.arg("-Wl,-(");
|
|
+ }
|
|
+
|
|
+ fn end_group(&mut self) {
|
|
+ self.cmd.arg("-Wl,-)");
|
|
}
|
|
}
|
|
|