diff options
44 files changed, 434 insertions, 218 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e4d2a9a..6623959 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,6 +310,8 @@ endmacro() # Simply to improve readability of the main script. #----------------------------------------------------------------------- macro (CMAKE_BUILD_UTILITIES) + find_package(Threads) + #--------------------------------------------------------------------- # Create the kwsys library for CMake. set(KWSYS_NAMESPACE cmsys) diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 3ac5123..13a72df 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -178,6 +178,7 @@ Variables that Change Behavior /variable/CMAKE_STAGING_PREFIX /variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS /variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE + /variable/CMAKE_SUPPRESS_REGENERATION /variable/CMAKE_SYSROOT /variable/CMAKE_SYSROOT_COMPILE /variable/CMAKE_SYSROOT_LINK diff --git a/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst b/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst new file mode 100644 index 0000000..dfe678c --- /dev/null +++ b/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst @@ -0,0 +1,6 @@ +variable-CMAKE_SUPPRESS_REGENERATION +------------------------------------ + +* The :variable:`CMAKE_SUPPRESS_REGENERATION` variable was extended to support the + :generator:`Ninja` and :ref:`Makefile Generators`. +* The :variable:`CMAKE_SUPPRESS_REGENERATION` variable is now documented. diff --git a/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst b/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst new file mode 100644 index 0000000..ed47e1a --- /dev/null +++ b/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst @@ -0,0 +1,11 @@ +CMAKE_SUPPRESS_REGENERATION +--------------------------- + +If CMAKE_SUPPRESS_REGENERATION is ``OFF``, which is default, then CMake adds a +special target on which all other targets depend that checks the build system +and optionally re-runs CMake to regenerate the build system when the target +specification source changes. + +If this variable evaluates to ``ON`` at the end of the top-level +``CMakeLists.txt`` file, CMake will not add the regeneration target to the +build system or perform any build system checks. diff --git a/Modules/FindGDAL.cmake b/Modules/FindGDAL.cmake index ceb8eee..2b940b0 100644 --- a/Modules/FindGDAL.cmake +++ b/Modules/FindGDAL.cmake @@ -49,6 +49,7 @@ find_path(GDAL_INCLUDE_DIR gdal.h PATH_SUFFIXES include/gdal include/GDAL + include ) if(UNIX) @@ -60,6 +61,7 @@ if(UNIX) HINTS ENV GDAL_DIR ENV GDAL_ROOT + PATH_SUFFIXES bin ) if(GDAL_CONFIG) @@ -79,6 +81,7 @@ find_library(GDAL_LIBRARY ENV GDAL_DIR ENV GDAL_ROOT ${_gdal_libpath} + PATH_SUFFIXES lib ) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) diff --git a/Modules/FindGIF.cmake b/Modules/FindGIF.cmake index 4b2f882..efc3973 100644 --- a/Modules/FindGIF.cmake +++ b/Modules/FindGIF.cmake @@ -30,6 +30,7 @@ find_path(GIF_INCLUDE_DIR gif_lib.h HINTS ENV GIF_DIR + PATH_SUFFIXES include ) # the gif library can have many names :-/ @@ -39,6 +40,7 @@ find_library(GIF_LIBRARY NAMES ${POTENTIAL_GIF_LIBS} HINTS ENV GIF_DIR + PATH_SUFFIXES lib ) # see readme.txt diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake index e3f5af6..c56c197 100644 --- a/Modules/FindJava.cmake +++ b/Modules/FindJava.cmake @@ -18,7 +18,7 @@ # :: # # Runtime = User just want to execute some Java byte-compiled -# Development = Development tools (java, javac, javah and javadoc), includes Runtime component +# Development = Development tools (java, javac, javah, jar and javadoc), includes Runtime component # IdlJ = idl compiler for Java # JarSigner = signer tool for jar # @@ -237,16 +237,16 @@ if(Java_FIND_COMPONENTS) endif() elseif(component STREQUAL "Development") list(APPEND _JAVA_REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAVAC_EXECUTABLE - Java_JAVADOC_EXECUTABLE) + Java_JAR_EXECUTABLE Java_JAVADOC_EXECUTABLE) if(Java_VERSION VERSION_LESS "1.10") list(APPEND _JAVA_REQUIRED_VARS Java_JAVAH_EXECUTABLE) if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE - AND Java_JAVAH_EXECUTABLE AND Java_JAVADOC_EXECUTABLE) + AND Java_JAVAH_EXECUTABLE AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE) set(Java_Development_FOUND TRUE) endif() else() if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE - AND Java_JAVADOC_EXECUTABLE) + AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE) set(Java_Development_FOUND TRUE) endif() endif() diff --git a/Modules/FindOpenThreads.cmake b/Modules/FindOpenThreads.cmake index b1b116a..a197e4d 100644 --- a/Modules/FindOpenThreads.cmake +++ b/Modules/FindOpenThreads.cmake @@ -58,6 +58,7 @@ find_path(OPENTHREADS_INCLUDE_DIR OpenThreads/Thread ENV OSG_ROOT ${OPENTHREADS_DIR} ${OSG_DIR} + PATH_SUFFIXES include ) @@ -73,6 +74,7 @@ find_library(OPENTHREADS_LIBRARY ENV OSG_ROOT ${OPENTHREADS_DIR} ${OSG_DIR} + PATH_SUFFIXES lib ) find_library(OPENTHREADS_LIBRARY_DEBUG @@ -88,6 +90,7 @@ find_library(OPENTHREADS_LIBRARY_DEBUG ENV OSG_ROOT ${OPENTHREADS_DIR} ${OSG_DIR} + PATH_SUFFIXES lib ) if(OPENTHREADS_LIBRARY_DEBUG) diff --git a/Modules/Findosg_functions.cmake b/Modules/Findosg_functions.cmake index 83d9844..60de726 100644 --- a/Modules/Findosg_functions.cmake +++ b/Modules/Findosg_functions.cmake @@ -28,6 +28,7 @@ function(OSG_FIND_PATH module header) ENV OSG_ROOT ${${module_uc}_DIR} ${OSG_DIR} + PATH_SUFFIXES include ) endfunction() @@ -47,6 +48,7 @@ function(OSG_FIND_LIBRARY module library) ENV OSG_ROOT ${${module_uc}_DIR} ${OSG_DIR} + PATH_SUFFIXES lib ) find_library(${module_uc}_LIBRARY_DEBUG @@ -58,6 +60,7 @@ function(OSG_FIND_LIBRARY module library) ENV OSG_ROOT ${${module_uc}_DIR} ${OSG_DIR} + PATH_SUFFIXES lib ) if(NOT ${module_uc}_LIBRARY_DEBUG) diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index 0737c12..a1f54c0 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -293,6 +293,34 @@ macro(__windows_compiler_msvc lang) set(CMAKE_${lang}_LINK_EXECUTABLE "${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") + if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC") + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "/GL") + set(CMAKE_${lang}_LINK_OPTIONS_IPO "/INCREMENTAL:NO" "/LTCG") + string(REPLACE "<LINK_FLAGS> " "/LTCG <LINK_FLAGS> " + CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}") + elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" OR + "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFlang") + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + + # '-flto=thin' available since Clang 3.9 and Xcode 8 + # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm + # * https://trac.macports.org/wiki/XcodeVersionInfo + set(_CMAKE_LTO_THIN TRUE) + if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9) + set(_CMAKE_LTO_THIN FALSE) + endif() + + if(_CMAKE_LTO_THIN) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin") + else() + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") + endif() + endif() + if("x${lang}" STREQUAL "xC" OR "x${lang}" STREQUAL "xCXX") if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index e7c0732..a0010a2 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -765,6 +765,7 @@ target_link_libraries(CMakeLib cmsys ${CMAKE_LIBUV_LIBRARIES} ${CMAKE_LIBRHASH_LIBRARIES} ${CMake_KWIML_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} ) if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b6f25bb..307b65d 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 20180222) +set(CMake_VERSION_PATCH 20180228) #set(CMake_VERSION_RC 1) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 8410609..55a403e 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1223,11 +1223,13 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) for (std::string const& file : files) { knownDependencies.insert(this->ConvertToNinjaPath(file)); } - // get list files which are implicit dependencies as well and will be phony - // for rebuild manifest - std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles(); - for (std::string const& j : lf) { - knownDependencies.insert(this->ConvertToNinjaPath(j)); + if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + // get list files which are implicit dependencies as well and will be + // phony for rebuild manifest + std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles(); + for (std::string const& j : lf) { + knownDependencies.insert(this->ConvertToNinjaPath(j)); + } } std::vector<cmGeneratorExpressionEvaluationFile*> const& ef = lg->GetMakefile()->GetEvaluationFiles(); @@ -1335,6 +1337,9 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os) void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) { + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + return; + } cmLocalGenerator* lg = this->LocalGenerators[0]; std::ostringstream cmd; diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index d990a6c..43032fb 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -256,6 +256,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2() void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile() { + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + return; + } + // Open the output file. This should not be copy-if-different // because the check-build-system step compares the makefile time to // see if the build system must be regenerated. @@ -525,7 +529,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( std::vector<std::string> depends; std::vector<std::string> commands; - depends.push_back("cmake_check_build_system"); + bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); + if (regenerate) { + depends.push_back("cmake_check_build_system"); + } // write the target convenience rules for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -558,7 +565,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules( tmp += "Makefile2"; commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name)); depends.clear(); - depends.push_back("cmake_check_build_system"); + if (regenerate) { + depends.push_back("cmake_check_build_system"); + } lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name, depends, commands, true); @@ -609,7 +618,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( // write the directory level rules for this local gen this->WriteDirectoryRules2(ruleFileStream, lg); - depends.push_back("cmake_check_build_system"); + bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); + if (regenerate) { + depends.push_back("cmake_check_build_system"); + } // for each target Generate the rule files for each target. const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets(); @@ -715,7 +727,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2( commands.push_back(progCmd.str()); } depends.clear(); - depends.push_back("cmake_check_build_system"); + if (regenerate) { + depends.push_back("cmake_check_build_system"); + } localName = lg->GetRelativeTargetDirectory(gtarget); localName += "/rule"; lg->WriteMakeRule(ruleFileStream, @@ -898,7 +912,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule( "for this Makefile:"); lg->AppendEcho(commands, "... all (the default if no target is provided)"); lg->AppendEcho(commands, "... clean"); - lg->AppendEcho(commands, "... depend"); + if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { + lg->AppendEcho(commands, "... depend"); + } // Keep track of targets already listed. std::set<std::string> emittedTargets; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index ab8ad70..87804ff 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -217,7 +217,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() cmMakefile* mf = lg->GetMakefile(); // Skip the target if no regeneration is to be done. - if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) { + if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) { return false; } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index a4570e1..fa7dc51 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -737,26 +737,24 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly( bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly( cmGeneratorTarget const* gt) { - // check to see if this is a C# build - std::set<std::string> languages; - { - // Issue diagnostic if the source files depend on the config. - std::vector<cmSourceFile*> sources; - if (!gt->GetConfigCommonSourceFiles(sources)) { - return false; - } - // Only "real" targets are allowed to be C# targets. - if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) { - return false; - } + // C# targets can be defined with add_library() (using SHARED or STATIC) and + // also using add_executable(). We do not treat imported C# targets the same + // (these come in as UTILITY) + if (gt->GetType() != cmStateEnums::SHARED_LIBRARY && + gt->GetType() != cmStateEnums::STATIC_LIBRARY && + gt->GetType() != cmStateEnums::EXECUTABLE) { + return false; } - gt->GetLanguages(languages, ""); - if (languages.size() == 1) { - if (*languages.begin() == "CSharp") { - return true; - } + + // Issue diagnostic if the source files depend on the config. + std::vector<cmSourceFile*> sources; + if (!gt->GetConfigCommonSourceFiles(sources)) { + return false; } - return false; + + std::set<std::string> languages; + gt->GetLanguages(languages, ""); + return languages.size() == 1 && languages.count("CSharp") > 0; } bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced( diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 2a38599..0d5dad2 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -458,8 +458,12 @@ void cmGlobalXCodeGenerator::AddExtraTargets( makeHelper.push_back(""); // placeholder, see below // Add ZERO_CHECK - bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); - if (regenerate) { + bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); + bool generateTopLevelProjectOnly = + mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + bool isTopLevel = + !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid(); + if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) { this->CreateReRunCMakeFile(root, gens); std::string file = this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str()); diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx index 354b757..f996788 100644 --- a/Source/cmIDEOptions.cxx +++ b/Source/cmIDEOptions.cxx @@ -25,7 +25,7 @@ cmIDEOptions::~cmIDEOptions() { } -void cmIDEOptions::HandleFlag(const char* flag) +void cmIDEOptions::HandleFlag(std::string const& flag) { // If the last option was -D then this option is the definition. if (this->DoingDefine) { @@ -49,26 +49,27 @@ void cmIDEOptions::HandleFlag(const char* flag) } // Look for known arguments. - if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) { + size_t len = flag.length(); + if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) { // Look for preprocessor definitions. - if (this->AllowDefine && flag[1] == 'D') { - if (flag[2] == '\0') { + if (this->AllowDefine && len > 1 && flag[1] == 'D') { + if (len <= 2) { // The next argument will have the definition. this->DoingDefine = true; } else { // Store this definition. - this->Defines.push_back(flag + 2); + this->Defines.push_back(flag.substr(2)); } return; } // Look for include directory. - if (this->AllowInclude && flag[1] == 'I') { - if (flag[2] == '\0') { + if (this->AllowInclude && len > 1 && flag[1] == 'I') { + if (len <= 2) { // The next argument will have the include directory. this->DoingInclude = true; } else { // Store this include directory. - this->Includes.push_back(flag + 2); + this->Includes.push_back(flag.substr(2)); } return; } @@ -92,8 +93,9 @@ void cmIDEOptions::HandleFlag(const char* flag) } bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table, - const char* flag, bool& flag_handled) + std::string const& flag, bool& flag_handled) { + const char* pf = flag.c_str() + 1; // Look for an entry in the flag table matching this flag. for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) { bool entry_found = false; @@ -102,17 +104,17 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table, // the entry specifies UserRequired we must match only if a // non-empty value is given. int n = static_cast<int>(strlen(entry->commandFlag)); - if ((strncmp(flag + 1, entry->commandFlag, n) == 0 || + if ((strncmp(pf, entry->commandFlag, n) == 0 || (entry->special & cmIDEFlagTable::CaseInsensitive && - cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) && + cmsysString_strncasecmp(pf, entry->commandFlag, n))) && (!(entry->special & cmIDEFlagTable::UserRequired) || - static_cast<int>(strlen(flag + 1)) > n)) { - this->FlagMapUpdate(entry, flag + n + 1); + static_cast<int>(strlen(pf)) > n)) { + this->FlagMapUpdate(entry, std::string(pf + n)); entry_found = true; } - } else if (strcmp(flag + 1, entry->commandFlag) == 0 || + } else if (strcmp(pf, entry->commandFlag) == 0 || (entry->special & cmIDEFlagTable::CaseInsensitive && - cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) { + cmsysString_strcasecmp(pf, entry->commandFlag) == 0)) { if (entry->special & cmIDEFlagTable::UserFollowing) { // This flag expects a value in the following argument. this->DoingFollowing = entry; @@ -137,7 +139,7 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table, } void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry, - const char* new_value) + std::string const& new_value) { if (entry->special & cmIDEFlagTable::UserIgnored) { // Ignore the user-specified value. @@ -157,9 +159,9 @@ void cmIDEOptions::AddDefine(const std::string& def) this->Defines.push_back(def); } -void cmIDEOptions::AddDefines(const char* defines) +void cmIDEOptions::AddDefines(std::string const& defines) { - if (defines) { + if (!defines.empty()) { // Expand the list of definitions. cmSystemTools::ExpandListArgument(defines, this->Defines); } @@ -179,9 +181,9 @@ void cmIDEOptions::AddInclude(const std::string& include) this->Includes.push_back(include); } -void cmIDEOptions::AddIncludes(const char* includes) +void cmIDEOptions::AddIncludes(std::string const& includes) { - if (includes) { + if (!includes.empty()) { // Expand the list of includes. cmSystemTools::ExpandListArgument(includes, this->Includes); } diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h index 54cb524..a4e5757 100644 --- a/Source/cmIDEOptions.h +++ b/Source/cmIDEOptions.h @@ -22,12 +22,12 @@ public: // Store definitions, includes and flags. void AddDefine(const std::string& define); - void AddDefines(const char* defines); + void AddDefines(std::string const& defines); void AddDefines(const std::vector<std::string>& defines); std::vector<std::string> const& GetDefines() const; void AddInclude(const std::string& includes); - void AddIncludes(const char* includes); + void AddIncludes(std::string const& includes); void AddIncludes(const std::vector<std::string>& includes); std::vector<std::string> const& GetIncludes() const; @@ -95,11 +95,12 @@ protected: FlagTableCount = 16 }; cmIDEFlagTable const* FlagTable[FlagTableCount]; - void HandleFlag(const char* flag); - bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag, + void HandleFlag(std::string const& flag); + bool CheckFlagTable(cmIDEFlagTable const* table, std::string const& flag, bool& flag_handled); - void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value); - virtual void StoreUnknownFlag(const char* flag) = 0; + void FlagMapUpdate(cmIDEFlagTable const* entry, + std::string const& new_value); + virtual void StoreUnknownFlag(std::string const& flag) = 0; }; #endif diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index ddd8cc4..c9237a8 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -760,7 +760,8 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom( // Write special "cmake_check_build_system" target to run cmake with // the --check-build-system flag. - { + if (!this->GlobalGenerator->GlobalSettingIsOn( + "CMAKE_SUPPRESS_REGENERATION")) { // Build command to run CMake to check if anything needs regenerating. std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); cmakefileName += "Makefile.cmake"; @@ -1580,7 +1581,11 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( std::string recursiveTarget = this->GetCurrentBinaryDirectory(); recursiveTarget += "/all"; - depends.push_back("cmake_check_build_system"); + bool regenerate = + !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); + if (regenerate) { + depends.push_back("cmake_check_build_system"); + } std::string progressDir = this->GetBinaryDirectory(); progressDir += cmake::GetCMakeFilesDirectory(); @@ -1643,7 +1648,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( if (!noall || cmSystemTools::IsOff(noall)) { // Drive the build before installing. depends.push_back("all"); - } else { + } else if (regenerate) { // At least make sure the build system is up to date. depends.push_back("cmake_check_build_system"); } @@ -1657,24 +1662,26 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules( this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.", "preinstall/fast", depends, commands, true); - // write the depend rule, really a recompute depends rule - depends.clear(); - commands.clear(); - std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); - cmakefileName += "Makefile.cmake"; - { - std::string runRule = - "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; - runRule += " --check-build-system "; - runRule += - this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); - runRule += " 1"; - commands.push_back(std::move(runRule)); + if (regenerate) { + // write the depend rule, really a recompute depends rule + depends.clear(); + commands.clear(); + std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash(); + cmakefileName += "Makefile.cmake"; + { + std::string runRule = + "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)"; + runRule += " --check-build-system "; + runRule += + this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL); + runRule += " 1"; + commands.push_back(std::move(runRule)); + } + this->CreateCDCommand(commands, this->GetBinaryDirectory(), + this->GetCurrentBinaryDirectory()); + this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends, + commands, true); } - this->CreateCDCommand(commands, this->GetBinaryDirectory(), - this->GetCurrentBinaryDirectory()); - this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends, - commands, true); } void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 98b1c44..500a0aa 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -210,7 +210,8 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj( cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() { - if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) { + if (this->GlobalGenerator->GlobalSettingIsOn( + "CMAKE_SUPPRESS_REGENERATION")) { return nullptr; } @@ -1677,8 +1678,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup( } Options fileOptions(this, tool, table, gg->ExtraFlagTable); fileOptions.Parse(fc.CompileFlags.c_str()); - fileOptions.AddDefines(fc.CompileDefs.c_str()); - fileOptions.AddDefines(fc.CompileDefsConfig.c_str()); + fileOptions.AddDefines(fc.CompileDefs); + fileOptions.AddDefines(fc.CompileDefsConfig); // validate source level include directories std::vector<std::string> includes; this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 82c6e81..47d75af 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -3138,6 +3138,14 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args) cmSourceFile* cmMakefile::GetSource(const std::string& sourceName, cmSourceFileLocationKind kind) const { + // First check "Known" paths (avoids the creation of cmSourceFileLocation) + if (kind == cmSourceFileLocationKind::Known) { + auto sfsi = this->KnownFileSearchIndex.find(sourceName); + if (sfsi != this->KnownFileSearchIndex.end()) { + return sfsi->second; + } + } + cmSourceFileLocation sfl(this, sourceName, kind); auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName()); #if defined(_WIN32) || defined(__APPLE__) @@ -3170,6 +3178,10 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, name = cmSystemTools::LowerCase(name); #endif this->SourceFileSearchIndex[name].push_back(sf); + // for "Known" paths add direct lookup (used for faster lookup in GetSource) + if (kind == cmSourceFileLocationKind::Known) { + this->KnownFileSearchIndex[sourceName] = sf; + } return sf; } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 5a30790..95ba53a 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -861,6 +861,9 @@ protected: typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap; SourceFileMap SourceFileSearchIndex; + // For "Known" paths we can store a direct filename to cmSourceFile map + std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex; + // Tests std::map<std::string, cmTest*> Tests; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 60c5a65..fa7d95a 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -869,9 +869,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["FLAGS"] = this->ComputeFlagsForObject(source, language); vars["DEFINES"] = this->ComputeDefines(source, language); vars["INCLUDES"] = this->ComputeIncludes(source, language); + if (!this->NeedDepTypeMSVC(language)) { - vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( - objectFileName + ".d", cmOutputConverter::SHELL); + bool replaceExt(false); + if (!language.empty()) { + std::string repVar = "CMAKE_"; + repVar += language; + repVar += "_DEPFILE_EXTENSION_REPLACE"; + replaceExt = this->Makefile->IsOn(repVar); + } + if (!replaceExt) { + // use original code + vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( + objectFileName + ".d", cmOutputConverter::SHELL); + } else { + // Replace the original source file extension with the + // depend file extension. + std::string dependFileName = + cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d"; + vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat( + objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL); + } } this->ExportObjectCompileCommand( diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 25db929..6519dd9 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -6,7 +6,7 @@ #include <assert.h> #include <ctype.h> #include <set> -#include <sstream> +#include <string.h> #include <vector> #include "cmAlgorithms.h" @@ -341,12 +341,14 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to use the caret character itself (^), use two in a row (^^). */ -int cmOutputConverter::Shell__CharIsWhitespace(char c) +/* Some helpers to identify character classes */ +namespace { +inline int Shell__CharIsWhitespace(char c) { return ((c == ' ') || (c == '\t')); } -int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c) +inline int Shell__CharNeedsQuotesOnUnix(char c) { return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') || (c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') || @@ -354,12 +356,18 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c) (c == '\\')); } -int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c) +inline int Shell__CharNeedsQuotesOnWindows(char c) { return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') || (c == '>') || (c == '|') || (c == '^')); } +inline int Shell__CharIsMakeVariableName(char c) +{ + return c && (c == '_' || isalpha((static_cast<int>(c)))); +} +} + int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) { /* On Windows the built-in command shell echo never needs quotes. */ @@ -386,11 +394,6 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags) return 0; } -int cmOutputConverter::Shell__CharIsMakeVariableName(char c) -{ - return c && (c == '_' || isalpha((static_cast<int>(c)))); -} - const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c) { while (*c == '$' && *(c + 1) == '(') { @@ -481,7 +484,9 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags) std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) { - std::ostringstream out; + /* Output will be at least as long as input string. */ + std::string out; + out.reserve(strlen(in)); /* String iterator. */ const char* c; @@ -495,11 +500,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* Add the opening quote for this argument. */ if (flags & Shell_Flag_WatcomQuote) { if (flags & Shell_Flag_IsUnix) { - out << '"'; + out += '"'; } - out << '\''; + out += '\''; } else { - out << '"'; + out += '"'; } } @@ -511,7 +516,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) if (skip != c) { /* Copy to the end of the make variable references. */ while (c != skip) { - out << *c++; + out += *c++; } /* The make variable reference eliminates any escaping needed @@ -531,7 +536,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) quoted argument. */ if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') { /* This character needs a backslash to escape it. */ - out << '\\'; + out += '\\'; } } else if (flags & Shell_Flag_EchoWindows) { /* On Windows the built-in command shell echo never needs escaping. */ @@ -545,11 +550,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) backslashes. */ while (windows_backslashes > 0) { --windows_backslashes; - out << '\\'; + out += '\\'; } /* Add the backslash to escape the double-quote. */ - out << '\\'; + out += '\\'; } else { /* We encountered a normal character. This eliminates any escaping needed for preceding backslashes. */ @@ -562,7 +567,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) if (flags & Shell_Flag_Make) { /* In Makefiles a dollar is written $$. The make tool will replace it with just $ before passing it to the shell. */ - out << "$$"; + out += "$$"; } else if (flags & Shell_Flag_VSIDE) { /* In a VS IDE a dollar is written "$". If this is written in an un-quoted argument it starts a quoted segment, inserts @@ -570,30 +575,30 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) argument it ends quoting, inserts the $ and restarts quoting. Either way the $ is isolated from surrounding text to avoid looking like a variable reference. */ - out << "\"$\""; + out += "\"$\""; } else { /* Otherwise a dollar is written just $. */ - out << '$'; + out += '$'; } } else if (*c == '#') { if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) { /* In Watcom WMake makefiles a pound is written $#. The make tool will replace it with just # before passing it to the shell. */ - out << "$#"; + out += "$#"; } else { /* Otherwise a pound is written just #. */ - out << '#'; + out += '#'; } } else if (*c == '%') { if ((flags & Shell_Flag_VSIDE) || ((flags & Shell_Flag_Make) && ((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) { /* In the VS IDE, NMake, or MinGW make a percent is written %%. */ - out << "%%"; + out += "%%"; } else { /* Otherwise a percent is written just %. */ - out << '%'; + out += '%'; } } else if (*c == ';') { if (flags & Shell_Flag_VSIDE) { @@ -602,14 +607,14 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) inserts the ; and ends the segment. If it is written in a quoted argument it ends quoting, inserts the ; and restarts quoting. Either way the ; is isolated. */ - out << "\";\""; + out += "\";\""; } else { /* Otherwise a semicolon is written just ;. */ - out << ';'; + out += ';'; } } else { /* Store this character. */ - out << *c; + out += *c; } } @@ -617,19 +622,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags) /* Add enough backslashes to escape any trailing ones. */ while (windows_backslashes > 0) { --windows_backslashes; - out << '\\'; + out += '\\'; } /* Add the closing quote for this argument. */ if (flags & Shell_Flag_WatcomQuote) { - out << '\''; + out += '\''; if (flags & Shell_Flag_IsUnix) { - out << '"'; + out += '"'; } } else { - out << '"'; + out += '"'; } } - return out.str(); + return out; } diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index ae15055..ed7143c 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -117,11 +117,7 @@ public: private: cmState* GetState() const; - static int Shell__CharIsWhitespace(char c); - static int Shell__CharNeedsQuotesOnUnix(char c); - static int Shell__CharNeedsQuotesOnWindows(char c); static int Shell__CharNeedsQuotes(char c, int flags); - static int Shell__CharIsMakeVariableName(char c); static const char* Shell__SkipMakeVariables(const char* c); static int Shell__ArgumentNeedsQuotes(const char* in, int flags); static std::string Shell__GetArgument(const char* in, int flags); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 92d67db..ed4a201 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -856,10 +856,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences() void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences() { - for (std::vector<TargetsFileAndConfigs>::iterator i = - this->TargetsFileAndConfigsVec.begin(); - i != this->TargetsFileAndConfigsVec.end(); ++i) { - TargetsFileAndConfigs const& tac = *i; + for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) { this->WriteString("<Import Project=\"", 3); (*this->BuildFileStream) << tac.File << "\" "; (*this->BuildFileStream) << "Condition=\""; @@ -894,10 +891,9 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences() } if (!references.empty()) { this->WriteString("<ItemGroup>\n", 1); - for (std::vector<std::string>::iterator ri = references.begin(); - ri != references.end(); ++ri) { + for (std::string const& ri : references) { this->WriteString("<Reference Include=\"", 2); - (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n"; + (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\">\n"; this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3); this->WriteString("</Reference>\n", 2); } @@ -910,13 +906,11 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences() void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() { this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1); - for (std::vector<std::string>::const_iterator i = - this->Configurations.begin(); - i != this->Configurations.end(); ++i) { + for (std::string const& c : this->Configurations) { this->WriteString("<ProjectConfiguration Include=\"", 2); - (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n"; + (*this->BuildFileStream) << c << "|" << this->Platform << "\">\n"; this->WriteString("<Configuration>", 3); - (*this->BuildFileStream) << *i << "</Configuration>\n"; + (*this->BuildFileStream) << c << "</Configuration>\n"; this->WriteString("<Platform>", 3); (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform) << "</Platform>\n"; @@ -927,10 +921,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() { - for (std::vector<std::string>::const_iterator i = - this->Configurations.begin(); - i != this->Configurations.end(); ++i) { - this->WritePlatformConfigTag("PropertyGroup", *i, 1, + for (std::string const& c : this->Configurations) { + this->WritePlatformConfigTag("PropertyGroup", c, 1, " Label=\"Configuration\"", "\n"); if (this->ProjectType != csproj) { @@ -977,12 +969,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() if (this->MSTools) { if (!this->Managed) { - this->WriteMSToolConfigurationValues(*i); + this->WriteMSToolConfigurationValues(c); } else { - this->WriteMSToolConfigurationValuesManaged(*i); + this->WriteMSToolConfigurationValuesManaged(c); } } else if (this->NsightTegra) { - this->WriteNsightTegraConfigurationValues(*i); + this->WriteNsightTegraConfigurationValues(c); } this->WriteString("</PropertyGroup>\n", 1); @@ -1132,10 +1124,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands() this->CSharpCustomCommandNames.clear(); std::vector<cmSourceFile const*> customCommands; this->GeneratorTarget->GetCustomCommands(customCommands, ""); - for (std::vector<cmSourceFile const*>::const_iterator si = - customCommands.begin(); - si != customCommands.end(); ++si) { - this->WriteCustomCommand(*si); + for (cmSourceFile const* si : customCommands) { + this->WriteCustomCommand(si); } // Add CMakeLists.txt file with rule to re-run CMake for user convenience. @@ -1154,9 +1144,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand( if (this->SourcesVisited.insert(sf).second) { if (std::vector<cmSourceFile*> const* depends = this->GeneratorTarget->GetSourceDepends(sf)) { - for (std::vector<cmSourceFile*>::const_iterator di = depends->begin(); - di != depends->end(); ++di) { - this->WriteCustomCommand(*di); + for (cmSourceFile const* di : *depends) { + this->WriteCustomCommand(di); } } if (cmCustomCommand const* command = sf->GetCustomCommand()) { @@ -1179,10 +1168,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( // VS 10 will always rebuild a custom command attached to a .rule // file that doesn't exist so create the file explicitly. if (source->GetPropertyAsBool("__CMAKE_RULE")) { - if (!cmSystemTools::FileExists(sourcePath.c_str())) { + if (!cmSystemTools::FileExists(sourcePath)) { // Make sure the path exists for the file std::string path = cmSystemTools::GetFilenamePath(sourcePath); - cmSystemTools::MakeDirectory(path.c_str()); + cmSystemTools::MakeDirectory(path); cmsys::ofstream fout(sourcePath.c_str()); if (fout) { fout << "# generated from CMake\n"; @@ -1216,20 +1205,17 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( this->WriteString("</None>\n", 2); this->WriteString("</ItemGroup>\n", 1); } - for (std::vector<std::string>::const_iterator i = - this->Configurations.begin(); - i != this->Configurations.end(); ++i) { - cmCustomCommandGenerator ccg(command, *i, lg); + for (std::string const& c : this->Configurations) { + cmCustomCommandGenerator ccg(command, c, lg); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg)); // input files for custom command std::stringstream inputs; inputs << cmVS10EscapeXML(source->GetFullPath()); - for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin(); - d != ccg.GetDepends().end(); ++d) { + for (std::string const& d : ccg.GetDepends()) { std::string dep; - if (lg->GetRealDependency(*d, *i, dep)) { + if (lg->GetRealDependency(d, c, dep)) { ConvertToWindowsSlash(dep); inputs << ";" << cmVS10EscapeXML(dep); } @@ -1237,15 +1223,14 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( // output files for custom command std::stringstream outputs; const char* sep = ""; - for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin(); - o != ccg.GetOutputs().end(); ++o) { - std::string out = *o; + for (std::string const& o : ccg.GetOutputs()) { + std::string out = o; ConvertToWindowsSlash(out); outputs << sep << cmVS10EscapeXML(out); sep = ";"; } if (this->ProjectType == csproj) { - std::string name = "CustomCommand_" + *i + "_" + + std::string name = "CustomCommand_" + c + "_" + cmSystemTools::ComputeStringMD5(sourcePath); std::string inputs_s = inputs.str(); std::string outputs_s = outputs.str(); @@ -1253,10 +1238,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( script = cmVS10EscapeQuotes(script); inputs_s = cmVS10EscapeQuotes(inputs_s); outputs_s = cmVS10EscapeQuotes(outputs_s); - this->WriteCustomRuleCSharp(*i, name, script, inputs_s, outputs_s, + this->WriteCustomRuleCSharp(c, name, script, inputs_s, outputs_s, comment); } else { - this->WriteCustomRuleCpp(*i, script, inputs.str(), outputs.str(), + this->WriteCustomRuleCpp(c, script, inputs.str(), outputs.str(), comment); } } @@ -1314,8 +1299,8 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath( { return forceRelative ? cmSystemTools::RelativePath( - this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str()) - : path.c_str(); + this->LocalGenerator->GetCurrentBinaryDirectory(), path) + : path; } static void ConvertToWindowsSlash(std::string& s) @@ -1341,10 +1326,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->GeneratorTarget->GetAllConfigSources(); std::set<cmSourceGroup*> groupsUsed; - for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si = - sources.begin(); - si != sources.end(); ++si) { - std::string const& source = si->Source->GetFullPath(); + for (cmGeneratorTarget::AllConfigSource const& si : sources) { + std::string const& source = si.Source->GetFullPath(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source, sourceGroups); groupsUsed.insert(sourceGroup); @@ -1376,9 +1359,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups() "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n"); this->WriteString(project_defaults.c_str(), 0); - for (ToolSourceMap::const_iterator ti = this->Tools.begin(); - ti != this->Tools.end(); ++ti) { - this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups); + for (auto const& ti : this->Tools) { + this->WriteGroupSources(ti.first.c_str(), ti.second, sourceGroups); } // Added files are images and the manifest. @@ -1510,7 +1492,7 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups( } void cmVisualStudio10TargetGenerator::WriteGroupSources( - const char* name, ToolSources const& sources, + std::string const& name, ToolSources const& sources, std::vector<cmSourceGroup>& sourceGroups) { this->WriteString("<ItemGroup>\n", 1); @@ -1847,7 +1829,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool, std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative); if (this->LocalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS10 && - cmSystemTools::FileIsFullPath(sourceFile.c_str())) { + cmSystemTools::FileIsFullPath(sourceFile)) { // Normal path conversion resulted in a full path. VS 10 (but not 11) // refuses to show the property page in the IDE for a source file with a // full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a @@ -2156,7 +2138,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( clOptions.AddDefines( genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS")); } else { - clOptions.AddDefines(configDefines.c_str()); + clOptions.AddDefines(configDefines); } std::vector<std::string> includeList; if (configDependentIncludes) { @@ -2168,7 +2150,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( *source); } clOptions.AddIncludes(includeList); - clOptions.SetConfiguration(config.c_str()); + clOptions.SetConfiguration(config); clOptions.PrependInheritedString("AdditionalOptions"); clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream, " ", "\n", lang); @@ -3451,6 +3433,17 @@ void cmVisualStudio10TargetGenerator::AddLibraries( std::string currentBinDir = this->LocalGenerator->GetCurrentBinaryDirectory(); for (cmComputeLinkInformation::Item const& l : libs) { + // Do not allow C# targets to be added to the LIB listing. LIB files are + // used for linking C++ dependencies. C# libraries do not have lib files. + // Instead, they compile down to C# reference libraries (DLL files). The + // `<ProjectReference>` elements added to the vcxproj are enough for the + // IDE to deduce the DLL file required by other C# projects that need its + // reference library. + if (l.Target && + cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(l.Target)) { + continue; + } + if (l.IsPath) { std::string path = this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index adef127..124db4e 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -153,7 +153,7 @@ private: void WriteEvent(const char* name, std::vector<cmCustomCommand> const& commands, std::string const& configName); - void WriteGroupSources(const char* name, ToolSources const& sources, + void WriteGroupSources(std::string const& name, ToolSources const& sources, std::vector<cmSourceGroup>&); void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed, const std::vector<cmSourceGroup>& allGroups); diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index ccbff83..2095d23 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -152,9 +152,8 @@ bool cmVisualStudioGeneratorOptions::IsManaged() const bool cmVisualStudioGeneratorOptions::UsingUnicode() const { // Look for the a _UNICODE definition. - for (std::vector<std::string>::const_iterator di = this->Defines.begin(); - di != this->Defines.end(); ++di) { - if (*di == "_UNICODE") { + for (std::string const& di : this->Defines) { + if (di == "_UNICODE") { return true; } } @@ -163,9 +162,8 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() const bool cmVisualStudioGeneratorOptions::UsingSBCS() const { // Look for the a _SBCS definition. - for (std::vector<std::string>::const_iterator di = this->Defines.begin(); - di != this->Defines.end(); ++di) { - if (*di == "_SBCS") { + for (std::string const& di : this->Defines) { + if (di == "_SBCS") { return true; } } @@ -227,7 +225,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() // It translates to -arch=<virtual> -code=<real>. cmSystemTools::ReplaceString(arch_name, "sm_", "compute_"); } - for (auto const& c : codes) { + for (std::string const& c : codes) { std::string entry = arch_name + "," + c; result.push_back(entry); } @@ -237,7 +235,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() // -gencode=<arch>,<code> // -gencode=<arch>,[<code1>,<code2>] // -gencode=<arch>,"<code1>,<code2>" - for (auto const& e : gencode) { + for (std::string const& e : gencode) { std::string entry = e; cmSystemTools::ReplaceString(entry, "arch=", ""); cmSystemTools::ReplaceString(entry, "code=", ""); @@ -285,7 +283,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags() uacExecuteLevelMap["highestAvailable"] = "HighestAvailable"; uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator"; - for (auto const& subopt : subOptions) { + for (std::string const& subopt : subOptions) { std::vector<std::string> keyValue; cmsys::SystemTools::Split(subopt, keyValue, '='); if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) { @@ -332,9 +330,8 @@ void cmVisualStudioGeneratorOptions::Parse(const char* flags) // Process flags that need to be represented specially in the IDE // project file. - for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end(); - ++ai) { - this->HandleFlag(ai->c_str()); + for (std::string const& ai : args) { + this->HandleFlag(ai); } } @@ -396,23 +393,23 @@ void cmVisualStudioGeneratorOptions::Reparse(std::string const& key) this->Parse(original.c_str()); } -void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) +void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag) { // Look for Intel Fortran flags that do not map well in the flag table. if (this->CurrentTool == FortranCompiler) { - if (strcmp(flag, "/dbglibs") == 0) { + if (flag == "/dbglibs") { this->FortranRuntimeDebug = true; return; } - if (strcmp(flag, "/threads") == 0) { + if (flag == "/threads") { this->FortranRuntimeMT = true; return; } - if (strcmp(flag, "/libs:dll") == 0) { + if (flag == "/libs:dll") { this->FortranRuntimeDLL = true; return; } - if (strcmp(flag, "/libs:static") == 0) { + if (flag == "/libs:static") { this->FortranRuntimeDLL = false; return; } @@ -420,7 +417,7 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag) // This option is not known. Store it in the output flags. std::string const opts = cmOutputConverter::EscapeWindowsShellArgument( - flag, cmOutputConverter::Shell_Flag_AllowMakeVariables | + flag.c_str(), cmOutputConverter::Shell_Flag_AllowMakeVariables | cmOutputConverter::Shell_Flag_VSIDE); this->AppendFlagString(this->UnknownFlagField, opts); } @@ -437,7 +434,8 @@ cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag( return value; } -void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) +void cmVisualStudioGeneratorOptions::SetConfiguration( + const std::string& config) { this->Configuration = config; } @@ -566,31 +564,27 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, const char* indent) { if (this->Version >= cmGlobalVisualStudioGenerator::VS10) { - for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); - m != this->FlagMap.end(); ++m) { + for (auto const& m : this->FlagMap) { fout << indent; if (!this->Configuration.empty()) { this->TargetGenerator->WritePlatformConfigTag( - m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout); + m.first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout); } else { - fout << "<" << m->first << ">"; + fout << "<" << m.first << ">"; } const char* sep = ""; - for (std::vector<std::string>::iterator i = m->second.begin(); - i != m->second.end(); ++i) { - fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i); + for (std::string const& i : m.second) { + fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(i); sep = ";"; } - fout << "</" << m->first << ">\n"; + fout << "</" << m.first << ">\n"; } } else { - for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); - m != this->FlagMap.end(); ++m) { - fout << indent << m->first << "=\""; + for (auto const& m : this->FlagMap) { + fout << indent << m.first << "=\""; const char* sep = ""; - for (std::vector<std::string>::iterator i = m->second.begin(); - i != m->second.end(); ++i) { - fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i); + for (std::string const& i : m.second) { + fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(i); sep = ";"; } fout << "\"\n"; diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 2dffe9b..5c3e415 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -91,7 +91,7 @@ public: const char* suffix, const std::string& lang); void OutputFlagMap(std::ostream& fout, const char* indent); - void SetConfiguration(const char* config); + void SetConfiguration(const std::string& config); private: cmLocalVisualStudioGenerator* LocalGenerator; @@ -107,7 +107,7 @@ private: std::string UnknownFlagField; - virtual void StoreUnknownFlag(const char* flag); + void StoreUnknownFlag(std::string const& flag) override; FlagValue TakeFlag(std::string const& key); }; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 93837dd..0ce6d72 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -348,6 +348,7 @@ if(BUILD_TESTING) if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])") ADD_TEST_MACRO(CSharpOnly CSharpOnly) ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx) + ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx) endif() ADD_TEST_MACRO(COnly COnly) diff --git a/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake b/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake index a93e7f5..43c9384 100644 --- a/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake +++ b/Tests/CMakeTests/String-TIMESTAMP-UnixTime.cmake @@ -11,12 +11,12 @@ string(TIMESTAMP days "%j" UTC) # see if we are somewhere in the right region. math(EXPR years_since_epoch "${year} - 1970") -math(EXPR lower_bound "((${years_since_epoch} * 365) + ${days}) * 86400") +math(EXPR lower_bound "((${years_since_epoch} * 365) + ${days} - 1) * 86400") math(EXPR upper_bound "((${years_since_epoch} * 366) + ${days}) * 86400") -if(unix_time GREATER lower_bound AND unix_time LESS upper_bound) +if(unix_time GREATER_EQUAL lower_bound AND unix_time LESS upper_bound) message("~${unix_time}~") else() - message(FATAL_ERROR "${timestamp} unix time not in expected range [${lower_bound}, ${upper_bound}]") + message(FATAL_ERROR "${timestamp} unix time not in expected range [${lower_bound}, ${upper_bound})") endif() diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in index 83655da..566f4b1 100644 --- a/Tests/CMakeTests/StringTest.cmake.in +++ b/Tests/CMakeTests/StringTest.cmake.in @@ -47,7 +47,7 @@ set(TIMESTAMP-AllSpecifiers-STDERR "~[0-9]+(;[0-9]+)*~") set(TIMESTAMP-MonthWeekNames-RESULT 0) set(TIMESTAMP-MonthWeekNames-STDERR "~[^%]+;[^%]+~") set(TIMESTAMP-UnixTime-RESULT 0) -set(TIMESTAMP-UnixTime-STDERR "~[1-9][0-9]+~") +set(TIMESTAMP-UnixTime-STDERR "~[0-9]+~") include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake") check_cmake_test(String diff --git a/Tests/CSharpLinkFromCxx/.gitattributes b/Tests/CSharpLinkFromCxx/.gitattributes new file mode 100644 index 0000000..57a39049 --- /dev/null +++ b/Tests/CSharpLinkFromCxx/.gitattributes @@ -0,0 +1 @@ +UsefulManagedCppClass.* -format.clang-format diff --git a/Tests/CSharpLinkFromCxx/CMakeLists.txt b/Tests/CSharpLinkFromCxx/CMakeLists.txt new file mode 100644 index 0000000..9a1a993 --- /dev/null +++ b/Tests/CSharpLinkFromCxx/CMakeLists.txt @@ -0,0 +1,19 @@ +# Take a C# shared library and link it to a managed C++ shared library +cmake_minimum_required(VERSION 3.10) +project (CSharpLinkFromCxx CXX CSharp) + +add_library(CSharpLibrary SHARED UsefulCSharpClass.cs) + +# we have to change the default flags for the +# managed C++ project to build +string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) +string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) + +# The C# project is a dependency of the C++/CLI project +add_library(ManagedCppLibrary SHARED UsefulManagedCppClass.cpp UsefulManagedCppClass.hpp) +target_compile_options(ManagedCppLibrary PRIVATE "/clr") +target_link_libraries(ManagedCppLibrary PUBLIC CSharpLibrary) + +# Main executable for the test framework +add_executable(CSharpLinkFromCxx CSharpLinkFromCxx.cs) +target_link_libraries(CSharpLinkFromCxx PRIVATE ManagedCppLibrary) diff --git a/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs new file mode 100644 index 0000000..31a74eb --- /dev/null +++ b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs @@ -0,0 +1,16 @@ +using System; +using CSharpLibrary; + +namespace CSharpLinkFromCxx +{ + internal class CSharpLinkFromCxx + { + public static void Main(string[] args) + { + Console.WriteLine("Starting test for CSharpLinkFromCxx"); + + var useful = new UsefulManagedCppClass(); + useful.RunTest(); + } + } +} diff --git a/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs new file mode 100644 index 0000000..749e57d --- /dev/null +++ b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs @@ -0,0 +1,12 @@ +using System; + +namespace CSharpLibrary +{ + public class UsefulCSharpClass + { + public string GetSomethingUseful() + { + return "Something Useful"; + } + } +} diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp new file mode 100644 index 0000000..9468812 --- /dev/null +++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp @@ -0,0 +1,15 @@ +#include "UsefulManagedCppClass.hpp" + +namespace CSharpLibrary +{ + UsefulManagedCppClass::UsefulManagedCppClass() + { + auto useful = gcnew UsefulCSharpClass(); + m_usefulString = useful->GetSomethingUseful(); + } + + void UsefulManagedCppClass::RunTest() + { + Console::WriteLine("Printing from Managed CPP Class: " + m_usefulString); + } +} diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp new file mode 100644 index 0000000..def7cea --- /dev/null +++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp @@ -0,0 +1,16 @@ +using namespace System; + +namespace CSharpLibrary +{ + public ref class UsefulManagedCppClass + { + public: + + UsefulManagedCppClass(); + void RunTest(); + + private: + + String^ m_usefulString; + }; +} diff --git a/Tests/Contracts/PLplot/CMakeLists.txt b/Tests/Contracts/PLplot/CMakeLists.txt index b87b4c3..7051d62 100644 --- a/Tests/Contracts/PLplot/CMakeLists.txt +++ b/Tests/Contracts/PLplot/CMakeLists.txt @@ -9,7 +9,7 @@ if(NOT PLplot_GIT_TAG) set(PLplot_GIT_TAG "plplot-5.13.0") endif() ExternalProject_Add(PLplot - GIT_REPOSITORY "https://git.code.sf.net/p/plplot/plplot.git" + GIT_REPOSITORY "git://git.code.sf.net/p/plplot/plplot" GIT_TAG "${PLplot_GIT_TAG}" PREFIX "${PLplot_PREFIX}" CMAKE_ARGS diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 64a07f0..5eff6b9 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -236,3 +236,17 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 8) deploymeny_target_test(${SDK}) endforeach() endif() + +function(XcodeDependOnZeroCheck) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeDependOnZeroCheck-build) + set(RunCMake_TEST_NO_CLEAN 1) + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(XcodeDependOnZeroCheck) + run_cmake_command(XcodeDependOnZeroCheck-build ${CMAKE_COMMAND} --build . --target parentdirlib) + run_cmake_command(XcodeDependOnZeroCheck-build ${CMAKE_COMMAND} --build . --target subdirlib) +endfunction() + +XcodeDependOnZeroCheck() diff --git a/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt new file mode 100644 index 0000000..92c9a29 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck-build-stdout.txt @@ -0,0 +1 @@ +BUILD AGGREGATE TARGET ZERO_CHECK diff --git a/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake new file mode 100644 index 0000000..d759a65 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeDependOnZeroCheck.cmake @@ -0,0 +1,4 @@ +set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY TRUE) +project(XcodeDependOnZeroCheck CXX) +add_subdirectory(zerocheck) +add_library(parentdirlib foo.cpp) diff --git a/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt b/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt new file mode 100644 index 0000000..4adde99 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/zerocheck/CMakeLists.txt @@ -0,0 +1,2 @@ +project(subproject) +add_library(subdirlib ../foo.cpp) |