diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 990bd471a..d16354a56 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -30,16 +30,30 @@ bool cmInstallFilesCommand::InitialPass(std::vector 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::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::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::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 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& 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; + } +} diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index 7297bbcc6..2c78c5f71 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -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 m_FinalArgs; + bool m_IsFilesForm; }; diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 6049bb0cb..6089538df 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -30,11 +30,10 @@ bool cmInstallProgramsCommand::InitialPass(std::vector 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::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; + } +} diff --git a/Source/cmInstallProgramsCommand.h b/Source/cmInstallProgramsCommand.h index 7a19297a8..1ab5a9773 100644 --- a/Source/cmInstallProgramsCommand.h +++ b/Source/cmInstallProgramsCommand.h @@ -77,7 +77,9 @@ public: cmTypeMacro(cmInstallProgramsCommand, cmCommand); - private: +protected: + std::string FindInstallSource(const char* name) const; +private: std::string m_TargetName; std::vector m_FinalArgs; }; diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 7abe109e9..09ccc2f1a 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -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 &sf = l->second.GetSourceLists(); std::vector::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 &sf = l->second.GetSourceLists(); std::vector::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;