Merge topic 'file-GENERATE-source'

b80557c7 file(GENERATE): Evaluate early to allow generating source files
0019d54b Genex: Fix whitespace issue.
This commit is contained in:
Brad King 2014-11-13 10:08:32 -05:00 committed by CMake Topic Stage
commit cddb5002b5
24 changed files with 177 additions and 3 deletions

View File

@ -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;

View File

@ -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;
};

View File

@ -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()
{

View File

@ -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,

View File

@ -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())
{

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -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();

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^$

View File

@ -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")

View File

@ -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\)

View File

@ -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")

View File

@ -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")

View File

@ -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.

View File

@ -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")

View File

@ -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")

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int empty()
{
return 0;
}