@@ -7,21 +7,25 @@ mod driver;
7
7
mod lints;
8
8
9
9
use std:: {
10
- ffi:: OsStr ,
10
+ ffi:: { OsStr , OsString } ,
11
11
fs:: create_dir_all,
12
+ io:: { self , Write } ,
13
+ os:: unix:: prelude:: OsStrExt ,
12
14
path:: { Path , PathBuf } ,
13
- process:: { exit, Command } ,
15
+ process:: exit,
14
16
} ;
15
17
16
18
use cli:: get_clap_config;
17
- use driver:: get_driver_path;
19
+ use driver:: { get_driver_path, run_driver} ;
20
+ use lints:: build_local_lint_crate;
18
21
use once_cell:: sync:: Lazy ;
19
22
23
+ use crate :: driver:: print_driver_version;
24
+
20
25
const CARGO_ARGS_SEPARATOR : & str = "--" ;
21
26
const VERSION : & str = concat ! ( "cargo-marker " , env!( "CARGO_PKG_VERSION" ) ) ;
22
27
const LINT_KRATES_BASE_DIR : & str = "./target/marker" ;
23
- static LINT_KRATES_TARGET_DIR : Lazy < String > = Lazy :: new ( || prepare_lint_build_dir ( "build" , "target" ) ) ;
24
- static LINT_KRATES_OUT_DIR : Lazy < String > = Lazy :: new ( || prepare_lint_build_dir ( "lints" , "out" ) ) ;
28
+ static MARKER_LINT_DIR : Lazy < String > = Lazy :: new ( || prepare_lint_build_dir ( "marker" , "marker" ) ) ;
25
29
26
30
#[ derive( Debug ) ]
27
31
pub enum ExitStatus {
@@ -35,6 +39,12 @@ pub enum ExitStatus {
35
39
DriverInstallationFailed = 300 ,
36
40
/// A general collection status, for failures originating from the driver
37
41
DriverFailed = 400 ,
42
+ /// The lint crate build failed for some reason
43
+ LintCrateBuildFail = 500 ,
44
+ /// Lint crate could not be found
45
+ LintCrateNotFound = 501 ,
46
+ /// The lint crate has been build, but the resulting binary could not be found.
47
+ LintCrateLibNotFound = 502 ,
38
48
/// Check failed
39
49
MarkerCheckFailed = 1000 ,
40
50
}
@@ -71,7 +81,7 @@ fn main() -> Result<(), ExitStatus> {
71
81
let verbose = matches. get_flag ( "verbose" ) ;
72
82
73
83
if matches. get_flag ( "version" ) {
74
- print_version ( ) ;
84
+ print_version ( verbose ) ;
75
85
return Ok ( ( ) ) ;
76
86
}
77
87
@@ -85,14 +95,15 @@ fn main() -> Result<(), ExitStatus> {
85
95
86
96
fn run_check ( matches : & clap:: ArgMatches , verbose : bool ) -> Result < ( ) , ExitStatus > {
87
97
let mut lint_crates = vec ! [ ] ;
88
- if let Some ( cmd_lint_crates) = matches. get_many :: < String > ( "lints" ) {
98
+ if let Some ( cmd_lint_crates) = matches. get_many :: < OsString > ( "lints" ) {
89
99
println ! ( ) ;
90
100
println ! ( "Compiling Lints:" ) ;
91
101
lint_crates. reserve ( cmd_lint_crates. len ( ) ) ;
102
+ let target_dir = Path :: new ( & * MARKER_LINT_DIR ) ;
92
103
for krate in cmd_lint_crates {
93
- if let Ok ( krate_dir ) = prepare_lint_crate ( krate, verbose ) {
94
- lint_crates . push ( krate_dir ) ;
95
- }
104
+ let src_dir = PathBuf :: from ( krate) ;
105
+ let crate_file = build_local_lint_crate ( src_dir . as_path ( ) , target_dir , verbose ) ? ;
106
+ lint_crates . push ( crate_file . as_os_str ( ) . to_os_string ( ) ) ;
96
107
}
97
108
}
98
109
@@ -101,115 +112,46 @@ fn run_check(matches: &clap::ArgMatches, verbose: bool) -> Result<(), ExitStatus
101
112
exit ( -1 ) ;
102
113
}
103
114
104
- if lint_crates. iter ( ) . any ( |path| path. contains ( ';' ) ) {
115
+ if lint_crates. iter ( ) . any ( |path| path. to_string_lossy ( ) . contains ( ';' ) ) {
105
116
eprintln ! ( "The absolute paths of lint crates are not allowed to contain a `;`" ) ;
106
117
exit ( -1 ) ;
107
118
}
108
119
109
- let driver_path = get_driver_path ( ) ;
110
- let marker_crates_env = lint_crates. join ( ";" ) ;
120
+ #[ rustfmt:: skip]
121
+ let env = vec ! [
122
+ ( OsString :: from( "RUSTC_WORKSPACE_WRAPPER" ) , get_driver_path( ) . as_os_str( ) . to_os_string( ) ) ,
123
+ ( OsString :: from( "MARKER_LINT_CRATES" ) , lint_crates. join( OsStr :: new( ";" ) ) )
124
+ ] ;
111
125
if matches. get_flag ( "test-setup" ) {
112
- println ! ( "env:RUSTC_WORKSPACE_WRAPPER={}" , driver_path. display( ) ) ;
113
- println ! ( "env:MARKER_LINT_CRATES={marker_crates_env}" ) ;
126
+ print_env ( env) . unwrap ( ) ;
114
127
Ok ( ( ) )
115
128
} else {
116
- run_driver ( & driver_path, & marker_crates_env)
129
+ let cargo_args = std:: env:: args ( ) . skip_while ( |c| c != CARGO_ARGS_SEPARATOR ) . skip ( 1 ) ;
130
+ run_driver ( env, cargo_args, verbose)
117
131
}
118
132
}
119
133
120
- fn print_version ( ) {
134
+ fn print_version ( verbose : bool ) {
121
135
println ! ( "cargo-marker version: {}" , env!( "CARGO_PKG_VERSION" ) ) ;
122
- }
123
-
124
- fn run_driver ( driver_path : & PathBuf , lint_crates : & str ) -> Result < ( ) , ExitStatus > {
125
- println ! ( ) ;
126
- println ! ( "Start linting:" ) ;
127
-
128
- let mut cmd = Command :: new ( "cargo" ) ;
129
- let cargo_args = std:: env:: args ( ) . skip_while ( |c| c != CARGO_ARGS_SEPARATOR ) . skip ( 1 ) ;
130
- cmd. env ( "RUSTC_WORKSPACE_WRAPPER" , driver_path)
131
- . env ( "MARKER_LINT_CRATES" , lint_crates)
132
- . arg ( "check" )
133
- . args ( cargo_args) ;
134
-
135
- let exit_status = cmd
136
- . spawn ( )
137
- . expect ( "could not run cargo" )
138
- . wait ( )
139
- . expect ( "failed to wait for cargo?" ) ;
140
136
141
- if exit_status. success ( ) {
142
- Ok ( ( ) )
143
- } else {
144
- Err ( ExitStatus :: MarkerCheckFailed )
137
+ if verbose {
138
+ print_driver_version ( ) ;
145
139
}
146
140
}
147
141
148
- /// This function ensures that the given crate is compiled as a library and
149
- /// returns the compiled library path if everything was successful. Otherwise
150
- /// it'll issue a warning and return `Err`
151
- fn prepare_lint_crate ( krate : & str , verbose : bool ) -> Result < String , ( ) > {
152
- let path = Path :: new ( krate) ;
153
- if !path. exists ( ) {
154
- eprintln ! ( "The given lint can't be found, searched at: `{}`" , path. display( ) ) ;
155
- return Err ( ( ) ) ;
156
- }
157
-
158
- let mut cmd = cargo_command ( verbose) ;
159
- let exit_status = cmd
160
- . current_dir ( std:: fs:: canonicalize ( path) . unwrap ( ) )
161
- . args ( [
162
- "build" ,
163
- "--lib" ,
164
- "--target-dir" ,
165
- & * LINT_KRATES_TARGET_DIR ,
166
- "-Z" ,
167
- "unstable-options" ,
168
- "--out-dir" ,
169
- & * LINT_KRATES_OUT_DIR ,
170
- ] )
171
- . env ( "RUSTFLAGS" , "--cap-lints=allow" )
172
- . spawn ( )
173
- . expect ( "could not run cargo" )
174
- . wait ( )
175
- . expect ( "failed to wait for cargo?" ) ;
176
-
177
- if !exit_status. success ( ) {
178
- return Err ( ( ) ) ;
142
+ fn print_env ( env : Vec < ( OsString , OsString ) > ) -> io:: Result < ( ) > {
143
+ // This directly uses the lock, to print the os strings correctly, the
144
+ // UTF-8 conversion could otherwise fail or be incomplete. This would be
145
+ // so much easier if everyone would follow the "UTF-8 Everywhere Manifesto"
146
+ let mut lock = io:: stdout ( ) . lock ( ) ;
147
+
148
+ for ( name, value) in env {
149
+ write ! ( lock, "env:" ) ?;
150
+ lock. write_all ( name. as_bytes ( ) ) ?;
151
+ write ! ( lock, "=" ) ?;
152
+ lock. write_all ( value. as_bytes ( ) ) ?;
153
+ writeln ! ( lock) ?;
179
154
}
180
155
181
- #[ cfg( any( target_os = "linux" , target_os = "macos" ) ) ]
182
- let lib_file_prefix = "lib" ;
183
- #[ cfg( target_os = "windows" ) ]
184
- let lib_file_prefix = "" ;
185
-
186
- // FIXME: currently this expect, that the lib name is the same as the crate dir.
187
- let file_name = format ! (
188
- "{lib_file_prefix}{}" ,
189
- path. file_name( ) . and_then( OsStr :: to_str) . unwrap_or_default( )
190
- ) ;
191
- let mut krate_path = Path :: new ( & * LINT_KRATES_OUT_DIR ) . join ( file_name) ;
192
-
193
- #[ cfg( target_os = "linux" ) ]
194
- krate_path. set_extension ( "so" ) ;
195
- #[ cfg( target_os = "macos" ) ]
196
- krate_path. set_extension ( "dylib" ) ;
197
- #[ cfg( target_os = "windows" ) ]
198
- krate_path. set_extension ( "dll" ) ;
199
-
200
- Ok ( krate_path. display ( ) . to_string ( ) )
201
- }
202
-
203
- fn cargo_command ( verbose : bool ) -> Command {
204
- // Here we want to use the normal cargo command, to go through the rustup
205
- // cargo executable and with that, set the required toolchain version.
206
- // This will add a slight overhead to each cargo call. This feels a bit
207
- // unavoidable, until marker is delivered as part of the toolchain. Let's
208
- // hope that day will happen!
209
- let mut cmd = Command :: new ( "cargo" ) ;
210
-
211
- if verbose {
212
- cmd. arg ( "--verbose" ) ;
213
- }
214
- cmd
156
+ Ok ( ( ) )
215
157
}
0 commit comments