Refactor per-source generator expression evaluation

Prepare to add generator expression support to more source properties.
Factor out some duplicated code into a helper to avoid further
duplication.
This commit is contained in:
Marc Chevrier 2017-12-01 17:10:45 +01:00 committed by Brad King
parent a4faf86387
commit 6bffc13ef1
8 changed files with 114 additions and 50 deletions

View File

@ -362,9 +362,8 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
// Add source file specific flags.
if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
const char* processed = ge.Parse(cflags)->Evaluate(lg, config);
lg->AppendFlags(flags, processed);
cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config);
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags));
}
return flags;

View File

@ -153,4 +153,54 @@ private:
bool EvaluateForBuildsystem;
};
class cmGeneratorExpressionInterpreter
{
CM_DISABLE_COPY(cmGeneratorExpressionInterpreter)
public:
cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
cmGeneratorTarget* generatorTarget,
const std::string& config)
: LocalGenerator(localGenerator)
, GeneratorTarget(generatorTarget)
, Config(config)
{
}
const char* Evaluate(const char* expression)
{
this->CompiledGeneratorExpression =
this->GeneratorExpression.Parse(expression);
return this->CompiledGeneratorExpression->Evaluate(
this->LocalGenerator, this->Config, false, this->GeneratorTarget);
}
const char* Evaluate(const std::string& expression)
{
return this->Evaluate(expression.c_str());
}
protected:
cmGeneratorExpression& GetGeneratorExpression()
{
return this->GeneratorExpression;
}
cmCompiledGeneratorExpression& GetCompiledGeneratorExpression()
{
return *(this->CompiledGeneratorExpression);
}
cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; }
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
private:
cmGeneratorExpression GeneratorExpression;
std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
cmLocalGenerator* LocalGenerator = nullptr;
cmGeneratorTarget* GeneratorTarget = nullptr;
std::string Config;
};
#endif

View File

@ -676,9 +676,51 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
return buildFile;
}
class XCodeGeneratorExpressionInterpreter
: public cmGeneratorExpressionInterpreter
{
CM_DISABLE_COPY(XCodeGeneratorExpressionInterpreter)
public:
XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
cmLocalGenerator* localGenerator,
cmGeneratorTarget* generatorTarget)
: cmGeneratorExpressionInterpreter(localGenerator, generatorTarget,
"NO-PER-CONFIG-SUPPORT-IN-XCODE")
, SourceFile(sourceFile)
{
}
using cmGeneratorExpressionInterpreter::Evaluate;
const char* Evaluate(const char* expression, const char* property)
{
const char* processed = this->Evaluate(expression);
if (this->GetCompiledGeneratorExpression()
.GetHadContextSensitiveCondition()) {
std::ostringstream e;
/* clang-format off */
e <<
"Xcode does not support per-config per-source " << property << ":\n"
" " << expression << "\n"
"specified for source:\n"
" " << this->SourceFile->GetFullPath() << "\n";
/* clang-format on */
this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
}
return processed;
}
private:
cmSourceFile* SourceFile = nullptr;
};
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
{
XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt);
// Add flags from target and source file properties.
std::string flags;
const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
@ -693,24 +735,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
break;
}
if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
std::unique_ptr<cmCompiledGeneratorExpression> compiledExpr =
ge.Parse(cflags);
const char* processed =
compiledExpr->Evaluate(lg, configName, false, gtgt);
if (compiledExpr->GetHadContextSensitiveCondition()) {
std::ostringstream e;
/* clang-format off */
e <<
"Xcode does not support per-config per-source COMPILE_FLAGS:\n"
" " << cflags << "\n"
"specified for source:\n"
" " << sf->GetFullPath() << "\n";
/* clang-format on */
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
}
lg->AppendFlags(flags, processed);
lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, "COMPILE_FLAGS"));
}
// Add per-source definitions.

View File

@ -1456,15 +1456,14 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
i != configs.end(); ++i, ++ci) {
std::string configUpper = cmSystemTools::UpperCase(*i);
cmLVS7GFileConfig fc;
cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i);
bool needfc = false;
if (!objectName.empty()) {
fc.ObjectName = objectName;
needfc = true;
}
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
fc.CompileFlags = cge->Evaluate(lg, *i, false, gt);
fc.CompileFlags = genexInterpreter.Evaluate(cflags);
needfc = true;
}
if (lg->FortranProject) {

View File

@ -425,6 +425,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget, config);
// Add Fortran format flags.
if (lang == "Fortran") {
@ -433,10 +435,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
// Add flags from source file properties.
if (const char* cflags = source.GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
false, this->GeneratorTarget);
const char* evaluatedFlags = genexInterpreter.Evaluate(cflags);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
*this->FlagFileStream << "# Custom flags: " << relativeObj
<< "_FLAGS = " << evaluatedFlags << "\n"

View File

@ -136,12 +136,11 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
// Add source file specific flags.
if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
std::string config = this->LocalGenerator->GetConfigName();
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
false, this->GeneratorTarget);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget,
this->LocalGenerator->GetConfigName());
this->LocalGenerator->AppendFlags(flags,
genexInterpreter.Evaluate(cflags));
}
return flags;

View File

@ -692,6 +692,8 @@ static Json::Value DumpSourceFilesList(
std::vector<cmSourceFile*> files;
target->GetSourceFiles(files, config);
cmGeneratorExpressionInterpreter genexInterpreter(
target->GetLocalGenerator(), target, config);
std::unordered_map<LanguageData, std::vector<std::string>> fileGroups;
for (cmSourceFile* file : files) {
@ -703,11 +705,7 @@ static Json::Value DumpSourceFilesList(
std::string compileFlags = ld.Flags;
if (const char* cflags = file->GetProperty("COMPILE_FLAGS")) {
cmGeneratorExpression ge;
auto cge = ge.Parse(cflags);
const char* processed =
cge->Evaluate(target->GetLocalGenerator(), config);
lg->AppendFlags(compileFlags, processed);
lg->AppendFlags(compileFlags, genexInterpreter.Evaluate(cflags));
}
fileData.Flags = compileFlags;

View File

@ -2062,10 +2062,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
bool configDependentFlags = false;
std::string defines;
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
if (cmGeneratorExpression::Find(cflags) != std::string::npos) {
configDependentFlags = true;
}
configDependentFlags =
cmGeneratorExpression::Find(cflags) != std::string::npos;
flags += cflags;
}
if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
@ -2122,8 +2120,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
// if we have flags or defines for this config then
// use them
if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
compileAs || noWinRT) {
if (!flags.empty() || !configDefines.empty() || compileAs || noWinRT) {
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
@ -2144,6 +2141,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else if (srclang == "CSharp") {
flagtable = gg->GetCSharpFlagTable();
}
cmGeneratorExpressionInterpreter genexInterpreter(
this->LocalGenerator, this->GeneratorTarget, *config);
cmVisualStudioGeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
flagtable, 0, this);
@ -2154,11 +2153,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
clOptions.AddFlag("CompileAsWinRT", "false");
}
if (configDependentFlags) {
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(flags);
std::string evaluatedFlags = cge->Evaluate(
this->LocalGenerator, *config, false, this->GeneratorTarget);
clOptions.Parse(evaluatedFlags.c_str());
clOptions.Parse(genexInterpreter.Evaluate(flags));
} else {
clOptions.Parse(flags.c_str());
}