1
+ // ignore-tidy-filelength
2
+
1
3
//! Contains infrastructure for configuring the compiler, including parsing
2
4
//! command-line options.
3
5
@@ -31,7 +33,7 @@ use std::fmt;
31
33
use std:: str:: { self , FromStr } ;
32
34
use std:: hash:: Hasher ;
33
35
use std:: collections:: hash_map:: DefaultHasher ;
34
- use std:: iter:: FromIterator ;
36
+ use std:: iter:: { self , FromIterator } ;
35
37
use std:: path:: { Path , PathBuf } ;
36
38
37
39
pub struct Config {
@@ -322,10 +324,35 @@ impl OutputTypes {
322
324
#[ derive( Clone ) ]
323
325
pub struct Externs ( BTreeMap < String , ExternEntry > ) ;
324
326
325
- #[ derive( Clone , Debug , Default ) ]
327
+ #[ derive( Clone , Debug ) ]
326
328
pub struct ExternEntry {
327
- pub locations : BTreeSet < Option < String > > ,
328
- pub is_private_dep : bool
329
+ pub location : ExternLocation ,
330
+ /// Indicates this is a "private" dependency for the
331
+ /// `exported_private_dependencies` lint.
332
+ ///
333
+ /// This can be set with the `priv` option like
334
+ /// `--extern priv:name=foo.rlib`.
335
+ pub is_private_dep : bool ,
336
+ /// Add the extern entry to the extern prelude.
337
+ ///
338
+ /// This can be disabled with the `noprelude` option like
339
+ /// `--extern noprelude:name`.
340
+ pub add_prelude : bool ,
341
+ }
342
+
343
+ #[ derive( Clone , Debug ) ]
344
+ pub enum ExternLocation {
345
+ /// Indicates to look for the library in the search paths.
346
+ ///
347
+ /// Added via `--extern name`.
348
+ FoundInLibrarySearchDirectories ,
349
+ /// The locations where this extern entry must be found.
350
+ ///
351
+ /// The `CrateLoader` is responsible for loading these and figuring out
352
+ /// which one to use.
353
+ ///
354
+ /// Added via `--extern prelude_name=some_file.rlib`
355
+ ExactPaths ( BTreeSet < String > ) ,
329
356
}
330
357
331
358
impl Externs {
@@ -342,6 +369,18 @@ impl Externs {
342
369
}
343
370
}
344
371
372
+ impl ExternEntry {
373
+ fn new ( location : ExternLocation ) -> ExternEntry {
374
+ ExternEntry { location, is_private_dep : false , add_prelude : false }
375
+ }
376
+
377
+ pub fn files ( & self ) -> Option < impl Iterator < Item = & String > > {
378
+ match & self . location {
379
+ ExternLocation :: ExactPaths ( set) => Some ( set. iter ( ) ) ,
380
+ _ => None ,
381
+ }
382
+ }
383
+ }
345
384
346
385
macro_rules! hash_option {
347
386
( $opt_name: ident, $opt_expr: expr, $sub_hashes: expr, [ UNTRACKED ] ) => ( { } ) ;
@@ -1869,12 +1908,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
1869
1908
"Specify where an external rust library is located" ,
1870
1909
"NAME[=PATH]" ,
1871
1910
) ,
1872
- opt:: multi_s(
1873
- "" ,
1874
- "extern-private" ,
1875
- "Specify where an extern rust library is located, marking it as a private dependency" ,
1876
- "NAME=PATH" ,
1877
- ) ,
1878
1911
opt:: opt_s( "" , "sysroot" , "Override the system root" , "PATH" ) ,
1879
1912
opt:: multi( "Z" , "" , "Set internal debugging options" , "FLAG" ) ,
1880
1913
opt:: opt_s(
@@ -2435,43 +2468,105 @@ fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType)
2435
2468
}
2436
2469
}
2437
2470
2438
- fn parse_externs (
2471
+ pub fn parse_externs (
2439
2472
matches : & getopts:: Matches ,
2440
2473
debugging_opts : & DebuggingOptions ,
2441
2474
error_format : ErrorOutputType ,
2442
2475
) -> Externs {
2443
- if matches. opt_present ( "extern-private" ) && !debugging_opts. unstable_options {
2444
- early_error (
2445
- ErrorOutputType :: default ( ) ,
2446
- "'--extern-private' is unstable and only \
2447
- available for nightly builds of rustc."
2448
- )
2449
- }
2450
-
2451
- // We start out with a `Vec<(Option<String>, bool)>>`,
2452
- // and later convert it into a `BTreeSet<(Option<String>, bool)>`
2453
- // This allows to modify entries in-place to set their correct
2454
- // 'public' value.
2476
+ let is_unstable_enabled = debugging_opts. unstable_options ;
2455
2477
let mut externs: BTreeMap < String , ExternEntry > = BTreeMap :: new ( ) ;
2456
- for ( arg, private) in matches. opt_strs ( "extern" ) . into_iter ( ) . map ( |v| ( v, false ) )
2457
- . chain ( matches. opt_strs ( "extern-private" ) . into_iter ( ) . map ( |v| ( v, true ) ) ) {
2458
-
2478
+ for arg in matches. opt_strs ( "extern" ) {
2459
2479
let mut parts = arg. splitn ( 2 , '=' ) ;
2460
- let name = parts. next ( ) . unwrap_or_else ( ||
2461
- early_error ( error_format, "--extern value must not be empty" ) ) ;
2462
- let location = parts. next ( ) . map ( |s| s. to_string ( ) ) ;
2480
+ let name = parts
2481
+ . next ( )
2482
+ . unwrap_or_else ( || early_error ( error_format, "--extern value must not be empty" ) ) ;
2483
+ let path = parts. next ( ) . map ( |s| s. to_string ( ) ) ;
2484
+
2485
+ let mut name_parts = name. splitn ( 2 , ':' ) ;
2486
+ let first_part = name_parts. next ( ) ;
2487
+ let second_part = name_parts. next ( ) ;
2488
+ let ( options, name) = match ( first_part, second_part) {
2489
+ ( Some ( opts) , Some ( name) ) => ( Some ( opts) , name) ,
2490
+ ( Some ( name) , None ) => ( None , name) ,
2491
+ ( None , None ) => early_error ( error_format, "--extern name must not be empty" ) ,
2492
+ _ => unreachable ! ( ) ,
2493
+ } ;
2494
+
2495
+ let entry = externs. entry ( name. to_owned ( ) ) ;
2463
2496
2464
- let entry = externs
2465
- . entry ( name. to_owned ( ) )
2466
- . or_default ( ) ;
2497
+ use std:: collections:: btree_map:: Entry ;
2467
2498
2499
+ let entry = if let Some ( path) = path {
2500
+ // --extern prelude_name=some_file.rlib
2501
+ match entry {
2502
+ Entry :: Vacant ( vacant) => {
2503
+ let files = BTreeSet :: from_iter ( iter:: once ( path) ) ;
2504
+ vacant. insert ( ExternEntry :: new ( ExternLocation :: ExactPaths ( files) ) )
2505
+ }
2506
+ Entry :: Occupied ( occupied) => {
2507
+ let ext_ent = occupied. into_mut ( ) ;
2508
+ match ext_ent {
2509
+ ExternEntry { location : ExternLocation :: ExactPaths ( files) , .. } => {
2510
+ files. insert ( path) ;
2511
+ }
2512
+ ExternEntry {
2513
+ location : location @ ExternLocation :: FoundInLibrarySearchDirectories ,
2514
+ ..
2515
+ } => {
2516
+ // Exact paths take precedence over search directories.
2517
+ let files = BTreeSet :: from_iter ( iter:: once ( path) ) ;
2518
+ * location = ExternLocation :: ExactPaths ( files) ;
2519
+ }
2520
+ }
2521
+ ext_ent
2522
+ }
2523
+ }
2524
+ } else {
2525
+ // --extern prelude_name
2526
+ match entry {
2527
+ Entry :: Vacant ( vacant) => {
2528
+ vacant. insert ( ExternEntry :: new ( ExternLocation :: FoundInLibrarySearchDirectories ) )
2529
+ }
2530
+ Entry :: Occupied ( occupied) => {
2531
+ // Ignore if already specified.
2532
+ occupied. into_mut ( )
2533
+ }
2534
+ }
2535
+ } ;
2468
2536
2469
- entry. locations . insert ( location. clone ( ) ) ;
2537
+ let mut is_private_dep = false ;
2538
+ let mut add_prelude = true ;
2539
+ if let Some ( opts) = options {
2540
+ if !is_unstable_enabled {
2541
+ early_error (
2542
+ error_format,
2543
+ "the `-Z unstable-options` flag must also be passed to \
2544
+ enable `--extern options",
2545
+ ) ;
2546
+ }
2547
+ for opt in opts. split ( ',' ) {
2548
+ match opt {
2549
+ "priv" => is_private_dep = true ,
2550
+ "noprelude" => {
2551
+ if let ExternLocation :: ExactPaths ( _) = & entry. location {
2552
+ add_prelude = false ;
2553
+ } else {
2554
+ early_error (
2555
+ error_format,
2556
+ "the `noprelude` --extern option requires a file path" ,
2557
+ ) ;
2558
+ }
2559
+ }
2560
+ _ => early_error ( error_format, & format ! ( "unknown --extern option `{}`" , opt) ) ,
2561
+ }
2562
+ }
2563
+ }
2470
2564
2471
- // Crates start out being not private,
2472
- // and go to being private if we see an '--extern-private'
2473
- // flag
2474
- entry. is_private_dep |= private;
2565
+ // Crates start out being not private, and go to being private `priv`
2566
+ // is specified.
2567
+ entry. is_private_dep |= is_private_dep;
2568
+ // If any flag is missing `noprelude`, then add to the prelude.
2569
+ entry. add_prelude |= add_prelude;
2475
2570
}
2476
2571
Externs ( externs)
2477
2572
}
0 commit comments