3
3
#[ cfg( feature = "rust-llvm" ) ]
4
4
extern crate aya_rustc_llvm_proxy;
5
5
6
- use std:: { env, fs, io, path:: PathBuf , str:: FromStr } ;
6
+ use std:: {
7
+ env, fs, io,
8
+ path:: { Component , Path , PathBuf } ,
9
+ str:: FromStr ,
10
+ } ;
7
11
8
12
use bpf_linker:: { Cpu , Linker , LinkerOptions , OptLevel , OutputType } ;
9
- use clap:: Parser ;
13
+ use clap:: {
14
+ builder:: { PathBufValueParser , TypedValueParser as _} ,
15
+ Parser ,
16
+ } ;
10
17
use thiserror:: Error ;
11
- use tracing:: { info, Level , Subscriber } ;
12
- use tracing_appender:: non_blocking:: WorkerGuard ;
18
+ use tracing:: { info, Level } ;
13
19
use tracing_subscriber:: { fmt:: MakeWriter , prelude:: * , EnvFilter } ;
14
20
use tracing_tree:: HierarchicalLayer ;
15
21
@@ -59,6 +65,20 @@ impl FromStr for CliOutputType {
59
65
}
60
66
}
61
67
68
+ fn parent_and_file_name ( p : PathBuf ) -> anyhow:: Result < ( PathBuf , PathBuf ) > {
69
+ let mut comps = p. components ( ) ;
70
+ let file_name = comps
71
+ . next_back ( )
72
+ . map ( |p| match p {
73
+ Component :: Normal ( p) => Ok ( p) ,
74
+ p => Err ( anyhow:: anyhow!( "unexpected path component {:?}" , p) ) ,
75
+ } )
76
+ . transpose ( ) ?
77
+ . ok_or_else ( || anyhow:: anyhow!( "unexpected empty path" ) ) ?;
78
+ let parent = comps. as_path ( ) ;
79
+ Ok ( ( parent. to_path_buf ( ) , Path :: new ( file_name) . to_path_buf ( ) ) )
80
+ }
81
+
62
82
#[ derive( Debug , Parser ) ]
63
83
struct CommandLine {
64
84
/// LLVM target triple. When not provided, the target is inferred from the inputs
@@ -100,8 +120,12 @@ struct CommandLine {
100
120
export_symbols : Option < PathBuf > ,
101
121
102
122
/// Output logs to the given `path`
103
- #[ clap( long, value_name = "path" ) ]
104
- log_file : Option < PathBuf > ,
123
+ #[ clap(
124
+ long,
125
+ value_name = "path" ,
126
+ value_parser = PathBufValueParser :: new( ) . try_map( parent_and_file_name) ,
127
+ ) ]
128
+ log_file : Option < ( PathBuf , PathBuf ) > ,
105
129
106
130
/// Set the log level. If not specified, no logging is used. Can be one of
107
131
/// `error`, `warn`, `info`, `debug`, `trace`.
@@ -135,6 +159,7 @@ struct CommandLine {
135
159
disable_memory_builtins : bool ,
136
160
137
161
/// Input files. Can be object files or static libraries
162
+ #[ clap( required = true ) ]
138
163
inputs : Vec < PathBuf > ,
139
164
140
165
/// Comma separated list of symbols to export. See also `--export-symbols`
@@ -161,8 +186,7 @@ where
161
186
. with_indent_lines ( true )
162
187
. with_writer ( writer)
163
188
}
164
-
165
- fn main ( ) {
189
+ fn main ( ) -> anyhow:: Result < ( ) > {
166
190
let args = env:: args ( ) . map ( |arg| {
167
191
if arg == "-flavor" {
168
192
"--flavor" . to_string ( )
@@ -192,57 +216,40 @@ fn main() {
192
216
export,
193
217
fatal_errors,
194
218
_debug,
195
- } = Parser :: parse_from ( args) ;
196
-
197
- if inputs. is_empty ( ) {
198
- error ( "no input files" , clap:: error:: ErrorKind :: TooFewValues ) ;
199
- }
219
+ } = Parser :: try_parse_from ( args) ?;
200
220
201
221
// Configure tracing.
202
- if let Some ( log_level) = log_level {
203
- let subscriber_registry = tracing_subscriber:: registry ( )
204
- . with ( EnvFilter :: from_default_env ( ) . add_directive ( log_level. into ( ) ) ) ;
205
- let ( subscriber, _guard) : (
206
- Box < dyn Subscriber + Send + Sync + ' static > ,
207
- Option < WorkerGuard > ,
208
- ) = match log_file {
209
- Some ( log_file) => {
210
- let file_appender = tracing_appender:: rolling:: never (
211
- log_file. parent ( ) . unwrap_or_else ( || {
212
- error ( "invalid log_file" , clap:: error:: ErrorKind :: InvalidValue )
213
- } ) ,
214
- log_file. file_name ( ) . unwrap_or_else ( || {
215
- error ( "invalid log_file" , clap:: error:: ErrorKind :: InvalidValue )
216
- } ) ,
217
- ) ;
218
- let ( non_blocking, _guard) = tracing_appender:: non_blocking ( file_appender) ;
222
+ let _guard = {
223
+ let filter = EnvFilter :: from_default_env ( ) ;
224
+ let filter = match log_level {
225
+ None => filter,
226
+ Some ( log_level) => filter. add_directive ( log_level. into ( ) ) ,
227
+ } ;
228
+ let subscriber_registry = tracing_subscriber:: registry ( ) . with ( filter) ;
229
+ match log_file {
230
+ Some ( ( parent, file_name) ) => {
231
+ let file_appender = tracing_appender:: rolling:: never ( parent, file_name) ;
232
+ let ( non_blocking, guard) = tracing_appender:: non_blocking ( file_appender) ;
219
233
let subscriber = subscriber_registry
220
234
. with ( tracing_layer ( io:: stdout) )
221
235
. with ( tracing_layer ( non_blocking) ) ;
222
-
223
- ( Box :: new ( subscriber ) , Some ( _guard ) )
236
+ tracing :: subscriber :: set_global_default ( subscriber ) ? ;
237
+ Some ( guard )
224
238
}
225
239
None => {
226
240
let subscriber = subscriber_registry. with ( tracing_layer ( io:: stderr) ) ;
227
- ( Box :: new ( subscriber) , None )
241
+ tracing:: subscriber:: set_global_default ( subscriber) ?;
242
+ None
228
243
}
229
- } ;
230
- if let Err ( e) = tracing:: subscriber:: set_global_default ( subscriber) {
231
- error ( & e. to_string ( ) , clap:: error:: ErrorKind :: Format ) ;
232
244
}
233
- }
245
+ } ;
234
246
235
247
info ! (
236
248
"command line: {:?}" ,
237
249
env:: args( ) . collect:: <Vec <_>>( ) . join( " " )
238
250
) ;
239
251
240
- let export_symbols = export_symbols
241
- . map ( fs:: read_to_string)
242
- . transpose ( )
243
- . unwrap_or_else ( |e| {
244
- error ( & e. to_string ( ) , clap:: error:: ErrorKind :: Io ) ;
245
- } ) ;
252
+ let export_symbols = export_symbols. map ( fs:: read_to_string) . transpose ( ) ?;
246
253
247
254
// TODO: the data is owned by this call frame; we could make this zero-alloc.
248
255
let export_symbols = export_symbols
@@ -282,20 +289,15 @@ fn main() {
282
289
btf,
283
290
} ) ;
284
291
285
- if let Err ( e) = linker. link ( ) {
286
- error ( & e. to_string ( ) , clap:: error:: ErrorKind :: Io ) ;
287
- }
292
+ linker. link ( ) ?;
288
293
289
294
if fatal_errors && linker. has_errors ( ) {
290
- error (
291
- "LLVM issued diagnostic with error severity" ,
292
- clap:: error:: ErrorKind :: Io ,
293
- ) ;
295
+ return Err ( anyhow:: anyhow!(
296
+ "LLVM issued diagnostic with error severity"
297
+ ) ) ;
294
298
}
295
- }
296
299
297
- fn error ( desc : & str , kind : clap:: error:: ErrorKind ) -> ! {
298
- clap:: Error :: raw ( kind, desc. to_string ( ) ) . exit ( ) ;
300
+ Ok ( ( ) )
299
301
}
300
302
301
303
#[ cfg( test) ]
0 commit comments