@@ -12,24 +12,24 @@ fn main() {
12
12
return ;
13
13
}
14
14
15
- let out = PathBuf :: from ( env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
16
- fs:: remove_dir_all ( & out ) . unwrap ( ) ;
17
- fs:: create_dir ( & out ) . unwrap ( ) ;
15
+ let out_dir = PathBuf :: from ( env:: var_os ( "OUT_DIR" ) . unwrap ( ) ) ;
16
+ fs:: remove_dir_all ( & out_dir ) . unwrap ( ) ;
17
+ fs:: create_dir ( & out_dir ) . unwrap ( ) ;
18
18
19
19
// The following are builds where we want to capture the output (i.e. stdout and
20
20
// stderr). We do that by re-running _this_ executable and passing in the
21
21
// action as the first argument.
22
- run_forked_capture_output ( & out , "metadata-on" ) ;
23
- run_forked_capture_output ( & out , "metadata-off" ) ;
22
+ run_forked_capture_output ( & out_dir , "metadata-on" ) ;
23
+ run_forked_capture_output ( & out_dir , "metadata-off" ) ;
24
24
25
- run_forked_capture_output ( & out , "warnings-off" ) ;
25
+ run_forked_capture_output ( & out_dir , "warnings-off" ) ;
26
26
if cc:: Build :: new ( ) . get_compiler ( ) . is_like_msvc ( ) {
27
27
// MSVC doesn't output warnings to stderr, so we can't capture them.
28
28
// the test will use this env var to know whether to run the test.
29
29
println ! ( "cargo:rustc-env=TEST_WARNINGS_ON=0" ) ;
30
30
} else {
31
31
println ! ( "cargo:rustc-env=TEST_WARNINGS_ON=1" ) ;
32
- run_forked_capture_output ( & out , "warnings-on" ) ;
32
+ run_forked_capture_output ( & out_dir , "warnings-on" ) ;
33
33
}
34
34
35
35
let mut build = cc:: Build :: new ( ) ;
@@ -104,7 +104,7 @@ fn main() {
104
104
// Test that the `windows_registry` module will set PATH by looking for
105
105
// nmake which runs vanilla cl, and then also test it after we remove all
106
106
// the relevant env vars from our own process.
107
- let out = out . join ( "tmp" ) ;
107
+ let out = out_dir . join ( "tmp" ) ;
108
108
fs:: create_dir ( & out) . unwrap ( ) ;
109
109
println ! ( "nmake 1" ) ;
110
110
let status = cc:: windows_registry:: find ( & target, "nmake.exe" )
@@ -173,6 +173,37 @@ fn main() {
173
173
let out = cc:: Build :: new ( ) . file ( "src/expand.c" ) . expand ( ) ;
174
174
let out = String :: from_utf8 ( out) . unwrap ( ) ;
175
175
assert ! ( out. contains( "hello world" ) ) ;
176
+
177
+ // Test static linking of stdc++ on Linux
178
+ #[ cfg( target_os = "linux" ) ]
179
+ {
180
+ // Rust linker has no problem linking against dynamic libraries, for instance
181
+ // it doesn't require any additional steps to link against system
182
+ // `libstdc++.so`, but if we emit `cargo:rustc-link-lib=static=stdc++`, it will
183
+ // not be able to find `libstdc++.a` file despite it almost always located next to
184
+ // `libstdc++.so`. So symlinking to OUT dir solves the problem
185
+
186
+ let mut cmd = Command :: new ( "g++" ) ;
187
+ cmd. arg ( "--print-file-name=libstdc++.a" ) ;
188
+ if arch == "i686" {
189
+ cmd. arg ( "-m32" ) ;
190
+ }
191
+ let libstdc_path: PathBuf =
192
+ String :: from_utf8 ( cmd. output ( ) . expect ( "Failed to run g++" ) . stdout )
193
+ . unwrap ( )
194
+ . trim ( )
195
+ . into ( ) ;
196
+
197
+ let out_stdlib = out_dir. join ( "libstdc++.a" ) ;
198
+ std:: os:: unix:: fs:: symlink ( libstdc_path, out_stdlib) . unwrap ( ) ;
199
+
200
+ cc:: Build :: new ( )
201
+ . file ( "src/baz.cpp" )
202
+ . cpp ( true )
203
+ . cpp_link_stdlib ( "stdc++" )
204
+ . cpp_link_stdlib_static ( true )
205
+ . compile ( "baz" ) ;
206
+ }
176
207
}
177
208
178
209
#[ track_caller]
0 commit comments