Ver Fonte

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.

Brad King há 20 anos atrás
pai
commit
a2e136fd17

+ 273 - 121
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<cmStdString, const char*> 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() )
-      {
-      destfile += ext;
-      }
-    switch( itype )
+    // 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)
       {
-    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() )
-        {
-        exe_version = properties["VERSION"];
         }
-      if ( exe_version )
+        break;
+      case cmTarget::EXECUTABLE:
         {
-        std::string exename = destfile;
-        std::string exename_nopath = fname;
-        exename_nopath += "-";
-        exename_nopath += exe_version;
+        // Handle executable versioning
+        const char* exe_version = 0;
+        if ( properties.find("VERSION") != properties.end() )
+          {
+          exe_version = properties["VERSION"];
+          }
+        if ( exe_version )
+          {
+          std::string exename = toFile;
+          std::string exename_nopath = fromName;
+          exename_nopath += "-";
+          exename_nopath += exe_version;
 
-        fname += "-";
-        fname += exe_version;
-        destfile += "-";
-        destfile += exe_version;
+          fromName += "-";
+          fromName += exe_version;
+          toFile += "-";
+          toFile += exe_version;
 
-        cmSystemTools::RemoveFile(exename.c_str());
+          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;
+          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);
           }
-        smanifest_files += ";";
-        smanifest_files += exename.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;
+        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());
-          return false;
+          // Set default permissions.
+          permissions = 0;
+          permissions |= mode_owner_read;
+          permissions |= mode_owner_write;
+          permissions |= mode_group_read;
+          permissions |= mode_world_read;
           }
-        switch( itype )
+
+        // 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()))
           {
-          case cmTarget::STATIC_LIBRARY:
+          cmOStringStream e;
+          e << "INSTALL cannot copy file \"" << fromFile
+            << "\" to \"" << toFile + "\".";
+          this->SetError(e.str().c_str());
+          return false;
+          }
+
+        // Perform post-installation processing on the file depending
+        // on its type.
 #if defined(__APPLE_CC__)
+        // Static libraries need ranlib on this platform.
+        if(itype == cmTarget::STATIC_LIBRARY)
+          {
+          std::string ranlib = "ranlib ";
+          ranlib += cmSystemTools::ConvertToOutputPath(toFile.c_str());
+          if(!cmSystemTools::RunSingleCommand(ranlib.c_str()))
             {
-            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());
-              }
+            std::string err = "ranlib failed: ";
+            err += ranlib;
+            this->SetError(err.c_str());
+            return false;
             }
+          }
 #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());
-              }
+
+        // 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 += destfile.substr(destDirLength);
+        smanifest_files += toFile.substr(destDirLength);
         }
-      else
+      else if(!optional)
         {
-        if ( !optional )
-          {
-          std::string errstring = "cannot find file: " + 
-            ctarget + " to install.";
-          this->SetError(errstring.c_str());
-          return false;
-          }
+        // 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;
 }

+ 79 - 1
Source/cmInstallCommand.cxx

@@ -299,8 +299,12 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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;
+}

+ 23 - 7
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 <dir>]\n"
-      "                               ] [...])\n"
+      "  INSTALL(TARGETS targets... [[LIBRARY|RUNTIME]\n"
+      "                              [DESTINATION <dir>]\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 <dir>)\n"
+      "  INSTALL(FILES files... DESTINATION <dir>\n"
+      "          [PERMISSIONS permissions...] [RENAME <name>])\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 <dir>)\n"
+      "  INSTALL(PROGRAMS files... DESTINATION <dir>\n"
+      "          [PERMISSIONS permissions...] [RENAME <name>])\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<std::string> const& args);
   bool HandleFilesMode(std::vector<std::string> const& args);
   void ComputeDestination(const char* destination, std::string& dest);
+  bool CheckPermissions(std::string const& arg, std::string& permissions);
 };
 
 

+ 9 - 3
Source/cmInstallFilesGenerator.cxx

@@ -21,8 +21,10 @@
 //----------------------------------------------------------------------------
 cmInstallFilesGenerator
 ::cmInstallFilesGenerator(std::vector<std::string> 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<std::string>::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());
     }
 }

+ 4 - 1
Source/cmInstallFilesGenerator.h

@@ -26,7 +26,8 @@ class cmInstallFilesGenerator: public cmInstallGenerator
 {
 public:
   cmInstallFilesGenerator(std::vector<std::string> 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<std::string> Files;
   std::string Destination;
   bool Programs;
+  std::string Permissions;
+  std::string Rename;
 };
 
 #endif

+ 11 - 1
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";
 }

+ 3 - 1
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;

+ 8 - 2
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;

+ 8 - 2
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.

+ 8 - 2
Tests/SimpleInstall/inst.cxx

@@ -1,7 +1,13 @@
 #include "foo.h"
 
-#include "lib1.h"
-#include "lib2.h"
+#ifdef STAGE_2
+# include <foo/lib1.h>
+# include <foo/lib2renamed.h>
+#else
+# include "lib1.h"
+# include "lib2.h"
+#endif
+
 #include "lib4.h"
 
 #include <stdio.h>

+ 2 - 0
Tests/SimpleInstall/inst2.cxx

@@ -0,0 +1,2 @@
+#define STAGE_2
+#include "inst.cxx"

+ 8 - 2
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.

+ 8 - 2
Tests/SimpleInstallS2/inst.cxx

@@ -1,7 +1,13 @@
 #include "foo.h"
 
-#include "lib1.h"
-#include "lib2.h"
+#ifdef STAGE_2
+# include <foo/lib1.h>
+# include <foo/lib2renamed.h>
+#else
+# include "lib1.h"
+# include "lib2.h"
+#endif
+
 #include "lib4.h"
 
 #include <stdio.h>

+ 2 - 0
Tests/SimpleInstallS2/inst2.cxx

@@ -0,0 +1,2 @@
+#define STAGE_2
+#include "inst.cxx"