浏览代码

add a fatal error, and make sure c and c++ compilers work before using them

Bill Hoffman 23 年之前
父节点
当前提交
2f4ea98a4c

+ 1 - 1
Modules/CMakeDetermineCCompiler.cmake

@@ -13,7 +13,7 @@ IF(NOT CMAKE_C_COMPILER)
     GET_FILENAME_COMPONENT(CMAKE_C_COMPILER_INIT $ENV{CC} PROGRAM PROGRAM_ARGS CMAKE_C_FLAGS_ENV_INIT)
     GET_FILENAME_COMPONENT(CMAKE_C_COMPILER_INIT $ENV{CC} PROGRAM PROGRAM_ARGS CMAKE_C_FLAGS_ENV_INIT)
     IF(EXISTS ${CMAKE_C_COMPILER_INIT})
     IF(EXISTS ${CMAKE_C_COMPILER_INIT})
     ELSE(EXISTS ${CMAKE_C_COMPILER_INIT})
     ELSE(EXISTS ${CMAKE_C_COMPILER_INIT})
-      MESSAGE(SEND_ERROR "Could not find compiler set in environment variable CC:\n$ENV{CC}.") 
+      MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable CC:\n$ENV{CC}.") 
     ENDIF(EXISTS ${CMAKE_C_COMPILER_INIT})
     ENDIF(EXISTS ${CMAKE_C_COMPILER_INIT})
   ENDIF($ENV{CC} MATCHES ".+")
   ENDIF($ENV{CC} MATCHES ".+")
 
 

+ 5 - 1
Modules/CMakeDetermineCXXCompiler.cmake

@@ -13,7 +13,7 @@ IF(NOT CMAKE_CXX_COMPILER)
     GET_FILENAME_COMPONENT(CMAKE_CXX_COMPILER_INIT $ENV{CXX} PROGRAM PROGRAM_ARGS CMAKE_CXX_FLAGS_ENV_INIT)
     GET_FILENAME_COMPONENT(CMAKE_CXX_COMPILER_INIT $ENV{CXX} PROGRAM PROGRAM_ARGS CMAKE_CXX_FLAGS_ENV_INIT)
     IF(EXISTS ${CMAKE_CXX_COMPILER_INIT})
     IF(EXISTS ${CMAKE_CXX_COMPILER_INIT})
     ELSE(EXISTS ${CMAKE_CXX_COMPILER_INIT})
     ELSE(EXISTS ${CMAKE_CXX_COMPILER_INIT})
-      MESSAGE(SEND_ERROR "Could not find compiler set in environment variable CXX:\n$ENV{CXX}.\n${CMAKE_CXX_COMPILER_INIT}")
+      MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable CXX:\n$ENV{CXX}.\n${CMAKE_CXX_COMPILER_INIT}")
     ENDIF(EXISTS ${CMAKE_CXX_COMPILER_INIT})
     ENDIF(EXISTS ${CMAKE_CXX_COMPILER_INIT})
   ENDIF($ENV{CXX} MATCHES ".+")
   ENDIF($ENV{CXX} MATCHES ".+")
 
 
@@ -50,3 +50,7 @@ ENDIF(NOT CMAKE_COMPILER_RETURN)
 CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in 
 CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in 
                ${CMAKE_BINARY_DIR}/CMakeCXXCompiler.cmake IMMEDIATE)
                ${CMAKE_BINARY_DIR}/CMakeCXXCompiler.cmake IMMEDIATE)
 MARK_AS_ADVANCED(CMAKE_CXX_COMPILER_FULLPATH)
 MARK_AS_ADVANCED(CMAKE_CXX_COMPILER_FULLPATH)
+
+
+   
+      

+ 19 - 0
Modules/CMakeTestCCompiler.cmake

@@ -0,0 +1,19 @@
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected C compiler can actually compile
+# and like the most basic of programs.   If not, a fatel error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+MESSAGE(STATUS "Check for working C compiler: ${CMAKE_C_COMPILER}")
+WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeTmp/testCCompiler.c "int main(){return 0;}")
+TRY_COMPILE(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR} 
+            ${CMAKE_BINARY_DIR}/CMakeTmp/testCCompiler.c
+            OUTPUT_VARIABLE OUTPUT)
+IF(NOT CMAKE_C_COMPILER_WORKS)
+   MESSAGE(STATUS "Check for working C compiler: ${CMAKE_C_COMPILER} -- broken")
+   MESSAGE(FATAL_ERROR "The C compiler \"${CMAKE_C_COMPILER}\" "
+                      "is not able to compile a simple tests program.\nIt fails "
+                      "with the following output:\n ${OUTPUT}\n\n"
+                      "CMake will not be able to correctly generate this project.")
+ELSE(NOT CMAKE_C_COMPILER_WORKS)
+  MESSAGE(STATUS "Check for working C compiler: ${CMAKE_C_COMPILER} -- works")
+ENDIF(NOT CMAKE_C_COMPILER_WORKS)

+ 19 - 0
Modules/CMakeTestCXXCompiler.cmake

@@ -0,0 +1,19 @@
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected C++ compiler can actually compile
+# and like the most basic of programs.   If not, a fatel error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+MESSAGE(STATUS "Check for working CXX compiler: ${CMAKE_CXX_COMPILER}")
+WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeTmp/testCXXCompiler.cxx "int main(){return 0;}")
+TRY_COMPILE(CMAKE_CXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} 
+          ${CMAKE_BINARY_DIR}/CMakeTmp/testCXXCompiler.cxx
+          OUTPUT_VARIABLE OUTPUT)
+IF(NOT CMAKE_CXX_COMPILER_WORKS)
+ MESSAGE(STATUS "Check for working CXX compiler: ${CMAKE_CXX_COMPILER} -- broken")
+ MESSAGE(FATAL_ERROR "The C++ compiler \"${CMAKE_CXX_COMPILER}\" "
+                     "is not able to compile a simple tests program.\nIt fails "
+                     "with the following output:\n ${OUTPUT}\n\n"
+                     "CMake will not be able to correctly generate this project.")
+ELSE(NOT CMAKE_CXX_COMPILER_WORKS)
+  MESSAGE(STATUS "Check for working CXX compiler: ${CMAKE_CXX_COMPILER} -- works")
+ENDIF(NOT CMAKE_CXX_COMPILER_WORKS)

+ 5 - 1
Source/cmGlobalGenerator.cxx

@@ -213,12 +213,14 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
       {
       {
       if (!m_CMakeInstance->GetIsInTryCompile())
       if (!m_CMakeInstance->GetIsInTryCompile())
         {
         {
+        std::string ifpath = root + "/Modules/CMakeTestCCompiler.cmake";
+        mf->ReadListFile(0,ifpath.c_str());
         // for old versions of CMake ListFiles
         // for old versions of CMake ListFiles
         const char* versionValue
         const char* versionValue
           = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
           = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
         if (atof(versionValue) <= 1.4)
         if (atof(versionValue) <= 1.4)
           {
           {
-          std::string ifpath = root + "/Modules/CMakeBackwardCompatibilityC.cmake";
+          ifpath = root + "/Modules/CMakeBackwardCompatibilityC.cmake";
           mf->ReadListFile(0,ifpath.c_str()); 
           mf->ReadListFile(0,ifpath.c_str()); 
           }
           }
         }
         }
@@ -227,6 +229,8 @@ void cmGlobalGenerator::EnableLanguage(const char* lang,
       {
       {
       if (!m_CMakeInstance->GetIsInTryCompile())
       if (!m_CMakeInstance->GetIsInTryCompile())
         {
         {
+        std::string ifpath = root + "/Modules/CMakeTestCXXCompiler.cmake";
+        mf->ReadListFile(0,ifpath.c_str());
         // for old versions of CMake ListFiles
         // for old versions of CMake ListFiles
         const char* versionValue
         const char* versionValue
           = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");
           = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY");

+ 21 - 4
Source/cmGlobalUnixMakefileGenerator.cxx

@@ -41,11 +41,19 @@ void cmGlobalUnixMakefileGenerator::EnableLanguage(const char* lang,
       cmSystemTools::Error("CMAKE_C_COMPILER not set, after EnableLanguage");
       cmSystemTools::Error("CMAKE_C_COMPILER not set, after EnableLanguage");
       return;
       return;
       }
       }
-    std::string path = cmSystemTools::FindProgram(mf->GetDefinition("CMAKE_C_COMPILER"));
+    const char* cc = mf->GetDefinition("CMAKE_C_COMPILER");
+    std::string path = cmSystemTools::FindProgram(cc);
     if(path.size() == 0)
     if(path.size() == 0)
       {
       {
       std::string message = "your C compiler: ";
       std::string message = "your C compiler: ";
-      message +=  mf->GetDefinition("CMAKE_C_COMPILER"); 
+      if(cc)
+        {
+        message +=  cc;
+        }
+      else
+        {
+        message += "(NULL)";
+        }
       message += " was not found in your path.   "
       message += " was not found in your path.   "
           "For CMake to correctly use try compile commands, the compiler must "
           "For CMake to correctly use try compile commands, the compiler must "
           "be in your path.   Please add the compiler to your PATH environment,"
           "be in your path.   Please add the compiler to your PATH environment,"
@@ -54,11 +62,20 @@ void cmGlobalUnixMakefileGenerator::EnableLanguage(const char* lang,
       }
       }
     if(strcmp(lang, "CXX") == 0)
     if(strcmp(lang, "CXX") == 0)
       {
       {
-      path = cmSystemTools::FindProgram(mf->GetDefinition("CMAKE_CXX_COMPILER"));
+      const char* cxx = mf->GetDefinition("CMAKE_CXX_COMPILER");
+      path = cmSystemTools::FindProgram(cxx);
       if(path.size() == 0)
       if(path.size() == 0)
         {
         {
         std::string message = "your C++ compiler: ";
         std::string message = "your C++ compiler: ";
-        message +=  mf->GetDefinition("CMAKE_CXX_COMPILER");
+        if(cxx)
+          {
+          message +=  cxx;
+          }
+        else
+          {
+          message +=  "(NULL)";
+          }
+        
         message += " was not found in your path.   "
         message += " was not found in your path.   "
           "For CMake to correctly use try compile commands, the compiler must "
           "For CMake to correctly use try compile commands, the compiler must "
           "be in your path.   Please add the compiler to your PATH environment,"
           "be in your path.   Please add the compiler to your PATH environment,"

+ 10 - 7
Source/cmMakefile.cxx

@@ -176,7 +176,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff)
     cmCommand* usedCommand = rm->Clone();
     cmCommand* usedCommand = rm->Clone();
     usedCommand->SetMakefile(this);
     usedCommand->SetMakefile(this);
     bool keepCommand = false;
     bool keepCommand = false;
-    if(usedCommand->GetEnabled())
+    if(usedCommand->GetEnabled() && !cmSystemTools::GetFatalErrorOccured())
       {
       {
       // if not running in inherit mode or
       // if not running in inherit mode or
       // if the command is inherited then InitialPass it.
       // if the command is inherited then InitialPass it.
@@ -208,12 +208,15 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff)
     }
     }
   else
   else
     {
     {
-    cmOStringStream error;
-    error << "Error in cmake code at\n"
-          << lff.m_FilePath << ":" << lff.m_Line << ":\n"
-          << "Unknown CMake command \"" << lff.m_Name.c_str() << "\".";
-    cmSystemTools::Error(error.str().c_str());
-    result = false;
+    if(!cmSystemTools::GetFatalErrorOccured())
+      {
+      cmOStringStream error;
+      error << "Error in cmake code at\n"
+            << lff.m_FilePath << ":" << lff.m_Line << ":\n"
+            << "Unknown CMake command \"" << lff.m_Name.c_str() << "\".";
+      cmSystemTools::Error(error.str().c_str());
+      result = false;
+      }
     }
     }
   
   
   return result;
   return result;

+ 16 - 4
Source/cmMessageCommand.cxx

@@ -28,6 +28,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args)
   std::vector<std::string>::const_iterator i = args.begin();
   std::vector<std::string>::const_iterator i = args.begin();
 
 
   bool send_error = false;
   bool send_error = false;
+  bool fatal_error = false;
   bool status = false;
   bool status = false;
   if (*i == "SEND_ERROR")
   if (*i == "SEND_ERROR")
     {
     {
@@ -36,11 +37,19 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args)
     }
     }
   else
   else
     {
     {
-      if (*i == "STATUS")
+    if (*i == "STATUS")
+      {
+      status = true;
+      ++i;
+      }
+    else
+      {
+      if (*i == "FATAL_ERROR")
         {
         {
-          status = true;
-          ++i;
+        fatal_error = true;
+        ++i;
         }
         }
+      }
     }
     }
 
 
   for(;i != args.end(); ++i)
   for(;i != args.end(); ++i)
@@ -63,7 +72,10 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args)
           cmSystemTools::Message(message.c_str());
           cmSystemTools::Message(message.c_str());
         }
         }
     }
     }
-
+  if(fatal_error)
+    {
+    cmSystemTools::SetFatalErrorOccured();
+    }
   return true;
   return true;
 }
 }
 
 

+ 1 - 1
Source/cmMessageCommand.h

@@ -60,7 +60,7 @@ public:
   virtual const char* GetFullDocumentation()
   virtual const char* GetFullDocumentation()
     {
     {
     return
     return
-      "MESSAGE([SEND_ERROR | STATUS] \"message to display\"...)\n"
+      "MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] \"message to display\"...)\n"
       "The arguments are messages to display. If the first argument is SEND_ERROR then an error is raised. If the first argument is STATUS then the message is diaplyed in the progress line for the GUI";
       "The arguments are messages to display. If the first argument is SEND_ERROR then an error is raised. If the first argument is STATUS then the message is diaplyed in the progress line for the GUI";
     }
     }
   
   

+ 5 - 0
Source/cmSystemTools.cxx

@@ -129,6 +129,7 @@ cmSystemTools::GetTime(void)
 bool cmSystemTools::s_RunCommandHideConsole = false;
 bool cmSystemTools::s_RunCommandHideConsole = false;
 bool cmSystemTools::s_DisableRunCommandOutput = false;
 bool cmSystemTools::s_DisableRunCommandOutput = false;
 bool cmSystemTools::s_ErrorOccured = false;
 bool cmSystemTools::s_ErrorOccured = false;
+bool cmSystemTools::s_FatalErrorOccured = false;
 bool cmSystemTools::s_DisableMessages = false;
 bool cmSystemTools::s_DisableMessages = false;
 
 
 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
@@ -1536,6 +1537,10 @@ std::string cmSystemTools::FindProgram(const char* name,
                                        const std::vector<std::string>& userPaths,
                                        const std::vector<std::string>& userPaths,
                                        bool no_system_path)
                                        bool no_system_path)
 {
 {
+  if(!name)
+    {
+    return "";
+    }
   // See if the executable exists as written.
   // See if the executable exists as written.
   if(cmSystemTools::FileExists(name) &&
   if(cmSystemTools::FileExists(name) &&
       !cmSystemTools::FileIsDirectory(name))
       !cmSystemTools::FileIsDirectory(name))

+ 14 - 2
Source/cmSystemTools.h

@@ -162,12 +162,23 @@ public:
   ///! Return true if there was an error at any point.
   ///! Return true if there was an error at any point.
   static bool GetErrorOccuredFlag() 
   static bool GetErrorOccuredFlag() 
     {
     {
-      return cmSystemTools::s_ErrorOccured;
+      return cmSystemTools::s_ErrorOccured || cmSystemTools::s_FatalErrorOccured;
+    }
+  ///! If this is set to true, cmake stops processing commands.
+  static void SetFatalErrorOccured()
+    {
+      cmSystemTools::s_FatalErrorOccured = true;
+    }
+ ///! Return true if there was an error at any point.
+  static bool GetFatalErrorOccured() 
+    {
+      return cmSystemTools::s_FatalErrorOccured;
     }
     }
 
 
-  ///! Set the error occured flag back to false
+  ///! Set the error occured flag and fatal error back to false
   static void ResetErrorOccuredFlag()
   static void ResetErrorOccuredFlag()
     {
     {
+      cmSystemTools::s_FatalErrorOccured = false;
       cmSystemTools::s_ErrorOccured = false;
       cmSystemTools::s_ErrorOccured = false;
     }
     }
   
   
@@ -364,6 +375,7 @@ protected:
 private:
 private:
   static bool s_RunCommandHideConsole;
   static bool s_RunCommandHideConsole;
   static bool s_ErrorOccured;
   static bool s_ErrorOccured;
+  static bool s_FatalErrorOccured;
   static bool s_DisableMessages;
   static bool s_DisableMessages;
   static bool s_DisableRunCommandOutput;
   static bool s_DisableRunCommandOutput;
   static ErrorCallback s_ErrorCallback;
   static ErrorCallback s_ErrorCallback;