1- use crate :: Result ;
1+ use crate :: { Result , TestGenerator } ;
22use std:: env;
33use std:: fs:: { canonicalize, File } ;
44use std:: io:: Write ;
55use std:: path:: { Path , PathBuf } ;
66use std:: process:: Command ;
77
8+ /// Generate all tests for the given crate and output the Rust side to a file.
9+ pub fn generate_test (
10+ generator : & mut TestGenerator ,
11+ crate_path : impl AsRef < Path > ,
12+ output_file_path : impl AsRef < Path > ,
13+ ) -> Result < PathBuf > {
14+ let output_file_path = generator. generate_files ( crate_path, output_file_path) ?;
15+
16+ // Search for the target and host to build for if specified manually (generator.target, generator.host),
17+ // via build script (TARGET, HOST), or for internal testing (TARGET_PLATFORM, HOST_PLATFORM).
18+ let target = generator. target . clone ( ) . unwrap_or_else ( || {
19+ env:: var ( "TARGET" ) . unwrap_or_else ( |_| env:: var ( "TARGET_PLATFORM" ) . unwrap ( ) )
20+ } ) ;
21+ let host = generator
22+ . host
23+ . clone ( )
24+ . unwrap_or_else ( || env:: var ( "HOST" ) . unwrap_or_else ( |_| env:: var ( "HOST_PLATFORM" ) . unwrap ( ) ) ) ;
25+
26+ let mut cfg = cc:: Build :: new ( ) ;
27+ // FIXME: Cpp not supported.
28+ cfg. file ( output_file_path. with_extension ( "c" ) ) ;
29+ cfg. host ( & host) ;
30+
31+ if target. contains ( "msvc" ) {
32+ cfg. flag ( "/W3" )
33+ . flag ( "/Wall" )
34+ . flag ( "/WX" )
35+ // ignored warnings
36+ . flag ( "/wd4820" ) // warning about adding padding?
37+ . flag ( "/wd4100" ) // unused parameters
38+ . flag ( "/wd4996" ) // deprecated functions
39+ . flag ( "/wd4296" ) // '<' being always false
40+ . flag ( "/wd4255" ) // converting () to (void)
41+ . flag ( "/wd4668" ) // using an undefined thing in preprocessor?
42+ . flag ( "/wd4366" ) // taking ref to packed struct field might be unaligned
43+ . flag ( "/wd4189" ) // local variable initialized but not referenced
44+ . flag ( "/wd4710" ) // function not inlined
45+ . flag ( "/wd5045" ) // compiler will insert Spectre mitigation
46+ . flag ( "/wd4514" ) // unreferenced inline function removed
47+ . flag ( "/wd4711" ) ; // function selected for automatic inline
48+ } else {
49+ cfg. flag ( "-Wall" )
50+ . flag ( "-Wextra" )
51+ . flag ( "-Werror" )
52+ . flag ( "-Wno-unused-parameter" )
53+ . flag ( "-Wno-type-limits" )
54+ // allow taking address of packed struct members:
55+ . flag ( "-Wno-address-of-packed-member" )
56+ . flag ( "-Wno-unknown-warning-option" )
57+ . flag ( "-Wno-deprecated-declarations" ) ; // allow deprecated items
58+ }
59+
60+ for p in & generator. includes {
61+ cfg. include ( p) ;
62+ }
63+
64+ let stem: & str = output_file_path. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
65+ cfg. target ( & target)
66+ . out_dir ( output_file_path. parent ( ) . unwrap ( ) )
67+ . compile ( stem) ;
68+
69+ Ok ( output_file_path)
70+ }
71+
872/// Compiles a Rust source file and links it against a static library.
973///
1074/// Returns the path to the generated binary.
11- pub fn compile_test < P : AsRef < Path > > (
12- output_dir : P ,
13- crate_path : P ,
14- library_file : P ,
75+ #[ doc( hidden) ]
76+ pub fn __compile_test (
77+ output_dir : impl AsRef < Path > ,
78+ crate_path : impl AsRef < Path > ,
79+ library_file : impl AsRef < Path > ,
1580) -> Result < PathBuf > {
1681 let rustc = env:: var ( "RUSTC" ) . unwrap_or_else ( |_| "rustc" . into ( ) ) ;
1782 let output_dir = output_dir. as_ref ( ) ;
1883 let crate_path = crate_path. as_ref ( ) ;
19- let library_file = library_file. as_ref ( ) ;
84+ let library_file = library_file. as_ref ( ) . file_stem ( ) . unwrap ( ) ;
2085
2186 let rust_file = output_dir
2287 . join ( crate_path. file_stem ( ) . unwrap ( ) )
2388 . with_extension ( "rs" ) ;
2489 let binary_path = output_dir. join ( rust_file. file_stem ( ) . unwrap ( ) ) ;
2590
91+ // Create a file that contains the Rust 'bindings' as well as the generated test code.
2692 File :: create ( & rust_file) ?. write_all (
2793 format ! (
2894 "include!(r#\" {}\" #);\n include!(r#\" {}.rs\" #);" ,
2995 canonicalize( crate_path) ?. display( ) ,
30- library_file. display ( )
96+ library_file. to_str ( ) . unwrap ( )
3197 )
3298 . as_bytes ( ) ,
3399 ) ?;
34100
101+ // Compile the test file with the compiled C library file found in `output_dir`
102+ // into a binary file, ignoring all warnings about unused items. (not all items
103+ // are currently tested)
104+
35105 let mut cmd = Command :: new ( rustc) ;
36106 cmd. arg ( & rust_file)
37107 . arg ( format ! ( "-Lnative={}" , output_dir. display( ) ) )
38- . arg ( format ! (
39- "-lstatic={}" ,
40- library_file. file_stem( ) . unwrap( ) . to_str( ) . unwrap( )
41- ) )
42- . arg ( "--target" )
43- . arg ( env:: var ( "TARGET_PLATFORM" ) . unwrap ( ) )
108+ . arg ( format ! ( "-lstatic={}" , library_file. to_str( ) . unwrap( ) ) )
109+ . arg ( "--edition" )
110+ . arg ( "2021" ) // Defaults to 2015.
44111 . arg ( "-o" )
45112 . arg ( & binary_path)
46113 . arg ( "-Aunused" ) ;
47114
115+ // Pass in a different target, linker or flags if set, useful for cross compilation.
116+
117+ let target = env:: var ( "TARGET_PLATFORM" ) . unwrap_or_default ( ) ;
118+ if !target. is_empty ( ) {
119+ cmd. arg ( "--target" ) . arg ( target) ;
120+ }
121+
48122 let linker = env:: var ( "LINKER" ) . unwrap_or_default ( ) ;
49123 if !linker. is_empty ( ) {
50124 cmd. arg ( format ! ( "-Clinker={linker}" ) ) ;
@@ -64,14 +138,17 @@ pub fn compile_test<P: AsRef<Path>>(
64138}
65139
66140/// Executes the compiled test binary and returns its output.
67- pub fn run_test ( test_binary : & str ) -> Result < String > {
141+ ///
142+ /// If a RUNNER environment variable is present, it will use that to run the binary.
143+ #[ doc( hidden) ]
144+ pub fn __run_test < P : AsRef < Path > > ( test_binary : P ) -> Result < String > {
68145 let runner = env:: var ( "RUNNER" ) . unwrap_or_default ( ) ;
69146 let output = if runner. is_empty ( ) {
70- Command :: new ( test_binary) . output ( ) ?
147+ Command :: new ( test_binary. as_ref ( ) ) . output ( ) ?
71148 } else {
72149 let mut args = runner. split_whitespace ( ) ;
73150 let mut cmd = Command :: new ( args. next ( ) . unwrap ( ) ) ;
74- cmd. args ( args) . arg ( test_binary) . output ( ) ?
151+ cmd. args ( args) . arg ( test_binary. as_ref ( ) ) . output ( ) ?
75152 } ;
76153
77154 if !output. status . success ( ) {
0 commit comments