mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 13:27:09 +00:00
1 parent
d291927f5d
commit
42fd1fa12d
48 files changed
+370
-111
No files matched your search
@@ -581,6 +581,7 @@ Properties on File Sets
|
||||
/prop_fs/COMPILE_DEFINITIONS
|
||||
/prop_fs/COMPILE_OPTIONS
|
||||
/prop_fs/CXX_SCAN_FOR_MODULES
|
||||
/prop_fs/LANGUAGE
|
||||
/prop_fs/JOB_POOL_COMPILE
|
||||
/prop_fs/INCLUDE_DIRECTORIES
|
||||
/prop_fs/INDEPENDENT_FILES
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
LANGUAGE
|
||||
--------
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
Specify the language used to compile members of a ``SOURCES`` file set.
|
||||
|
||||
This property selects the language whose compiler and compilation rules
|
||||
are used for members of the file set when building a target. It takes
|
||||
precedence over both the :prop_sf:`LANGUAGE` source file property and
|
||||
language selection based on the file extension, without modifying the
|
||||
source file property.
|
||||
|
||||
The selection applies to targets that compile sources from the file set,
|
||||
including targets that inherit those sources through linked target
|
||||
interfaces. This allows the same source file to be compiled using
|
||||
different languages' compilers and compilation rules in different targets.
|
||||
|
||||
The value must be a literal language name. Generator expressions and
|
||||
appending values are not supported. The named language must be enabled by a
|
||||
:command:`project` or :command:`enable_language` command.
|
||||
@@ -1,15 +1,20 @@
|
||||
LANGUAGE
|
||||
--------
|
||||
|
||||
Specify the programming language in which a source file is written.
|
||||
Specify the language used to compile a source file.
|
||||
|
||||
A property that can be set to indicate what programming language the
|
||||
source file is. If it is not set the language is determined based on
|
||||
the file extension. Typical values are ``CXX`` (i.e. C++), ``C``,
|
||||
This property selects the language whose compiler and compilation rules
|
||||
are used for the source file. If it is not set, the language is determined
|
||||
from the file extension. Typical values are ``CXX`` (i.e. C++), ``C``,
|
||||
``CSharp``, ``CUDA``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``. Setting
|
||||
this property for a file means this file will be compiled, unless
|
||||
:prop_sf:`HEADER_FILE_ONLY` is set.
|
||||
|
||||
.. versionadded:: 4.5
|
||||
The :prop_fs:`LANGUAGE` property of a ``SOURCES`` file set takes precedence
|
||||
over this property when compiling a member of that set for a target.
|
||||
This target-specific selection does not modify the source file property.
|
||||
|
||||
.. versionchanged:: 3.20
|
||||
Setting this property causes the source file to be compiled as the
|
||||
specified language, using explicit flags if possible. Previously it
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
file-set-language
|
||||
-----------------
|
||||
|
||||
* The :prop_fs:`LANGUAGE` file set property was added to select the compile
|
||||
language for members of a ``SOURCES`` file set without modifying their
|
||||
:prop_sf:`LANGUAGE` source file property.
|
||||
@@ -447,7 +447,7 @@ cmBuildDatabase cmBuildDatabase::ForTarget(cmGeneratorTarget* gt,
|
||||
|
||||
bool isCXXModule = false;
|
||||
bool isPrivate = true;
|
||||
if (sf->GetLanguage() == "CXX"_s) {
|
||||
if (gt->GetSourceFileLanguage(sf, config) == "CXX"_s) {
|
||||
auto const* fs = gt->GetFileSetForSource(config, sf);
|
||||
if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) {
|
||||
isCXXModule = true;
|
||||
|
||||
@@ -445,7 +445,8 @@ std::string cmCommonTargetGenerator::GenerateCodeCheckRules(
|
||||
std::string const& cmakeCmd, std::string const& config,
|
||||
std::function<std::string(std::string const&)> const& pathConverter)
|
||||
{
|
||||
std::string const lang = source.GetLanguage();
|
||||
std::string const lang =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&source, config);
|
||||
std::string tidy;
|
||||
std::string iwyu;
|
||||
std::string cpplint;
|
||||
@@ -683,11 +684,12 @@ std::string cmCommonTargetGenerator::ConvertLauncherToShell(
|
||||
}
|
||||
|
||||
bool cmCommonTargetGenerator::HaveRequiredLanguages(
|
||||
std::vector<cmSourceFile const*> const& sources,
|
||||
std::vector<cmSourceFile const*> const& sources, std::string const& config,
|
||||
std::set<std::string>& languagesNeeded) const
|
||||
{
|
||||
for (cmSourceFile const* sf : sources) {
|
||||
languagesNeeded.insert(sf->GetLanguage());
|
||||
languagesNeeded.insert(
|
||||
this->GeneratorTarget->GetSourceFileLanguage(sf, config));
|
||||
}
|
||||
|
||||
auto* makefile = this->Makefile;
|
||||
|
||||
@@ -91,6 +91,7 @@ protected:
|
||||
std::vector<std::string> const& launcher) const;
|
||||
|
||||
bool HaveRequiredLanguages(std::vector<cmSourceFile const*> const& sources,
|
||||
std::string const& config,
|
||||
std::set<std::string>& languagesNeeded) const;
|
||||
|
||||
void ComputeRustFlagsForObjects(std::string& linkCrates,
|
||||
|
||||
@@ -199,7 +199,8 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt,
|
||||
}
|
||||
|
||||
auto const* sf = sf_entry.second.first;
|
||||
if (!gt->NeedDyndepForSource(sf->GetLanguage(), config, sf)) {
|
||||
std::string const language = gt->GetSourceFileLanguage(sf, config);
|
||||
if (!gt->NeedDyndepForSource(language, config, sf)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -208,7 +209,7 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt,
|
||||
Json::Value& tdi_source_info = tdi_sources[obj_path] = Json::objectValue;
|
||||
|
||||
tdi_source_info["source"] = full_file;
|
||||
tdi_source_info["language"] = sf->GetLanguage();
|
||||
tdi_source_info["language"] = language;
|
||||
}
|
||||
|
||||
return info;
|
||||
|
||||
@@ -637,6 +637,14 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets(
|
||||
std::string targetName = cmStrCat(this->Namespace, gte->GetExportName());
|
||||
for (auto const& type : types) {
|
||||
auto fsInfo = GetFileSetInformation(type);
|
||||
if (fsInfo &&
|
||||
std::any_of(gfs->GetInterfaceFileSets(type).begin(),
|
||||
gfs->GetInterfaceFileSets(type).end(),
|
||||
[](cmGeneratorFileSet const* fileSet) {
|
||||
return !fileSet->GetProperty("LANGUAGE").IsEmpty();
|
||||
})) {
|
||||
fsInfo->CMakeVersion = "4.5.0"_s;
|
||||
}
|
||||
if (fsInfo) {
|
||||
os << "if(NOT CMAKE_VERSION VERSION_LESS \"" << fsInfo->CMakeVersion
|
||||
<< "\")\n ";
|
||||
|
||||
@@ -152,6 +152,8 @@ bool cmExportFileGenerator::PopulateFileSetInterfaceProperties(
|
||||
properties);
|
||||
this->PopulateFileSetInterfaceProperty("INTERFACE_COMPILE_OPTIONS", target,
|
||||
fileSet, preprocessRule, properties);
|
||||
this->PopulateFileSetInterfaceProperty("LANGUAGE", target, fileSet,
|
||||
preprocessRule, properties);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -344,17 +344,16 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
|
||||
cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* gtgt)
|
||||
{
|
||||
std::string flags;
|
||||
std::string language = source->GetOrDetermineLanguage();
|
||||
std::string const& config =
|
||||
lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
|
||||
std::string language = gtgt->GetSourceFileLanguage(source, config);
|
||||
if (language.empty()) {
|
||||
language = "C";
|
||||
}
|
||||
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
gtgt->AddExplicitLanguageFlags(flags, *source);
|
||||
|
||||
std::string const& config =
|
||||
lg->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE");
|
||||
gtgt->AddExplicitLanguageFlags(flags, *source, config);
|
||||
|
||||
lg->GetTargetCompileFlags(gtgt, config, language, flags);
|
||||
|
||||
|
||||
@@ -145,7 +145,8 @@ cmFastbuildNormalTargetGenerator::cmFastbuildNormalTargetGenerator(
|
||||
std::string cmFastbuildNormalTargetGenerator::DetectCompilerFlags(
|
||||
cmSourceFile const& srcFile, std::string const& arch)
|
||||
{
|
||||
std::string const language = srcFile.GetLanguage();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&srcFile, Config);
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(
|
||||
this->GetLocalGenerator(), Config, this->GeneratorTarget, language);
|
||||
|
||||
@@ -174,7 +175,8 @@ std::string cmFastbuildNormalTargetGenerator::DetectCompilerFlags(
|
||||
|
||||
std::string compileFlags =
|
||||
CompileFlagsByLangAndArch[std::make_pair(language, arch)];
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(compileFlags, srcFile);
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(compileFlags, srcFile,
|
||||
Config);
|
||||
|
||||
if (cmValue const cflags = srcFile.GetProperty(COMPILE_FLAGS)) {
|
||||
this->LocalGenerator->AppendFlags(
|
||||
@@ -450,7 +452,8 @@ void cmFastbuildNormalTargetGenerator::ApplyLWYUToLinkerCommand(
|
||||
std::string cmFastbuildNormalTargetGenerator::ComputeDefines(
|
||||
cmSourceFile const& srcFile)
|
||||
{
|
||||
std::string const language = srcFile.GetLanguage();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&srcFile, Config);
|
||||
std::set<std::string> defines;
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(
|
||||
this->GetLocalGenerator(), Config, this->GeneratorTarget, language);
|
||||
@@ -506,7 +509,8 @@ void cmFastbuildNormalTargetGenerator::ComputePCH(
|
||||
!node.PCHOutputFile.empty()) {
|
||||
return;
|
||||
}
|
||||
std::string const language = srcFile.GetLanguage();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&srcFile, Config);
|
||||
cmGeneratorExpressionInterpreter genexInterpreter(
|
||||
this->GetLocalGenerator(), Config, this->GeneratorTarget, language);
|
||||
|
||||
@@ -1324,7 +1328,8 @@ void cmFastbuildNormalTargetGenerator::AppendExtraResources(
|
||||
std::string cmFastbuildNormalTargetGenerator::GetCompileOptions(
|
||||
cmSourceFile const& srcFile, std::string const& arch)
|
||||
{
|
||||
std::string const language = srcFile.GetLanguage();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&srcFile, Config);
|
||||
cmRulePlaceholderExpander::RuleVariables compileObjectVars =
|
||||
ComputeRuleVariables();
|
||||
std::string const compilerFlags = DetectCompilerFlags(srcFile, arch);
|
||||
@@ -1473,12 +1478,15 @@ void cmFastbuildNormalTargetGenerator::GenerateObjects(FastbuildTarget& target)
|
||||
|
||||
cmSourceFile const& srcFile = *source;
|
||||
std::string const pathToFile = srcFile.GetFullPath();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(&srcFile, Config);
|
||||
cmGeneratorFileSet const* const fileSet =
|
||||
GeneratorTarget->GetFileSetForSource(Config, source);
|
||||
bool fileUsesUnity = useUnity;
|
||||
if (useUnity) {
|
||||
// Check if the source should be added to "UnityInputExcludedFiles".
|
||||
if (IsExcludedFromUnity(GeneratorTarget, fileSet, srcFile)) {
|
||||
if (IsExcludedFromUnity(GeneratorTarget, fileSet, srcFile) ||
|
||||
language != srcFile.GetLanguage()) {
|
||||
fileUsesUnity = false;
|
||||
excludedFromUnity.emplace(pathToFile);
|
||||
}
|
||||
@@ -1493,12 +1501,10 @@ void cmFastbuildNormalTargetGenerator::GenerateObjects(FastbuildTarget& target)
|
||||
ObjectOutDir, '/', this->GeneratorTarget->GetObjectName(source)));
|
||||
|
||||
// Do not generate separate node for PCH source file.
|
||||
if (this->GeneratorTarget->GetPchSource(Config, srcFile.GetLanguage()) ==
|
||||
pathToFile) {
|
||||
if (this->GeneratorTarget->GetPchSource(Config, language) == pathToFile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string const language = srcFile.GetLanguage();
|
||||
LogMessage(
|
||||
cmStrCat("Source file: ", this->ConvertToFastbuildPath(pathToFile)));
|
||||
LogMessage("Language: " + language);
|
||||
@@ -1537,7 +1543,7 @@ void cmFastbuildNormalTargetGenerator::GenerateObjects(FastbuildTarget& target)
|
||||
// If file does not need PCH - it must be in another ObjectList.
|
||||
(fileSet && fileSet->GetProperty("SKIP_PRECOMPILE_HEADERS")) ||
|
||||
srcFile.GetProperty("SKIP_PRECOMPILE_HEADERS"),
|
||||
srcFile.GetLanguage()));
|
||||
language));
|
||||
|
||||
LogMessage("ObjectList Hash: " + objectListHash);
|
||||
|
||||
|
||||
@@ -1497,7 +1497,7 @@ CompileData Target::BuildCompileData(cmSourceFile* sf)
|
||||
{
|
||||
CompileData fd;
|
||||
|
||||
fd.Language = sf->GetOrDetermineLanguage();
|
||||
fd.Language = this->GT->GetSourceFileLanguage(sf, this->Config);
|
||||
if (fd.Language.empty()) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmMakefile.h"
|
||||
@@ -179,6 +180,7 @@ cm::string_view const INTERFACE_COMPILE_DEFINITIONS =
|
||||
cm::string_view const COMPILE_OPTIONS = "COMPILE_OPTIONS"_s;
|
||||
cm::string_view const INTERFACE_COMPILE_OPTIONS =
|
||||
"INTERFACE_COMPILE_OPTIONS"_s;
|
||||
cm::string_view const LANGUAGE = "LANGUAGE"_s;
|
||||
}
|
||||
|
||||
void cmFileSet::SetProperty(std::string const& prop, cmValue value)
|
||||
@@ -265,6 +267,20 @@ void cmFileSet::SetProperty(std::string const& prop, cmValue value)
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == LANGUAGE) {
|
||||
if (this->GetType() != cm::FileSetMetadata::SOURCES) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
"LANGUAGE property may only be set on a SOURCES file set.");
|
||||
return;
|
||||
}
|
||||
if (value && cmGeneratorExpression::Find(*value) != std::string::npos) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
"LANGUAGE file set property does not support generator expressions.");
|
||||
return;
|
||||
}
|
||||
this->Properties.SetProperty(prop, value);
|
||||
} else {
|
||||
this->Properties.SetProperty(prop, value);
|
||||
}
|
||||
@@ -346,6 +362,10 @@ void cmFileSet::AppendProperty(std::string const& prop,
|
||||
cmListFileBacktrace lfbt = this->GetMakefile()->GetBacktrace();
|
||||
this->InterfaceCompileDefinitions.emplace_back(value, lfbt);
|
||||
}
|
||||
} else if (prop == LANGUAGE) {
|
||||
this->Makefile->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
"LANGUAGE file set property does not support appending values.");
|
||||
} else {
|
||||
this->Properties.AppendProperty(prop, value, asString);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "cmLinkItem.h"
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmSourceFile.h"
|
||||
@@ -167,11 +168,35 @@ cmGeneratorFileSets::GetAllFileSetsForSource(std::string const& config,
|
||||
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
std::string const& config, std::string const& file) const
|
||||
{
|
||||
auto const& fileSets = this->GetAllFileSetsForSource(config, file);
|
||||
if (fileSets.empty()) {
|
||||
return nullptr;
|
||||
this->BuildInfoCache(config);
|
||||
auto const& info = this->Configs[config];
|
||||
|
||||
using FileSetCache =
|
||||
std::map<std::string, std::unordered_set<cmGeneratorFileSet const*>>;
|
||||
auto lookup = [&file](FileSetCache const& cache, bool nonHeaderOnly) {
|
||||
auto const entry = cache.find(file);
|
||||
if (entry == cache.end()) {
|
||||
return static_cast<cmGeneratorFileSet const*>(nullptr);
|
||||
}
|
||||
auto const fileSet =
|
||||
std::find_if(entry->second.begin(), entry->second.end(),
|
||||
[nonHeaderOnly](cmGeneratorFileSet const* candidate) {
|
||||
return !nonHeaderOnly ||
|
||||
candidate->GetType() != cm::FileSetMetadata::HEADERS;
|
||||
});
|
||||
return fileSet == entry->second.end() ? nullptr : *fileSet;
|
||||
};
|
||||
|
||||
if (auto const* fileSet = lookup(info.FileSetCache, true)) {
|
||||
return fileSet;
|
||||
}
|
||||
return *fileSets.begin();
|
||||
if (auto const* fileSet = lookup(info.InterfaceFileSetCache, true)) {
|
||||
return fileSet;
|
||||
}
|
||||
if (auto const* fileSet = lookup(info.FileSetCache, false)) {
|
||||
return fileSet;
|
||||
}
|
||||
return lookup(info.InterfaceFileSetCache, false);
|
||||
}
|
||||
cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
std::string const& config, cmSourceFile const* sf) const
|
||||
@@ -179,6 +204,18 @@ cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource(
|
||||
return this->GetFileSetForSource(config, sf->GetFullPath());
|
||||
}
|
||||
|
||||
cm::optional<std::string> cmGeneratorFileSets::GetLanguageForSource(
|
||||
std::string const& config, cmSourceFile const* sf) const
|
||||
{
|
||||
this->BuildInfoCache(config);
|
||||
auto const& languages = this->Configs[config].LanguageCache;
|
||||
auto const language = languages.find(sf->GetFullPath());
|
||||
if (language == languages.end()) {
|
||||
return cm::nullopt;
|
||||
}
|
||||
return language->second;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
||||
cmGeneratorFileSets::GetSources(
|
||||
std::function<bool(cmGeneratorFileSet const*)> include,
|
||||
@@ -377,7 +414,8 @@ std::string cmGeneratorFileSets::EvaluateInterfaceProperty(
|
||||
|
||||
namespace {
|
||||
void GetInterfaceFiles(
|
||||
cmGeneratorTarget const* target, cm::GenEx::Context const& context,
|
||||
cmGeneratorTarget const* target, cmGeneratorTarget const* headTarget,
|
||||
cm::GenEx::Context const& context,
|
||||
std::unordered_set<cmGeneratorTarget const*>& targets,
|
||||
std::map<std::string, std::unordered_set<cmGeneratorFileSet const*>>& cache)
|
||||
{
|
||||
@@ -388,7 +426,7 @@ void GetInterfaceFiles(
|
||||
if (fileSetDescriptor &&
|
||||
fileSetDescriptor->Lookup == Metadata::FileSetLookup::Dependencies) {
|
||||
for (auto const* fileSet : target->GetInterfaceFileSets(type)) {
|
||||
auto files = fileSet->GetFiles(context, target);
|
||||
auto files = fileSet->GetFiles(context, headTarget);
|
||||
|
||||
for (auto const& it : files.first) {
|
||||
for (auto const& filename : it.second) {
|
||||
@@ -401,12 +439,12 @@ void GetInterfaceFiles(
|
||||
}
|
||||
|
||||
if (cmLinkInterfaceLibraries const* iface =
|
||||
target->GetLinkInterfaceLibraries(context.Config, target,
|
||||
target->GetLinkInterfaceLibraries(context.Config, headTarget,
|
||||
cmGeneratorTarget::UseTo::Compile)) {
|
||||
for (cmLinkItem const& lib : iface->Libraries) {
|
||||
if (lib.Target && lib.Target != target &&
|
||||
targets.insert(lib.Target).second) {
|
||||
GetInterfaceFiles(lib.Target, context, targets, cache);
|
||||
GetInterfaceFiles(lib.Target, headTarget, context, targets, cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,6 +463,9 @@ void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
|
||||
|
||||
for (auto const& item : this->FileSets) {
|
||||
auto const* fileSet = item.second.get();
|
||||
if (!fileSet->IsForSelf()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto files = fileSet->GetFiles(context, this->Target);
|
||||
|
||||
@@ -443,12 +484,41 @@ void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const
|
||||
this->Target->GetLinkImplementationLibraries(
|
||||
config, cmGeneratorTarget::UseTo::Compile)) {
|
||||
for (cmLinkItem const& lib : impl->Libraries) {
|
||||
if (lib.Target) {
|
||||
GetInterfaceFiles(lib.Target, context, targets,
|
||||
if (lib.Target && targets.insert(lib.Target).second) {
|
||||
GetInterfaceFiles(lib.Target, this->Target, context, targets,
|
||||
info.InterfaceFileSetCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto indexLanguages =
|
||||
[this,
|
||||
&info](std::map<std::string,
|
||||
std::unordered_set<cmGeneratorFileSet const*>> const&
|
||||
fileSets) {
|
||||
for (auto const& file : fileSets) {
|
||||
for (auto const* fileSet : file.second) {
|
||||
if (fileSet->GetType() != cm::FileSetMetadata::SOURCES) {
|
||||
continue;
|
||||
}
|
||||
cmValue const language = fileSet->GetProperty("LANGUAGE");
|
||||
if (language.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
auto const inserted =
|
||||
info.LanguageCache.emplace(file.first, *language);
|
||||
if (!inserted.second && inserted.first->second != *language) {
|
||||
this->LocalGenerator->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("Source file\n ", file.first,
|
||||
"\nbelongs to multiple SOURCES file sets with "
|
||||
"conflicting LANGUAGE properties."));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
indexLanguages(info.FileSetCache);
|
||||
indexLanguages(info.InterfaceFileSetCache);
|
||||
|
||||
info.BuiltCache = true;
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <cm/optional>
|
||||
#include <cm/string_view>
|
||||
|
||||
#include "cmFileSetMetadata.h"
|
||||
@@ -65,6 +66,8 @@ public:
|
||||
std::string const& file) const;
|
||||
cmGeneratorFileSet const* GetFileSetForSource(std::string const& config,
|
||||
cmSourceFile const* sf) const;
|
||||
cm::optional<std::string> GetLanguageForSource(std::string const& config,
|
||||
cmSourceFile const* sf) const;
|
||||
|
||||
std::vector<std::unique_ptr<TargetPropertyEntry>> GetSources(
|
||||
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
||||
@@ -118,6 +121,7 @@ private:
|
||||
FileSetCache;
|
||||
std::map<std::string, std::unordered_set<cmGeneratorFileSet const*>>
|
||||
InterfaceFileSetCache;
|
||||
std::unordered_map<std::string, std::string> LanguageCache;
|
||||
};
|
||||
mutable std::map<std::string, InfoByConfig> Configs;
|
||||
|
||||
|
||||
@@ -2171,7 +2171,7 @@ cmGeneratorTarget::GetClassifiedFlagsForSource(cmSourceFile const* sf,
|
||||
}
|
||||
|
||||
ClassifiedFlags flags;
|
||||
std::string const& lang = sf->GetLanguage();
|
||||
std::string const lang = this->GetSourceFileLanguage(sf, config);
|
||||
|
||||
if (!IsSupportedClassifiedFlagsLanguage(lang)) {
|
||||
return flags;
|
||||
@@ -2213,7 +2213,7 @@ cmGeneratorTarget::GetClassifiedFlagsForSource(cmSourceFile const* sf,
|
||||
std::string mfFlags;
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
this->AddExplicitLanguageFlags(mfFlags, *sf);
|
||||
this->AddExplicitLanguageFlags(mfFlags, *sf, config);
|
||||
|
||||
for (auto const& flag : SplitFlags(mfFlags)) {
|
||||
flags.emplace_back(cls, kind, flag);
|
||||
@@ -2560,7 +2560,7 @@ cmGeneratorTarget::SourceVariables cmGeneratorTarget::GetSourceVariables(
|
||||
cmSourceFile const* sf, std::string const& config)
|
||||
{
|
||||
SourceVariables vars;
|
||||
auto const language = sf->GetLanguage();
|
||||
auto const language = this->GetSourceFileLanguage(sf, config);
|
||||
auto const targetType = this->GetType();
|
||||
auto const* const lg = this->GetLocalGenerator();
|
||||
auto const* const gg = this->GetGlobalGenerator();
|
||||
@@ -2659,9 +2659,16 @@ cmGeneratorTarget::SourceVariables cmGeneratorTarget::GetSourceVariables(
|
||||
return vars;
|
||||
}
|
||||
|
||||
void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags,
|
||||
cmSourceFile const& sf) const
|
||||
void cmGeneratorTarget::AddExplicitLanguageFlags(
|
||||
std::string& flags, cmSourceFile const& sf, std::string const& config) const
|
||||
{
|
||||
if (auto const language =
|
||||
this->FileSets->GetLanguageForSource(config, &sf)) {
|
||||
this->LocalGenerator->AppendFeatureOptions(flags, *language,
|
||||
"EXPLICIT_LANGUAGE");
|
||||
return;
|
||||
}
|
||||
|
||||
cmValue lang = sf.GetProperty("LANGUAGE");
|
||||
if (!lang) {
|
||||
return;
|
||||
@@ -5269,7 +5276,7 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
|
||||
std::vector<cmSourceFile*> sourceFiles;
|
||||
this->GetSourceFiles(sourceFiles, config);
|
||||
for (cmSourceFile* src : sourceFiles) {
|
||||
std::string const& lang = src->GetOrDetermineLanguage();
|
||||
std::string const lang = this->GetSourceFileLanguage(src, config);
|
||||
if (!lang.empty()) {
|
||||
languages.insert(lang);
|
||||
}
|
||||
@@ -5998,8 +6005,9 @@ bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const
|
||||
{
|
||||
auto sources = this->GetSourceFiles(config);
|
||||
bool const have_direct = std::any_of(
|
||||
sources.begin(), sources.end(), [](BT<cmSourceFile*> const& sf) -> bool {
|
||||
return sf.Value->GetLanguage() == "Fortran"_s;
|
||||
sources.begin(), sources.end(),
|
||||
[this, &config](BT<cmSourceFile*> const& sf) -> bool {
|
||||
return this->GetSourceFileLanguage(sf.Value, config) == "Fortran"_s;
|
||||
});
|
||||
bool have_via_target_objects = false;
|
||||
if (!have_direct) {
|
||||
@@ -6015,11 +6023,8 @@ bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const
|
||||
|
||||
bool cmGeneratorTarget::HaveFortranSources() const
|
||||
{
|
||||
auto sources = this->GetAllConfigSources();
|
||||
bool const have_direct = std::any_of(
|
||||
sources.begin(), sources.end(), [](AllConfigSource const& sf) -> bool {
|
||||
return sf.Source->GetLanguage() == "Fortran"_s;
|
||||
});
|
||||
bool const have_direct =
|
||||
this->GetAllConfigCompileLanguages().count("Fortran") != 0;
|
||||
bool have_via_target_objects = false;
|
||||
if (!have_direct) {
|
||||
std::vector<std::string> configs =
|
||||
@@ -6096,7 +6101,7 @@ void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const
|
||||
auto sources = this->GetSourceFiles(config);
|
||||
for (auto const& source : sources) {
|
||||
auto const* sf = source.Value;
|
||||
auto const& lang = sf->GetLanguage();
|
||||
auto const lang = this->GetSourceFileLanguage(sf, config);
|
||||
if (lang != "CXX"_s) {
|
||||
continue;
|
||||
}
|
||||
@@ -6303,6 +6308,16 @@ cmGeneratorFileSet const* cmGeneratorTarget::GetFileSetForSource(
|
||||
return this->FileSets->GetFileSetForSource(config, sf);
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetSourceFileLanguage(
|
||||
cmSourceFile const* source, std::string const& config) const
|
||||
{
|
||||
if (auto const language =
|
||||
this->FileSets->GetLanguageForSource(config, source)) {
|
||||
return *language;
|
||||
}
|
||||
return source->GetLanguage();
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::BuildDatabasePath(
|
||||
std::string const& lang, std::string const& config) const
|
||||
{
|
||||
|
||||
@@ -136,6 +136,8 @@ public:
|
||||
std::string const& config) const;
|
||||
std::vector<BT<cmSourceFile*>> GetSourceFiles(
|
||||
std::string const& config) const;
|
||||
std::string GetSourceFileLanguage(cmSourceFile const* source,
|
||||
std::string const& config) const;
|
||||
|
||||
/** Source file kinds (classifications).
|
||||
Generators use this to decide how to treat a source file. */
|
||||
@@ -611,8 +613,8 @@ public:
|
||||
SourceVariables GetSourceVariables(cmSourceFile const* sf,
|
||||
std::string const& config);
|
||||
|
||||
void AddExplicitLanguageFlags(std::string& flags,
|
||||
cmSourceFile const& sf) const;
|
||||
void AddExplicitLanguageFlags(std::string& flags, cmSourceFile const& sf,
|
||||
std::string const& config) const;
|
||||
|
||||
void AddCUDAArchitectureFlags(cmBuildStep compileOrLink,
|
||||
std::string const& config,
|
||||
|
||||
@@ -345,8 +345,7 @@ cm::optional<std::string> cmGeneratorTarget::ResolveHeaderLanguage(
|
||||
*/
|
||||
if (!defaultLanguage) {
|
||||
std::set<std::string> langs;
|
||||
for (AllConfigSource const& tgtSource : this->GetAllConfigSources()) {
|
||||
std::string const& lang = tgtSource.Source->GetOrDetermineLanguage();
|
||||
for (std::string const& lang : this->GetAllConfigCompileLanguages()) {
|
||||
if (isSupported(lang)) {
|
||||
langs.insert(lang);
|
||||
}
|
||||
|
||||
@@ -422,6 +422,8 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
|
||||
SourceKind kind;
|
||||
std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
|
||||
cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf);
|
||||
sf->GetOrDetermineLanguage();
|
||||
std::string const language = this->GetSourceFileLanguage(sf, config);
|
||||
if (sf->GetCustomCommand()) {
|
||||
kind = SourceKindCustomCommand;
|
||||
} else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
|
||||
@@ -443,8 +445,8 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
|
||||
kind = SourceKindHeader;
|
||||
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
|
||||
kind = SourceKindExternalObject;
|
||||
} else if (!sf->GetOrDetermineLanguage().empty()) {
|
||||
if (sf->GetOrDetermineLanguage() == "Rust") {
|
||||
} else if (!language.empty()) {
|
||||
if (language == "Rust") {
|
||||
// NOLINTNEXTLINE(bugprone-branch-clone)
|
||||
if (this->Target->GetType() == cm::TargetType::OBJECT_LIBRARY) {
|
||||
// There is no main crate root for object libraries.
|
||||
@@ -562,11 +564,16 @@ cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
|
||||
void cmGeneratorTarget::ComputeAllConfigCompileLanguages() const
|
||||
{
|
||||
std::set<std::string> languages;
|
||||
std::vector<std::string> const configs =
|
||||
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
|
||||
std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
|
||||
for (AllConfigSource const& si : sources) {
|
||||
std::string const& lang = si.Source->GetOrDetermineLanguage();
|
||||
if (!lang.empty()) {
|
||||
languages.emplace(lang);
|
||||
for (size_t const configIndex : si.Configs) {
|
||||
std::string const lang =
|
||||
this->GetSourceFileLanguage(si.Source, configs[configIndex]);
|
||||
if (!lang.empty()) {
|
||||
languages.emplace(lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->AllConfigCompileLanguages = languages;
|
||||
|
||||
@@ -1094,7 +1094,10 @@ private:
|
||||
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
|
||||
{
|
||||
std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
|
||||
// Sources are independent of the config but a config is needed to evaluate
|
||||
// file set properties.
|
||||
auto const& config = this->CurrentConfigurationTypes[0];
|
||||
std::string lang = gtgt->GetSourceFileLanguage(sf, config);
|
||||
|
||||
XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt, lang);
|
||||
|
||||
@@ -1113,14 +1116,12 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
|
||||
}
|
||||
|
||||
// lookup for the associated file set, if any.
|
||||
//// sources are independent of the config but needed here
|
||||
auto const& config = this->CurrentConfigurationTypes[0];
|
||||
auto const* fileSet =
|
||||
gtgt->GetGeneratorFileSets()->GetFileSetForSource(config, sf);
|
||||
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
gtgt->AddExplicitLanguageFlags(flags, *sf);
|
||||
gtgt->AddExplicitLanguageFlags(flags, *sf, config);
|
||||
|
||||
std::string const COMPILE_FLAGS("COMPILE_FLAGS");
|
||||
if (cmValue cflags = sf->GetProperty(COMPILE_FLAGS)) {
|
||||
|
||||
@@ -2800,7 +2800,7 @@ void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
|
||||
// generating
|
||||
for (cmSourceFile const* sf : sources) {
|
||||
// Generate this object file's rule file.
|
||||
std::string const& lang = sf->GetLanguage();
|
||||
std::string const lang = target->GetSourceFileLanguage(sf, config);
|
||||
if (lang == "ISPC") {
|
||||
std::string const& objectName = target->GetObjectName(sf);
|
||||
|
||||
@@ -2856,7 +2856,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
|
||||
sources.begin(), sources.end(),
|
||||
[&target, &config, &lang](cmSourceFile* sf) {
|
||||
auto const* const fileSet = target->GetFileSetForSource(config, sf);
|
||||
return lang == sf->GetLanguage() &&
|
||||
return lang == target->GetSourceFileLanguage(sf, config) &&
|
||||
!((fileSet && fileSet->GetProperty("SKIP_PRECOMPILE_HEADERS")) ||
|
||||
sf->GetProperty("SKIP_PRECOMPILE_HEADERS"));
|
||||
});
|
||||
@@ -2891,7 +2891,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target)
|
||||
if (pchSource.empty() || pchHeader.empty()) {
|
||||
if (this->GetGlobalGenerator()->IsXcode() && !pchLangSet.empty()) {
|
||||
for (auto* sf : sources) {
|
||||
auto const sourceLanguage = sf->GetLanguage();
|
||||
auto const sourceLanguage =
|
||||
target->GetSourceFileLanguage(sf, config);
|
||||
if (!sourceLanguage.empty() &&
|
||||
pchLangSet.find(sourceLanguage) == pchLangSet.end()) {
|
||||
sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON");
|
||||
@@ -3411,6 +3412,10 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
.contains(cm::FileSetMetadata::FileSetAttributes::UnityBuild)) {
|
||||
continue;
|
||||
}
|
||||
if (target->GetSourceFileLanguage(sf, configs[ci]) !=
|
||||
sf->GetOrDetermineLanguage()) {
|
||||
continue;
|
||||
}
|
||||
// Files which need C++ scanning cannot participate in unity builds as
|
||||
// there is a single place in TUs that may perform module-dependency bits
|
||||
// and a unity source cannot `#include` them in-order and represent a
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "cmRange.h"
|
||||
#include "cmRulePlaceholderExpander.h"
|
||||
#include "cmScriptGenerator.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmState.h"
|
||||
#include "cmStateSnapshot.h"
|
||||
#include "cmStdIoStream.h"
|
||||
@@ -248,7 +247,8 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
|
||||
}
|
||||
LocalObjectInfo& info = localObjectFiles[objectName];
|
||||
info.HasSourceExtension = hasSourceExtension;
|
||||
info.emplace_back(gt.get(), sf->GetLanguage());
|
||||
info.emplace_back(gt.get(),
|
||||
gt->GetSourceFileLanguage(sf, this->GetConfigName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +353,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
|
||||
|
||||
// validate that all languages requested are enabled.
|
||||
std::set<std::string> requiredLangs;
|
||||
if (this->HaveRequiredLanguages(objectSources, requiredLangs)) {
|
||||
if (this->HaveRequiredLanguages(objectSources, this->GetConfigName(),
|
||||
requiredLangs)) {
|
||||
for (cmSourceFile const* sf : objectSources) {
|
||||
// Generate this object file's rule file.
|
||||
this->WriteObjectRuleFiles(*sf);
|
||||
@@ -601,7 +602,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
cmSourceFile const& source)
|
||||
{
|
||||
// Identify the language of the source file.
|
||||
std::string const& lang = source.GetLanguage();
|
||||
std::string const lang = this->GeneratorTarget->GetSourceFileLanguage(
|
||||
&source, this->GetConfigName());
|
||||
if (lang.empty()) {
|
||||
// don't know anything about this file so skip it
|
||||
return;
|
||||
@@ -719,7 +721,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(flags, source);
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(flags, source, config);
|
||||
|
||||
// Add language-specific flags.
|
||||
std::string const langFlags =
|
||||
|
||||
@@ -163,7 +163,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules(
|
||||
std::set<std::string> languages;
|
||||
std::vector<cmSourceFile const*> sourceFiles;
|
||||
this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
|
||||
if (this->HaveRequiredLanguages(sourceFiles, languages)) {
|
||||
if (this->HaveRequiredLanguages(sourceFiles, config, languages)) {
|
||||
for (std::string const& language : languages) {
|
||||
this->WriteLanguageRules(language, config);
|
||||
}
|
||||
@@ -175,7 +175,7 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules(
|
||||
std::set<std::string> languages;
|
||||
std::vector<cmSourceFile const*> sourceFiles;
|
||||
this->GetGeneratorTarget()->GetCxxModuleSources(sourceFiles, config);
|
||||
if (this->HaveRequiredLanguages(sourceFiles, languages)) {
|
||||
if (this->HaveRequiredLanguages(sourceFiles, config, languages)) {
|
||||
for (std::string const& language : languages) {
|
||||
this->WriteLanguageRules(language, config);
|
||||
}
|
||||
@@ -1255,7 +1255,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
|
||||
this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
|
||||
cmLocalGenerator const* LocalGen = this->GetLocalGenerator();
|
||||
for (auto const& source : sourceFiles) {
|
||||
std::string const sourcePath = source->GetLanguage() == "Swift"
|
||||
std::string const sourcePath =
|
||||
this->GetGeneratorTarget()->GetSourceFileLanguage(source, config) ==
|
||||
"Swift"
|
||||
? this->GetCompiledSourceNinjaPath(source)
|
||||
: this->GetObjectFilePath(source, config);
|
||||
result = cmStrCat(std::move(result), ' ',
|
||||
@@ -1277,7 +1279,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
|
||||
std::vector<cmSourceFile const*> sources;
|
||||
gt->GetObjectSources(sources, config);
|
||||
for (auto const& source : sources) {
|
||||
if (source->GetLanguage() == "Swift") {
|
||||
if (gt->GetSourceFileLanguage(source, config) == "Swift") {
|
||||
linkBuild.Outputs.push_back(
|
||||
this->ConvertToNinjaPath(this->GetObjectFilePath(source, config)));
|
||||
linkBuild.ExplicitDeps.emplace_back(
|
||||
|
||||
@@ -210,7 +210,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
|
||||
std::string flags;
|
||||
// Explicitly add the explicit language flag before any other flag
|
||||
// so user flags can override it.
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(flags, *source);
|
||||
this->GeneratorTarget->AddExplicitLanguageFlags(flags, *source, config);
|
||||
|
||||
if (!flags.empty()) {
|
||||
flags += " ";
|
||||
@@ -1251,7 +1251,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
std::vector<cmSourceFile const*> swiftSources;
|
||||
for (cmSourceFile const* sf : objectSources) {
|
||||
if (this->GetLocalGenerator()->IsSplitSwiftBuild() &&
|
||||
sf->GetLanguage() == "Swift") {
|
||||
this->GeneratorTarget->GetSourceFileLanguage(sf, config) ==
|
||||
"Swift") {
|
||||
swiftSources.push_back(sf);
|
||||
} else {
|
||||
this->WriteObjectBuildStatement(sf, config, fileConfig,
|
||||
@@ -1525,7 +1526,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
cmSourceFile const* source, std::string const& config,
|
||||
std::string const& fileConfig, bool firstForConfig)
|
||||
{
|
||||
std::string const language = source->GetLanguage();
|
||||
std::string const language =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(source, config);
|
||||
std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source);
|
||||
std::string const targetSupportDir =
|
||||
this->ConvertToNinjaPath(this->GeneratorTarget->GetCMFSupportDirectory());
|
||||
|
||||
@@ -2866,21 +2866,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
cm::string_view const extLang = ext == "C"_s
|
||||
? "C"_s
|
||||
: this->GlobalGenerator->GetLanguageFromExtension(ext);
|
||||
std::string lang = this->LocalGenerator->GetSourceFileLanguage(sf);
|
||||
char const* compileAs = nullptr;
|
||||
if (lang != extLang) {
|
||||
if (lang == "CXX"_s) {
|
||||
// force a C++ file type
|
||||
compileAs = "CompileAsCpp";
|
||||
} else if (lang == "C"_s) {
|
||||
// force to c
|
||||
compileAs = "CompileAsC";
|
||||
}
|
||||
}
|
||||
|
||||
bool noWinRT = this->TargetCompileAsWinRT && lang == "C"_s;
|
||||
|
||||
if (lang == "ASM_NASM"_s) {
|
||||
if (this->LocalGenerator->GetSourceFileLanguage(sf) == "ASM_NASM"_s) {
|
||||
if (cmValue objectDeps = sf.GetProperty("OBJECT_DEPENDS")) {
|
||||
cmList depends{ *objectDeps };
|
||||
for (auto& d : depends) {
|
||||
@@ -2893,6 +2879,20 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
bool isCppModule = false;
|
||||
|
||||
for (std::string const& config : this->Configurations) {
|
||||
std::string const lang =
|
||||
this->GeneratorTarget->GetSourceFileLanguage(source, config);
|
||||
char const* compileAs = nullptr;
|
||||
if (lang != extLang) {
|
||||
if (lang == "CXX"_s) {
|
||||
// force a C++ file type
|
||||
compileAs = "CompileAsCpp";
|
||||
} else if (lang == "C"_s) {
|
||||
// force to c
|
||||
compileAs = "CompileAsC";
|
||||
}
|
||||
}
|
||||
bool noWinRT = this->TargetCompileAsWinRT && lang == "C"_s;
|
||||
|
||||
this->GeneratorTarget->NeedCxxModuleSupport(lang, config);
|
||||
|
||||
std::string configUpper = cmSystemTools::UpperCase(config);
|
||||
@@ -2990,7 +2990,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
|
||||
this->ScanSourceForModuleDependencies[config])) {
|
||||
cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
|
||||
cmIDEFlagTable const* flagtable = nullptr;
|
||||
std::string const& srclang = source->GetLanguage();
|
||||
std::string const& srclang = lang;
|
||||
if (srclang == "C"_s || srclang == "CXX"_s) {
|
||||
flagtable = gg->GetClFlagTable();
|
||||
} else if (srclang == "ASM_MARMASM"_s &&
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/export.cmake" content)
|
||||
if(NOT content MATCHES [[VERSION_LESS "4\.5\.0"]])
|
||||
set(RunCMake_TEST_FAILED "Export does not require CMake 4.5")
|
||||
endif()
|
||||
if(NOT content MATCHES [[PROPERTY LANGUAGE "CXX"]])
|
||||
set(RunCMake_TEST_FAILED "Export does not preserve LANGUAGE CXX")
|
||||
endif()
|
||||
@@ -1,15 +1,18 @@
|
||||
enable_language(C)
|
||||
enable_language(C CXX)
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PRIVATE lib1.c)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY LANGUAGE CXX)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS
|
||||
LIB1_A EXPECT_CXX "$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_OPTIONS -DOPT_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir1>"
|
||||
"$<INSTALL_INTERFACE:include/subdir1>")
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS
|
||||
INTERFACE_LIB1_A EXPECT_CXX "$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_OPTIONS -DOPT_INTERFACE_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/subdir2>"
|
||||
"$<INSTALL_INTERFACE:include/subdir2>")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
enable_language(C)
|
||||
enable_language(C CXX)
|
||||
|
||||
get_property(multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
@@ -21,17 +21,15 @@ endfunction()
|
||||
cmake_path(GET CMAKE_BINARY_DIR PARENT_PATH export_build_dir)
|
||||
cmake_path(APPEND export_build_dir "FileSetExport-build")
|
||||
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_EQUAL 4.3
|
||||
AND NOT CMAKE_PATCH_VERSION VERSION_LESS 20000000)
|
||||
# development version for future 4.4: Force version 4.4
|
||||
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_EQUAL 4.4
|
||||
AND NOT CMAKE_PATCH_VERSION VERSION_LESS 20000000)
|
||||
# development version for future 4.5: Force version 4.5
|
||||
set(CMAKE_VERSION_BACKUP "${CMAKE_VERSION}")
|
||||
set(CMAKE_VERSION 4.4)
|
||||
set(CMAKE_VERSION 4.5)
|
||||
endif()
|
||||
include("${export_build_dir}/export.cmake")
|
||||
include("${export_build_dir}/install/lib/cmake/export.cmake")
|
||||
if(CMAKE_VERSION VERSION_GREATER 4.3 AND CMAKE_VERSION VERSION_LESS 4.4
|
||||
AND NOT CMake_VERSION_PATCH VERSION_LESS 20000000)
|
||||
# development version for future 4.4: Force version 4.4
|
||||
if(DEFINED CMAKE_VERSION_BACKUP)
|
||||
set(CMAKE_VERSION "${CMAKE_VERSION_BACKUP}")
|
||||
endif()
|
||||
|
||||
@@ -42,7 +40,9 @@ assert_target_prop_eq(export::lib1 SOURCE_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/lib
|
||||
assert_target_prop_eq(export::lib1 SOURCE_SET "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
|
||||
assert_target_prop_eq(export::lib1 SOURCE_SET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/lib5.c")
|
||||
|
||||
assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
|
||||
assert_fileset_prop_eq(export::lib1 a LANGUAGE "CXX")
|
||||
assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_DEFINITIONS
|
||||
"INTERFACE_LIB1_A;EXPECT_CXX;$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
assert_fileset_prop_eq(export::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
|
||||
assert_fileset_prop_eq(export::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
|
||||
|
||||
@@ -67,7 +67,9 @@ else()
|
||||
assert_target_prop_eq(install::lib1 SOURCE_SET_SOURCES "${export_build_dir}/install/sources/debug/lib5.c")
|
||||
endif()
|
||||
|
||||
assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_DEFINITIONS "INTERFACE_LIB1_A")
|
||||
assert_fileset_prop_eq(install::lib1 a LANGUAGE "CXX")
|
||||
assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_DEFINITIONS
|
||||
"INTERFACE_LIB1_A;EXPECT_CXX;$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
assert_fileset_prop_eq(install::lib1 a INTERFACE_COMPILE_OPTIONS "-DOPT_INTERFACE_LIB1_A")
|
||||
assert_fileset_prop_eq(install::lib1 a INTERFACE_INCLUDE_DIRECTORIES "${export_build_dir}/install/include/subdir2")
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
enable_language(C)
|
||||
enable_language(C CXX)
|
||||
|
||||
add_library(lib1 STATIC)
|
||||
target_sources(lib1 PRIVATE lib1.c)
|
||||
target_sources(lib1 PUBLIC FILE_SET a TYPE SOURCES FILES lib2.c)
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS LIB1_A)
|
||||
set_source_files_properties(lib2.c PROPERTIES LANGUAGE C)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY LANGUAGE CXX)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY COMPILE_DEFINITIONS
|
||||
LIB1_A EXPECT_CXX "$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir1")
|
||||
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS INTERFACE_LIB1_A)
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_COMPILE_DEFINITIONS
|
||||
INTERFACE_LIB1_A EXPECT_CXX "$<$<COMPILE_LANGUAGE:CXX>:EXPECTED_LANGUAGE>")
|
||||
set_property(FILE_SET a TARGET lib1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/subdir2")
|
||||
|
||||
add_executable(main main.c)
|
||||
|
||||
@@ -19,6 +19,19 @@
|
||||
# include "h1.h"
|
||||
#endif
|
||||
|
||||
void f2(void)
|
||||
#if defined(EXPECT_CXX)
|
||||
# if !defined(__cplusplus)
|
||||
# error "Expected this source to be compiled as C++"
|
||||
# endif
|
||||
# if !defined(EXPECTED_LANGUAGE)
|
||||
# error "COMPILE_LANGUAGE did not use the file set language"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
void
|
||||
f2(void)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
/* empty */
|
||||
@@ -0,0 +1 @@
|
||||
/* empty */
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at LANGUAGE-Append\.cmake:[0-9]+ \(set_property\):
|
||||
LANGUAGE file set property does not support appending values\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,3 @@
|
||||
add_library(foo STATIC foo.c)
|
||||
target_sources(foo PRIVATE FILE_SET sources TYPE SOURCES)
|
||||
set_property(FILE_SET sources TARGET foo APPEND PROPERTY LANGUAGE CXX)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at LANGUAGE-Genex\.cmake:[0-9]+ \(set_property\):
|
||||
LANGUAGE file set property does not support generator expressions\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,3 @@
|
||||
add_library(foo STATIC foo.c)
|
||||
target_sources(foo PRIVATE FILE_SET sources TYPE SOURCES)
|
||||
set_property(FILE_SET sources TARGET foo PROPERTY LANGUAGE "$<1:CXX>")
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at LANGUAGE-Headers\.cmake:[0-9]+ \(set_property\):
|
||||
LANGUAGE property may only be set on a SOURCES file set\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,3 @@
|
||||
add_library(foo INTERFACE)
|
||||
target_sources(foo INTERFACE FILE_SET HEADERS)
|
||||
set_property(FILE_SET HEADERS TARGET foo PROPERTY LANGUAGE CXX)
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
^CMake Error at LANGUAGE-WrongType\.cmake:[0-9]+ \(set_property\):
|
||||
LANGUAGE property may only be set on a SOURCES file set\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,3 @@
|
||||
add_library(foo STATIC foo.c)
|
||||
target_sources(foo PRIVATE FILE_SET modules TYPE CXX_MODULES)
|
||||
set_property(FILE_SET modules TARGET foo PROPERTY LANGUAGE CXX)
|
||||
@@ -0,0 +1,8 @@
|
||||
add_library(foo STATIC)
|
||||
target_sources(foo PRIVATE FILE_SET sources TYPE SOURCES FILES foo.c)
|
||||
set_property(FILE_SET sources TARGET foo PROPERTY LANGUAGE CXX)
|
||||
|
||||
get_property(language FILE_SET sources TARGET foo PROPERTY LANGUAGE)
|
||||
if(NOT language STREQUAL "CXX")
|
||||
message(SEND_ERROR "wrong language: '${language}' instead of 'CXX'")
|
||||
endif()
|
||||
@@ -6,3 +6,10 @@ run_cmake(TYPE)
|
||||
run_cmake(SCOPE)
|
||||
run_cmake(SOURCES)
|
||||
run_cmake(BASE_DIRS)
|
||||
|
||||
run_cmake(LANGUAGE)
|
||||
|
||||
run_cmake(LANGUAGE-Append)
|
||||
run_cmake(LANGUAGE-Genex)
|
||||
run_cmake(LANGUAGE-Headers)
|
||||
run_cmake(LANGUAGE-WrongType)
|
||||
Reference in new issue
Block a user