summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmGeneratorExpression.cxx2
-rw-r--r--Source/cmGeneratorExpression.h5
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx17
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx4
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h1
-rw-r--r--Source/cmGeneratorTarget.cxx11
-rw-r--r--Source/cmGlobalGenerator.cxx30
-rw-r--r--Source/cmGlobalGenerator.h10
-rw-r--r--Source/cmLocalGenerator.cxx11
-rw-r--r--Tests/RunCMake/File_Generate/GenerateSource-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/GenerateSource-stderr.txt1
-rw-r--r--Tests/RunCMake/File_Generate/GenerateSource.cmake12
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesObjects-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt9
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake10
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-stderr.txt1
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources.cmake14
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesSources-result.txt1
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesSources-stderr.txt7
-rw-r--r--Tests/RunCMake/File_Generate/OutputNameMatchesSources.cmake12
-rw-r--r--Tests/RunCMake/File_Generate/RunCMakeTest.cmake8
-rw-r--r--Tests/RunCMake/File_Generate/empty.cpp7
24 files changed, 176 insertions, 2 deletions
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 09d02ea..bff6f5f 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -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;
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index b952520..57f78c5 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -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;
};
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 3a8dc48..1a101dd 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -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>
@@ -90,6 +93,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()
{
mode_t perm = 0;
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 4e87a88..3394ade 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -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,
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index f62bdb6..9aa8e6f 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -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())
{
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 8a529e8..0bf1797 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -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;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 1d1225f..5836a27 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -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);
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index a729c3d..26cfdbe 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1253,8 +1253,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)
@@ -1270,6 +1268,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)
{
@@ -2983,6 +2983,32 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
}
//----------------------------------------------------------------------------
+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,
cmMakefile *makefile,
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index ddd7e91..8a10d38 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -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
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 69b56c6..3fb1e1e 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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();
diff --git a/Tests/RunCMake/File_Generate/GenerateSource-result.txt b/Tests/RunCMake/File_Generate/GenerateSource-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/GenerateSource-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/File_Generate/GenerateSource-stderr.txt b/Tests/RunCMake/File_Generate/GenerateSource-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/GenerateSource-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/File_Generate/GenerateSource.cmake b/Tests/RunCMake/File_Generate/GenerateSource.cmake
new file mode 100644
index 0000000..147a7f6
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/GenerateSource.cmake
@@ -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")
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-result.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
new file mode 100644
index 0000000..d3aa973
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects-stderr.txt
@@ -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\)
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
new file mode 100644
index 0000000..d807450
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesObjects.cmake
@@ -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")
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-result.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources.cmake
new file mode 100644
index 0000000..ce601da
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesOtherSources.cmake
@@ -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")
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesSources-result.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesSources-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesSources-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesSources-stderr.txt b/Tests/RunCMake/File_Generate/OutputNameMatchesSources-stderr.txt
new file mode 100644
index 0000000..cefb4e5
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesSources-stderr.txt
@@ -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.
diff --git a/Tests/RunCMake/File_Generate/OutputNameMatchesSources.cmake b/Tests/RunCMake/File_Generate/OutputNameMatchesSources.cmake
new file mode 100644
index 0000000..2feb9d1
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/OutputNameMatchesSources.cmake
@@ -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")
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index 578df81..7db77d4 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -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")
diff --git a/Tests/RunCMake/File_Generate/empty.cpp b/Tests/RunCMake/File_Generate/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+ return 0;
+}