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.HadContextSensitiveCondition = false;
|
||||
context.HadHeadSensitiveCondition = false;
|
||||
context.SourceSensitiveTargets.clear();
|
||||
context.HeadTarget = headTarget;
|
||||
context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
|
||||
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
|
||||
|
@ -118,6 +119,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
|
|||
{
|
||||
this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
|
||||
this->HadHeadSensitiveCondition = context.HadHeadSensitiveCondition;
|
||||
this->SourceSensitiveTargets = context.SourceSensitiveTargets;
|
||||
}
|
||||
|
||||
this->DependTargets = context.DependTargets;
|
||||
|
|
|
@ -115,6 +115,10 @@ public:
|
|||
{
|
||||
return this->HadHeadSensitiveCondition;
|
||||
}
|
||||
std::set<cmTarget const*> GetSourceSensitiveTargets() const
|
||||
{
|
||||
return this->SourceSensitiveTargets;
|
||||
}
|
||||
|
||||
void SetEvaluateForBuildsystem(bool eval)
|
||||
{
|
||||
|
@ -146,6 +150,7 @@ private:
|
|||
mutable std::string Output;
|
||||
mutable bool HadContextSensitiveCondition;
|
||||
mutable bool HadHeadSensitiveCondition;
|
||||
mutable std::set<cmTarget const*> SourceSensitiveTargets;
|
||||
bool EvaluateForBuildsystem;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include "cmGeneratorExpressionEvaluationFile.h"
|
||||
|
||||
#include "cmMakefile.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#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()
|
||||
{
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
|
||||
std::vector<std::string> GetFiles() const { return this->Files; }
|
||||
|
||||
void CreateOutputFile(std::string const& config);
|
||||
|
||||
private:
|
||||
void Generate(const std::string& config,
|
||||
cmCompiledGeneratorExpression* inputExpression,
|
||||
|
|
|
@ -939,7 +939,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
reportError(context, content->GetOriginalExpression(), e.str());
|
||||
return std::string();
|
||||
}
|
||||
context->AllTargets.insert(target);
|
||||
context->AllTargets.insert(target);
|
||||
}
|
||||
|
||||
if (target == context->HeadTarget)
|
||||
|
@ -950,6 +950,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
// value for all evaluations.
|
||||
context->SeenTargetProperties.insert(propertyName);
|
||||
}
|
||||
if (propertyName == "SOURCES")
|
||||
{
|
||||
context->SourceSensitiveTargets.insert(target);
|
||||
}
|
||||
|
||||
if (propertyName.empty())
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ struct cmGeneratorExpressionContext
|
|||
std::set<cmTarget*> DependTargets;
|
||||
std::set<cmTarget const*> AllTargets;
|
||||
std::set<std::string> SeenTargetProperties;
|
||||
std::set<cmTarget const*> SourceSensitiveTargets;
|
||||
std::map<cmTarget const*, std::map<std::string, std::string> >
|
||||
MaxLanguageStandard;
|
||||
cmMakefile *Makefile;
|
||||
|
|
|
@ -646,6 +646,17 @@ cmTargetTraceDependencies
|
|||
si != sources.end(); ++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)
|
||||
{
|
||||
this->SourceQueue.push(sf);
|
||||
|
|
|
@ -1263,8 +1263,6 @@ void cmGlobalGenerator::Generate()
|
|||
// Create per-target generator information.
|
||||
this->CreateGeneratorTargets();
|
||||
|
||||
this->ForceLinkerLanguages();
|
||||
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
for (AutogensType::iterator it = autogens.begin(); it != autogens.end();
|
||||
++it)
|
||||
|
@ -1280,6 +1278,8 @@ void cmGlobalGenerator::Generate()
|
|||
this->LocalGenerators[i]->TraceDependencies();
|
||||
}
|
||||
|
||||
this->ForceLinkerLanguages();
|
||||
|
||||
// Compute the manifest of main targets generated.
|
||||
for (i = 0; i < this->LocalGenerators.size(); ++i)
|
||||
{
|
||||
|
@ -2992,6 +2992,32 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
|
|||
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,
|
||||
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
|
||||
|
|
|
@ -341,6 +341,13 @@ public:
|
|||
|
||||
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:
|
||||
virtual void Generate();
|
||||
|
||||
|
@ -488,6 +495,9 @@ private:
|
|||
|
||||
// track targets to issue CMP0042 warning for.
|
||||
std::set<std::string> CMP0042WarnTargets;
|
||||
|
||||
mutable std::map<cmSourceFile*, std::set<cmTarget const*> >
|
||||
FilenameTargetDepends;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -259,6 +259,17 @@ void cmLocalGenerator::ConfigureFinalPass()
|
|||
|
||||
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.
|
||||
cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets();
|
||||
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(BadCondition)
|
||||
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")
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int empty()
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue