summaryrefslogtreecommitdiffstats
path: root/Source/cmFileCommand.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r--Source/cmFileCommand.cxx167
1 files changed, 138 insertions, 29 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index dc97e37..ff6e2b7 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2,23 +2,19 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFileCommand.h"
+#include "cm_kwiml.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+#include "cmsys/Glob.hxx"
+#include "cmsys/RegularExpression.hxx"
+#include "cmsys/String.hxx"
#include <algorithm>
#include <assert.h>
-#include <cm_kwiml.h>
-#include <cmsys/Directory.hxx>
-#include <cmsys/FStream.hxx>
-#include <cmsys/Glob.hxx>
-#include <cmsys/RegularExpression.hxx>
-#include <cmsys/String.hxx>
-#include <list>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <sys/types.h>
-// include sys/stat.h after sys/types.h
-#include <sys/stat.h>
+#include <vector>
#include "cmAlgorithms.h"
#include "cmCommandArgumentsHelper.h"
@@ -35,11 +31,17 @@
#include "cmSystemTools.h"
#include "cmTimestamp.h"
#include "cm_auto_ptr.hxx"
+#include "cm_sys_stat.h"
#include "cmake.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmCurl.h"
#include "cmFileLockResult.h"
+#include "cm_curl.h"
+#endif
+
+#if defined(CMAKE_USE_ELF_PARSER)
+#include "cmELF.h"
#endif
#if defined(_WIN32)
@@ -170,6 +172,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "RPATH_REMOVE") {
return this->HandleRPathRemoveCommand(args);
}
+ if (subCommand == "READ_ELF") {
+ return this->HandleReadElfCommand(args);
+ }
if (subCommand == "RELATIVE_PATH") {
return this->HandleRelativePathCommand(args);
}
@@ -612,8 +617,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
continue;
}
- else if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
- (c == '\n' && newline_consume)) {
+ if ((c >= 0x20 && c < 0x7F) || c == '\t' ||
+ (c == '\n' && newline_consume)) {
// This is an ASCII character that may be part of a string.
// Cast added to avoid compiler warning. Cast is ok because
// c is guaranteed to fit in char by the above if...
@@ -1028,8 +1033,6 @@ protected:
{
}
};
- struct MatchRule;
- friend struct MatchRule;
struct MatchRule
{
cmsys::RegularExpression Regex;
@@ -1148,6 +1151,7 @@ protected:
bool UseGivenPermissionsDir;
bool UseSourcePermissions;
std::string Destination;
+ std::string FilesFromDir;
std::vector<std::string> Files;
int Doing;
@@ -1157,6 +1161,7 @@ protected:
DoingNone,
DoingError,
DoingDestination,
+ DoingFilesFromDir,
DoingFiles,
DoingPattern,
DoingRegex,
@@ -1252,6 +1257,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") {
@@ -1315,13 +1326,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
{
switch (this->Doing) {
case DoingFiles:
- if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
- this->Files.push_back(arg);
- } else {
- std::string file = this->Makefile->GetCurrentSourceDirectory();
- file += "/" + arg;
- this->Files.push_back(file);
- }
+ this->Files.push_back(arg);
break;
case DoingDestination:
if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
@@ -1332,6 +1337,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
@@ -1391,17 +1406,41 @@ bool cmFileCopier::Run(std::vector<std::string> const& args)
return false;
}
- std::vector<std::string> const& files = this->Files;
- for (std::vector<std::string>::size_type i = 0; i < files.size(); ++i) {
+ for (std::vector<std::string>::const_iterator i = this->Files.begin();
+ i != this->Files.end(); ++i) {
+ std::string file;
+ if (!i->empty() && !cmSystemTools::FileIsFullPath(*i)) {
+ 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;
+ }
+
// Split the input file into its directory and name components.
std::vector<std::string> fromPathComponents;
- cmSystemTools::SplitPath(files[i], fromPathComponents);
+ cmSystemTools::SplitPath(file, fromPathComponents);
std::string fromName = *(fromPathComponents.end() - 1);
std::string fromDir = cmSystemTools::JoinPath(
fromPathComponents.begin(), fromPathComponents.end() - 1);
// 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 += "/";
@@ -1486,6 +1525,9 @@ bool cmFileCopier::InstallSymlink(const char* fromFile, const char* toFile)
// Remove the destination file so we can always create the symlink.
cmSystemTools::RemoveFile(toFile);
+ // Create destination directory if it doesn't exist
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));
+
// Create the symlink.
if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
std::ostringstream e;
@@ -1749,6 +1791,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 "
@@ -2181,6 +2228,68 @@ bool cmFileCommand::HandleRPathCheckCommand(
return true;
}
+bool cmFileCommand::HandleReadElfCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 4) {
+ this->SetError("READ_ELF must be called with at least three additional "
+ "arguments.");
+ return false;
+ }
+
+ cmCommandArgumentsHelper argHelper;
+ cmCommandArgumentGroup group;
+
+ cmCAString readArg(&argHelper, "READ_ELF");
+ cmCAString fileNameArg(&argHelper, CM_NULLPTR);
+
+ cmCAString rpathArg(&argHelper, "RPATH", &group);
+ cmCAString runpathArg(&argHelper, "RUNPATH", &group);
+ cmCAString errorArg(&argHelper, "CAPTURE_ERROR", &group);
+
+ readArg.Follows(CM_NULLPTR);
+ fileNameArg.Follows(&readArg);
+ group.Follows(&fileNameArg);
+ argHelper.Parse(&args, CM_NULLPTR);
+
+ if (!cmSystemTools::FileExists(fileNameArg.GetString(), true)) {
+ std::ostringstream e;
+ e << "READ_ELF given FILE \"" << fileNameArg.GetString()
+ << "\" that does not exist.";
+ this->SetError(e.str());
+ return false;
+ }
+
+#if defined(CMAKE_USE_ELF_PARSER)
+ cmELF elf(fileNameArg.GetCString());
+
+ if (!rpathArg.GetString().empty()) {
+ if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) {
+ std::string rpath(se_rpath->Value);
+ std::replace(rpath.begin(), rpath.end(), ':', ';');
+ this->Makefile->AddDefinition(rpathArg.GetString(), rpath.c_str());
+ }
+ }
+ if (!runpathArg.GetString().empty()) {
+ if (cmELF::StringEntry const* se_runpath = elf.GetRunPath()) {
+ std::string runpath(se_runpath->Value);
+ std::replace(runpath.begin(), runpath.end(), ':', ';');
+ this->Makefile->AddDefinition(runpathArg.GetString(), runpath.c_str());
+ }
+ }
+
+ return true;
+#else
+ std::string error = "ELF parser not available on this platform.";
+ if (errorArg.GetString().empty()) {
+ this->SetError(error);
+ return false;
+ } else {
+ this->Makefile->AddDefinition(errorArg.GetString(), error.c_str());
+ return true;
+ }
+#endif
+}
+
bool cmFileCommand::HandleInstallCommand(std::vector<std::string> const& args)
{
cmFileInstaller installer(this);
@@ -2513,7 +2622,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
bool showProgress = false;
std::string userpwd;
- std::list<std::string> curl_headers;
+ std::vector<std::string> curl_headers;
while (i != args.end()) {
if (*i == "TIMEOUT") {
@@ -2757,7 +2866,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
}
struct curl_slist* headers = CM_NULLPTR;
- for (std::list<std::string>::const_iterator h = curl_headers.begin();
+ for (std::vector<std::string>::const_iterator h = curl_headers.begin();
h != curl_headers.end(); ++h) {
headers = ::curl_slist_append(headers, h->c_str());
}
@@ -2847,7 +2956,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
bool showProgress = false;
std::string userpwd;
- std::list<std::string> curl_headers;
+ std::vector<std::string> curl_headers;
while (i != args.end()) {
if (*i == "TIMEOUT") {
@@ -3015,7 +3124,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
}
struct curl_slist* headers = CM_NULLPTR;
- for (std::list<std::string>::const_iterator h = curl_headers.begin();
+ for (std::vector<std::string>::const_iterator h = curl_headers.begin();
h != curl_headers.end(); ++h) {
headers = ::curl_slist_append(headers, h->c_str());
}