@@ -184,97 +184,9 @@ impl Display for Error {
184
184
185
185
impl std:: error:: Error for Error { }
186
186
187
- /// Configuration used to represent an invocation of a C compiler.
188
- ///
189
- /// This can be used to figure out what compiler is in use, what the arguments
190
- /// to it are, and what the environment variables look like for the compiler.
191
- /// This can be used to further configure other build systems (e.g. forward
192
- /// along CC and/or CFLAGS) or the `to_command` method can be used to run the
193
- /// compiler itself.
194
- #[ derive( Clone , Debug ) ]
195
- pub struct Tool {
196
- path : PathBuf ,
197
- cc_wrapper_path : Option < PathBuf > ,
198
- cc_wrapper_args : Vec < OsString > ,
199
- args : Vec < OsString > ,
200
- env : Vec < ( OsString , OsString ) > ,
201
- family : ToolFamily ,
202
- cuda : bool ,
203
- removed_args : Vec < OsString > ,
204
- has_internal_target_arg : bool ,
205
- }
206
-
207
- /// Represents the family of tools this tool belongs to.
208
- ///
209
- /// Each family of tools differs in how and what arguments they accept.
210
- ///
211
- /// Detection of a family is done on best-effort basis and may not accurately reflect the tool.
212
- #[ derive( Copy , Clone , Debug , PartialEq ) ]
213
- enum ToolFamily {
214
- /// Tool is GNU Compiler Collection-like.
215
- Gnu ,
216
- /// Tool is Clang-like. It differs from the GCC in a sense that it accepts superset of flags
217
- /// and its cross-compilation approach is different.
218
- Clang ,
219
- /// Tool is the MSVC cl.exe.
220
- Msvc { clang_cl : bool } ,
221
- }
222
-
223
- impl ToolFamily {
224
- /// What the flag to request debug info for this family of tools look like
225
- fn add_debug_flags ( & self , cmd : & mut Tool , dwarf_version : Option < u32 > ) {
226
- match * self {
227
- ToolFamily :: Msvc { .. } => {
228
- cmd. push_cc_arg ( "-Z7" . into ( ) ) ;
229
- }
230
- ToolFamily :: Gnu | ToolFamily :: Clang => {
231
- cmd. push_cc_arg (
232
- dwarf_version
233
- . map_or_else ( || "-g" . into ( ) , |v| format ! ( "-gdwarf-{}" , v) )
234
- . into ( ) ,
235
- ) ;
236
- }
237
- }
238
- }
239
-
240
- /// What the flag to force frame pointers.
241
- fn add_force_frame_pointer ( & self , cmd : & mut Tool ) {
242
- match * self {
243
- ToolFamily :: Gnu | ToolFamily :: Clang => {
244
- cmd. push_cc_arg ( "-fno-omit-frame-pointer" . into ( ) ) ;
245
- }
246
- _ => ( ) ,
247
- }
248
- }
249
-
250
- /// What the flags to enable all warnings
251
- fn warnings_flags ( & self ) -> & ' static str {
252
- match * self {
253
- ToolFamily :: Msvc { .. } => "-W4" ,
254
- ToolFamily :: Gnu | ToolFamily :: Clang => "-Wall" ,
255
- }
256
- }
257
-
258
- /// What the flags to enable extra warnings
259
- fn extra_warnings_flags ( & self ) -> Option < & ' static str > {
260
- match * self {
261
- ToolFamily :: Msvc { .. } => None ,
262
- ToolFamily :: Gnu | ToolFamily :: Clang => Some ( "-Wextra" ) ,
263
- }
264
- }
265
-
266
- /// What the flag to turn warning into errors
267
- fn warnings_to_errors_flag ( & self ) -> & ' static str {
268
- match * self {
269
- ToolFamily :: Msvc { .. } => "-WX" ,
270
- ToolFamily :: Gnu | ToolFamily :: Clang => "-Werror" ,
271
- }
272
- }
273
-
274
- fn verbose_stderr ( & self ) -> bool {
275
- * self == ToolFamily :: Clang
276
- }
277
- }
187
+ mod tool;
188
+ pub use tool:: Tool ;
189
+ use tool:: ToolFamily ;
278
190
279
191
/// Represents an object.
280
192
///
@@ -3549,280 +3461,6 @@ impl Default for Build {
3549
3461
}
3550
3462
}
3551
3463
3552
- impl Tool {
3553
- fn new ( path : PathBuf , cargo_output : & CargoOutput ) -> Self {
3554
- Tool :: with_features ( path, None , false , cargo_output)
3555
- }
3556
-
3557
- fn with_clang_driver (
3558
- path : PathBuf ,
3559
- clang_driver : Option < & str > ,
3560
- cargo_output : & CargoOutput ,
3561
- ) -> Self {
3562
- Self :: with_features ( path, clang_driver, false , cargo_output)
3563
- }
3564
-
3565
- #[ cfg( windows) ]
3566
- /// Explicitly set the `ToolFamily`, skipping name-based detection.
3567
- fn with_family ( path : PathBuf , family : ToolFamily ) -> Self {
3568
- Self {
3569
- path,
3570
- cc_wrapper_path : None ,
3571
- cc_wrapper_args : Vec :: new ( ) ,
3572
- args : Vec :: new ( ) ,
3573
- env : Vec :: new ( ) ,
3574
- family,
3575
- cuda : false ,
3576
- removed_args : Vec :: new ( ) ,
3577
- has_internal_target_arg : false ,
3578
- }
3579
- }
3580
-
3581
- fn with_features (
3582
- path : PathBuf ,
3583
- clang_driver : Option < & str > ,
3584
- cuda : bool ,
3585
- cargo_output : & CargoOutput ,
3586
- ) -> Self {
3587
- fn detect_family ( path : & Path , cargo_output : & CargoOutput ) -> ToolFamily {
3588
- let mut cmd = Command :: new ( path) ;
3589
- cmd. arg ( "--version" ) ;
3590
-
3591
- let stdout = match run_output (
3592
- & mut cmd,
3593
- & path. to_string_lossy ( ) ,
3594
- // tool detection issues should always be shown as warnings
3595
- cargo_output,
3596
- )
3597
- . ok ( )
3598
- . and_then ( |o| String :: from_utf8 ( o) . ok ( ) )
3599
- {
3600
- Some ( s) => s,
3601
- None => {
3602
- // --version failed. fallback to gnu
3603
- cargo_output. print_warning ( & format_args ! ( "Failed to run: {:?}" , cmd) ) ;
3604
- return ToolFamily :: Gnu ;
3605
- }
3606
- } ;
3607
- if stdout. contains ( "clang" ) {
3608
- ToolFamily :: Clang
3609
- } else if stdout. contains ( "GCC" ) {
3610
- ToolFamily :: Gnu
3611
- } else {
3612
- // --version doesn't include clang for GCC
3613
- cargo_output. print_warning ( & format_args ! (
3614
- "Compiler version doesn't include clang or GCC: {:?}" ,
3615
- cmd
3616
- ) ) ;
3617
- ToolFamily :: Gnu
3618
- }
3619
- }
3620
-
3621
- // Try to detect family of the tool from its name, falling back to Gnu.
3622
- let family = if let Some ( fname) = path. file_name ( ) . and_then ( |p| p. to_str ( ) ) {
3623
- if fname. contains ( "clang-cl" ) {
3624
- ToolFamily :: Msvc { clang_cl : true }
3625
- } else if fname. ends_with ( "cl" ) || fname == "cl.exe" {
3626
- ToolFamily :: Msvc { clang_cl : false }
3627
- } else if fname. contains ( "clang" ) {
3628
- match clang_driver {
3629
- Some ( "cl" ) => ToolFamily :: Msvc { clang_cl : true } ,
3630
- _ => ToolFamily :: Clang ,
3631
- }
3632
- } else {
3633
- detect_family ( & path, cargo_output)
3634
- }
3635
- } else {
3636
- detect_family ( & path, cargo_output)
3637
- } ;
3638
-
3639
- Tool {
3640
- path,
3641
- cc_wrapper_path : None ,
3642
- cc_wrapper_args : Vec :: new ( ) ,
3643
- args : Vec :: new ( ) ,
3644
- env : Vec :: new ( ) ,
3645
- family,
3646
- cuda,
3647
- removed_args : Vec :: new ( ) ,
3648
- has_internal_target_arg : false ,
3649
- }
3650
- }
3651
-
3652
- /// Add an argument to be stripped from the final command arguments.
3653
- fn remove_arg ( & mut self , flag : OsString ) {
3654
- self . removed_args . push ( flag) ;
3655
- }
3656
-
3657
- /// Push an "exotic" flag to the end of the compiler's arguments list.
3658
- ///
3659
- /// Nvidia compiler accepts only the most common compiler flags like `-D`,
3660
- /// `-I`, `-c`, etc. Options meant specifically for the underlying
3661
- /// host C++ compiler have to be prefixed with `-Xcompiler`.
3662
- /// [Another possible future application for this function is passing
3663
- /// clang-specific flags to clang-cl, which otherwise accepts only
3664
- /// MSVC-specific options.]
3665
- fn push_cc_arg ( & mut self , flag : OsString ) {
3666
- if self . cuda {
3667
- self . args . push ( "-Xcompiler" . into ( ) ) ;
3668
- }
3669
- self . args . push ( flag) ;
3670
- }
3671
-
3672
- /// Checks if an argument or flag has already been specified or conflicts.
3673
- ///
3674
- /// Currently only checks optimization flags.
3675
- fn is_duplicate_opt_arg ( & self , flag : & OsString ) -> bool {
3676
- let flag = flag. to_str ( ) . unwrap ( ) ;
3677
- let mut chars = flag. chars ( ) ;
3678
-
3679
- // Only duplicate check compiler flags
3680
- if self . is_like_msvc ( ) {
3681
- if chars. next ( ) != Some ( '/' ) {
3682
- return false ;
3683
- }
3684
- } else if self . is_like_gnu ( ) || self . is_like_clang ( ) {
3685
- if chars. next ( ) != Some ( '-' ) {
3686
- return false ;
3687
- }
3688
- }
3689
-
3690
- // Check for existing optimization flags (-O, /O)
3691
- if chars. next ( ) == Some ( 'O' ) {
3692
- return self
3693
- . args ( )
3694
- . iter ( )
3695
- . any ( |a| a. to_str ( ) . unwrap_or ( "" ) . chars ( ) . nth ( 1 ) == Some ( 'O' ) ) ;
3696
- }
3697
-
3698
- // TODO Check for existing -m..., -m...=..., /arch:... flags
3699
- false
3700
- }
3701
-
3702
- /// Don't push optimization arg if it conflicts with existing args.
3703
- fn push_opt_unless_duplicate ( & mut self , flag : OsString ) {
3704
- if self . is_duplicate_opt_arg ( & flag) {
3705
- println ! ( "Info: Ignoring duplicate arg {:?}" , & flag) ;
3706
- } else {
3707
- self . push_cc_arg ( flag) ;
3708
- }
3709
- }
3710
-
3711
- /// Converts this compiler into a `Command` that's ready to be run.
3712
- ///
3713
- /// This is useful for when the compiler needs to be executed and the
3714
- /// command returned will already have the initial arguments and environment
3715
- /// variables configured.
3716
- pub fn to_command ( & self ) -> Command {
3717
- let mut cmd = match self . cc_wrapper_path {
3718
- Some ( ref cc_wrapper_path) => {
3719
- let mut cmd = Command :: new ( cc_wrapper_path) ;
3720
- cmd. arg ( & self . path ) ;
3721
- cmd
3722
- }
3723
- None => Command :: new ( & self . path ) ,
3724
- } ;
3725
- cmd. args ( & self . cc_wrapper_args ) ;
3726
-
3727
- let value = self
3728
- . args
3729
- . iter ( )
3730
- . filter ( |a| !self . removed_args . contains ( a) )
3731
- . collect :: < Vec < _ > > ( ) ;
3732
- cmd. args ( & value) ;
3733
-
3734
- for ( k, v) in self . env . iter ( ) {
3735
- cmd. env ( k, v) ;
3736
- }
3737
- cmd
3738
- }
3739
-
3740
- /// Returns the path for this compiler.
3741
- ///
3742
- /// Note that this may not be a path to a file on the filesystem, e.g. "cc",
3743
- /// but rather something which will be resolved when a process is spawned.
3744
- pub fn path ( & self ) -> & Path {
3745
- & self . path
3746
- }
3747
-
3748
- /// Returns the default set of arguments to the compiler needed to produce
3749
- /// executables for the target this compiler generates.
3750
- pub fn args ( & self ) -> & [ OsString ] {
3751
- & self . args
3752
- }
3753
-
3754
- /// Returns the set of environment variables needed for this compiler to
3755
- /// operate.
3756
- ///
3757
- /// This is typically only used for MSVC compilers currently.
3758
- pub fn env ( & self ) -> & [ ( OsString , OsString ) ] {
3759
- & self . env
3760
- }
3761
-
3762
- /// Returns the compiler command in format of CC environment variable.
3763
- /// Or empty string if CC env was not present
3764
- ///
3765
- /// This is typically used by configure script
3766
- pub fn cc_env ( & self ) -> OsString {
3767
- match self . cc_wrapper_path {
3768
- Some ( ref cc_wrapper_path) => {
3769
- let mut cc_env = cc_wrapper_path. as_os_str ( ) . to_owned ( ) ;
3770
- cc_env. push ( " " ) ;
3771
- cc_env. push ( self . path . to_path_buf ( ) . into_os_string ( ) ) ;
3772
- for arg in self . cc_wrapper_args . iter ( ) {
3773
- cc_env. push ( " " ) ;
3774
- cc_env. push ( arg) ;
3775
- }
3776
- cc_env
3777
- }
3778
- None => OsString :: from ( "" ) ,
3779
- }
3780
- }
3781
-
3782
- /// Returns the compiler flags in format of CFLAGS environment variable.
3783
- /// Important here - this will not be CFLAGS from env, its internal gcc's flags to use as CFLAGS
3784
- /// This is typically used by configure script
3785
- pub fn cflags_env ( & self ) -> OsString {
3786
- let mut flags = OsString :: new ( ) ;
3787
- for ( i, arg) in self . args . iter ( ) . enumerate ( ) {
3788
- if i > 0 {
3789
- flags. push ( " " ) ;
3790
- }
3791
- flags. push ( arg) ;
3792
- }
3793
- flags
3794
- }
3795
-
3796
- /// Whether the tool is GNU Compiler Collection-like.
3797
- pub fn is_like_gnu ( & self ) -> bool {
3798
- self . family == ToolFamily :: Gnu
3799
- }
3800
-
3801
- /// Whether the tool is Clang-like.
3802
- pub fn is_like_clang ( & self ) -> bool {
3803
- self . family == ToolFamily :: Clang
3804
- }
3805
-
3806
- /// Whether the tool is AppleClang under .xctoolchain
3807
- #[ cfg( target_vendor = "apple" ) ]
3808
- fn is_xctoolchain_clang ( & self ) -> bool {
3809
- let path = self . path . to_string_lossy ( ) ;
3810
- path. contains ( ".xctoolchain/" )
3811
- }
3812
- #[ cfg( not( target_vendor = "apple" ) ) ]
3813
- fn is_xctoolchain_clang ( & self ) -> bool {
3814
- false
3815
- }
3816
-
3817
- /// Whether the tool is MSVC-like.
3818
- pub fn is_like_msvc ( & self ) -> bool {
3819
- match self . family {
3820
- ToolFamily :: Msvc { .. } => true ,
3821
- _ => false ,
3822
- }
3823
- }
3824
- }
3825
-
3826
3464
fn wait_on_child ( cmd : & Command , program : & str , child : & mut Child ) -> Result < ( ) , Error > {
3827
3465
let status = match child. wait ( ) {
3828
3466
Ok ( s) => s,
0 commit comments