Kaynağa Gözat

install: Add sane set of defaults for DESTINATION and file type parameters

If the user does not specify a DESTINATION for a target type, the
install() command checks to see if the appropriate variable from
GNUInstallDirs is set. If it is not, then it uses an appropriate
hard-coded guess.

In addition, for FILES and DIRECTORY, the user can specify a file
type instead of a DESTINATION, and the command will use the
appropriate variable from GNUInstallDirs, or a hard-coded guess if
it is not set.
Kyle Edwards 7 yıl önce
ebeveyn
işleme
9fc20a4f3e
36 değiştirilmiş dosya ile 832 ekleme ve 79 silme
  1. 297 79
      Source/cmInstallCommand.cxx
  2. 22 0
      Source/cmInstallCommand.h
  3. 6 0
      Source/cmInstallCommandArguments.cxx
  4. 2 0
      Source/cmInstallCommandArguments.h
  5. 1 0
      Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE-result.txt
  6. 5 0
      Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE-stderr.txt
  7. 1 0
      Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE.cmake
  8. 42 0
      Tests/RunCMake/install/DIRECTORY-TYPE-Cache-all-check.cmake
  9. 13 0
      Tests/RunCMake/install/DIRECTORY-TYPE-Cache.cmake
  10. 24 0
      Tests/RunCMake/install/DIRECTORY-TYPE-CacheDependent-all-check.cmake
  11. 7 0
      Tests/RunCMake/install/DIRECTORY-TYPE-CacheDependent.cmake
  12. 42 0
      Tests/RunCMake/install/DIRECTORY-TYPE-all-check.cmake
  13. 13 0
      Tests/RunCMake/install/DIRECTORY-TYPE.cmake
  14. 1 0
      Tests/RunCMake/install/FILES-DESTINATION-TYPE-result.txt
  15. 5 0
      Tests/RunCMake/install/FILES-DESTINATION-TYPE-stderr.txt
  16. 1 0
      Tests/RunCMake/install/FILES-DESTINATION-TYPE.cmake
  17. 29 0
      Tests/RunCMake/install/FILES-TYPE-Cache-all-check.cmake
  18. 13 0
      Tests/RunCMake/install/FILES-TYPE-Cache.cmake
  19. 17 0
      Tests/RunCMake/install/FILES-TYPE-CacheDependent-all-check.cmake
  20. 7 0
      Tests/RunCMake/install/FILES-TYPE-CacheDependent.cmake
  21. 29 0
      Tests/RunCMake/install/FILES-TYPE-all-check.cmake
  22. 13 0
      Tests/RunCMake/install/FILES-TYPE.cmake
  23. 46 0
      Tests/RunCMake/install/RunCMakeTest.cmake
  24. 1 0
      Tests/RunCMake/install/TARGETS-Apple-Defaults-result.txt
  25. 12 0
      Tests/RunCMake/install/TARGETS-Apple-Defaults-stderr.txt
  26. 8 0
      Tests/RunCMake/install/TARGETS-Apple-Defaults.cmake
  27. 49 0
      Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake
  28. 19 0
      Tests/RunCMake/install/TARGETS-Defaults-Cache.cmake
  29. 49 0
      Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake
  30. 19 0
      Tests/RunCMake/install/TARGETS-Defaults.cmake
  31. 7 0
      Tests/RunCMake/install/obj3.c
  32. 6 0
      Tests/RunCMake/install/obj3.h
  33. 7 0
      Tests/RunCMake/install/obj4.c
  34. 6 0
      Tests/RunCMake/install/obj4.h
  35. 7 0
      Tests/RunCMake/install/obj5.c
  36. 6 0
      Tests/RunCMake/install/obj5.h

+ 297 - 79
Source/cmInstallCommand.cxx

@@ -3,6 +3,7 @@
 #include "cmInstallCommand.h"
 
 #include "cmsys/Glob.hxx"
+#include <set>
 #include <sstream>
 #include <stddef.h>
 #include <utility>
@@ -33,8 +34,8 @@ class cmExecutionStatus;
 
 static cmInstallTargetGenerator* CreateInstallTargetGenerator(
   cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
-  cmListFileBacktrace const& backtrace, bool forceOpt = false,
-  bool namelink = false)
+  cmListFileBacktrace const& backtrace, const std::string& destination,
+  bool forceOpt = false, bool namelink = false)
 {
   cmInstallGenerator::MessageLevel message =
     cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
@@ -42,25 +43,49 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(
   const char* component = namelink ? args.GetNamelinkComponent().c_str()
                                    : args.GetComponent().c_str();
   return new cmInstallTargetGenerator(
-    target.GetName(), args.GetDestination().c_str(), impLib,
+    target.GetName(), destination.c_str(), impLib,
     args.GetPermissions().c_str(), args.GetConfigurations(), component,
     message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt,
     backtrace);
 }
 
+static cmInstallTargetGenerator* CreateInstallTargetGenerator(
+  cmTarget& target, const cmInstallCommandArguments& args, bool impLib,
+  cmListFileBacktrace const& backtrace, bool forceOpt = false,
+  bool namelink = false)
+{
+  return CreateInstallTargetGenerator(target, args, impLib, backtrace,
+                                      args.GetDestination(), forceOpt,
+                                      namelink);
+}
+
 static cmInstallFilesGenerator* CreateInstallFilesGenerator(
   cmMakefile* mf, const std::vector<std::string>& absFiles,
-  const cmInstallCommandArguments& args, bool programs)
+  const cmInstallCommandArguments& args, bool programs,
+  const std::string& destination)
 {
   cmInstallGenerator::MessageLevel message =
     cmInstallGenerator::SelectMessageLevel(mf);
   return new cmInstallFilesGenerator(
-    absFiles, args.GetDestination().c_str(), programs,
-    args.GetPermissions().c_str(), args.GetConfigurations(),
-    args.GetComponent().c_str(), message, args.GetExcludeFromAll(),
-    args.GetRename().c_str(), args.GetOptional());
+    absFiles, destination.c_str(), programs, args.GetPermissions().c_str(),
+    args.GetConfigurations(), args.GetComponent().c_str(), message,
+    args.GetExcludeFromAll(), args.GetRename().c_str(), args.GetOptional());
 }
 
+static cmInstallFilesGenerator* CreateInstallFilesGenerator(
+  cmMakefile* mf, const std::vector<std::string>& absFiles,
+  const cmInstallCommandArguments& args, bool programs)
+{
+  return CreateInstallFilesGenerator(mf, absFiles, args, programs,
+                                     args.GetDestination());
+}
+
+static const std::set<std::string> allowedTypes{
+  "BIN",         "SBIN",       "LIB",      "INCLUDE", "SYSCONF",
+  "SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA",    "INFO",
+  "LOCALE",      "MAN",        "DOC",
+};
+
 // cmInstallCommand
 bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
                                    cmExecutionStatus&)
@@ -335,6 +360,17 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
                    "At most one of these two options may be specified.");
     return false;
   }
+  if (!genericArgs.GetType().empty() || !archiveArgs.GetType().empty() ||
+      !libraryArgs.GetType().empty() || !runtimeArgs.GetType().empty() ||
+      !objectArgs.GetType().empty() || !frameworkArgs.GetType().empty() ||
+      !bundleArgs.GetType().empty() || !privateHeaderArgs.GetType().empty() ||
+      !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty()) {
+    std::ostringstream e;
+    e << "TARGETS given TYPE option. The TYPE option may only be specified in "
+         " install(FILES) and install(DIRECTORIES).";
+    this->SetError(e.str());
+    return false;
+  }
 
   // Select the mode for installing symlinks to versioned shared libraries.
   cmInstallTargetGenerator::NamelinkModeType namelinkMode =
@@ -447,8 +483,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
               target, runtimeArgs, false, this->Makefile->GetBacktrace());
           }
           if ((archiveGenerator == nullptr) && (runtimeGenerator == nullptr)) {
-            this->SetError("Library TARGETS given no DESTINATION!");
-            return false;
+            archiveGenerator = CreateInstallTargetGenerator(
+              target, archiveArgs, true, this->Makefile->GetBacktrace(),
+              this->GetArchiveDestination(nullptr));
+            runtimeGenerator = CreateInstallTargetGenerator(
+              target, runtimeArgs, false, this->Makefile->GetBacktrace(),
+              this->GetRuntimeDestination(nullptr));
           }
         } else {
           // This is a non-DLL platform.
@@ -474,30 +514,22 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
             }
           } else {
             // The shared library uses the LIBRARY properties.
-            if (!libraryArgs.GetDestination().empty()) {
-              if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
-                libraryGenerator = CreateInstallTargetGenerator(
-                  target, libraryArgs, false, this->Makefile->GetBacktrace());
-                libraryGenerator->SetNamelinkMode(
-                  cmInstallTargetGenerator::NamelinkModeSkip);
-              }
-              if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
-                namelinkGenerator = CreateInstallTargetGenerator(
-                  target, libraryArgs, false, this->Makefile->GetBacktrace(),
-                  false, true);
-                namelinkGenerator->SetNamelinkMode(
-                  cmInstallTargetGenerator::NamelinkModeOnly);
-              }
-              namelinkOnly =
-                (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
-            } else {
-              std::ostringstream e;
-              e << "TARGETS given no LIBRARY DESTINATION for shared library "
-                   "target \""
-                << target.GetName() << "\".";
-              this->SetError(e.str());
-              return false;
+            if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
+              libraryGenerator = CreateInstallTargetGenerator(
+                target, libraryArgs, false, this->Makefile->GetBacktrace(),
+                this->GetLibraryDestination(&libraryArgs));
+              libraryGenerator->SetNamelinkMode(
+                cmInstallTargetGenerator::NamelinkModeSkip);
+            }
+            if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
+              namelinkGenerator = CreateInstallTargetGenerator(
+                target, libraryArgs, false, this->Makefile->GetBacktrace(),
+                this->GetLibraryDestination(&libraryArgs), false, true);
+              namelinkGenerator->SetNamelinkMode(
+                cmInstallTargetGenerator::NamelinkModeOnly);
             }
+            namelinkOnly =
+              (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
           }
         }
       } break;
@@ -524,17 +556,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           }
         } else {
           // Static libraries use ARCHIVE properties.
-          if (!archiveArgs.GetDestination().empty()) {
-            archiveGenerator = CreateInstallTargetGenerator(
-              target, archiveArgs, false, this->Makefile->GetBacktrace());
-          } else {
-            std::ostringstream e;
-            e << "TARGETS given no ARCHIVE DESTINATION for static library "
-                 "target \""
-              << target.GetName() << "\".";
-            this->SetError(e.str());
-            return false;
-          }
+          archiveGenerator = CreateInstallTargetGenerator(
+            target, archiveArgs, false, this->Makefile->GetBacktrace(),
+            this->GetArchiveDestination(&archiveArgs));
         }
       } break;
       case cmStateEnums::MODULE_LIBRARY: {
@@ -602,17 +626,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           }
         } else {
           // Executables use the RUNTIME properties.
-          if (!runtimeArgs.GetDestination().empty()) {
-            runtimeGenerator = CreateInstallTargetGenerator(
-              target, runtimeArgs, false, this->Makefile->GetBacktrace());
-          } else {
-            std::ostringstream e;
-            e << "TARGETS given no RUNTIME DESTINATION for executable "
-                 "target \""
-              << target.GetName() << "\".";
-            this->SetError(e.str());
-            return false;
-          }
+          runtimeGenerator = CreateInstallTargetGenerator(
+            target, runtimeArgs, false, this->Makefile->GetBacktrace(),
+            this->GetRuntimeDestination(&runtimeArgs));
         }
 
         // On DLL platforms an executable may also have an import
@@ -659,15 +675,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         }
 
         // Create the files install generator.
-        if (!privateHeaderArgs.GetDestination().empty()) {
-          privateHeaderGenerator = CreateInstallFilesGenerator(
-            this->Makefile, absFiles, privateHeaderArgs, false);
-        } else {
-          std::ostringstream e;
-          e << "INSTALL TARGETS - target " << target.GetName() << " has "
-            << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
-          cmSystemTools::Message(e.str().c_str(), "Warning");
-        }
+        privateHeaderGenerator = CreateInstallFilesGenerator(
+          this->Makefile, absFiles, privateHeaderArgs, false,
+          this->GetIncludeDestination(&privateHeaderArgs));
       }
 
       files = target.GetProperty("PUBLIC_HEADER");
@@ -680,15 +690,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
         }
 
         // Create the files install generator.
-        if (!publicHeaderArgs.GetDestination().empty()) {
-          publicHeaderGenerator = CreateInstallFilesGenerator(
-            this->Makefile, absFiles, publicHeaderArgs, false);
-        } else {
-          std::ostringstream e;
-          e << "INSTALL TARGETS - target " << target.GetName() << " has "
-            << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
-          cmSystemTools::Message(e.str().c_str(), "Warning");
-        }
+        publicHeaderGenerator = CreateInstallFilesGenerator(
+          this->Makefile, absFiles, publicHeaderArgs, false,
+          this->GetIncludeDestination(&publicHeaderArgs));
       }
 
       files = target.GetProperty("RESOURCE");
@@ -824,6 +828,14 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
     return false;
   }
 
+  std::string type = ica.GetType();
+  if (!type.empty() && allowedTypes.count(type) == 0) {
+    std::ostringstream e;
+    e << args[0] << " given non-type \"" << type << "\" with TYPE argument.";
+    this->SetError(e.str());
+    return false;
+  }
+
   const std::vector<std::string>& filesVector = files.GetVector();
 
   // Check if there is something to do.
@@ -886,7 +898,17 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
     return false;
   }
 
-  if (ica.GetDestination().empty()) {
+  if (!type.empty() && !ica.GetDestination().empty()) {
+    std::ostringstream e;
+    e << args[0]
+      << " given both TYPE and DESTINATION arguments. You may only specify "
+         "one.";
+    this->SetError(e.str());
+    return false;
+  }
+
+  std::string destination = this->GetDestinationForType(&ica, type);
+  if (destination.empty()) {
     // A destination is required.
     std::ostringstream e;
     e << args[0] << " given no DESTINATION!";
@@ -895,8 +917,8 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
   }
 
   // Create the files install generator.
-  this->Makefile->AddInstallGenerator(
-    CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs));
+  this->Makefile->AddInstallGenerator(CreateInstallFilesGenerator(
+    this->Makefile, absFiles, ica, programs, destination));
 
   // Tell the global generator about any installation component names
   // specified.
@@ -920,7 +942,8 @@ bool cmInstallCommand::HandleDirectoryMode(
     DoingPermsDir,
     DoingPermsMatch,
     DoingConfigurations,
-    DoingComponent
+    DoingComponent,
+    DoingType
   };
   Doing doing = DoingDirs;
   bool in_match_mode = false;
@@ -934,6 +957,7 @@ bool cmInstallCommand::HandleDirectoryMode(
   std::vector<std::string> configurations;
   std::string component = this->DefaultComponentName;
   std::string literal_args;
+  std::string type;
   for (unsigned int i = 1; i < args.size(); ++i) {
     if (args[i] == "DESTINATION") {
       if (in_match_mode) {
@@ -946,6 +970,17 @@ bool cmInstallCommand::HandleDirectoryMode(
 
       // Switch to setting the destination property.
       doing = DoingDestination;
+    } else if (args[i] == "TYPE") {
+      if (in_match_mode) {
+        std::ostringstream e;
+        e << args[0] << " does not allow \"" << args[i]
+          << "\" after PATTERN or REGEX.";
+        this->SetError(e.str());
+        return false;
+      }
+
+      // Switch to setting the type.
+      doing = DoingType;
     } else if (args[i] == "OPTIONAL") {
       if (in_match_mode) {
         std::ostringstream e;
@@ -1106,6 +1141,17 @@ bool cmInstallCommand::HandleDirectoryMode(
     } else if (doing == DoingDestination) {
       destination = args[i].c_str();
       doing = DoingNone;
+    } else if (doing == DoingType) {
+      if (allowedTypes.count(args[i]) == 0) {
+        std::ostringstream e;
+        e << args[0] << " given non-type \"" << args[i]
+          << "\" with TYPE argument.";
+        this->SetError(e.str());
+        return false;
+      }
+
+      type = args[i];
+      doing = DoingNone;
     } else if (doing == DoingPattern) {
       // Convert the pattern to a regular expression.  Require a
       // leading slash and trailing end-of-string in the matched
@@ -1179,10 +1225,22 @@ bool cmInstallCommand::HandleDirectoryMode(
   if (dirs.empty()) {
     return true;
   }
+  std::string destinationStr;
   if (!destination) {
-    // A destination is required.
+    if (type.empty()) {
+      // A destination is required.
+      std::ostringstream e;
+      e << args[0] << " given no DESTINATION!";
+      this->SetError(e.str());
+      return false;
+    }
+    destinationStr = this->GetDestinationForType(nullptr, type);
+    destination = destinationStr.c_str();
+  } else if (!type.empty()) {
     std::ostringstream e;
-    e << args[0] << " given no DESTINATION!";
+    e << args[0]
+      << " given both TYPE and DESTINATION arguments. You may only specify "
+         "one.";
     this->SetError(e.str());
     return false;
   }
@@ -1456,3 +1514,163 @@ bool cmInstallCommand::CheckCMP0006(bool& failure)
   }
   return false;
 }
+
+std::string cmInstallCommand::GetDestination(
+  const cmInstallCommandArguments* args, const std::string& varName,
+  const std::string& guess)
+{
+  if (args && !args->GetDestination().empty()) {
+    return args->GetDestination();
+  }
+  std::string val = this->Makefile->GetSafeDefinition(varName);
+  if (!val.empty()) {
+    return val;
+  }
+  return guess;
+}
+
+std::string cmInstallCommand::GetRuntimeDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_BINDIR", "bin");
+}
+
+std::string cmInstallCommand::GetSbinDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_SBINDIR", "sbin");
+}
+
+std::string cmInstallCommand::GetArchiveDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string cmInstallCommand::GetLibraryDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
+}
+
+std::string cmInstallCommand::GetIncludeDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_INCLUDEDIR", "include");
+}
+
+std::string cmInstallCommand::GetSysconfDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_SYSCONFDIR", "etc");
+}
+
+std::string cmInstallCommand::GetSharedStateDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_SHAREDSTATEDIR", "com");
+}
+
+std::string cmInstallCommand::GetLocalStateDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_LOCALSTATEDIR", "var");
+}
+
+std::string cmInstallCommand::GetRunStateDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_RUNSTATEDIR",
+                              this->GetLocalStateDestination(nullptr) +
+                                "/run");
+}
+
+std::string cmInstallCommand::GetDataRootDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_DATAROOTDIR", "share");
+}
+
+std::string cmInstallCommand::GetDataDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_DATADIR",
+                              this->GetDataRootDestination(nullptr));
+}
+
+std::string cmInstallCommand::GetInfoDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_INFODIR",
+                              this->GetDataRootDestination(nullptr) + "/info");
+}
+
+std::string cmInstallCommand::GetLocaleDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_LOCALEDIR",
+                              this->GetDataRootDestination(nullptr) +
+                                "/locale");
+}
+
+std::string cmInstallCommand::GetManDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_MANDIR",
+                              this->GetDataRootDestination(nullptr) + "/man");
+}
+
+std::string cmInstallCommand::GetDocDestination(
+  const cmInstallCommandArguments* args)
+{
+  return this->GetDestination(args, "CMAKE_INSTALL_DOCDIR",
+                              this->GetDataRootDestination(nullptr) + "/doc");
+}
+
+std::string cmInstallCommand::GetDestinationForType(
+  const cmInstallCommandArguments* args, const std::string& type)
+{
+  if (args && !args->GetDestination().empty()) {
+    return args->GetDestination();
+  }
+  if (type == "BIN") {
+    return this->GetRuntimeDestination(nullptr);
+  }
+  if (type == "SBIN") {
+    return this->GetSbinDestination(nullptr);
+  }
+  if (type == "SYSCONF") {
+    return this->GetSysconfDestination(nullptr);
+  }
+  if (type == "SHAREDSTATE") {
+    return this->GetSharedStateDestination(nullptr);
+  }
+  if (type == "LOCALSTATE") {
+    return this->GetLocalStateDestination(nullptr);
+  }
+  if (type == "RUNSTATE") {
+    return this->GetRunStateDestination(nullptr);
+  }
+  if (type == "LIB") {
+    return this->GetLibraryDestination(nullptr);
+  }
+  if (type == "INCLUDE") {
+    return this->GetIncludeDestination(nullptr);
+  }
+  if (type == "DATA") {
+    return this->GetDataDestination(nullptr);
+  }
+  if (type == "INFO") {
+    return this->GetInfoDestination(nullptr);
+  }
+  if (type == "LOCALE") {
+    return this->GetLocaleDestination(nullptr);
+  }
+  if (type == "MAN") {
+    return this->GetManDestination(nullptr);
+  }
+  if (type == "DOC") {
+    return this->GetDocDestination(nullptr);
+  }
+  return "";
+}

+ 22 - 0
Source/cmInstallCommand.h

@@ -11,6 +11,7 @@
 #include "cmCommand.h"
 
 class cmExecutionStatus;
+class cmInstallCommandArguments;
 
 /** \class cmInstallCommand
  * \brief Specifies where to install some files
@@ -45,6 +46,27 @@ private:
                          std::vector<std::string>& absFiles);
   bool CheckCMP0006(bool& failure);
 
+  std::string GetDestination(const cmInstallCommandArguments* args,
+                             const std::string& varName,
+                             const std::string& guess);
+  std::string GetRuntimeDestination(const cmInstallCommandArguments* args);
+  std::string GetSbinDestination(const cmInstallCommandArguments* args);
+  std::string GetArchiveDestination(const cmInstallCommandArguments* args);
+  std::string GetLibraryDestination(const cmInstallCommandArguments* args);
+  std::string GetIncludeDestination(const cmInstallCommandArguments* args);
+  std::string GetSysconfDestination(const cmInstallCommandArguments* args);
+  std::string GetSharedStateDestination(const cmInstallCommandArguments* args);
+  std::string GetLocalStateDestination(const cmInstallCommandArguments* args);
+  std::string GetRunStateDestination(const cmInstallCommandArguments* args);
+  std::string GetDataRootDestination(const cmInstallCommandArguments* args);
+  std::string GetDataDestination(const cmInstallCommandArguments* args);
+  std::string GetInfoDestination(const cmInstallCommandArguments* args);
+  std::string GetLocaleDestination(const cmInstallCommandArguments* args);
+  std::string GetManDestination(const cmInstallCommandArguments* args);
+  std::string GetDocDestination(const cmInstallCommandArguments* args);
+  std::string GetDestinationForType(const cmInstallCommandArguments* args,
+                                    const std::string& type);
+
   std::string DefaultComponentName;
 };
 

+ 6 - 0
Source/cmInstallCommandArguments.cxx

@@ -29,6 +29,7 @@ cmInstallCommandArguments::cmInstallCommandArguments(
   , Optional(&Parser, "OPTIONAL", &ArgumentGroup)
   , NamelinkOnly(&Parser, "NAMELINK_ONLY", &ArgumentGroup)
   , NamelinkSkip(&Parser, "NAMELINK_SKIP", &ArgumentGroup)
+  , Type(&Parser, "TYPE", &ArgumentGroup)
   , GenericArguments(nullptr)
   , DefaultComponentName(defaultComponent)
 {
@@ -145,6 +146,11 @@ bool cmInstallCommandArguments::HasNamelinkComponent() const
   return false;
 }
 
+const std::string& cmInstallCommandArguments::GetType() const
+{
+  return this->Type.GetString();
+}
+
 const std::vector<std::string>& cmInstallCommandArguments::GetConfigurations()
   const
 {

+ 2 - 0
Source/cmInstallCommandArguments.h

@@ -35,6 +35,7 @@ public:
   bool GetNamelinkOnly() const;
   bool GetNamelinkSkip() const;
   bool HasNamelinkComponent() const;
+  const std::string& GetType() const;
 
   // once HandleDirectoryMode() is also switched to using
   // cmInstallCommandArguments then these two functions can become non-static
@@ -55,6 +56,7 @@ private:
   cmCAEnabler Optional;
   cmCAEnabler NamelinkOnly;
   cmCAEnabler NamelinkSkip;
+  cmCAString Type;
 
   std::string DestinationString;
   std::string PermissionsString;

+ 1 - 0
Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at DIRECTORY-DESTINATION-TYPE\.cmake:[0-9]+ \(install\):
+  install DIRECTORY given both TYPE and DESTINATION arguments\.  You may only
+  specify one\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 1 - 0
Tests/RunCMake/install/DIRECTORY-DESTINATION-TYPE.cmake

@@ -0,0 +1 @@
+install(DIRECTORY dir TYPE BIN DESTINATION mybin)

+ 42 - 0
Tests/RunCMake/install/DIRECTORY-TYPE-Cache-all-check.cmake

@@ -0,0 +1,42 @@
+set(_check_files
+  [[mybin]]
+  [[mybin/dir]]
+  [[mybin/dir/empty\.txt]]
+  [[mycom]]
+  [[mycom/dir]]
+  [[mycom/dir/empty\.txt]]
+  [[mydoc]]
+  [[mydoc/dir]]
+  [[mydoc/dir/empty\.txt]]
+  [[myetc]]
+  [[myetc/dir]]
+  [[myetc/dir/empty\.txt]]
+  [[myinclude]]
+  [[myinclude/dir]]
+  [[myinclude/dir/empty\.txt]]
+  [[myinfo]]
+  [[myinfo/dir]]
+  [[myinfo/dir/empty\.txt]]
+  [[mylib]]
+  [[mylib/dir]]
+  [[mylib/dir/empty\.txt]]
+  [[mylocale]]
+  [[mylocale/dir]]
+  [[mylocale/dir/empty\.txt]]
+  [[myman]]
+  [[myman/dir]]
+  [[myman/dir/empty\.txt]]
+  [[myrun]]
+  [[myrun/dir]]
+  [[myrun/dir/empty\.txt]]
+  [[mysbin]]
+  [[mysbin/dir]]
+  [[mysbin/dir/empty\.txt]]
+  [[myshare]]
+  [[myshare/dir]]
+  [[myshare/dir/empty\.txt]]
+  [[myvar]]
+  [[myvar/dir]]
+  [[myvar/dir/empty\.txt]]
+  )
+check_installed("^${_check_files}$")

+ 13 - 0
Tests/RunCMake/install/DIRECTORY-TYPE-Cache.cmake

@@ -0,0 +1,13 @@
+install(DIRECTORY dir TYPE BIN)
+install(DIRECTORY dir TYPE SBIN)
+install(DIRECTORY dir TYPE LIB)
+install(DIRECTORY dir TYPE INCLUDE)
+install(DIRECTORY dir TYPE SYSCONF)
+install(DIRECTORY dir TYPE SHAREDSTATE)
+install(DIRECTORY dir TYPE LOCALSTATE)
+install(DIRECTORY dir TYPE RUNSTATE)
+install(DIRECTORY dir TYPE DATA)
+install(DIRECTORY dir TYPE INFO)
+install(DIRECTORY dir TYPE LOCALE)
+install(DIRECTORY dir TYPE MAN)
+install(DIRECTORY dir TYPE DOC)

+ 24 - 0
Tests/RunCMake/install/DIRECTORY-TYPE-CacheDependent-all-check.cmake

@@ -0,0 +1,24 @@
+set(_check_files
+  [[myshare]]
+  [[myshare/dir]]
+  [[myshare/dir/empty\.txt]]
+  [[myshare/doc]]
+  [[myshare/doc/dir]]
+  [[myshare/doc/dir/empty\.txt]]
+  [[myshare/info]]
+  [[myshare/info/dir]]
+  [[myshare/info/dir/empty\.txt]]
+  [[myshare/locale]]
+  [[myshare/locale/dir]]
+  [[myshare/locale/dir/empty\.txt]]
+  [[myshare/man]]
+  [[myshare/man/dir]]
+  [[myshare/man/dir/empty.txt]]
+  [[myvar]]
+  [[myvar/dir]]
+  [[myvar/dir/empty\.txt]]
+  [[myvar/run]]
+  [[myvar/run/dir]]
+  [[myvar/run/dir/empty\.txt]]
+  )
+check_installed("^${_check_files}$")

+ 7 - 0
Tests/RunCMake/install/DIRECTORY-TYPE-CacheDependent.cmake

@@ -0,0 +1,7 @@
+install(DIRECTORY dir TYPE LOCALSTATE)
+install(DIRECTORY dir TYPE RUNSTATE)
+install(DIRECTORY dir TYPE DATA)
+install(DIRECTORY dir TYPE INFO)
+install(DIRECTORY dir TYPE LOCALE)
+install(DIRECTORY dir TYPE MAN)
+install(DIRECTORY dir TYPE DOC)

+ 42 - 0
Tests/RunCMake/install/DIRECTORY-TYPE-all-check.cmake

@@ -0,0 +1,42 @@
+set(_check_files
+  [[bin]]
+  [[bin/dir]]
+  [[bin/dir/empty\.txt]]
+  [[com]]
+  [[com/dir]]
+  [[com/dir/empty\.txt]]
+  [[etc]]
+  [[etc/dir]]
+  [[etc/dir/empty\.txt]]
+  [[include]]
+  [[include/dir]]
+  [[include/dir/empty\.txt]]
+  [[lib]]
+  [[lib/dir]]
+  [[lib/dir/empty\.txt]]
+  [[sbin]]
+  [[sbin/dir]]
+  [[sbin/dir/empty\.txt]]
+  [[share]]
+  [[share/dir]]
+  [[share/dir/empty\.txt]]
+  [[share/doc]]
+  [[share/doc/dir]]
+  [[share/doc/dir/empty\.txt]]
+  [[share/info]]
+  [[share/info/dir]]
+  [[share/info/dir/empty\.txt]]
+  [[share/locale]]
+  [[share/locale/dir]]
+  [[share/locale/dir/empty\.txt]]
+  [[share/man]]
+  [[share/man/dir]]
+  [[share/man/dir/empty\.txt]]
+  [[var]]
+  [[var/dir]]
+  [[var/dir/empty\.txt]]
+  [[var/run]]
+  [[var/run/dir]]
+  [[var/run/dir/empty\.txt]]
+  )
+check_installed("^${_check_files}$")

+ 13 - 0
Tests/RunCMake/install/DIRECTORY-TYPE.cmake

@@ -0,0 +1,13 @@
+install(DIRECTORY dir TYPE BIN)
+install(DIRECTORY dir TYPE SBIN)
+install(DIRECTORY dir TYPE LIB)
+install(DIRECTORY dir TYPE INCLUDE)
+install(DIRECTORY dir TYPE SYSCONF)
+install(DIRECTORY dir TYPE SHAREDSTATE)
+install(DIRECTORY dir TYPE LOCALSTATE)
+install(DIRECTORY dir TYPE RUNSTATE)
+install(DIRECTORY dir TYPE DATA)
+install(DIRECTORY dir TYPE INFO)
+install(DIRECTORY dir TYPE LOCALE)
+install(DIRECTORY dir TYPE MAN)
+install(DIRECTORY dir TYPE DOC)

+ 1 - 0
Tests/RunCMake/install/FILES-DESTINATION-TYPE-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/install/FILES-DESTINATION-TYPE-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at FILES-DESTINATION-TYPE\.cmake:[0-9]+ \(install\):
+  install FILES given both TYPE and DESTINATION arguments\.  You may only
+  specify one\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 1 - 0
Tests/RunCMake/install/FILES-DESTINATION-TYPE.cmake

@@ -0,0 +1 @@
+install(FILES main.c TYPE BIN DESTINATION mybin)

+ 29 - 0
Tests/RunCMake/install/FILES-TYPE-Cache-all-check.cmake

@@ -0,0 +1,29 @@
+set(_check_files
+  [[mybin]]
+  [[mybin/main\.c]]
+  [[mycom]]
+  [[mycom/main\.c]]
+  [[mydoc]]
+  [[mydoc/main\.c]]
+  [[myetc]]
+  [[myetc/main\.c]]
+  [[myinclude]]
+  [[myinclude/main\.c]]
+  [[myinfo]]
+  [[myinfo/main\.c]]
+  [[mylib]]
+  [[mylib/main\.c]]
+  [[mylocale]]
+  [[mylocale/main\.c]]
+  [[myman]]
+  [[myman/main\.c]]
+  [[myrun]]
+  [[myrun/main\.c]]
+  [[mysbin]]
+  [[mysbin/main\.c]]
+  [[myshare]]
+  [[myshare/main\.c]]
+  [[myvar]]
+  [[myvar/main\.c]]
+  )
+check_installed("^${_check_files}$")

+ 13 - 0
Tests/RunCMake/install/FILES-TYPE-Cache.cmake

@@ -0,0 +1,13 @@
+install(FILES main.c TYPE BIN)
+install(FILES main.c TYPE SBIN)
+install(FILES main.c TYPE LIB)
+install(FILES main.c TYPE INCLUDE)
+install(FILES main.c TYPE SYSCONF)
+install(FILES main.c TYPE SHAREDSTATE)
+install(FILES main.c TYPE LOCALSTATE)
+install(FILES main.c TYPE RUNSTATE)
+install(FILES main.c TYPE DATA)
+install(FILES main.c TYPE INFO)
+install(FILES main.c TYPE LOCALE)
+install(FILES main.c TYPE MAN)
+install(FILES main.c TYPE DOC)

+ 17 - 0
Tests/RunCMake/install/FILES-TYPE-CacheDependent-all-check.cmake

@@ -0,0 +1,17 @@
+set(_check_files
+  [[myshare]]
+  [[myshare/doc]]
+  [[myshare/doc/main\.c]]
+  [[myshare/info]]
+  [[myshare/info/main\.c]]
+  [[myshare/locale]]
+  [[myshare/locale/main\.c]]
+  [[myshare/main\.c]]
+  [[myshare/man]]
+  [[myshare/man/main\.c]]
+  [[myvar]]
+  [[myvar/main\.c]]
+  [[myvar/run]]
+  [[myvar/run/main\.c]]
+  )
+check_installed("^${_check_files}$")

+ 7 - 0
Tests/RunCMake/install/FILES-TYPE-CacheDependent.cmake

@@ -0,0 +1,7 @@
+install(FILES main.c TYPE LOCALSTATE)
+install(FILES main.c TYPE RUNSTATE)
+install(FILES main.c TYPE DATA)
+install(FILES main.c TYPE INFO)
+install(FILES main.c TYPE LOCALE)
+install(FILES main.c TYPE MAN)
+install(FILES main.c TYPE DOC)

+ 29 - 0
Tests/RunCMake/install/FILES-TYPE-all-check.cmake

@@ -0,0 +1,29 @@
+set(_check_files
+  [[bin]]
+  [[bin/main\.c]]
+  [[com]]
+  [[com/main\.c]]
+  [[etc]]
+  [[etc/main\.c]]
+  [[include]]
+  [[include/main\.c]]
+  [[lib]]
+  [[lib/main\.c]]
+  [[sbin]]
+  [[sbin/main\.c]]
+  [[share]]
+  [[share/doc]]
+  [[share/doc/main\.c]]
+  [[share/info]]
+  [[share/info/main\.c]]
+  [[share/locale]]
+  [[share/locale/main\.c]]
+  [[share/main\.c]]
+  [[share/man]]
+  [[share/man/main\.c]]
+  [[var]]
+  [[var/main\.c]]
+  [[var/run]]
+  [[var/run/main\.c]]
+  )
+check_installed("^${_check_files}$")

+ 13 - 0
Tests/RunCMake/install/FILES-TYPE.cmake

@@ -0,0 +1,13 @@
+install(FILES main.c TYPE BIN)
+install(FILES main.c TYPE SBIN)
+install(FILES main.c TYPE LIB)
+install(FILES main.c TYPE INCLUDE)
+install(FILES main.c TYPE SYSCONF)
+install(FILES main.c TYPE SHAREDSTATE)
+install(FILES main.c TYPE LOCALSTATE)
+install(FILES main.c TYPE RUNSTATE)
+install(FILES main.c TYPE DATA)
+install(FILES main.c TYPE INFO)
+install(FILES main.c TYPE LOCALE)
+install(FILES main.c TYPE MAN)
+install(FILES main.c TYPE DOC)

+ 46 - 0
Tests/RunCMake/install/RunCMakeTest.cmake

@@ -65,6 +65,12 @@ run_cmake(CMP0062-NEW)
 run_cmake(CMP0062-WARN)
 run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all)
 run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc)
+run_cmake(FILES-DESTINATION-TYPE)
+run_cmake(DIRECTORY-DESTINATION-TYPE)
+
+if(APPLE)
+  run_cmake(TARGETS-Apple-Defaults)
+endif()
 
 if(NOT RunCMake_GENERATOR STREQUAL "Xcode" OR NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
   run_install_test(FILES-TARGET_OBJECTS)
@@ -74,6 +80,46 @@ run_install_test(TARGETS-InstallFromSubDir)
 run_install_test(TARGETS-OPTIONAL)
 run_install_test(FILES-OPTIONAL)
 run_install_test(DIRECTORY-OPTIONAL)
+run_install_test(TARGETS-Defaults)
+
+set(RunCMake_TEST_OPTIONS
+  "-DCMAKE_INSTALL_BINDIR:PATH=mybin"
+  "-DCMAKE_INSTALL_LIBDIR:PATH=mylib"
+  "-DCMAKE_INSTALL_INCLUDEDIR:PATH=myinclude"
+  )
+run_install_test(TARGETS-Defaults-Cache)
+unset(RunCMake_TEST_OPTIONS)
+
+run_install_test(FILES-TYPE)
+run_install_test(DIRECTORY-TYPE)
+
+set(RunCMake_TEST_OPTIONS
+  "-DCMAKE_INSTALL_BINDIR:PATH=mybin"
+  "-DCMAKE_INSTALL_SBINDIR:PATH=mysbin"
+  "-DCMAKE_INSTALL_LIBEXECDIR:PATH=mylibexec"
+  "-DCMAKE_INSTALL_LIBDIR:PATH=mylib"
+  "-DCMAKE_INSTALL_INCLUDEDIR:PATH=myinclude"
+  "-DCMAKE_INSTALL_SYSCONFDIR:PATH=myetc"
+  "-DCMAKE_INSTALL_SHAREDSTATEDIR:PATH=mycom"
+  "-DCMAKE_INSTALL_LOCALSTATEDIR:PATH=myvar"
+  "-DCMAKE_INSTALL_RUNSTATEDIR:PATH=myrun"
+  "-DCMAKE_INSTALL_DATADIR:PATH=myshare"
+  "-DCMAKE_INSTALL_INFODIR:PATH=myinfo"
+  "-DCMAKE_INSTALL_LOCALEDIR:PATH=mylocale"
+  "-DCMAKE_INSTALL_MANDIR:PATH=myman"
+  "-DCMAKE_INSTALL_DOCDIR:PATH=mydoc"
+  )
+run_install_test(FILES-TYPE-Cache)
+run_install_test(DIRECTORY-TYPE-Cache)
+unset(RunCMake_TEST_OPTIONS)
+
+set(RunCMake_TEST_OPTIONS
+  "-DCMAKE_INSTALL_LOCALSTATEDIR:PATH=myvar"
+  "-DCMAKE_INSTALL_DATAROOTDIR:PATH=myshare"
+  )
+run_install_test(FILES-TYPE-CacheDependent)
+run_install_test(DIRECTORY-TYPE-CacheDependent)
+unset(RunCMake_TEST_OPTIONS)
 
 set(RunCMake_TEST_OPTIONS "-DCMAKE_BUILD_TYPE:STRING=Debug")
 run_install_test(TARGETS-OUTPUT_NAME)

+ 1 - 0
Tests/RunCMake/install/TARGETS-Apple-Defaults-result.txt

@@ -0,0 +1 @@
+1

+ 12 - 0
Tests/RunCMake/install/TARGETS-Apple-Defaults-stderr.txt

@@ -0,0 +1,12 @@
+^CMake Error at TARGETS-Apple-Defaults\.cmake:[0-9]+ \(install\):
+  install TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable
+  target "exe"\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Error at TARGETS-Apple-Defaults\.cmake:[0-9]+ \(install\):
+  install TARGETS given no FRAMEWORK DESTINATION for shared library FRAMEWORK
+  target "lib1"\.
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$

+ 8 - 0
Tests/RunCMake/install/TARGETS-Apple-Defaults.cmake

@@ -0,0 +1,8 @@
+enable_language(C)
+
+add_executable(exe MACOSX_BUNDLE main.c)
+add_library(lib1 SHARED obj1.c)
+set_property(TARGET lib1 PROPERTY FRAMEWORK ON)
+
+install(TARGETS exe)
+install(TARGETS lib1)

+ 49 - 0
Tests/RunCMake/install/TARGETS-Defaults-Cache-all-check.cmake

@@ -0,0 +1,49 @@
+if(WIN32)
+  set(_check_files
+    [[lib3]]
+    [[lib3/(lib)?lib3\.(dll\.a|lib)]]
+    [[lib4]]
+    [[lib4/(lib)?lib4\.dll]]
+    [[mybin]]
+    [[mybin/exe\.exe]]
+    [[mybin/(lib)?lib1\.dll]]
+    [[myinclude]]
+    [[myinclude/obj4\.h]]
+    [[myinclude/obj5\.h]]
+    [[mylib]]
+    [[mylib/(lib)?lib1\.(dll\.a|lib)]]
+    [[mylib/(lib)?lib2\.(a|lib)]]
+    )
+elseif(CYGWIN)
+  set(_check_files
+    [[lib3]]
+    [[lib3/liblib3\.dll\.a]]
+    [[lib4]]
+    [[lib4/cyglib4\.dll]]
+    [[mybin]]
+    [[mybin/exe\.exe]]
+    [[mybin/cyglib1\.dll]]
+    [[myinclude]]
+    [[myinclude/obj4\.h]]
+    [[myinclude/obj5\.h]]
+    [[mylib]]
+    [[mylib/liblib1\.dll\.a]]
+    [[mylib/liblib2\.a]]
+    )
+else()
+  set(_check_files
+    [[lib3]]
+    [[lib3/liblib3\.(dylib|so)]]
+    [[lib4]]
+    [[lib4/liblib4\.(dylib|so)]]
+    [[mybin]]
+    [[mybin/exe]]
+    [[myinclude]]
+    [[myinclude/obj4\.h]]
+    [[myinclude/obj5\.h]]
+    [[mylib]]
+    [[mylib/liblib1\.(dylib|so)]]
+    [[mylib/liblib2\.a]]
+    )
+endif()
+check_installed("^${_check_files}$")

+ 19 - 0
Tests/RunCMake/install/TARGETS-Defaults-Cache.cmake

@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_executable(exe main.c)
+add_library(lib1 SHARED obj1.c)
+add_library(lib2 STATIC obj3.c)
+add_library(lib3 SHARED obj4.c)
+set_property(TARGET lib3 PROPERTY PRIVATE_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/obj4.h)
+add_library(lib4 SHARED obj5.c)
+set_property(TARGET lib4 PROPERTY PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/obj5.h)
+
+install(TARGETS exe lib1 lib2)
+install(TARGETS lib3
+  LIBRARY DESTINATION lib3
+  ARCHIVE DESTINATION lib3
+  )
+install(TARGETS lib4
+  LIBRARY DESTINATION lib4
+  RUNTIME DESTINATION lib4
+  )

+ 49 - 0
Tests/RunCMake/install/TARGETS-Defaults-all-check.cmake

@@ -0,0 +1,49 @@
+if(WIN32)
+  set(_check_files
+    [[bin]]
+    [[bin/exe\.exe]]
+    [[bin/(lib)?lib1\.dll]]
+    [[include]]
+    [[include/obj4\.h]]
+    [[include/obj5\.h]]
+    [[lib]]
+    [[lib/(lib)?lib1\.(dll\.a|lib)]]
+    [[lib/(lib)?lib2\.(a|lib)]]
+    [[lib3]]
+    [[lib3/(lib)?lib3\.(dll\.a|lib)]]
+    [[lib4]]
+    [[lib4/(lib)?lib4\.dll]]
+    )
+elseif(CYGWIN)
+  set(_check_files
+    [[bin]]
+    [[bin/exe\.exe]]
+    [[bin/cyglib1\.dll]]
+    [[include]]
+    [[include/obj4\.h]]
+    [[include/obj5\.h]]
+    [[lib]]
+    [[lib/liblib1\.dll\.a]]
+    [[lib/liblib2\.a]]
+    [[lib3]]
+    [[lib3/liblib3\.dll\.a]]
+    [[lib4]]
+    [[lib4/cyglib4\.dll]]
+    )
+else()
+  set(_check_files
+    [[bin]]
+    [[bin/exe]]
+    [[include]]
+    [[include/obj4\.h]]
+    [[include/obj5\.h]]
+    [[lib]]
+    [[lib/liblib1\.(dylib|so)]]
+    [[lib/liblib2\.a]]
+    [[lib3]]
+    [[lib3/liblib3\.(dylib|so)]]
+    [[lib4]]
+    [[lib4/liblib4\.(dylib|so)]]
+    )
+endif()
+check_installed("^${_check_files}$")

+ 19 - 0
Tests/RunCMake/install/TARGETS-Defaults.cmake

@@ -0,0 +1,19 @@
+enable_language(C)
+
+add_executable(exe main.c)
+add_library(lib1 SHARED obj1.c)
+add_library(lib2 STATIC obj3.c)
+add_library(lib3 SHARED obj4.c)
+set_property(TARGET lib3 PROPERTY PRIVATE_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/obj4.h)
+add_library(lib4 SHARED obj5.c)
+set_property(TARGET lib4 PROPERTY PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/obj5.h)
+
+install(TARGETS exe lib1 lib2)
+install(TARGETS lib3
+  LIBRARY DESTINATION lib3
+  ARCHIVE DESTINATION lib3
+  )
+install(TARGETS lib4
+  LIBRARY DESTINATION lib4
+  RUNTIME DESTINATION lib4
+  )

+ 7 - 0
Tests/RunCMake/install/obj3.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int obj3(void)
+{
+  return 0;
+}

+ 6 - 0
Tests/RunCMake/install/obj3.h

@@ -0,0 +1,6 @@
+#ifndef OBJ3_H
+#define OBJ3_H
+
+int obj3(void);
+
+#endif /* OBJ3_H */

+ 7 - 0
Tests/RunCMake/install/obj4.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int obj4(void)
+{
+  return 0;
+}

+ 6 - 0
Tests/RunCMake/install/obj4.h

@@ -0,0 +1,6 @@
+#ifndef OBJ4_H
+#define OBJ4_H
+
+int obj4(void);
+
+#endif /* OBJ4_H */

+ 7 - 0
Tests/RunCMake/install/obj5.c

@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  int obj5(void)
+{
+  return 0;
+}

+ 6 - 0
Tests/RunCMake/install/obj5.h

@@ -0,0 +1,6 @@
+#ifndef OBJ5_H
+#define OBJ5_H
+
+int obj5(void);
+
+#endif /* OBJ5_H */