@@ -184,97 +184,9 @@ impl Display for Error {
184184
185185impl std:: error:: Error for Error { }
186186
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 ;
278190
279191/// Represents an object.
280192///
@@ -3549,280 +3461,6 @@ impl Default for Build {
35493461 }
35503462}
35513463
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-
38263464fn wait_on_child ( cmd : & Command , program : & str , child : & mut Child ) -> Result < ( ) , Error > {
38273465 let status = match child. wait ( ) {
38283466 Ok ( s) => s,
0 commit comments