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