summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackGenerator.cxx70
-rw-r--r--Source/cmFileAPICodemodel.cxx6
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx58
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h5
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx29
-rw-r--r--Source/cmcmd.cxx15
-rw-r--r--Source/kwsys/CMakeLists.txt8
-rw-r--r--Source/kwsys/SystemTools.cxx123
-rw-r--r--Source/kwsys/testSystemTools.cxx83
10 files changed, 235 insertions, 164 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 1b06e45..46f7cce 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 15)
-set(CMake_VERSION_PATCH 20190829)
+set(CMake_VERSION_PATCH 20190903)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 288d5d8..a96c1c8 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -594,11 +594,37 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
componentsVector.push_back(project.Component);
}
- const char* buildConfigCstr = this->GetOption("CPACK_BUILD_CONFIG");
- std::string buildConfig = buildConfigCstr ? buildConfigCstr : "";
- cmGlobalGenerator* globalGenerator =
+ std::vector<std::string> buildConfigs;
+
+ // Try get configuration names given via `-C` CLI option
+ {
+ const char* const buildConfigCstr =
+ this->GetOption("CPACK_BUILD_CONFIG");
+ auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{};
+ cmExpandList(buildConfig, buildConfigs);
+ }
+
+ // Try get configurations requested by the user explicitly
+ {
+ const char* const configsCstr =
+ this->GetOption("CPACK_INSTALL_CMAKE_CONFIGURATIONS");
+ auto configs = configsCstr ? configsCstr : std::string{};
+ cmExpandList(configs, buildConfigs);
+ }
+
+ // Remove duplicates
+ std::sort(buildConfigs.begin(), buildConfigs.end());
+ buildConfigs.erase(std::unique(buildConfigs.begin(), buildConfigs.end()),
+ buildConfigs.end());
+
+ // Ensure we have at least one configuration.
+ if (buildConfigs.empty()) {
+ buildConfigs.emplace_back();
+ }
+
+ std::unique_ptr<cmGlobalGenerator> globalGenerator(
this->MakefileMap->GetCMakeInstance()->CreateGlobalGenerator(
- cmakeGenerator);
+ cmakeGenerator));
if (!globalGenerator) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Specified package generator not found. "
@@ -611,27 +637,29 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
// on windows.
cmSystemTools::SetForceUnixPaths(globalGenerator->GetForceUnixPaths());
- if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
- globalGenerator, buildConfig)) {
- return 0;
- }
-
- delete globalGenerator;
-
- cmCPackLogger(cmCPackLog::LOG_OUTPUT,
- "- Install project: " << project.ProjectName << std::endl);
-
- // Run the installation for each component
- for (std::string const& component : componentsVector) {
- if (!this->InstallCMakeProject(
- setDestDir, project.Directory, baseTempInstallDirectory,
- default_dir_mode, component, componentInstall,
- project.SubDirectory, buildConfig, absoluteDestFiles)) {
+ // Run the installation for the selected build configurations
+ for (auto const& buildConfig : buildConfigs) {
+ if (!this->RunPreinstallTarget(project.ProjectName, project.Directory,
+ globalGenerator.get(), buildConfig)) {
return 0;
}
+
+ cmCPackLogger(cmCPackLog::LOG_OUTPUT,
+ "- Install project: " << project.ProjectName << " ["
+ << buildConfig << ']'
+ << std::endl);
+ // Run the installation for each component
+ for (std::string const& component : componentsVector) {
+ if (!this->InstallCMakeProject(
+ setDestDir, project.Directory, baseTempInstallDirectory,
+ default_dir_mode, component, componentInstall,
+ project.SubDirectory, buildConfig, absoluteDestFiles)) {
+ return 0;
+ }
+ }
}
- this->CMakeProjects.push_back(project);
+ this->CMakeProjects.emplace_back(std::move(project));
}
}
this->SetOption("CPACK_ABSOLUTE_DESTINATION_FILES",
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index 08db7c7..eff32ea 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -582,6 +582,12 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
{
Target t(gt, this->Config);
std::string prefix = "target-" + gt->GetName();
+ for (char& c : prefix) {
+ // CMP0037 OLD behavior allows slashes in target names. Remove them.
+ if (c == '/' || c == '\\') {
+ c = '_';
+ }
+ }
if (!this->Config.empty()) {
prefix += "-" + this->Config;
}
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 48b17c0..7d437f3 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -232,7 +232,15 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
if (this->GeneratorToolsetCuda.empty()) {
// Find the highest available version of the CUDA tools.
std::vector<std::string> cudaTools;
- std::string const bcDir = this->VCTargetsPath + "/BuildCustomizations";
+ std::string bcDir;
+ if (this->GeneratorToolsetCudaCustomDir.empty()) {
+ bcDir = this->VCTargetsPath + "/BuildCustomizations";
+ } else {
+ bcDir = this->GetPlatformToolsetCudaCustomDirString() +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions";
+ cmSystemTools::ConvertToUnixSlashes(bcDir);
+ }
cmsys::Glob gl;
gl.SetRelative(bcDir.c_str());
if (gl.FindFiles(bcDir + "/CUDA *.props")) {
@@ -243,6 +251,24 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
std::sort(cudaTools.begin(), cudaTools.end(),
cmSystemTools::VersionCompareGreater);
this->GeneratorToolsetCuda = cudaTools.at(0);
+ } else if (!this->GeneratorToolsetCudaCustomDir.empty()) {
+ // Generate an error if Visual Studio integration files are not found
+ // inside of custom cuda toolset.
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "given toolset\n"
+ " cuda=" << this->GeneratorToolsetCudaCustomDir << "\n"
+ "cannot detect Visual Studio integration files in path\n"
+ " " << bcDir;
+
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+
+ // Clear the configured tool-set
+ this->GeneratorToolsetCuda.clear();
}
}
@@ -319,6 +345,9 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(
if (const char* cuda = this->GetPlatformToolsetCuda()) {
mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA", cuda);
}
+ if (const char* cudaDir = this->GetPlatformToolsetCudaCustomDir()) {
+ mf->AddDefinition("CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR", cudaDir);
+ }
return true;
}
@@ -395,7 +424,17 @@ bool cmGlobalVisualStudio10Generator::ProcessGeneratorToolsetField(
std::string const& key, std::string const& value)
{
if (key == "cuda") {
- this->GeneratorToolsetCuda = value;
+ /* test if cuda toolset is path to custom dir or cuda version */
+ auto pos = value.find_first_not_of("0123456789.");
+ if (pos != std::string::npos) {
+ this->GeneratorToolsetCudaCustomDir = value;
+ /* ensure trailing backslash for easy path joining */
+ if (this->GeneratorToolsetCudaCustomDir.back() != '\\') {
+ this->GeneratorToolsetCudaCustomDir.push_back('\\');
+ }
+ } else {
+ this->GeneratorToolsetCuda = value;
+ }
return true;
}
if (key == "version") {
@@ -643,6 +682,21 @@ cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaString() const
return this->GeneratorToolsetCuda;
}
+const char* cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDir()
+ const
+{
+ if (!this->GeneratorToolsetCudaCustomDir.empty()) {
+ return this->GeneratorToolsetCudaCustomDir.c_str();
+ }
+ return nullptr;
+}
+
+std::string const&
+cmGlobalVisualStudio10Generator::GetPlatformToolsetCudaCustomDirString() const
+{
+ return this->GeneratorToolsetCudaCustomDir;
+}
+
bool cmGlobalVisualStudio10Generator::IsDefaultToolset(
const std::string&) const
{
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 1d30cd6..9adcf08 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -61,6 +61,10 @@ public:
const char* GetPlatformToolsetCuda() const;
std::string const& GetPlatformToolsetCudaString() const;
+ /** The custom cuda install directory */
+ const char* GetPlatformToolsetCudaCustomDir() const;
+ std::string const& GetPlatformToolsetCudaCustomDirString() const;
+
/** Return whether we need to use No/Debug instead of false/true
for GenerateDebugInformation. */
bool GetPlatformToolsetNeedsDebugEnum() const
@@ -152,6 +156,7 @@ protected:
std::string GeneratorToolsetVersion;
std::string GeneratorToolsetHostArchitecture;
std::string GeneratorToolsetCuda;
+ std::string GeneratorToolsetCudaCustomDir;
std::string DefaultPlatformToolset;
std::string DefaultPlatformToolsetHostArchitecture;
std::string WindowsTargetPlatformVersion;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index b4f05c7..06e1798 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -527,6 +527,13 @@ void cmVisualStudio10TargetGenerator::Generate()
}
e1.Element("TargetFrameworkTargetsVersion", targetFrameworkVer);
}
+ if (!this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString()
+ .empty()) {
+ e1.Element(
+ "CudaToolkitCustomDir",
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString() +
+ "nvcc");
+ }
}
// Disable the project upgrade prompt that is displayed the first time a
@@ -613,10 +620,17 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.SetHasElements();
if (this->GlobalGenerator->IsCudaEnabled()) {
+ auto customDir =
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
+ std::string cudaPath = customDir.empty()
+ ? "$(VCTargetsPath)\\BuildCustomizations\\"
+ : customDir +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
- this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ std::move(cudaPath) + "CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCuda() +
".props");
}
if (this->GlobalGenerator->IsMasmEnabled()) {
@@ -698,10 +712,17 @@ void cmVisualStudio10TargetGenerator::Generate()
e1.SetHasElements();
this->WriteTargetsFileReferences(e1);
if (this->GlobalGenerator->IsCudaEnabled()) {
+ auto customDir =
+ this->GlobalGenerator->GetPlatformToolsetCudaCustomDirString();
+ std::string cudaPath = customDir.empty()
+ ? "$(VCTargetsPath)\\BuildCustomizations\\"
+ : customDir +
+ "CUDAVisualStudioIntegration\\extras\\"
+ "visual_studio_integration\\MSBuildExtensions\\";
Elem(e1, "Import")
.Attribute("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\CUDA " +
- this->GlobalGenerator->GetPlatformToolsetCudaString() +
+ std::move(cudaPath) + "CUDA " +
+ this->GlobalGenerator->GetPlatformToolsetCuda() +
".targets");
}
if (this->GlobalGenerator->IsMasmEnabled()) {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 2be8bae..6cbe546 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -673,10 +673,17 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
// If an error occurs, we want to continue removing directories.
bool return_value = false;
for (auto const& arg : cmMakeRange(args).advance(2)) {
- if (cmSystemTools::FileIsDirectory(arg) &&
- !cmSystemTools::RemoveADirectory(arg)) {
- std::cerr << "Error removing directory \"" << arg << "\".\n";
- return_value = true;
+ if (cmSystemTools::FileIsDirectory(arg)) {
+ if (cmSystemTools::FileIsSymlink(arg)) {
+ if (!cmSystemTools::RemoveFile(arg)) {
+ std::cerr << "Error removing directory symlink \"" << arg
+ << "\".\n";
+ return_value = true;
+ }
+ } else if (!cmSystemTools::RemoveADirectory(arg)) {
+ std::cerr << "Error removing directory \"" << arg << "\".\n";
+ return_value = true;
+ }
}
}
return return_value;
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 79e813e..09bcdb9 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -121,8 +121,8 @@ if(KWSYS_CXX_STANDARD)
set(CMAKE_CXX_STANDARD "${KWSYS_CXX_STANDARD}")
elseif(NOT DEFINED CMAKE_CXX_STANDARD AND NOT DEFINED KWSYS_CXX_STANDARD)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
- AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"
- AND "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU"
+ AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"
+ AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU"
)
set(CMAKE_CXX_STANDARD 14)
else()
@@ -1013,7 +1013,7 @@ ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
# Disable deprecation warnings for standard C functions.
IF(MSVC OR (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "Intel" OR
- (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC"))))
+ (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC"))))
ADD_DEFINITIONS(
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_SECURE_NO_DEPRECATE
@@ -1104,7 +1104,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testConsoleBuf.cxx
)
- IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND
+ IF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
set_property(SOURCE testConsoleBuf.cxx testConsoleBufChild.cxx PROPERTY COMPILE_FLAGS /utf-8)
ENDIF()
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 36f24c7..8571477 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2169,24 +2169,24 @@ std::string SystemTools::ConvertToWindowsOutputPath(const std::string& path)
return ret;
}
+/**
+ * Append the filename from the path source to the directory name dir.
+ */
+static std::string FileInDir(const std::string& source, const std::string& dir)
+{
+ std::string new_destination = dir;
+ SystemTools::ConvertToUnixSlashes(new_destination);
+ return new_destination + '/' + SystemTools::GetFilenameName(source);
+}
+
bool SystemTools::CopyFileIfDifferent(const std::string& source,
const std::string& destination)
{
// special check for a destination that is a directory
// FilesDiffer does not handle file to directory compare
if (SystemTools::FileIsDirectory(destination)) {
- std::string new_destination = destination;
- SystemTools::ConvertToUnixSlashes(new_destination);
- new_destination += '/';
- std::string source_name = source;
- new_destination += SystemTools::GetFilenameName(source_name);
- if (SystemTools::FilesDiffer(source, new_destination)) {
- return SystemTools::CopyFileAlways(source, destination);
- } else {
- // the files are the same so the copy is done return
- // true
- return true;
- }
+ const std::string new_destination = FileInDir(source, destination);
+ return SystemTools::CopyFileIfDifferent(source, new_destination);
}
// source and destination are files so do a copy if they
// are different
@@ -2612,101 +2612,6 @@ std::string SystemTools::GetLastSystemError()
return strerror(e);
}
-#ifdef _WIN32
-
-static bool IsJunction(const std::wstring& source)
-{
-# ifdef FSCTL_GET_REPARSE_POINT
- const DWORD JUNCTION_ATTRS =
- FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
- DWORD attrs = GetFileAttributesW(source.c_str());
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- return false;
- }
- if ((attrs & JUNCTION_ATTRS) != JUNCTION_ATTRS) {
- return false;
- }
-
- // Adjust privileges so that we can succefully open junction points.
- HANDLE token;
- TOKEN_PRIVILEGES privs;
- OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
- LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &privs.Privileges[0].Luid);
- privs.PrivilegeCount = 1;
- privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
- NULL);
- CloseHandle(token);
-
- HANDLE dir = CreateFileW(
- source.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (dir == INVALID_HANDLE_VALUE) {
- return false;
- }
-
- // Query whether this is a reparse point or not.
- BYTE buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
- REPARSE_GUID_DATA_BUFFER* reparse_buffer = (REPARSE_GUID_DATA_BUFFER*)buffer;
- DWORD sentinel;
-
- BOOL success =
- DeviceIoControl(dir, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_buffer,
- MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &sentinel, NULL);
-
- CloseHandle(dir);
-
- return (success &&
- (reparse_buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT));
-# else
- return false;
-# endif
-}
-
-static bool DeleteJunction(const std::wstring& source)
-{
-# ifdef FSCTL_DELETE_REPARSE_POINT
- // Adjust privileges so that we can succefully open junction points as
- // read/write.
- HANDLE token;
- TOKEN_PRIVILEGES privs;
- OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
- LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &privs.Privileges[0].Luid);
- privs.PrivilegeCount = 1;
- privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL,
- NULL);
- CloseHandle(token);
-
- HANDLE dir = CreateFileW(
- source.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (dir == INVALID_HANDLE_VALUE) {
- return false;
- }
-
- // Set up the structure so that we can delete the junction.
- std::vector<BYTE> buffer(REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 0);
- REPARSE_GUID_DATA_BUFFER* reparse_buffer =
- (REPARSE_GUID_DATA_BUFFER*)&buffer[0];
- DWORD sentinel;
-
- reparse_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-
- BOOL success = DeviceIoControl(
- dir, FSCTL_DELETE_REPARSE_POINT, reparse_buffer,
- REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0, &sentinel, NULL);
-
- CloseHandle(dir);
-
- return !!success;
-# else
- return false;
-# endif
-}
-
-#endif
-
bool SystemTools::RemoveFile(const std::string& source)
{
#ifdef _WIN32
@@ -2728,9 +2633,7 @@ bool SystemTools::RemoveFile(const std::string& source)
SetLastError(err);
return false;
}
- if (IsJunction(ws) && DeleteJunction(ws)) {
- return true;
- }
+
const DWORD DIRECTORY_SOFT_LINK_ATTRS =
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
DWORD attrs = GetFileAttributesW(ws.c_str());
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index ffa6a29..88277de 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -999,30 +999,45 @@ static bool writeFile(const char* fileName, const char* data)
return true;
}
+static std::string readFile(const char* fileName)
+{
+ kwsys::ifstream in(fileName, std::ios::binary);
+ std::stringstream sstr;
+ sstr << in.rdbuf();
+ std::string data = sstr.str();
+ if (!in) {
+ std::cerr << "Failed to read file: " << fileName << std::endl;
+ return std::string();
+ }
+ return data;
+}
+
+struct
+{
+ const char* a;
+ const char* b;
+ bool differ;
+} diff_test_cases[] = { { "one", "one", false },
+ { "one", "two", true },
+ { "", "", false },
+ { "\n", "\r\n", false },
+ { "one\n", "one\n", false },
+ { "one\r\n", "one\n", false },
+ { "one\n", "one", false },
+ { "one\ntwo", "one\ntwo", false },
+ { "one\ntwo", "one\r\ntwo", false } };
+
static bool CheckTextFilesDiffer()
{
- struct
- {
- const char* a;
- const char* b;
- bool differ;
- } test_cases[] = { { "one", "one", false },
- { "one", "two", true },
- { "", "", false },
- { "\n", "\r\n", false },
- { "one\n", "one\n", false },
- { "one\r\n", "one\n", false },
- { "one\n", "one", false },
- { "one\ntwo", "one\ntwo", false },
- { "one\ntwo", "one\r\ntwo", false } };
- const int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+ const int num_test_cases =
+ sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
for (int i = 0; i < num_test_cases; ++i) {
- if (!writeFile("file_a", test_cases[i].a) ||
- !writeFile("file_b", test_cases[i].b)) {
+ if (!writeFile("file_a", diff_test_cases[i].a) ||
+ !writeFile("file_b", diff_test_cases[i].b)) {
return false;
}
if (kwsys::SystemTools::TextFilesDiffer("file_a", "file_b") !=
- test_cases[i].differ) {
+ diff_test_cases[i].differ) {
std::cerr << "Incorrect TextFilesDiffer result for test case " << i + 1
<< "." << std::endl;
return false;
@@ -1032,6 +1047,36 @@ static bool CheckTextFilesDiffer()
return true;
}
+static bool CheckCopyFileIfDifferent()
+{
+ bool ret = true;
+ const int num_test_cases =
+ sizeof(diff_test_cases) / sizeof(diff_test_cases[0]);
+ for (int i = 0; i < num_test_cases; ++i) {
+ if (!writeFile("file_a", diff_test_cases[i].a) ||
+ !writeFile("file_b", diff_test_cases[i].b)) {
+ return false;
+ }
+ const char* cptarget =
+ i < 4 ? TEST_SYSTEMTOOLS_BINARY_DIR "/file_b" : "file_b";
+ if (!kwsys::SystemTools::CopyFileIfDifferent("file_a", cptarget)) {
+ std::cerr << "CopyFileIfDifferent() returned false for test case "
+ << i + 1 << "." << std::endl;
+ ret = false;
+ continue;
+ }
+ std::string bdata = readFile("file_b");
+ if (diff_test_cases[i].a != bdata) {
+ std::cerr << "Incorrect CopyFileIfDifferent file contents in test case "
+ << i + 1 << "." << std::endl;
+ ret = false;
+ continue;
+ }
+ }
+
+ return ret;
+}
+
int testSystemTools(int, char* [])
{
bool res = true;
@@ -1077,5 +1122,7 @@ int testSystemTools(int, char* [])
res &= CheckTextFilesDiffer();
+ res &= CheckCopyFileIfDifferent();
+
return res ? 0 : 1;
}