From d1526f825e7464b8cb8a82b73718bbf2eb4965c9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 7 Nov 2013 15:30:59 -0500 Subject: [PATCH] Refactor internal resource location APIs and initialization Rename cmSystemTools::FindExecutableDirectory to FindCMakeResources. Teach it to compute the locations of cmake, ctest, cpack, ccmake, and cmake-gui executables, and the location of CMAKE_ROOT. Provide this information from static cmSystemTools::Get() methods. Refactor code that needs these locations to use the new APIs. Teach FindCMakeResources to use the OS X system API to lookup the executable location. When running from the CMake build tree itself, leave a file in the tree that FindCMakeResources can use to read the location of the source tree. This avoids the need to compile the source tree location into a binary that may be installed and used without the source tree. Teach the QtDialog on OS X to create a "cmake-gui" symlink in the build tree next to "cmake" and the other tools, as is already done in the install tree for the application bundle. This ensures a consistent set of executables are available in one directory. --- Source/CMakeLists.txt | 6 + Source/CMakeSourceDir.txt.in | 1 + Source/CPack/cmCPackGenerator.cxx | 32 --- Source/CPack/cmCPackGenerator.h | 7 - Source/CPack/cpack.cxx | 3 +- Source/CTest/cmCTestBuildAndTestHandler.cxx | 2 +- Source/CTest/cmCTestConfigureCommand.cxx | 2 +- Source/CTest/cmCTestScriptHandler.cxx | 8 +- Source/CursesDialog/ccmake.cxx | 3 +- Source/CursesDialog/cmCursesMainForm.cxx | 4 +- Source/QtDialog/CMakeLists.txt | 7 + Source/QtDialog/CMakeSetup.cxx | 3 +- Source/QtDialog/QCMake.cxx | 25 +-- Source/cmCTest.cxx | 27 +-- Source/cmCTest.h | 9 - Source/cmConfigure.cmake.h.in | 2 - Source/cmDocumentation.cxx | 5 +- Source/cmDocumentation.h | 4 - Source/cmGlobalGenerator.cxx | 6 +- Source/cmMakefile.cxx | 1 - Source/cmSystemTools.cxx | 150 +++++++++++++- Source/cmSystemTools.h | 15 +- Source/cmake.cxx | 213 ++------------------ Source/cmake.h | 17 +- Source/cmakemain.cxx | 3 +- Source/ctest.cxx | 3 +- 26 files changed, 210 insertions(+), 348 deletions(-) create mode 100644 Source/CMakeSourceDir.txt.in diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c01245c3a..570b7e28e 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -38,6 +38,12 @@ configure_file( "${CMake_BINARY_DIR}/Source/CPack/cmCPackConfigure.h" ) +# Tell CMake executable in the build tree where to find the source tree. +configure_file( + "${CMake_SOURCE_DIR}/Source/CMakeSourceDir.txt.in" + "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt" @ONLY + ) + # add the include path to find the .h include_directories( "${CMake_BINARY_DIR}/Source" diff --git a/Source/CMakeSourceDir.txt.in b/Source/CMakeSourceDir.txt.in new file mode 100644 index 000000000..5e6a988c0 --- /dev/null +++ b/Source/CMakeSourceDir.txt.in @@ -0,0 +1 @@ +@CMake_SOURCE_DIR@ diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 63a759699..0e16a40ae 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -1143,12 +1143,6 @@ int cmCPackGenerator::Initialize(const char* name, cmMakefile* mf) { this->MakefileMap = mf; this->Name = name; - if ( !this->SetCMakeRoot() ) - { - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Cannot initialize the generator" << std::endl); - return 0; - } // set the running generator name this->SetOption("CPACK_GENERATOR", this->Name.c_str()); // Load the project specific config file @@ -1204,32 +1198,6 @@ const char* cmCPackGenerator::GetOption(const char* op) const return ret; } -//---------------------------------------------------------------------- -int cmCPackGenerator::SetCMakeRoot() -{ - // use the CMAKE_ROOT from cmake which should have been - // found by now - const char* root= - this->MakefileMap->GetDefinition("CMAKE_ROOT"); - - if(root) - { - this->CMakeRoot = root; - cmCPackLogger(cmCPackLog::LOG_DEBUG, "Looking for CMAKE_ROOT: " - << this->CMakeRoot.c_str() << std::endl); - this->SetOption("CMAKE_ROOT", this->CMakeRoot.c_str()); - return 1; - } - cmCPackLogger(cmCPackLog::LOG_ERROR, - "Could not find CMAKE_ROOT !!!" - << std::endl - << "CMake has most likely not been installed correctly." - << std::endl - <<"Modules directory not found in" - << std::endl); - return 0; -} - //---------------------------------------------------------------------- int cmCPackGenerator::PackageFiles() { diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 5cb2280bc..bb33aa0f1 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -105,9 +105,6 @@ public: bool IsSet(const char* name) const; bool IsOn(const char* name) const; - //! Set all the variables - int SetCMakeRoot(); - //! Set the logger void SetLogger(cmCPackLog* log) { this->Logger = log; } @@ -285,10 +282,6 @@ protected: */ std::vector files; - std::string CPackSelf; - std::string CMakeSelf; - std::string CMakeRoot; - std::map InstallationTypes; /** * The set of components. diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 9f8cc14f5..438b16d6b 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -99,7 +99,7 @@ int cpackDefinitionArgument(const char* argument, const char* cValue, // this is CPack. int main (int argc, char *argv[]) { - cmSystemTools::FindExecutableDirectory(argv[0]); + cmSystemTools::FindCMakeResources(argv[0]); cmCPackLog log; log.SetErrorPrefix("CPack Error: "); @@ -228,7 +228,6 @@ int main (int argc, char *argv[]) // This part is used for cpack documentation lookup as well. cminst.AddCMakePaths(); - doc.SetCMakeRoot(cminst.GetCacheDefinition("CMAKE_ROOT")); if ( parsed && !help ) { diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 4fa3c53b9..5e53dbe38 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -59,7 +59,7 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring, { unsigned int k; std::vector args; - args.push_back(this->CTest->GetCMakeExecutable()); + args.push_back(cmSystemTools::GetCMakeCommand()); args.push_back(this->SourceDir); if(this->BuildGenerator.size()) { diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx index db33cb68e..5eed40972 100644 --- a/Source/CTest/cmCTestConfigureCommand.cxx +++ b/Source/CTest/cmCTestConfigureCommand.cxx @@ -86,7 +86,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler() } std::string cmakeConfigureCommand = "\""; - cmakeConfigureCommand += this->CTest->GetCMakeExecutable(); + cmakeConfigureCommand += cmSystemTools::GetCMakeCommand(); cmakeConfigureCommand += "\""; std::vector::const_iterator it; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 7d33cf368..00a0a097c 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -222,13 +222,13 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg) // execute the script passing in the arguments to the script as well as the // arguments from this invocation of cmake std::vector argv; - argv.push_back(this->CTest->GetCTestExecutable()); + argv.push_back(cmSystemTools::GetCTestCommand().c_str()); argv.push_back("-SR"); argv.push_back(total_script_arg.c_str()); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Executable for CTest is: " << - this->CTest->GetCTestExecutable() << "\n"); + cmSystemTools::GetCTestCommand() << "\n"); // now pass through all the other arguments std::vector &initArgs = @@ -397,9 +397,9 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg) this->Makefile->AddDefinition("CTEST_SCRIPT_NAME", cmSystemTools::GetFilenameName(script).c_str()); this->Makefile->AddDefinition("CTEST_EXECUTABLE_NAME", - this->CTest->GetCTestExecutable()); + cmSystemTools::GetCTestCommand().c_str()); this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME", - this->CTest->GetCMakeExecutable()); + cmSystemTools::GetCMakeCommand().c_str()); this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true); this->UpdateElapsedTime(); diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index fdfe331c3..ce508452a 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -80,14 +80,13 @@ void CMakeErrorHandler(const char* message, const char* title, bool&, void* clie int main(int argc, char** argv) { - cmSystemTools::FindExecutableDirectory(argv[0]); + cmSystemTools::FindCMakeResources(argv[0]); cmDocumentation doc; doc.addCMakeStandardDocSections(); if(doc.CheckOptions(argc, argv)) { cmake hcm; hcm.AddCMakePaths(); - doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT")); std::vector generators; hcm.GetGeneratorDocumentation(generators); doc.SetName("ccmake"); diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx index 4fee0bbd3..d94cd37fa 100644 --- a/Source/CursesDialog/cmCursesMainForm.cxx +++ b/Source/CursesDialog/cmCursesMainForm.cxx @@ -43,14 +43,14 @@ cmCursesMainForm::cmCursesMainForm(std::vector const& args, this->HelpMessage.push_back(""); this->HelpMessage.push_back(s_ConstHelpMessage); this->CMakeInstance = new cmake; - this->CMakeInstance->SetCMakeEditCommand("ccmake"); + this->CMakeInstance->SetCMakeEditCommand( + cmSystemTools::GetCMakeCursesCommand()); // create the arguments for the cmake object std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0].c_str()); whereCMake += "/cmake"; this->Args[0] = whereCMake; this->CMakeInstance->SetArgs(this->Args); - this->CMakeInstance->SetCMakeCommand(whereCMake.c_str()); this->SearchString = ""; this->OldSearchString = ""; this->SearchMode = false; diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 15f9ef1fd..88a9fc987 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -118,6 +118,13 @@ if(APPLE) # TBD: MACOSX_BUNDLE_BUNDLE_VERSION "${CMAKE_BUNDLE_VERSION}" MACOSX_BUNDLE_COPYRIGHT "Copyright 2000-2013 Kitware, Inc." ) + + # Create a symlink in the build tree to provide a "cmake-gui" next + # to the "cmake" executable that refers to the application bundle. + add_custom_command(TARGET cmake-gui POST_BUILD + COMMAND ln -sf ${CMAKE_BUNDLE_NAME}.app/Contents/MacOS/${CMAKE_BUNDLE_NAME} + $/cmake-gui + ) endif() set(CMAKE_INSTALL_DESTINATION_ARGS BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}") diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 095aeb648..408bb4c9e 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -48,7 +48,7 @@ static const char * cmDocumentationOptions[][2] = int main(int argc, char** argv) { - cmSystemTools::FindExecutableDirectory(argv[0]); + cmSystemTools::FindCMakeResources(argv[0]); // check docs first so that X is not need to get docs // do docs, if args were given cmDocumentation doc; @@ -58,7 +58,6 @@ int main(int argc, char** argv) // Construct and print requested documentation. cmake hcm; hcm.AddCMakePaths(); - doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT")); std::vector generators; hcm.GetGeneratorDocumentation(generators); diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index 0d0118164..0fe5f8cb8 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -33,34 +33,13 @@ QCMake::QCMake(QObject* p) qRegisterMetaType(); qRegisterMetaType(); - QDir execDir(QCoreApplication::applicationDirPath()); - -#if defined(Q_OS_MAC) - if(execDir.exists("../bin/cmake")) - { - execDir.cd("../bin"); - } - else - { - execDir.cd("../../../"); // path to cmake in build directory (need to fix for deployment) - } -#endif - - QString cmakeCommand = QString("cmake")+QString::fromLocal8Bit(cmSystemTools::GetExecutableExtension()); - cmakeCommand = execDir.filePath(cmakeCommand); - cmSystemTools::DisableRunCommandOutput(); cmSystemTools::SetRunCommandHideConsole(true); cmSystemTools::SetErrorCallback(QCMake::errorCallback, this); - cmSystemTools::FindExecutableDirectory(cmakeCommand.toLocal8Bit().data()); this->CMakeInstance = new cmake; - this->CMakeInstance->SetCMakeCommand(cmakeCommand.toLocal8Bit().data()); -#if defined(Q_OS_MAC) - this->CMakeInstance->SetCMakeEditCommand("cmake-gui.app/Contents/MacOS/cmake-gui"); -#else - this->CMakeInstance->SetCMakeEditCommand("cmake-gui"); -#endif + this->CMakeInstance->SetCMakeEditCommand( + cmSystemTools::GetCMakeGUICommand()); this->CMakeInstance->SetProgressCallback(QCMake::progressCallback, this); cmSystemTools::SetInterruptCallback(QCMake::interruptCallback, this); diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 98f19cc97..bfabc9f2d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1298,7 +1298,8 @@ int cmCTest::RunTest(std::vector argv, } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Test timeout computed to be: " << timeout << "\n"); - if(cmSystemTools::SameFile(argv[0], this->CTestSelf.c_str()) && + if(cmSystemTools::SameFile( + argv[0], cmSystemTools::GetCTestCommand().c_str()) && !this->ForceNewCTestProcess) { cmCTest inst; @@ -2257,7 +2258,6 @@ bool cmCTest::AddVariableDefinition(const std::string &arg) // the main entry point of ctest, called from main int cmCTest::Run(std::vector &args, std::string* output) { - this->FindRunningCMake(); const char* ctestExec = "ctest"; bool cmakeAndTest = false; bool executeTests = true; @@ -2497,29 +2497,6 @@ int cmCTest::Run(std::vector &args, std::string* output) return 1; } -//---------------------------------------------------------------------- -void cmCTest::FindRunningCMake() -{ - // Find our own executable. - this->CTestSelf = cmSystemTools::GetExecutableDirectory(); - this->CTestSelf += "/ctest"; - this->CTestSelf += cmSystemTools::GetExecutableExtension(); - if(!cmSystemTools::FileExists(this->CTestSelf.c_str())) - { - cmSystemTools::Error("CTest executable cannot be found at ", - this->CTestSelf.c_str()); - } - - this->CMakeSelf = cmSystemTools::GetExecutableDirectory(); - this->CMakeSelf += "/cmake"; - this->CMakeSelf += cmSystemTools::GetExecutableExtension(); - if(!cmSystemTools::FileExists(this->CMakeSelf.c_str())) - { - cmSystemTools::Error("CMake executable cannot be found at ", - this->CMakeSelf.c_str()); - } -} - //---------------------------------------------------------------------- void cmCTest::SetNotesFiles(const char* notes) { diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 5dd35ce41..c0a06c5d3 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -287,10 +287,6 @@ public: //source directory, it will become /.../relative/path/to/file std::string GetShortPathToFile(const char* fname); - //! Get the path to CTest - const char* GetCTestExecutable() { return this->CTestSelf.c_str(); } - const char* GetCMakeExecutable() { return this->CMakeSelf.c_str(); } - enum { EXPERIMENTAL, NIGHTLY, @@ -490,8 +486,6 @@ private: int CompatibilityMode; // information for the --build-and-test options - std::string CMakeSelf; - std::string CTestSelf; std::string BinaryDir; std::string NotesFiles; @@ -546,9 +540,6 @@ private: int GenerateCTestNotesOutput(std::ostream& os, const VectorOfStrings& files); - ///! Find the running cmake - void FindRunningCMake(); - //! Check if the argument is the one specified bool CheckArgument(const std::string& arg, const char* varg1, const char* varg2 = 0); diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 348f5d30f..c5e95d0ca 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -16,6 +16,4 @@ #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV #cmakedefine CMAKE_USE_ELF_PARSER -#define CMAKE_ROOT_DIR "${CMake_SOURCE_DIR}" -#define CMAKE_BUILD_DIR "${CMake_BINARY_DIR}" #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 682478eed..802957758 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -605,7 +605,8 @@ void cmDocumentation::GlobHelp(std::vector& files, std::string const& pattern) { cmsys::Glob gl; - std::string findExpr = this->CMakeRoot + "/Help/" + pattern + ".rst"; + std::string findExpr = + cmSystemTools::GetCMakeRoot() + "/Help/" + pattern + ".rst"; if(gl.FindFiles(findExpr)) { files = gl.GetFiles(); @@ -649,7 +650,7 @@ bool cmDocumentation::PrintFiles(std::ostream& os, std::vector files; this->GlobHelp(files, pattern); std::sort(files.begin(), files.end()); - cmRST r(os, this->CMakeRoot + "/Help"); + cmRST r(os, cmSystemTools::GetCMakeRoot() + "/Help"); for (std::vector::const_iterator i = files.begin(); i != files.end(); ++i) { diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 07e614db6..209cc278c 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -83,9 +83,6 @@ public: void AppendSection(const char *sectionName, cmDocumentationEntry &docs); - /** Set cmake root so we can find installed files */ - void SetCMakeRoot(const char* root) { this->CMakeRoot = root? root:"";} - /** Add common (to all tools) documentation section(s) */ void addCommonStandardDocSections(); @@ -127,7 +124,6 @@ private: std::string NameString; std::map AllSections; - std::string CMakeRoot; std::string CurrentArgument; struct RequestedHelpItem diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 71dd897e9..eb1e37ed3 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2068,7 +2068,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) cmCustomCommandLines cpackCommandLines; std::vector depends; cmCustomCommandLine singleLine; - singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand()); + singleLine.push_back(cmSystemTools::GetCPackCommand()); if ( cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.' ) { singleLine.push_back("-C"); @@ -2109,7 +2109,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) cpackCommandLines.end()); singleLine.erase(singleLine.begin(), singleLine.end()); depends.erase(depends.begin(), depends.end()); - singleLine.push_back(this->GetCMakeInstance()->GetCPackCommand()); + singleLine.push_back(cmSystemTools::GetCPackCommand()); singleLine.push_back("--config"); configFile = mf->GetStartOutputDirectory();; configFile += "/CPackSourceConfig.cmake"; @@ -2135,7 +2135,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) cpackCommandLines.end()); singleLine.erase(singleLine.begin(), singleLine.end()); depends.erase(depends.begin(), depends.end()); - singleLine.push_back(this->GetCMakeInstance()->GetCTestCommand()); + singleLine.push_back(cmSystemTools::GetCTestCommand()); singleLine.push_back("--force-new-ctest-process"); if(cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c18a7eb02..ac8381cc9 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3072,7 +3072,6 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir, cm.SetHomeOutputDirectory(bindir); cm.SetStartDirectory(srcdir); cm.SetStartOutputDirectory(bindir); - cm.SetCMakeCommand(cmakeCommand.c_str()); cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset()); cm.LoadCache(); if(!gg->IsMultiConfig()) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 1ecda887a..f5376eb4b 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -43,6 +43,10 @@ # include #endif +#if defined(__APPLE__) +# include +#endif + #include #if defined(_WIN32) && \ @@ -2011,16 +2015,59 @@ unsigned int cmSystemTools::RandomSeed() } //---------------------------------------------------------------------------- -static std::string cmSystemToolsExecutableDirectory; -void cmSystemTools::FindExecutableDirectory(const char* argv0) +static std::string cmSystemToolsCMakeCommand; +static std::string cmSystemToolsCTestCommand; +static std::string cmSystemToolsCPackCommand; +static std::string cmSystemToolsCMakeCursesCommand; +static std::string cmSystemToolsCMakeGUICommand; +static std::string cmSystemToolsCMakeRoot; +void cmSystemTools::FindCMakeResources(const char* argv0) { + std::string exe_dir; #if defined(_WIN32) && !defined(__CYGWIN__) (void)argv0; // ignore this on windows char modulepath[_MAX_PATH]; ::GetModuleFileName(NULL, modulepath, sizeof(modulepath)); - cmSystemToolsExecutableDirectory = - cmSystemTools::GetFilenamePath(modulepath); - return; + exe_dir = cmSystemTools::GetFilenamePath(modulepath); +#elif defined(__APPLE__) + (void)argv0; // ignore this on OS X +# define CM_EXE_PATH_LOCAL_SIZE 16384 + char exe_path_local[CM_EXE_PATH_LOCAL_SIZE]; +# if defined(MAC_OS_X_VERSION_10_3) && !defined(MAC_OS_X_VERSION_10_4) + unsigned long exe_path_size = CM_EXE_PATH_LOCAL_SIZE; +# else + uint32_t exe_path_size = CM_EXE_PATH_LOCAL_SIZE; +# endif +# undef CM_EXE_PATH_LOCAL_SIZE + char* exe_path = exe_path_local; + if(_NSGetExecutablePath(exe_path, &exe_path_size) < 0) + { + exe_path = (char*)malloc(exe_path_size); + _NSGetExecutablePath(exe_path, &exe_path_size); + } + exe_dir = + cmSystemTools::GetFilenamePath( + cmSystemTools::GetRealPath(exe_path)); + if(exe_path != exe_path_local) + { + free(exe_path); + } + if(cmSystemTools::GetFilenameName(exe_dir) == "MacOS") + { + // The executable is inside an application bundle. + // Look for ../bin (install tree) and then fall back to + // ../../../bin (build tree). + exe_dir = cmSystemTools::GetFilenamePath(exe_dir); + if(cmSystemTools::FileExists((exe_dir+"/bin/cmake").c_str())) + { + exe_dir += "/bin"; + } + else + { + exe_dir = cmSystemTools::GetFilenamePath(exe_dir); + exe_dir = cmSystemTools::GetFilenamePath(exe_dir); + } + } #else std::string errorMsg; std::string exe; @@ -2028,20 +2075,107 @@ void cmSystemTools::FindExecutableDirectory(const char* argv0) { // remove symlinks exe = cmSystemTools::GetRealPath(exe.c_str()); - cmSystemToolsExecutableDirectory = + exe_dir = cmSystemTools::GetFilenamePath(exe.c_str()); } else { // ??? } +#endif + cmSystemToolsCMakeCommand = exe_dir; + cmSystemToolsCMakeCommand += "/cmake"; + cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCTestCommand = exe_dir; + cmSystemToolsCTestCommand += "/ctest"; + cmSystemToolsCTestCommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCPackCommand = exe_dir; + cmSystemToolsCPackCommand += "/cpack"; + cmSystemToolsCPackCommand += cmSystemTools::GetExecutableExtension(); + cmSystemToolsCMakeGUICommand = exe_dir; + cmSystemToolsCMakeGUICommand += "/cmake-gui"; + cmSystemToolsCMakeGUICommand += cmSystemTools::GetExecutableExtension(); + if(!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand.c_str())) + { + cmSystemToolsCMakeGUICommand = ""; + } + cmSystemToolsCMakeCursesCommand = exe_dir; + cmSystemToolsCMakeCursesCommand += "/ccmake"; + cmSystemToolsCMakeCursesCommand += cmSystemTools::GetExecutableExtension(); + if(!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand.c_str())) + { + cmSystemToolsCMakeCursesCommand = ""; + } + +#ifdef CMAKE_BUILD_WITH_CMAKE + // Install tree has "/bin/cmake" and "". + std::string dir = cmSystemTools::GetFilenamePath(exe_dir); + cmSystemToolsCMakeRoot = dir + CMAKE_DATA_DIR; + if(!cmSystemTools::FileExists( + (cmSystemToolsCMakeRoot+"/Modules/CMake.cmake").c_str())) + { + // Build tree has "/bin[/]/cmake" and + // "/CMakeFiles/CMakeSourceDir.txt". + std::string src_dir_txt = dir + "/CMakeFiles/CMakeSourceDir.txt"; + std::ifstream fin(src_dir_txt.c_str()); + std::string src_dir; + if(fin && cmSystemTools::GetLineFromStream(fin, src_dir) && + cmSystemTools::FileIsDirectory(src_dir.c_str())) + { + cmSystemToolsCMakeRoot = src_dir; + } + else + { + dir = cmSystemTools::GetFilenamePath(dir); + src_dir_txt = dir + "/CMakeFiles/CMakeSourceDir.txt"; + std::ifstream fin2(src_dir_txt.c_str()); + if(fin2 && cmSystemTools::GetLineFromStream(fin2, src_dir) && + cmSystemTools::FileIsDirectory(src_dir.c_str())) + { + cmSystemToolsCMakeRoot = src_dir; + } + } + } +#else + // Bootstrap build knows its source. + cmSystemToolsCMakeRoot = CMAKE_ROOT_DIR; #endif } //---------------------------------------------------------------------------- -const char* cmSystemTools::GetExecutableDirectory() +std::string const& cmSystemTools::GetCMakeCommand() { - return cmSystemToolsExecutableDirectory.c_str(); + return cmSystemToolsCMakeCommand; +} + +//---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCTestCommand() +{ + return cmSystemToolsCTestCommand; +} + +//---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCPackCommand() +{ + return cmSystemToolsCPackCommand; +} + +//---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCMakeCursesCommand() +{ + return cmSystemToolsCMakeCursesCommand; +} + +//---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCMakeGUICommand() +{ + return cmSystemToolsCMakeGUICommand; +} + +//---------------------------------------------------------------------------- +std::string const& cmSystemTools::GetCMakeRoot() +{ + return cmSystemToolsCMakeRoot; } //---------------------------------------------------------------------------- diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 07235daac..69f6381d6 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -406,13 +406,16 @@ public: /** Random seed generation. */ static unsigned int RandomSeed(); - /** Find the directory containing the running executable. Save it - in a global location to be queried by GetExecutableDirectory - later. */ - static void FindExecutableDirectory(const char* argv0); + /** Find the directory containing CMake executables. */ + static void FindCMakeResources(const char* argv0); - /** Get the directory containing the currently running executable. */ - static const char* GetExecutableDirectory(); + /** Get the CMake resource paths, after FindCMakeResources. */ + static std::string const& GetCTestCommand(); + static std::string const& GetCPackCommand(); + static std::string const& GetCMakeCommand(); + static std::string const& GetCMakeGUICommand(); + static std::string const& GetCMakeCursesCommand(); + static std::string const& GetCMakeRoot(); #if defined(CMAKE_BUILD_WITH_CMAKE) /** Echo a message in color using KWSys's Terminal cprintf. */ diff --git a/Source/cmake.cxx b/Source/cmake.cxx index f786691d9..8bde300c9 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -932,34 +932,18 @@ void cmake::SetDirectoriesFromFile(const char* arg) // cache int cmake::AddCMakePaths() { - // Find the cmake executable - std::string cMakeSelf = cmSystemTools::GetExecutableDirectory(); - cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str()); - cMakeSelf += "/cmake"; - cMakeSelf += cmSystemTools::GetExecutableExtension(); -#ifdef __APPLE__ - // on the apple this might be the gui bundle - if(!cmSystemTools::FileExists(cMakeSelf.c_str())) - { - cMakeSelf = cmSystemTools::GetExecutableDirectory(); - cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str()); - cMakeSelf += "../../../.."; - cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str()); - cMakeSelf = cmSystemTools::CollapseFullPath(cMakeSelf.c_str()); - cMakeSelf += "/cmake"; - std::cerr << cMakeSelf.c_str() << "\n"; - } -#endif - if(!cmSystemTools::FileExists(cMakeSelf.c_str())) - { - cmSystemTools::Error("CMake executable cannot be found at ", - cMakeSelf.c_str()); - return 0; - } // Save the value in the cache this->CacheManager->AddCacheEntry - ("CMAKE_COMMAND",cMakeSelf.c_str(), "Path to CMake executable.", - cmCacheManager::INTERNAL); + ("CMAKE_COMMAND", cmSystemTools::GetCMakeCommand().c_str(), + "Path to CMake executable.", cmCacheManager::INTERNAL); +#ifdef CMAKE_BUILD_WITH_CMAKE + this->CacheManager->AddCacheEntry + ("CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(), + "Path to ctest program executable.", cmCacheManager::INTERNAL); + this->CacheManager->AddCacheEntry + ("CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand().c_str(), + "Path to cpack program executable.", cmCacheManager::INTERNAL); +#endif // if the edit command is not yet in the cache, // or if CMakeEditCommand has been set on this object, // then set the CMAKE_EDIT_COMMAND in the cache @@ -972,20 +956,17 @@ int cmake::AddCMakePaths() std::string editCacheCommand; if(!this->CMakeEditCommand.empty()) { - editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) - + std::string("/") - + this->CMakeEditCommand - + cmSystemTools::GetFilenameExtension(cMakeSelf); + editCacheCommand = this->CMakeEditCommand; } - if( !cmSystemTools::FileExists(editCacheCommand.c_str())) + if(!cmSystemTools::FileExists(editCacheCommand.c_str()) && + !cmSystemTools::GetCMakeCursesCommand().empty()) { - editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) + - "/ccmake" + cmSystemTools::GetFilenameExtension(cMakeSelf); + editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); } - if( !cmSystemTools::FileExists(editCacheCommand.c_str())) + if(!cmSystemTools::FileExists(editCacheCommand.c_str()) && + !cmSystemTools::GetCMakeGUICommand().empty()) { - editCacheCommand = cmSystemTools::GetFilenamePath(cMakeSelf) + - "/cmake-gui" + cmSystemTools::GetFilenameExtension(cMakeSelf); + editCacheCommand = cmSystemTools::GetCMakeGUICommand(); } if(cmSystemTools::FileExists(editCacheCommand.c_str())) { @@ -994,84 +975,19 @@ int cmake::AddCMakePaths() "Path to cache edit program executable.", cmCacheManager::INTERNAL); } } - std::string ctestCommand = cmSystemTools::GetFilenamePath(cMakeSelf) + - "/ctest" + cmSystemTools::GetFilenameExtension(cMakeSelf); - if(cmSystemTools::FileExists(ctestCommand.c_str())) - { - this->CacheManager->AddCacheEntry - ("CMAKE_CTEST_COMMAND", ctestCommand.c_str(), - "Path to ctest program executable.", cmCacheManager::INTERNAL); - } - std::string cpackCommand = cmSystemTools::GetFilenamePath(cMakeSelf) + - "/cpack" + cmSystemTools::GetFilenameExtension(cMakeSelf); - if(cmSystemTools::FileExists(cpackCommand.c_str())) - { - this->CacheManager->AddCacheEntry - ("CMAKE_CPACK_COMMAND", cpackCommand.c_str(), - "Path to cpack program executable.", cmCacheManager::INTERNAL); - } - // do CMAKE_ROOT, look for the environment variable first - std::string cMakeRoot; - std::string modules; - if (getenv("CMAKE_ROOT")) - { - cMakeRoot = getenv("CMAKE_ROOT"); - modules = cMakeRoot + "/Modules/CMake.cmake"; - } - if(!cmSystemTools::FileExists(modules.c_str())) - { - // next try exe/.. - cMakeRoot = cmSystemTools::GetRealPath(cMakeSelf.c_str()); - cMakeRoot = cmSystemTools::GetProgramPath(cMakeRoot.c_str()); - std::string::size_type slashPos = cMakeRoot.rfind("/"); - if(slashPos != std::string::npos) - { - cMakeRoot = cMakeRoot.substr(0, slashPos); - } - // is there no Modules directory there? - modules = cMakeRoot + "/Modules/CMake.cmake"; - } - - if (!cmSystemTools::FileExists(modules.c_str())) - { - // try exe/../share/cmake - cMakeRoot += CMAKE_DATA_DIR; - modules = cMakeRoot + "/Modules/CMake.cmake"; - } -#ifdef CMAKE_ROOT_DIR - if (!cmSystemTools::FileExists(modules.c_str())) - { - // try compiled in root directory - cMakeRoot = CMAKE_ROOT_DIR; - modules = cMakeRoot + "/Modules/CMake.cmake"; - } -#endif - if (!cmSystemTools::FileExists(modules.c_str())) - { - // try - cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str()); - cMakeRoot += CMAKE_DATA_DIR; - modules = cMakeRoot + "/Modules/CMake.cmake"; - } - if(!cmSystemTools::FileExists(modules.c_str())) - { - // next try exe - cMakeRoot = cmSystemTools::GetProgramPath(cMakeSelf.c_str()); - // is there no Modules directory there? - modules = cMakeRoot + "/Modules/CMake.cmake"; - } - if (!cmSystemTools::FileExists(modules.c_str())) + if(!cmSystemTools::FileExists( + (cmSystemTools::GetCMakeRoot()+"/Modules/CMake.cmake").c_str())) { // couldn't find modules cmSystemTools::Error("Could not find CMAKE_ROOT !!!\n" "CMake has most likely not been installed correctly.\n" "Modules directory not found in\n", - cMakeRoot.c_str()); + cmSystemTools::GetCMakeRoot().c_str()); return 0; } this->CacheManager->AddCacheEntry - ("CMAKE_ROOT", cMakeRoot.c_str(), + ("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(), "Path to CMake installation.", cmCacheManager::INTERNAL); return 1; @@ -1705,9 +1621,6 @@ int cmake::Run(const std::vector& args, bool noconfigure) return 0; } - // set the cmake command - this->CMakeCommand = args[0]; - if ( this->GetWorkingMode() == NORMAL_MODE ) { // load the cache @@ -1925,14 +1838,6 @@ int cmake::LoadCache() } } - if (this->CMakeCommand.size() < 2) - { - cmSystemTools::Error( - "cmake command was not specified prior to loading the cache in " - "cmake.cxx"); - return -1; - } - // setup CMAKE_ROOT and CMAKE_COMMAND if(!this->AddCMakePaths()) { @@ -2238,82 +2143,6 @@ inline std::string removeQuotes(const std::string& s) return s; } -std::string cmake::FindCMakeProgram(const char* name) const -{ - std::string path; - if ((name) && (*name)) - { - const cmMakefile* mf - = this->GetGlobalGenerator()->GetLocalGenerators()[0]->GetMakefile(); -#ifdef CMAKE_BUILD_WITH_CMAKE - path = mf->GetRequiredDefinition("CMAKE_COMMAND"); - path = removeQuotes(path); - path = cmSystemTools::GetFilenamePath(path.c_str()); - path += "/"; - path += name; - path += cmSystemTools::GetExecutableExtension(); - if(!cmSystemTools::FileExists(path.c_str())) - { - path = mf->GetRequiredDefinition("CMAKE_COMMAND"); - path = cmSystemTools::GetFilenamePath(path.c_str()); - path += "/Debug/"; - path += name; - path += cmSystemTools::GetExecutableExtension(); - } - if(!cmSystemTools::FileExists(path.c_str())) - { - path = mf->GetRequiredDefinition("CMAKE_COMMAND"); - path = cmSystemTools::GetFilenamePath(path.c_str()); - path += "/Release/"; - path += name; - path += cmSystemTools::GetExecutableExtension(); - } -#else - // Only for bootstrap - path += mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"); - path += "/"; - path += name; - path += cmSystemTools::GetExecutableExtension(); -#endif - } - return path; -} - -const char* cmake::GetCTestCommand() -{ - if ( this->CTestCommand.empty() ) - { - this->CTestCommand = this->FindCMakeProgram("ctest"); - } - if ( this->CTestCommand.empty() ) - { - cmSystemTools::Error("Cannot find the CTest executable"); - this->CTestCommand = "CTEST-COMMAND-NOT-FOUND"; - } - return this->CTestCommand.c_str(); -} - -const char* cmake::GetCPackCommand() -{ - if ( this->CPackCommand.empty() ) - { - this->CPackCommand = this->FindCMakeProgram("cpack"); - } - if ( this->CPackCommand.empty() ) - { - cmSystemTools::Error("Cannot find the CPack executable"); - this->CPackCommand = "CPACK-COMMAND-NOT-FOUND"; - } - return this->CPackCommand.c_str(); -} - - -const char* cmake::GetCMakeCommand() -{ - return this->CMakeCommand.c_str(); -} - - void cmake::MarkCliAsUsed(const std::string& variable) { this->UsedCliVariables[variable] = true; diff --git a/Source/cmake.h b/Source/cmake.h index 7fe130b52..d461fbd0a 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -200,9 +200,6 @@ class cmake ///! get the cmCachemManager used by this invocation of cmake cmCacheManager *GetCacheManager() { return this->CacheManager; } - ///! set the cmake command this instance of cmake should use - void SetCMakeCommand(const char* cmd) { this->CMakeCommand = cmd; } - /** * Given a variable name, return its value (as a string). */ @@ -301,13 +298,6 @@ class cmake */ cmFileTimeComparison* GetFileComparison() { return this->FileComparison; } - /** - * Get the path to ctest - */ - const char* GetCTestCommand(); - const char* GetCPackCommand(); - const char* GetCMakeCommand(); - // Do we want debug output during the cmake run. bool GetDebugOutput() { return this->DebugOutput; } void SetDebugOutputOn(bool b) { this->DebugOutput = b;} @@ -344,7 +334,7 @@ class cmake debugging configurations.*/ std::vector const& GetDebugConfigs(); - void SetCMakeEditCommand(const char* s) + void SetCMakeEditCommand(std::string const& s) { this->CMakeEditCommand = s; } @@ -425,8 +415,6 @@ protected: cmVariableWatch* VariableWatch; - ///! Find the full path to one of the cmake programs like ctest, cpack, etc. - std::string FindCMakeProgram(const char* name) const; private: cmake(const cmake&); // Not implemented. void operator=(const cmake&); // Not implemented. @@ -443,15 +431,12 @@ private: bool CheckSystemVars; std::map UsedCliVariables; std::string CMakeEditCommand; - std::string CMakeCommand; std::string CXXEnvironment; std::string CCEnvironment; std::string CheckBuildSystemArgument; std::string CheckStampFile; std::string CheckStampList; std::string VSSolutionFile; - std::string CTestCommand; - std::string CPackCommand; bool ClearBuildSystem; bool DebugTryCompile; cmFileTimeComparison* FileComparison; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index ff5c8ae24..6ef0579b9 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -162,7 +162,7 @@ static void cmakemainProgressCallback(const char *m, float prog, int main(int ac, char** av) { cmSystemTools::EnableMSVCDebugHook(); - cmSystemTools::FindExecutableDirectory(av[0]); + cmSystemTools::FindCMakeResources(av[0]); if(ac > 1) { if(strcmp(av[1], "--build") == 0) @@ -198,7 +198,6 @@ int do_cmake(int ac, char** av) // Construct and print requested documentation. cmake hcm; hcm.AddCMakePaths(); - doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT")); // the command line args are processed here so that you can do // -DCMAKE_MODULE_PATH=/some/path and have this value accessible here diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 12e71b61d..de0745860 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -115,7 +115,7 @@ int main (int argc, char *argv[]) { cmSystemTools::DoNotInheritStdPipes(); cmSystemTools::EnableMSVCDebugHook(); - cmSystemTools::FindExecutableDirectory(argv[0]); + cmSystemTools::FindCMakeResources(argv[0]); // Dispatch 'ctest --launch' mode directly. if(argc >= 2 && strcmp(argv[1], "--launch") == 0) @@ -151,7 +151,6 @@ int main (int argc, char *argv[]) { cmake hcm; hcm.AddCMakePaths(); - doc.SetCMakeRoot(hcm.GetCacheDefinition("CMAKE_ROOT")); // Construct and print requested documentation. cmCTestScriptHandler* ch =