diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake index 7870ef30c..6c7d4c728 100644 --- a/Modules/CMakeDetermineCCompiler.cmake +++ b/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) IF(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($ENV{CC} MATCHES ".+") diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake index e7dcf8715..3de759b87 100644 --- a/Modules/CMakeDetermineCXXCompiler.cmake +++ b/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) IF(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($ENV{CXX} MATCHES ".+") @@ -50,3 +50,7 @@ ENDIF(NOT CMAKE_COMPILER_RETURN) CONFIGURE_FILE(${CMAKE_ROOT}/Modules/CMakeCXXCompiler.cmake.in ${CMAKE_BINARY_DIR}/CMakeCXXCompiler.cmake IMMEDIATE) MARK_AS_ADVANCED(CMAKE_CXX_COMPILER_FULLPATH) + + + + diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake new file mode 100644 index 000000000..8e88c0afe --- /dev/null +++ b/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) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake new file mode 100644 index 000000000..5609c963f --- /dev/null +++ b/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) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index edbed8071..e5991e47e 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -213,12 +213,14 @@ void cmGlobalGenerator::EnableLanguage(const char* lang, { if (!m_CMakeInstance->GetIsInTryCompile()) { + std::string ifpath = root + "/Modules/CMakeTestCCompiler.cmake"; + mf->ReadListFile(0,ifpath.c_str()); // for old versions of CMake ListFiles const char* versionValue = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); if (atof(versionValue) <= 1.4) { - std::string ifpath = root + "/Modules/CMakeBackwardCompatibilityC.cmake"; + ifpath = root + "/Modules/CMakeBackwardCompatibilityC.cmake"; mf->ReadListFile(0,ifpath.c_str()); } } @@ -227,6 +229,8 @@ void cmGlobalGenerator::EnableLanguage(const char* lang, { if (!m_CMakeInstance->GetIsInTryCompile()) { + std::string ifpath = root + "/Modules/CMakeTestCXXCompiler.cmake"; + mf->ReadListFile(0,ifpath.c_str()); // for old versions of CMake ListFiles const char* versionValue = mf->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); diff --git a/Source/cmGlobalUnixMakefileGenerator.cxx b/Source/cmGlobalUnixMakefileGenerator.cxx index 823d742e0..d11954e24 100644 --- a/Source/cmGlobalUnixMakefileGenerator.cxx +++ b/Source/cmGlobalUnixMakefileGenerator.cxx @@ -41,11 +41,19 @@ void cmGlobalUnixMakefileGenerator::EnableLanguage(const char* lang, cmSystemTools::Error("CMAKE_C_COMPILER not set, after EnableLanguage"); 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) { 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. " "For CMake to correctly use try compile commands, the compiler must " "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) { - path = cmSystemTools::FindProgram(mf->GetDefinition("CMAKE_CXX_COMPILER")); + const char* cxx = mf->GetDefinition("CMAKE_CXX_COMPILER"); + path = cmSystemTools::FindProgram(cxx); if(path.size() == 0) { 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. " "For CMake to correctly use try compile commands, the compiler must " "be in your path. Please add the compiler to your PATH environment," diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 75878cebc..a567f8382 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -176,7 +176,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff) cmCommand* usedCommand = rm->Clone(); usedCommand->SetMakefile(this); bool keepCommand = false; - if(usedCommand->GetEnabled()) + if(usedCommand->GetEnabled() && !cmSystemTools::GetFatalErrorOccured()) { // if not running in inherit mode or // if the command is inherited then InitialPass it. @@ -208,12 +208,15 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff) } 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; diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index c6e8e1603..e1722be2a 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -28,6 +28,7 @@ bool cmMessageCommand::InitialPass(std::vector const& args) std::vector::const_iterator i = args.begin(); bool send_error = false; + bool fatal_error = false; bool status = false; if (*i == "SEND_ERROR") { @@ -36,11 +37,19 @@ bool cmMessageCommand::InitialPass(std::vector const& args) } 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) @@ -63,7 +72,10 @@ bool cmMessageCommand::InitialPass(std::vector const& args) cmSystemTools::Message(message.c_str()); } } - + if(fatal_error) + { + cmSystemTools::SetFatalErrorOccured(); + } return true; } diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h index a312edcee..6ff551204 100644 --- a/Source/cmMessageCommand.h +++ b/Source/cmMessageCommand.h @@ -60,7 +60,7 @@ public: virtual const char* GetFullDocumentation() { 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"; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 6b10ab2b8..4b71bf415 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -129,6 +129,7 @@ cmSystemTools::GetTime(void) bool cmSystemTools::s_RunCommandHideConsole = false; bool cmSystemTools::s_DisableRunCommandOutput = false; bool cmSystemTools::s_ErrorOccured = false; +bool cmSystemTools::s_FatalErrorOccured = false; bool cmSystemTools::s_DisableMessages = false; std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com"; @@ -1536,6 +1537,10 @@ std::string cmSystemTools::FindProgram(const char* name, const std::vector& userPaths, bool no_system_path) { + if(!name) + { + return ""; + } // See if the executable exists as written. if(cmSystemTools::FileExists(name) && !cmSystemTools::FileIsDirectory(name)) diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 167926a3f..9c3d2aec2 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -162,12 +162,23 @@ public: ///! Return true if there was an error at any point. 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() { + cmSystemTools::s_FatalErrorOccured = false; cmSystemTools::s_ErrorOccured = false; } @@ -364,6 +375,7 @@ protected: private: static bool s_RunCommandHideConsole; static bool s_ErrorOccured; + static bool s_FatalErrorOccured; static bool s_DisableMessages; static bool s_DisableRunCommandOutput; static ErrorCallback s_ErrorCallback;