|
|
@@ -37,6 +37,7 @@
|
|
|
#include "cmMessageType.h"
|
|
|
#include "cmOutputConverter.h"
|
|
|
#include "cmPropertyMap.h"
|
|
|
+#include "cmRulePlaceholderExpander.h"
|
|
|
#include "cmSourceFile.h"
|
|
|
#include "cmSourceFileLocation.h"
|
|
|
#include "cmSourceFileLocationKind.h"
|
|
|
@@ -138,6 +139,20 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
|
|
|
} else {
|
|
|
this->LinkerLanguage = this->Target->GetSafeProperty("LINKER_LANGUAGE");
|
|
|
}
|
|
|
+
|
|
|
+ auto configs =
|
|
|
+ this->Makefile->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
|
|
|
+ std::string build_db_languages[] = { "CXX" };
|
|
|
+ for (auto const& language : build_db_languages) {
|
|
|
+ for (auto const& config : configs) {
|
|
|
+ auto bdb_path = this->BuildDatabasePath(language, config);
|
|
|
+ if (!bdb_path.empty()) {
|
|
|
+ this->Makefile->GetOrCreateGeneratedSource(bdb_path);
|
|
|
+ this->GetGlobalGenerator()->AddBuildDatabaseFile(language, config,
|
|
|
+ bdb_path);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
cmGeneratorTarget::~cmGeneratorTarget() = default;
|
|
|
@@ -173,6 +188,20 @@ const std::string& cmGeneratorTarget::GetName() const
|
|
|
return this->Target->GetName();
|
|
|
}
|
|
|
|
|
|
+std::string cmGeneratorTarget::GetFamilyName() const
|
|
|
+{
|
|
|
+ if (!this->IsImported() && !this->IsSynthetic()) {
|
|
|
+ return this->Target->GetTemplateName();
|
|
|
+ }
|
|
|
+ cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
|
|
|
+ constexpr size_t HASH_TRUNCATION = 12;
|
|
|
+ auto dirhash =
|
|
|
+ hasher.HashString(this->GetLocalGenerator()->GetCurrentBinaryDirectory());
|
|
|
+ auto targetIdent = hasher.HashString(cmStrCat("@d_", dirhash));
|
|
|
+ return cmStrCat(this->Target->GetTemplateName(), '@',
|
|
|
+ targetIdent.substr(0, HASH_TRUNCATION));
|
|
|
+}
|
|
|
+
|
|
|
std::string cmGeneratorTarget::GetExportName() const
|
|
|
{
|
|
|
cmValue exportName = this->GetProperty("EXPORT_NAME");
|
|
|
@@ -2010,6 +2039,425 @@ std::vector<std::string> cmGeneratorTarget::GetAppleArchs(
|
|
|
return std::move(archList.data());
|
|
|
}
|
|
|
|
|
|
+namespace {
|
|
|
+
|
|
|
+bool IsSupportedClassifiedFlagsLanguage(std::string const& lang)
|
|
|
+{
|
|
|
+ return lang == "CXX"_s;
|
|
|
+}
|
|
|
+
|
|
|
+bool CanUseCompilerLauncher(std::string const& lang)
|
|
|
+{
|
|
|
+ // Also found in `cmCommonTargetGenerator::GetCompilerLauncher`.
|
|
|
+ return lang == "C"_s || lang == "CXX"_s || lang == "Fortran"_s ||
|
|
|
+ lang == "CUDA"_s || lang == "HIP"_s || lang == "ISPC"_s ||
|
|
|
+ lang == "OBJC"_s || lang == "OBJCXX"_s;
|
|
|
+}
|
|
|
+
|
|
|
+// FIXME: return a vector of `cm::string_view` instead to avoid lots of tiny
|
|
|
+// allocations.
|
|
|
+std::vector<std::string> SplitFlags(std::string const& flags)
|
|
|
+{
|
|
|
+ std::vector<std::string> options;
|
|
|
+
|
|
|
+#ifdef _WIN32
|
|
|
+ cmSystemTools::ParseWindowsCommandLine(flags.c_str(), options);
|
|
|
+#else
|
|
|
+ cmSystemTools::ParseUnixCommandLine(flags.c_str(), options);
|
|
|
+#endif
|
|
|
+
|
|
|
+ return options;
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+cmGeneratorTarget::ClassifiedFlags
|
|
|
+cmGeneratorTarget::GetClassifiedFlagsForSource(cmSourceFile const* sf,
|
|
|
+ std::string const& config)
|
|
|
+{
|
|
|
+ auto& sourceFlagsCache = this->Configs[config].SourceFlags;
|
|
|
+ auto cacheEntry = sourceFlagsCache.lower_bound(sf);
|
|
|
+ if (cacheEntry != sourceFlagsCache.end() && cacheEntry->first == sf) {
|
|
|
+ return cacheEntry->second;
|
|
|
+ }
|
|
|
+
|
|
|
+ ClassifiedFlags flags;
|
|
|
+ std::string const& lang = sf->GetLanguage();
|
|
|
+
|
|
|
+ if (!IsSupportedClassifiedFlagsLanguage(lang)) {
|
|
|
+ return flags;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto* const lg = this->GetLocalGenerator();
|
|
|
+ auto const* const mf = this->Makefile;
|
|
|
+
|
|
|
+ // Compute the compiler launcher flags.
|
|
|
+ if (CanUseCompilerLauncher(lang)) {
|
|
|
+ // Compiler launchers are all execution flags and should not be relevant to
|
|
|
+ // the actual compilation.
|
|
|
+ FlagClassification cls = FlagClassification::ExecutionFlag;
|
|
|
+ FlagKind kind = FlagKind::NotAFlag;
|
|
|
+
|
|
|
+ std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER");
|
|
|
+ cmValue clauncher = this->GetProperty(clauncher_prop);
|
|
|
+ std::string const evaluatedClauncher = cmGeneratorExpression::Evaluate(
|
|
|
+ *clauncher, lg, config, this, nullptr, this, lang);
|
|
|
+
|
|
|
+ for (auto const& flag : SplitFlags(evaluatedClauncher)) {
|
|
|
+ flags.emplace_back(cls, kind, flag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ClassifiedFlags define_flags;
|
|
|
+ ClassifiedFlags include_flags;
|
|
|
+ ClassifiedFlags compile_flags;
|
|
|
+
|
|
|
+ SourceVariables sfVars = this->GetSourceVariables(sf, config);
|
|
|
+
|
|
|
+ // Compute language flags.
|
|
|
+ {
|
|
|
+ FlagClassification cls = FlagClassification::BaselineFlag;
|
|
|
+ FlagKind kind = FlagKind::Compile;
|
|
|
+
|
|
|
+ std::string mfFlags;
|
|
|
+ // Explicitly add the explicit language flag before any other flag
|
|
|
+ // so user flags can override it.
|
|
|
+ this->AddExplicitLanguageFlags(mfFlags, *sf);
|
|
|
+
|
|
|
+ for (auto const& flag : SplitFlags(mfFlags)) {
|
|
|
+ flags.emplace_back(cls, kind, flag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ std::unordered_map<std::string, std::string> pchSources;
|
|
|
+ std::string filterArch;
|
|
|
+
|
|
|
+ {
|
|
|
+ std::vector<std::string> pchArchs = this->GetPchArchs(config, lang);
|
|
|
+
|
|
|
+ for (const std::string& arch : pchArchs) {
|
|
|
+ const std::string pchSource = this->GetPchSource(config, lang, arch);
|
|
|
+ if (pchSource == sf->GetFullPath()) {
|
|
|
+ filterArch = arch;
|
|
|
+ }
|
|
|
+ if (!pchSource.empty()) {
|
|
|
+ pchSources.insert(std::make_pair(pchSource, arch));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Compute target-wide flags.
|
|
|
+ {
|
|
|
+ FlagClassification cls = FlagClassification::BaselineFlag;
|
|
|
+
|
|
|
+ // Compile flags
|
|
|
+ {
|
|
|
+ FlagKind kind = FlagKind::Compile;
|
|
|
+ std::string targetFlags;
|
|
|
+
|
|
|
+ lg->GetTargetCompileFlags(this, config, lang, targetFlags, filterArch);
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(targetFlags)) {
|
|
|
+ compile_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Define flags
|
|
|
+ {
|
|
|
+ FlagKind kind = FlagKind::Definition;
|
|
|
+ std::set<std::string> defines;
|
|
|
+
|
|
|
+ lg->GetTargetDefines(this, config, lang, defines);
|
|
|
+
|
|
|
+ std::string defineFlags;
|
|
|
+ lg->JoinDefines(defines, defineFlags, lang);
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(defineFlags)) {
|
|
|
+ define_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Include flags
|
|
|
+ {
|
|
|
+ FlagKind kind = FlagKind::Include;
|
|
|
+ std::vector<std::string> includes;
|
|
|
+
|
|
|
+ lg->GetIncludeDirectories(includes, this, lang, config);
|
|
|
+ auto includeFlags =
|
|
|
+ lg->GetIncludeFlags(includes, this, lang, config, false);
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(includeFlags)) {
|
|
|
+ include_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
|
|
|
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
|
|
|
+
|
|
|
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, config, this, lang);
|
|
|
+
|
|
|
+ // Source-specific flags.
|
|
|
+ {
|
|
|
+ FlagClassification cls = FlagClassification::PrivateFlag;
|
|
|
+ FlagKind kind = FlagKind::Compile;
|
|
|
+
|
|
|
+ std::string sourceFlags;
|
|
|
+
|
|
|
+ if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
|
|
|
+ lg->AppendFlags(sourceFlags,
|
|
|
+ genexInterpreter.Evaluate(*cflags, COMPILE_FLAGS));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (cmValue coptions = sf->GetProperty(COMPILE_OPTIONS)) {
|
|
|
+ lg->AppendCompileOptions(
|
|
|
+ sourceFlags, genexInterpreter.Evaluate(*coptions, COMPILE_OPTIONS));
|
|
|
+ }
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(sourceFlags)) {
|
|
|
+ compile_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Dependency tracking flags.
|
|
|
+ {
|
|
|
+ if (!sfVars.DependencyFlags.empty()) {
|
|
|
+ cmRulePlaceholderExpander::RuleVariables vars;
|
|
|
+ auto rulePlaceholderExpander = lg->CreateRulePlaceholderExpander();
|
|
|
+
|
|
|
+ vars.DependencyFile = sfVars.DependencyFile.c_str();
|
|
|
+ vars.DependencyTarget = sfVars.DependencyTarget.c_str();
|
|
|
+
|
|
|
+ std::string depfileFlags = sfVars.DependencyFlags;
|
|
|
+ rulePlaceholderExpander->ExpandRuleVariables(lg, depfileFlags, vars);
|
|
|
+ for (auto&& flag : SplitFlags(depfileFlags)) {
|
|
|
+ compile_flags.emplace_back(FlagClassification::LocationFlag,
|
|
|
+ FlagKind::BuildSystem, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Precompiled headers.
|
|
|
+ {
|
|
|
+ FlagClassification cls = FlagClassification::PrivateFlag;
|
|
|
+ FlagKind kind = FlagKind::Compile;
|
|
|
+
|
|
|
+ std::string pchFlags;
|
|
|
+
|
|
|
+ // Add precompile headers compile options.
|
|
|
+ if (!sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) {
|
|
|
+ if (!pchSources.empty()) {
|
|
|
+ std::string pchOptions;
|
|
|
+ auto pchIt = pchSources.find(sf->GetFullPath());
|
|
|
+ if (pchIt != pchSources.end()) {
|
|
|
+ pchOptions =
|
|
|
+ this->GetPchCreateCompileOptions(config, lang, pchIt->second);
|
|
|
+ } else {
|
|
|
+ pchOptions = this->GetPchUseCompileOptions(config, lang);
|
|
|
+ }
|
|
|
+
|
|
|
+ this->LocalGenerator->AppendCompileOptions(
|
|
|
+ pchFlags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(pchFlags)) {
|
|
|
+ compile_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // C++ module flags.
|
|
|
+ if (lang == "CXX"_s) {
|
|
|
+ FlagClassification cls = FlagClassification::LocationFlag;
|
|
|
+ FlagKind kind = FlagKind::BuildSystem;
|
|
|
+
|
|
|
+ std::string bmiFlags;
|
|
|
+
|
|
|
+ auto const* fs = this->GetFileSetForSource(config, sf);
|
|
|
+ if (fs && fs->GetType() == "CXX_MODULES"_s) {
|
|
|
+ if (lang != "CXX"_s) {
|
|
|
+ mf->IssueMessage(
|
|
|
+ MessageType::FATAL_ERROR,
|
|
|
+ cmStrCat(
|
|
|
+ "Target \"", this->Target->GetName(), "\" contains the source\n ",
|
|
|
+ sf->GetFullPath(), "\nin a file set of type \"", fs->GetType(),
|
|
|
+ R"(" but the source is not classified as a "CXX" source.)"));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this->Target->IsNormal()) {
|
|
|
+ auto flag = mf->GetSafeDefinition("CMAKE_CXX_MODULE_BMI_ONLY_FLAG");
|
|
|
+ cmRulePlaceholderExpander::RuleVariables compileObjectVars;
|
|
|
+ compileObjectVars.Object = sfVars.ObjectFileDir.c_str();
|
|
|
+ auto rulePlaceholderExpander = lg->CreateRulePlaceholderExpander();
|
|
|
+ rulePlaceholderExpander->ExpandRuleVariables(lg, flag,
|
|
|
+ compileObjectVars);
|
|
|
+ lg->AppendCompileOptions(bmiFlags, flag);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (auto&& flag : SplitFlags(bmiFlags)) {
|
|
|
+ compile_flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cmRulePlaceholderExpander::RuleVariables vars;
|
|
|
+ vars.CMTargetName = this->GetName().c_str();
|
|
|
+ vars.CMTargetType = cmState::GetTargetTypeName(this->GetType()).c_str();
|
|
|
+ vars.Language = lang.c_str();
|
|
|
+ auto const sfPath = this->LocalGenerator->ConvertToOutputFormat(
|
|
|
+ sf->GetFullPath(), cmOutputConverter::SHELL);
|
|
|
+
|
|
|
+ // Compute the base compiler command line. We'll find placeholders and
|
|
|
+ // replace them with arguments later in this function.
|
|
|
+ {
|
|
|
+ FlagClassification cls = FlagClassification::ExecutionFlag;
|
|
|
+ FlagKind kind = FlagKind::NotAFlag;
|
|
|
+
|
|
|
+ std::string const cmdVar = cmStrCat("CMAKE_", lang, "_COMPILE_OBJECT");
|
|
|
+ std::string const& compileCmd = mf->GetRequiredDefinition(cmdVar);
|
|
|
+ cmList compileCmds(compileCmd); // FIXME: which command to use?
|
|
|
+ std::string& cmd = compileCmds[0];
|
|
|
+ auto rulePlaceholderExpander = lg->CreateRulePlaceholderExpander();
|
|
|
+
|
|
|
+ static std::string const PlaceholderDefines = "__CMAKE_DEFINES";
|
|
|
+ static std::string const PlaceholderIncludes = "__CMAKE_INCLUDES";
|
|
|
+ static std::string const PlaceholderFlags = "__CMAKE_FLAGS";
|
|
|
+ static std::string const PlaceholderSource = "__CMAKE_SOURCE";
|
|
|
+
|
|
|
+ vars.Defines = PlaceholderDefines.c_str();
|
|
|
+ vars.Includes = PlaceholderIncludes.c_str();
|
|
|
+ vars.TargetPDB = sfVars.TargetPDB.c_str();
|
|
|
+ vars.TargetCompilePDB = sfVars.TargetCompilePDB.c_str();
|
|
|
+ vars.Object = sfVars.ObjectFileDir.c_str();
|
|
|
+ vars.ObjectDir = sfVars.ObjectDir.c_str();
|
|
|
+ vars.ObjectFileDir = sfVars.ObjectFileDir.c_str();
|
|
|
+ vars.Flags = PlaceholderFlags.c_str();
|
|
|
+ vars.DependencyFile = sfVars.DependencyFile.c_str();
|
|
|
+ vars.DependencyTarget = sfVars.DependencyTarget.c_str();
|
|
|
+ vars.Source = PlaceholderSource.c_str();
|
|
|
+
|
|
|
+ rulePlaceholderExpander->ExpandRuleVariables(lg, cmd, vars);
|
|
|
+ for (auto&& flag : SplitFlags(cmd)) {
|
|
|
+ if (flag == PlaceholderDefines) {
|
|
|
+ flags.insert(flags.end(), define_flags.begin(), define_flags.end());
|
|
|
+ } else if (flag == PlaceholderIncludes) {
|
|
|
+ flags.insert(flags.end(), include_flags.begin(), include_flags.end());
|
|
|
+ } else if (flag == PlaceholderFlags) {
|
|
|
+ flags.insert(flags.end(), compile_flags.begin(), compile_flags.end());
|
|
|
+ } else if (flag == PlaceholderSource) {
|
|
|
+ flags.emplace_back(FlagClassification::LocationFlag,
|
|
|
+ FlagKind::BuildSystem, sfPath);
|
|
|
+ } else {
|
|
|
+ flags.emplace_back(cls, kind, std::move(flag));
|
|
|
+ // All remaining flags here are build system flags.
|
|
|
+ kind = FlagKind::BuildSystem;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cacheEntry = sourceFlagsCache.emplace_hint(cacheEntry, sf, std::move(flags));
|
|
|
+ return cacheEntry->second;
|
|
|
+}
|
|
|
+
|
|
|
+cmGeneratorTarget::SourceVariables cmGeneratorTarget::GetSourceVariables(
|
|
|
+ cmSourceFile const* sf, std::string const& config)
|
|
|
+{
|
|
|
+ SourceVariables vars;
|
|
|
+ auto const language = sf->GetLanguage();
|
|
|
+ auto const targetType = this->GetType();
|
|
|
+ auto const* const lg = this->GetLocalGenerator();
|
|
|
+ auto const* const gg = this->GetGlobalGenerator();
|
|
|
+ auto const* const mf = this->Makefile;
|
|
|
+
|
|
|
+ // PDB settings.
|
|
|
+ {
|
|
|
+ if (mf->GetDefinition("MSVC_C_ARCHITECTURE_ID") ||
|
|
|
+ mf->GetDefinition("MSVC_CXX_ARCHITECTURE_ID") ||
|
|
|
+ mf->GetDefinition("MSVC_CUDA_ARCHITECTURE_ID")) {
|
|
|
+ std::string pdbPath;
|
|
|
+ std::string compilePdbPath;
|
|
|
+ if (targetType <= cmStateEnums::OBJECT_LIBRARY) {
|
|
|
+ compilePdbPath = this->GetCompilePDBPath(config);
|
|
|
+ if (compilePdbPath.empty()) {
|
|
|
+ // Match VS default: `$(IntDir)vc$(PlatformToolsetVersion).pdb`.
|
|
|
+ // A trailing slash tells the toolchain to add its default file name.
|
|
|
+ compilePdbPath = this->GetSupportDirectory();
|
|
|
+ if (gg->IsMultiConfig()) {
|
|
|
+ compilePdbPath = cmStrCat(compilePdbPath, '/', config);
|
|
|
+ }
|
|
|
+ compilePdbPath += '/';
|
|
|
+ if (targetType == cmStateEnums::STATIC_LIBRARY) {
|
|
|
+ // Match VS default for static libs: `$(IntDir)$(ProjectName).pdb`.
|
|
|
+ compilePdbPath = cmStrCat(compilePdbPath, this->GetName(), ".pdb");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (targetType == cmStateEnums::EXECUTABLE ||
|
|
|
+ targetType == cmStateEnums::STATIC_LIBRARY ||
|
|
|
+ targetType == cmStateEnums::SHARED_LIBRARY ||
|
|
|
+ targetType == cmStateEnums::MODULE_LIBRARY) {
|
|
|
+ pdbPath = cmStrCat(this->GetPDBDirectory(config), '/',
|
|
|
+ this->GetPDBName(config));
|
|
|
+ }
|
|
|
+
|
|
|
+ vars.TargetPDB = lg->ConvertToOutputFormat(
|
|
|
+ gg->ConvertToOutputPath(std::move(pdbPath)), cmOutputConverter::SHELL);
|
|
|
+ vars.TargetCompilePDB = lg->ConvertToOutputFormat(
|
|
|
+ gg->ConvertToOutputPath(std::move(compilePdbPath)),
|
|
|
+ cmOutputConverter::SHELL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Object settings.
|
|
|
+ {
|
|
|
+ std::string const objectDir = gg->ConvertToOutputPath(
|
|
|
+ cmStrCat(this->GetSupportDirectory(), gg->GetConfigDirectory(config)));
|
|
|
+ std::string const objectFileName = this->GetObjectName(sf);
|
|
|
+ std::string const objectFilePath =
|
|
|
+ cmStrCat(objectDir, '/', objectFileName);
|
|
|
+
|
|
|
+ vars.ObjectDir =
|
|
|
+ lg->ConvertToOutputFormat(objectDir, cmOutputConverter::SHELL);
|
|
|
+ vars.ObjectFileDir =
|
|
|
+ lg->ConvertToOutputFormat(objectFilePath, cmOutputConverter::SHELL);
|
|
|
+
|
|
|
+ // Dependency settings.
|
|
|
+ {
|
|
|
+ std::string const depfileFormatName =
|
|
|
+ cmStrCat("CMAKE_", language, "_DEPFILE_FORMAT");
|
|
|
+ std::string const depfileFormat =
|
|
|
+ mf->GetSafeDefinition(depfileFormatName);
|
|
|
+ if (depfileFormat != "msvc"_s) {
|
|
|
+ std::string const flagsName =
|
|
|
+ cmStrCat("CMAKE_DEPFILE_FLAGS_", language);
|
|
|
+ std::string const depfileFlags = mf->GetSafeDefinition(flagsName);
|
|
|
+ if (!depfileFlags.empty()) {
|
|
|
+ bool replaceExt = false;
|
|
|
+ if (!language.empty()) {
|
|
|
+ std::string const repVar =
|
|
|
+ cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE");
|
|
|
+ replaceExt = mf->IsOn(repVar);
|
|
|
+ }
|
|
|
+ std::string const depfilePath = cmStrCat(
|
|
|
+ objectDir, '/',
|
|
|
+ replaceExt
|
|
|
+ ? cmSystemTools::GetFilenameWithoutLastExtension(objectFileName)
|
|
|
+ : objectFileName,
|
|
|
+ ".d");
|
|
|
+
|
|
|
+ vars.DependencyFlags = depfileFlags;
|
|
|
+ vars.DependencyTarget = vars.ObjectFileDir;
|
|
|
+ vars.DependencyFile =
|
|
|
+ lg->ConvertToOutputFormat(depfilePath, cmOutputConverter::SHELL);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return vars;
|
|
|
+}
|
|
|
+
|
|
|
void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
|
|
|
cmSourceFile const& sf) const
|
|
|
{
|
|
|
@@ -5486,6 +5934,31 @@ cmGeneratorTarget::CxxModuleSupport cmGeneratorTarget::NeedCxxDyndep(
|
|
|
return policyAnswer;
|
|
|
}
|
|
|
|
|
|
+std::string cmGeneratorTarget::BuildDatabasePath(
|
|
|
+ std::string const& lang, std::string const& config) const
|
|
|
+{
|
|
|
+ // Check to see if the target wants it.
|
|
|
+ if (!this->GetPropertyAsBool("EXPORT_BUILD_DATABASE")) {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ if (!cmExperimental::HasSupportEnabled(
|
|
|
+ *this->Makefile, cmExperimental::Feature::ExportBuildDatabase)) {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ // Check to see if the generator supports it.
|
|
|
+ if (!this->GetGlobalGenerator()->SupportsBuildDatabase()) {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this->GetGlobalGenerator()->IsMultiConfig()) {
|
|
|
+ return cmStrCat(this->GetSupportDirectory(), '/', config, '/', lang,
|
|
|
+ "_build_database.json");
|
|
|
+ }
|
|
|
+
|
|
|
+ return cmStrCat(this->GetSupportDirectory(), '/', lang,
|
|
|
+ "_build_database.json");
|
|
|
+}
|
|
|
+
|
|
|
void cmGeneratorTarget::BuildFileSetInfoCache(std::string const& config) const
|
|
|
{
|
|
|
auto& per_config = this->Configs[config];
|