@@ -30,3 +30,129 @@ meaning.
30
30
It is highly recommended to * not* use this attribute, and rather use the more
31
31
formal ` #[link(...)] ` attribute on ` extern ` blocks instead.
32
32
33
+ # Static linking
34
+
35
+ Static linking refers to the process of creating output that contain all
36
+ required libraries and so don't need libraries installed on every system where
37
+ you want to use your compiled project. Rust libraries are statically linked by
38
+ default so you can use Rust-created binaries and libraries without installing
39
+ the Rust runtime everywhere. By contrast, native libraries are dynamically
40
+ linked by default, but sometimes it can be useful to change this.
41
+
42
+ Linking is a very platform dependant topic - on some platforms, static linking
43
+ may not be possible at all! This section assumes some basic familiarity with
44
+ linking on your platform on choice.
45
+
46
+ ## Linux
47
+
48
+ By default, all Rust programs on Linux will link to the system libc along with
49
+ a number of other libraries Let's look at an example on a 64-bit linux machine
50
+ with GCC and glibc (by far the most common libc on Linux):
51
+
52
+ ``` text
53
+ $ cat example.rs
54
+ fn main() {}
55
+ $ rustc example.rs
56
+ $ ldd example
57
+ linux-vdso.so.1 => (0x00007ffd565fd000)
58
+ libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
59
+ libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
60
+ librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
61
+ libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
62
+ libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
63
+ /lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
64
+ libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
65
+ ```
66
+
67
+ Dynamic linking on Linux can be undesirable if you wish to target older
68
+ machines as applications compiled aginst newer versions glibc are not
69
+ guaranteed to run against older versions.
70
+
71
+ You can examine Rust linking arguments with an option to rustc. Newlines have
72
+ been added for readability:
73
+
74
+ ``` text
75
+ $ rustc example.rs -Z print-link-args
76
+ "cc"
77
+ "-Wl,--as-needed"
78
+ "-m64"
79
+ [...]
80
+ "-o" "example"
81
+ "example.o"
82
+ "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive"
83
+ "-Wl,--gc-sections"
84
+ "-pie"
85
+ "-nodefaultlibs"
86
+ [...]
87
+ "-Wl,--whole-archive" "-Wl,-Bstatic"
88
+ "-Wl,--no-whole-archive" "-Wl,-Bdynamic"
89
+ "-ldl" "-lpthread" "-lrt" "-lgcc_s" "-lpthread" "-lc" "-lm" "-lcompiler-rt"
90
+ ```
91
+
92
+ Arguments with a ` -L ` before them set up the linker search path and arguments
93
+ ending with ` .rlib ` are linking Rust crates statically into your application.
94
+ Neither of these are relevent for static linking so have been ommitted.
95
+
96
+ The first step in being able to statically link is to obtain an object file.
97
+ This can be achieved with ` rustc --emit obj example.rs ` , and creates a file
98
+ called ` example.o ` , which you can see being passed in the command line above -
99
+ rustc automatically deletes it when finished with it by default. As you now have
100
+ the object file, you should be able to run the link command obtained with
101
+ ` print-link-args ` to create perform the linking stage yourself.
102
+
103
+ In order to statically link, there are a number of changes you must make. Below
104
+ is the command required to perform a static link; we will go through them each
105
+ in turn.
106
+
107
+ ``` text
108
+ $ rustc example.rs -Z print-link-args
109
+ "cc"
110
+ "-static"
111
+ "-m64"
112
+ [...]
113
+ "-o" "example"
114
+ "example.o"
115
+ "-Wl,--whole-archive" "-lmorestack" "-Wl,--no-whole-archive"
116
+ "-Wl,--gc-sections"
117
+ "-nodefaultlibs"
118
+ [...]
119
+ "-Wl,--whole-archive"
120
+ "-Wl,--no-whole-archive"
121
+ "-ldl" "-lpthread" "-lrt" "-lgcc_eh" "-lpthread" "-lc" "-lm" "-lcompiler-rt"
122
+ ```
123
+
124
+ - ` -static ` was added - this is the signal to the compiler to use a static
125
+ glibc, among other things
126
+ - ` -Wl,--as-needed ` was removed - this can be left in, but is unnecessary
127
+ as it only applies to dynamic librares
128
+ - ` -pie ` was removed - this is not compatible with static binaries
129
+ - both ` -Wl,-B* ` options were removed - everything will be linked statically,
130
+ so informing the linker of how certain libraries should be linked is not
131
+ appropriate
132
+ - ` -lgcc_s ` was changed to ` -lgcc_eh ` - ` gcc_s ` is the GCC support library,
133
+ which Rust uses for unwinding support. This is only available as a dynamic
134
+ library, so we must specify the static version of the library providing
135
+ unwinding support.
136
+
137
+ By running this command, you will likely see some warnings like
138
+
139
+ ``` text
140
+ warning: Using 'getpwuid_r' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
141
+ ```
142
+
143
+ These should be considered carefully! They indicate calls in glibc which
144
+ * cannot* be statically linked without significant extra effort. An application
145
+ using these calls will find it is not as portable as 'static binary' would imply.
146
+ Rust supports targeting musl as an alternative libc to be able to fully
147
+ statically link these calls.
148
+
149
+ As we are confident that our code does not use these calls, we can now see the
150
+ fruits of our labour:
151
+
152
+ ```
153
+ $ ldd example
154
+ not a dynamic executable
155
+ ```
156
+
157
+ This binary can be copied to virtually any 64-bit Linux machine and work
158
+ without requiring external libraries.
0 commit comments