From 5079efdc68c94d93a2b77e5b42dd229de2a77836 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 May 2001 16:55:18 -0400 Subject: [PATCH] ENH: Added cmSystemTools::FindProgram() and full-path detection utilities. --- Source/cmFindProgramCommand.cxx | 32 +++---- Source/cmSystemTools.cxx | 152 ++++++++++++++++++++++++++++++++ Source/cmSystemTools.h | 9 ++ 3 files changed, 174 insertions(+), 19 deletions(-) diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index a3d18549e..aef1a74e6 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -76,27 +76,21 @@ bool cmFindProgramCommand::Invoke(std::vector& args) m_Makefile->ExpandVariablesInString(exp); path.push_back(exp); } - cmSystemTools::GetPath(path); - - for(unsigned int k=0; k < path.size(); k++) + + // Try to find the program. + std::string result = cmSystemTools::FindProgram(i->c_str(), path); + + if(result != "") { - std::string tryPath = path[k]; - tryPath += "/"; - tryPath += *i; -#ifdef _WIN32 - tryPath += ".exe"; -#endif - if(cmSystemTools::FileExists(tryPath.c_str())) - { - // Save the value in the cache - cmCacheManager::GetInstance()->AddCacheEntry(define, - tryPath.c_str(), - "Path to a program.", - cmCacheManager::FILEPATH); - m_Makefile->AddDefinition(define, tryPath.c_str()); - return true; - } + // Save the value in the cache + cmCacheManager::GetInstance()->AddCacheEntry(define, + result.c_str(), + "Path to a program.", + cmCacheManager::FILEPATH); + m_Makefile->AddDefinition(define, result.c_str()); + return true; } + return false; } diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 9211d8b1d..0a2ff7921 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -53,6 +53,14 @@ inline int Mkdir(const char* dir) { return _mkdir(dir); } +inline const char* Getcwd(char* buf, unsigned int len) +{ + return _getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + return _chdir(dir); +} #else #include #include @@ -61,6 +69,14 @@ inline int Mkdir(const char* dir) { return mkdir(dir, 00777); } +inline const char* Getcwd(char* buf, unsigned int len) +{ + return getcwd(buf, len); +} +inline int Chdir(const char* dir) +{ + return chdir(dir); +} #endif bool cmSystemTools::s_ErrorOccured = false; @@ -561,3 +577,139 @@ bool cmSystemTools::IsOff(const char* val) return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" || v == "N" || v == "NOTFOUND"); } + + +/** + * Find the executable with the given name. Searches the given path and then + * the system search path. Returns the full path to the executable if it is + * found. Otherwise, the empty string is returned. + */ +std::string cmSystemTools::FindProgram(const char* name, + const std::vector& userPaths) +{ + // See if the executable exists as written. + if(cmSystemTools::FileExists(name)) + { + return cmSystemTools::CollapseFullPath(name); + } + + // Add the system search path to our path. + std::vector path = userPaths; + cmSystemTools::GetPath(path); + + for(std::vector::const_iterator p = path.begin(); + p != path.end(); ++p) + { + std::string tryPath = *p; + tryPath += "/"; + tryPath += name; + if(cmSystemTools::FileExists(tryPath.c_str())) + { + return cmSystemTools::CollapseFullPath(tryPath.c_str()); + } + tryPath += cmSystemTools::GetExecutableExtension(); + if(cmSystemTools::FileExists(tryPath.c_str())) + { + return cmSystemTools::CollapseFullPath(tryPath.c_str()); + } + } + + // Couldn't find the program. + return ""; +} + +bool cmSystemTools::FileIsDirectory(const char* name) +{ + struct stat fs; + if(stat(name, &fs) == 0) + { +#if _WIN32 + return ((fs.st_mode & _S_IFDIR) != 0); +#else + return S_ISDIR(fs.st_mode); +#endif + } + else + { + return false; + } +} + + +std::string cmSystemTools::GetCurrentWorkingDirectory() +{ + char buf[2048]; + std::string path = Getcwd(buf, 2048); + return path; +} + +/** + * Given the path to a program executable, get the directory part of the path with the + * file stripped off. If there is no directory part, the empty string is returned. + */ +std::string cmSystemTools::GetProgramPath(const char* in_name) +{ + std::string dir, file; + cmSystemTools::SplitProgramPath(in_name, dir, file); + return dir; +} + +/** + * Given the path to a program executable, get the directory part of the path with the + * file stripped off. If there is no directory part, the empty string is returned. + */ +void cmSystemTools::SplitProgramPath(const char* in_name, + std::string& dir, + std::string& file) +{ + dir = in_name; + file = ""; + cmSystemTools::ConvertToUnixSlashes(dir); + + if(!cmSystemTools::FileIsDirectory(dir.c_str())) + { + std::string::size_type slashPos = dir.rfind("/"); + if(slashPos != std::string::npos) + { + file = dir.substr(slashPos+1) + file; + dir = dir.substr(0, slashPos); + } + else + { + file = dir; + dir = ""; + } + } + + if((dir != "") && !cmSystemTools::FileIsDirectory(dir.c_str())) + { + std::string oldDir = in_name; + cmSystemTools::ConvertToUnixSlashes(oldDir); + cmSystemTools::Error("Error splitting file name off end of path:\n", + oldDir.c_str()); + dir = in_name; + return; + } +} + +/** + * Given a path to a file or directory, convert it to a full path. + * This collapses away relative paths. The full path is returned. + */ +std::string cmSystemTools::CollapseFullPath(const char* in_name) +{ + std::string dir, file; + cmSystemTools::SplitProgramPath(in_name, dir, file); + // Ultra-hack warning: + // This changes to the target directory, saves the working directory, + // and then changes back to the original working directory. + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + if(dir != "") { Chdir(dir.c_str()); } + std::string newDir = cmSystemTools::GetCurrentWorkingDirectory(); + Chdir(cwd.c_str()); + + cmSystemTools::ConvertToUnixSlashes(newDir); + std::string newPath = newDir+"/"+file; + + return newPath; +} diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 2cc9c8ecf..3c6fd4569 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -166,6 +166,15 @@ public: */ static bool IsOff(const char* val); + static std::string FindProgram(const char* name, + const std::vector& = std::vector()); + + static bool FileIsDirectory(const char* name); + static std::string GetCurrentWorkingDirectory(); + static std::string GetProgramPath(const char*); + static void SplitProgramPath(const char* in_name, std::string& dir, std::string& file); + static std::string CollapseFullPath(const char*); + static long int ModifiedTime(const char* filename); private: