summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2008-01-02 20:17:56 (GMT)
committerBrad King <brad.king@kitware.com>2008-01-02 20:17:56 (GMT)
commit60bf0531b01b641a00f6844dfd38ef803d2deda1 (patch)
tree1f39b207ca36da6e19b1ae0363836517b3e663bd
parent509764067136026cfab21e7eb83c9f03ddc1c96a (diff)
downloadCMake-60bf0531b01b641a00f6844dfd38ef803d2deda1.zip
CMake-60bf0531b01b641a00f6844dfd38ef803d2deda1.tar.gz
CMake-60bf0531b01b641a00f6844dfd38ef803d2deda1.tar.bz2
ENH: Added FILES_MATCHING option to INSTALL(DIRECTORY). This will help install a tree of header files while ignoring non-headers.
-rw-r--r--Source/cmFileCommand.cxx36
-rw-r--r--Source/cmInstallCommand.cxx23
-rw-r--r--Source/cmInstallCommand.h27
-rw-r--r--Tests/SimpleInstall/CMakeLists.txt13
-rw-r--r--Tests/SimpleInstallS2/CMakeLists.txt13
5 files changed, 101 insertions, 11 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 3a31a3f..092dfb1 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -702,7 +702,7 @@ struct cmFileInstaller
// All instances need the file command and makefile using them.
cmFileInstaller(cmFileCommand* fc, cmMakefile* mf):
- FileCommand(fc), Makefile(mf), DestDirLength(0)
+ FileCommand(fc), Makefile(mf), DestDirLength(0), MatchlessFiles(true)
{
// Get the current manifest.
this->Manifest =
@@ -724,6 +724,9 @@ public:
// The length of the destdir setting.
int DestDirLength;
+ // Whether to install a file not matching any expression.
+ bool MatchlessFiles;
+
// The current file manifest (semicolon separated list).
std::string Manifest;
@@ -749,7 +752,8 @@ public:
std::vector<MatchRule> MatchRules;
// Get the properties from rules matching this input file.
- MatchProperties CollectMatchProperties(const char* file)
+ MatchProperties CollectMatchProperties(const char* file,
+ bool isDirectory)
{
// Match rules are case-insensitive on some platforms.
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
@@ -758,16 +762,22 @@ public:
#endif
// Collect properties from all matching rules.
+ bool matched = false;
MatchProperties result;
for(std::vector<MatchRule>::iterator mr = this->MatchRules.begin();
mr != this->MatchRules.end(); ++mr)
{
if(mr->Regex.find(file))
{
+ matched = true;
result.Exclude |= mr->Properties.Exclude;
result.Permissions |= mr->Properties.Permissions;
}
}
+ if(!matched && !this->MatchlessFiles && !isDirectory)
+ {
+ result.Exclude = true;
+ }
return result;
}
@@ -868,7 +878,8 @@ bool cmFileInstaller::InstallFile(const char* fromFile, const char* toFile,
bool always)
{
// Collect any properties matching this file name.
- MatchProperties match_properties = this->CollectMatchProperties(fromFile);
+ MatchProperties match_properties =
+ this->CollectMatchProperties(fromFile, false);
// Skip the file if it is excluded.
if(match_properties.Exclude)
@@ -946,7 +957,8 @@ bool cmFileInstaller::InstallDirectory(const char* source,
bool always)
{
// Collect any properties matching this directory name.
- MatchProperties match_properties = this->CollectMatchProperties(source);
+ MatchProperties match_properties =
+ this->CollectMatchProperties(source, true);
// Skip the directory if it is excluded.
if(match_properties.Exclude)
@@ -1463,6 +1475,22 @@ bool cmFileCommand::ParseInstallArgs(std::vector<std::string> const& args,
doing_permissions_dir = false;
use_source_permissions = true;
}
+ else if ( *cstr == "FILES_MATCHING" )
+ {
+ if(current_match_rule)
+ {
+ cmOStringStream e;
+ e << "INSTALL does not allow \"" << *cstr << "\" after REGEX.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ doing_properties = false;
+ doing_files = false;
+ doing_permissions_file = false;
+ doing_permissions_dir = false;
+ installer.MatchlessFiles = false;
+ }
else if ( *cstr == "COMPONENTS" )
{
cmOStringStream e;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index a2e3764..c04a682 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -871,6 +871,29 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
doing_component = false;
literal_args += " USE_SOURCE_PERMISSIONS";
}
+ else if(args[i] == "FILES_MATCHING")
+ {
+ if(in_match_mode)
+ {
+ cmOStringStream e;
+ e << args[0] << " does not allow \""
+ << args[i] << "\" after PATTERN or REGEX.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ // Add this option literally.
+ doing_dirs = false;
+ doing_destination = false;
+ doing_pattern = false;
+ doing_regex = false;
+ doing_permissions_file = false;
+ doing_permissions_dir = false;
+ doing_permissions_match = false;
+ doing_configurations = false;
+ doing_component = false;
+ literal_args += " FILES_MATCHING";
+ }
else if(args[i] == "CONFIGURATIONS")
{
if(in_match_mode)
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index d7b3f64..15332ae 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -178,7 +178,7 @@ public:
" [DIRECTORY_PERMISSIONS permissions...]\n"
" [USE_SOURCE_PERMISSIONS]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
- " [COMPONENT <component>]\n"
+ " [COMPONENT <component>] [FILES_MATCHING]\n"
" [[PATTERN <pattern> | REGEX <regex>]\n"
" [EXCLUDE] [PERMISSIONS permissions...]] [...])\n"
"The DIRECTORY form installs contents of one or more directories "
@@ -198,18 +198,31 @@ public:
"If no permissions are specified files will be given the default "
"permissions specified in the FILES form of the command, and the "
"directories will be given the default permissions specified in the "
- "PROGRAMS form of the command. "
- "The PATTERN and REGEX options specify a globbing pattern or regular "
- "expression to match directories or files encountered during traversal "
- "of an input directory. The full path to an input file or directory "
+ "PROGRAMS form of the command.\n"
+
+ "Installation of directories may be controlled with fine granularity "
+ "using the PATTERN or REGEX options. These \"match\" options specify a "
+ "globbing pattern or regular expression to match directories or files "
+ "encountered within input directories. They may be used to apply "
+ "certain options (see below) to a subset of the files and directories "
+ "encountered. "
+ "The full path to each input file or directory "
"(with forward slashes) is matched against the expression. "
"A PATTERN will match only complete file names: the portion of the "
"full path matching the pattern must occur at the end of the file name "
"and be preceded by a slash. "
"A REGEX will match any portion of the full path but it may use "
"'/' and '$' to simulate the PATTERN behavior. "
- "Options following one of these matching expressions "
- "are applied only to files or directories matching them. "
+ "By default all files and directories are installed whether "
+ "or not they are matched. "
+ "The FILES_MATCHING option may be given before the first match option "
+ "to disable installation of files (but not directories) not matched by "
+ "any expression. For example, the code\n"
+ " install(DIRECTORY src/ DESTINATION include/myproj\n"
+ " FILES_MATCHING PATTERN \"*.h\")\n"
+ "will extract and install header files from a source tree.\n"
+ "Some options may follow a PATTERN or REGEX expression and are "
+ "applied only to files or directories matching them. "
"The EXCLUDE option will skip the matched file or directory. "
"The PERMISSIONS option overrides the permissions setting for the "
"matched file or directory. "
diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt
index 2f181ef..25b54ab 100644
--- a/Tests/SimpleInstall/CMakeLists.txt
+++ b/Tests/SimpleInstall/CMakeLists.txt
@@ -97,6 +97,12 @@ IF(STAGE2)
IF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
MESSAGE(FATAL_ERROR "Directory installation installed CMakeLists.txt.")
ENDIF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
+ IF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
+ MESSAGE(FATAL_ERROR "Directory installation did not install alternate TSD.h")
+ ENDIF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
+ IF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
+ MESSAGE(FATAL_ERROR "Directory installation installed alternate TSD.cxx")
+ ENDIF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
# Check that scripts properly installed.
IF(WIN32 AND NOT CYGWIN)
@@ -248,6 +254,13 @@ ELSE(STAGE2)
PATTERN "CVS" EXCLUDE
REGEX "\\.txt$" EXCLUDE
)
+ INSTALL(
+ DIRECTORY TestSubDir DESTINATION MyTest/share/alt
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE
+ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ FILES_MATCHING PATTERN "*.h"
+ )
# Test empty directory installation.
INSTALL(DIRECTORY DESTINATION MyTest/share/empty)
diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt
index 2f181ef..25b54ab 100644
--- a/Tests/SimpleInstallS2/CMakeLists.txt
+++ b/Tests/SimpleInstallS2/CMakeLists.txt
@@ -97,6 +97,12 @@ IF(STAGE2)
IF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
MESSAGE(FATAL_ERROR "Directory installation installed CMakeLists.txt.")
ENDIF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/CMakeLists.txt")
+ IF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
+ MESSAGE(FATAL_ERROR "Directory installation did not install alternate TSD.h")
+ ENDIF(NOT EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.h")
+ IF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
+ MESSAGE(FATAL_ERROR "Directory installation installed alternate TSD.cxx")
+ ENDIF(EXISTS "${CMAKE_INSTALL_PREFIX}/MyTest/share/alt/TestSubDir/TSD.cxx")
# Check that scripts properly installed.
IF(WIN32 AND NOT CYGWIN)
@@ -248,6 +254,13 @@ ELSE(STAGE2)
PATTERN "CVS" EXCLUDE
REGEX "\\.txt$" EXCLUDE
)
+ INSTALL(
+ DIRECTORY TestSubDir DESTINATION MyTest/share/alt
+ FILE_PERMISSIONS OWNER_READ OWNER_WRITE
+ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
+ GROUP_READ GROUP_EXECUTE
+ FILES_MATCHING PATTERN "*.h"
+ )
# Test empty directory installation.
INSTALL(DIRECTORY DESTINATION MyTest/share/empty)