diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/CPack/cmCPackGenerator.cxx | 70 | ||||
-rw-r--r-- | Source/cmFileAPICodemodel.cxx | 6 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.cxx | 58 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.h | 5 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 29 | ||||
-rw-r--r-- | Source/cmcmd.cxx | 15 | ||||
-rw-r--r-- | Source/kwsys/CMakeLists.txt | 8 | ||||
-rw-r--r-- | Source/kwsys/SystemTools.cxx | 123 | ||||
-rw-r--r-- | Source/kwsys/testSystemTools.cxx | 83 |
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; } |