ENH: Improved implementation of INSTALL_FILES and INSTALL_PROGRAMS commands. Source paths can now be relative or full paths, and don't need to be in the same directory as the CMakeLists.txt file.

This commit is contained in:
Brad King 2002-09-17 10:56:18 -04:00
parent 222b04f6d9
commit e5e0132203
5 changed files with 163 additions and 60 deletions

View File

@ -30,16 +30,30 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
// Create an INSTALL_FILES target specifically for this path.
m_TargetName = "INSTALL_FILES_"+args[0];
cmTarget target;
cmTarget& target = m_Makefile->GetTargets()[m_TargetName];
target.SetInAll(false);
target.SetType(cmTarget::INSTALL_FILES);
target.SetInstallPath(args[0].c_str());
m_Makefile->GetTargets().insert(cmTargets::value_type(m_TargetName, target));
std::vector<std::string>::const_iterator s = args.begin();
for (++s;s != args.end(); ++s)
if((args.size() > 1) && (args[1] == "FILES"))
{
m_FinalArgs.push_back(*s);
m_IsFilesForm = true;
for(std::vector<std::string>::const_iterator s = args.begin()+2;
s != args.end(); ++s)
{
// Find the source location for each file listed.
std::string f = this->FindInstallSource(s->c_str());
target.GetSourceLists().push_back(f);
}
}
else
{
m_IsFilesForm = false;
std::vector<std::string>::const_iterator s = args.begin();
for (++s;s != args.end(); ++s)
{
m_FinalArgs.push_back(*s);
}
}
return true;
@ -47,6 +61,12 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& argsIn)
void cmInstallFilesCommand::FinalPass()
{
// No final pass for "FILES" form of arguments.
if(m_IsFilesForm)
{
return;
}
std::string testf;
std::string ext = m_FinalArgs[0];
std::vector<std::string>& targetSourceLists =
@ -72,8 +92,9 @@ void cmInstallFilesCommand::FinalPass()
{
testf = cmSystemTools::GetFilenameWithoutLastExtension(temps) + ext;
}
// add to the result
targetSourceLists.push_back(testf);
targetSourceLists.push_back(this->FindInstallSource(testf.c_str()));
}
}
else // reg exp list
@ -87,9 +108,47 @@ void cmInstallFilesCommand::FinalPass()
// for each argument, get the files
for (;s != files.end(); ++s)
{
targetSourceLists.push_back(*s);
targetSourceLists.push_back(this->FindInstallSource(s->c_str()));
}
}
}
/**
* Find a file in the build or source tree for installation given a
* relative path from the CMakeLists.txt file. This will favor files
* present in the build tree. If a full path is given, it is just
* returned.
*/
std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
{
if(cmSystemTools::FileIsFullPath(name))
{
// This is a full path.
return name;
}
// This is a relative path.
std::string tb = m_Makefile->GetCurrentOutputDirectory();
tb += "/";
tb += name;
std::string ts = m_Makefile->GetCurrentDirectory();
ts += "/";
ts += name;
if(cmSystemTools::FileExists(tb.c_str()))
{
// The file exists in the binary tree. Use it.
return tb;
}
else if(cmSystemTools::FileExists(ts.c_str()))
{
// The file exists in the source tree. Use it.
return ts;
}
else
{
// The file doesn't exist. Assume it will be present in the
// binary tree when the install occurs.
return tb;
}
}

View File

@ -72,14 +72,29 @@ public:
return
"INSTALL_FILES(path extension file file ...)\n"
"INSTALL_FILES(path regexp)\n"
"Create rules to install the listed files into the path. Path is relative to the variable CMAKE_INSTALL_PREFIX. There are two forms for this command. In the first the files can be specified explicitly. If a file specified already has an extension, that extension will be removed first. This is useful for providing lists of source files such as foo.cxx when you want the corresponding foo.h to be installed. A typical extension is .h etc... In the second form any files in the current directory that match the regular expression will be installed.";
"INSTALL_FILES(path FILES file file ...)\n"
"Create rules to install the listed files into the path. Path is\n"
"relative to the variable CMAKE_INSTALL_PREFIX. There are three forms for\n"
"this command. In the first the files can be specified explicitly. If a\n"
"file specified already has an extension, that extension will be\n"
"removed first. This is useful for providing lists of source files such\n"
"as foo.cxx when you want the corresponding foo.h to be installed. A\n"
"typical extension is .h etc... In the second form any files in the\n"
"current directory that match the regular expression will be installed.\n"
"In the third form, any files listed after the FILES keyword will be\n"
"installed explicitly from the names given. Full paths are allowed in\n"
"this form.";
}
cmTypeMacro(cmInstallFilesCommand, cmCommand);
protected:
std::string FindInstallSource(const char* name) const;
private:
std::string m_TargetName;
std::vector<std::string> m_FinalArgs;
bool m_IsFilesForm;
};

View File

@ -30,11 +30,10 @@ bool cmInstallProgramsCommand::InitialPass(std::vector<std::string> const& argsI
// Create an INSTALL_PROGRAMS target specifically for this path.
m_TargetName = "INSTALL_PROGRAMS_"+args[0];
cmTarget target;
cmTarget& target = m_Makefile->GetTargets()[m_TargetName];
target.SetInAll(false);
target.SetType(cmTarget::INSTALL_PROGRAMS);
target.SetInstallPath(args[0].c_str());
m_Makefile->GetTargets().insert(cmTargets::value_type(m_TargetName, target));
std::vector<std::string>::const_iterator s = args.begin();
for (++s;s != args.end(); ++s)
@ -58,7 +57,7 @@ void cmInstallProgramsCommand::FinalPass()
s != m_FinalArgs.end(); ++s)
{
// add to the result
targetSourceLists.push_back(*s);
targetSourceLists.push_back(this->FindInstallSource(s->c_str()));
}
}
else // reg exp list
@ -71,9 +70,47 @@ void cmInstallProgramsCommand::FinalPass()
// for each argument, get the programs
for (;s != programs.end(); ++s)
{
targetSourceLists.push_back(*s);
targetSourceLists.push_back(this->FindInstallSource(s->c_str()));
}
}
}
/**
* Find a file in the build or source tree for installation given a
* relative path from the CMakeLists.txt file. This will favor files
* present in the build tree. If a full path is given, it is just
* returned.
*/
std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
{
if(cmSystemTools::FileIsFullPath(name))
{
// This is a full path.
return name;
}
// This is a relative path.
std::string tb = m_Makefile->GetCurrentOutputDirectory();
tb += "/";
tb += name;
std::string ts = m_Makefile->GetCurrentDirectory();
ts += "/";
ts += name;
if(cmSystemTools::FileExists(tb.c_str()))
{
// The file exists in the binary tree. Use it.
return tb;
}
else if(cmSystemTools::FileExists(ts.c_str()))
{
// The file exists in the source tree. Use it.
return ts;
}
else
{
// The file doesn't exist. Assume it will be present in the
// binary tree when the install occurs.
return tb;
}
}

View File

@ -77,7 +77,9 @@ public:
cmTypeMacro(cmInstallProgramsCommand, cmCommand);
private:
protected:
std::string FindInstallSource(const char* name) const;
private:
std::string m_TargetName;
std::vector<std::string> m_FinalArgs;
};

View File

@ -1664,81 +1664,71 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
break;
case cmTarget::INSTALL_FILES:
{
std::string sourcePath = m_Makefile->GetCurrentDirectory();
std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
sourcePath += "/";
binaryPath += "/";
const std::vector<std::string> &sf = l->second.GetSourceLists();
std::vector<std::string>::const_iterator i;
for (i = sf.begin(); i != sf.end(); ++i)
{
fout << "\t@ echo \"Installing " << *i << " \"\n";
fout << "\t@if [ -f " << *i << " ] ; then \\\n";
std::string f = *i;
if(f.substr(0, sourcePath.length()) == sourcePath)
{
f = f.substr(sourcePath.length());
}
else if(f.substr(0, binaryPath.length()) == binaryPath)
{
f = f.substr(binaryPath.length());
}
fout << "\t@ echo \"Installing " << f.c_str() << " \"\n";
// avoid using install-sh to install install-sh
// does not work on windows....
if(*i == "install-sh")
{
fout << "\t cp ";
fout << "\t @cp ";
}
else
{
fout << "\t $(INSTALL_DATA) ";
fout << "\t @$(INSTALL_DATA) ";
}
fout << *i
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "; \\\n";
fout << "\t elif [ -f $(CMAKE_CURRENT_SOURCE)/" << *i << " ] ; then \\\n";
// avoid using install-sh to install install-sh
// does not work on windows....
if(*i == "install-sh")
{
fout << "\t cp ";
}
else
{
fout << "\t $(INSTALL_DATA) ";
}
fout << "$(CMAKE_CURRENT_SOURCE)/" << *i
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "; \\\n";
fout << "\telse \\\n";
fout << "\t echo \" ERROR!!! Unable to find: " << *i
<< " \"; \\\n";
fout << "\t fi\n";
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "\n";
}
}
break;
case cmTarget::INSTALL_PROGRAMS:
{
std::string sourcePath = m_Makefile->GetCurrentDirectory();
std::string binaryPath = m_Makefile->GetCurrentOutputDirectory();
sourcePath += "/";
binaryPath += "/";
const std::vector<std::string> &sf = l->second.GetSourceLists();
std::vector<std::string>::const_iterator i;
for (i = sf.begin(); i != sf.end(); ++i)
{
fout << "\t@ echo \"Installing " << *i << " \"\n";
fout << "\t@if [ -f " << *i << " ] ; then \\\n";
std::string f = *i;
if(f.substr(0, sourcePath.length()) == sourcePath)
{
f = f.substr(sourcePath.length());
}
else if(f.substr(0, binaryPath.length()) == binaryPath)
{
f = f.substr(binaryPath.length());
}
fout << "\t@ echo \"Installing " << f.c_str() << " \"\n";
// avoid using install-sh to install install-sh
// does not work on windows....
if(*i == "install-sh")
{
fout << "\t cp ";
fout << "\t @cp ";
}
else
{
fout << "\t $(INSTALL_PROGRAM) ";
fout << "\t @$(INSTALL_DATA) ";
}
fout << *i
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "; \\\n";
fout << "\t elif [ -f $(CMAKE_CURRENT_SOURCE)/" << *i << " ] ; then \\\n";
// avoid using install-sh to install install-sh
// does not work on windows....
if(*i == "install-sh")
{
fout << "\t cp ";
}
else
{
fout << "\t $(INSTALL_PROGRAM) ";
}
fout << "$(CMAKE_CURRENT_SOURCE)/" << *i
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "; \\\n";
fout << "\telse \\\n";
fout << "\t echo \" ERROR!!! Unable to find: " << *i
<< " \"; \\\n";
fout << "\t fi\n";
<< " $(DESTDIR)" << prefix << l->second.GetInstallPath() << "\n";
}
}
break;