diff options
45 files changed, 676 insertions, 260 deletions
diff --git a/.clang-tidy b/.clang-tidy index cfca64e..a6378e0 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -7,15 +7,11 @@ bugprone-*,\ -bugprone-too-small-loop-variable,\ google-readability-casting,\ misc-*,\ --misc-incorrect-roundings,\ --misc-macro-parentheses,\ --misc-misplaced-widening-cast,\ -misc-non-private-member-variables-in-classes,\ -misc-static-assert,\ modernize-*,\ -modernize-avoid-c-arrays,\ -modernize-deprecated-headers,\ --modernize-return-braced-init-list,\ -modernize-use-auto,\ -modernize-use-nodiscard,\ -modernize-use-noexcept,\ @@ -24,7 +20,6 @@ performance-*,\ readability-*,\ -readability-function-size,\ -readability-identifier-naming,\ --readability-implicit-bool-cast,\ -readability-implicit-bool-conversion,\ -readability-inconsistent-declaration-parameter-name,\ -readability-magic-numbers,\ diff --git a/Help/release/dev/windows-auto-export-incremental-build.rst b/Help/release/dev/windows-auto-export-incremental-build.rst new file mode 100644 index 0000000..3126329 --- /dev/null +++ b/Help/release/dev/windows-auto-export-incremental-build.rst @@ -0,0 +1,6 @@ +windows-auto-export-incremental-build +------------------------------------- + +* On Windows, existing auto generated exports are now only updated if the + modified time stamp of the exports is not newer than any modified time stamp + of the input files. diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 857e5f1..0d48a72 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 20190909) +set(CMake_VERSION_PATCH 20190911) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index cf28cdb..4c8c224 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -498,7 +498,7 @@ cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry( cmCacheManager::CacheIterator cmCacheManager::GetCacheIterator(const char* key) { - return CacheIterator(*this, key); + return { *this, key }; } const std::string* cmCacheManager::GetInitializedCacheValue( diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index a988bd8..faa60c5 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -94,7 +94,7 @@ public: }; //! return an iterator to iterate through the cache map - cmCacheManager::CacheIterator NewIterator() { return CacheIterator(*this); } + cmCacheManager::CacheIterator NewIterator() { return { *this }; } //! Load a cache for given makefile. Loads from path/CMakeCache.txt. bool LoadCache(const std::string& path, bool internal, diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 9f0396b..e9d2412 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -311,7 +311,7 @@ cmExportBuildFileGenerator::FindBuildExportInfo(cmGlobalGenerator* gg, } } - return std::make_pair(exportFiles, ns); + return { exportFiles, ns }; } void cmExportBuildFileGenerator::ComplainAboutMissingTarget( diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index e7f301e..4e3db09 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -496,7 +496,7 @@ cmExportInstallFileGenerator::FindNamespaces(cmGlobalGenerator* gg, } } - return std::make_pair(exportFiles, ns); + return { exportFiles, ns }; } void cmExportInstallFileGenerator::ComplainAboutMissingTarget( diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 3ac769c..805da81 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -802,9 +802,13 @@ void Target::ProcessLanguage(std::string const& lang) { // FIXME: Add flags from end section of ExpandRuleVariable, // which may need to be factored out. - std::string flags; - lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags); - cd.Flags.emplace_back(std::move(flags), JBTIndex()); + std::vector<BT<std::string>> flags = + lg->GetTargetCompileFlags(this->GT, this->Config, lang); + + cd.Flags.reserve(flags.size()); + for (const BT<std::string>& f : flags) { + cd.Flags.emplace_back(this->ToJBT(f)); + } } std::set<BT<std::string>> defines = lg->GetTargetDefines(this->GT, this->Config, lang); @@ -1264,7 +1268,7 @@ Json::Value Target::DumpLinkCommandFragments() Json::Value linkFragments = Json::arrayValue; std::string linkLanguageFlags; - std::string linkFlags; + std::vector<BT<std::string>> linkFlags; std::string frameworkPath; std::string linkPath; std::string linkLibs; @@ -1275,7 +1279,6 @@ Json::Value Target::DumpLinkCommandFragments() linkLanguageFlags, linkFlags, frameworkPath, linkPath, this->GT); linkLanguageFlags = cmTrimWhitespace(linkLanguageFlags); - linkFlags = cmTrimWhitespace(linkFlags); frameworkPath = cmTrimWhitespace(frameworkPath); linkPath = cmTrimWhitespace(linkPath); linkLibs = cmTrimWhitespace(linkLibs); @@ -1286,8 +1289,11 @@ Json::Value Target::DumpLinkCommandFragments() } if (!linkFlags.empty()) { - linkFragments.append( - this->DumpCommandFragment(std::move(linkFlags), "flags")); + for (BT<std::string> frag : linkFlags) { + frag.Value = cmTrimWhitespace(frag.Value); + linkFragments.append( + this->DumpCommandFragment(this->ToJBT(frag), "flags")); + } } if (!frameworkPath.empty()) { diff --git a/Source/cmFileLockResult.cxx b/Source/cmFileLockResult.cxx index 9ca5d8a..c4779f0 100644 --- a/Source/cmFileLockResult.cxx +++ b/Source/cmFileLockResult.cxx @@ -8,7 +8,7 @@ #define WINMSG_BUF_LEN (1024) cmFileLockResult cmFileLockResult::MakeOk() { - return cmFileLockResult(OK, 0); + return { OK, 0 }; } cmFileLockResult cmFileLockResult::MakeSystem() @@ -18,27 +18,27 @@ cmFileLockResult cmFileLockResult::MakeSystem() #else const Error lastError = errno; #endif - return cmFileLockResult(SYSTEM, lastError); + return { SYSTEM, lastError }; } cmFileLockResult cmFileLockResult::MakeTimeout() { - return cmFileLockResult(TIMEOUT, 0); + return { TIMEOUT, 0 }; } cmFileLockResult cmFileLockResult::MakeAlreadyLocked() { - return cmFileLockResult(ALREADY_LOCKED, 0); + return { ALREADY_LOCKED, 0 }; } cmFileLockResult cmFileLockResult::MakeInternal() { - return cmFileLockResult(INTERNAL, 0); + return { INTERNAL, 0 }; } cmFileLockResult cmFileLockResult::MakeNoFunction() { - return cmFileLockResult(NO_FUNCTION, 0); + return { NO_FUNCTION, 0 }; } bool cmFileLockResult::IsOk() const diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index 7475e9f..491d96f 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -4,6 +4,7 @@ #include <stdio.h> +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #if !defined(CMAKE_BOOTSTRAP) @@ -149,7 +150,7 @@ bool cmGeneratedFileStreamBase::Close() // The destination is to be replaced. Rename the temporary to the // destination atomically. if (this->Compress) { - std::string gzname = this->TempName + ".temp.gz"; + std::string gzname = cmStrCat(this->TempName, ".temp.gz"); if (this->CompressFile(this->TempName, gzname)) { this->RenameFile(gzname, resname); } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index b4706a3..e4659b7 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3417,8 +3417,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, file << pchEpilogue << "\n"; } } - cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); - cmSystemTools::RemoveFile(filename_tmp); + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); } return inserted.first->second; } @@ -3451,8 +3450,7 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, cmGeneratedFileStream file(filename_tmp); file << "/* generated by CMake */\n"; } - cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); - cmSystemTools::RemoveFile(filename_tmp); + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); } return inserted.first->second; } @@ -4778,21 +4776,21 @@ template <> std::pair<bool, bool> consistentProperty(bool lhs, bool rhs, CompatibleType /*unused*/) { - return std::make_pair(lhs == rhs, lhs); + return { lhs == rhs, lhs }; } std::pair<bool, const char*> consistentStringProperty(const char* lhs, const char* rhs) { const bool b = strcmp(lhs, rhs) == 0; - return std::make_pair(b, b ? lhs : nullptr); + return { b, b ? lhs : nullptr }; } std::pair<bool, std::string> consistentStringProperty(const std::string& lhs, const std::string& rhs) { const bool b = lhs == rhs; - return std::make_pair(b, b ? lhs : valueAsString(nullptr)); + return { b, b ? lhs : valueAsString(nullptr) }; } std::pair<bool, const char*> consistentNumberProperty(const char* lhs, @@ -4801,22 +4799,21 @@ std::pair<bool, const char*> consistentNumberProperty(const char* lhs, { char* pEnd; - const char* const null_ptr = nullptr; - long lnum = strtol(lhs, &pEnd, 0); if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) { - return std::pair<bool, const char*>(false, null_ptr); + return { false, nullptr }; } long rnum = strtol(rhs, &pEnd, 0); if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) { - return std::pair<bool, const char*>(false, null_ptr); + return { false, nullptr }; } if (t == NumberMaxType) { - return std::make_pair(true, std::max(lnum, rnum) == lnum ? lhs : rhs); + return { true, std::max(lnum, rnum) == lnum ? lhs : rhs }; } - return std::make_pair(true, std::min(lnum, rnum) == lnum ? lhs : rhs); + + return { true, std::min(lnum, rnum) == lnum ? lhs : rhs }; } template <> @@ -4825,21 +4822,19 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, CompatibleType t) { if (!lhs && !rhs) { - return std::make_pair(true, lhs); + return { true, lhs }; } if (!lhs) { - return std::make_pair(true, rhs); + return { true, rhs }; } if (!rhs) { - return std::make_pair(true, lhs); + return { true, lhs }; } - const char* const null_ptr = nullptr; - switch (t) { case BoolType: { bool same = cmIsOn(lhs) == cmIsOn(rhs); - return std::make_pair(same, same ? lhs : nullptr); + return { same, same ? lhs : nullptr }; } case StringType: return consistentStringProperty(lhs, rhs); @@ -4848,7 +4843,7 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, return consistentNumberProperty(lhs, rhs, t); } assert(false && "Unreachable!"); - return std::pair<bool, const char*>(false, null_ptr); + return { false, nullptr }; } std::pair<bool, std::string> consistentProperty(const std::string& lhs, @@ -4858,31 +4853,31 @@ std::pair<bool, std::string> consistentProperty(const std::string& lhs, const std::string null_ptr = valueAsString(nullptr); if (lhs == null_ptr && rhs == null_ptr) { - return std::make_pair(true, lhs); + return { true, lhs }; } if (lhs == null_ptr) { - return std::make_pair(true, rhs); + return { true, rhs }; } if (rhs == null_ptr) { - return std::make_pair(true, lhs); + return { true, lhs }; } switch (t) { case BoolType: { bool same = cmIsOn(lhs) == cmIsOn(rhs); - return std::make_pair(same, same ? lhs : null_ptr); + return { same, same ? lhs : null_ptr }; } case StringType: return consistentStringProperty(lhs, rhs); case NumberMinType: case NumberMaxType: { auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t); - return std::make_pair( - value.first, value.first ? std::string(value.second) : null_ptr); + return { value.first, + value.first ? std::string(value.second) : null_ptr }; } } assert(false && "Unreachable!"); - return std::pair<bool, std::string>(false, null_ptr); + return { false, null_ptr }; } template <typename PropertyType> diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index f6d5998..7aa231e 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -228,7 +228,7 @@ public: return this->GG->ConvertToNinjaPath(path); } }; - MapToNinjaPathImpl MapToNinjaPath() { return MapToNinjaPathImpl(this); } + MapToNinjaPathImpl MapToNinjaPath() { return { this }; } // -- Additional clean files void AddAdditionalCleanFile(std::string fileName); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 10f822f..3dae824 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1254,7 +1254,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - for (auto keySources : bundleFiles) { + for (auto const& keySources : bundleFiles) { cmXCodeObject* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); copyFilesBuildPhase->SetComment("Copy files"); @@ -1302,7 +1302,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - for (auto keySources : bundleFiles) { + for (auto const& keySources : bundleFiles) { cmXCodeObject* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); copyFilesBuildPhase->SetComment("Copy files"); @@ -1433,7 +1433,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase( void cmGlobalXCodeGenerator::CreateCustomCommands( cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase, - std::vector<cmXCodeObject*> contentBuildPhases, + std::vector<cmXCodeObject*> const& contentBuildPhases, cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt) { std::vector<cmCustomCommand> const& prebuild = gtgt->GetPreBuildCommands(); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 71446f9..af905d0 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -122,13 +122,11 @@ private: std::string RelativeToSource(const std::string& p); std::string RelativeToBinary(const std::string& p); std::string ConvertToRelativeForMake(std::string const& p); - void CreateCustomCommands(cmXCodeObject* buildPhases, - cmXCodeObject* sourceBuildPhase, - cmXCodeObject* headerBuildPhase, - cmXCodeObject* resourceBuildPhase, - std::vector<cmXCodeObject*> contentBuildPhases, - cmXCodeObject* frameworkBuildPhase, - cmGeneratorTarget* gtgt); + void CreateCustomCommands( + cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, + cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase, + std::vector<cmXCodeObject*> const& contentBuildPhases, + cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt); std::string ComputeInfoPListLocation(cmGeneratorTarget* target); diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 9c0e20f..1a602ca 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -82,6 +82,9 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( ItemVector const& items = cli.GetItems(); std::string config = cli.GetConfig(); bool skipItemAfterFramework = false; + // Note: + // Any modification of this algorithm should be reflected also in + // cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions for (auto const& item : items) { if (skipItemAfterFramework) { skipItemAfterFramework = false; @@ -91,6 +94,7 @@ std::string cmLinkLineDeviceComputer::ComputeLinkLibraries( if (item.Target) { bool skip = false; switch (item.Target->GetType()) { + case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: case cmStateEnums::INTERFACE_LIBRARY: skip = true; diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index ff3ecd9..349d5e9 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -326,6 +326,7 @@ cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot) { } +/* NOLINTNEXTLINE(performance-unnecessary-value-param) */ cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent, cmListFileContext const& lfc) : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc)) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9152e94..9f22277 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -14,6 +14,7 @@ #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" +#include "cmLinkLineDeviceComputer.h" #include "cmMakefile.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -832,29 +833,50 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, const std::string& lang, const std::string& config) { + std::vector<BT<std::string>> tmpFlags; + this->AddCompileOptions(tmpFlags, target, lang, config); + this->AppendFlags(flags, tmpFlags); +} + +void cmLocalGenerator::AddCompileOptions(std::vector<BT<std::string>>& flags, + cmGeneratorTarget* target, + const std::string& lang, + const std::string& config) +{ std::string langFlagRegexVar = std::string("CMAKE_") + lang + "_FLAG_REGEX"; if (const char* langFlagRegexStr = this->Makefile->GetDefinition(langFlagRegexVar)) { // Filter flags acceptable to this language. - std::vector<std::string> opts; if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) { + std::vector<std::string> opts; cmSystemTools::ParseWindowsCommandLine(targetFlags, opts); + // Re-escape these flags since COMPILE_FLAGS were already parsed + // as a command line above. + std::string compileOpts; + this->AppendCompileOptions(compileOpts, opts, langFlagRegexStr); + if (!compileOpts.empty()) { + flags.emplace_back(std::move(compileOpts)); + } } - target->GetCompileOptions(opts, config, lang); - // (Re-)Escape these flags. COMPILE_FLAGS were already parsed - // as a command line above, and COMPILE_OPTIONS are escaped. - this->AppendCompileOptions(flags, opts, langFlagRegexStr); + std::vector<BT<std::string>> targetCompileOpts = + target->GetCompileOptions(config, lang); + // COMPILE_OPTIONS are escaped. + this->AppendCompileOptions(flags, targetCompileOpts, langFlagRegexStr); } else { // Use all flags. if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) { // COMPILE_FLAGS are not escaped for historical reasons. - this->AppendFlags(flags, targetFlags); + std::string compileFlags; + this->AppendFlags(compileFlags, targetFlags); + if (!compileFlags.empty()) { + flags.emplace_back(std::move(compileFlags)); + } } - std::vector<std::string> opts; - target->GetCompileOptions(opts, config, lang); + std::vector<BT<std::string>> targetCompileOpts = + target->GetCompileOptions(config, lang); // COMPILE_OPTIONS are escaped. - this->AppendCompileOptions(flags, opts); + this->AppendCompileOptions(flags, targetCompileOpts); } for (auto const& it : target->GetMaxLanguageStandards()) { @@ -881,7 +903,12 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, return; } } - this->AddCompilerRequirementFlag(flags, target, lang); + + std::string compReqFlag; + this->AddCompilerRequirementFlag(compReqFlag, target, lang); + if (!compReqFlag.empty()) { + flags.emplace_back(std::move(compReqFlag)); + } // Add compile flag for the MSVC compiler only. cmMakefile* mf = this->GetMakefile(); @@ -902,7 +929,11 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags, std::string isJMCEnabled = cge->Evaluate(this, config); if (cmIsOn(isJMCEnabled)) { std::vector<std::string> optVec = cmExpandedList(jmc); - this->AppendCompileOptions(flags, optVec); + std::string jmcFlags; + this->AppendCompileOptions(jmcFlags, optVec); + if (!jmcFlags.empty()) { + flags.emplace_back(std::move(jmcFlags)); + } } } } @@ -1117,24 +1148,49 @@ void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags, std::string const& linkLanguage, cmGeneratorTarget* target) { + std::vector<BT<std::string>> tmpFlags = + this->GetStaticLibraryFlags(config, linkLanguage, target); + this->AppendFlags(flags, tmpFlags); +} + +std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags( + std::string const& config, std::string const& linkLanguage, + cmGeneratorTarget* target) +{ + std::vector<BT<std::string>> flags; if (linkLanguage != "Swift") { + std::string staticLibFlags; this->AppendFlags( - flags, this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); + staticLibFlags, + this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS")); if (!config.empty()) { std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config; - this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name)); + this->AppendFlags(staticLibFlags, + this->Makefile->GetSafeDefinition(name)); + } + if (!staticLibFlags.empty()) { + flags.emplace_back(std::move(staticLibFlags)); } } - this->AppendFlags(flags, target->GetSafeProperty("STATIC_LIBRARY_FLAGS")); + + std::string staticLibFlags; + this->AppendFlags(staticLibFlags, + target->GetSafeProperty("STATIC_LIBRARY_FLAGS")); if (!config.empty()) { std::string name = "STATIC_LIBRARY_FLAGS_" + config; - this->AppendFlags(flags, target->GetSafeProperty(name)); + this->AppendFlags(staticLibFlags, target->GetSafeProperty(name)); + } + + if (!staticLibFlags.empty()) { + flags.emplace_back(std::move(staticLibFlags)); } - std::vector<std::string> options; - target->GetStaticLibraryLinkOptions(options, config, linkLanguage); + std::vector<BT<std::string>> staticLibOpts = + target->GetStaticLibraryLinkOptions(config, linkLanguage); // STATIC_LIBRARY_OPTIONS are escaped. - this->AppendCompileOptions(flags, options); + this->AppendCompileOptions(flags, staticLibOpts); + + return flags; } void cmLocalGenerator::GetTargetFlags( @@ -1142,6 +1198,18 @@ void cmLocalGenerator::GetTargetFlags( std::string& linkLibs, std::string& flags, std::string& linkFlags, std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target) { + std::vector<BT<std::string>> tmpLinkFlags; + this->GetTargetFlags(linkLineComputer, config, linkLibs, flags, tmpLinkFlags, + frameworkPath, linkPath, target); + this->AppendFlags(linkFlags, tmpLinkFlags); +} + +void cmLocalGenerator::GetTargetFlags( + cmLinkLineComputer* linkLineComputer, const std::string& config, + std::string& linkLibs, std::string& flags, + std::vector<BT<std::string>>& linkFlags, std::string& frameworkPath, + std::string& linkPath, cmGeneratorTarget* target) +{ const std::string buildType = cmSystemTools::UpperCase(config); cmComputeLinkInformation* pcli = target->GetLinkInformation(config); const char* libraryLinkVariable = @@ -1152,19 +1220,26 @@ void cmLocalGenerator::GetTargetFlags( switch (target->GetType()) { case cmStateEnums::STATIC_LIBRARY: - this->GetStaticLibraryFlags(linkFlags, buildType, linkLanguage, target); + linkFlags = this->GetStaticLibraryFlags(buildType, linkLanguage, target); + if (pcli && dynamic_cast<cmLinkLineDeviceComputer*>(linkLineComputer)) { + // Compute the required cuda device link libraries when + // resolving cuda device symbols + this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, + frameworkPath, linkPath); + } break; case cmStateEnums::MODULE_LIBRARY: libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; CM_FALLTHROUGH; case cmStateEnums::SHARED_LIBRARY: { + std::string sharedLibFlags; if (linkLanguage != "Swift") { - linkFlags = cmStrCat( + sharedLibFlags = cmStrCat( this->Makefile->GetSafeDefinition(libraryLinkVariable), ' '); if (!buildType.empty()) { std::string build = cmStrCat(libraryLinkVariable, '_', buildType); - linkFlags += this->Makefile->GetSafeDefinition(build); - linkFlags += " "; + sharedLibFlags += this->Makefile->GetSafeDefinition(build); + sharedLibFlags += " "; } if (this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN") || @@ -1175,10 +1250,10 @@ void cmLocalGenerator::GetTargetFlags( this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); for (cmSourceFile* sf : sources) { if (sf->GetExtension() == "def") { - linkFlags += defFlag; - linkFlags += this->ConvertToOutputFormat( + sharedLibFlags += defFlag; + sharedLibFlags += this->ConvertToOutputFormat( cmSystemTools::CollapseFullPath(sf->ResolveFullPath()), SHELL); - linkFlags += " "; + sharedLibFlags += " "; } } } @@ -1186,36 +1261,40 @@ void cmLocalGenerator::GetTargetFlags( const char* targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { - linkFlags += targetLinkFlags; - linkFlags += " "; + sharedLibFlags += targetLinkFlags; + sharedLibFlags += " "; } if (!buildType.empty()) { targetLinkFlags = target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); if (targetLinkFlags) { - linkFlags += targetLinkFlags; - linkFlags += " "; + sharedLibFlags += targetLinkFlags; + sharedLibFlags += " "; } } - std::vector<std::string> opts; - target->GetLinkOptions(opts, config, linkLanguage); + if (!sharedLibFlags.empty()) { + linkFlags.emplace_back(std::move(sharedLibFlags)); + } + + std::vector<BT<std::string>> linkOpts = + target->GetLinkOptions(config, linkLanguage); // LINK_OPTIONS are escaped. - this->AppendCompileOptions(linkFlags, opts); + this->AppendCompileOptions(linkFlags, linkOpts); if (pcli) { this->OutputLinkLibraries(pcli, linkLineComputer, linkLibs, frameworkPath, linkPath); } } break; case cmStateEnums::EXECUTABLE: { + std::string exeFlags; if (linkLanguage != "Swift") { - linkFlags += - this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS"); - linkFlags += " "; + exeFlags = this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS"); + exeFlags += " "; if (!buildType.empty()) { - linkFlags += this->Makefile->GetSafeDefinition( + exeFlags += this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_EXE_LINKER_FLAGS_", buildType)); - linkFlags += " "; + exeFlags += " "; } if (linkLanguage.empty()) { cmSystemTools::Error( @@ -1225,19 +1304,19 @@ void cmLocalGenerator::GetTargetFlags( } if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) { - linkFlags += + exeFlags += this->Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); - linkFlags += " "; + exeFlags += " "; } else { - linkFlags += + exeFlags += this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"); - linkFlags += " "; + exeFlags += " "; } if (target->IsExecutableWithExports()) { - linkFlags += this->Makefile->GetSafeDefinition( + exeFlags += this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG")); - linkFlags += " "; + exeFlags += " "; } } @@ -1250,43 +1329,52 @@ void cmLocalGenerator::GetTargetFlags( if (cmIsOn(this->Makefile->GetDefinition("BUILD_SHARED_LIBS"))) { std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") + linkLanguage + std::string("_FLAGS"); - linkFlags += this->Makefile->GetSafeDefinition(sFlagVar); - linkFlags += " "; + exeFlags += this->Makefile->GetSafeDefinition(sFlagVar); + exeFlags += " "; } std::string cmp0065Flags = this->GetLinkLibsCMP0065(linkLanguage, *target); if (!cmp0065Flags.empty()) { - linkFlags += cmp0065Flags; - linkFlags += " "; + exeFlags += cmp0065Flags; + exeFlags += " "; } const char* targetLinkFlags = target->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { - linkFlags += targetLinkFlags; - linkFlags += " "; + exeFlags += targetLinkFlags; + exeFlags += " "; } if (!buildType.empty()) { targetLinkFlags = target->GetProperty(cmStrCat("LINK_FLAGS_", buildType)); if (targetLinkFlags) { - linkFlags += targetLinkFlags; - linkFlags += " "; + exeFlags += targetLinkFlags; + exeFlags += " "; } } - std::vector<std::string> opts; - target->GetLinkOptions(opts, config, linkLanguage); + if (!exeFlags.empty()) { + linkFlags.emplace_back(std::move(exeFlags)); + } + + std::vector<BT<std::string>> linkOpts = + target->GetLinkOptions(config, linkLanguage); // LINK_OPTIONS are escaped. - this->AppendCompileOptions(linkFlags, opts); + this->AppendCompileOptions(linkFlags, linkOpts); } break; default: break; } - this->AppendPositionIndependentLinkerFlags(linkFlags, target, config, + std::string extraLinkFlags; + this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config, linkLanguage); - this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage); + this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage); + + if (!extraLinkFlags.empty()) { + linkFlags.emplace_back(std::move(extraLinkFlags)); + } } void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, @@ -1294,26 +1382,45 @@ void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, std::string const& lang, std::string& flags) { + std::vector<BT<std::string>> tmpFlags = + this->GetTargetCompileFlags(target, config, lang); + this->AppendFlags(flags, tmpFlags); +} + +std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags( + cmGeneratorTarget* target, std::string const& config, + std::string const& lang) +{ + std::vector<BT<std::string>> flags; + std::string compileFlags; + cmMakefile* mf = this->GetMakefile(); // Add language-specific flags. - this->AddLanguageFlags(flags, target, lang, config); + this->AddLanguageFlags(compileFlags, target, lang, config); if (target->IsIPOEnabled(lang, config)) { - this->AppendFeatureOptions(flags, lang, "IPO"); + this->AppendFeatureOptions(compileFlags, lang, "IPO"); } - this->AddArchitectureFlags(flags, target, lang, config); + this->AddArchitectureFlags(compileFlags, target, lang, config); if (lang == "Fortran") { - this->AppendFlags(flags, this->GetTargetFortranFlags(target, config)); + this->AppendFlags(compileFlags, + this->GetTargetFortranFlags(target, config)); } - this->AddCMP0018Flags(flags, target, lang, config); - this->AddVisibilityPresetFlags(flags, target, lang); - this->AppendFlags(flags, mf->GetDefineFlags()); - this->AppendFlags(flags, this->GetFrameworkFlags(lang, config, target)); + this->AddCMP0018Flags(compileFlags, target, lang, config); + this->AddVisibilityPresetFlags(compileFlags, target, lang); + this->AppendFlags(compileFlags, mf->GetDefineFlags()); + this->AppendFlags(compileFlags, + this->GetFrameworkFlags(lang, config, target)); + + if (!compileFlags.empty()) { + flags.emplace_back(std::move(compileFlags)); + } this->AddCompileOptions(flags, target, lang, config); + return flags; } static std::string GetFrameworkFlags(const std::string& lang, @@ -2089,12 +2196,11 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags, const std::string& config) { // Add the flags from the variable itself. - std::string flagsVar = var; - this->AppendFlags(flags, this->Makefile->GetSafeDefinition(flagsVar)); + this->AppendFlags(flags, this->Makefile->GetSafeDefinition(var)); // Add the flags from the build-type specific variable. if (!config.empty()) { - flagsVar += "_"; - flagsVar += cmSystemTools::UpperCase(config); + const std::string flagsVar = + cmStrCat(var, '_', cmSystemTools::UpperCase(config)); this->AppendFlags(flags, this->Makefile->GetSafeDefinition(flagsVar)); } } @@ -2110,6 +2216,14 @@ void cmLocalGenerator::AppendFlags(std::string& flags, } } +void cmLocalGenerator::AppendFlags( + std::string& flags, const std::vector<BT<std::string>>& newFlags) const +{ + for (BT<std::string> const& flag : newFlags) { + this->AppendFlags(flags, flag.Value); + } +} + void cmLocalGenerator::AppendFlagEscape(std::string& flags, const std::string& rawFlag) const { @@ -2275,8 +2389,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target, } } } - cmSystemTools::CopyFileIfDifferent(filename_tmp, filename); - cmSystemTools::RemoveFile(filename_tmp); + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); target->AddSource(filename, true); @@ -2386,6 +2499,30 @@ void cmLocalGenerator::AppendCompileOptions( } } +void cmLocalGenerator::AppendCompileOptions( + std::vector<BT<std::string>>& options, + const std::vector<BT<std::string>>& options_vec, const char* regex) const +{ + if (regex != nullptr) { + // Filter flags upon specified regular expressions. + cmsys::RegularExpression r(regex); + + for (BT<std::string> const& opt : options_vec) { + if (r.find(opt.Value)) { + std::string flag; + this->AppendFlagEscape(flag, opt.Value); + options.emplace_back(std::move(flag), opt.Backtrace); + } + } + } else { + for (BT<std::string> const& opt : options_vec) { + std::string flag; + this->AppendFlagEscape(flag, opt.Value); + options.emplace_back(std::move(flag), opt.Backtrace); + } + } +} + void cmLocalGenerator::AppendIncludeDirectories( std::vector<std::string>& includes, const char* includes_list, const cmSourceFile& sourceFile) const diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index e6ba333..34f58bd 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -121,6 +121,8 @@ public: //! Append flags to a string. virtual void AppendFlags(std::string& flags, const std::string& newFlags) const; + virtual void AppendFlags(std::string& flags, + const std::vector<BT<std::string>>& newFlags) const; virtual void AppendFlagEscape(std::string& flags, const std::string& rawFlag) const; void AddPchDependencies(cmGeneratorTarget* target, @@ -197,6 +199,9 @@ public: void AppendCompileOptions(std::string& options, const std::vector<std::string>& options_vec, const char* regex = nullptr) const; + void AppendCompileOptions(std::vector<BT<std::string>>& options, + const std::vector<BT<std::string>>& options_vec, + const char* regex = nullptr) const; /** * Join a set of defines into a definesString with a space separator. @@ -283,6 +288,9 @@ public: void AddCompileOptions(std::string& flags, cmGeneratorTarget* target, const std::string& lang, const std::string& config); + void AddCompileOptions(std::vector<BT<std::string>>& flags, + cmGeneratorTarget* target, const std::string& lang, + const std::string& config); std::string GetProjectName() const; @@ -363,6 +371,9 @@ public: void GetStaticLibraryFlags(std::string& flags, std::string const& config, std::string const& linkLanguage, cmGeneratorTarget* target); + std::vector<BT<std::string>> GetStaticLibraryFlags( + std::string const& config, std::string const& linkLanguage, + cmGeneratorTarget* target); /** Fill out these strings for the given target. Libraries to link, * flags, and linkflags. */ @@ -371,6 +382,12 @@ public: std::string& flags, std::string& linkFlags, std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target); + void GetTargetFlags(cmLinkLineComputer* linkLineComputer, + const std::string& config, std::string& linkLibs, + std::string& flags, + std::vector<BT<std::string>>& linkFlags, + std::string& frameworkPath, std::string& linkPath, + cmGeneratorTarget* target); void GetTargetDefines(cmGeneratorTarget const* target, std::string const& config, std::string const& lang, std::set<std::string>& defines) const; @@ -380,6 +397,9 @@ public: void GetTargetCompileFlags(cmGeneratorTarget* target, std::string const& config, std::string const& lang, std::string& flags); + std::vector<BT<std::string>> GetTargetCompileFlags(cmGeneratorTarget* target, + std::string const& config, + std::string const& lang); std::string GetFrameworkFlags(std::string const& l, std::string const& config, diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 745e251..c02c0dc 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -90,6 +90,7 @@ public: // append flags to a string void AppendFlags(std::string& flags, const std::string& newFlags) const override; + using cmLocalCommonGenerator::AppendFlags; // append an echo command enum EchoColor diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 411add3..d729451 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -860,7 +860,7 @@ void cmMakefile::AddCustomCommandToTarget( e << "No TARGET '" << target << "' has been created in this directory."; } - IssueMessage(messageType, e.str()); + this->IssueMessage(messageType, e.str()); } return; @@ -886,11 +886,7 @@ void cmMakefile::AddCustomCommandToTarget( } // Always create the byproduct sources and mark them generated. - for (std::string const& o : byproducts) { - if (cmSourceFile* out = this->GetOrCreateSource(o, true)) { - out->SetProperty("GENERATED", "1"); - } - } + this->CreateGeneratedSources(byproducts); // Add the command to the appropriate build step for the target. std::vector<std::string> no_output; @@ -940,6 +936,10 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( } } + // Always create the output sources and mark them generated. + this->CreateGeneratedSources(outputs, cmSourceFileLocationKind::Known); + this->CreateGeneratedSources(byproducts, cmSourceFileLocationKind::Known); + // Choose a source file on which to store the custom command. cmSourceFile* file = nullptr; if (!commandLines.empty() && !main_dependency.empty()) { @@ -987,20 +987,6 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput( file->SetProperty("__CMAKE_RULE", "1"); } - // Always create the output sources and mark them generated. - for (std::string const& o : outputs) { - if (cmSourceFile* out = - this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) { - out->SetProperty("GENERATED", "1"); - } - } - for (std::string const& o : byproducts) { - if (cmSourceFile* out = - this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) { - out->SetProperty("GENERATED", "1"); - } - } - // Attach the custom command to the file. if (file) { // Construct a complete list of dependencies. @@ -1180,6 +1166,7 @@ cmTarget* cmMakefile::AddUtilityCommand( if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } + if (!comment) { // Use an empty comment to avoid generation of default comment. comment = ""; @@ -1187,6 +1174,9 @@ cmTarget* cmMakefile::AddUtilityCommand( // Store the custom command in the target. if (!commandLines.empty() || !depends.empty()) { + // Always create the byproduct sources and mark them generated. + this->CreateGeneratedSources(byproducts, cmSourceFileLocationKind::Known); + std::string force = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName); std::vector<std::string> forced; @@ -1205,14 +1195,6 @@ cmTarget* cmMakefile::AddUtilityCommand( } else { cmSystemTools::Error("Could not get source file entry for " + force); } - - // Always create the byproduct sources and mark them generated. - for (std::string const& byproduct : byproducts) { - if (cmSourceFile* out = this->GetOrCreateSource( - byproduct, true, cmSourceFileLocationKind::Known)) { - out->SetProperty("GENERATED", "1"); - } - } } return target; } @@ -3325,6 +3307,16 @@ cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName, return this->CreateSource(sourceName, generated, kind); } +void cmMakefile::CreateGeneratedSources( + const std::vector<std::string>& outputs, cmSourceFileLocationKind kind) +{ + for (std::string const& output : outputs) { + if (cmSourceFile* out = this->GetOrCreateSource(output, true, kind)) { + out->SetProperty("GENERATED", "1"); + } + } +} + void cmMakefile::AddTargetObject(std::string const& tgtName, std::string const& objFile) { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 09f53c9..52464d6 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1030,6 +1030,11 @@ private: bool escapeQuotes, bool noEscapes, bool atOnly, const char* filename, long line, bool replaceAt) const; + + void CreateGeneratedSources( + const std::vector<std::string>& outputs, + cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous); + /** * Old version of GetSourceFileWithOutput(const std::string&) kept for * backward-compatibility. It implements a linear search and support diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d603dac..36f6809 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -301,19 +301,16 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules( // Collect up flags to link in needed libraries. std::string linkLibs; - if (this->GeneratorTarget->GetType() != cmStateEnums::STATIC_LIBRARY) { - - std::unique_ptr<cmLinkLineComputer> linkLineComputer( - new cmLinkLineDeviceComputer( - this->LocalGenerator, - this->LocalGenerator->GetStateSnapshot().GetDirectory())); - linkLineComputer->SetForResponse(useResponseFileForLibs); - linkLineComputer->SetUseWatcomQuote(useWatcomQuote); - linkLineComputer->SetRelink(relink); - - this->CreateLinkLibs(linkLineComputer.get(), linkLibs, - useResponseFileForLibs, depends); - } + std::unique_ptr<cmLinkLineComputer> linkLineComputer( + new cmLinkLineDeviceComputer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory())); + linkLineComputer->SetForResponse(useResponseFileForLibs); + linkLineComputer->SetUseWatcomQuote(useWatcomQuote); + linkLineComputer->SetRelink(relink); + + this->CreateLinkLibs(linkLineComputer.get(), linkLibs, + useResponseFileForLibs, depends); // Construct object file lists that may be needed to expand the // rule. diff --git a/Source/cmScriptGenerator.h b/Source/cmScriptGenerator.h index eee331f..c8bb1ab 100644 --- a/Source/cmScriptGenerator.h +++ b/Source/cmScriptGenerator.h @@ -25,7 +25,7 @@ public: } cmScriptGeneratorIndent Next(int step = 2) const { - return cmScriptGeneratorIndent(this->Level + step); + return { this->Level + step }; } private: diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 670161d..d576f36 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -167,7 +167,7 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/, std::pair<int, int> cmServerProtocol1::ProtocolVersion() const { - return std::make_pair(1, 2); + return { 1, 2 }; } static void setErrorMessage(std::string* errorMessage, const std::string& text) diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 902287c..92d17ab 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -324,7 +324,7 @@ cmStateSnapshot cmState::Reset() this->DefineProperty("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true); this->DefineProperty("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true); - return cmStateSnapshot(this, pos); + return { this, pos }; } void cmState::DefineProperty(const std::string& name, @@ -789,7 +789,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot() assert(pos->Vars.IsValid()); pos->Parent = this->VarTree.Root(); pos->Root = this->VarTree.Root(); - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreateBuildsystemDirectorySnapshot( @@ -842,7 +842,7 @@ cmStateSnapshot cmState::CreateFunctionCallSnapshot( cmLinkedTree<cmDefinitions>::iterator origin = originSnapshot.Position->Vars; pos->Parent = origin; pos->Vars = this->VarTree.Push(origin); - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreateMacroCallSnapshot( @@ -857,7 +857,7 @@ cmStateSnapshot cmState::CreateMacroCallSnapshot( assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreateIncludeFileSnapshot( @@ -872,7 +872,7 @@ cmStateSnapshot cmState::CreateIncludeFileSnapshot( assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreateVariableScopeSnapshot( @@ -890,7 +890,7 @@ cmStateSnapshot cmState::CreateVariableScopeSnapshot( pos->Parent = origin; pos->Vars = this->VarTree.Push(origin); assert(pos->Vars.IsValid()); - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreateInlineListFileSnapshot( @@ -904,7 +904,7 @@ cmStateSnapshot cmState::CreateInlineListFileSnapshot( originSnapshot.Position->ExecutionListFile, fileName); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::CreatePolicyScopeSnapshot( @@ -916,7 +916,7 @@ cmStateSnapshot cmState::CreatePolicyScopeSnapshot( pos->Keep = false; pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; - return cmStateSnapshot(this, pos); + return { this, pos }; } cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot) @@ -948,7 +948,7 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot) this->SnapshotData.Pop(pos); } - return cmStateSnapshot(this, prevPos); + return { this, prevPos }; } static bool ParseEntryWithoutType(const std::string& entry, std::string& var, diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 121923d..3c54f52 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -66,8 +66,7 @@ bool cmStateSnapshot::IsValid() const cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const { - return cmStateSnapshot(this->State, - this->Position->BuildSystemDirectory->DirectoryEnd); + return { this->State, this->Position->BuildSystemDirectory->DirectoryEnd }; } cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const @@ -126,7 +125,7 @@ cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const pos != this->State->SnapshotData.Root()) { ++pos; } - return cmStateSnapshot(this->State, pos); + return { this->State, pos }; } void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak) @@ -426,7 +425,7 @@ cmState* cmStateSnapshot::GetState() const cmStateDirectory cmStateSnapshot::GetDirectory() const { - return cmStateDirectory(this->Position->BuildSystemDirectory, *this); + return { this->Position->BuildSystemDirectory, *this }; } void cmStateSnapshot::SetProjectName(const std::string& name) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index b7287d9..074faa5 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -855,6 +855,18 @@ bool cmSystemTools::RenameFile(const std::string& oldname, #endif } +void cmSystemTools::MoveFileIfDifferent(const std::string& source, + const std::string& destination) +{ + if (FilesDiffer(source, destination)) { + if (RenameFile(source, destination)) { + return; + } + CopyFileAlways(source, destination); + } + RemoveFile(source); +} + std::string cmSystemTools::ComputeFileHash(const std::string& source, cmCryptoHash::Algo algo) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 863db3f..8ca4939 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -131,6 +131,10 @@ public: static bool RenameFile(const std::string& oldname, const std::string& newname); + //! Rename a file if contents are different, delete the source otherwise + static void MoveFileIfDifferent(const std::string& source, + const std::string& destination); + //! Compute the hash of a file static std::string ComputeFileHash(const std::string& source, cmCryptoHash::Algo algo); diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx index cfc00e8..1fd386b 100644 --- a/Source/cmUseMangledMesaCommand.cxx +++ b/Source/cmUseMangledMesaCommand.cxx @@ -98,7 +98,6 @@ void CopyAndFullPathMesaHeader(const std::string& source, // close the files before attempting to copy fin.close(); fout.close(); - cmSystemTools::CopyFileIfDifferent(tempOutputFile, outFile); - cmSystemTools::RemoveFile(tempOutputFile); + cmSystemTools::MoveFileIfDifferent(tempOutputFile, outFile); } } diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx index db23efd..f9f7d66 100644 --- a/Source/cmVariableWatchCommand.cxx +++ b/Source/cmVariableWatchCommand.cxx @@ -91,6 +91,7 @@ static void deleteVariableWatchCallbackData(void* client_data) class FinalAction { public: + /* NOLINTNEXTLINE(performance-unnecessary-value-param) */ FinalAction(cmMakefile* makefile, std::string variable) : Action(std::make_shared<Impl>(makefile, std::move(variable))) { diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 5e92622..ba72294 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3152,6 +3152,82 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( "-Wno-deprecated-gpu-targets"); } + // For static libraries that have device linking enabled compute + // the libraries + if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY && + doDeviceLinking) { + cmComputeLinkInformation* pcli = + this->GeneratorTarget->GetLinkInformation(configName); + if (!pcli) { + cmSystemTools::Error( + "CMake can not compute cmComputeLinkInformation for target: " + + this->Name); + return false; + } + + // Would like to use: + // cmLinkLineDeviceComputer computer(this->LocalGenerator, + // this->LocalGenerator->GetStateSnapshot().GetDirectory()); + // std::string computed_libs = computer.ComputeLinkLibraries(cli, + // std::string{}); but it outputs in "<libA> <libB>" format instead of + // "<libA>;<libB>" + // Note: + // Any modification of this algorithm should be reflected also in + // cmLinkLineDeviceComputer + cmComputeLinkInformation& cli = *pcli; + std::vector<std::string> libVec; + const std::string currentBinDir = + this->LocalGenerator->GetCurrentBinaryDirectory(); + const auto& libs = cli.GetItems(); + for (cmComputeLinkInformation::Item const& l : libs) { + + if (l.Target) { + auto managedType = l.Target->GetManagedType(configName); + // 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 (managedType == cmGeneratorTarget::ManagedType::Managed) { + continue; + } + const auto type = l.Target->GetType(); + + bool skip = false; + switch (type) { + case cmStateEnums::SHARED_LIBRARY: + case cmStateEnums::MODULE_LIBRARY: + case cmStateEnums::INTERFACE_LIBRARY: + skip = true; + break; + case cmStateEnums::STATIC_LIBRARY: + skip = l.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS"); + break; + default: + break; + } + if (skip) { + continue; + } + } + + if (l.IsPath) { + std::string path = this->LocalGenerator->MaybeConvertToRelativePath( + currentBinDir, l.Value); + ConvertToWindowsSlash(path); + if (!cmVS10IsTargetsFile(l.Value)) { + libVec.push_back(path); + } + } else { + libVec.push_back(l.Value); + } + } + + cudaLinkOptions.AddFlag("AdditionalDependencies", libVec); + } + this->CudaLinkOptions[configName] = std::move(pOptions); return true; } diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index a5b06af..c4103cc 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -77,14 +77,11 @@ private: void CloseStartElement(); private: - static cmXMLSafe SafeAttribute(const char* value) - { - return cmXMLSafe(value); - } + static cmXMLSafe SafeAttribute(const char* value) { return { value }; } static cmXMLSafe SafeAttribute(std::string const& value) { - return cmXMLSafe(value); + return { value }; } template <typename T> diff --git a/Source/cmake.cxx b/Source/cmake.cxx index ace9198..e7c714e 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1081,20 +1081,18 @@ createExtraGenerator( const std::vector<std::string> generators = i->GetSupportedGlobalGenerators(); if (i->GetName() == name) { // Match aliases - return std::make_pair(i->CreateExternalMakefileProjectGenerator(), - generators.at(0)); + return { i->CreateExternalMakefileProjectGenerator(), generators.at(0) }; } for (std::string const& g : generators) { const std::string fullName = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( g, i->GetName()); if (fullName == name) { - return std::make_pair(i->CreateExternalMakefileProjectGenerator(), g); + return { i->CreateExternalMakefileProjectGenerator(), g }; } } } - return std::make_pair( - static_cast<cmExternalMakefileProjectGenerator*>(nullptr), name); + return { nullptr, name }; } cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index a79a2ff..e6dd99a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -562,19 +562,36 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) "objlistfile [-nm=nm-path]\n"; return 1; } - FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); - if (!fout) { - std::cerr << "could not open output .def file: " << args[2].c_str() - << "\n"; - return 1; - } cmsys::ifstream fin(args[3].c_str(), std::ios::in | std::ios::binary); if (!fin) { std::cerr << "could not open object list file: " << args[3].c_str() << "\n"; return 1; } - std::string file; + std::vector<std::string> files; + { + std::string file; + cmFileTime outTime; + bool outValid = outTime.Load(args[2]); + while (cmSystemTools::GetLineFromStream(fin, file)) { + files.push_back(file); + if (outValid) { + cmFileTime inTime; + outValid = inTime.Load(file) && inTime.Older(outTime); + } + } + if (outValid) { + // The def file already exists and all input files are older than the + // existing def file. + return 0; + } + } + FILE* fout = cmsys::SystemTools::Fopen(args[2].c_str(), "w+"); + if (!fout) { + std::cerr << "could not open output .def file: " << args[2].c_str() + << "\n"; + return 1; + } bindexplib deffile; if (args.size() >= 5) { auto a = args[4]; @@ -585,7 +602,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args) std::cerr << "unknown argument: " << a << "\n"; } } - while (cmSystemTools::GetLineFromStream(fin, file)) { + for (auto const& file : files) { std::string const& ext = cmSystemTools::GetFilenameLastExtension(file); if (cmSystemTools::LowerCase(ext) == ".def") { if (!deffile.AddDefinitionFile(file.c_str())) { diff --git a/Tests/CMakeLib/testUVProcessChainHelper.cxx b/Tests/CMakeLib/testUVProcessChainHelper.cxx index 263665d..a77ec90 100644 --- a/Tests/CMakeLib/testUVProcessChainHelper.cxx +++ b/Tests/CMakeLib/testUVProcessChainHelper.cxx @@ -44,7 +44,7 @@ int main(int argc, char** argv) } if (command == "dedup") { // Use a nested scope to free all resources before aborting below. - { + try { std::string input = getStdin(); std::set<char> seen; std::string output; @@ -56,6 +56,7 @@ int main(int argc, char** argv) } std::cout << output << std::flush; std::cerr << "3" << std::flush; + } catch (...) { } // On Windows, the exit code of abort() is different between debug and diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt index 796e133..64845c5 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt +++ b/Tests/CudaOnly/ResolveDeviceSymbols/CMakeLists.txt @@ -16,21 +16,29 @@ else() endif() #Goal for this example: -# Build a static library that defines multiple methods and kernels that -# use each other. -# Resolve the device symbols into that static library -# Verify that we can't use those device symbols from anything that links +# 1. Build two static libraries that defines multiple methods and kernels +# 2. Resolve the device symbols into the second static library, therefore +# confirming that the first static library is on the device link line +# 3. Verify that we can't use those device symbols from anything that links # to the static library -string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[compute_30] -gencode arch=compute_50,code=\\\"compute_50\\\"") +string(APPEND CMAKE_CUDA_FLAGS " -gencode arch=compute_30,code=[sm_30] -gencode arch=compute_50,code=\\\"compute_50\\\"") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CUDA_STANDARD 11) -add_library(CUDAResolveDeviceLib STATIC file1.cu file2.cu) +add_library(CUDAResolveDeviceDepsA STATIC file1.cu) +add_library(CUDAResolveDeviceDepsB STATIC file2.cu) +set_target_properties(CUDAResolveDeviceDepsA CUDAResolveDeviceDepsB + PROPERTIES + CUDA_SEPARABLE_COMPILATION ON + POSITION_INDEPENDENT_CODE ON) + +add_library(CUDAResolveDeviceLib STATIC file2_launch.cu) set_target_properties(CUDAResolveDeviceLib PROPERTIES CUDA_SEPARABLE_COMPILATION ON CUDA_RESOLVE_DEVICE_SYMBOLS ON POSITION_INDEPENDENT_CODE ON) +target_link_libraries(CUDAResolveDeviceLib PRIVATE CUDAResolveDeviceDepsA CUDAResolveDeviceDepsB) if(dump_command) add_custom_command(TARGET CUDAResolveDeviceLib POST_BUILD @@ -45,7 +53,8 @@ endif() add_executable(CudaOnlyResolveDeviceSymbols main.cu) set_target_properties(CudaOnlyResolveDeviceSymbols PROPERTIES - CUDA_SEPARABLE_COMPILATION ON) + CUDA_SEPARABLE_COMPILATION OFF + CUDA_RESOLVE_DEVICE_SYMBOLS OFF) target_link_libraries(CudaOnlyResolveDeviceSymbols PRIVATE CUDAResolveDeviceLib) diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file1.h b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h index ff1945c..b33bcae 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/file1.h +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file1.h @@ -1,7 +1,10 @@ #pragma once + struct result_type { int input; int sum; }; + +result_type __device__ file1_func(int x); diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu index 278fd6c..0e5e7aa 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.cu @@ -1,25 +1,9 @@ #include "file2.h" -result_type __device__ file1_func(int x); - result_type_dynamic __device__ file2_func(int x) { const result_type r = file1_func(x); const result_type_dynamic rd{ r.input, r.sum, true }; return rd; } - -static __global__ void file2_kernel(result_type_dynamic& r, int x) -{ - // call static_func which is a method that is defined in the - // static library that is always out of date - r = file2_func(x); -} - -int file2_launch_kernel(int x) -{ - result_type_dynamic r; - file2_kernel<<<1, 1>>>(r, x); - return r.sum; -} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2.h b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h index d2dbaa4..c6e2875 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/file2.h +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2.h @@ -8,3 +8,5 @@ struct result_type_dynamic int sum; bool from_static; }; + +result_type_dynamic __device__ file2_func(int x); diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/file2_launch.cu b/Tests/CudaOnly/ResolveDeviceSymbols/file2_launch.cu new file mode 100644 index 0000000..4e8da13 --- /dev/null +++ b/Tests/CudaOnly/ResolveDeviceSymbols/file2_launch.cu @@ -0,0 +1,18 @@ + +#include "file2.h" + +static __global__ void file2_kernel(result_type_dynamic& r, int x) +{ + // call static_func which is a method that is defined in the + // static library that is always out of date + r = file2_func(x); +} + +static __global__ void file2_kernel(result_type_dynamic& r, int x); + +int file2_launch_kernel(int x) +{ + result_type_dynamic r; + file2_kernel<<<1, 1>>>(r, x); + return r.sum; +} diff --git a/Tests/CudaOnly/ResolveDeviceSymbols/main.cu b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu index d464f96..ea842cc 100644 --- a/Tests/CudaOnly/ResolveDeviceSymbols/main.cu +++ b/Tests/CudaOnly/ResolveDeviceSymbols/main.cu @@ -1,26 +1,10 @@ #include <iostream> -#include "file1.h" #include "file2.h" int file2_launch_kernel(int x); -result_type_dynamic __device__ file2_func(int x); -static __global__ void main_kernel(result_type_dynamic& r, int x) -{ - // call function that was not device linked to us, this will cause - // a runtime failure of "invalid device function" - r = file2_func(x); -} - -int main_launch_kernel(int x) -{ - result_type_dynamic r; - main_kernel<<<1, 1>>>(r, x); - return r.sum; -} - int choose_cuda_device() { int nDevices = 0; @@ -62,12 +46,10 @@ int main(int argc, char** argv) return 0; } - main_launch_kernel(1); + file2_launch_kernel(1); cudaError_t err = cudaGetLastError(); - if (err == cudaSuccess) { - // This kernel launch should fail as the file2_func was device linked - // into the static library and is not usable by the executable - std::cerr << "main_launch_kernel: kernel launch should have failed" + if (err != cudaSuccess) { + std::cerr << "file2_launch_kernel: kernel launch should have passed" << std::endl; return 1; } diff --git a/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake b/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake index 27a609d..6c9be4b 100644 --- a/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake +++ b/Tests/RunCMake/AutoExportDll/RunCMakeTest.cmake @@ -7,9 +7,13 @@ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") run_cmake(AutoExport) unset(RunCMake_TEST_OPTIONS) # don't run this test on Watcom or Borland make as it is not supported -if("${RunCMake_GENERATOR}" MATCHES "Watcom WMake|Borland Makefiles") +if(RunCMake_GENERATOR MATCHES "Watcom WMake|Borland Makefiles") return() endif() +if(RunCMake_GENERATOR MATCHES "Ninja|Visual Studio" AND + CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(EXPORTS TRUE) +endif() # we build debug so the say.exe will be found in Debug/say.exe for # Visual Studio generators if(RunCMake_GENERATOR_IS_MULTI_CONFIG) @@ -18,9 +22,36 @@ endif() # build AutoExport run_cmake_command(AutoExportBuild ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Debug --clean-first) +# save the current timestamp of exports.def +if(EXPORTS) + set(EXPORTS_DEF "${RunCMake_TEST_BINARY_DIR}/say.dir/${INTDIR}exports.def") + if(NOT EXISTS "${EXPORTS_DEF}") + set(EXPORTS_DEF + "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/say.dir/${INTDIR}exports.def") + endif() + file(TIMESTAMP "${EXPORTS_DEF}" timestamp) + if(NOT timestamp) + message(SEND_ERROR "Could not get timestamp for \"${EXPORTS_DEF}\"") + endif() +endif() # run the executable that uses symbols from the dll if(WIN32) set(EXE_EXT ".exe") endif() run_cmake_command(AutoExportRun - ${RunCMake_BINARY_DIR}/AutoExport-build/bin/${INTDIR}say${EXE_EXT}) + ${RunCMake_TEST_BINARY_DIR}/bin/${INTDIR}say${EXE_EXT}) +# build AutoExport again without modification +run_cmake_command(AutoExportBuildAgain ${CMAKE_COMMAND} --build + ${RunCMake_TEST_BINARY_DIR} --config Debug) +# compare timestamps of exports.def to make sure it has not been updated +if(EXPORTS) + file(TIMESTAMP "${EXPORTS_DEF}" timestamp_after) + if(NOT timestamp_after) + message(SEND_ERROR "Could not get timestamp for \"${EXPORTS_DEF}\"") + endif() + if (timestamp_after STREQUAL timestamp) + message(STATUS "AutoExportTimeStamp - PASSED") + else() + message(SEND_ERROR "\"${EXPORTS_DEF}\" has been updated.") + endif() +endif() diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 8fd5234..c663484 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -543,7 +543,7 @@ set(cpack_tests add_RunCMake_test_group(CPack "${cpack_tests}") # add a test to make sure symbols are exported from a shared library # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used -add_RunCMake_test(AutoExportDll) +add_RunCMake_test(AutoExportDll -DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) add_RunCMake_test(AndroidMK) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index 89f63d0..2a24421 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -232,17 +232,37 @@ def check_target(c): assert is_string(obj["link"]["language"], expected["link"]["language"]) - # FIXME: Properly test commandFragments if "commandFragments" in obj["link"]: link_keys.append("commandFragments") assert is_list(obj["link"]["commandFragments"]) for f in obj["link"]["commandFragments"]: assert is_dict(f) - assert sorted(f.keys()) == ["fragment", "role"] + assert sorted(f.keys()) == ["fragment", "role"] or sorted(f.keys()) == ["backtrace", "fragment", "role"] assert is_string(f["fragment"]) assert is_string(f["role"]) assert f["role"] in ("flags", "libraries", "libraryPath", "frameworkPath") + if expected["link"]["commandFragments"] is not None: + def check_link_command_fragments(actual, expected): + assert is_dict(actual) + expected_keys = ["fragment", "role"] + + if expected["backtrace"] is not None: + expected_keys.append("backtrace") + assert actual["fragment"] == expected["fragment"] + assert actual["role"] == expected["role"] + check_backtrace(obj, actual["backtrace"], expected["backtrace"]) + + assert sorted(actual.keys()) == sorted(expected_keys) + + check_list_match(lambda a, e: is_string(a["fragment"], e["fragment"]), + obj["link"]["commandFragments"], expected["link"]["commandFragments"], + check=check_link_command_fragments, + check_exception=lambda a, e: "Link fragment: %s" % a["fragment"], + missing_exception=lambda e: "Link fragment: %s" % e["fragment"], + extra_exception=lambda a: "Link fragment: %s" % a["fragment"], + allow_extra=True) + if expected["link"]["lto"] is not None: link_keys.append("lto") assert is_bool(obj["link"]["lto"], expected["link"]["lto"]) @@ -327,15 +347,33 @@ def check_target(c): missing_exception=lambda e: "Source path: %s" % e, extra_exception=lambda a: "Source path: %s" % obj["sources"][a]["path"]) - # FIXME: Properly test compileCommandFragments if "compileCommandFragments" in actual: expected_keys.append("compileCommandFragments") assert is_list(actual["compileCommandFragments"]) for f in actual["compileCommandFragments"]: assert is_dict(f) - assert sorted(f.keys()) == ["fragment"] assert is_string(f["fragment"]) + if expected["compileCommandFragments"] is not None: + def check_compile_command_fragments(actual, expected): + assert is_dict(actual) + expected_keys = ["fragment"] + + if expected["backtrace"] is not None: + expected_keys.append("backtrace") + assert actual["fragment"] == expected["fragment"] + check_backtrace(obj, actual["backtrace"], expected["backtrace"]) + + assert sorted(actual.keys()) == sorted(expected_keys) + + check_list_match(lambda a, e: is_string(a["fragment"], e["fragment"]), + actual["compileCommandFragments"], expected["compileCommandFragments"], + check=check_compile_command_fragments, + check_exception=lambda a, e: "Compile fragment: %s" % a["fragment"], + missing_exception=lambda e: "Compile fragment: %s" % e["fragment"], + extra_exception=lambda a: "Compile fragment: %s" % a["fragment"], + allow_extra=True) + if expected["includes"] is not None: expected_keys.append("includes") @@ -931,6 +969,7 @@ def gen_check_targets(c, g, inSource): "backtrace": None, }, ], + "compileCommandFragments": None, }, ], "backtrace": [ @@ -998,6 +1037,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -1064,6 +1104,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1171,6 +1212,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1217,6 +1259,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -1317,6 +1360,7 @@ def gen_check_targets(c, g, inSource): "backtrace": None, }, ], + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1367,6 +1411,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": True, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -1433,6 +1478,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1479,6 +1525,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": True, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -1574,6 +1621,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1681,6 +1729,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -1727,6 +1776,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -1979,6 +2029,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2062,6 +2113,25 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": [ + { + "fragment" : "TargetCompileOptions", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 17, + "command": "target_compile_options", + "hasParent": True, + }, + { + "file" : "^cxx/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + } + ], }, ], "backtrace": [ @@ -2129,6 +2199,26 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": [ + { + "fragment" : "TargetLinkOptions", + "role" : "flags", + "backtrace": [ + { + "file": "^cxx/CMakeLists\\.txt$", + "line": 18, + "command": "target_link_options", + "hasParent": True, + }, + { + "file" : "^cxx/CMakeLists\\.txt$", + "line": None, + "command": None, + "hasParent": False, + }, + ], + }, + ], }, "archive": None, "dependencies": [ @@ -2205,6 +2295,7 @@ def gen_check_targets(c, g, inSource): "backtrace": None, }, ], + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2243,6 +2334,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -2297,6 +2389,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2331,6 +2424,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -2402,6 +2496,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2485,6 +2580,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2519,6 +2615,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -2743,6 +2840,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2777,6 +2875,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -2848,6 +2947,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -2882,6 +2982,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3114,6 +3215,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3221,6 +3323,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3276,6 +3379,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3337,6 +3441,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3444,6 +3549,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3499,6 +3605,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3725,6 +3832,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3759,6 +3867,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3813,6 +3922,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3847,6 +3957,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3901,6 +4012,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -3935,6 +4047,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -3989,6 +4102,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -4023,6 +4137,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -4077,6 +4192,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -4111,6 +4227,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -4401,6 +4518,7 @@ def gen_check_targets(c, g, inSource): ], "includes": None, "defines": None, + "compileCommandFragments": None, }, ], "backtrace": [ @@ -4435,6 +4553,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "C", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ @@ -4748,6 +4867,7 @@ def gen_check_targets(c, g, inSource): ], }, ], + "compileCommandFragments": None, }, { "language": "CXX", @@ -4810,6 +4930,7 @@ def gen_check_targets(c, g, inSource): ], }, ], + "compileCommandFragments": None, }, ], "backtrace": [ @@ -4844,6 +4965,7 @@ def gen_check_targets(c, g, inSource): "link": { "language": "CXX", "lto": None, + "commandFragments": None, }, "archive": None, "dependencies": [ diff --git a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt index 29b61b8..17ff455 100644 --- a/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/cxx/CMakeLists.txt @@ -13,3 +13,6 @@ target_link_libraries(cxx_shared_exe PRIVATE cxx_shared_lib) add_library(cxx_static_lib STATIC ../empty.cxx) add_executable(cxx_static_exe ../empty.cxx) target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib) + +target_compile_options(cxx_exe PUBLIC TargetCompileOptions) +target_link_options(cxx_exe PUBLIC TargetLinkOptions) |