cmFindProgramCommand: Re-implement search using more flexible approach

Avoid using KWSys SystemTools::FindProgram because it does much more
than we actually need for find_program and does not allow us to control
the order of preference between directories and names.  Create our own
cmFindProgramHelper much like cmFindLibraryHelper but without all the
find_library-specific parts.
This commit is contained in:
Brad King 2015-09-01 13:54:33 -04:00
parent fdbfc9f677
commit fc1990c933
2 changed files with 97 additions and 1 deletions

View File

@ -16,6 +16,75 @@
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#endif #endif
//----------------------------------------------------------------------------
struct cmFindProgramHelper
{
cmFindProgramHelper()
{
#if defined (_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
// Consider platform-specific extensions.
this->Extensions.push_back(".com");
this->Extensions.push_back(".exe");
#endif
// Consider original name with no extensions.
this->Extensions.push_back("");
}
// List of valid extensions.
std::vector<std::string> Extensions;
// Keep track of the best program file found so far.
std::string BestPath;
// Current names under consideration.
std::vector<std::string> Names;
// Current full path under consideration.
std::string TestPath;
void AddName(std::string const& name)
{
this->Names.push_back(name);
}
void SetName(std::string const& name)
{
this->Names.clear();
this->AddName(name);
}
bool CheckDirectory(std::string const& path)
{
for (std::vector<std::string>::iterator i = this->Names.begin();
i != this->Names.end(); ++i)
{
if (this->CheckDirectoryForName(path, *i))
{
return true;
}
}
return false;
}
bool CheckDirectoryForName(std::string const& path, std::string const& name)
{
for (std::vector<std::string>::iterator ext = this->Extensions.begin();
ext != this->Extensions.end(); ++ext)
{
this->TestPath = path;
this->TestPath += name;
if (!ext->empty() && cmSystemTools::StringEndsWith(name, ext->c_str()))
{
continue;
}
this->TestPath += *ext;
if (cmSystemTools::FileExists(this->TestPath, true))
{
this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
return true;
}
}
return false;
}
};
// cmFindProgramCommand // cmFindProgramCommand
bool cmFindProgramCommand bool cmFindProgramCommand
::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &) ::InitialPass(std::vector<std::string> const& argsIn, cmExecutionStatus &)
@ -69,7 +138,7 @@ std::string cmFindProgramCommand::FindProgram()
} }
if(program.empty() && !this->SearchAppBundleOnly) if(program.empty() && !this->SearchAppBundleOnly)
{ {
program = cmSystemTools::FindProgram(this->Names, this->SearchPaths, true); program = this->FindNormalProgram();
} }
if(program.empty() && this->SearchAppBundleLast) if(program.empty() && this->SearchAppBundleLast)
@ -79,6 +148,32 @@ std::string cmFindProgramCommand::FindProgram()
return program; return program;
} }
//----------------------------------------------------------------------------
std::string cmFindProgramCommand::FindNormalProgram()
{
// Search the entire path for each name.
cmFindProgramHelper helper;
for (std::vector<std::string>::const_iterator ni = this->Names.begin();
ni != this->Names.end() ; ++ni)
{
// Switch to searching for this name.
helper.SetName(*ni);
// Search every directory.
for (std::vector<std::string>::const_iterator
p = this->SearchPaths.begin();
p != this->SearchPaths.end(); ++p)
{
if (helper.CheckDirectory(*p))
{
return helper.BestPath;
}
}
}
// Couldn't find the program.
return "";
}
std::string cmFindProgramCommand::FindAppBundle() std::string cmFindProgramCommand::FindAppBundle()
{ {
for(std::vector<std::string>::const_iterator name = this->Names.begin(); for(std::vector<std::string>::const_iterator name = this->Names.begin();

View File

@ -54,6 +54,7 @@ public:
private: private:
std::string FindProgram(); std::string FindProgram();
std::string FindNormalProgram();
std::string FindAppBundle(); std::string FindAppBundle();
std::string GetBundleExecutable(std::string bundlePath); std::string GetBundleExecutable(std::string bundlePath);