소스 검색

file: Add COPY/INSTALL option for fixed layout relative to a directory

Add a `FILES_FROM_DIR` option to install a specific set of files
specified relative to a given directory and preserve their layout
in the destination.  Currently we intend to use this internally
to implement other things so we don't provide an `install()`
porcelain or documentation yet.
Brad King 8 년 전
부모
커밋
99b90dbf3c

+ 39 - 1
Source/cmFileCommand.cxx

@@ -1147,6 +1147,7 @@ protected:
   bool UseGivenPermissionsDir;
   bool UseSourcePermissions;
   std::string Destination;
+  std::string FilesFromDir;
   std::vector<std::string> Files;
   int Doing;
 
@@ -1156,6 +1157,7 @@ protected:
     DoingNone,
     DoingError,
     DoingDestination,
+    DoingFilesFromDir,
     DoingFiles,
     DoingPattern,
     DoingRegex,
@@ -1251,6 +1253,12 @@ bool cmFileCopier::CheckKeyword(std::string const& arg)
     } else {
       this->Doing = DoingDestination;
     }
+  } else if (arg == "FILES_FROM_DIR") {
+    if (this->CurrentMatchRule) {
+      this->NotAfterMatch(arg);
+    } else {
+      this->Doing = DoingFilesFromDir;
+    }
   } else if (arg == "PATTERN") {
     this->Doing = DoingPattern;
   } else if (arg == "REGEX") {
@@ -1325,6 +1333,16 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       }
       this->Doing = DoingNone;
       break;
+    case DoingFilesFromDir:
+      if (cmSystemTools::FileIsFullPath(arg.c_str())) {
+        this->FilesFromDir = arg;
+      } else {
+        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
+        this->FilesFromDir += "/" + arg;
+      }
+      cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
+      this->Doing = DoingNone;
+      break;
     case DoingPattern: {
       // Convert the pattern to a regular expression.  Require a
       // leading slash and trailing end-of-string in the matched
@@ -1388,9 +1406,17 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
        i != this->Files.end(); ++i) {
     std::string file;
     if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) {
-      file = this->Makefile->GetCurrentSourceDirectory();
+      if (!this->FilesFromDir.empty()) {
+        file = this->FilesFromDir;
+      } else {
+        file = this->Makefile->GetCurrentSourceDirectory();
+      }
       file += "/";
       file += *i;
+    } else if (!this->FilesFromDir.empty()) {
+      this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
+                                  "to be specified as relative paths.");
+      return false;
     } else {
       file = *i;
     }
@@ -1404,6 +1430,13 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
 
     // Compute the full path to the destination file.
     std::string toFile = this->Destination;
+    if (!this->FilesFromDir.empty()) {
+      std::string dir = cmSystemTools::GetFilenamePath(*i);
+      if (!dir.empty()) {
+        toFile += "/";
+        toFile += dir;
+      }
+    }
     std::string const& toName = this->ToName(fromName);
     if (!toName.empty()) {
       toFile += "/";
@@ -1754,6 +1787,11 @@ bool cmFileInstaller::Parse(std::vector<std::string> const& args)
   }
 
   if (!this->Rename.empty()) {
+    if (!this->FilesFromDir.empty()) {
+      this->FileCommand->SetError("INSTALL option RENAME may not be "
+                                  "combined with FILES_FROM_DIR.");
+      return false;
+    }
     if (this->InstallType != cmInstallType_FILES &&
         this->InstallType != cmInstallType_PROGRAMS) {
       this->FileCommand->SetError("INSTALL option RENAME may be used "

+ 1 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-result.txt

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

+ 15 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad-stderr.txt

@@ -0,0 +1,15 @@
+^CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR requires all files to be specified as relative
+  paths\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file INSTALL option RENAME may not be combined with FILES_FROM_DIR\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
++
+CMake Error at INSTALL-FILES_FROM_DIR-bad.cmake:[0-9]+ \(file\):
+  file option FILES_FROM_DIR may not appear after PATTERN or REGEX\.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 5 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-bad.cmake

@@ -0,0 +1,5 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(INSTALL FILES ${src}/a.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt FILES_FROM_DIR ${src} DESTINATION ${dst} RENAME b.txt)
+file(INSTALL FILES a.txt DESTINATION ${dst} PATTERN *.txt FILES_FROM_DIR)

+ 8 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-stdout.txt

@@ -0,0 +1,8 @@
+-- Before Installing
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Installing: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b.txt
+-- Up-to-date: .*/Tests/RunCMake/file/INSTALL-FILES_FROM_DIR-build/from/a/b/c.txt
+-- After Installing

+ 7 - 0
Tests/RunCMake/file/INSTALL-FILES_FROM_DIR.cmake

@@ -0,0 +1,7 @@
+set(src ${CMAKE_CURRENT_SOURCE_DIR}/from)
+set(dst ${CMAKE_CURRENT_BINARY_DIR}/from)
+file(REMOVE RECURSE ${dst})
+message(STATUS "Before Installing")
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR ${src} DESTINATION ${dst})
+file(INSTALL FILES a.txt a/b.txt a/b/c.txt FILES_FROM_DIR from DESTINATION ${dst})
+message(STATUS "After Installing")

+ 2 - 0
Tests/RunCMake/file/RunCMakeTest.cmake

@@ -8,6 +8,8 @@ run_cmake(UPLOAD-unused-argument)
 run_cmake(UPLOAD-httpheader-not-set)
 run_cmake(UPLOAD-pass-not-set)
 run_cmake(INSTALL-DIRECTORY)
+run_cmake(INSTALL-FILES_FROM_DIR)
+run_cmake(INSTALL-FILES_FROM_DIR-bad)
 run_cmake(INSTALL-MESSAGE-bad)
 run_cmake(FileOpenFailRead)
 run_cmake(LOCK)

+ 0 - 0
Tests/RunCMake/file/from/a.txt


+ 0 - 0
Tests/RunCMake/file/from/a/b.txt


+ 0 - 0
Tests/RunCMake/file/from/a/b/c.txt