@@ -514,6 +514,8 @@ impl Config {
514514 // Build up the first cmake command to build the build system.
515515 let mut cmd = self . cmake_configure_command ( & target) ;
516516
517+ let version = Version :: from_command ( cmd. get_program ( ) ) . unwrap_or_default ( ) ;
518+
517519 if self . verbose_cmake {
518520 cmd. arg ( "-Wdev" ) ;
519521 cmd. arg ( "--debug-output" ) ;
@@ -812,9 +814,13 @@ impl Config {
812814
813815 cmd. arg ( "--config" ) . arg ( & profile) ;
814816
815- if let Ok ( s) = env:: var ( "NUM_JOBS" ) {
816- // See https://cmake.org/cmake/help/v3.12/manual/cmake.1.html#build-tool-mode
817- cmd. arg ( "--parallel" ) . arg ( s) ;
817+ // --parallel requires CMake 3.12:
818+ // https://cmake.org/cmake/help/latest/release/3.12.html#command-line
819+ if version >= Version :: new ( 3 , 12 ) {
820+ if let Ok ( s) = env:: var ( "NUM_JOBS" ) {
821+ // See https://cmake.org/cmake/help/v3.12/manual/cmake.1.html#build-tool-mode
822+ cmd. arg ( "--parallel" ) . arg ( s) ;
823+ }
818824 }
819825
820826 if !& self . build_args . is_empty ( ) {
@@ -964,6 +970,52 @@ impl Config {
964970 }
965971}
966972
973+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord ) ]
974+ struct Version {
975+ major : u32 ,
976+ minor : u32 ,
977+ }
978+
979+ impl Version {
980+ fn new ( major : u32 , minor : u32 ) -> Self {
981+ Self { major, minor }
982+ }
983+
984+ fn parse ( s : & str ) -> Option < Self > {
985+ // As of 3.22, the format of the version output is "cmake version <major>.<minor>.<patch>".
986+ // ```
987+ // $ cmake --version
988+ // cmake version 3.22.2
989+ //
990+ // CMake suite maintained and supported by Kitware (kitware.com/cmake).
991+ // ```
992+ let version = s. lines ( ) . next ( ) ?. strip_prefix ( "cmake version " ) ?;
993+ let mut digits = version. splitn ( 3 , '.' ) ; // split version string to major minor patch
994+ let major = digits. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
995+ let minor = digits. next ( ) ?. parse :: < u32 > ( ) . ok ( ) ?;
996+ // Ignore the patch version because it does not change the API.
997+ Some ( Version :: new ( major, minor) )
998+ }
999+
1000+ fn from_command ( executable : & OsStr ) -> Option < Self > {
1001+ let output = Command :: new ( executable) . arg ( "--version" ) . output ( ) . ok ( ) ?;
1002+ if !output. status . success ( ) {
1003+ return None ;
1004+ }
1005+ let stdout = core:: str:: from_utf8 ( & output. stdout ) . ok ( ) ?;
1006+ Self :: parse ( stdout)
1007+ }
1008+ }
1009+
1010+ impl Default for Version {
1011+ fn default ( ) -> Self {
1012+ // If the version parsing fails, we assume that it is the latest known
1013+ // version. This is because the failure of version parsing may be due to
1014+ // the version output being changed.
1015+ Self :: new ( 3 , 22 )
1016+ }
1017+ }
1018+
9671019fn run ( cmd : & mut Command , program : & str ) {
9681020 println ! ( "running: {:?}" , cmd) ;
9691021 let status = match cmd. status ( ) {
@@ -1001,3 +1053,22 @@ fn getenv_unwrap(v: &str) -> String {
10011053fn fail ( s : & str ) -> ! {
10021054 panic ! ( "\n {}\n \n build script failed, must exit now" , s)
10031055}
1056+
1057+ #[ cfg( test) ]
1058+ mod tests {
1059+ use super :: Version ;
1060+
1061+ #[ test]
1062+ fn test_cmake_version ( ) {
1063+ let text = "cmake version 3.22.2
1064+
1065+ CMake suite maintained and supported by Kitware (kitware.com/cmake).
1066+ " ;
1067+ let v = Version :: parse ( text) . unwrap ( ) ;
1068+ assert_eq ! ( v, Version :: new( 3 , 22 ) ) ;
1069+ assert ! ( Version :: new( 3 , 22 ) > Version :: new( 3 , 21 ) ) ;
1070+ assert ! ( Version :: new( 3 , 22 ) < Version :: new( 3 , 23 ) ) ;
1071+
1072+ let _v = Version :: from_command ( "cmake" . as_ref ( ) ) . unwrap ( ) ;
1073+ }
1074+ }
0 commit comments