From a2e136fd17b693765a4961220433bdf207930583 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 3 Mar 2006 18:44:32 -0500 Subject: [PATCH] ENH: Added PERMISSIONS and RENAME options to the INSTALL command's FILES and PROGRAMS mode, and corresponding support to FILE(INSTALL). Default permissions for shared libraries on non-Windows/non-OSX platforms no longer has the execute bit set. --- Source/cmFileCommand.cxx | 406 ++++++++++++++++++--------- Source/cmInstallCommand.cxx | 80 +++++- Source/cmInstallCommand.h | 30 +- Source/cmInstallFilesGenerator.cxx | 12 +- Source/cmInstallFilesGenerator.h | 5 +- Source/cmInstallGenerator.cxx | 12 +- Source/cmInstallGenerator.h | 4 +- Source/cmLocalGenerator.cxx | 10 +- Tests/SimpleInstall/CMakeLists.txt | 10 +- Tests/SimpleInstall/inst.cxx | 10 +- Tests/SimpleInstall/inst2.cxx | 2 + Tests/SimpleInstallS2/CMakeLists.txt | 10 +- Tests/SimpleInstallS2/inst.cxx | 10 +- Tests/SimpleInstallS2/inst2.cxx | 2 + 14 files changed, 452 insertions(+), 151 deletions(-) create mode 100644 Tests/SimpleInstall/inst2.cxx create mode 100644 Tests/SimpleInstallS2/inst2.cxx diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 36d309e79..3c45d666f 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -276,6 +276,7 @@ bool cmFileCommand::HandleInstallCommand( return false; } + std::string rename = ""; std::string destination = ""; std::string stype = "FILES"; const char* build_type = m_Makefile->GetDefinition("BUILD_TYPE"); @@ -298,8 +299,38 @@ bool cmFileCommand::HandleInstallCommand( std::map properties; + // Build a table of permissions flags. +#if defined(_WIN32) && !defined(__CYGWIN__) + mode_t mode_owner_read = S_IREAD; + mode_t mode_owner_write = S_IWRITE; + mode_t mode_owner_execute = S_IEXEC; + mode_t mode_group_read = 0; + mode_t mode_group_write = 0; + mode_t mode_group_execute = 0; + mode_t mode_world_read = 0; + mode_t mode_world_write = 0; + mode_t mode_world_execute = 0; + mode_t mode_setuid = 0; + mode_t mode_setgid = 0; +#else + mode_t mode_owner_read = S_IRUSR; + mode_t mode_owner_write = S_IWUSR; + mode_t mode_owner_execute = S_IXUSR; + mode_t mode_group_read = S_IRGRP; + mode_t mode_group_write = S_IWGRP; + mode_t mode_group_execute = S_IXGRP; + mode_t mode_world_read = S_IROTH; + mode_t mode_world_write = S_IWOTH; + mode_t mode_world_execute = S_IXOTH; + mode_t mode_setuid = S_ISUID; + mode_t mode_setgid = S_ISGID; +#endif + bool in_files = false; bool in_properties = false; + bool in_permissions = false; + bool use_given_permissions = false; + mode_t permissions = 0; bool optional = false; for ( ; i != args.size(); ++i ) { @@ -310,6 +341,7 @@ bool cmFileCommand::HandleInstallCommand( destination = args[i]; in_files = false; in_properties = false; + in_permissions = false; } else if ( *cstr == "TYPE" && i < args.size()-1 ) { @@ -322,16 +354,34 @@ bool cmFileCommand::HandleInstallCommand( } in_properties = false; in_files = false; + in_permissions = false; + } + else if ( *cstr == "RENAME" && i < args.size()-1 ) + { + i++; + rename = args[i]; + in_properties = false; + in_files = false; + in_permissions = false; } else if ( *cstr == "PROPERTIES" ) { in_properties = true; in_files = false; + in_permissions = false; + } + else if ( *cstr == "PERMISSIONS" ) + { + use_given_permissions = true; + in_properties = false; + in_files = false; + in_permissions = true; } else if ( *cstr == "FILES" && !in_files) { in_files = true; in_properties = false; + in_permissions = false; } else if ( in_properties && i < args.size()-1 ) { @@ -342,6 +392,50 @@ bool cmFileCommand::HandleInstallCommand( { files.push_back(*cstr); } + else if(in_permissions && args[i] == "OWNER_READ") + { + permissions |= mode_owner_read; + } + else if(in_permissions && args[i] == "OWNER_WRITE") + { + permissions |= mode_owner_write; + } + else if(in_permissions && args[i] == "OWNER_EXECUTE") + { + permissions |= mode_owner_execute; + } + else if(in_permissions && args[i] == "GROUP_READ") + { + permissions |= mode_group_read; + } + else if(in_permissions && args[i] == "GROUP_WRITE") + { + permissions |= mode_group_write; + } + else if(in_permissions && args[i] == "GROUP_EXECUTE") + { + permissions |= mode_group_execute; + } + else if(in_permissions && args[i] == "WORLD_READ") + { + permissions |= mode_world_read; + } + else if(in_permissions && args[i] == "WORLD_WRITE") + { + permissions |= mode_world_write; + } + else if(in_permissions && args[i] == "WORLD_EXECUTE") + { + permissions |= mode_world_execute; + } + else if(in_permissions && args[i] == "SETUID") + { + permissions |= mode_setuid; + } + else if(in_permissions && args[i] == "SETGID") + { + permissions |= mode_setgid; + } else { this->SetError("called with inappropriate arguments"); @@ -458,6 +552,61 @@ bool cmFileCommand::HandleInstallCommand( return false; } + // Check rename form. + if(!rename.empty()) + { + if(itype != cmTarget::INSTALL_FILES) + { + this->SetError("INSTALL option RENAME may be used only with FILES."); + return false; + } + if(files.size() > 1) + { + this->SetError("INSTALL option RENAME may be used only with one file."); + return false; + } + } + + // If permissions were not specified set default permissions for + // this target type. + bool use_source_permissions = false; + if(!use_given_permissions) + { + switch(itype) + { + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: +#if !defined(_WIN32) && !defined(__APPLE_CC__) + // Use read/write permissions. + use_given_permissions = true; + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_group_read; + permissions |= mode_world_read; + break; +#endif + case cmTarget::EXECUTABLE: + case cmTarget::INSTALL_PROGRAMS: + // Use read/write/executable permissions. + use_given_permissions = true; + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_owner_execute; + permissions |= mode_group_read; + permissions |= mode_group_execute; + permissions |= mode_world_read; + permissions |= mode_world_execute; + break; + default: + // Use the permissions of the file being copied. + use_source_permissions = true; + break; + } + } + + // Get the current manifest. const char* manifest_files = m_Makefile->GetDefinition("CMAKE_INSTALL_MANIFEST_FILES"); std::string smanifest_files; @@ -466,26 +615,24 @@ bool cmFileCommand::HandleInstallCommand( smanifest_files = manifest_files; } + // Handle each file listed. for ( i = 0; i < files.size(); i ++ ) { - std::string destfilewe - = destination + "/" - + cmSystemTools::GetFilenameWithoutExtension(files[i]); - std::string ctarget = files[i].c_str(); - std::string fname = cmSystemTools::GetFilenameName(ctarget); - std::string ext = cmSystemTools::GetFilenameExtension(ctarget); - std::string fnamewe - = cmSystemTools::GetFilenameWithoutExtension(ctarget); - std::string destfile = destfilewe; - if ( ext.size() ) + // Split the input file into its directory and name components. + std::string fromDir = cmSystemTools::GetFilenamePath(files[i]); + std::string fromName = cmSystemTools::GetFilenameName(files[i]); + + // Compute the full path to the destination file. + std::string toFile = destination; + toFile += "/"; + toFile += rename.empty()? fromName : rename; + + // Handle type-specific installation details. + switch(itype) { - destfile += ext; - } - switch( itype ) - { - case cmTarget::MODULE_LIBRARY: - case cmTarget::STATIC_LIBRARY: - case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + case cmTarget::STATIC_LIBRARY: + case cmTarget::SHARED_LIBRARY: { // Handle shared library versioning const char* lib_version = 0; @@ -508,18 +655,18 @@ bool cmFileCommand::HandleInstallCommand( } if ( lib_version && lib_soversion ) { - std::string libname = destfile; - std::string soname = destfile; - std::string soname_nopath = fname; + std::string libname = toFile; + std::string soname = toFile; + std::string soname_nopath = fromName; soname += "."; soname += lib_soversion; soname_nopath += "."; soname_nopath += lib_soversion; - fname += "."; - fname += lib_version; - destfile += "."; - destfile += lib_version; + fromName += "."; + fromName += lib_version; + toFile += "."; + toFile += lib_version; cmSystemTools::RemoveFile(soname.c_str()); cmSystemTools::RemoveFile(libname.c_str()); @@ -532,11 +679,11 @@ bool cmFileCommand::HandleInstallCommand( } smanifest_files += ";"; smanifest_files += libname.substr(destDirLength);; - if ( destfile != soname ) + if ( toFile != soname ) { - if ( !cmSystemTools::CreateSymlink(fname.c_str(), soname.c_str()) ) + if ( !cmSystemTools::CreateSymlink(fromName.c_str(), soname.c_str()) ) { - std::string errstring = "error when creating symlink from: " + soname + " to " + fname; + std::string errstring = "error when creating symlink from: " + soname + " to " + fromName; this->SetError(errstring.c_str()); return false; } @@ -544,129 +691,134 @@ bool cmFileCommand::HandleInstallCommand( smanifest_files += soname.substr(destDirLength); } } - - // Reconstruct the source file path taking into account the - // possibly new file name. - cmOStringStream str; - str << cmSystemTools::GetFilenamePath(ctarget) << "/" << fname; - ctarget = str.str(); } - break; - case cmTarget::EXECUTABLE: - { - // Handle executable versioning - const char* exe_version = 0; - if ( properties.find("VERSION") != properties.end() ) + break; + case cmTarget::EXECUTABLE: { - exe_version = properties["VERSION"]; - } - if ( exe_version ) - { - std::string exename = destfile; - std::string exename_nopath = fname; - exename_nopath += "-"; - exename_nopath += exe_version; - - fname += "-"; - fname += exe_version; - destfile += "-"; - destfile += exe_version; - - cmSystemTools::RemoveFile(exename.c_str()); - - if (!cmSystemTools::CreateSymlink(exename_nopath.c_str(), exename.c_str()) ) + // Handle executable versioning + const char* exe_version = 0; + if ( properties.find("VERSION") != properties.end() ) { - std::string errstring = "error when creating symlink from: " + exename + " to " + exename_nopath; - this->SetError(errstring.c_str()); - return false; + exe_version = properties["VERSION"]; } - smanifest_files += ";"; - smanifest_files += exename.substr(destDirLength); - } + if ( exe_version ) + { + std::string exename = toFile; + std::string exename_nopath = fromName; + exename_nopath += "-"; + exename_nopath += exe_version; - // Reconstruct the source file path taking into account the - // possibly new file name. - cmOStringStream str; - str << cmSystemTools::GetFilenamePath(ctarget) << "/" << fname; - ctarget = str.str(); - } - break; + fromName += "-"; + fromName += exe_version; + toFile += "-"; + toFile += exe_version; + + cmSystemTools::RemoveFile(exename.c_str()); + + if (!cmSystemTools::CreateSymlink(exename_nopath.c_str(), exename.c_str()) ) + { + std::string errstring = "error when creating symlink from: " + exename + " to " + exename_nopath; + this->SetError(errstring.c_str()); + return false; + } + smanifest_files += ";"; + smanifest_files += exename.substr(destDirLength); + } + } + break; } + // Construct the full path to the source file. The file name may + // have been changed above. + std::string fromFile = fromDir; + fromFile += "/"; + fromFile += fromName; + std::string message; - if ( !cmSystemTools::SameFile(ctarget.c_str(), destfile.c_str()) ) + if(!cmSystemTools::SameFile(fromFile.c_str(), toFile.c_str())) { - if ( cmSystemTools::FileExists(ctarget.c_str()) ) + if(cmSystemTools::FileExists(fromFile.c_str())) { + // We will install this file. Display the information. message = "Installing "; - message += destfile.c_str(); + message += toFile.c_str(); m_Makefile->DisplayStatus(message.c_str(), -1); - cmSystemTools::RemoveFile(destfile.c_str()); - if ( !cmSystemTools::CopyFileAlways(ctarget.c_str(), - destination.c_str()) ) + + // If no permissions were already given use the permissions of + // the file being copied. + if(!use_given_permissions && + (!use_source_permissions || + !cmSystemTools::GetPermissions(fromFile.c_str(), permissions))) { - std::string errstring = "cannot copy file: " + ctarget + - " to directory : " + destination + "."; - this->SetError(errstring.c_str()); + // Set default permissions. + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_group_read; + permissions |= mode_world_read; + } + + // Remove the original file and try copying the new file. + // TODO: This should be copy-if-different. Don't forget to + // edit the destination file permissions, or compare files + // first. This would need a new SystemTools::FilesDiffer that + // does not read all of the files at once. + cmSystemTools::RemoveFile(toFile.c_str()); + if(!cmSystemTools::CopyFileAlways(fromFile.c_str(), toFile.c_str())) + { + cmOStringStream e; + e << "INSTALL cannot copy file \"" << fromFile + << "\" to \"" << toFile + "\"."; + this->SetError(e.str().c_str()); return false; } - switch( itype ) - { - case cmTarget::STATIC_LIBRARY: + + // Perform post-installation processing on the file depending + // on its type. #if defined(__APPLE_CC__) - { - std::string ranlib = "ranlib "; - ranlib += cmSystemTools::ConvertToOutputPath(destfile.c_str()); - if(!cmSystemTools::RunSingleCommand(ranlib.c_str())) - { - std::string err = "ranlib failed: "; - err += ranlib; - this->SetError(err.c_str()); - } - } -#endif - break; - - case cmTarget::MODULE_LIBRARY: - case cmTarget::SHARED_LIBRARY: - case cmTarget::EXECUTABLE: - case cmTarget::INSTALL_PROGRAMS: - - if ( !cmSystemTools::SetPermissions(destfile.c_str(), -#if defined( _MSC_VER ) || defined( __MINGW32__ ) - S_IREAD | S_IWRITE | S_IEXEC -#elif defined( __BORLANDC__ ) - S_IRUSR | S_IWUSR | S_IXUSR -#else - S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH -#endif - ) ) - { - cmOStringStream err; - err << "Problem setting permissions on file: " - << destfile.c_str(); - perror(err.str().c_str()); - } - } - smanifest_files += ";"; - smanifest_files += destfile.substr(destDirLength); - } - else - { - if ( !optional ) + // Static libraries need ranlib on this platform. + if(itype == cmTarget::STATIC_LIBRARY) { - std::string errstring = "cannot find file: " + - ctarget + " to install."; - this->SetError(errstring.c_str()); + std::string ranlib = "ranlib "; + ranlib += cmSystemTools::ConvertToOutputPath(toFile.c_str()); + if(!cmSystemTools::RunSingleCommand(ranlib.c_str())) + { + std::string err = "ranlib failed: "; + err += ranlib; + this->SetError(err.c_str()); + return false; + } + } +#endif + + // Set permissions of the destination file. + if(!cmSystemTools::SetPermissions(toFile.c_str(), permissions)) + { + cmOStringStream e; + e << "Problem setting permissions on file \"" + << toFile.c_str() << "\""; + this->SetError(e.str().c_str()); return false; } + + // Add the file to the manifest. + smanifest_files += ";"; + smanifest_files += toFile.substr(destDirLength); + } + else if(!optional) + { + // The input file does not exist and installation is not optional. + cmOStringStream e; + e << "INSTALL cannot find file \"" << fromFile << "\" to install."; + this->SetError(e.str().c_str()); + return false; } } } + + // Save the updated install manifest. m_Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES", - smanifest_files.c_str()); + smanifest_files.c_str()); return true; } diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 6f86ee697..15a0f2bf4 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -299,8 +299,12 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) bool programs = (args[0] == "PROGRAMS"); bool doing_files = true; bool doing_destination = false; + bool doing_permissions = false; + bool doing_rename = false; std::vector files; const char* destination = 0; + std::string rename; + std::string permissions; for(unsigned int i=1; i < args.size(); ++i) { if(args[i] == "DESTINATION") @@ -308,6 +312,24 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) // Switch to setting the destination property. doing_files = false; doing_destination = true; + doing_permissions = false; + doing_rename = false; + } + else if(args[i] == "PERMISSIONS") + { + // Switch to setting the permissions property. + doing_files = false; + doing_destination = false; + doing_permissions = true; + doing_rename = false; + } + else if(args[i] == "RENAME") + { + // Switch to setting the rename property. + doing_files = false; + doing_destination = false; + doing_permissions = false; + doing_rename = true; } else if(doing_files) { @@ -337,6 +359,23 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) destination = args[i].c_str(); doing_destination = false; } + else if(doing_permissions) + { + // Check the requested permission. + if(!this->CheckPermissions(args[i], permissions)) + { + cmOStringStream e; + e << args[0] << " given invalid permission \"" + << args[i] << "\"."; + this->SetError(e.str().c_str()); + return false; + } + } + else if(doing_rename) + { + rename = args[i]; + doing_rename = false; + } else { // Unknown argument. @@ -354,11 +393,20 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) } if(!destination) { + // A destination is required. cmOStringStream e; e << args[0] << " given no DESTINATION!"; this->SetError(e.str().c_str()); return false; } + if(!rename.empty() && files.size() > 1) + { + // The rename option works only with one file. + cmOStringStream e; + e << args[0] << " given RENAME option with more than one file."; + this->SetError(e.str().c_str()); + return false; + } // Compute destination path. std::string dest; @@ -366,7 +414,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector const& args) // Create the files install generator. m_Makefile->AddInstallGenerator( - new cmInstallFilesGenerator(files, dest.c_str(), programs)); + new cmInstallFilesGenerator(files, dest.c_str(), programs, + permissions.c_str(), rename.c_str())); return true; } @@ -398,3 +447,32 @@ void cmInstallCommand::ComputeDestination(const char* destination, dest = ""; } } + +//---------------------------------------------------------------------------- +bool cmInstallCommand::CheckPermissions(std::string const& arg, + std::string& permissions) +{ + // Table of valid permissions. + const char* table[] = + { + "OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE", + "GROUP_READ", "GROUP_WRITE", "GROUP_EXECUTE", + "WORLD_READ", "WORLD_WRITE", "WORLD_EXECUTE", + "SETUID", "SETGID", 0 + }; + + // Check the permission against the table. + for(const char** valid = table; *valid; ++valid) + { + if(arg == *valid) + { + // This is a valid permission. + permissions += " "; + permissions += arg; + return true; + } + } + + // This is not a valid permission. + return false; +} diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 296bc3f0c..c692c223b 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -68,16 +68,29 @@ public: "\n" "There are multiple signatures for this command. Some of them define " "installation properties for files and targets. Properties common to " - "multiple signatures are covered here. DESTINATION arguments specify " + "multiple signatures are covered here but they are valid only for " + "signatures that specify them. " + "DESTINATION arguments specify " "the directory on disk to which a file will be installed. " "If a full path (with a leading slash or drive letter) is given it " "is used directly. If a relative path is given it is interpreted " - "relative to the value of CMAKE_INSTALL_PREFIX." + "relative to the value of CMAKE_INSTALL_PREFIX. " + "PERMISSIONS arguments specify permissions for installed files. " + "Valid permissions are " + "OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, " + "GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, " + "WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, " + "SETUID, and SETGID. " + "Permissions that do not make sense on certain platforms are ignored " + "on those platforms. " + "The RENAME argument specifies a name for an installed file that " + "may be different from the original file. Renaming is allowed only " + "when a single file is installed by the command. " "\n" "The TARGETS signature:\n" - " INSTALL(TARGETS [targets...] [[LIBRARY|RUNTIME]\n" - " [DESTINATION ]\n" - " ] [...])\n" + " INSTALL(TARGETS targets... [[LIBRARY|RUNTIME]\n" + " [DESTINATION ]\n" + " ] [...])\n" "The TARGETS form specifies rules for installing targets from a " "project. There are two kinds of target files that may be " "installed: library and runtime. Static libraries and modules " @@ -110,14 +123,16 @@ public: "/some/full/path." "\n" "The FILES signature:\n" - " INSTALL(FILES [files...] DESTINATION )\n" + " INSTALL(FILES files... DESTINATION \n" + " [PERMISSIONS permissions...] [RENAME ])\n" "The FILES form specifies rules for installing files for a " "project. File names given as relative paths are interpreted with " "respect to the current source directory. Files installed by this " "form are given the same permissions as the original file by default." "\n" "The PROGRAMS signature:\n" - " INSTALL(PROGRAMS [files...] DESTINATION )\n" + " INSTALL(PROGRAMS files... DESTINATION \n" + " [PERMISSIONS permissions...] [RENAME ])\n" "The PROGRAMS form is identical to the FILES form except that the " "default permissions for the installed file mark it as executable. " "This form is intended to install programs that are not targets, " @@ -147,6 +162,7 @@ private: bool HandleTargetsMode(std::vector const& args); bool HandleFilesMode(std::vector const& args); void ComputeDestination(const char* destination, std::string& dest); + bool CheckPermissions(std::string const& arg, std::string& permissions); }; diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index 7a73327ce..ff32fe2bd 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -21,8 +21,10 @@ //---------------------------------------------------------------------------- cmInstallFilesGenerator ::cmInstallFilesGenerator(std::vector const& files, - const char* dest, bool programs): - Files(files), Destination(dest), Programs(programs) + const char* dest, bool programs, + const char* permissions, const char* rename): + Files(files), Destination(dest), Programs(programs), + Permissions(permissions), Rename(rename) { } @@ -39,9 +41,13 @@ void cmInstallFilesGenerator::GenerateScript(std::ostream& os) for(std::vector::const_iterator fi = this->Files.begin(); fi != this->Files.end(); ++fi) { + bool not_optional = false; + const char* no_properties = 0; this->AddInstallRule(os, this->Destination.c_str(), (this->Programs ? cmTarget::INSTALL_PROGRAMS - : cmTarget::INSTALL_FILES), fi->c_str()); + : cmTarget::INSTALL_FILES), fi->c_str(), + not_optional, no_properties, + this->Permissions.c_str(), this->Rename.c_str()); } } diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 9d35c73e0..dc2094fc3 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -26,7 +26,8 @@ class cmInstallFilesGenerator: public cmInstallGenerator { public: cmInstallFilesGenerator(std::vector const& files, - const char* dest, bool programs); + const char* dest, bool programs, + const char* permissions, const char* rename); virtual ~cmInstallFilesGenerator(); protected: @@ -34,6 +35,8 @@ protected: std::vector Files; std::string Destination; bool Programs; + std::string Permissions; + std::string Rename; }; #endif diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx index a7e1d6f93..0cb3a51a6 100644 --- a/Source/cmInstallGenerator.cxx +++ b/Source/cmInstallGenerator.cxx @@ -52,7 +52,9 @@ void cmInstallGenerator::AddInstallRule(std::ostream& os, int type, const char* file, bool optional /* = false */, - const char* properties /* = 0 */) + const char* properties /* = 0 */, + const char* permissions /* = 0 */, + const char* rename /* = 0 */) { // Use the FILE command to install the file. std::string stype; @@ -75,5 +77,13 @@ void cmInstallGenerator::AddInstallRule(std::ostream& os, { os << " PROPERTIES" << properties; } + if(permissions && *permissions) + { + os << " PERMISSIONS" << permissions; + } + if(rename && *rename) + { + os << " RENAME \"" << rename << "\""; + } os << " FILES \"" << file << "\")\n"; } diff --git a/Source/cmInstallGenerator.h b/Source/cmInstallGenerator.h index e04ba52c0..73aa4ff13 100644 --- a/Source/cmInstallGenerator.h +++ b/Source/cmInstallGenerator.h @@ -36,7 +36,9 @@ public: static void AddInstallRule(std::ostream& os, const char* dest, int type, const char* file, bool optional = false, - const char* properties = 0); + const char* properties = 0, + const char* permissions = 0, + const char* rename = 0); protected: virtual void GenerateScript(std::ostream& os)=0; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ab2d31d9b..ba62ebb9c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1654,16 +1654,22 @@ cmLocalGenerator case cmTarget::INSTALL_FILES: { // Use a file install generator. + const char* no_permissions = ""; + const char* no_rename = ""; cmInstallFilesGenerator g(l->second.GetSourceLists(), - destination.c_str(), false); + destination.c_str(), false, + no_permissions, no_rename); g.Generate(os, config, configurationTypes); } break; case cmTarget::INSTALL_PROGRAMS: { // Use a file install generator. + const char* no_permissions = ""; + const char* no_rename = ""; cmInstallFilesGenerator g(l->second.GetSourceLists(), - destination.c_str(), true); + destination.c_str(), true, + no_permissions, no_rename); g.Generate(os, config, configurationTypes); } break; diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index 14beef303..fc5c861e3 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -58,7 +58,8 @@ IF(STAGE2) PATHS ${LIBPATHS} DOC "Fourth library") - ADD_EXECUTABLE (SimpleInstallS2 inst.cxx foo.c foo.h) + INCLUDE_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/include) + ADD_EXECUTABLE (SimpleInstallS2 inst2.cxx foo.c foo.h) TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY}) SET(install_target SimpleInstallS2) @@ -93,7 +94,12 @@ ELSE(STAGE2) INSTALL(TARGETS SimpleInstall test1 test2 test3 test4 RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - INSTALL(FILES lib1.h lib2.h DESTINATION include) + INSTALL(FILES lib1.h DESTINATION include/foo) + INSTALL(FILES lib2.h + DESTINATION include/foo + PERMISSIONS OWNER_READ OWNER_WRITE + RENAME lib2renamed.h + ) INSTALL_FILES(/include FILES lib3.h) # Test user-specified install scripts. diff --git a/Tests/SimpleInstall/inst.cxx b/Tests/SimpleInstall/inst.cxx index 241a296b4..53082dcee 100644 --- a/Tests/SimpleInstall/inst.cxx +++ b/Tests/SimpleInstall/inst.cxx @@ -1,7 +1,13 @@ #include "foo.h" -#include "lib1.h" -#include "lib2.h" +#ifdef STAGE_2 +# include +# include +#else +# include "lib1.h" +# include "lib2.h" +#endif + #include "lib4.h" #include diff --git a/Tests/SimpleInstall/inst2.cxx b/Tests/SimpleInstall/inst2.cxx new file mode 100644 index 000000000..c70b93af1 --- /dev/null +++ b/Tests/SimpleInstall/inst2.cxx @@ -0,0 +1,2 @@ +#define STAGE_2 +#include "inst.cxx" diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index 14beef303..fc5c861e3 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -58,7 +58,8 @@ IF(STAGE2) PATHS ${LIBPATHS} DOC "Fourth library") - ADD_EXECUTABLE (SimpleInstallS2 inst.cxx foo.c foo.h) + INCLUDE_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/include) + ADD_EXECUTABLE (SimpleInstallS2 inst2.cxx foo.c foo.h) TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY}) SET(install_target SimpleInstallS2) @@ -93,7 +94,12 @@ ELSE(STAGE2) INSTALL(TARGETS SimpleInstall test1 test2 test3 test4 RUNTIME DESTINATION bin LIBRARY DESTINATION lib) - INSTALL(FILES lib1.h lib2.h DESTINATION include) + INSTALL(FILES lib1.h DESTINATION include/foo) + INSTALL(FILES lib2.h + DESTINATION include/foo + PERMISSIONS OWNER_READ OWNER_WRITE + RENAME lib2renamed.h + ) INSTALL_FILES(/include FILES lib3.h) # Test user-specified install scripts. diff --git a/Tests/SimpleInstallS2/inst.cxx b/Tests/SimpleInstallS2/inst.cxx index 241a296b4..53082dcee 100644 --- a/Tests/SimpleInstallS2/inst.cxx +++ b/Tests/SimpleInstallS2/inst.cxx @@ -1,7 +1,13 @@ #include "foo.h" -#include "lib1.h" -#include "lib2.h" +#ifdef STAGE_2 +# include +# include +#else +# include "lib1.h" +# include "lib2.h" +#endif + #include "lib4.h" #include diff --git a/Tests/SimpleInstallS2/inst2.cxx b/Tests/SimpleInstallS2/inst2.cxx new file mode 100644 index 000000000..c70b93af1 --- /dev/null +++ b/Tests/SimpleInstallS2/inst2.cxx @@ -0,0 +1,2 @@ +#define STAGE_2 +#include "inst.cxx"