Merge topic 'file-GENERATE-source'
b80557c7
file(GENERATE): Evaluate early to allow generating source files0019d54b
Genex: Fix whitespace issue.
This commit is contained in:
commit
cddb5002b5
|
@ -90,6 +90,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
||||||
context.HadError = false;
|
context.HadError = false;
|
||||||
context.HadContextSensitiveCondition = false;
|
context.HadContextSensitiveCondition = false;
|
||||||
context.HadHeadSensitiveCondition = false;
|
context.HadHeadSensitiveCondition = false;
|
||||||
|
context.SourceSensitiveTargets.clear();
|
||||||
context.HeadTarget = headTarget;
|
context.HeadTarget = headTarget;
|
||||||
context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
|
context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
|
||||||
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
|
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
|
||||||
|
@ -118,6 +119,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
||||||
{
|
{
|
||||||
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
||||||
this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
|
this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
|
||||||
|
this->SourceSensitiveTargets = context.SourceSensitiveTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->DependTargets = context.DependTargets;
|
this->DependTargets = context.DependTargets;
|
||||||
|
|
|
@ -115,6 +115,10 @@ public:
|
||||||
{
|
{
|
||||||
return this->HadHeadSensitiveCondition;
|
return this->HadHeadSensitiveCondition;
|
||||||
}
|
}
|
||||||
|
std::set<cmTarget const*> GetSourceSensitiveTargets() const
|
||||||
|
{
|
||||||
|
return this->SourceSensitiveTargets;
|
||||||
|
}
|
||||||
|
|
||||||
void SetEvaluateForBuildsystem(bool eval)
|
void SetEvaluateForBuildsystem(bool eval)
|
||||||
{
|
{
|
||||||
|
@ -146,6 +150,7 @@ private:
|
||||||
mutable std::string Output;
|
mutable std::string Output;
|
||||||
mutable bool HadContextSensitiveCondition;
|
mutable bool HadContextSensitiveCondition;
|
||||||
mutable bool HadHeadSensitiveCondition;
|
mutable bool HadHeadSensitiveCondition;
|
||||||
|
mutable std::set<cmTarget const*> SourceSensitiveTargets;
|
||||||
bool EvaluateForBuildsystem;
|
bool EvaluateForBuildsystem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@
|
||||||
#include "cmGeneratorExpressionEvaluationFile.h"
|
#include "cmGeneratorExpressionEvaluationFile.h"
|
||||||
|
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
|
#include "cmLocalGenerator.h"
|
||||||
|
#include "cmGlobalGenerator.h"
|
||||||
|
#include "cmSourceFile.h"
|
||||||
#include "cmGeneratedFileStream.h"
|
#include "cmGeneratedFileStream.h"
|
||||||
#include <cmsys/FStream.hxx>
|
#include <cmsys/FStream.hxx>
|
||||||
|
|
||||||
|
@ -89,6 +92,20 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
|
||||||
|
std::string const& config)
|
||||||
|
{
|
||||||
|
std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config);
|
||||||
|
cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
|
||||||
|
sf->SetProperty("GENERATED", "1");
|
||||||
|
|
||||||
|
cmGlobalGenerator *gg
|
||||||
|
= this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
||||||
|
gg->SetFilenameTargetDepends(sf,
|
||||||
|
this->OutputFileExpr->GetSourceSensitiveTargets());
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmGeneratorExpressionEvaluationFile::Generate()
|
void cmGeneratorExpressionEvaluationFile::Generate()
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
|
|
||||||
std::vector<std::string> GetFiles() const { return this->Files; }
|
std::vector<std::string> GetFiles() const { return this->Files; }
|
||||||
|
|
||||||
|
void CreateOutputFile(std::string const& config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Generate(const std::string& config,
|
void Generate(const std::string& config,
|
||||||
cmCompiledGeneratorExpression* inputExpression,
|
cmCompiledGeneratorExpression* inputExpression,
|
||||||
|
|
|
@ -939,7 +939,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
reportError(context, content->GetOriginalExpression(), e.str());
|
reportError(context, content->GetOriginalExpression(), e.str());
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
context->AllTargets.insert(target);
|
context->AllTargets.insert(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target == context->HeadTarget)
|
if (target == context->HeadTarget)
|
||||||
|
@ -950,6 +950,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
// value for all evaluations.
|
// value for all evaluations.
|
||||||
context->SeenTargetProperties.insert(propertyName);
|
context->SeenTargetProperties.insert(propertyName);
|
||||||
}
|
}
|
||||||
|
if (propertyName == "SOURCES")
|
||||||
|
{
|
||||||
|
context->SourceSensitiveTargets.insert(target);
|
||||||
|
}
|
||||||
|
|
||||||
if (propertyName.empty())
|
if (propertyName.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct cmGeneratorExpressionContext
|
||||||
std::set<cmTarget*> DependTargets;
|
std::set<cmTarget*> DependTargets;
|
||||||
std::set<cmTarget const*> AllTargets;
|
std::set<cmTarget const*> AllTargets;
|
||||||
std::set<std::string> SeenTargetProperties;
|
std::set<std::string> SeenTargetProperties;
|
||||||
|
std::set<cmTarget const*> SourceSensitiveTargets;
|
||||||
std::map<cmTarget const*, std::map<std::string, std::string> >
|
std::map<cmTarget const*, std::map<std::string, std::string> >
|
||||||
MaxLanguageStandard;
|
MaxLanguageStandard;
|
||||||
cmMakefile *Makefile;
|
cmMakefile *Makefile;
|
||||||
|
|
|
@ -646,6 +646,17 @@ cmTargetTraceDependencies
|
||||||
si != sources.end(); ++si)
|
si != sources.end(); ++si)
|
||||||
{
|
{
|
||||||
cmSourceFile* sf = *si;
|
cmSourceFile* sf = *si;
|
||||||
|
const std::set<cmTarget const*> tgts =
|
||||||
|
this->GlobalGenerator->GetFilenameTargetDepends(sf);
|
||||||
|
if (tgts.find(this->Target) != tgts.end())
|
||||||
|
{
|
||||||
|
cmOStringStream e;
|
||||||
|
e << "Evaluation output file\n \"" << sf->GetFullPath()
|
||||||
|
<< "\"\ndepends on the sources of a target it is used in. This "
|
||||||
|
"is a dependency loop and is not allowed.";
|
||||||
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(emitted.insert(sf).second && this->SourcesQueued.insert(sf).second)
|
if(emitted.insert(sf).second && this->SourcesQueued.insert(sf).second)
|
||||||
{
|
{
|
||||||
this->SourceQueue.push(sf);
|
this->SourceQueue.push(sf);
|
||||||
|
|
|
@ -1263,8 +1263,6 @@ void cmGlobalGenerator::Generate()
|
||||||
// Create per-target generator information.
|
// Create per-target generator information.
|
||||||
this->CreateGeneratorTargets();
|
this->CreateGeneratorTargets();
|
||||||
|
|
||||||
this->ForceLinkerLanguages();
|
|
||||||
|
|
||||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
for (AutogensType::iterator it = autogens.begin(); it != autogens.end();
|
for (AutogensType::iterator it = autogens.begin(); it != autogens.end();
|
||||||
++it)
|
++it)
|
||||||
|
@ -1280,6 +1278,8 @@ void cmGlobalGenerator::Generate()
|
||||||
this->LocalGenerators[i]->TraceDependencies();
|
this->LocalGenerators[i]->TraceDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->ForceLinkerLanguages();
|
||||||
|
|
||||||
// Compute the manifest of main targets generated.
|
// Compute the manifest of main targets generated.
|
||||||
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -2992,6 +2992,32 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalGenerator::SetFilenameTargetDepends(cmSourceFile* sf,
|
||||||
|
std::set<cmTarget const*> tgts)
|
||||||
|
{
|
||||||
|
this->FilenameTargetDepends[sf] = tgts;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
std::set<cmTarget const*> const&
|
||||||
|
cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const {
|
||||||
|
return this->FilenameTargetDepends[sf];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmGlobalGenerator::CreateEvaluationSourceFiles(
|
||||||
|
std::string const& config) const
|
||||||
|
{
|
||||||
|
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
|
||||||
|
li = this->EvaluationFiles.begin();
|
||||||
|
li != this->EvaluationFiles.end();
|
||||||
|
++li)
|
||||||
|
{
|
||||||
|
(*li)->CreateOutputFile(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
|
void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
|
||||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
|
||||||
|
|
|
@ -341,6 +341,13 @@ public:
|
||||||
|
|
||||||
bool GenerateCPackPropertiesFile();
|
bool GenerateCPackPropertiesFile();
|
||||||
|
|
||||||
|
void CreateEvaluationSourceFiles(std::string const& config) const;
|
||||||
|
|
||||||
|
void SetFilenameTargetDepends(cmSourceFile* sf,
|
||||||
|
std::set<cmTarget const*> tgts);
|
||||||
|
std::set<cmTarget const*> const&
|
||||||
|
GetFilenameTargetDepends(cmSourceFile* sf) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void Generate();
|
virtual void Generate();
|
||||||
|
|
||||||
|
@ -488,6 +495,9 @@ private:
|
||||||
|
|
||||||
// track targets to issue CMP0042 warning for.
|
// track targets to issue CMP0042 warning for.
|
||||||
std::set<std::string> CMP0042WarnTargets;
|
std::set<std::string> CMP0042WarnTargets;
|
||||||
|
|
||||||
|
mutable std::map<cmSourceFile*, std::set<cmTarget const*> >
|
||||||
|
FilenameTargetDepends;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -259,6 +259,17 @@ void cmLocalGenerator::ConfigureFinalPass()
|
||||||
|
|
||||||
void cmLocalGenerator::TraceDependencies()
|
void cmLocalGenerator::TraceDependencies()
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> configs;
|
||||||
|
this->Makefile->GetConfigurations(configs);
|
||||||
|
if (configs.empty())
|
||||||
|
{
|
||||||
|
configs.push_back("");
|
||||||
|
}
|
||||||
|
for(std::vector<std::string>::const_iterator ci = configs.begin();
|
||||||
|
ci != configs.end(); ++ci)
|
||||||
|
{
|
||||||
|
this->GlobalGenerator->CreateEvaluationSourceFiles(*ci);
|
||||||
|
}
|
||||||
// Generate the rule files for each target.
|
// Generate the rule files for each target.
|
||||||
cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets();
|
cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets();
|
||||||
for(cmGeneratorTargetsType::iterator t = targets.begin();
|
for(cmGeneratorTargetsType::iterator t = targets.begin();
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
|
@ -0,0 +1 @@
|
||||||
|
^$
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
# Ensure re-generation
|
||||||
|
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
|
||||||
|
CONTENT "int main() { return 0; }\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(mn "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1,9 @@
|
||||||
|
CMake Error at OutputNameMatchesObjects.cmake:2 \(file\):
|
||||||
|
Error evaluating generator expression:
|
||||||
|
|
||||||
|
\$<TARGET_OBJECTS:foo>
|
||||||
|
|
||||||
|
The evaluation of the TARGET_OBJECTS generator expression is only suitable
|
||||||
|
for consumption by CMake. It is not suitable for writing out elsewhere.
|
||||||
|
Call Stack \(most recent call first\):
|
||||||
|
CMakeLists.txt:6 \(include\)
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_OBJECTS:foo>>somefile.cpp"
|
||||||
|
CONTENT "static const char content[] = \"$<TARGET_OBJECTS:foo>\";\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/input.txt"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/input.txt" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
|
add_executable(foo empty.cpp "${CMAKE_CURRENT_BINARY_DIR}/1somefile.cpp" "${CMAKE_CURRENT_BINARY_DIR}/input.txt")
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
|
@ -0,0 +1 @@
|
||||||
|
^$
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_PROPERTY:foo,SOURCES>>somefile.cpp"
|
||||||
|
CONTENT "static const char content[] = \"$<TARGET_PROPERTY:foo,SOURCES>\";\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated.cpp"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/generated.cpp" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
|
add_executable(foo empty.cpp "${CMAKE_CURRENT_BINARY_DIR}/generated.cpp")
|
||||||
|
|
||||||
|
add_executable(bar "${CMAKE_CURRENT_BINARY_DIR}/1somefile.cpp")
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
|
@ -0,0 +1,7 @@
|
||||||
|
CMake Error in CMakeLists.txt:
|
||||||
|
Evaluation output file
|
||||||
|
|
||||||
|
".*Tests/RunCMake/File_Generate/OutputNameMatchesSources-build/1somefile.cpp"
|
||||||
|
|
||||||
|
depends on the sources of a target it is used in. This is a dependency
|
||||||
|
loop and is not allowed.
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<BOOL:$<TARGET_PROPERTY:foo,SOURCES>>somefile.cpp"
|
||||||
|
CONTENT "static const char content[] = \"$<TARGET_PROPERTY:foo,SOURCES>\";\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/renamed.cpp"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp" "${CMAKE_CURRENT_BINARY_DIR}/renamed.cpp")
|
||||||
|
|
||||||
|
add_executable(foo "${CMAKE_CURRENT_BINARY_DIR}/1somefile.cpp" "${CMAKE_CURRENT_BINARY_DIR}/renamed.cpp")
|
|
@ -8,6 +8,14 @@ run_cmake(EmptyCondition1)
|
||||||
run_cmake(EmptyCondition2)
|
run_cmake(EmptyCondition2)
|
||||||
run_cmake(BadCondition)
|
run_cmake(BadCondition)
|
||||||
run_cmake(DebugEvaluate)
|
run_cmake(DebugEvaluate)
|
||||||
|
run_cmake(GenerateSource)
|
||||||
|
run_cmake(OutputNameMatchesSources)
|
||||||
|
run_cmake(OutputNameMatchesObjects)
|
||||||
|
run_cmake(OutputNameMatchesOtherSources)
|
||||||
|
file(READ "${RunCMake_BINARY_DIR}/OutputNameMatchesOtherSources-build/1somefile.cpp" file_contents)
|
||||||
|
if (NOT file_contents MATCHES "generated.cpp.rule")
|
||||||
|
message(SEND_ERROR "Rule file not in target sources! ${file_contents}")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(timeformat "%Y%j%H%M%S")
|
set(timeformat "%Y%j%H%M%S")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifdef _WIN32
|
||||||
|
__declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
int empty()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue