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