diff options
29 files changed, 654 insertions, 417 deletions
diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst new file mode 100644 index 0000000..000677a --- /dev/null +++ b/Help/generator/Visual Studio 10 2010.rst @@ -0,0 +1,12 @@ +Visual Studio 10 2010 +--------------------- + +Generates Visual Studio 10 (VS 2010) project files. + +It is possible to append a space followed by the platform name to +create project files for a specific target platform. E.g. +"Visual Studio 10 2010 Win64" will create project files for the +x64 processor; "Visual Studio 10 2010 IA64" for Itanium. + +For compatibility with CMake versions prior to 3.0, one may specify this +generator using the name "Visual Studio 10" without the year component. diff --git a/Help/generator/Visual Studio 10.rst b/Help/generator/Visual Studio 10.rst deleted file mode 100644 index 9ea7970..0000000 --- a/Help/generator/Visual Studio 10.rst +++ /dev/null @@ -1,9 +0,0 @@ -Visual Studio 10 ----------------- - -Generates Visual Studio 10 (2010) project files. - -It is possible to append a space followed by the platform name to -create project files for a specific target platform. E.g. "Visual -Studio 10 Win64" will create project files for the x64 processor; -"Visual Studio 10 IA64" for Itanium. diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst new file mode 100644 index 0000000..42f6f91 --- /dev/null +++ b/Help/generator/Visual Studio 11 2012.rst @@ -0,0 +1,12 @@ +Visual Studio 11 2012 +--------------------- + +Generates Visual Studio 11 (VS 2012) project files. + +It is possible to append a space followed by the platform name to +create project files for a specific target platform. E.g. +"Visual Studio 11 2012 Win64" will create project files for the +x64 processor; "Visual Studio 11 2012 ARM" for ARM. + +For compatibility with CMake versions prior to 3.0, one may specify this +generator using the name "Visual Studio 11" without the year component. diff --git a/Help/generator/Visual Studio 11.rst b/Help/generator/Visual Studio 11.rst deleted file mode 100644 index 4115c8d..0000000 --- a/Help/generator/Visual Studio 11.rst +++ /dev/null @@ -1,9 +0,0 @@ -Visual Studio 11 ----------------- - -Generates Visual Studio 11 (2012) project files. - -It is possible to append a space followed by the platform name to -create project files for a specific target platform. E.g. "Visual -Studio 11 Win64" will create project files for the x64 processor; -"Visual Studio 11 ARM" for ARM. diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst new file mode 100644 index 0000000..d2f4912 --- /dev/null +++ b/Help/generator/Visual Studio 12 2013.rst @@ -0,0 +1,12 @@ +Visual Studio 12 2013 +--------------------- + +Generates Visual Studio 12 (VS 2013) project files. + +It is possible to append a space followed by the platform name to +create project files for a specific target platform. E.g. +"Visual Studio 12 2013 Win64" will create project files for the +x64 processor; "Visual Studio 12 2013 ARM" for ARM. + +For compatibility with CMake versions prior to 3.0, one may specify this +generator using the name "Visual Studio 12" without the year component. diff --git a/Help/generator/Visual Studio 12.rst b/Help/generator/Visual Studio 12.rst deleted file mode 100644 index 51bcab7..0000000 --- a/Help/generator/Visual Studio 12.rst +++ /dev/null @@ -1,9 +0,0 @@ -Visual Studio 12 ----------------- - -Generates Visual Studio 12 (2013) project files. - -It is possible to append a space followed by the platform name to -create project files for a specific target platform. E.g. "Visual -Studio 12 Win64" will create project files for the x64 processor; -"Visual Studio 12 ARM" for ARM. diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 4f0d9c3..a290d1a 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -32,9 +32,9 @@ All Generators /generator/Sublime Text 2 - NMake Makefiles /generator/Sublime Text 2 - Unix Makefiles /generator/Unix Makefiles - /generator/Visual Studio 10 - /generator/Visual Studio 11 - /generator/Visual Studio 12 + /generator/Visual Studio 10 2010 + /generator/Visual Studio 11 2012 + /generator/Visual Studio 12 2013 /generator/Visual Studio 6 /generator/Visual Studio 7 .NET 2003 /generator/Visual Studio 7 diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 010ddc2..f2dd3bd 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -2,5 +2,5 @@ set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MINOR 8) set(CMake_VERSION_PATCH 12) -set(CMake_VERSION_TWEAK 20131030) +set(CMake_VERSION_TWEAK 20131101) #set(CMake_VERSION_RC 1) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6217955..b512675 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -19,6 +19,8 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" +#include <queue> + //---------------------------------------------------------------------------- cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) { @@ -46,6 +48,18 @@ const char *cmGeneratorTarget::GetProperty(const char *prop) } //---------------------------------------------------------------------------- +std::vector<cmSourceFile*> const* +cmGeneratorTarget::GetSourceDepends(cmSourceFile* sf) +{ + SourceEntriesType::iterator i = this->SourceEntries.find(sf); + if(i != this->SourceEntries.end()) + { + return &i->second.Depends; + } + return 0; +} + +//---------------------------------------------------------------------------- bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir, const char *config) { @@ -277,6 +291,285 @@ void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) } //---------------------------------------------------------------------------- +class cmTargetTraceDependencies +{ +public: + cmTargetTraceDependencies(cmGeneratorTarget* target); + void Trace(); +private: + cmTarget* Target; + cmGeneratorTarget* GeneratorTarget; + cmMakefile* Makefile; + cmGlobalGenerator* GlobalGenerator; + typedef cmGeneratorTarget::SourceEntry SourceEntry; + SourceEntry* CurrentEntry; + std::queue<cmSourceFile*> SourceQueue; + std::set<cmSourceFile*> SourcesQueued; + typedef std::map<cmStdString, cmSourceFile*> NameMapType; + NameMapType NameMap; + + void QueueSource(cmSourceFile* sf); + void FollowName(std::string const& name); + void FollowNames(std::vector<std::string> const& names); + bool IsUtility(std::string const& dep); + void CheckCustomCommand(cmCustomCommand const& cc); + void CheckCustomCommands(const std::vector<cmCustomCommand>& commands); +}; + +//---------------------------------------------------------------------------- +cmTargetTraceDependencies +::cmTargetTraceDependencies(cmGeneratorTarget* target): + Target(target->Target), GeneratorTarget(target) +{ + // Convenience. + this->Makefile = this->Target->GetMakefile(); + this->GlobalGenerator = + this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + this->CurrentEntry = 0; + + // Queue all the source files already specified for the target. + std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles(); + for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); + si != sources.end(); ++si) + { + this->QueueSource(*si); + } + + // Queue pre-build, pre-link, and post-build rule dependencies. + this->CheckCustomCommands(this->Target->GetPreBuildCommands()); + this->CheckCustomCommands(this->Target->GetPreLinkCommands()); + this->CheckCustomCommands(this->Target->GetPostBuildCommands()); +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::Trace() +{ + // Process one dependency at a time until the queue is empty. + while(!this->SourceQueue.empty()) + { + // Get the next source from the queue. + cmSourceFile* sf = this->SourceQueue.front(); + this->SourceQueue.pop(); + this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf]; + + // Queue dependencies added explicitly by the user. + if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) + { + std::vector<std::string> objDeps; + cmSystemTools::ExpandListArgument(additionalDeps, objDeps); + this->FollowNames(objDeps); + } + + // Queue the source needed to generate this file, if any. + this->FollowName(sf->GetFullPath()); + + // Queue dependencies added programatically by commands. + this->FollowNames(sf->GetDepends()); + + // Queue custom command dependencies. + if(cmCustomCommand const* cc = sf->GetCustomCommand()) + { + this->CheckCustomCommand(*cc); + } + } + this->CurrentEntry = 0; +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf) +{ + if(this->SourcesQueued.insert(sf).second) + { + this->SourceQueue.push(sf); + + // Make sure this file is in the target. + this->Target->AddSourceFile(sf); + } +} + +//---------------------------------------------------------------------------- +void cmTargetTraceDependencies::FollowName(std::string const& name) +{ + NameMapType::iterator i = this->NameMap.find(name); + if(i == this->NameMap.end()) + { + // Check if we know how to generate this file. + cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str()); + NameMapType::value_type entry(name, sf); + i = this->NameMap.insert(entry).first; + } + if(cmSourceFile* sf = i->second) + { + // Record the dependency we just followed. + if(this->CurrentEntry) + { + this->CurrentEntry->Depends.push_back(sf); + } + + this->QueueSource(sf); + } +} + +//---------------------------------------------------------------------------- +void +cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names) +{ + for(std::vector<std::string>::const_iterator i = names.begin(); + i != names.end(); ++i) + { + this->FollowName(*i); + } +} + +//---------------------------------------------------------------------------- +bool cmTargetTraceDependencies::IsUtility(std::string const& dep) +{ + // Dependencies on targets (utilities) are supposed to be named by + // just the target name. However for compatibility we support + // naming the output file generated by the target (assuming there is + // no output-name property which old code would not have set). In + // that case the target name will be the file basename of the + // dependency. + std::string util = cmSystemTools::GetFilenameName(dep); + if(cmSystemTools::GetFilenameLastExtension(util) == ".exe") + { + util = cmSystemTools::GetFilenameWithoutLastExtension(util); + } + + // Check for a target with this name. + if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str())) + { + // If we find the target and the dep was given as a full path, + // then make sure it was not a full path to something else, and + // the fact that the name matched a target was just a coincidence. + if(cmSystemTools::FileIsFullPath(dep.c_str())) + { + if(t->GetType() >= cmTarget::EXECUTABLE && + t->GetType() <= cmTarget::MODULE_LIBRARY) + { + // This is really only for compatibility so we do not need to + // worry about configuration names and output names. + std::string tLocation = t->GetLocation(0); + tLocation = cmSystemTools::GetFilenamePath(tLocation); + std::string depLocation = cmSystemTools::GetFilenamePath(dep); + depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str()); + tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str()); + if(depLocation == tLocation) + { + this->Target->AddUtility(util.c_str()); + return true; + } + } + } + else + { + // The original name of the dependency was not a full path. It + // must name a target, so add the target-level dependency. + this->Target->AddUtility(util.c_str()); + return true; + } + } + + // The dependency does not name a target built in this project. + return false; +} + +//---------------------------------------------------------------------------- +void +cmTargetTraceDependencies +::CheckCustomCommand(cmCustomCommand const& cc) +{ + // Transform command names that reference targets built in this + // project to corresponding target-level dependencies. + cmGeneratorExpression ge(cc.GetBacktrace()); + + // Add target-level dependencies referenced by generator expressions. + std::set<cmTarget*> targets; + + for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin(); + cit != cc.GetCommandLines().end(); ++cit) + { + std::string const& command = *cit->begin(); + // Check for a target with this name. + if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str())) + { + if(t->GetType() == cmTarget::EXECUTABLE) + { + // The command refers to an executable target built in + // this project. Add the target-level dependency to make + // sure the executable is up to date before this custom + // command possibly runs. + this->Target->AddUtility(command.c_str()); + } + } + + // Check for target references in generator expressions. + for(cmCustomCommandLine::const_iterator cli = cit->begin(); + cli != cit->end(); ++cli) + { + const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge + = ge.Parse(*cli); + cge->Evaluate(this->Makefile, 0, true); + std::set<cmTarget*> geTargets = cge->GetTargets(); + for(std::set<cmTarget*>::const_iterator it = geTargets.begin(); + it != geTargets.end(); ++it) + { + targets.insert(*it); + } + } + } + + for(std::set<cmTarget*>::iterator ti = targets.begin(); + ti != targets.end(); ++ti) + { + this->Target->AddUtility((*ti)->GetName()); + } + + // Queue the custom command dependencies. + std::vector<std::string> const& depends = cc.GetDepends(); + for(std::vector<std::string>::const_iterator di = depends.begin(); + di != depends.end(); ++di) + { + std::string const& dep = *di; + if(!this->IsUtility(dep)) + { + // The dependency does not name a target and may be a file we + // know how to generate. Queue it. + this->FollowName(dep); + } + } +} + +//---------------------------------------------------------------------------- +void +cmTargetTraceDependencies +::CheckCustomCommands(const std::vector<cmCustomCommand>& commands) +{ + for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin(); + cli != commands.end(); ++cli) + { + this->CheckCustomCommand(*cli); + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::TraceDependencies() +{ + // CMake-generated targets have no dependencies to trace. Normally tracing + // would find nothing anyway, but when building CMake itself the "install" + // target command ends up referencing the "cmake" target but we do not + // really want the dependency because "install" depend on "all" anyway. + if(this->GetType() == cmTarget::GLOBAL_TARGET) + { + return; + } + + // Use a helper object to trace the dependencies. + cmTargetTraceDependencies tracer(this); + tracer.Trace(); +} + +//---------------------------------------------------------------------------- void cmGeneratorTarget::GetAppleArchs(const char* config, std::vector<std::string>& archVec) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 9723f72..a99f54b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -77,9 +77,22 @@ public: /** Add the target output files to the global generator manifest. */ void GenerateTargetManifest(const char* config); + /** + * Trace through the source files in this target and add al source files + * that they depend on, used by all generators + */ + void TraceDependencies(); + void ClassifySources(); void LookupObjectLibraries(); + /** Get sources that must be built before the given source. */ + std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf); + + struct SourceEntry { std::vector<cmSourceFile*> Depends; }; + typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType; + SourceEntriesType SourceEntries; + private: std::map<std::string, std::vector<std::string> > SystemIncludesCache; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index df434b3..4d6e10f 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -52,6 +52,10 @@ public: ///! Get the name for this generator virtual const char *GetName() const { return "Generic"; }; + /** Check whether the given name matches the current generator. */ + virtual bool MatchesGeneratorName(const char* name) const + { return strcmp(this->GetName(), name) == 0; } + /** Set the generator-specific toolset name. Returns true if toolset is supported and false otherwise. */ virtual bool SetGeneratorToolset(std::string const& ts); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 07ccc33..5e29fd7 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -18,42 +18,65 @@ #include "cmVisualStudioSlnParser.h" #include "cmake.h" -static const char vs10Win32generatorName[] = "Visual Studio 10"; -static const char vs10Win64generatorName[] = "Visual Studio 10 Win64"; -static const char vs10IA64generatorName[] = "Visual Studio 10 IA64"; +static const char vs10generatorName[] = "Visual Studio 10 2010"; + +// Map generator name without year to name with year. +static const char* cmVS10GenName(const char* name, std::string& genName) +{ + if(strncmp(name, vs10generatorName, sizeof(vs10generatorName)-6) != 0) + { + return 0; + } + const char* p = name + sizeof(vs10generatorName) - 6; + if(strncmp(p, " 2010", 5) == 0) + { + p += 5; + } + genName = std::string(vs10generatorName) + p; + return p; +} class cmGlobalVisualStudio10Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(!strcmp(name, vs10Win32generatorName)) + virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const + { + std::string genName; + const char* p = cmVS10GenName(name, genName); + if(!p) + { return 0; } + name = genName.c_str(); + if(strcmp(p, "") == 0) { return new cmGlobalVisualStudio10Generator( name, NULL, NULL); } - if(!strcmp(name, vs10Win64generatorName)) + if(strcmp(p, " Win64") == 0) { return new cmGlobalVisualStudio10Generator( name, "x64", "CMAKE_FORCE_WIN64"); } - if(!strcmp(name, vs10IA64generatorName)) + if(strcmp(p, " IA64") == 0) { return new cmGlobalVisualStudio10Generator( name, "Itanium", "CMAKE_FORCE_IA64"); } return 0; - } + } - virtual void GetDocumentation(cmDocumentationEntry& entry) const { - entry.Name = "Visual Studio 10"; - entry.Brief = "Generates Visual Studio 10 (2010) project files."; - } + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = vs10generatorName; + entry.Brief = "Generates Visual Studio 10 (VS 2010) project files."; + } - virtual void GetGenerators(std::vector<std::string>& names) const { - names.push_back(vs10Win32generatorName); - names.push_back(vs10Win64generatorName); - names.push_back(vs10IA64generatorName); } + virtual void GetGenerators(std::vector<std::string>& names) const + { + names.push_back(vs10generatorName); + names.push_back(vs10generatorName + std::string(" IA64")); + names.push_back(vs10generatorName + std::string(" Win64")); + } }; //---------------------------------------------------------------------------- @@ -79,6 +102,18 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( //---------------------------------------------------------------------------- bool +cmGlobalVisualStudio10Generator::MatchesGeneratorName(const char* name) const +{ + std::string genName; + if(cmVS10GenName(name, genName)) + { + return genName == this->GetName(); + } + return false; +} + +//---------------------------------------------------------------------------- +bool cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts) { this->PlatformToolset = ts; diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 31e122e..e9e7cb1 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -28,6 +28,8 @@ public: const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); + virtual bool MatchesGeneratorName(const char* name) const; + virtual bool SetGeneratorToolset(std::string const& ts); virtual std::string diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 41a349e..d968c6d 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -13,42 +13,54 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -static const char vs11generatorName[] = "Visual Studio 11"; +static const char vs11generatorName[] = "Visual Studio 11 2012"; + +// Map generator name without year to name with year. +static const char* cmVS11GenName(const char* name, std::string& genName) +{ + if(strncmp(name, vs11generatorName, sizeof(vs11generatorName)-6) != 0) + { + return 0; + } + const char* p = name + sizeof(vs11generatorName) - 6; + if(strncmp(p, " 2012", 5) == 0) + { + p += 5; + } + genName = std::string(vs11generatorName) + p; + return p; +} class cmGlobalVisualStudio11Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(strstr(name, vs11generatorName) != name) - { - return 0; - } - - const char* p = name + sizeof(vs11generatorName) - 1; - if(p[0] == '\0') + virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const + { + std::string genName; + const char* p = cmVS11GenName(name, genName); + if(!p) + { return 0; } + name = genName.c_str(); + if(strcmp(p, "") == 0) { return new cmGlobalVisualStudio11Generator( name, NULL, NULL); } - - if(p[0] != ' ') + if(strcmp(p, " Win64") == 0) { - return 0; + return new cmGlobalVisualStudio11Generator( + name, "x64", "CMAKE_FORCE_WIN64"); } - - ++p; - - if(!strcmp(p, "ARM")) + if(strcmp(p, " ARM") == 0) { return new cmGlobalVisualStudio11Generator( name, "ARM", NULL); } - if(!strcmp(p, "Win64")) + if(*p++ != ' ') { - return new cmGlobalVisualStudio11Generator( - name, "x64", "CMAKE_FORCE_WIN64"); + return 0; } std::set<std::string> installedSDKs = @@ -63,14 +75,16 @@ public: new cmGlobalVisualStudio11Generator(name, p, NULL); ret->WindowsCEVersion = "8.00"; return ret; - } + } - virtual void GetDocumentation(cmDocumentationEntry& entry) const { - entry.Name = "Visual Studio 11"; - entry.Brief = "Generates Visual Studio 11 (2012) project files."; - } + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = vs11generatorName; + entry.Brief = "Generates Visual Studio 11 (VS 2012) project files."; + } - virtual void GetGenerators(std::vector<std::string>& names) const { + virtual void GetGenerators(std::vector<std::string>& names) const + { names.push_back(vs11generatorName); names.push_back(vs11generatorName + std::string(" ARM")); names.push_back(vs11generatorName + std::string(" Win64")); @@ -80,9 +94,9 @@ public: for(std::set<std::string>::const_iterator i = installedSDKs.begin(); i != installedSDKs.end(); ++i) { - names.push_back("Visual Studio 11 " + *i); + names.push_back(std::string(vs11generatorName) + " " + *i); } - } + } }; //---------------------------------------------------------------------------- @@ -107,6 +121,18 @@ cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( } //---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio11Generator::MatchesGeneratorName(const char* name) const +{ + std::string genName; + if(cmVS11GenName(name, genName)) + { + return genName == this->GetName(); + } + return false; +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index 7cc7e69..7ef77e7 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -24,6 +24,8 @@ public: const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); + virtual bool MatchesGeneratorName(const char* name) const; + virtual void WriteSLNHeader(std::ostream& fout); ///! create the correct local generator diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index c2cdc0b..f3806df 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -13,42 +13,65 @@ #include "cmLocalVisualStudio10Generator.h" #include "cmMakefile.h" -static const char vs12Win32generatorName[] = "Visual Studio 12"; -static const char vs12Win64generatorName[] = "Visual Studio 12 Win64"; -static const char vs12ARMgeneratorName[] = "Visual Studio 12 ARM"; +static const char vs12generatorName[] = "Visual Studio 12 2013"; + +// Map generator name without year to name with year. +static const char* cmVS12GenName(const char* name, std::string& genName) +{ + if(strncmp(name, vs12generatorName, sizeof(vs12generatorName)-6) != 0) + { + return 0; + } + const char* p = name + sizeof(vs12generatorName) - 6; + if(strncmp(p, " 2013", 5) == 0) + { + p += 5; + } + genName = std::string(vs12generatorName) + p; + return p; +} class cmGlobalVisualStudio12Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const { - if(!strcmp(name, vs12Win32generatorName)) + virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const + { + std::string genName; + const char* p = cmVS12GenName(name, genName); + if(!p) + { return 0; } + name = genName.c_str(); + if(strcmp(p, "") == 0) { return new cmGlobalVisualStudio12Generator( name, NULL, NULL); } - if(!strcmp(name, vs12Win64generatorName)) + if(strcmp(p, " Win64") == 0) { return new cmGlobalVisualStudio12Generator( name, "x64", "CMAKE_FORCE_WIN64"); } - if(!strcmp(name, vs12ARMgeneratorName)) + if(strcmp(p, " ARM") == 0) { return new cmGlobalVisualStudio12Generator( name, "ARM", NULL); } return 0; - } + } - virtual void GetDocumentation(cmDocumentationEntry& entry) const { - entry.Name = "Visual Studio 12"; - entry.Brief = "Generates Visual Studio 12 (2013) project files."; - } + virtual void GetDocumentation(cmDocumentationEntry& entry) const + { + entry.Name = vs12generatorName; + entry.Brief = "Generates Visual Studio 12 (VS 2013) project files."; + } - virtual void GetGenerators(std::vector<std::string>& names) const { - names.push_back(vs12Win32generatorName); - names.push_back(vs12Win64generatorName); - names.push_back(vs12ARMgeneratorName); } + virtual void GetGenerators(std::vector<std::string>& names) const + { + names.push_back(vs12generatorName); + names.push_back(vs12generatorName + std::string(" ARM")); + names.push_back(vs12generatorName + std::string(" Win64")); + } }; //---------------------------------------------------------------------------- @@ -73,6 +96,18 @@ cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( } //---------------------------------------------------------------------------- +bool +cmGlobalVisualStudio12Generator::MatchesGeneratorName(const char* name) const +{ + std::string genName; + if(cmVS12GenName(name, genName)) + { + return genName == this->GetName(); + } + return false; +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index 8c8aeb1..5a4a78d 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -24,6 +24,8 @@ public: const char* platformName, const char* additionalPlatformDefinition); static cmGlobalGeneratorFactory* NewFactory(); + virtual bool MatchesGeneratorName(const char* name) const; + virtual void WriteSLNHeader(std::ostream& fout); ///! create the correct local generator diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 2a29061..63ec576 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -257,10 +257,11 @@ void cmLocalGenerator::ConfigureFinalPass() void cmLocalGenerator::TraceDependencies() { // Generate the rule files for each target. - cmTargets& targets = this->Makefile->GetTargets(); - for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t) + cmGeneratorTargetsType targets = this->Makefile->GetGeneratorTargets(); + for(cmGeneratorTargetsType::iterator t = targets.begin(); + t != targets.end(); ++t) { - t->second.TraceDependencies(); + t->second->TraceDependencies(); } } diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index d95a213..f1d5e2c 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -318,9 +318,13 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc, cdCmd << cdStr << this->ConvertToOutputFormat(wd, SHELL); cmdLines.push_back(cdCmd.str()); } + + std::string launcher = this->MakeCustomLauncher(*cc); + for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) { - cmdLines.push_back(this->ConvertToOutputFormat(ccg.GetCommand(i).c_str(), - SHELL)); + cmdLines.push_back(launcher + + this->ConvertToOutputFormat(ccg.GetCommand(i).c_str(), SHELL)); + std::string& cmd = cmdLines.back(); ccg.AppendArguments(i, cmd); } @@ -407,3 +411,39 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements() this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps); } } + +std::string cmLocalNinjaGenerator::MakeCustomLauncher( + const cmCustomCommand& cc) +{ + const char* property = "RULE_LAUNCH_CUSTOM"; + const char* property_value = this->Makefile->GetProperty(property); + + if(!property_value || !*property_value) + { + return std::string(); + } + + // Expand rules in the empty string. It may insert the launcher and + // perform replacements. + RuleVariables vars; + vars.RuleLauncher = property; + std::string output; + const std::vector<std::string>& outputs = cc.GetOutputs(); + if(!outputs.empty()) + { + RelativeRoot relative_root = + cc.GetWorkingDirectory() ? NONE : START_OUTPUT; + + output = this->Convert(outputs[0].c_str(), relative_root, SHELL); + } + vars.Output = output.c_str(); + + std::string launcher; + this->ExpandRuleVariables(launcher, vars); + if(!launcher.empty()) + { + launcher += " "; + } + + return launcher; +} diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index c450841..8eb63c5 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -121,6 +121,7 @@ private: void WriteCustomCommandBuildStatements(); + std::string MakeCustomLauncher(const cmCustomCommand& cc); std::string ConfigName; std::string HomeRelativeOutputPath; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 6d6d2d8..92eca0f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -22,7 +22,6 @@ #include <cmsys/RegularExpression.hxx> #include <map> #include <set> -#include <queue> #include <stdlib.h> // required for atof #include <assert.h> @@ -84,12 +83,9 @@ public: { this->SourceFileFlagsConstructed = false; } - cmTargetInternals(cmTargetInternals const& r) + cmTargetInternals(cmTargetInternals const&) { this->SourceFileFlagsConstructed = false; - // Only some of these entries are part of the object state. - // Others not copied here are result caches. - this->SourceEntries = r.SourceEntries; } ~cmTargetInternals(); typedef cmTarget::SourceFileFlags SourceFileFlags; @@ -125,10 +121,6 @@ public: LinkClosureMapType; LinkClosureMapType LinkClosureMap; - struct SourceEntry { std::vector<cmSourceFile*> Depends; }; - typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType; - SourceEntriesType SourceEntries; - struct TargetPropertyEntry { TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge, const std::string &targetName = std::string()) @@ -493,285 +485,6 @@ bool cmTarget::IsBundleOnApple() } //---------------------------------------------------------------------------- -class cmTargetTraceDependencies -{ -public: - cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal); - void Trace(); -private: - cmTarget* Target; - cmTargetInternals* Internal; - cmMakefile* Makefile; - cmGlobalGenerator* GlobalGenerator; - typedef cmTargetInternals::SourceEntry SourceEntry; - SourceEntry* CurrentEntry; - std::queue<cmSourceFile*> SourceQueue; - std::set<cmSourceFile*> SourcesQueued; - typedef std::map<cmStdString, cmSourceFile*> NameMapType; - NameMapType NameMap; - - void QueueSource(cmSourceFile* sf); - void FollowName(std::string const& name); - void FollowNames(std::vector<std::string> const& names); - bool IsUtility(std::string const& dep); - void CheckCustomCommand(cmCustomCommand const& cc); - void CheckCustomCommands(const std::vector<cmCustomCommand>& commands); -}; - -//---------------------------------------------------------------------------- -cmTargetTraceDependencies -::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal): - Target(target), Internal(internal) -{ - // Convenience. - this->Makefile = this->Target->GetMakefile(); - this->GlobalGenerator = - this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); - this->CurrentEntry = 0; - - // Queue all the source files already specified for the target. - std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles(); - for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); - si != sources.end(); ++si) - { - this->QueueSource(*si); - } - - // Queue pre-build, pre-link, and post-build rule dependencies. - this->CheckCustomCommands(this->Target->GetPreBuildCommands()); - this->CheckCustomCommands(this->Target->GetPreLinkCommands()); - this->CheckCustomCommands(this->Target->GetPostBuildCommands()); -} - -//---------------------------------------------------------------------------- -void cmTargetTraceDependencies::Trace() -{ - // Process one dependency at a time until the queue is empty. - while(!this->SourceQueue.empty()) - { - // Get the next source from the queue. - cmSourceFile* sf = this->SourceQueue.front(); - this->SourceQueue.pop(); - this->CurrentEntry = &this->Internal->SourceEntries[sf]; - - // Queue dependencies added explicitly by the user. - if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) - { - std::vector<std::string> objDeps; - cmSystemTools::ExpandListArgument(additionalDeps, objDeps); - this->FollowNames(objDeps); - } - - // Queue the source needed to generate this file, if any. - this->FollowName(sf->GetFullPath()); - - // Queue dependencies added programatically by commands. - this->FollowNames(sf->GetDepends()); - - // Queue custom command dependencies. - if(cmCustomCommand const* cc = sf->GetCustomCommand()) - { - this->CheckCustomCommand(*cc); - } - } - this->CurrentEntry = 0; -} - -//---------------------------------------------------------------------------- -void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf) -{ - if(this->SourcesQueued.insert(sf).second) - { - this->SourceQueue.push(sf); - - // Make sure this file is in the target. - this->Target->AddSourceFile(sf); - } -} - -//---------------------------------------------------------------------------- -void cmTargetTraceDependencies::FollowName(std::string const& name) -{ - NameMapType::iterator i = this->NameMap.find(name); - if(i == this->NameMap.end()) - { - // Check if we know how to generate this file. - cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str()); - NameMapType::value_type entry(name, sf); - i = this->NameMap.insert(entry).first; - } - if(cmSourceFile* sf = i->second) - { - // Record the dependency we just followed. - if(this->CurrentEntry) - { - this->CurrentEntry->Depends.push_back(sf); - } - - this->QueueSource(sf); - } -} - -//---------------------------------------------------------------------------- -void -cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names) -{ - for(std::vector<std::string>::const_iterator i = names.begin(); - i != names.end(); ++i) - { - this->FollowName(*i); - } -} - -//---------------------------------------------------------------------------- -bool cmTargetTraceDependencies::IsUtility(std::string const& dep) -{ - // Dependencies on targets (utilities) are supposed to be named by - // just the target name. However for compatibility we support - // naming the output file generated by the target (assuming there is - // no output-name property which old code would not have set). In - // that case the target name will be the file basename of the - // dependency. - std::string util = cmSystemTools::GetFilenameName(dep); - if(cmSystemTools::GetFilenameLastExtension(util) == ".exe") - { - util = cmSystemTools::GetFilenameWithoutLastExtension(util); - } - - // Check for a target with this name. - if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str())) - { - // If we find the target and the dep was given as a full path, - // then make sure it was not a full path to something else, and - // the fact that the name matched a target was just a coincidence. - if(cmSystemTools::FileIsFullPath(dep.c_str())) - { - if(t->GetType() >= cmTarget::EXECUTABLE && - t->GetType() <= cmTarget::MODULE_LIBRARY) - { - // This is really only for compatibility so we do not need to - // worry about configuration names and output names. - std::string tLocation = t->GetLocation(0); - tLocation = cmSystemTools::GetFilenamePath(tLocation); - std::string depLocation = cmSystemTools::GetFilenamePath(dep); - depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str()); - tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str()); - if(depLocation == tLocation) - { - this->Target->AddUtility(util.c_str()); - return true; - } - } - } - else - { - // The original name of the dependency was not a full path. It - // must name a target, so add the target-level dependency. - this->Target->AddUtility(util.c_str()); - return true; - } - } - - // The dependency does not name a target built in this project. - return false; -} - -//---------------------------------------------------------------------------- -void -cmTargetTraceDependencies -::CheckCustomCommand(cmCustomCommand const& cc) -{ - // Transform command names that reference targets built in this - // project to corresponding target-level dependencies. - cmGeneratorExpression ge(cc.GetBacktrace()); - - // Add target-level dependencies referenced by generator expressions. - std::set<cmTarget*> targets; - - for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin(); - cit != cc.GetCommandLines().end(); ++cit) - { - std::string const& command = *cit->begin(); - // Check for a target with this name. - if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str())) - { - if(t->GetType() == cmTarget::EXECUTABLE) - { - // The command refers to an executable target built in - // this project. Add the target-level dependency to make - // sure the executable is up to date before this custom - // command possibly runs. - this->Target->AddUtility(command.c_str()); - } - } - - // Check for target references in generator expressions. - for(cmCustomCommandLine::const_iterator cli = cit->begin(); - cli != cit->end(); ++cli) - { - const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge - = ge.Parse(*cli); - cge->Evaluate(this->Makefile, 0, true); - std::set<cmTarget*> geTargets = cge->GetTargets(); - for(std::set<cmTarget*>::const_iterator it = geTargets.begin(); - it != geTargets.end(); ++it) - { - targets.insert(*it); - } - } - } - - for(std::set<cmTarget*>::iterator ti = targets.begin(); - ti != targets.end(); ++ti) - { - this->Target->AddUtility((*ti)->GetName()); - } - - // Queue the custom command dependencies. - std::vector<std::string> const& depends = cc.GetDepends(); - for(std::vector<std::string>::const_iterator di = depends.begin(); - di != depends.end(); ++di) - { - std::string const& dep = *di; - if(!this->IsUtility(dep)) - { - // The dependency does not name a target and may be a file we - // know how to generate. Queue it. - this->FollowName(dep); - } - } -} - -//---------------------------------------------------------------------------- -void -cmTargetTraceDependencies -::CheckCustomCommands(const std::vector<cmCustomCommand>& commands) -{ - for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin(); - cli != commands.end(); ++cli) - { - this->CheckCustomCommand(*cli); - } -} - -//---------------------------------------------------------------------------- -void cmTarget::TraceDependencies() -{ - // CMake-generated targets have no dependencies to trace. Normally tracing - // would find nothing anyway, but when building CMake itself the "install" - // target command ends up referencing the "cmake" target but we do not - // really want the dependency because "install" depend on "all" anyway. - if(this->GetType() == cmTarget::GLOBAL_TARGET) - { - return; - } - - // Use a helper object to trace the dependencies. - cmTargetTraceDependencies tracer(this, this->Internal.Get()); - tracer.Trace(); -} - -//---------------------------------------------------------------------------- bool cmTarget::FindSourceFiles() { for(std::vector<cmSourceFile*>::const_iterator @@ -802,31 +515,14 @@ std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles() //---------------------------------------------------------------------------- void cmTarget::AddSourceFile(cmSourceFile* sf) { - typedef cmTargetInternals::SourceEntriesType SourceEntriesType; - SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf); - if(i == this->Internal->SourceEntries.end()) + if (std::find(this->SourceFiles.begin(), this->SourceFiles.end(), sf) + == this->SourceFiles.end()) { - typedef cmTargetInternals::SourceEntry SourceEntry; - SourceEntriesType::value_type entry(sf, SourceEntry()); - i = this->Internal->SourceEntries.insert(entry).first; this->SourceFiles.push_back(sf); } } //---------------------------------------------------------------------------- -std::vector<cmSourceFile*> const* -cmTarget::GetSourceDepends(cmSourceFile* sf) -{ - typedef cmTargetInternals::SourceEntriesType SourceEntriesType; - SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf); - if(i != this->Internal->SourceEntries.end()) - { - return &i->second.Depends; - } - return 0; -} - -//---------------------------------------------------------------------------- void cmTarget::AddSources(std::vector<std::string> const& srcs) { for(std::vector<std::string>::const_iterator i = srcs.begin(); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 41af8ab..f3b60b0 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -34,6 +34,8 @@ class cmGlobalGenerator; class cmComputeLinkInformation; class cmListFileBacktrace; class cmTarget; +class cmGeneratorTarget; +class cmTargetTraceDependencies; struct cmTargetLinkInformationMap: public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*> @@ -128,9 +130,6 @@ public: return this->ObjectLibraries; } - /** Get sources that must be built before the given source. */ - std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf); - /** * Flags for a given source file as used in this target. Typically assigned * via SET_TARGET_PROPERTIES when the property is a list of source files. @@ -347,12 +346,6 @@ public: void GetTargetVersion(bool soversion, int& major, int& minor, int& patch); /** - * Trace through the source files in this target and add al source files - * that they depend on, used by all generators - */ - void TraceDependencies(); - - /** * Make sure the full path to all source files is known. */ bool FindSourceFiles(); @@ -732,6 +725,8 @@ private: // Internal representation details. friend class cmTargetInternals; + friend class cmGeneratorTarget; + friend class cmTargetTraceDependencies; cmTargetInternalPointer Internal; void ConstructSourceFileFlags(); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 0dbb5eb..ab97b5e 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -562,7 +562,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(cmSourceFile* sf) if(this->SourcesVisited.insert(sf).second) { if(std::vector<cmSourceFile*> const* depends = - this->Target->GetSourceDepends(sf)) + this->GeneratorTarget->GetSourceDepends(sf)) { for(std::vector<cmSourceFile*>::const_iterator di = depends->begin(); di != depends->end(); ++di) @@ -1049,7 +1049,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() si = this->GeneratorTarget->ExternalObjects.begin(); si != this->GeneratorTarget->ExternalObjects.end(); ++si) { - std::vector<cmSourceFile*> const* d=this->Target->GetSourceDepends(*si); + std::vector<cmSourceFile*> const* d = + this->GeneratorTarget->GetSourceDepends(*si); this->WriteSource((d && !d->empty())? "None":"Object", *si); } } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 186d4e6..f786691 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -1468,9 +1468,9 @@ int cmake::ActualConfigure() {"7.1", "Visual Studio 7 .NET 2003"}, {"8.0", "Visual Studio 8 2005"}, {"9.0", "Visual Studio 9 2008"}, - {"10.0", "Visual Studio 10"}, - {"11.0", "Visual Studio 11"}, - {"12.0", "Visual Studio 12"}, + {"10.0", "Visual Studio 10 2010"}, + {"11.0", "Visual Studio 11 2012"}, + {"12.0", "Visual Studio 12 2013"}, {0, 0}}; for(int i=0; version[i].MSVersion != 0; i++) { @@ -1509,7 +1509,7 @@ int cmake::ActualConfigure() const char* genName = this->CacheManager->GetCacheValue("CMAKE_GENERATOR"); if(genName) { - if(strcmp(this->GlobalGenerator->GetName(), genName) != 0) + if(!this->GlobalGenerator->MatchesGeneratorName(genName)) { std::string message = "Error: generator : "; message += this->GlobalGenerator->GetName(); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 4b08c88..7c939ed 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2344,6 +2344,17 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ --output-log "${CMake_BINARY_DIR}/Tests/CTestTest2/testOutput.log" ) + if("${CMAKE_TEST_GENERATOR}" MATCHES "Makefiles" OR "${CMAKE_TEST_GENERATOR}" MATCHES "Ninja") + configure_file("${CMake_SOURCE_DIR}/Tests/CTestTestLaunchers/test.cmake.in" + "${CMake_BINARY_DIR}/Tests/CTestTestLaunchers/test.cmake" @ONLY ESCAPE_QUOTES) + add_test(CTestTestLaunchers ${CMAKE_CTEST_COMMAND} + -S "${CMake_BINARY_DIR}/Tests/CTestTestLaunchers/test.cmake" -V + --output-log "${CMake_BINARY_DIR}/Tests/CTestTestLaunchers/testOutput.log" + ) + set_tests_properties(CTestTestLaunchers PROPERTIES + PASS_REGULAR_EXPRESSION "CTEST_TEST_LAUNCHER_SUCCESS") + endif() + configure_file("${CMake_SOURCE_DIR}/Tests/CTestTestChecksum/test.cmake.in" "${CMake_BINARY_DIR}/Tests/CTestTestChecksum/test.cmake" @ONLY ESCAPE_QUOTES) diff --git a/Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt b/Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt new file mode 100644 index 0000000..06c5725 --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_test_project/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 2.8.12) + +project(launcher_test_project) + +include(CTest) + +add_custom_command( + OUTPUT test1.txt + COMMAND ${CMAKE_COMMAND} + ARGS -DTESTID=1 -P "${CMAKE_CURRENT_SOURCE_DIR}/command.cmake" +) + +add_custom_command( + OUTPUT test2.txt + COMMAND ${CMAKE_COMMAND} + ARGS -DTESTID=2 -P "${CMAKE_CURRENT_SOURCE_DIR}/command.cmake" +) + +add_custom_target(mytarget ALL DEPENDS test1.txt test2.txt) diff --git a/Tests/CTestTestLaunchers/launcher_test_project/CTestConfig.cmake b/Tests/CTestTestLaunchers/launcher_test_project/CTestConfig.cmake new file mode 100644 index 0000000..bf404ab --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_test_project/CTestConfig.cmake @@ -0,0 +1,8 @@ +set(CTEST_USE_LAUNCHERS 1) +set(CTEST_PROJECT_NAME "CTestTestLaunchers") +set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT") +set(CTEST_DART_SERVER_VERSION "2") +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "www.cdash.org") +set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Tests/CTestTestLaunchers/launcher_test_project/command.cmake b/Tests/CTestTestLaunchers/launcher_test_project/command.cmake new file mode 100644 index 0000000..7f31af9 --- /dev/null +++ b/Tests/CTestTestLaunchers/launcher_test_project/command.cmake @@ -0,0 +1,5 @@ +if("${TESTID}" STREQUAL "1") + message("success") +elseif("${TESTID}" STREQUAL "2") + message(FATAL_ERROR "failure") +endif() diff --git a/Tests/CTestTestLaunchers/test.cmake.in b/Tests/CTestTestLaunchers/test.cmake.in new file mode 100644 index 0000000..43a6533 --- /dev/null +++ b/Tests/CTestTestLaunchers/test.cmake.in @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 2.8.12) + +# Settings: +set(CTEST_DASHBOARD_SOURCE "@CMake_SOURCE_DIR@/Tests/CTestTestLaunchers") +set(CTEST_DASHBOARD_ROOT "@CMake_BINARY_DIR@/Tests/CTestTestLaunchers") +set(CTEST_SITE "@SITE@") +set(CTEST_BUILD_NAME "Launchers-@BUILDNAME@-CTestTestLaunchers") + +set(CTEST_SOURCE_DIRECTORY "${CTEST_DASHBOARD_SOURCE}/launcher_test_project") +set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/launcher_test_project-bin") +set(CTEST_CMAKE_GENERATOR "@CMAKE_GENERATOR@") +set(CTEST_CMAKE_GENERATOR_TOOLSET "@CMAKE_GENERATOR_TOOLSET@") +set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}") +set(CTEST_NOTES_FILES "${CTEST_SCRIPT_DIRECTORY}/${CTEST_SCRIPT_NAME}") + +ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) + +file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" " +CMAKE_CXX_FLAGS:STRING=@CMAKE_CXX_FLAGS@ +CMAKE_C_FLAGS:STRING=@CMAKE_C_FLAGS@ +CMAKE_C_COMPILER:STRING=@CMAKE_C_COMPILER@ +CMAKE_CXX_COMPILER:STRING=@CMAKE_CXX_COMPILER@ +CMAKE_C_COMPILER_ARG1:STRING=@CMAKE_C_COMPILER_ARG1@ +CMAKE_CXX_COMPILER_ARG1:STRING=@CMAKE_CXX_COMPILER_ARG1@ +") + +set(TEST_SUCCESS FALSE) + +ctest_start(Experimental) +ctest_configure(OPTIONS "-DCTEST_USE_LAUNCHERS=1") +ctest_build(NUMBER_ERRORS error_count) + +if("${error_count}" STREQUAL "1") + set(TEST_SUCCESS TRUE) +endif() + +if(TEST_SUCCESS) + message("CTEST_TEST_LAUNCHER_SUCCESS") +endif() |