diff options
90 files changed, 1160 insertions, 428 deletions
@@ -5,3 +5,6 @@ *.pyc Testing + +# Visual Studio work directory +.vs/ diff --git a/Help/command/file.rst b/Help/command/file.rst index 5e18077..43ce3d9 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -98,10 +98,10 @@ command. :: file(GLOB <variable> - [LIST_DIRECTORIES true|false] [RELATIVE <path>] + [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...]) file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS] - [LIST_DIRECTORIES true|false] [RELATIVE <path>] + [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...]) Generate a list of files that match the ``<globbing-expressions>`` and @@ -110,6 +110,11 @@ regular expressions, but much simpler. If ``RELATIVE`` flag is specified, the results will be returned as relative paths to the given path. The results will be ordered lexicographically. +If the ``CONFIGURE_DEPENDS`` flag is specified, CMake will add logic +to the main build system check target to rerun the flagged ``GLOB`` commands +at build time. If any of the outputs change, CMake will regenerate the build +system. + By default ``GLOB`` lists directories - directories are omitted in result if ``LIST_DIRECTORIES`` is set to false. @@ -118,6 +123,10 @@ By default ``GLOB`` lists directories - directories are omitted in result if your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate. + The ``CONFIGURE_DEPENDS`` flag may not work reliably on all generators, or if + a new generator is added in the future that cannot support it, projects using + it will be stuck. Even if ``CONFIGURE_DEPENDS`` works reliably, there is + still a cost to perform the check on every rebuild. Examples of globbing expressions include:: diff --git a/Help/command/install.rst b/Help/command/install.rst index eb7b07c..e9c185c 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -339,12 +339,12 @@ Installing Exports install(EXPORT <export-name> DESTINATION <dir> [NAMESPACE <namespace>] [[FILE <name>.cmake]| - [EXPORT_ANDROID_MK <name>.mk]] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [EXPORT_LINK_INTERFACE_LIBRARIES] [COMPONENT <component>] [EXCLUDE_FROM_ALL]) + install(EXPORT_ANDROID_MK <export-name> DESTINATION <dir> [...]) The ``EXPORT`` form generates and installs a CMake file containing code to import targets from the installation tree into another project. @@ -367,8 +367,9 @@ specified that does not match that given to the targets associated with included in the export but a target to which it links is not included the behavior is unspecified. -In addition to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe -used to specify an export to the android ndk build system. The Android +In addition to cmake language files, the ``EXPORT_ANDROID_MK`` mode maybe +used to specify an export to the android ndk build system. This mode +accepts the same options as the normal export mode. The Android NDK supports the use of prebuilt libraries, both static and shared. This allows cmake to build the libraries of a project and make them available to an ndk build system complete with transitive dependencies, include flags @@ -385,7 +386,7 @@ and installed by the current project. For example, the code will install the executable myexe to ``<prefix>/bin`` and code to import it in the file ``<prefix>/lib/myproj/myproj.cmake`` and -``<prefix>/lib/share/ndk-modules/Android.mk``. An outside project +``<prefix>/share/ndk-modules/Android.mk``. An outside project may load this file with the include command and reference the ``myexe`` executable from the installation tree using the imported target name ``mp_myexe`` as if the target were built in its own tree. diff --git a/Help/release/dev/glob_configure_depends.rst b/Help/release/dev/glob_configure_depends.rst new file mode 100644 index 0000000..147e44a --- /dev/null +++ b/Help/release/dev/glob_configure_depends.rst @@ -0,0 +1,6 @@ +glob_configure_depends +---------------------- + +* The :command:`file(GLOB)` and :command:`file(GLOB_RECURSE)` commands + learned a new flag ``CONFIGURE_DEPENDS`` which enables expression of + build system dependency on globbed directory's contents. diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index 6f6f349..a0e4aa9 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -557,6 +557,11 @@ else() set(c_compiler_realpath "") endif() set(CUDA_HOST_COMPILER "${c_compiler_realpath}" CACHE FILEPATH "Host side compiler used by NVCC") + elseif(MSVC AND "${CMAKE_C_COMPILER}" MATCHES "clcache") + # NVCC does not think it will work if it is passed clcache.exe as the host + # compiler, which means that builds with CC=cl.exe won't work. Best to just + # feed it whatever the actual cl.exe is as the host compiler. + set(CUDA_HOST_COMPILER "cl.exe" CACHE FILEPATH "Host side compiler used by NVCC") else() set(CUDA_HOST_COMPILER "${CMAKE_C_COMPILER}" CACHE FILEPATH "Host side compiler used by NVCC") diff --git a/Modules/FindImageMagick.cmake b/Modules/FindImageMagick.cmake index 881bff1..6d94d3b 100644 --- a/Modules/FindImageMagick.cmake +++ b/Modules/FindImageMagick.cmake @@ -104,6 +104,7 @@ function(FIND_IMAGEMAGICK_API component header) PATH_SUFFIXES ImageMagick ImageMagick-6 ImageMagick-7 DOC "Path to the ImageMagick arch-independent include dir." + NO_DEFAULT_PATH ) find_path(ImageMagick_${component}_ARCH_INCLUDE_DIR NAMES magick/magick-baseconfig.h @@ -116,6 +117,7 @@ function(FIND_IMAGEMAGICK_API component header) PATH_SUFFIXES ImageMagick ImageMagick-6 ImageMagick-7 DOC "Path to the ImageMagick arch-specific include dir." + NO_DEFAULT_PATH ) find_library(ImageMagick_${component}_LIBRARY NAMES ${ARGN} @@ -125,6 +127,7 @@ function(FIND_IMAGEMAGICK_API component header) PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/lib" DOC "Path to the ImageMagick Magick++ library." + NO_DEFAULT_PATH ) # old version have only indep dir diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake index af997ea..f2d6285 100644 --- a/Modules/FindwxWidgets.cmake +++ b/Modules/FindwxWidgets.cmake @@ -925,14 +925,16 @@ unset(_wx_lib_missing) # Check if a specific version was requested by find_package(). if(wxWidgets_FOUND) - find_file(_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) - dbg_msg("_filename: ${_filename}") + unset(_wx_filename) + find_file(_wx_filename wx/version.h PATHS ${wxWidgets_INCLUDE_DIRS} NO_DEFAULT_PATH) + dbg_msg("_wx_filename: ${_wx_filename}") - if(NOT _filename) + if(NOT _wx_filename) message(FATAL_ERROR "wxWidgets wx/version.h file not found in ${wxWidgets_INCLUDE_DIRS}.") endif() - file(READ ${_filename} _wx_version_h) + file(READ "${_wx_filename}" _wx_version_h) + unset(_wx_filename CACHE) string(REGEX REPLACE "^(.*\n)?#define +wxMAJOR_VERSION +([0-9]+).*" "\\2" wxWidgets_VERSION_MAJOR "${_wx_version_h}" ) diff --git a/Modules/MatlabTestsRedirect.cmake b/Modules/MatlabTestsRedirect.cmake index 64d580d..fc36fc3 100644 --- a/Modules/MatlabTestsRedirect.cmake +++ b/Modules/MatlabTestsRedirect.cmake @@ -55,11 +55,12 @@ endif() if(no_unittest_framework) - set(unittest_to_run "try, ${unittest_file_to_run_name}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)") + set(unittest_to_run "${unittest_file_to_run_name}") endif() +set(command_to_run "try, ${unittest_to_run}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)") set(Matlab_SCRIPT_TO_RUN - "addpath(${concat_string}); ${cmd_to_run_before_test}; ${unittest_to_run}" + "addpath(${concat_string}); ${cmd_to_run_before_test}; ${command_to_run}" ) # if the working directory is not specified then default # to the output_directory because the log file will go there diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 5f9afc1..8713cd8 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -28,7 +28,11 @@ Defines the following command for use with ``SWIG``: those targets can be used with any command expecting a target (e.g. :command:`target_link_libraries`). - The arguments are: + .. note:: + + For multi-config generators, this module does not support + configuration-specific files generated by ``SWIG``. All build + configurations must result in the same generated source file. ``TYPE`` ``SHARED``, ``MODULE`` and ``STATIC`` have the same semantic as for the @@ -297,7 +301,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) # handle various swig compile flags properties get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES) if (include_directories) - list (APPEND swig_source_file_flags "-I$<JOIN:${include_directories},$<SEMICOLON>-I>") + list (APPEND swig_source_file_flags "$<$<BOOL:${include_directories}>:-I$<JOIN:${include_directories},$<SEMICOLON>-I>>") endif() set (property "$<TARGET_PROPERTY:${name},SWIG_INCLUDE_DIRECTORIES>") list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>") @@ -306,7 +310,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:${property},$<SEMICOLON>-D>>") get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS) if (compile_definitions) - list (APPEND swig_source_file_flags "-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>") + list (APPEND swig_source_file_flags "$<$<BOOL:${compile_definitions}>:-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>>") endif() list (APPEND swig_source_file_flags "$<TARGET_PROPERTY:${name},SWIG_COMPILE_OPTIONS>") @@ -348,7 +352,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) list (REMOVE_DUPLICATES cmake_include_directories) set (swig_include_dirs) if (cmake_include_directories) - set (swig_include_dirs "-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>") + set (swig_include_dirs "$<$<BOOL:${cmake_include_directories}>:-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>>") endif() set(swig_special_flags) @@ -374,7 +378,7 @@ function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) list (APPEND swig_dependencies ${file_depends}) endif() - if (UseSWIG_MODULE_VERSION VERSION_EQUAL 2) + if (UseSWIG_MODULE_VERSION VERSION_GREATER 1) # as part of custom command, start by removing old generated files # to ensure obsolete files do not stay set (swig_cleanup_command COMMAND "${CMAKE_COMMAND}" -E remove_directory "${outdir}") @@ -501,7 +505,7 @@ function(SWIG_ADD_LIBRARY name) if (CMAKE_SWIG_OUTDIR) set (outputdir "${CMAKE_SWIG_OUTDIR}") else() - if (UseSWIG_MODULE_VERSION VERSION_EQUAL 2) + if (UseSWIG_MODULE_VERSION VERSION_GREATER 1) set (outputdir "${workingdir}/${_SAM_LANGUAGE}.files") else() set (outputdir "${CMAKE_CURRENT_BINARY_DIR}") @@ -550,7 +554,7 @@ function(SWIG_ADD_LIBRARY name) endforeach() set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps}) - if (UseSWIG_MODULE_VERSION VERSION_EQUAL 2) + if (UseSWIG_MODULE_VERSION VERSION_GREATER 1) set_property (DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${outputdir}") endif() diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index e547356..e23b070 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -246,6 +246,8 @@ set(SRCS cmGlobalGeneratorFactory.h cmGlobalUnixMakefileGenerator3.cxx cmGlobalUnixMakefileGenerator3.h + cmGlobVerificationManager.cxx + cmGlobVerificationManager.h cmGraphAdjacencyList.h cmGraphVizWriter.cxx cmGraphVizWriter.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index a173a1e..593c139 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 11) -set(CMake_VERSION_PATCH 20180405) +set(CMake_VERSION_PATCH 20180412) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 507a10c..b6ff38b 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -350,16 +350,16 @@ int main(int argc, char const* const* argv) } if (parsed) { cpackGenerator = generators.NewGenerator(gen); - if (!cpackGenerator) { + if (cpackGenerator) { + cpackGenerator->SetTrace(trace); + cpackGenerator->SetTraceExpand(traceExpand); + } else { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot initialize CPack generator: " << gen << std::endl); parsed = 0; } - cpackGenerator->SetTrace(trace); - cpackGenerator->SetTraceExpand(traceExpand); - if (parsed && !cpackGenerator->Initialize(gen, mf)) { cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot initialize the generator " << gen diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h index 427a392..86d9489 100644 --- a/Source/CTest/cmCTestCurl.h +++ b/Source/CTest/cmCTestCurl.h @@ -16,7 +16,7 @@ class cmCTestCurl public: cmCTestCurl(cmCTest*); ~cmCTestCurl(); - bool UploadFile(std::string const& url, std::string const& file, + bool UploadFile(std::string const& local_file, std::string const& url, std::string const& fields, std::string& response); bool HttpRequest(std::string const& url, std::string const& fields, std::string& response); diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index 3380b78..244dc1c 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -311,7 +311,7 @@ struct RemoveDuplicatesAPI<Range, T*> template <typename Range> typename Range::const_iterator cmRemoveDuplicates(Range& r) { - typedef typename ContainerAlgorithms::RemoveDuplicatesAPI<Range> API; + typedef ContainerAlgorithms::RemoveDuplicatesAPI<Range> API; typedef typename API::value_type T; std::vector<T> unique; unique.reserve(r.size()); diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 85ac985..13407e5 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -8,6 +8,7 @@ #include <sstream> #include <stdio.h> #include <string.h> +#include <string> #include "cmGeneratedFileStream.h" #include "cmMessenger.h" @@ -243,19 +244,18 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) } // before writing the cache, update the version numbers // to the - char temp[1024]; - sprintf(temp, "%d", cmVersion::GetMinorVersion()); - this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", temp, - "Minor version of cmake used to create the " + this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", + std::to_string(cmVersion::GetMajorVersion()).c_str(), + "Major version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); - sprintf(temp, "%d", cmVersion::GetMajorVersion()); - this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", temp, - "Major version of cmake used to create the " + this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", + std::to_string(cmVersion::GetMinorVersion()).c_str(), + "Minor version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); - sprintf(temp, "%d", cmVersion::GetPatchVersion()); - this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", temp, + this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", + std::to_string(cmVersion::GetPatchVersion()).c_str(), "Patch version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index bf314bd..ccb4f88 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -101,10 +101,11 @@ const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) // not been "cleared"/initialized with a set(foo ) call if (this->WarnUninitialized && !this->Makefile->VariableInitialized(var)) { if (this->CheckSystemVars || - cmSystemTools::IsSubDirectory(this->FileName, - this->Makefile->GetHomeDirectory()) || - cmSystemTools::IsSubDirectory( - this->FileName, this->Makefile->GetHomeOutputDirectory())) { + (this->FileName && + (cmSystemTools::IsSubDirectory( + this->FileName, this->Makefile->GetHomeDirectory()) || + cmSystemTools::IsSubDirectory( + this->FileName, this->Makefile->GetHomeOutputDirectory())))) { std::ostringstream msg; msg << "uninitialized variable \'" << var << "\'"; this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h index cff934b..5603c50 100644 --- a/Source/cmConfigureFileCommand.h +++ b/Source/cmConfigureFileCommand.h @@ -32,9 +32,9 @@ private: std::string InputFile; std::string OutputFile; - bool CopyOnly; - bool EscapeQuotes; - bool AtOnly; + bool CopyOnly = false; + bool EscapeQuotes = false; + bool AtOnly = false; }; #endif diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 6f35a54..ae714a6 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -46,7 +46,7 @@ protected: std::string BinaryDirectory; std::string OutputFile; std::string FindErrorMessage; - bool SrcFileSignature; + bool SrcFileSignature = false; private: std::vector<std::string> WarnCMP0067; diff --git a/Source/cmExportLibraryDependenciesCommand.h b/Source/cmExportLibraryDependenciesCommand.h index bf5e9bc..8414866 100644 --- a/Source/cmExportLibraryDependenciesCommand.h +++ b/Source/cmExportLibraryDependenciesCommand.h @@ -27,7 +27,7 @@ public: private: std::string Filename; - bool Append; + bool Append = false; void ConstFinalPass() const; }; diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h index 5cc6442..d48abca 100644 --- a/Source/cmExternalMakefileProjectGenerator.h +++ b/Source/cmExternalMakefileProjectGenerator.h @@ -62,7 +62,7 @@ protected: ///! Contains the names of the global generators support by this generator. std::vector<std::string> SupportedGlobalGenerators; ///! the global generator which creates the makefiles - const cmGlobalGenerator* GlobalGenerator; + const cmGlobalGenerator* GlobalGenerator = nullptr; std::string Name; }; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 90b943b..0d31070 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -758,7 +758,11 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, } std::vector<std::string> files; + bool configureDepends = false; + bool warnConfigureLate = false; bool warnFollowedSymlinks = false; + const cmake::WorkingMode workingMode = + this->Makefile->GetCMakeInstance()->GetWorkingMode(); while (i != args.end()) { if (*i == "LIST_DIRECTORIES") { ++i; @@ -807,6 +811,27 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, this->SetError("GLOB requires a glob expression after the directory."); return false; } + } else if (*i == "CONFIGURE_DEPENDS") { + // Generated build system depends on glob results + if (!configureDepends && warnConfigureLate) { + this->Makefile->IssueMessage( + cmake::AUTHOR_WARNING, + "CONFIGURE_DEPENDS flag was given after a glob expression was " + "already evaluated."); + } + if (workingMode != cmake::NORMAL_MODE) { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "CONFIGURE_DEPENDS is invalid for script and find package modes."); + return false; + } + configureDepends = true; + ++i; + if (i == args.end()) { + this->SetError( + "GLOB requires a glob expression after CONFIGURE_DEPENDS."); + return false; + } } else { std::string expr = *i; if (!cmsys::SystemTools::FileIsFullPath(*i)) { @@ -849,6 +874,19 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, std::vector<std::string>& foundFiles = g.GetFiles(); files.insert(files.end(), foundFiles.begin(), foundFiles.end()); + + if (configureDepends) { + std::sort(foundFiles.begin(), foundFiles.end()); + foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()), + foundFiles.end()); + this->Makefile->GetCMakeInstance()->AddGlobCacheEntry( + recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()), + (recurse ? g.GetRecurseThroughSymlinks() : false), + (g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable, + this->Makefile->GetBacktrace()); + } else { + warnConfigureLate = true; + } ++i; } } diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx new file mode 100644 index 0000000..e23b6ea --- /dev/null +++ b/Source/cmGlobVerificationManager.cxx @@ -0,0 +1,172 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmGlobVerificationManager.h" + +#include "cmsys/FStream.hxx" +#include <sstream> + +#include "cmGeneratedFileStream.h" +#include "cmListFileCache.h" +#include "cmSystemTools.h" +#include "cmVersion.h" +#include "cmake.h" + +bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path) +{ + if (this->Cache.empty()) { + return true; + } + + std::string scriptFile = path; + scriptFile += cmake::GetCMakeFilesDirectory(); + std::string stampFile = scriptFile; + cmSystemTools::MakeDirectory(scriptFile); + scriptFile += "/VerifyGlobs.cmake"; + stampFile += "/cmake.verify_globs"; + cmGeneratedFileStream verifyScriptFile(scriptFile.c_str()); + verifyScriptFile.SetCopyIfDifferent(true); + if (!verifyScriptFile) { + cmSystemTools::Error("Unable to open verification script file for save. ", + scriptFile.c_str()); + cmSystemTools::ReportLastSystemError(""); + return false; + } + + verifyScriptFile << std::boolalpha; + verifyScriptFile << "# CMAKE generated file: DO NOT EDIT!\n" + << "# Generated by CMake Version " + << cmVersion::GetMajorVersion() << "." + << cmVersion::GetMinorVersion() << "\n"; + + for (auto const& i : this->Cache) { + CacheEntryKey k = std::get<0>(i); + CacheEntryValue v = std::get<1>(i); + + if (!v.Initialized) { + continue; + } + + verifyScriptFile << "\n"; + + for (auto const& bt : v.Backtraces) { + verifyScriptFile << "# " << std::get<0>(bt); + std::get<1>(bt).PrintTitle(verifyScriptFile); + verifyScriptFile << "\n"; + } + + k.PrintGlobCommand(verifyScriptFile, "NEW_GLOB"); + verifyScriptFile << "\n"; + + verifyScriptFile << "set(OLD_GLOB\n"; + for (const std::string& file : v.Files) { + verifyScriptFile << " \"" << file << "\"\n"; + } + verifyScriptFile << " )\n"; + + verifyScriptFile << "if(NOT \"${NEW_GLOB}\" STREQUAL \"${OLD_GLOB}\")\n" + << " message(\"-- GLOB mismatch!\")\n" + << " file(TOUCH_NOCREATE \"" << stampFile << "\")\n" + << "endif()\n"; + } + verifyScriptFile.Close(); + + cmsys::ofstream verifyStampFile(stampFile.c_str()); + if (!verifyStampFile) { + cmSystemTools::Error("Unable to open verification stamp file for write. ", + stampFile.c_str()); + return false; + } + verifyStampFile << "# This file is generated by CMake for checking of the " + "VerifyGlobs.cmake file\n"; + this->VerifyScript = scriptFile; + this->VerifyStamp = stampFile; + return true; +} + +bool cmGlobVerificationManager::DoWriteVerifyTarget() const +{ + return !this->VerifyScript.empty() && !this->VerifyStamp.empty(); +} + +bool cmGlobVerificationManager::CacheEntryKey::operator<( + const CacheEntryKey& r) const +{ + if (this->Recurse < r.Recurse) { + return true; + } + if (this->Recurse > r.Recurse) { + return false; + } + if (this->ListDirectories < r.ListDirectories) { + return true; + } + if (this->ListDirectories > r.ListDirectories) { + return false; + } + if (this->FollowSymlinks < r.FollowSymlinks) { + return true; + } + if (this->FollowSymlinks > r.FollowSymlinks) { + return false; + } + if (this->Relative < r.Relative) { + return true; + } + if (this->Relative > r.Relative) { + return false; + } + if (this->Expression < r.Expression) { + return true; + } + if (this->Expression > r.Expression) { + return false; + } + return false; +} + +void cmGlobVerificationManager::CacheEntryKey::PrintGlobCommand( + std::ostream& out, const std::string& cmdVar) +{ + out << "file(GLOB" << (this->Recurse ? "_RECURSE " : " "); + out << cmdVar << " "; + if (this->Recurse && this->FollowSymlinks) { + out << "FOLLOW_SYMLINKS "; + } + out << "LIST_DIRECTORIES " << this->ListDirectories << " "; + if (!this->Relative.empty()) { + out << "RELATIVE \"" << this->Relative << "\" "; + } + out << "\"" << this->Expression << "\")"; +} + +void cmGlobVerificationManager::AddCacheEntry( + const bool recurse, const bool listDirectories, const bool followSymlinks, + const std::string& relative, const std::string& expression, + const std::vector<std::string>& files, const std::string& variable, + const cmListFileBacktrace& backtrace) +{ + CacheEntryKey key = CacheEntryKey(recurse, listDirectories, followSymlinks, + relative, expression); + CacheEntryValue& value = this->Cache[key]; + if (!value.Initialized) { + value.Files = files; + value.Initialized = true; + value.Backtraces.emplace_back(variable, backtrace); + } else if (value.Initialized && value.Files != files) { + std::ostringstream message; + message << std::boolalpha; + message << "The glob expression\n"; + key.PrintGlobCommand(message, variable); + backtrace.PrintTitle(message); + message << "\nwas already present in the glob cache but the directory\n" + "contents have changed during the configuration run.\n"; + message << "Matching glob expressions:"; + for (auto const& bt : value.Backtraces) { + message << "\n " << std::get<0>(bt); + std::get<1>(bt).PrintTitle(message); + } + cmSystemTools::Error(message.str().c_str()); + } else { + value.Backtraces.emplace_back(variable, backtrace); + } +} diff --git a/Source/cmGlobVerificationManager.h b/Source/cmGlobVerificationManager.h new file mode 100644 index 0000000..4508602 --- /dev/null +++ b/Source/cmGlobVerificationManager.h @@ -0,0 +1,89 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmGlobVerificationManager_h +#define cmGlobVerificationManager_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmListFileCache.h" + +#include <iosfwd> +#include <map> +#include <string> +#include <utility> +#include <vector> + +/** \class cmGlobVerificationManager + * \brief Class for expressing build-time dependencies on glob expressions. + * + * Generates a CMake script which verifies glob outputs during prebuild. + * + */ +class cmGlobVerificationManager +{ +public: + cmGlobVerificationManager() {} + +protected: + ///! Save verification script for given makefile. + ///! Saves to output <path>/<CMakeFilesDirectory>/VerifyGlobs.cmake + bool SaveVerificationScript(const std::string& path); + + ///! Add an entry into the glob cache + void AddCacheEntry(bool recurse, bool listDirectories, bool followSymlinks, + const std::string& relative, + const std::string& expression, + const std::vector<std::string>& files, + const std::string& variable, + const cmListFileBacktrace& bt); + + ///! Check targets should be written in generated build system. + bool DoWriteVerifyTarget() const; + + ///! Get the paths to the generated script and stamp files + std::string const& GetVerifyScript() const { return this->VerifyScript; } + std::string const& GetVerifyStamp() const { return this->VerifyStamp; } + +private: + struct CacheEntryKey + { + const bool Recurse; + const bool ListDirectories; + const bool FollowSymlinks; + const std::string Relative; + const std::string Expression; + CacheEntryKey(const bool rec, const bool l, const bool s, + const std::string& rel, const std::string& e) + : Recurse(rec) + , ListDirectories(l) + , FollowSymlinks(s) + , Relative(rel) + , Expression(e) + { + } + bool operator<(const CacheEntryKey& r) const; + void PrintGlobCommand(std::ostream& out, const std::string& cmdVar); + }; + + struct CacheEntryValue + { + bool Initialized; + std::vector<std::string> Files; + std::vector<std::pair<std::string, cmListFileBacktrace>> Backtraces; + CacheEntryValue() + : Initialized(false) + { + } + }; + + typedef std::map<CacheEntryKey, CacheEntryValue> CacheEntryMap; + CacheEntryMap Cache; + std::string VerifyScript; + std::string VerifyStamp; + + // Only cmState should be able to add cache values. + // cmGlobVerificationManager should never be used directly. + friend class cmState; // allow access to add cache values +}; + +#endif diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 55a403e..d562df7 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -475,6 +475,7 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) , PolicyCMP0058(cmPolicies::WARN) , NinjaSupportsConsolePool(false) , NinjaSupportsImplicitOuts(false) + , NinjaSupportsManifestRestat(false) , NinjaSupportsDyndeps(0) { #ifdef _WIN32 @@ -597,6 +598,9 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsImplicitOuts = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), this->RequiredNinjaVersionForImplicitOuts().c_str()); + this->NinjaSupportsManifestRestat = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForManifestRestat().c_str()); { // Our ninja branch adds ".dyndep-#" to its version number, // where '#' is a feature-specific version number. Extract it. @@ -1361,6 +1365,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) /*generator=*/true); cmNinjaDeps implicitDeps; + cmNinjaDeps explicitDeps; for (cmLocalGenerator* localGen : this->LocalGenerators) { std::vector<std::string> const& lf = localGen->GetMakefile()->GetListFiles(); @@ -1370,10 +1375,6 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) } implicitDeps.push_back(this->CMakeCacheFile); - std::sort(implicitDeps.begin(), implicitDeps.end()); - implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()), - implicitDeps.end()); - cmNinjaVars variables; // Use 'console' pool to get non buffered output of the CMake re-run call // Available since Ninja 1.5 @@ -1381,12 +1382,71 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) variables["pool"] = "console"; } + cmake* cm = this->GetCMakeInstance(); + if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) { + std::ostringstream verify_cmd; + verify_cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), + cmOutputConverter::SHELL) + << " -P " + << lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL); + + WriteRule(*this->RulesFileStream, "VERIFY_GLOBS", verify_cmd.str(), + "Re-checking globbed directories...", + "Rule for re-checking globbed directories.", + /*depfile=*/"", + /*deptype=*/"", + /*rspfile=*/"", + /*rspcontent*/ "", + /*restat=*/"", + /*generator=*/true); + + std::string verifyForce = cm->GetGlobVerifyScript() + "_force"; + cmNinjaDeps verifyForceDeps(1, this->NinjaOutputPath(verifyForce)); + + this->WritePhonyBuild(os, "Phony target to force glob verification run.", + verifyForceDeps, cmNinjaDeps()); + + variables["restat"] = "1"; + std::string const verifyScriptFile = + this->NinjaOutputPath(cm->GetGlobVerifyScript()); + std::string const verifyStampFile = + this->NinjaOutputPath(cm->GetGlobVerifyStamp()); + this->WriteBuild(os, + "Re-run CMake to check if globbed directories changed.", + "VERIFY_GLOBS", + /*outputs=*/cmNinjaDeps(1, verifyStampFile), + /*implicitOuts=*/cmNinjaDeps(), + /*explicitDeps=*/cmNinjaDeps(), + /*implicitDeps=*/verifyForceDeps, + /*orderOnlyDeps=*/cmNinjaDeps(), variables); + + variables.erase("restat"); + implicitDeps.push_back(verifyScriptFile); + explicitDeps.push_back(verifyStampFile); + } else if (!this->SupportsManifestRestat() && + cm->DoWriteGlobVerifyTarget()) { + std::ostringstream msg; + msg << "The detected version of Ninja:\n" + << " " << this->NinjaVersion << "\n" + << "is less than the version of Ninja required by CMake for adding " + "restat dependencies to the build.ninja manifest regeneration " + "target:\n" + << " " << this->RequiredNinjaVersionForManifestRestat() << "\n"; + msg << "Any pre-check scripts, such as those generated for file(GLOB " + "CONFIGURE_DEPENDS), will not be run by Ninja."; + this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); + } + + std::sort(implicitDeps.begin(), implicitDeps.end()); + implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()), + implicitDeps.end()); + std::string const ninjaBuildFile = this->NinjaOutputPath(NINJA_BUILD_FILE); this->WriteBuild(os, "Re-run CMake if any of its inputs changed.", "RERUN_CMAKE", /*outputs=*/cmNinjaDeps(1, ninjaBuildFile), - /*implicitOuts=*/cmNinjaDeps(), - /*explicitDeps=*/cmNinjaDeps(), implicitDeps, + /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, /*orderOnlyDeps=*/cmNinjaDeps(), variables); cmNinjaDeps missingInputs; @@ -1419,6 +1479,11 @@ bool cmGlobalNinjaGenerator::SupportsImplicitOuts() const return this->NinjaSupportsImplicitOuts; } +bool cmGlobalNinjaGenerator::SupportsManifestRestat() const +{ + return this->NinjaSupportsManifestRestat; +} + void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) { WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean", diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 7f80d08..a779919 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -346,8 +346,10 @@ public: static std::string RequiredNinjaVersion() { return "1.3"; } static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; } static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; } + static std::string RequiredNinjaVersionForManifestRestat() { return "1.8"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; + bool SupportsManifestRestat() const; std::string NinjaOutputPath(std::string const& path) const; bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); } @@ -460,6 +462,7 @@ private: std::string NinjaVersion; bool NinjaSupportsConsolePool; bool NinjaSupportsImplicitOuts; + bool NinjaSupportsManifestRestat; unsigned long NinjaSupportsDyndeps; private: diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index c92df55..a005885 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -301,6 +301,13 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() lfiles.insert(lfiles.end(), lg->GetMakefile()->GetListFiles().begin(), lg->GetMakefile()->GetListFiles().end()); } + + cmake* cm = this->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + lfiles.push_back(cm->GetGlobVerifyScript()); + lfiles.push_back(cm->GetGlobVerifyStamp()); + } + // Sort the list and remove duplicates. std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>()); #if !defined(__VMS) // The Compaq STL on VMS crashes, so accept duplicates. diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index ad72f5e..117d051 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -87,18 +87,18 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() { // Add a special target on which all other targets depend that // checks the build system and optionally re-runs CMake. - const char* no_working_directory = 0; + // Skip the target if no regeneration is to be done. + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + return false; + } + + const char* no_working_directory = nullptr; std::vector<std::string> no_depends; std::vector<cmLocalGenerator*> const& generators = this->LocalGenerators; cmLocalVisualStudio7Generator* lg = static_cast<cmLocalVisualStudio7Generator*>(generators[0]); cmMakefile* mf = lg->GetMakefile(); - // Skip the target if no regeneration is to be done. - if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { - return false; - } - cmCustomCommandLines noCommandLines; cmTarget* tgt = mf->AddUtilityCommand( CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator, @@ -144,6 +144,30 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.insert(listFiles.end(), lmf->GetListFiles().begin(), lmf->GetListFiles().end()); } + + // Add a custom prebuild target to run the VerifyGlobs script. + cmake* cm = this->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + cmCustomCommandLine verifyCommandLine; + verifyCommandLine.push_back(cmSystemTools::GetCMakeCommand()); + verifyCommandLine.push_back("-P"); + verifyCommandLine.push_back(cm->GetGlobVerifyScript()); + cmCustomCommandLines verifyCommandLines; + verifyCommandLines.push_back(verifyCommandLine); + std::vector<std::string> byproducts; + byproducts.push_back(cm->GetGlobVerifyStamp()); + + mf->AddCustomCommandToTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, byproducts, + no_depends, verifyCommandLines, + cmTarget::PRE_BUILD, "Checking File Globs", + no_working_directory, false); + + // Ensure ZERO_CHECK always runs in Visual Studio using MSBuild, + // otherwise the prebuild command will not be run. + tgt->SetProperty("VS_GLOBAL_DisableFastUpToDateCheck", "true"); + listFiles.push_back(cm->GetGlobVerifyStamp()); + } + // Sort the list of input files and remove duplicates. std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); std::vector<std::string>::iterator new_end = @@ -151,8 +175,6 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() listFiles.erase(new_end, listFiles.end()); // Create a rule to re-run CMake. - std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash(); - stampName += "generate.stamp"; cmCustomCommandLine commandLine; commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string argH = "-H"; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index f8597af..df671c2 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -537,6 +537,12 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( std::vector<std::string>::iterator new_end = std::unique(lfiles.begin(), lfiles.end()); lfiles.erase(new_end, lfiles.end()); + + cmake* cm = this->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + lfiles.emplace_back(cm->GetGlobVerifyStamp()); + } + this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory(); this->CurrentReRunCMakeMakefile += "/CMakeScripts"; cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str()); @@ -555,14 +561,28 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard " << this->ConvertToRelativeForMake(lfile) << "))\n"; } + makefileStream << "\n"; std::string checkCache = root->GetBinaryDirectory(); checkCache += "/"; checkCache += cmake::GetCMakeFilesDirectoryPostSlash(); checkCache += "cmake.check_cache"; - makefileStream << "\n" - << this->ConvertToRelativeForMake(checkCache) + if (cm->DoWriteGlobVerifyTarget()) { + makefileStream << ".NOTPARALLEL:\n\n"; + makefileStream << ".PHONY: all VERIFY_GLOBS\n\n"; + makefileStream << "all: VERIFY_GLOBS " + << this->ConvertToRelativeForMake(checkCache) << "\n\n"; + makefileStream << "VERIFY_GLOBS:\n"; + makefileStream << "\t" + << this->ConvertToRelativeForMake( + cmSystemTools::GetCMakeCommand()) + << " -P " + << this->ConvertToRelativeForMake(cm->GetGlobVerifyScript()) + << "\n\n"; + } + + makefileStream << this->ConvertToRelativeForMake(checkCache) << ": $(TARGETS)\n"; makefileStream << "\t" << this->ConvertToRelativeForMake( diff --git a/Source/cmInstallFilesCommand.h b/Source/cmInstallFilesCommand.h index 19f2559..a52f45e 100644 --- a/Source/cmInstallFilesCommand.h +++ b/Source/cmInstallFilesCommand.h @@ -48,7 +48,7 @@ protected: private: std::vector<std::string> FinalArgs; - bool IsFilesForm; + bool IsFilesForm = false; std::string Destination; std::vector<std::string> Files; }; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index c1af92f..c714299 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -197,6 +197,16 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool(); } + // The Ninja generator writes rules which require support for restat + // when rebuilding build.ninja manifest (>= 1.8) + if (this->GetGlobalNinjaGenerator()->SupportsManifestRestat() && + this->GetCMakeInstance()->DoWriteGlobVerifyTarget() && + !this->GetGlobalNinjaGenerator()->GlobalSettingIsOn( + "CMAKE_SUPPRESS_REGENERATION")) { + requiredVersion = + this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForManifestRestat(); + } + cmGlobalNinjaGenerator::WriteComment( os, "Minimal version of Ninja required by this file"); os << "ninja_required_version = " << requiredVersion << std::endl diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index c9237a8..cf2a7b9 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -763,6 +763,14 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( if (!this->GlobalGenerator->GlobalSettingIsOn( "CMAKE_SUPPRESS_REGENERATION")) { // Build command to run CMake to check if anything needs regenerating. + std::vector<std::string> commands; + cmake* cm = this->GlobalGenerator->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + std::string rescanRule = "$(CMAKE_COMMAND) -P "; + rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL); + commands.push_back(rescanRule); + } std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); cmakefileName += "Makefile.cmake"; std::string runRule = @@ -773,7 +781,6 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( runRule += " 0"; std::vector<std::string> no_depends; - std::vector<std::string> commands; commands.push_back(std::move(runRule)); if (!this->IsRootMakefile()) { this->CreateCDCommand(commands, this->GetBinaryDirectory(), @@ -1666,6 +1673,13 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( // write the depend rule, really a recompute depends rule depends.clear(); commands.clear(); + cmake* cm = this->GlobalGenerator->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + std::string rescanRule = "$(CMAKE_COMMAND) -P "; + rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(), + cmOutputConverter::SHELL); + commands.push_back(rescanRule); + } std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); cmakefileName += "Makefile.cmake"; { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 91ee09f..acb5921 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -160,10 +160,21 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() depName += ".depend"; cmsys::ofstream depFile(depName.c_str()); depFile << "# CMake generation dependency list for this directory.\n"; - std::vector<std::string> const& listFiles = this->Makefile->GetListFiles(); - for (std::vector<std::string>::const_iterator lf = listFiles.begin(); - lf != listFiles.end(); ++lf) { - depFile << *lf << std::endl; + + std::vector<std::string> listFiles(this->Makefile->GetListFiles()); + cmake* cm = this->GlobalGenerator->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + listFiles.push_back(cm->GetGlobVerifyStamp()); + } + + // Sort the list of input files and remove duplicates. + std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); + std::vector<std::string>::iterator new_end = + std::unique(listFiles.begin(), listFiles.end()); + listFiles.erase(new_end, listFiles.end()); + + for (const std::string& lf : listFiles) { + depFile << lf << "\n"; } } @@ -228,6 +239,18 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() return nullptr; } + std::vector<std::string> listFiles = this->Makefile->GetListFiles(); + cmake* cm = this->GlobalGenerator->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + listFiles.push_back(cm->GetGlobVerifyStamp()); + } + + // Sort the list of input files and remove duplicates. + std::sort(listFiles.begin(), listFiles.end(), std::less<std::string>()); + std::vector<std::string>::iterator new_end = + std::unique(listFiles.begin(), listFiles.end()); + listFiles.erase(new_end, listFiles.end()); + std::string stampName = this->GetCurrentBinaryDirectory(); stampName += "/"; stampName += cmake::GetCMakeFilesDirectoryPostSlash(); @@ -245,17 +268,14 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() commandLine.push_back(args); commandLine.push_back("--check-stamp-file"); commandLine.push_back(stampName); - - std::vector<std::string> const& listFiles = this->Makefile->GetListFiles(); - cmCustomCommandLines commandLines; commandLines.push_back(commandLine); const char* no_working_directory = 0; std::string fullpathStampName = cmSystemTools::CollapseFullPath(stampName.c_str()); this->Makefile->AddCustomCommandToOutput( - fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines, - comment.c_str(), no_working_directory, true, false); + fullpathStampName, listFiles, makefileIn, commandLines, comment.c_str(), + no_working_directory, true, false); if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) { // Finalize the source file path now since we're adding this after // the generator validated all project-named sources. diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index 07943e3..6f4b930 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -93,7 +93,7 @@ bool cmMacroHelperCommand::InvokeInitialPass( argVs.reserve(expandedArgs.size()); char argvName[60]; for (unsigned int j = 0; j < expandedArgs.size(); ++j) { - sprintf(argvName, "${ARGV%i}", j); + sprintf(argvName, "${ARGV%u}", j); argVs.push_back(argvName); } // Invoke all the functions that were collected in the block. diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 3ecd7eb..87cfc3b 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1836,12 +1836,10 @@ void cmMakefile::AddGlobalLinkInformation(cmTarget& target) std::vector<std::string> linkDirs; cmSystemTools::ExpandListArgument(linkDirsProp, linkDirs); - for (std::string const& linkDir : linkDirs) { - std::string newdir = linkDir; - // remove trailing slashes - if (*linkDir.rbegin() == '/') { - newdir = linkDir.substr(0, linkDir.size() - 1); - } + for (std::string& linkDir : linkDirs) { + // Sanitize the path the same way the link_directories command does + // in case projects set the LINK_DIRECTORIES property directly. + cmSystemTools::ConvertToUnixSlashes(linkDir); target.AddLinkDirectory(linkDir); } } @@ -2705,10 +2703,11 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( if (this->GetCMakeInstance()->GetWarnUninitialized() && !this->VariableInitialized(lookup)) { if (this->CheckSystemVars || - cmSystemTools::IsSubDirectory(filename, - this->GetHomeDirectory()) || - cmSystemTools::IsSubDirectory( - filename, this->GetHomeOutputDirectory())) { + (filename && + (cmSystemTools::IsSubDirectory(filename, + this->GetHomeDirectory()) || + cmSystemTools::IsSubDirectory( + filename, this->GetHomeOutputDirectory())))) { std::ostringstream msg; msg << "uninitialized variable \'" << lookup << "\'"; this->IssueMessage(cmake::AUTHOR_WARNING, msg.str()); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index fa7d95a..ddb1d54 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -445,72 +445,18 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) cmMakefile* mf = this->GetMakefile(); std::string flags = "$FLAGS"; - std::string rspfile; - std::string rspcontent; + std::string responseFlag; bool const lang_supports_response = !(lang == "RC" || lang == "CUDA"); if (lang_supports_response && this->ForceResponseFile()) { std::string const responseFlagVar = "CMAKE_" + lang + "_RESPONSE_FILE_FLAG"; - std::string responseFlag = - this->Makefile->GetSafeDefinition(responseFlagVar); + responseFlag = this->Makefile->GetSafeDefinition(responseFlagVar); if (responseFlag.empty()) { responseFlag = "@"; } - rspfile = "$RSP_FILE"; - responseFlag += rspfile; - rspcontent = " $DEFINES $INCLUDES $FLAGS"; - flags = std::move(responseFlag); - vars.Defines = ""; - vars.Includes = ""; - } - - // Tell ninja dependency format so all deps can be loaded into a database - std::string deptype; - std::string depfile; - std::string cldeps; - if (explicitPP) { - // The explicit preprocessing step will handle dependency scanning. - } else if (this->NeedDepTypeMSVC(lang)) { - deptype = "msvc"; - depfile.clear(); - flags += " /showIncludes"; - } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) { - // For the MS resource compiler we need cmcldeps, but skip dependencies - // for source-file try_compile cases because they are always fresh. - if (!mf->GetIsSourceFileTryCompile()) { - deptype = "gcc"; - depfile = "$DEP_FILE"; - const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER") - ? mf->GetSafeDefinition("CMAKE_C_COMPILER") - : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); - cldeps = "\""; - cldeps += cmSystemTools::GetCMClDepsCommand(); - cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \""; - cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); - cldeps += "\" \"" + cl + "\" "; - } - } else { - deptype = "gcc"; - const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang); - if (langdeptype) { - deptype = langdeptype; - } - depfile = "$DEP_FILE"; - const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang; - std::string depfileFlags = mf->GetSafeDefinition(flagsName); - if (!depfileFlags.empty()) { - cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE"); - cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out"); - cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>", - mf->GetDefinition("CMAKE_C_COMPILER")); - flags += " " + depfileFlags; - } } - vars.Flags = flags.c_str(); - vars.DependencyFile = depfile.c_str(); - std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander( this->GetLocalGenerator()->CreateRulePlaceholderExpander()); @@ -550,7 +496,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) vars.Source = "$in"; // Preprocessing and compilation use the same flags. - ppVars.Flags = vars.Flags; + std::string ppFlags = flags; // Move preprocessor definitions to the preprocessor rule. ppVars.Defines = vars.Defines; @@ -560,6 +506,20 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // compilation rule still needs them for the INCLUDE directive. ppVars.Includes = vars.Includes; + // If using a response file, move defines, includes, and flags into it. + std::string ppRspFile; + std::string ppRspContent; + if (!responseFlag.empty()) { + ppRspFile = "$RSP_FILE"; + ppRspContent = std::string(" ") + ppVars.Defines + " " + + ppVars.Includes + " " + ppFlags; + ppFlags = responseFlag + ppRspFile; + ppVars.Defines = ""; + ppVars.Includes = ""; + } + + ppVars.Flags = ppFlags.c_str(); + // Rule for preprocessing source file. std::vector<std::string> ppCmds; cmSystemTools::ExpandListArgument(ppCmd, ppCmds); @@ -588,13 +548,11 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) ppComment << "Rule for preprocessing " << lang << " files."; std::ostringstream ppDesc; ppDesc << "Building " << lang << " preprocessed $out"; - this->GetGlobalGenerator()->AddRule(this->LanguagePreprocessRule(lang), - ppCmdLine, ppDesc.str(), - ppComment.str(), ppDepfile, ppDeptype, - /*rspfile*/ "", - /*rspcontent*/ "", - /*restat*/ "", - /*generator*/ false); + this->GetGlobalGenerator()->AddRule( + this->LanguagePreprocessRule(lang), ppCmdLine, ppDesc.str(), + ppComment.str(), ppDepfile, ppDeptype, ppRspFile, ppRspContent, + /*restat*/ "", + /*generator*/ false); } if (needDyndep) { @@ -631,6 +589,64 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) /*generator*/ false); } + // If using a response file, move defines, includes, and flags into it. + std::string rspfile; + std::string rspcontent; + if (!responseFlag.empty()) { + rspfile = "$RSP_FILE"; + rspcontent = + std::string(" ") + vars.Defines + " " + vars.Includes + " " + flags; + flags = responseFlag + rspfile; + vars.Defines = ""; + vars.Includes = ""; + } + + // Tell ninja dependency format so all deps can be loaded into a database + std::string deptype; + std::string depfile; + std::string cldeps; + if (explicitPP) { + // The explicit preprocessing step will handle dependency scanning. + } else if (this->NeedDepTypeMSVC(lang)) { + deptype = "msvc"; + depfile.clear(); + flags += " /showIncludes"; + } else if (mf->IsOn("CMAKE_NINJA_CMCLDEPS_" + lang)) { + // For the MS resource compiler we need cmcldeps, but skip dependencies + // for source-file try_compile cases because they are always fresh. + if (!mf->GetIsSourceFileTryCompile()) { + deptype = "gcc"; + depfile = "$DEP_FILE"; + const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER") + ? mf->GetSafeDefinition("CMAKE_C_COMPILER") + : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); + cldeps = "\""; + cldeps += cmSystemTools::GetCMClDepsCommand(); + cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \""; + cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); + cldeps += "\" \"" + cl + "\" "; + } + } else { + deptype = "gcc"; + const char* langdeptype = mf->GetDefinition("CMAKE_NINJA_DEPTYPE_" + lang); + if (langdeptype) { + deptype = langdeptype; + } + depfile = "$DEP_FILE"; + const std::string flagsName = "CMAKE_DEPFILE_FLAGS_" + lang; + std::string depfileFlags = mf->GetSafeDefinition(flagsName); + if (!depfileFlags.empty()) { + cmSystemTools::ReplaceString(depfileFlags, "<DEPFILE>", "$DEP_FILE"); + cmSystemTools::ReplaceString(depfileFlags, "<OBJECT>", "$out"); + cmSystemTools::ReplaceString(depfileFlags, "<CMAKE_C_COMPILER>", + mf->GetDefinition("CMAKE_C_COMPILER")); + flags += " " + depfileFlags; + } + } + + vars.Flags = flags.c_str(); + vars.DependencyFile = depfile.c_str(); + // Rule for compiling object file. std::vector<std::string> compileCmds; if (lang == "CUDA") { @@ -865,6 +881,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const objectFileDir = cmSystemTools::GetFilenamePath(objectFileName); + bool const lang_supports_response = + !(language == "RC" || language == "CUDA"); + int const commandLineLengthLimit = + ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; + cmNinjaVars vars; vars["FLAGS"] = this->ComputeFlagsForObject(source, language); vars["DEFINES"] = this->ComputeDefines(source, language); @@ -1012,9 +1033,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), ppVars); + std::string const ppRspFile = ppFileName + ".rsp"; + this->GetGlobalGenerator()->WriteBuild( this->GetBuildFileStream(), ppComment, ppRule, ppOutputs, ppImplicitOuts, - ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars); + ppExplicitDeps, ppImplicitDeps, ppOrderOnlyDeps, ppVars, ppRspFile, + commandLineLengthLimit); } if (needDyndep) { std::string const dyndep = this->GetDyndepFilePath(language); @@ -1034,10 +1058,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->SetMsvcTargetPdbVariable(vars); - bool const lang_supports_response = - !(language == "RC" || language == "CUDA"); - int const commandLineLengthLimit = - ((lang_supports_response && this->ForceResponseFile())) ? -1 : 0; std::string const rspfile = objectFileName + ".rsp"; this->GetGlobalGenerator()->WriteBuild( diff --git a/Source/cmState.cxx b/Source/cmState.cxx index bb891b5..a93fb11 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -13,6 +13,7 @@ #include "cmCommand.h" #include "cmDefinitions.h" #include "cmDisallowedCommand.h" +#include "cmGlobVerificationManager.h" #include "cmListFileCache.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" @@ -31,11 +32,13 @@ cmState::cmState() , MSYSShell(false) { this->CacheManager = new cmCacheManager; + this->GlobVerificationManager = new cmGlobVerificationManager; } cmState::~cmState() { delete this->CacheManager; + delete this->GlobVerificationManager; cmDeleteAll(this->BuiltinCommands); cmDeleteAll(this->ScriptedCommands); } @@ -207,6 +210,39 @@ void cmState::AddCacheEntry(const std::string& key, const char* value, this->CacheManager->AddCacheEntry(key, value, helpString, type); } +bool cmState::DoWriteGlobVerifyTarget() const +{ + return this->GlobVerificationManager->DoWriteVerifyTarget(); +} + +std::string const& cmState::GetGlobVerifyScript() const +{ + return this->GlobVerificationManager->GetVerifyScript(); +} + +std::string const& cmState::GetGlobVerifyStamp() const +{ + return this->GlobVerificationManager->GetVerifyStamp(); +} + +bool cmState::SaveVerificationScript(const std::string& path) +{ + return this->GlobVerificationManager->SaveVerificationScript(path); +} + +void cmState::AddGlobCacheEntry(bool recurse, bool listDirectories, + bool followSymlinks, + const std::string& relative, + const std::string& expression, + const std::vector<std::string>& files, + const std::string& variable, + cmListFileBacktrace const& backtrace) +{ + this->GlobVerificationManager->AddCacheEntry( + recurse, listDirectories, followSymlinks, relative, expression, files, + variable, backtrace); +} + void cmState::RemoveCacheEntry(std::string const& key) { this->CacheManager->RemoveCacheEntry(key); diff --git a/Source/cmState.h b/Source/cmState.h index 6cbf82d..4c6fc69 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -12,6 +12,7 @@ #include "cmDefinitions.h" #include "cmLinkedTree.h" +#include "cmListFileCache.h" #include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinitionMap.h" @@ -21,6 +22,7 @@ class cmCacheManager; class cmCommand; +class cmGlobVerificationManager; class cmPropertyDefinition; class cmStateSnapshot; class cmMessenger; @@ -165,12 +167,24 @@ private: const char* helpString, cmStateEnums::CacheEntryType type); + bool DoWriteGlobVerifyTarget() const; + std::string const& GetGlobVerifyScript() const; + std::string const& GetGlobVerifyStamp() const; + bool SaveVerificationScript(const std::string& path); + void AddGlobCacheEntry(bool recurse, bool listDirectories, + bool followSymlinks, const std::string& relative, + const std::string& expression, + const std::vector<std::string>& files, + const std::string& variable, + cmListFileBacktrace const& bt); + std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions; std::vector<std::string> EnabledLanguages; std::map<std::string, cmCommand*> BuiltinCommands; std::map<std::string, cmCommand*> ScriptedCommands; cmPropertyMap GlobalProperties; cmCacheManager* CacheManager; + cmGlobVerificationManager* GlobVerificationManager; cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType> BuildsystemDirectory; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 479ecd2..0d97c33 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -6,7 +6,7 @@ #include <algorithm> #include <assert.h> #include <iterator> -#include <stdio.h> +#include <string> #include "cmAlgorithms.h" #include "cmDefinitions.h" @@ -328,15 +328,14 @@ void cmStateSnapshot::SetDefaultDefinitions() this->SetDefinition("CMAKE_HOST_SOLARIS", "1"); #endif - char temp[1024]; - sprintf(temp, "%d", cmVersion::GetMinorVersion()); - this->SetDefinition("CMAKE_MINOR_VERSION", temp); - sprintf(temp, "%d", cmVersion::GetMajorVersion()); - this->SetDefinition("CMAKE_MAJOR_VERSION", temp); - sprintf(temp, "%d", cmVersion::GetPatchVersion()); - this->SetDefinition("CMAKE_PATCH_VERSION", temp); - sprintf(temp, "%d", cmVersion::GetTweakVersion()); - this->SetDefinition("CMAKE_TWEAK_VERSION", temp); + this->SetDefinition("CMAKE_MAJOR_VERSION", + std::to_string(cmVersion::GetMajorVersion())); + this->SetDefinition("CMAKE_MINOR_VERSION", + std::to_string(cmVersion::GetMinorVersion())); + this->SetDefinition("CMAKE_PATCH_VERSION", + std::to_string(cmVersion::GetPatchVersion())); + this->SetDefinition("CMAKE_TWEAK_VERSION", + std::to_string(cmVersion::GetTweakVersion())); this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion()); this->SetDefinition("CMAKE_FILES_DIRECTORY", diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index a2f3ecd..54f8cf4 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -43,7 +43,7 @@ private: void LinkLibraryTypeSpecifierWarning(int left, int right); static const char* LinkLibraryTypeNames[3]; - cmTarget* Target; + cmTarget* Target = nullptr; enum ProcessingState { ProcessingLinkLibraries, @@ -55,7 +55,7 @@ private: ProcessingKeywordPrivateInterface }; - ProcessingState CurrentProcessingState; + ProcessingState CurrentProcessingState = ProcessingLinkLibraries; bool HandleLibrary(const std::string& lib, cmTargetLinkLibraryType llt); }; diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h index 3c736fc..943285d 100644 --- a/Source/cmTargetPropCommandBase.h +++ b/Source/cmTargetPropCommandBase.h @@ -28,7 +28,7 @@ public: protected: std::string Property; - cmTarget* Target; + cmTarget* Target = nullptr; virtual void HandleInterfaceContent(cmTarget* tgt, const std::vector<std::string>& content, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index c0333ff..3289b55 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -371,8 +371,8 @@ void cmVisualStudio10TargetGenerator::Generate() if (this->NsightTegra) { this->WriteString("<PropertyGroup Label=\"NsightTegraProject\">\n", 1); - const int nsightTegraMajorVersion = this->NsightTegraVersion[0]; - const int nsightTegraMinorVersion = this->NsightTegraVersion[1]; + const unsigned int nsightTegraMajorVersion = this->NsightTegraVersion[0]; + const unsigned int nsightTegraMinorVersion = this->NsightTegraVersion[1]; if (nsightTegraMajorVersion >= 2) { this->WriteString("<NsightTegraProjectRevisionNumber>", 2); if (nsightTegraMajorVersion > 3 || diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 4df03b6..3c53d1b 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -204,7 +204,7 @@ private: bool MSTools; bool Managed; bool NsightTegra; - int NsightTegraVersion[4]; + unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmGeneratedFileStream* BuildFileStream; diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx index 3cbc70d..9d2a3c4 100644 --- a/Source/cmXMLWriter.cxx +++ b/Source/cmXMLWriter.cxx @@ -9,6 +9,7 @@ cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level) : Output(output) , IndentationElement(1, '\t') , Level(level) + , Indent(0) , ElementOpen(false) , BreakAttrib(false) , IsContent(false) @@ -17,7 +18,7 @@ cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level) cmXMLWriter::~cmXMLWriter() { - assert(this->Elements.empty()); + assert(this->Indent == 0); } void cmXMLWriter::StartDocument(const char* encoding) @@ -27,27 +28,29 @@ void cmXMLWriter::StartDocument(const char* encoding) void cmXMLWriter::EndDocument() { - assert(this->Elements.empty()); + assert(this->Indent == 0); this->Output << '\n'; } void cmXMLWriter::StartElement(std::string const& name) { this->CloseStartElement(); - this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->ConditionalLineBreak(!this->IsContent); this->Output << '<' << name; this->Elements.push(name); + ++this->Indent; this->ElementOpen = true; this->BreakAttrib = false; } void cmXMLWriter::EndElement() { - assert(!this->Elements.empty()); + assert(this->Indent > 0); + --this->Indent; if (this->ElementOpen) { this->Output << "/>"; } else { - this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1); + this->ConditionalLineBreak(!this->IsContent); this->IsContent = false; this->Output << "</" << this->Elements.top() << '>'; } @@ -58,7 +61,7 @@ void cmXMLWriter::EndElement() void cmXMLWriter::Element(const char* name) { this->CloseStartElement(); - this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->ConditionalLineBreak(!this->IsContent); this->Output << '<' << name << "/>"; } @@ -70,7 +73,7 @@ void cmXMLWriter::BreakAttributes() void cmXMLWriter::Comment(const char* comment) { this->CloseStartElement(); - this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->ConditionalLineBreak(!this->IsContent); this->Output << "<!-- " << comment << " -->"; } @@ -83,14 +86,14 @@ void cmXMLWriter::CData(std::string const& data) void cmXMLWriter::Doctype(const char* doctype) { this->CloseStartElement(); - this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->ConditionalLineBreak(!this->IsContent); this->Output << "<!DOCTYPE " << doctype << ">"; } void cmXMLWriter::ProcessingInstruction(const char* target, const char* data) { this->CloseStartElement(); - this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->ConditionalLineBreak(!this->IsContent); this->Output << "<?" << target << ' ' << data << "?>"; } @@ -106,11 +109,11 @@ void cmXMLWriter::SetIndentationElement(std::string const& element) this->IndentationElement = element; } -void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent) +void cmXMLWriter::ConditionalLineBreak(bool condition) { if (condition) { this->Output << '\n'; - for (std::size_t i = 0; i < indent + this->Level; ++i) { + for (std::size_t i = 0; i < this->Indent + this->Level; ++i) { this->Output << this->IndentationElement; } } @@ -119,7 +122,7 @@ void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent) void cmXMLWriter::PreAttribute() { assert(this->ElementOpen); - this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size()); + this->ConditionalLineBreak(this->BreakAttrib); if (!this->BreakAttrib) { this->Output << ' '; } @@ -134,7 +137,7 @@ void cmXMLWriter::PreContent() void cmXMLWriter::CloseStartElement() { if (this->ElementOpen) { - this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size()); + this->ConditionalLineBreak(this->BreakAttrib); this->Output << '>'; this->ElementOpen = false; } diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 80940ee..ff0df18 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -67,7 +67,7 @@ public: void SetIndentationElement(std::string const& element); private: - void ConditionalLineBreak(bool condition, std::size_t indent); + void ConditionalLineBreak(bool condition); void PreAttribute(); void PreContent(); @@ -128,6 +128,7 @@ private: std::stack<std::string, std::vector<std::string>> Elements; std::string IndentationElement; std::size_t Level; + std::size_t Indent; bool ElementOpen; bool BreakAttrib; bool IsContent; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 83c5384..5bae4e7 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1433,6 +1433,7 @@ int cmake::ActualConfigure() // only save the cache if there were no fatal errors if (this->GetWorkingMode() == NORMAL_MODE) { + this->State->SaveVerificationScript(this->GetHomeOutputDirectory()); this->SaveCache(this->GetHomeOutputDirectory()); } if (cmSystemTools::GetErrorOccuredFlag()) { @@ -1647,6 +1648,33 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, this->UnwatchUnusedCli(key); } +bool cmake::DoWriteGlobVerifyTarget() const +{ + return this->State->DoWriteGlobVerifyTarget(); +} + +std::string const& cmake::GetGlobVerifyScript() const +{ + return this->State->GetGlobVerifyScript(); +} + +std::string const& cmake::GetGlobVerifyStamp() const +{ + return this->State->GetGlobVerifyStamp(); +} + +void cmake::AddGlobCacheEntry(bool recurse, bool listDirectories, + bool followSymlinks, const std::string& relative, + const std::string& expression, + const std::vector<std::string>& files, + const std::string& variable, + cmListFileBacktrace const& backtrace) +{ + this->State->AddGlobCacheEntry(recurse, listDirectories, followSymlinks, + relative, expression, files, variable, + backtrace); +} + std::string cmake::StripExtension(const std::string& file) const { auto dotpos = file.rfind('.'); @@ -2434,37 +2462,49 @@ int cmake::Build(const std::string& dir, const std::string& target, cmGlobalVisualStudio9Generator::GetGenerateStampList(); // Note that the stampList file only exists for VS generators. - if (cmSystemTools::FileExists(stampList) && - !cmakeCheckStampList(stampList.c_str(), false)) { - - // Correctly initialize the home (=source) and home output (=binary) - // directories, which is required for running the generation step. - std::string homeOrig = this->GetHomeDirectory(); - std::string homeOutputOrig = this->GetHomeOutputDirectory(); - this->SetDirectoriesFromFile(cachePath.c_str()); + if (cmSystemTools::FileExists(stampList)) { + // Check if running for Visual Studio 9 - we need to explicitly run + // the glob verification script before starting the build this->AddScriptingCommands(); - this->AddProjectCommands(); + if (this->GlobalGenerator->MatchesGeneratorName("Visual Studio 9 2008")) { + std::string const globVerifyScript = cachePath + "/" + + GetCMakeFilesDirectoryPostSlash() + "VerifyGlobs.cmake"; + if (cmSystemTools::FileExists(globVerifyScript)) { + std::vector<std::string> args; + this->ReadListFile(args, globVerifyScript.c_str()); + } + } - int ret = this->Configure(); - if (ret) { - cmSystemTools::Message("CMake Configure step failed. " - "Build files cannot be regenerated correctly."); - return ret; - } - ret = this->Generate(); - if (ret) { - cmSystemTools::Message("CMake Generate step failed. " - "Build files cannot be regenerated correctly."); - return ret; - } - std::string message = "Build files have been written to: "; - message += this->GetHomeOutputDirectory(); - this->UpdateProgress(message.c_str(), -1); - - // Restore the previously set directories to their original value. - this->SetHomeDirectory(homeOrig); - this->SetHomeOutputDirectory(homeOutputOrig); + if (!cmakeCheckStampList(stampList.c_str(), false)) { + // Correctly initialize the home (=source) and home output (=binary) + // directories, which is required for running the generation step. + std::string homeOrig = this->GetHomeDirectory(); + std::string homeOutputOrig = this->GetHomeOutputDirectory(); + this->SetDirectoriesFromFile(cachePath.c_str()); + + this->AddProjectCommands(); + + int ret = this->Configure(); + if (ret) { + cmSystemTools::Message("CMake Configure step failed. " + "Build files cannot be regenerated correctly."); + return ret; + } + ret = this->Generate(); + if (ret) { + cmSystemTools::Message("CMake Generate step failed. " + "Build files cannot be regenerated correctly."); + return ret; + } + std::string message = "Build files have been written to: "; + message += this->GetHomeOutputDirectory(); + this->UpdateProgress(message.c_str(), -1); + + // Restore the previously set directories to their original value. + this->SetHomeDirectory(homeOrig); + this->SetHomeOutputDirectory(homeOutputOrig); + } } #endif diff --git a/Source/cmake.h b/Source/cmake.h index cc56a07..63dbe9f 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -255,6 +255,16 @@ public: void AddCacheEntry(const std::string& key, const char* value, const char* helpString, int type); + bool DoWriteGlobVerifyTarget() const; + std::string const& GetGlobVerifyScript() const; + std::string const& GetGlobVerifyStamp() const; + void AddGlobCacheEntry(bool recurse, bool listDirectories, + bool followSymlinks, const std::string& relative, + const std::string& expression, + const std::vector<std::string>& files, + const std::string& variable, + cmListFileBacktrace const& bt); + /** * Get the system information and write it to the file specified */ diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 1309c42..aad7cfc 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1442,6 +1442,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release ADD_TEST_MACRO(FindMatlab.basic_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) ADD_TEST_MACRO(FindMatlab.versions_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) ADD_TEST_MACRO(FindMatlab.components_checks ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) + ADD_TEST_MACRO(FindMatlab.failure_reports ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>) endif() find_package(GTK2 QUIET) diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index e94473f..b0bc656 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -224,69 +224,22 @@ if (C_expected_features) add_executable(CompileFeaturesGenex_C genex_test.c) set_property(TARGET CompileFeaturesGenex_C PROPERTY C_STANDARD 11) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.6) - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=1 - ) - else() - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=0 - ) - endif() - elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" - OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=1 - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Intel") - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 15) - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=1 - ) - else() - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=0 - ) - endif() - elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") - list(APPEND expected_defs - EXPECT_C_RESTRICT=0 - EXPECT_C_STATIC_ASSERT=0 + foreach(f + c_restrict + c_static_assert + c_function_prototypes ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "SunPro") - if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.13) - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=1 - ) + if(${f} IN_LIST C_expected_features) + set(expect_${f} 1) else() - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 - EXPECT_C_STATIC_ASSERT=0 - ) + set(expect_${f} 0) endif() - else() - list(APPEND expected_defs - EXPECT_C_RESTRICT=1 + string(TOUPPER "${f}" F) + target_compile_definitions(CompileFeaturesGenex_C PRIVATE + EXPECT_${F}=${expect_${f}} + HAVE_${F}=$<COMPILE_FEATURES:${f}> ) - endif() - - list(APPEND expected_defs - EXPECT_C_FUNCTION_PROTOTYPES=1 - ) - - target_compile_definitions(CompileFeaturesGenex_C PRIVATE - HAVE_C_FUNCTION_PROTOTYPES=$<COMPILE_FEATURES:c_function_prototypes> - HAVE_C_RESTRICT=$<COMPILE_FEATURES:c_restrict> - HAVE_C_STATIC_ASSERT=$<COMPILE_FEATURES:c_static_assert> - ${expected_defs} - ) + endforeach() endif() if (CMAKE_CXX_COMPILE_FEATURES) @@ -334,118 +287,43 @@ else() add_executable(IfaceCompileFeatures main.cpp) target_link_libraries(IfaceCompileFeatures iface) - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 + foreach(f + cxx_final + cxx_override + cxx_auto_type + cxx_inheriting_constructors ) + if(${f} IN_LIST CXX_expected_features) + set(expect_${f} 1) else() - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=0 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=0 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - else() - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) - else() - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=0 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=0 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) - endif() - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=1 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=1 - ) - elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=1 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=1 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) - else() - add_definitions( - -DEXPECT_OVERRIDE_CONTROL=0 - -DEXPECT_INHERITING_CONSTRUCTORS=0 - -DEXPECT_FINAL=0 - -DEXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=0 - ) + set(expect_${f} 0) endif() + endforeach() + + if(expect_cxx_final AND expect_cxx_override) + set(expect_override_control 1) + else() + set(expect_override_control 0) + endif() + if(expect_cxx_inheriting_constructors AND expect_cxx_final) + set(expect_inheriting_constructors_and_final 1) + else() + set(expect_inheriting_constructors_and_final 0) endif() - add_executable(CompileFeaturesGenex genex_test.cpp) - set_property(TARGET CompileFeaturesGenex PROPERTY CXX_STANDARD 11) - target_compile_definitions(CompileFeaturesGenex PRIVATE + set(genex_test_defs HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override> HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type> HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors> HAVE_FINAL=$<COMPILE_FEATURES:cxx_final> HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final> - ) + EXPECT_OVERRIDE_CONTROL=${expect_override_control} + EXPECT_INHERITING_CONSTRUCTORS=${expect_cxx_inheriting_constructors} + EXPECT_FINAL=${expect_cxx_final} + EXPECT_INHERITING_CONSTRUCTORS_AND_FINAL=${expect_inheriting_constructors_and_final} + ) if (CMAKE_CXX_STANDARD_DEFAULT) - target_compile_definitions(CompileFeaturesGenex PRIVATE + list(APPEND genex_test_defs TEST_CXX_STD HAVE_CXX_STD_11=$<COMPILE_FEATURES:cxx_std_11> HAVE_CXX_STD_14=$<COMPILE_FEATURES:cxx_std_14> @@ -454,25 +332,17 @@ else() ) endif() + add_executable(CompileFeaturesGenex genex_test.cpp) + set_property(TARGET CompileFeaturesGenex PROPERTY CXX_STANDARD 11) + target_compile_definitions(CompileFeaturesGenex PRIVATE ${genex_test_defs}) + add_executable(CompileFeaturesGenex2 genex_test.cpp) target_compile_features(CompileFeaturesGenex2 PRIVATE cxx_std_11) - target_compile_definitions(CompileFeaturesGenex2 PRIVATE - HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override> - HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type> - HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors> - HAVE_FINAL=$<COMPILE_FEATURES:cxx_final> - HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final> - ) + target_compile_definitions(CompileFeaturesGenex2 PRIVATE ${genex_test_defs}) add_library(std_11_iface INTERFACE) target_compile_features(std_11_iface INTERFACE cxx_std_11) add_executable(CompileFeaturesGenex3 genex_test.cpp) target_link_libraries(CompileFeaturesGenex3 PRIVATE std_11_iface) - target_compile_definitions(CompileFeaturesGenex3 PRIVATE - HAVE_OVERRIDE_CONTROL=$<COMPILE_FEATURES:cxx_final,cxx_override> - HAVE_AUTO_TYPE=$<COMPILE_FEATURES:cxx_auto_type> - HAVE_INHERITING_CONSTRUCTORS=$<COMPILE_FEATURES:cxx_inheriting_constructors> - HAVE_FINAL=$<COMPILE_FEATURES:cxx_final> - HAVE_INHERITING_CONSTRUCTORS_AND_FINAL=$<COMPILE_FEATURES:cxx_inheriting_constructors,cxx_final> - ) + target_compile_definitions(CompileFeaturesGenex3 PRIVATE ${genex_test_defs}) endif() diff --git a/Tests/FindMatlab/basic_checks/CMakeLists.txt b/Tests/FindMatlab/basic_checks/CMakeLists.txt index bf54427..951fcf2 100644 --- a/Tests/FindMatlab/basic_checks/CMakeLists.txt +++ b/Tests/FindMatlab/basic_checks/CMakeLists.txt @@ -24,11 +24,12 @@ matlab_add_mex( matlab_add_unit_test( NAME ${PROJECT_NAME}_matlabtest-1 - TIMEOUT 90 + TIMEOUT 300 UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests1.m ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1> ) +# timeout tests, TIMEOUT set to very short on purpose matlab_add_unit_test( NAME ${PROJECT_NAME}_matlabtest-2 TIMEOUT 15 @@ -41,7 +42,7 @@ set_tests_properties(${PROJECT_NAME}_matlabtest-2 PROPERTIES WILL_FAIL TRUE) # testing the test without the unittest framework of Matlab matlab_add_unit_test( NAME ${PROJECT_NAME}_matlabtest-3 - TIMEOUT 30 + TIMEOUT 300 NO_UNITTEST_FRAMEWORK UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests2.m ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1> @@ -49,7 +50,7 @@ matlab_add_unit_test( matlab_add_unit_test( NAME ${PROJECT_NAME}_matlabtest-4 - TIMEOUT 30 + TIMEOUT 300 NO_UNITTEST_FRAMEWORK UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_matlab_unit_tests3.m ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1> diff --git a/Tests/FindMatlab/failure_reports/CMakeLists.txt b/Tests/FindMatlab/failure_reports/CMakeLists.txt new file mode 100644 index 0000000..1cf9613 --- /dev/null +++ b/Tests/FindMatlab/failure_reports/CMakeLists.txt @@ -0,0 +1,39 @@ + +cmake_minimum_required (VERSION 2.8.12) +enable_testing() +project(failure_reports) + +# gather tests about proper failure reports + +set(MATLAB_FIND_DEBUG TRUE) + +find_package(Matlab REQUIRED COMPONENTS MX_LIBRARY MAIN_PROGRAM) + +# main extensions for testing, same as other tests +matlab_add_mex( + # target name + NAME cmake_matlab_test_wrapper1 + # output name + OUTPUT_NAME cmake_matlab_mex1 + SRC ${CMAKE_CURRENT_SOURCE_DIR}/../matlab_wrapper1.cpp + DOCUMENTATION ${CMAKE_CURRENT_SOURCE_DIR}/../help_text1.m.txt + ) + +# the unit test file does not exist: the failure should be properly reported +matlab_add_unit_test( + NAME ${PROJECT_NAME}_matlabtest-1 + TIMEOUT 300 + UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../nonexistantfile.m + ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1> + ) +set_tests_properties(${PROJECT_NAME}_matlabtest-1 PROPERTIES WILL_FAIL TRUE) + +# without the unit test framework +matlab_add_unit_test( + NAME ${PROJECT_NAME}_matlabtest-2 + TIMEOUT 300 + NO_UNITTEST_FRAMEWORK + UNITTEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../nonexistantfile2.m + ADDITIONAL_PATH $<TARGET_FILE_DIR:cmake_matlab_test_wrapper1> + ) +set_tests_properties(${PROJECT_NAME}_matlabtest-2 PROPERTIES WILL_FAIL TRUE) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index c0c361e..44a8c45 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -121,6 +121,9 @@ if(CMAKE_GENERATOR STREQUAL "Ninja") -DCMAKE_C_OUTPUT_EXTENSION=${CMAKE_C_OUTPUT_EXTENSION} -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX}) + if(CMAKE_Fortran_COMPILER) + list(APPEND Ninja_ARGS -DTEST_Fortran=1) + endif() add_RunCMake_test(Ninja) endif() add_RunCMake_test(CTest) @@ -336,6 +339,7 @@ add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(CommandLineTar) add_RunCMake_test(install) +add_RunCMake_test(CPackCommandLine) add_RunCMake_test(CPackConfig) add_RunCMake_test(CPackInstallProperties) add_RunCMake_test(ExternalProject) diff --git a/Tests/RunCMake/CPackCommandLine/NotAGenerator-result.txt b/Tests/RunCMake/CPackCommandLine/NotAGenerator-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CPackCommandLine/NotAGenerator-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CPackCommandLine/NotAGenerator-stderr.txt b/Tests/RunCMake/CPackCommandLine/NotAGenerator-stderr.txt new file mode 100644 index 0000000..fe4e455 --- /dev/null +++ b/Tests/RunCMake/CPackCommandLine/NotAGenerator-stderr.txt @@ -0,0 +1 @@ +^CPack Error: Cannot initialize CPack generator: NotAGenerator diff --git a/Tests/RunCMake/CPackCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CPackCommandLine/RunCMakeTest.cmake new file mode 100644 index 0000000..991146c --- /dev/null +++ b/Tests/RunCMake/CPackCommandLine/RunCMakeTest.cmake @@ -0,0 +1,10 @@ +include(RunCMake) +set(RunCMake_TEST_TIMEOUT 60) + +file(WRITE "${RunCMake_BINARY_DIR}/NotAGenerator-build/CPackConfig.cmake" [[ +set(CPACK_PACKAGE_NAME "Test") +set(CPACK_PACKAGE_VERSION "1") +]]) +set(RunCMake_TEST_NO_CLEAN 1) +run_cmake_command(NotAGenerator ${CMAKE_CPACK_COMMAND} -G NotAGenerator) +unset(RunCMake_TEST_NO_CLEAN) diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index 5df2fbf..d8dbeec 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -287,6 +287,10 @@ set(RunCMake_TEST_OPTIONS --trace-expand) run_cmake(trace-expand) unset(RunCMake_TEST_OPTIONS) +set(RunCMake_TEST_OPTIONS --trace-expand --warn-uninitialized) +run_cmake(trace-expand-warn-uninitialized) +unset(RunCMake_TEST_OPTIONS) + set(RunCMake_TEST_OPTIONS --trace-source=trace-only-this-file.cmake) run_cmake(trace-source) unset(RunCMake_TEST_OPTIONS) diff --git a/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized-stderr.txt b/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized-stderr.txt new file mode 100644 index 0000000..74429b6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized-stderr.txt @@ -0,0 +1,2 @@ +^.*/Tests/RunCMake/CommandLine/CMakeLists.txt\(1\): cmake_minimum_required\(VERSION 3.0 \) +.*/Tests/RunCMake/CommandLine/CMakeLists.txt\(2\): project\(trace-expand-warn-uninitialized NONE \) diff --git a/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized.cmake b/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized.cmake new file mode 100644 index 0000000..ec3e4d4 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trace-expand-warn-uninitialized.cmake @@ -0,0 +1,4 @@ +cmake_policy(SET CMP0053 OLD) +message(STATUS "'${uninitialized_variable}'") +cmake_policy(SET CMP0053 NEW) +message(STATUS "'${uninitialized_variable}'") diff --git a/Tests/RunCMake/Ninja/RspFileC.cmake b/Tests/RunCMake/Ninja/RspFileC.cmake new file mode 100644 index 0000000..4a40682 --- /dev/null +++ b/Tests/RunCMake/Ninja/RspFileC.cmake @@ -0,0 +1,2 @@ +set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1) +enable_language(C) diff --git a/Tests/RunCMake/Ninja/RspFileCXX.cmake b/Tests/RunCMake/Ninja/RspFileCXX.cmake new file mode 100644 index 0000000..9e61ffe --- /dev/null +++ b/Tests/RunCMake/Ninja/RspFileCXX.cmake @@ -0,0 +1,2 @@ +set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1) +enable_language(CXX) diff --git a/Tests/RunCMake/Ninja/RspFileFortran.cmake b/Tests/RunCMake/Ninja/RspFileFortran.cmake new file mode 100644 index 0000000..8c18e37 --- /dev/null +++ b/Tests/RunCMake/Ninja/RspFileFortran.cmake @@ -0,0 +1,2 @@ +set(ENV{CMAKE_NINJA_FORCE_RESPONSE_FILE} 1) +enable_language(Fortran) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index b3720fb..3bb2b6b 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -40,6 +40,12 @@ run_CMP0058(NEW-by) run_cmake(CustomCommandDepfile) +run_cmake(RspFileC) +run_cmake(RspFileCXX) +if(TEST_Fortran) + run_cmake(RspFileFortran) +endif() + function(run_CommandConcat) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CommandConcat-build) set(RunCMake_TEST_NO_CLEAN 1) diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt new file mode 100644 index 0000000..71ab721 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-build-stdout.txt @@ -0,0 +1 @@ +.*b9fbdd8803c036dbe9f5ea6b74db4b9670c78a72 diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt new file mode 100644 index 0000000..ff90f9c --- /dev/null +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first-stdout.txt @@ -0,0 +1,2 @@ +.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake +.*6bc141b40c0f851d20fa9a1fe5fbdae94acc5de0 diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt new file mode 100644 index 0000000..cf2a5af --- /dev/null +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second-stdout.txt @@ -0,0 +1,2 @@ +.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake +.*0c3ceab9daa7914fde7410c34cae4049e140aa51 diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-stdout.txt b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-stdout.txt new file mode 100644 index 0000000..66b6c44 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake-stdout.txt @@ -0,0 +1 @@ +.*Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake diff --git a/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake.cmake b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake.cmake new file mode 100644 index 0000000..fe87c78 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-CONFIGURE_DEPENDS-RerunCMake.cmake @@ -0,0 +1,10 @@ +message(STATUS "Running CMake on GLOB-CONFIGURE_DEPENDS-RerunCMake") +file(GLOB_RECURSE + CONTENT_LIST + CONFIGURE_DEPENDS + LIST_DIRECTORIES false + RELATIVE "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}/test/*" + ) +string(SHA1 CONTENT_LIST_HASH "${CONTENT_LIST}") +add_custom_target(CONTENT_ECHO ALL ${CMAKE_COMMAND} -E echo ${CONTENT_LIST_HASH}) diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-result.txt b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-stderr.txt b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-stderr.txt new file mode 100644 index 0000000..40083c1 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE-stderr.txt @@ -0,0 +1 @@ +.*CONFIGURE_DEPENDS is invalid for script and find package modes\. diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake new file mode 100644 index 0000000..9dc0f03 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake @@ -0,0 +1 @@ +file(GLOB CONTENT_LIST CONFIGURE_DEPENDS) diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-result.txt b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-stderr.txt b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-stderr.txt new file mode 100644 index 0000000..d7b36eb --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error: The glob expression +.* at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\) +was already present in the glob cache but the directory +contents have changed during the configuration run. +Matching glob expressions: + CONTENT_LIST_1 at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\) + CONTENT_LIST_2 at GLOB-error-CONFIGURE_DEPENDS-modified\.cmake:[0-9]+ \(file\)$ diff --git a/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified.cmake b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified.cmake new file mode 100644 index 0000000..8d74dea --- /dev/null +++ b/Tests/RunCMake/file/GLOB-error-CONFIGURE_DEPENDS-modified.cmake @@ -0,0 +1,21 @@ +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/second") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/third") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "one") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/second/two" "two") +file(GLOB_RECURSE CONTENT_LIST_1 + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/test/*" + ) + +file(GLOB_RECURSE CONTENT_LIST_2 + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/test/*" + ) + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/third/three" "three") +file(GLOB_RECURSE CONTENT_LIST_3 + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/test/*" + ) diff --git a/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-result.txt b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-stderr.txt b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-stderr.txt new file mode 100644 index 0000000..01d204f --- /dev/null +++ b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at GLOB-noexp-CONFIGURE_DEPENDS\.cmake:[0-9]+ \(file\): + file GLOB requires a glob expression after CONFIGURE_DEPENDS\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS.cmake b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS.cmake new file mode 100644 index 0000000..9dc0f03 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-noexp-CONFIGURE_DEPENDS.cmake @@ -0,0 +1 @@ +file(GLOB CONTENT_LIST CONFIGURE_DEPENDS) diff --git a/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late-stderr.txt b/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late-stderr.txt new file mode 100644 index 0000000..af722a4 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late-stderr.txt @@ -0,0 +1,6 @@ +^CMake Warning \(dev\) at GLOB-warn-CONFIGURE_DEPENDS-late\.cmake:[0-9]+ \(file\): + CONFIGURE_DEPENDS flag was given after a glob expression was already + evaluated\. +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\) +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late.cmake b/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late.cmake new file mode 100644 index 0000000..0b69552 --- /dev/null +++ b/Tests/RunCMake/file/GLOB-warn-CONFIGURE_DEPENDS-late.cmake @@ -0,0 +1,11 @@ +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/second") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "Hi, Mom!") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/second/two" "Love you!") + +file(GLOB CONTENT_LIST + "${CMAKE_CURRENT_BINARY_DIR}/test/first/*" + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/test/second/*" + ) diff --git a/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version-stderr.txt b/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version-stderr.txt new file mode 100644 index 0000000..8d22332 --- /dev/null +++ b/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version-stderr.txt @@ -0,0 +1,13 @@ +^CMake Warning \(dev\): + The detected version of Ninja: + + .* + + is less than the version of Ninja required by CMake for adding restat + dependencies to the build\.ninja manifest regeneration target: + + 1\.8 + + Any pre-check scripts, such as those generated for file\(GLOB + CONFIGURE_DEPENDS\), will not be run by Ninja\. +This warning is for project developers\. Use -Wno-dev to suppress it\.$ diff --git a/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version.cmake b/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version.cmake new file mode 100644 index 0000000..8e80895 --- /dev/null +++ b/Tests/RunCMake/file/GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version.cmake @@ -0,0 +1,6 @@ +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/first") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/first/one" "one") +file(GLOB_RECURSE CONTENT_LIST + CONFIGURE_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/test/*" + ) diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index 4aab32d..342606b 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -43,10 +43,79 @@ run_cmake(GLOB-error-FOLLOW_SYMLINKS) run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean) run_cmake(GLOB-error-LIST_DIRECTORIES-no-arg) run_cmake(GLOB-error-RELATIVE-no-arg) +run_cmake(GLOB-error-CONFIGURE_DEPENDS-modified) +run_cmake(GLOB-noexp-CONFIGURE_DEPENDS) run_cmake(GLOB-noexp-LIST_DIRECTORIES) run_cmake(GLOB-noexp-RELATIVE) +run_cmake_command(GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE ${CMAKE_COMMAND} -P + ${RunCMake_SOURCE_DIR}/GLOB-error-CONFIGURE_DEPENDS-SCRIPT_MODE.cmake) if(NOT WIN32 OR CYGWIN) run_cmake(GLOB_RECURSE-cyclic-recursion) run_cmake(INSTALL-SYMLINK) endif() + +if(RunCMake_GENERATOR STREQUAL "Ninja") + # Detect ninja version so we know what tests can be supported. + execute_process( + COMMAND "${RunCMake_MAKE_PROGRAM}" --version + OUTPUT_VARIABLE ninja_out + ERROR_VARIABLE ninja_out + RESULT_VARIABLE ninja_res + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(ninja_res EQUAL 0 AND "x${ninja_out}" MATCHES "^x[0-9]+\\.[0-9]+") + set(ninja_version "${ninja_out}") + message(STATUS "ninja version: ${ninja_version}") + else() + message(FATAL_ERROR "'ninja --version' reported:\n${ninja_out}") + endif() + + if("${ninja_version}" VERSION_LESS 1.8) + message(STATUS "Ninja is too old for GLOB CONFIGURE_DEPENDS; expect a warning.") + endif() +endif() + +if(RunCMake_GENERATOR STREQUAL "Ninja" AND "${ninja_version}" VERSION_LESS 1.8) + run_cmake(GLOB_RECURSE-warn-CONFIGURE_DEPENDS-ninja-version) +else() + run_cmake(GLOB-warn-CONFIGURE_DEPENDS-late) + + # Use a single build tree for a few tests without cleaning. + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/GLOB-CONFIGURE_DEPENDS-RerunCMake-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_DEFAULT_stderr ".*") + if(RunCMake_GENERATOR STREQUAL "Borland Makefiles" OR + RunCMake_GENERATOR STREQUAL "Watcom WMake") + set(fs_delay 3) + else() + set(fs_delay 1.125) + endif() + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test") + set(tf_1 "${RunCMake_TEST_BINARY_DIR}/test/1.txt") + file(WRITE "${tf_1}" "1") + + message(STATUS "GLOB-RerunCMake: first configuration...") + run_cmake(GLOB-CONFIGURE_DEPENDS-RerunCMake) + run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-build ${CMAKE_COMMAND} --build .) + + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) + message(STATUS "GLOB-CONFIGURE_DEPENDS-RerunCMake: add another file...") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/test/sub") + set(tf_2 "${RunCMake_TEST_BINARY_DIR}/test/sub/2.txt") + file(WRITE "${tf_2}" "2") + run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_first ${CMAKE_COMMAND} --build .) + run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .) + + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) + message(STATUS "GLOB-CONFIGURE_DEPENDS-RerunCMake: remove first test file...") + file(REMOVE "${RunCMake_TEST_BINARY_DIR}/test/1.txt") + run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-rebuild_second ${CMAKE_COMMAND} --build .) + run_cmake_command(GLOB-CONFIGURE_DEPENDS-RerunCMake-nowork ${CMAKE_COMMAND} --build .) + + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_NO_CLEAN) + unset(RunCMake_DEFAULT_stderr) +endif() diff --git a/Tests/UseSWIG/BasicConfiguration.cmake b/Tests/UseSWIG/BasicConfiguration.cmake index 73298567..d025d2a 100644 --- a/Tests/UseSWIG/BasicConfiguration.cmake +++ b/Tests/UseSWIG/BasicConfiguration.cmake @@ -2,6 +2,13 @@ find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) +# Path separator +if (WIN32) + set (PS "$<SEMICOLON>") +else() + set (PS ":") +endif() + unset(SWIG_LANG_TYPE) unset(SWIG_LANG_INCLUDE_DIRECTORIES) unset(SWIG_LANG_DEFINITIONS) diff --git a/Tests/UseSWIG/BasicPerl/CMakeLists.txt b/Tests/UseSWIG/BasicPerl/CMakeLists.txt index 10c1cd8..476ef0e 100644 --- a/Tests/UseSWIG/BasicPerl/CMakeLists.txt +++ b/Tests/UseSWIG/BasicPerl/CMakeLists.txt @@ -8,15 +8,7 @@ set(language "perl") include (../BasicConfiguration.cmake) -if (WIN32) - file (TO_CMAKE_PATH "$ENV{PATH}" perl_path) - string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}") - set (perl_env "PATH=$<TARGET_FILE_DIR:example>$<SEMICOLON>${perl_path}") -else() - set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:example>") -endif() - add_test (NAME BasicPerl - COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" - "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:example>" + COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}" + "-I$<TARGET_FILE_DIR:example>" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl") diff --git a/Tests/UseSWIG/BasicPython/CMakeLists.txt b/Tests/UseSWIG/BasicPython/CMakeLists.txt index 1ca4e25..cf1d821 100644 --- a/Tests/UseSWIG/BasicPython/CMakeLists.txt +++ b/Tests/UseSWIG/BasicPython/CMakeLists.txt @@ -9,5 +9,5 @@ set(language "python") include (../BasicConfiguration.cmake) add_test (NAME BasicPython - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example>" + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}${PS}$<TARGET_FILE_DIR:example>" "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") diff --git a/Tests/UseSWIG/LegacyConfiguration.cmake b/Tests/UseSWIG/LegacyConfiguration.cmake index 640c713..1acc05a 100644 --- a/Tests/UseSWIG/LegacyConfiguration.cmake +++ b/Tests/UseSWIG/LegacyConfiguration.cmake @@ -5,6 +5,13 @@ set (CMAKE_WARN_DEPRECATED FALSE) find_package(SWIG REQUIRED) include(${SWIG_USE_FILE}) +# Path separator +if (WIN32) + set (PS "$<SEMICOLON>") +else() + set (PS ":") +endif() + unset(SWIG_LANG_TYPE) if(${language} MATCHES python) find_package(PythonInterp REQUIRED) diff --git a/Tests/UseSWIG/LegacyPerl/CMakeLists.txt b/Tests/UseSWIG/LegacyPerl/CMakeLists.txt index 0def5f5..90d92f4 100644 --- a/Tests/UseSWIG/LegacyPerl/CMakeLists.txt +++ b/Tests/UseSWIG/LegacyPerl/CMakeLists.txt @@ -8,15 +8,7 @@ set(language "perl") include (../LegacyConfiguration.cmake) -if (WIN32) - file (TO_CMAKE_PATH "$ENV{PATH}" perl_path) - string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}") - set (perl_env "PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>$<SEMICOLON>${perl_path}") -else() - set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>") -endif() - add_test (NAME LegacyPerl - COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" - "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" + COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}" + "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl") diff --git a/Tests/UseSWIG/LegacyPython/CMakeLists.txt b/Tests/UseSWIG/LegacyPython/CMakeLists.txt index 11a0d28..03facb1 100644 --- a/Tests/UseSWIG/LegacyPython/CMakeLists.txt +++ b/Tests/UseSWIG/LegacyPython/CMakeLists.txt @@ -9,5 +9,5 @@ set(language "python") include (../LegacyConfiguration.cmake) add_test (NAME LegacyPython - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}${PS}$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>" "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") diff --git a/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt b/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt index 92cbcd3..3f9d363 100644 --- a/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt +++ b/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt @@ -10,6 +10,12 @@ include(${SWIG_USE_FILE}) find_package(Python2 REQUIRED COMPONENTS Interpreter Development) find_package(Python3 REQUIRED COMPONENTS Interpreter Development) +if (WIN32) + set (PS $<SEMICOLON>) +else() + set (PS ":") +endif() + set (UseSWIG_MODULE_VERSION 2) unset(CMAKE_SWIG_FLAGS) @@ -41,12 +47,6 @@ set_target_properties (example2 PROPERTIES target_link_libraries(example2 PRIVATE Python3::Python) -if (WIN32) - set (PS $<SEMICOLON>) -else() - set (PS ":") -endif() - add_test (NAME ModuleVersion2.example1 COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_PROPERTY:example1,SWIG_SUPPORT_FILES_DIRECTORY>${PS}$<TARGET_FILE_DIR:example1>" "${Python2_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") diff --git a/Tests/UseSWIG/MultipleModules/CMakeLists.txt b/Tests/UseSWIG/MultipleModules/CMakeLists.txt index d495007..578825f 100644 --- a/Tests/UseSWIG/MultipleModules/CMakeLists.txt +++ b/Tests/UseSWIG/MultipleModules/CMakeLists.txt @@ -12,6 +12,13 @@ find_package(Python REQUIRED COMPONENTS Interpreter Development) find_package(Perl REQUIRED) find_package(PerlLibs REQUIRED) +# Path separator +if (WIN32) + set (PS "$<SEMICOLON>") +else() + set (PS ":") +endif() + unset(CMAKE_SWIG_FLAGS) set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON) @@ -51,19 +58,11 @@ target_link_libraries(example2 PRIVATE ${PERL_LIBRARY}) add_test (NAME MultipleModules.Python - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example1>" + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python${PS}$<TARGET_FILE_DIR:example1>" "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") -if (WIN32) - file (TO_CMAKE_PATH "$ENV{PATH}" perl_path) - string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}") - set (perl_env "PATH=$<TARGET_FILE_DIR:example2>$<SEMICOLON>${perl_path}") -else() - set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:example2>") -endif() - add_test (NAME MultipleModules.Perl - COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}" - "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:example2>" + COMMAND "${PERL_EXECUTABLE}" "-I${CMAKE_CURRENT_BINARY_DIR}/Perl" + "-I$<TARGET_FILE_DIR:example2>" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.pl") diff --git a/Tests/UseSWIG/MultiplePython/CMakeLists.txt b/Tests/UseSWIG/MultiplePython/CMakeLists.txt index 260a382..a5e3eed 100644 --- a/Tests/UseSWIG/MultiplePython/CMakeLists.txt +++ b/Tests/UseSWIG/MultiplePython/CMakeLists.txt @@ -10,6 +10,13 @@ include(${SWIG_USE_FILE}) find_package(Python2 REQUIRED COMPONENTS Interpreter Development) find_package(Python3 REQUIRED COMPONENTS Interpreter Development) +# Path separator +if (WIN32) + set (PS "$<SEMICOLON>") +else() + set (PS ":") +endif() + unset(CMAKE_SWIG_FLAGS) set_property(SOURCE "../example.i" PROPERTY CPLUSPLUS ON) @@ -44,9 +51,9 @@ target_link_libraries(example2 PRIVATE Python3::Python) add_test (NAME MultiplePython.example1 - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example1>" + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python2${PS}$<TARGET_FILE_DIR:example1>" "${Python2_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") add_test (NAME MultiplePython.example2 - COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example2>" + COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/Python3${PS}$<TARGET_FILE_DIR:example2>" "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/../runme.py") @@ -332,6 +332,7 @@ CMAKE_CXX_SOURCES="\ cmGlobalCommonGenerator \ cmGlobalGenerator \ cmGlobalUnixMakefileGenerator3 \ + cmGlobVerificationManager \ cmHexFileConverter \ cmIfCommand \ cmIncludeCommand \ |