From 11d9b211266865f0ce4a1005bbb18748c0806bce Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 11:44:48 -0500 Subject: Add cmGeneratorTarget to represent a target during generation Some per-target information and logic is common to all generators. Some of that information is currently stored in cmTarget but that should be reserved for the configure step. Create a class to hold per-target information for generators. On construction classify sources from the target and store them in separate members. This classification is already implemented separately in each generator. --- Source/CMakeLists.txt | 2 ++ Source/cmGeneratorTarget.cxx | 74 ++++++++++++++++++++++++++++++++++++++++++++ Source/cmGeneratorTarget.h | 50 ++++++++++++++++++++++++++++++ bootstrap | 1 + 4 files changed, 127 insertions(+) create mode 100644 Source/cmGeneratorTarget.cxx create mode 100644 Source/cmGeneratorTarget.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 0c420b9..af74ead 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -185,6 +185,8 @@ SET(SRCS cmGeneratedFileStream.cxx cmGeneratorExpression.cxx cmGeneratorExpression.h + cmGeneratorTarget.cxx + cmGeneratorTarget.h cmGlobalGenerator.cxx cmGlobalGenerator.h cmGlobalUnixMakefileGenerator3.cxx diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx new file mode 100644 index 0000000..afb1f39 --- /dev/null +++ b/Source/cmGeneratorTarget.cxx @@ -0,0 +1,74 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmGeneratorTarget.h" + +#include "cmTarget.h" +#include "cmMakefile.h" +#include "cmLocalGenerator.h" +#include "cmGlobalGenerator.h" +#include "cmSourceFile.h" + +//---------------------------------------------------------------------------- +cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) +{ + this->Makefile = this->Target->GetMakefile(); + this->LocalGenerator = this->Makefile->GetLocalGenerator(); + this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + this->ClassifySources(); +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::ClassifySources() +{ + std::vector const& sources = this->Target->GetSourceFiles(); + for(std::vector::const_iterator si = sources.begin(); + si != sources.end(); ++si) + { + cmSourceFile* sf = *si; + cmTarget::SourceFileFlags tsFlags = + this->Target->GetTargetSourceFileFlags(sf); + if(sf->GetCustomCommand()) + { + this->CustomCommands.push_back(sf); + } + else if(tsFlags.Type != cmTarget::SourceFileTypeNormal) + { + this->OSXContent.push_back(sf); + } + else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) + { + this->HeaderSources.push_back(sf); + } + else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) + { + this->ExternalObjects.push_back(sf); + } + else if(cmSystemTools::LowerCase(sf->GetExtension()) == "def") + { + this->ModuleDefinitionFile = sf->GetFullPath(); + } + else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) + { + // We only get here if a source file is not an external object + // and has an extension that is listed as an ignored file type. + // No message or diagnosis should be given. + } + else if(sf->GetLanguage()) + { + this->ObjectSources.push_back(sf); + } + else + { + this->ExtraSources.push_back(sf); + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h new file mode 100644 index 0000000..d93b052 --- /dev/null +++ b/Source/cmGeneratorTarget.h @@ -0,0 +1,50 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2000-2012 Kitware, Inc., Insight Software Consortium + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#ifndef cmGeneratorTarget_h +#define cmGeneratorTarget_h + +#include "cmStandardIncludes.h" + +class cmCustomCommand; +class cmGlobalGenerator; +class cmLocalGenerator; +class cmMakefile; +class cmSourceFile; +class cmTarget; + +class cmGeneratorTarget +{ +public: + cmGeneratorTarget(cmTarget*); + + cmTarget* Target; + cmMakefile* Makefile; + cmLocalGenerator* LocalGenerator; + cmGlobalGenerator* GlobalGenerator; + + /** Sources classified by purpose. */ + std::vector CustomCommands; + std::vector ExtraSources; + std::vector HeaderSources; + std::vector ObjectSources; + std::vector ExternalObjects; + std::vector OSXContent; + std::string ModuleDefinitionFile; + +private: + void ClassifySources(); + + cmGeneratorTarget(cmGeneratorTarget const&); + void operator=(cmGeneratorTarget const&); +}; + +#endif diff --git a/bootstrap b/bootstrap index 665c6c5..3be3d1f 100755 --- a/bootstrap +++ b/bootstrap @@ -208,6 +208,7 @@ CMAKE_CXX_SOURCES="\ cmExportInstallFileGenerator \ cmInstallDirectoryGenerator \ cmGeneratedFileStream \ + cmGeneratorTarget \ cmGeneratorExpression \ cmGlobalGenerator \ cmLocalGenerator \ -- cgit v0.12 From 4b245580913e02ba577d6eb7825866300d364b53 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 11:50:41 -0500 Subject: Create a cmGeneratorTarget for each cmTarget during generation Construct the instances after the final set of targets is known but before computing inter-target dependencies. This order will allow initialization of cmGeneratorTarget instances to adjust and finalize declared inter-target dependencies. --- Source/cmGlobalGenerator.cxx | 47 ++++++++++++++++++++++++++++++++++++++++++++ Source/cmGlobalGenerator.h | 10 ++++++++++ 2 files changed, 57 insertions(+) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index a988844..a1f80d9 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -24,6 +24,7 @@ #include "cmExportInstallFileGenerator.h" #include "cmComputeTargetDepends.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" #include @@ -74,6 +75,7 @@ cmGlobalGenerator::~cmGlobalGenerator() delete this->ExtraGenerator; } + this->ClearGeneratorTargets(); this->ClearExportSets(); } @@ -807,6 +809,7 @@ bool cmGlobalGenerator::IsDependedOn(const char* project, void cmGlobalGenerator::Configure() { this->FirstTimeProgress = 0.0f; + this->ClearGeneratorTargets(); this->ClearExportSets(); // Delete any existing cmLocalGenerators unsigned int i; @@ -947,6 +950,9 @@ void cmGlobalGenerator::Generate() this->LocalGenerators[i]->GenerateTargetManifest(); } + // Create per-target generator information. + this->CreateGeneratorTargets(); + // Compute the inter-target dependencies. if(!this->ComputeTargetDepends()) { @@ -1056,6 +1062,47 @@ void cmGlobalGenerator::CreateAutomocTargets() #endif } +//---------------------------------------------------------------------------- +void cmGlobalGenerator::CreateGeneratorTargets() +{ + // Construct per-target generator information. + for(unsigned int i=0; i < this->LocalGenerators.size(); ++i) + { + cmTargets& targets = + this->LocalGenerators[i]->GetMakefile()->GetTargets(); + for(cmTargets::iterator ti = targets.begin(); + ti != targets.end(); ++ti) + { + cmTarget* t = &ti->second; + this->GeneratorTargets[t] = new cmGeneratorTarget(t); + } + } +} + +//---------------------------------------------------------------------------- +void cmGlobalGenerator::ClearGeneratorTargets() +{ + for(GeneratorTargetsType::iterator i = this->GeneratorTargets.begin(); + i != this->GeneratorTargets.end(); ++i) + { + delete i->second; + } + this->GeneratorTargets.clear(); +} + +//---------------------------------------------------------------------------- +cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const +{ + GeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t); + if(ti == this->GeneratorTargets.end()) + { + this->CMakeInstance->IssueMessage( + cmake::INTERNAL_ERROR, "Missing cmGeneratorTarget instance!", + cmListFileBacktrace()); + return 0; + } + return ti->second; +} void cmGlobalGenerator::CheckLocalGenerators() { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 1a0e41a..b94cc6c 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -19,6 +19,7 @@ #include "cmTargetDepend.h" // For cmTargetDependSet #include "cmSystemTools.h" // for cmSystemTools::OutputOption class cmake; +class cmGeneratorTarget; class cmMakefile; class cmLocalGenerator; class cmExternalMakefileProjectGenerator; @@ -251,6 +252,9 @@ public: // via a target_link_libraries or add_dependencies TargetDependSet const& GetTargetDirectDepends(cmTarget & target); + /** Get per-target generator information. */ + cmGeneratorTarget* GetGeneratorTarget(cmTarget*) const; + const std::map >& GetProjectMap() const {return this->ProjectMap;} @@ -370,6 +374,12 @@ private: typedef std::map TargetDependMap; TargetDependMap TargetDependencies; + // Per-target generator information. + typedef std::map GeneratorTargetsType; + GeneratorTargetsType GeneratorTargets; + void CreateGeneratorTargets(); + void ClearGeneratorTargets(); + // Cache directory content and target files to be built. struct DirectoryContent: public std::set { -- cgit v0.12 From 45c2f93240eb0556b3a8025e154a3dea5e206c7a Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 11:54:52 -0500 Subject: Simplify cmMakefileTargetGenerator using cmGeneratorTarget Replace the classification of source files in this generator using that computed by cmGeneratorTarget. --- Source/cmMakefileTargetGenerator.cxx | 90 ++++++++++++++++-------------------- Source/cmMakefileTargetGenerator.h | 5 +- 2 files changed, 42 insertions(+), 53 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index b9120c4..b374bb6 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmMakefileTargetGenerator.h" +#include "cmGeneratorTarget.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -42,6 +43,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target) this->GlobalGenerator = static_cast( this->LocalGenerator->GetGlobalGenerator()); + this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target); cmake* cm = this->GlobalGenerator->GetCMakeInstance(); this->NoRuleMessages = false; if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES")) @@ -131,58 +133,46 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // First generate the object rule files. Save a list of all object // files for this target. - const std::vector& sources = this->Target->GetSourceFiles(); - for(std::vector::const_iterator source = sources.begin(); - source != sources.end(); ++source) + for(std::vector::const_iterator + si = this->GeneratorTarget->CustomCommands.begin(); + si != this->GeneratorTarget->CustomCommands.end(); ++si) { - cmTarget::SourceFileFlags tsFlags = - this->Target->GetTargetSourceFileFlags(*source); - if(cmCustomCommand* cc = (*source)->GetCustomCommand()) + cmCustomCommand const* cc = (*si)->GetCustomCommand(); + this->GenerateCustomRuleFile(*cc); + if (clean) { - this->GenerateCustomRuleFile(*cc); - if (clean) - { - const std::vector& outputs = cc->GetOutputs(); - for(std::vector::const_iterator o = outputs.begin(); - o != outputs.end(); ++o) - { - this->CleanFiles.push_back - (this->Convert(o->c_str(), - cmLocalGenerator::START_OUTPUT, - cmLocalGenerator::UNCHANGED)); - } - } - } - else if(tsFlags.Type != cmTarget::SourceFileTypeNormal) - { - this->WriteMacOSXContentRules(*(*source), tsFlags.MacFolder); - } - else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY")) - { - if(!this->GlobalGenerator->IgnoreFile - ((*source)->GetExtension().c_str())) - { - // Generate this object file's rule file. - this->WriteObjectRuleFiles(*(*source)); - } - else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT")) - { - // This is an external object file. Just add it. - this->ExternalObjects.push_back((*source)->GetFullPath()); - } - else if(cmSystemTools::UpperCase((*source)->GetExtension()) == "DEF") - { - this->ModuleDefinitionFile = (*source)->GetFullPath(); - } - else + const std::vector& outputs = cc->GetOutputs(); + for(std::vector::const_iterator o = outputs.begin(); + o != outputs.end(); ++o) { - // We only get here if a source file is not an external object - // and has an extension that is listed as an ignored file type - // for this language. No message or diagnosis should be - // given. + this->CleanFiles.push_back + (this->Convert(o->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED)); } } } + for(std::vector::const_iterator + si = this->GeneratorTarget->OSXContent.begin(); + si != this->GeneratorTarget->OSXContent.end(); ++si) + { + cmTarget::SourceFileFlags tsFlags = + this->Target->GetTargetSourceFileFlags(*si); + this->WriteMacOSXContentRules(**si, tsFlags.MacFolder); + } + for(std::vector::const_iterator + si = this->GeneratorTarget->ExternalObjects.begin(); + si != this->GeneratorTarget->ExternalObjects.end(); ++si) + { + this->ExternalObjects.push_back((*si)->GetFullPath()); + } + for(std::vector::const_iterator + si = this->GeneratorTarget->ObjectSources.begin(); + si != this->GeneratorTarget->ObjectSources.end(); ++si) + { + // Generate this object file's rule file. + this->WriteObjectRuleFiles(**si); + } } @@ -1633,9 +1623,9 @@ void cmMakefileTargetGenerator this->BuildFileNameFull.c_str()); // Add a dependency on the link definitions file, if any. - if(!this->ModuleDefinitionFile.empty()) + if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) { - depends.push_back(this->ModuleDefinitionFile); + depends.push_back(this->GeneratorTarget->ModuleDefinitionFile); } // Add dependencies on the external object files. @@ -1971,7 +1961,7 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) { - if(this->ModuleDefinitionFile.empty()) + if(this->GeneratorTarget->ModuleDefinitionFile.empty()) { return; } @@ -1988,7 +1978,7 @@ void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; flag += (this->LocalGenerator->ConvertToLinkReference( - this->ModuleDefinitionFile.c_str())); + this->GeneratorTarget->ModuleDefinitionFile.c_str())); this->LocalGenerator->AppendFlags(flags, flag.c_str()); } diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 8fba13f..dbc607a 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -17,6 +17,7 @@ class cmCustomCommand; class cmDependInformation; class cmDepends; +class cmGeneratorTarget; class cmGeneratedFileStream; class cmGlobalUnixMakefileGenerator3; class cmLocalUnixMakefileGenerator3; @@ -157,6 +158,7 @@ protected: void RemoveForbiddenFlags(const char* flagVar, const char* linkLang, std::string& linkFlags); cmTarget *Target; + cmGeneratorTarget* GeneratorTarget; cmLocalUnixMakefileGenerator3 *LocalGenerator; cmGlobalUnixMakefileGenerator3 *GlobalGenerator; cmMakefile *Makefile; @@ -198,9 +200,6 @@ protected: std::vector Objects; std::vector ExternalObjects; - // The windows module definition source file (.def), if any. - std::string ModuleDefinitionFile; - // Set of object file names that will be built in this directory. std::set ObjectFiles; -- cgit v0.12 From 62a841b80b5f4b4f9cc0ddba77ae010a29b0e27e Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 11:56:21 -0500 Subject: Simplify cmVisualStudio10TargetGenerator using cmGeneratorTarget Use CustomCommands and ModuleDefinitionFile computed in the latter instead of recomputing them from the original target source files. --- Source/cmVisualStudio10TargetGenerator.cxx | 37 ++++++++---------------------- Source/cmVisualStudio10TargetGenerator.h | 4 ++-- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 66f9a36..9168818 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -11,6 +11,7 @@ ============================================================================*/ #include "cmVisualStudio10TargetGenerator.h" #include "cmGlobalVisualStudio10Generator.h" +#include "cmGeneratorTarget.h" #include "cmTarget.h" #include "cmComputeLinkInformation.h" #include "cmGeneratedFileStream.h" @@ -62,6 +63,7 @@ cmVisualStudio10TargetGenerator(cmTarget* target, { this->GlobalGenerator = gg; this->Target = target; + this->GeneratorTarget = gg->GetGeneratorTarget(target); this->Makefile = target->GetMakefile(); this->LocalGenerator = (cmLocalVisualStudio7Generator*) @@ -70,7 +72,8 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->GlobalGenerator->CreateGUID(this->Name.c_str()); this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str()); this->Platform = gg->GetPlatformName(); - this->ComputeObjectNames(); + this->LocalGenerator + ->ComputeObjectNameRequirements(target->GetSourceFiles()); this->BuildFileStream = 0; } @@ -421,12 +424,11 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() void cmVisualStudio10TargetGenerator::WriteCustomCommands() { this->SourcesVisited.clear(); - std::vector const& sources = this->Target->GetSourceFiles(); - for(std::vector::const_iterator source = sources.begin(); - source != sources.end(); ++source) + for(std::vector::const_iterator + si = this->GeneratorTarget->CustomCommands.begin(); + si != this->GeneratorTarget->CustomCommands.end(); ++si) { - cmSourceFile* sf = *source; - this->WriteCustomCommand(sf); + this->WriteCustomCommand(*si); } } @@ -875,25 +877,6 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() this->WriteString("\n", 1); } -void cmVisualStudio10TargetGenerator::ComputeObjectNames() -{ - // get the classes from the source lists then add them to the groups - std::vectorconst & classes = this->Target->GetSourceFiles(); - for(std::vector::const_iterator i = classes.begin(); - i != classes.end(); i++) - { - // Add the file to the list of sources. - std::string source = (*i)->GetFullPath(); - if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") - { - this->ModuleDefinitionFile = (*i)->GetFullPath(); - } - } - - // Compute which sources need unique object computation. - this->LocalGenerator->ComputeObjectNameRequirements(classes); -} - bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmSourceFile* source) { @@ -1513,10 +1496,10 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& linkOptions.AddFlag("ImportLibrary", imLib.c_str()); linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); linkOptions.Parse(flags.c_str()); - if(!this->ModuleDefinitionFile.empty()) + if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) { linkOptions.AddFlag("ModuleDefinitionFile", - this->ModuleDefinitionFile.c_str()); + this->GeneratorTarget->ModuleDefinitionFile.c_str()); } linkOptions.RemoveFlag("GenerateManifest"); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 90035f2..64fb124 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -15,6 +15,7 @@ class cmTarget; class cmMakefile; +class cmGeneratorTarget; class cmGeneratedFileStream; class cmGlobalVisualStudio10Generator; class cmSourceFile; @@ -75,7 +76,6 @@ private: void WriteEvents(std::string const& configName); void WriteEvent(const char* name, std::vector & commands, std::string const& configName); - void ComputeObjectNames(); void WriteGroupSources(const char* name, std::vector const& sources, std::vector& ); @@ -87,9 +87,9 @@ private: typedef cmVisualStudioGeneratorOptions Options; typedef std::map OptionsMap; OptionsMap ClOptions; - std::string ModuleDefinitionFile; std::string PathToVcxproj; cmTarget* Target; + cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; std::string Platform; std::string GUID; -- cgit v0.12 From 3baaf6ccecb9117b613fc89cd37206960298dfaa Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 14:01:46 -0500 Subject: Pre-compute object file names before Makefile generation Add a virtual cmGlobalGenerator::ComputeTargetObjects method invoked during cmGeneratorTarget construction. Implement it in the Makefile generator to pre-compute all object file names for each target. Use the results during generation instead of re-computing it later. --- Source/cmGeneratorTarget.h | 2 ++ Source/cmGlobalGenerator.cxx | 10 +++++++- Source/cmGlobalGenerator.h | 1 + Source/cmGlobalUnixMakefileGenerator3.cxx | 32 +++++++++++++++++++++++++ Source/cmGlobalUnixMakefileGenerator3.h | 2 ++ Source/cmLocalUnixMakefileGenerator3.cxx | 39 ------------------------------- Source/cmLocalUnixMakefileGenerator3.h | 5 ---- Source/cmMakefileTargetGenerator.cxx | 14 ++++------- 8 files changed, 50 insertions(+), 55 deletions(-) diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index d93b052..976cac4 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -40,6 +40,8 @@ public: std::vector OSXContent; std::string ModuleDefinitionFile; + std::map Objects; + private: void ClassifySources(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index a1f80d9..d7ba8b6 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1074,7 +1074,9 @@ void cmGlobalGenerator::CreateGeneratorTargets() ti != targets.end(); ++ti) { cmTarget* t = &ti->second; - this->GeneratorTargets[t] = new cmGeneratorTarget(t); + cmGeneratorTarget* gt = new cmGeneratorTarget(t); + this->GeneratorTargets[t] = gt; + this->ComputeTargetObjects(gt); } } } @@ -1104,6 +1106,12 @@ cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const return ti->second; } +//---------------------------------------------------------------------------- +void cmGlobalGenerator::ComputeTargetObjects(cmGeneratorTarget*) const +{ + // Implemented in generator subclasses that need this. +} + void cmGlobalGenerator::CheckLocalGenerators() { std::map notFoundMap; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index b94cc6c..e818e37 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -379,6 +379,7 @@ private: GeneratorTargetsType GeneratorTargets; void CreateGeneratorTargets(); void ClearGeneratorTargets(); + virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const; // Cache directory content and target files to be built. struct DirectoryContent: public std::set diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index a23c0d8..059692e 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -17,6 +17,7 @@ #include "cmGeneratedFileStream.h" #include "cmSourceFile.h" #include "cmTarget.h" +#include "cmGeneratorTarget.h" cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3() { @@ -71,6 +72,37 @@ void cmGlobalUnixMakefileGenerator3 } //---------------------------------------------------------------------------- +void +cmGlobalUnixMakefileGenerator3 +::ComputeTargetObjects(cmGeneratorTarget* gt) const +{ + cmTarget* target = gt->Target; + cmLocalUnixMakefileGenerator3* lg = + static_cast(gt->LocalGenerator); + + // Compute full path to object file directory for this target. + std::string dir_max; + dir_max += gt->Makefile->GetCurrentOutputDirectory(); + dir_max += "/"; + dir_max += gt->LocalGenerator->GetTargetDirectory(*target); + dir_max += "/"; + + // Compute the name of each object file. + for(std::vector::iterator + si = gt->ObjectSources.begin(); + si != gt->ObjectSources.end(); ++si) + { + cmSourceFile* sf = *si; + bool hasSourceExtension = true; + std::string objectName = gt->LocalGenerator + ->GetObjectFileNameWithoutTarget(*sf, dir_max, + &hasSourceExtension); + gt->Objects[sf] = objectName; + lg->AddLocalObjectFile(target, sf, objectName, hasSourceExtension); + } +} + +//---------------------------------------------------------------------------- std::string EscapeJSON(const std::string& s) { std::string result; for (std::string::size_type i = 0; i < s.size(); ++i) { diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 9663b55..e6dd09d 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -182,6 +182,8 @@ protected: size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg); cmGeneratedFileStream *CommandDatabase; +private: + virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const; }; #endif diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index fdf59b2..b991b25 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -2009,45 +2009,6 @@ void cmLocalUnixMakefileGenerator3 } //---------------------------------------------------------------------------- -std::string -cmLocalUnixMakefileGenerator3 -::GetObjectFileName(cmTarget& target, - const cmSourceFile& source, - std::string* nameWithoutTargetDir, - bool* hasSourceExtension) -{ - // Make sure we never hit this old case. - if(source.GetProperty("MACOSX_PACKAGE_LOCATION")) - { - std::string msg = "MACOSX_PACKAGE_LOCATION set on source file: "; - msg += source.GetFullPath(); - this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, - msg.c_str()); - } - - // Start with the target directory. - std::string obj = this->GetTargetDirectory(target); - obj += "/"; - - // Get the object file name without the target directory. - std::string dir_max; - dir_max += this->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += obj; - std::string objectName = - this->GetObjectFileNameWithoutTarget(source, dir_max, - hasSourceExtension); - if(nameWithoutTargetDir) - { - *nameWithoutTargetDir = objectName; - } - - // Append the object name to the target directory. - obj += objectName; - return obj; -} - -//---------------------------------------------------------------------------- void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os) { os diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 4bde082..e374959 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -284,11 +284,6 @@ protected: cmTarget& target, const std::vector& objects); - std::string GetObjectFileName(cmTarget& target, - const cmSourceFile& source, - std::string* nameWithoutTargetDir = 0, - bool* hasSourceExtension = 0); - void AppendRuleDepend(std::vector& depends, const char* ruleFileName); void AppendRuleDepends(std::vector& depends, diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index b374bb6..fc55f1e 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -418,12 +418,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source) } // Get the full path name of the object file. - bool hasSourceExtension; - std::string objNoTargetDir; - std::string obj = - this->LocalGenerator->GetObjectFileName(*this->Target, source, - &objNoTargetDir, - &hasSourceExtension); + std::string const& objectName = this->GeneratorTarget->Objects[&source]; + std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target); + obj += "/"; + obj += objectName; // Avoid generating duplicate rules. if(this->ObjectFiles.find(obj) == this->ObjectFiles.end()) @@ -477,10 +475,6 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source) AddImplicitDepends(*this->Target, lang, objFullPath.c_str(), srcFullPath.c_str()); - - // add this to the list of objects for this local generator - this->LocalGenerator->AddLocalObjectFile( - this->Target, &source, objNoTargetDir, hasSourceExtension); } //---------------------------------------------------------------------------- -- cgit v0.12 From d57047de33e096eac6fc84976c733b7941c9add3 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 7 Mar 2012 14:04:33 -0500 Subject: Pre-compute object file names before VS project generation Implement cmGlobalGenerator::ComputeTargetObjects in the VS generator to pre-compute all the object file names. Use the results during generation instead of re-computing it later. --- Source/cmGeneratorTarget.h | 1 + Source/cmGlobalVisualStudioGenerator.cxx | 46 ++++++++++++++++++++- Source/cmGlobalVisualStudioGenerator.h | 2 + Source/cmLocalVisualStudio6Generator.cxx | 64 ++++++++++++++++-------------- Source/cmLocalVisualStudio6Generator.h | 1 + Source/cmLocalVisualStudio7Generator.cxx | 36 +++++++---------- Source/cmLocalVisualStudio7Generator.h | 6 +-- Source/cmLocalVisualStudioGenerator.cxx | 63 ----------------------------- Source/cmLocalVisualStudioGenerator.h | 8 +--- Source/cmVisualStudio10TargetGenerator.cxx | 13 ++---- 10 files changed, 104 insertions(+), 136 deletions(-) diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 976cac4..2bfc037 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -41,6 +41,7 @@ public: std::string ModuleDefinitionFile; std::map Objects; + std::set ExplicitObjectName; private: void ClassifySources(); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 449d090..e5a9784 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -12,8 +12,10 @@ #include "cmGlobalVisualStudioGenerator.h" #include "cmCallVisualStudioMacro.h" -#include "cmLocalGenerator.h" +#include "cmGeneratorTarget.h" +#include "cmLocalVisualStudioGenerator.h" #include "cmMakefile.h" +#include "cmSourceFile.h" #include "cmTarget.h" //---------------------------------------------------------------------------- @@ -98,6 +100,48 @@ void cmGlobalVisualStudioGenerator::Generate() } //---------------------------------------------------------------------------- +void +cmGlobalVisualStudioGenerator +::ComputeTargetObjects(cmGeneratorTarget* gt) const +{ + cmLocalVisualStudioGenerator* lg = + static_cast(gt->LocalGenerator); + std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target); + + // Count the number of object files with each name. Note that + // windows file names are not case sensitive. + std::map counts; + for(std::vector::const_iterator + si = gt->ObjectSources.begin(); + si != gt->ObjectSources.end(); ++si) + { + cmSourceFile* sf = *si; + std::string objectNameLower = cmSystemTools::LowerCase( + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); + objectNameLower += ".obj"; + counts[objectNameLower] += 1; + } + + // For all source files producing duplicate names we need unique + // object name computation. + for(std::vector::const_iterator + si = gt->ObjectSources.begin(); + si != gt->ObjectSources.end(); ++si) + { + cmSourceFile* sf = *si; + std::string objectName = + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); + objectName += ".obj"; + if(counts[cmSystemTools::LowerCase(objectName)] > 1) + { + gt->ExplicitObjectName.insert(sf); + objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max); + } + gt->Objects[sf] = objectName; + } +} + +//---------------------------------------------------------------------------- bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, const std::string& regKeyBase, std::string& nextAvailableSubKeyName); diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index bc96f4e..b62ba22 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -97,6 +97,8 @@ protected: typedef std::map UtilityDependsMap; UtilityDependsMap UtilityDepends; private: + void ComputeTargetObjects(cmGeneratorTarget* gt) const; + void FollowLinkDepends(cmTarget* target, std::set& linked); class TargetSetMap: public std::map {}; diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 678c5bf..8f5f111 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -15,6 +15,7 @@ #include "cmSystemTools.h" #include "cmSourceFile.h" #include "cmCacheManager.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #include "cmComputeLinkInformation.h" @@ -336,9 +337,6 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, } } - // Compute which sources need unique object computation. - this->ComputeObjectNameRequirements(classes); - // Write the DSP file's header. this->WriteDSPHeader(fout, libName, target, sourceGroups); @@ -358,6 +356,8 @@ void cmLocalVisualStudio6Generator ::WriteGroup(const cmSourceGroup *sg, cmTarget& target, std::ostream &fout, const char *libName) { + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); const std::vector &sourceFiles = sg->GetSourceFiles(); // If the group is empty, don't write it at all. @@ -374,28 +374,6 @@ void cmLocalVisualStudio6Generator this->WriteDSPBeginGroup(fout, name.c_str(), ""); } - // Compute the maximum length configuration name. - std::string config_max; - for(std::vector::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) - { - // Strip the subdirectory name out of the configuration name. - std::string config = this->GetConfigName(*i); - if(config.size() > config_max.size()) - { - config_max = config; - } - } - - // Compute the maximum length full path to the intermediate - // files directory for any configuration. This is used to construct - // object file names that do not produce paths that are too long. - std::string dir_max; - dir_max += this->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += config_max; - dir_max += "/"; - // Loop through each source in the source group. for(std::vector::const_iterator sf = sourceFiles.begin(); sf != sourceFiles.end(); ++sf) @@ -406,11 +384,9 @@ void cmLocalVisualStudio6Generator std::string compileFlags; std::vector depends; std::string objectNameDir; - if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end()) + if(gt->ExplicitObjectName.find(*sf) != gt->ExplicitObjectName.end()) { - objectNameDir = - cmSystemTools::GetFilenamePath( - this->GetObjectFileNameWithoutTarget(*(*sf), dir_max)); + objectNameDir = cmSystemTools::GetFilenamePath(gt->Objects[*sf]); } // Add per-source file flags. @@ -1795,6 +1771,36 @@ cmLocalVisualStudio6Generator return ""; } +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio6Generator +::ComputeLongestObjectDirectory(cmTarget&) const +{ + // Compute the maximum length configuration name. + std::string config_max; + for(std::vector::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) + { + // Strip the subdirectory name out of the configuration name. + std::string config = this->GetConfigName(*i); + if(config.size() > config_max.size()) + { + config_max = config; + } + } + + // Compute the maximum length full path to the intermediate + // files directory for any configuration. This is used to construct + // object file names that do not produce paths that are too long. + std::string dir_max; + dir_max += this->Makefile->GetCurrentOutputDirectory(); + dir_max += "/"; + dir_max += config_max; + dir_max += "/"; + return dir_max; +} + std::string cmLocalVisualStudio6Generator ::GetConfigName(std::string const& configuration) const diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 4e588c3..d36d633 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -50,6 +50,7 @@ public: void SetBuildType(BuildType, const char* libName, cmTarget&); virtual std::string GetTargetDirectory(cmTarget const& target) const; + virtual std::string ComputeLongestObjectDirectory(cmTarget&) const; private: std::string DSPHeaderTemplate; std::string DSPFooterTemplate; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c5714cc..ee54433 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -17,6 +17,7 @@ #include "cmSystemTools.h" #include "cmSourceFile.h" #include "cmCacheManager.h" +#include "cmGeneratorTarget.h" #include "cmake.h" #include "cmComputeLinkInformation.h" @@ -1310,9 +1311,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, sourceGroup.AssignSource(*i); } - // Compute which sources need unique object computation. - this->ComputeObjectNameRequirements(classes); - // open the project this->WriteProjectStart(fout, libName, target, sourceGroups); // write the configuration information @@ -1352,8 +1350,7 @@ public: cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector* configs, - std::string const& dir_max); + std::vector* configs); std::map FileConfigMap; }; @@ -1361,13 +1358,14 @@ cmLocalVisualStudio7GeneratorFCInfo ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector* configs, - std::string const& dir_max) + std::vector* configs) { + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(&target); std::string objectName; - if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end()) + if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end()) { - objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max); + objectName = gt->Objects[&sf]; } // Compute per-source, per-config information. @@ -1478,11 +1476,11 @@ cmLocalVisualStudio7GeneratorFCInfo } } - -void cmLocalVisualStudio7Generator -::ComputeMaxDirectoryLength(std::string& maxdir, - cmTarget& target) -{ +//---------------------------------------------------------------------------- +std::string +cmLocalVisualStudio7Generator +::ComputeLongestObjectDirectory(cmTarget& target) const +{ std::vector *configs = static_cast (this->GlobalGenerator)->GetConfigurations(); @@ -1507,7 +1505,7 @@ void cmLocalVisualStudio7Generator dir_max += "/"; dir_max += config_max; dir_max += "/"; - maxdir = dir_max; + return dir_max; } void cmLocalVisualStudio7Generator @@ -1530,19 +1528,13 @@ void cmLocalVisualStudio7Generator this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } - // Compute the maximum length full path to the intermediate - // files directory for any configuration. This is used to construct - // object file names that do not produce paths that are too long. - std::string dir_max; - this->ComputeMaxDirectoryLength(dir_max, target); - // Loop through each source in the source group. std::string objectName; for(std::vector::const_iterator sf = sourceFiles.begin(); sf != sourceFiles.end(); ++sf) { std::string source = (*sf)->GetFullPath(); - FCInfo fcinfo(this, target, *(*sf), configs, dir_max); + FCInfo fcinfo(this, target, *(*sf), configs); if (source != libName || target.GetType() == cmTarget::UTILITY || target.GetType() == cmTarget::GLOBAL_TARGET ) diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 6ddf82a..9d3a9f2 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -60,11 +60,7 @@ public: virtual std::string GetTargetDirectory(cmTarget const&) const; cmSourceFile* CreateVCProjBuildRule(); void WriteStampFiles(); - // Compute the maximum length full path to the intermediate - // files directory for any configuration. This is used to construct - // object file names that do not produce paths that are too long. - void ComputeMaxDirectoryLength(std::string& maxdir, - cmTarget& target); + virtual std::string ComputeLongestObjectDirectory(cmTarget&) const; virtual void ReadAndStoreExternalGUID(const char* name, const char* path); diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index f389b35..4bcf4de 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -65,69 +65,6 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target, } //---------------------------------------------------------------------------- -bool cmLocalVisualStudioGenerator::SourceFileCompiles(const cmSourceFile* sf) -{ - // Identify the language of the source file. - if(const char* lang = this->GetSourceFileLanguage(*sf)) - { - // Check whether this source will actually be compiled. - return (!sf->GetCustomCommand() && - !sf->GetPropertyAsBool("HEADER_FILE_ONLY") && - !sf->GetPropertyAsBool("EXTERNAL_OBJECT")); - } - else - { - // Unknown source file language. Assume it will not be compiled. - return false; - } -} - -//---------------------------------------------------------------------------- -void -cmLocalVisualStudioGenerator::ComputeObjectNameRequirements( - std::vector const& sources - ) -{ - // Clear the current set of requirements. - this->NeedObjectName.clear(); - - // Count the number of object files with each name. Note that - // windows file names are not case sensitive. - std::map counts; - for(std::vector::const_iterator s = sources.begin(); - s != sources.end(); ++s) - { - const cmSourceFile* sf = *s; - if(this->SourceFileCompiles(sf)) - { - std::string objectName = cmSystemTools::LowerCase( - cmSystemTools::GetFilenameWithoutLastExtension( - sf->GetFullPath())); - objectName += ".obj"; - counts[objectName] += 1; - } - } - - // For all source files producing duplicate names we need unique - // object name computation. - for(std::vector::const_iterator s = sources.begin(); - s != sources.end(); ++s) - { - const cmSourceFile* sf = *s; - if(this->SourceFileCompiles(sf)) - { - std::string objectName = cmSystemTools::LowerCase( - cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())); - objectName += ".obj"; - if(counts[objectName] > 1) - { - this->NeedObjectName.insert(sf); - } - } - } -} - -//---------------------------------------------------------------------------- const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const { return ":VCReportError"; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index e58c757..410cc9a 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -56,6 +56,8 @@ public: /** Version of Visual Studio. */ VSVersion GetVersion() const { return this->Version; } + virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0; + protected: virtual const char* ReportErrorLabel() const; virtual bool CustomCommandUseLocal() const { return false; } @@ -64,12 +66,6 @@ protected: cmsys::auto_ptr MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran); - // Safe object file name generation. - void ComputeObjectNameRequirements(std::vector const&); - bool SourceFileCompiles(const cmSourceFile* sf); - std::set NeedObjectName; - friend class cmVisualStudio10TargetGenerator; - VSVersion Version; }; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9168818..b5794d6 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -72,8 +72,6 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->GlobalGenerator->CreateGUID(this->Name.c_str()); this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str()); this->Platform = gg->GetPlatformName(); - this->LocalGenerator - ->ComputeObjectNameRequirements(target->GetSourceFiles()); this->BuildFileStream = 0; } @@ -883,16 +881,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmSourceFile& sf = *source; cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - // Compute the maximum length full path to the intermediate - // files directory for any configuration. This is used to construct - // object file names that do not produce paths that are too long. - std::string dir_max; - lg->ComputeMaxDirectoryLength(dir_max, *this->Target); - std::string objectName; - if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end()) + if(this->GeneratorTarget->ExplicitObjectName.find(&sf) + != this->GeneratorTarget->ExplicitObjectName.end()) { - objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max); + objectName = this->GeneratorTarget->Objects[&sf]; } std::string flags; std::string defines; -- cgit v0.12 From 46f49406759423dcc6f4050c9ad83c7167bd4dfc Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 8 Mar 2012 10:13:30 -0500 Subject: Remove unused cmSourceGroup method The non-const GetSourceFiles method is not needed. --- Source/cmSourceGroup.cxx | 6 ------ Source/cmSourceGroup.h | 1 - 2 files changed, 7 deletions(-) diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index 19ae8fc..2b34f2b 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -120,12 +120,6 @@ const std::vector& cmSourceGroup::GetSourceFiles() const } //---------------------------------------------------------------------------- -std::vector& cmSourceGroup::GetSourceFiles() -{ - return this->SourceFiles; -} - -//---------------------------------------------------------------------------- void cmSourceGroup::AddChild(cmSourceGroup child) { this->Internal->GroupChildren.push_back(child); diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index 71ccb51..641dcbd 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -100,7 +100,6 @@ public: * source group. */ const std::vector& GetSourceFiles() const; - std::vector& GetSourceFiles(); std::vector const& GetGroupChildren() const; private: -- cgit v0.12 From 9c0a00d6dd6e7419eba61bcac30bdd0715b8b2cd Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 8 Mar 2012 16:18:55 -0500 Subject: Rename/constify build-time config placeholder lookup Rename cmGlobalGenerator::GetCMakeCFG{InitDirectory => IntDir} to have a shorter name without a typo. Add a 'const' qualifier since the method is only for lookup and never needs to modify anything. --- Source/cmGlobalGenerator.cxx | 2 +- Source/cmGlobalGenerator.h | 2 +- Source/cmGlobalVisualStudio10Generator.h | 2 +- Source/cmGlobalVisualStudio6Generator.h | 2 +- Source/cmGlobalVisualStudio7Generator.h | 2 +- Source/cmGlobalXCodeGenerator.cxx | 2 +- Source/cmGlobalXCodeGenerator.h | 2 +- Source/cmMakefile.cxx | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index d7ba8b6..545f9e8 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1769,7 +1769,7 @@ void cmGlobalGenerator::SetCMakeInstance(cmake* cm) void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) { cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); - const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory(); + const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND"); // CPack diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index e818e37..80b948b 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -184,7 +184,7 @@ public: const char* GetLanguageOutputExtension(cmSourceFile const&); ///! What is the configurations directory variable called? - virtual const char* GetCMakeCFGInitDirectory() { return "."; } + virtual const char* GetCMakeCFGIntDir() const { return "."; } /** Get whether the generator should use a script for link commands. */ bool GetUseLinkScript() const { return this->UseLinkScript; } diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 18b483d..750b89c 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -72,7 +72,7 @@ public: * Studio? */ virtual std::string GetUserMacrosRegKeyBase(); - virtual const char* GetCMakeCFGInitDirectory() + virtual const char* GetCMakeCFGIntDir() const { return "$(Configuration)";} bool Find64BitTools(cmMakefile* mf); protected: diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index 77d5370..da08a12 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -82,7 +82,7 @@ public: std::string& dir); ///! What is the configurations directory variable called? - virtual const char* GetCMakeCFGInitDirectory() { return "$(IntDir)"; } + virtual const char* GetCMakeCFGIntDir() const { return "$(IntDir)"; } protected: virtual const char* GetIDEVersion() { return "6.0"; } diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index adfb757..c92998e 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -87,7 +87,7 @@ public: std::string& dir); ///! What is the configurations directory variable called? - virtual const char* GetCMakeCFGInitDirectory() { return "$(OutDir)"; } + virtual const char* GetCMakeCFGIntDir() const { return "$(OutDir)"; } /** Return true if the target project file should have the option LinkLibraryDependencies and link to .sln dependencies. */ diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index e552928..a6a9200 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3283,7 +3283,7 @@ cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, } //---------------------------------------------------------------------------- -const char* cmGlobalXCodeGenerator::GetCMakeCFGInitDirectory() +const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const { return this->XcodeVersion >= 21 ? "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : "."; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 45f62eb..b9cf775 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -74,7 +74,7 @@ public: std::string& dir); ///! What is the configurations directory variable called? - virtual const char* GetCMakeCFGInitDirectory(); + virtual const char* GetCMakeCFGIntDir() const; void SetCurrentLocalGenerator(cmLocalGenerator*); diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index f90c35c..68a8272 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -945,7 +945,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector& outputs, outName += ".rule"; const char* dir = this->LocalGenerator->GetGlobalGenerator()-> - GetCMakeCFGInitDirectory(); + GetCMakeCFGIntDir(); if(dir && dir[0] == '$') { cmSystemTools::ReplaceString(outName, dir, @@ -2865,7 +2865,7 @@ void cmMakefile::EnableLanguage(std::vector const & lang, { this->AddDefinition("CMAKE_CFG_INTDIR", this->LocalGenerator->GetGlobalGenerator() - ->GetCMakeCFGInitDirectory()); + ->GetCMakeCFGIntDir()); this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this, optional); } -- cgit v0.12 From f737bd416a49d79db032f97c3046e7eccc6aaea9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 8 Mar 2012 16:32:03 -0500 Subject: Pre-compute and store target object directory in cmGeneratorTarget Add cmGeneratorTarget::ObjectDirectory member to hold the value. In ComputeTargetObjects set the value to the full path to the target object directory including any necessary placeholder for the configuration name. --- Source/cmGeneratorTarget.h | 5 +++++ Source/cmGlobalUnixMakefileGenerator3.cxx | 1 + Source/cmGlobalVisualStudioGenerator.cxx | 16 ++++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 2bfc037..b083ba1 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -43,6 +43,11 @@ public: std::map Objects; std::set ExplicitObjectName; + /** Full path with trailing slash to the top-level directory + holding object files for this target. Includes the build + time config name placeholder if needed for the generator. */ + std::string ObjectDirectory; + private: void ClassifySources(); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 059692e..9d8a02c 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -86,6 +86,7 @@ cmGlobalUnixMakefileGenerator3 dir_max += "/"; dir_max += gt->LocalGenerator->GetTargetDirectory(*target); dir_max += "/"; + gt->ObjectDirectory = dir_max; // Compute the name of each object file. for(std::vector::iterator diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index e5a9784..4b9e487 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -139,6 +139,22 @@ cmGlobalVisualStudioGenerator } gt->Objects[sf] = objectName; } + + std::string dir = gt->Makefile->GetCurrentOutputDirectory(); + dir += "/"; + std::string tgtDir = lg->GetTargetDirectory(*gt->Target); + if(!tgtDir.empty()) + { + dir += tgtDir; + dir += "/"; + } + const char* cd = this->GetCMakeCFGIntDir(); + if(cd && *cd) + { + dir += cd; + dir += "/"; + } + gt->ObjectDirectory = dir; } //---------------------------------------------------------------------------- -- cgit v0.12 From b87d7a60a0ed146b79c49baedb666db228d5a70f Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 10:47:40 -0400 Subject: Add OBJECT_LIBRARY target type This library type can compile sources to object files but does not link or archive them. It will be useful to reference from executable and normal library targets for direct inclusion of object files in them. Diagnose and reject the following as errors: * An OBJECT library may not be referenced in target_link_libraries. * An OBJECT library may contain only compiling sources and supporting headers and custom commands. Other source types that are not normally ignored are not allowed. * An OBJECT library may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands. * An OBJECT library may not be installed, exported, or imported. Some of these cases may be supported in the future but are not for now. Teach the VS generator that OBJECT_LIBRARY targets are "linkable" just like STATIC_LIBRARY targets for the LinkLibraryDependencies behavior. --- Source/cmAddLibraryCommand.cxx | 14 ++++++++++++++ Source/cmComputeLinkDepends.cxx | 13 +++++++++++++ Source/cmExportCommand.cxx | 8 ++++++++ Source/cmGeneratorTarget.cxx | 21 +++++++++++++++++++++ Source/cmGlobalVisualStudioGenerator.cxx | 8 +++++++- Source/cmInstallCommand.cxx | 11 ++++++++++- Source/cmInstallTargetGenerator.cxx | 1 + Source/cmLocalGenerator.cxx | 4 ++++ Source/cmMakefile.cxx | 13 ++++++++++++- Source/cmTarget.cxx | 2 ++ Source/cmTarget.h | 3 ++- Source/cmTargetLinkLibrariesCommand.cxx | 10 ++++++++++ 12 files changed, 104 insertions(+), 4 deletions(-) diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 9a776fb..c1d0e9d 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -64,6 +64,12 @@ bool cmAddLibraryCommand type = cmTarget::MODULE_LIBRARY; haveSpecifiedType = true; } + else if(libType == "OBJECT") + { + ++s; + type = cmTarget::OBJECT_LIBRARY; + haveSpecifiedType = true; + } else if(libType == "UNKNOWN") { ++s; @@ -118,6 +124,14 @@ bool cmAddLibraryCommand this->SetError("called with IMPORTED argument but no library type."); return false; } + if(type == cmTarget::OBJECT_LIBRARY) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The OBJECT library type may not be used for IMPORTED libraries." + ); + return true; + } // Make sure the target does not already exist. if(this->Makefile->FindTargetToUse(libName.c_str())) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index ddff2d9..055aab0 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -633,6 +633,19 @@ cmTarget* cmComputeLinkDepends::FindTargetToLink(int depender_index, tgt = 0; } + if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << this->Target->GetName() << "\" links to " + "OBJECT library \"" << tgt->GetName() << "\" but this is not " + "allowed. " + "One may link only to STATIC or SHARED libraries, or to executables " + "with the ENABLE_EXPORTS property set."; + this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + tgt = 0; + } + // Return the target found, if any. return tgt; } diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index cb614d4..1cc1754 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -124,6 +124,14 @@ bool cmExportCommand { targets.push_back(target); } + else if(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "given OBJECT library \"" << *currentTarget + << "\" which may not be exported."; + this->SetError(e.str().c_str()); + return false; + } else { cmOStringStream e; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index afb1f39..369eb5c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -29,6 +29,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) //---------------------------------------------------------------------------- void cmGeneratorTarget::ClassifySources() { + bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY; + std::vector badObjLib; std::vector const& sources = this->Target->GetSourceFiles(); for(std::vector::const_iterator si = sources.begin(); si != sources.end(); ++si) @@ -43,6 +45,7 @@ void cmGeneratorTarget::ClassifySources() else if(tsFlags.Type != cmTarget::SourceFileTypeNormal) { this->OSXContent.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY")) { @@ -51,10 +54,12 @@ void cmGeneratorTarget::ClassifySources() else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { this->ExternalObjects.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } else if(cmSystemTools::LowerCase(sf->GetExtension()) == "def") { this->ModuleDefinitionFile = sf->GetFullPath(); + if(isObjLib) { badObjLib.push_back(sf); } } else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str())) { @@ -69,6 +74,22 @@ void cmGeneratorTarget::ClassifySources() else { this->ExtraSources.push_back(sf); + if(isObjLib) { badObjLib.push_back(sf); } } } + + if(!badObjLib.empty()) + { + cmOStringStream e; + e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n"; + for(std::vector::iterator i = badObjLib.begin(); + i != badObjLib.end(); ++i) + { + e << " " << (*i)->GetLocation().GetName() << "\n"; + } + e << "but may contain only headers and sources that compile."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + } } diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 4b9e487..7da4f86 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -375,6 +375,12 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends() } //---------------------------------------------------------------------------- +static bool VSLinkable(cmTarget* t) +{ + return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY; +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) { if(this->VSTargetDepends.find(&target) != this->VSTargetDepends.end()) @@ -458,7 +464,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target) di != utilDepends.end(); ++di) { cmTarget* dep = *di; - if(allowLinkable || !dep->IsLinkable() || linked.count(dep)) + if(allowLinkable || !VSLinkable(dep) || linked.count(dep)) { // Direct dependency allowed. vsTargetDepend.insert(dep->GetName()); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index dca528d..c656487 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -357,7 +357,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) if(target->GetType() != cmTarget::EXECUTABLE && target->GetType() != cmTarget::STATIC_LIBRARY && target->GetType() != cmTarget::SHARED_LIBRARY && - target->GetType() != cmTarget::MODULE_LIBRARY) + target->GetType() != cmTarget::MODULE_LIBRARY && + target->GetType() != cmTarget::OBJECT_LIBRARY) { cmOStringStream e; e << "TARGETS given target \"" << (*targetIt) @@ -365,6 +366,14 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) this->SetError(e.str().c_str()); return false; } + else if(target->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "TARGETS given OBJECT library \"" << (*targetIt) + << "\" which may not be installed."; + this->SetError(e.str().c_str()); + return false; + } // Store the target in the list to be installed. targets.push_back(target); } diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index c74dda0..5f9b658 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -90,6 +90,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os, case cmTarget::STATIC_LIBRARY: type = cmInstallType_STATIC_LIBRARY; break; case cmTarget::SHARED_LIBRARY: type = cmInstallType_SHARED_LIBRARY; break; case cmTarget::MODULE_LIBRARY: type = cmInstallType_MODULE_LIBRARY; break; + case cmTarget::OBJECT_LIBRARY: case cmTarget::UTILITY: case cmTarget::GLOBAL_TARGET: case cmTarget::UNKNOWN_LIBRARY: diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 19537b5..ebfb586 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1904,6 +1904,10 @@ bool cmLocalGenerator::GetRealDependency(const char* inName, case cmTarget::UNKNOWN_LIBRARY: dep = target->GetLocation(config); return true; + case cmTarget::OBJECT_LIBRARY: + // An object library has no single file on which to depend. + // This was listed to get the target-level dependency. + return false; case cmTarget::UTILITY: case cmTarget::GLOBAL_TARGET: // A utility target has no file on which to depend. This was listed diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 68a8272..aba2e38 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -853,6 +853,14 @@ cmMakefile::AddCustomCommandToTarget(const char* target, cmTargets::iterator ti = this->Targets.find(target); if(ti != this->Targets.end()) { + if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Target \"" << target << "\" is an OBJECT library " + "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands."; + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } // Add the command to the appropriate build step for the target. std::vector no_output; cmCustomCommand cc(this, no_output, depends, @@ -1912,8 +1920,11 @@ cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type, // wrong type ? default to STATIC if ( (type != cmTarget::STATIC_LIBRARY) && (type != cmTarget::SHARED_LIBRARY) - && (type != cmTarget::MODULE_LIBRARY)) + && (type != cmTarget::MODULE_LIBRARY) + && (type != cmTarget::OBJECT_LIBRARY)) { + this->IssueMessage(cmake::INTERNAL_ERROR, + "cmMakefile::AddLibrary given invalid target type."); type = cmTarget::STATIC_LIBRARY; } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index e6be83a..9e86681 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -37,6 +37,8 @@ const char* cmTarget::GetTargetTypeName(TargetType targetType) return "MODULE_LIBRARY"; case cmTarget::SHARED_LIBRARY: return "SHARED_LIBRARY"; + case cmTarget::OBJECT_LIBRARY: + return "OBJECT_LIBRARY"; case cmTarget::EXECUTABLE: return "EXECUTABLE"; case cmTarget::UTILITY: diff --git a/Source/cmTarget.h b/Source/cmTarget.h index ff05cd3..e2502f0 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -59,7 +59,8 @@ class cmTarget public: cmTarget(); enum TargetType { EXECUTABLE, STATIC_LIBRARY, - SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET, + SHARED_LIBRARY, MODULE_LIBRARY, + OBJECT_LIBRARY, UTILITY, GLOBAL_TARGET, UNKNOWN_LIBRARY}; static const char* GetTargetTypeName(TargetType targetType); enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD }; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 36c4ca8..dbea1c3 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -84,6 +84,16 @@ bool cmTargetLinkLibrariesCommand return true; } + if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY) + { + cmOStringStream e; + e << "Object library target \"" << args[0] << "\" " + << "may not link to anything."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + cmSystemTools::SetFatalErrorOccured(); + return true; + } + // but we might not have any libs after variable expansion if(args.size() < 2) { -- cgit v0.12 From 3aa741acb6b47d83a0892ddf027ddb0abdc33e78 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 10:54:37 -0400 Subject: Build object library targets in Makefiles Treat OBJECT libraries as STATIC libraries but leave out the archive step. The object files will be left behind for reference by other targets later. --- Source/cmGlobalUnixMakefileGenerator3.cxx | 5 +++++ Source/cmLocalUnixMakefileGenerator3.cxx | 1 + Source/cmMakefileLibraryTargetGenerator.cxx | 26 +++++++++++++++++++++++++ Source/cmMakefileLibraryTargetGenerator.h | 1 + Source/cmMakefileTargetGenerator.cxx | 30 ++++++++++++++++++----------- Source/cmMakefileTargetGenerator.h | 3 +++ 6 files changed, 55 insertions(+), 11 deletions(-) diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 9d8a02c..e63de9c 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -411,6 +411,7 @@ void cmGlobalUnixMakefileGenerator3 (l->second.GetType() == cmTarget::STATIC_LIBRARY) || (l->second.GetType() == cmTarget::SHARED_LIBRARY) || (l->second.GetType() == cmTarget::MODULE_LIBRARY) || + (l->second.GetType() == cmTarget::OBJECT_LIBRARY) || (l->second.GetType() == cmTarget::UTILITY)) { std::string tname = lg->GetRelativeTargetDirectory(l->second); @@ -446,6 +447,7 @@ cmGlobalUnixMakefileGenerator3 (l->second.GetType() == cmTarget::STATIC_LIBRARY) || (l->second.GetType() == cmTarget::SHARED_LIBRARY) || (l->second.GetType() == cmTarget::MODULE_LIBRARY) || + (l->second.GetType() == cmTarget::OBJECT_LIBRARY) || (l->second.GetType() == cmTarget::UTILITY)) { // Add this to the list of depends rules in this directory. @@ -620,6 +622,7 @@ cmGlobalUnixMakefileGenerator3 (t->second.GetType() == cmTarget::STATIC_LIBRARY) || (t->second.GetType() == cmTarget::SHARED_LIBRARY) || (t->second.GetType() == cmTarget::MODULE_LIBRARY) || + (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || (t->second.GetType() == cmTarget::UTILITY))) { // Add a rule to build the target by name. @@ -706,6 +709,7 @@ cmGlobalUnixMakefileGenerator3 || (t->second.GetType() == cmTarget::STATIC_LIBRARY) || (t->second.GetType() == cmTarget::SHARED_LIBRARY) || (t->second.GetType() == cmTarget::MODULE_LIBRARY) + || (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || (t->second.GetType() == cmTarget::UTILITY))) { std::string makefileName; @@ -1015,6 +1019,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule (t->second.GetType() == cmTarget::STATIC_LIBRARY) || (t->second.GetType() == cmTarget::SHARED_LIBRARY) || (t->second.GetType() == cmTarget::MODULE_LIBRARY) || + (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || (t->second.GetType() == cmTarget::GLOBAL_TARGET) || (t->second.GetType() == cmTarget::UTILITY)) { diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index b991b25..a645303 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -358,6 +358,7 @@ void cmLocalUnixMakefileGenerator3 (t->second.GetType() == cmTarget::STATIC_LIBRARY) || (t->second.GetType() == cmTarget::SHARED_LIBRARY) || (t->second.GetType() == cmTarget::MODULE_LIBRARY) || + (t->second.GetType() == cmTarget::OBJECT_LIBRARY) || (t->second.GetType() == cmTarget::UTILITY)) { emitted.insert(t->second.GetName()); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index b4174cc..38aa59d 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -101,6 +101,9 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() this->WriteModuleLibraryRules(true); } break; + case cmTarget::OBJECT_LIBRARY: + this->WriteObjectLibraryRules(); + break; default: // If language is not known, this is an error. cmSystemTools::Error("Unknown Library Type"); @@ -122,6 +125,29 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles() } //---------------------------------------------------------------------------- +void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules() +{ + std::vector commands; + std::vector depends; + + // Add post-build rules. + this->LocalGenerator-> + AppendCustomCommands(commands, this->Target->GetPostBuildCommands(), + this->Target); + + // Depend on the object files. + this->AppendObjectDepends(depends); + + // Write the rule. + this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, + this->Target->GetName(), + depends, commands, true); + + // Write the main driver rule to build everything in this target. + this->WriteTargetDriverRule(this->Target->GetName(), false); +} + +//---------------------------------------------------------------------------- void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules() { const char* linkLanguage = diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h index f3c47db..e6a5867 100644 --- a/Source/cmMakefileLibraryTargetGenerator.h +++ b/Source/cmMakefileLibraryTargetGenerator.h @@ -25,6 +25,7 @@ public: virtual void WriteRuleFiles(); protected: + void WriteObjectLibraryRules(); void WriteStaticLibraryRules(); void WriteSharedLibraryRules(bool relink); void WriteModuleLibraryRules(bool relink); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index fc55f1e..d0cfd99 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -65,6 +65,7 @@ cmMakefileTargetGenerator::New(cmTarget *tgt) case cmTarget::STATIC_LIBRARY: case cmTarget::SHARED_LIBRARY: case cmTarget::MODULE_LIBRARY: + case cmTarget::OBJECT_LIBRARY: result = new cmMakefileLibraryTargetGenerator(tgt); break; case cmTarget::UTILITY: @@ -1596,7 +1597,7 @@ void cmMakefileTargetGenerator //---------------------------------------------------------------------------- void cmMakefileTargetGenerator -::AppendLinkDepends(std::vector& depends) +::AppendObjectDepends(std::vector& depends) { // Add dependencies on the compiled object files. std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath(); @@ -1609,12 +1610,27 @@ void cmMakefileTargetGenerator depends.push_back(objTarget); } - // Add dependencies on targets that must be built first. - this->AppendTargetDepends(depends); + // Add dependencies on the external object files. + for(std::vector::const_iterator obj + = this->ExternalObjects.begin(); + obj != this->ExternalObjects.end(); ++obj) + { + depends.push_back(*obj); + } // Add a dependency on the rule file itself. this->LocalGenerator->AppendRuleDepend(depends, this->BuildFileNameFull.c_str()); +} + +//---------------------------------------------------------------------------- +void cmMakefileTargetGenerator +::AppendLinkDepends(std::vector& depends) +{ + this->AppendObjectDepends(depends); + + // Add dependencies on targets that must be built first. + this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) @@ -1622,14 +1638,6 @@ void cmMakefileTargetGenerator depends.push_back(this->GeneratorTarget->ModuleDefinitionFile); } - // Add dependencies on the external object files. - for(std::vector::const_iterator obj - = this->ExternalObjects.begin(); - obj != this->ExternalObjects.end(); ++obj) - { - depends.push_back(*obj); - } - // Add user-specified dependencies. if(const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS")) diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index dbc607a..e1e554b 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -118,6 +118,9 @@ protected: // append intertarget dependencies void AppendTargetDepends(std::vector& depends); + // Append object file dependencies. + void AppendObjectDepends(std::vector& depends); + // Append link rule dependencies (objects, etc.). void AppendLinkDepends(std::vector& depends); -- cgit v0.12 From 3a53005f7dd5e582b855ef1f3c0e6814ce7d024a Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 10:55:07 -0400 Subject: Build object library targets in VS Treat OBJECT libraries as STATIC libraries. The VS project file format provides no way to avoid running the librarian so hide the resulting .lib away next to the object files as it should never be referenced. The object files will be left behind for reference by other targets later. --- Source/cmLocalVisualStudio6Generator.cxx | 41 +++++++++++++++++++++++------- Source/cmLocalVisualStudio7Generator.cxx | 18 +++++++++++++ Source/cmVisualStudio10TargetGenerator.cxx | 38 ++++++++++++++++++--------- 3 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 8f5f111..f53ad0e 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -127,6 +127,7 @@ void cmLocalVisualStudio6Generator::OutputDSPFile() switch(l->second.GetType()) { case cmTarget::STATIC_LIBRARY: + case cmTarget::OBJECT_LIBRARY: this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second); break; case cmTarget::SHARED_LIBRARY: @@ -1240,8 +1241,18 @@ void cmLocalVisualStudio6Generator outputNameMinSizeRel = target.GetFullName("MinSizeRel"); outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo"); } + else if(target.GetType() == cmTarget::OBJECT_LIBRARY) + { + outputName = target.GetName(); + outputName += ".lib"; + outputNameDebug = outputName; + outputNameRelease = outputName; + outputNameMinSizeRel = outputName; + outputNameRelWithDebInfo = outputName; + } // Compute the output directory for the target. + std::string outputDirOld; std::string outputDirDebug; std::string outputDirRelease; std::string outputDirMinSizeRel; @@ -1251,6 +1262,11 @@ void cmLocalVisualStudio6Generator target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY) { +#ifdef CM_USE_OLD_VS6 + outputDirOld = + removeQuotes(this->ConvertToOptionallyRelativeOutputPath + (target.GetDirectory().c_str())); +#endif outputDirDebug = removeQuotes(this->ConvertToOptionallyRelativeOutputPath( target.GetDirectory("Debug").c_str())); @@ -1264,6 +1280,14 @@ void cmLocalVisualStudio6Generator removeQuotes(this->ConvertToOptionallyRelativeOutputPath( target.GetDirectory("RelWithDebInfo").c_str())); } + else if(target.GetType() == cmTarget::OBJECT_LIBRARY) + { + std::string outputDir = cmake::GetCMakeFilesDirectoryPostSlash(); + outputDirDebug = outputDir + "Debug"; + outputDirRelease = outputDir + "Release"; + outputDirMinSizeRel = outputDir + "MinSizeRel"; + outputDirRelWithDebInfo = outputDir + "RelWithDebInfo"; + } // Compute the proper link information for the target. std::string optionsDebug; @@ -1432,7 +1456,8 @@ void cmLocalVisualStudio6Generator libnameExports.c_str()); cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG", mfcFlag); - if(target.GetType() == cmTarget::STATIC_LIBRARY ) + if(target.GetType() == cmTarget::STATIC_LIBRARY || + target.GetType() == cmTarget::OBJECT_LIBRARY) { cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_DEBUG", staticLibOptionsDebug.c_str()); @@ -1531,7 +1556,7 @@ void cmLocalVisualStudio6Generator (exePath.c_str())).c_str()); #endif - if(targetBuilds) + if(targetBuilds || target.GetType() == cmTarget::OBJECT_LIBRARY) { cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_DEBUG", outputDirDebug.c_str()); @@ -1541,13 +1566,11 @@ void cmLocalVisualStudio6Generator outputDirMinSizeRel.c_str()); cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_RELWITHDEBINFO", outputDirRelWithDebInfo.c_str()); -#ifdef CM_USE_OLD_VS6 - std::string outPath = target.GetDirectory(); - cmSystemTools::ReplaceString - (line, "OUTPUT_DIRECTORY", - removeQuotes(this->ConvertToOptionallyRelativeOutputPath - (outPath.c_str())).c_str()); -#endif + if(!outputDirOld.empty()) + { + cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY", + outputDirOld.c_str()); + } } cmSystemTools::ReplaceString(line, diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index ee54433..2f145a6 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -642,6 +642,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, bool targetBuilds = true; switch(target.GetType()) { + case cmTarget::OBJECT_LIBRARY: + targetBuilds = false; // TODO: PDB for object library? case cmTarget::STATIC_LIBRARY: projectType = "typeStaticLibrary"; configType = "4"; @@ -1001,6 +1003,22 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } switch(target.GetType()) { + case cmTarget::OBJECT_LIBRARY: + { + std::string libpath = this->GetTargetDirectory(target); + libpath += "/"; + libpath += configName; + libpath += "/"; + libpath += target.GetName(); + libpath += ".lib"; + const char* tool = + this->FortranProject? "VFLibrarianTool":"VCLibrarianTool"; + fout << "\t\t\tConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n"; + break; + } case cmTarget::STATIC_LIBRARY: { std::string targetNameFull = target.GetFullName(configName); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index b5794d6..db37dfc 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -148,7 +148,7 @@ void cmVisualStudio10TargetGenerator::Generate() this->Target->SetProperty("GENERATOR_FILE_NAME",this->Name.c_str()); this->Target->SetProperty("GENERATOR_FILE_NAME_EXT", ".vcxproj"); - if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY) + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { if(!this->ComputeClOptions()) { @@ -359,6 +359,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() case cmTarget::MODULE_LIBRARY: configType += "DynamicLibrary"; break; + case cmTarget::OBJECT_LIBRARY: case cmTarget::STATIC_LIBRARY: configType += "StaticLibrary"; break; @@ -389,7 +390,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() mfcLine += useOfMfcValue + "\n"; this->WriteString(mfcLine.c_str(), 2); - if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY && + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY && this->ClOptions[*i]->UsingUnicode() || this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) { @@ -1006,20 +1007,29 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() } else { - std::string targetNameFull = - this->Target->GetFullName(config->c_str()); std::string intermediateDir = this->LocalGenerator-> GetTargetDirectory(*this->Target); intermediateDir += "/"; intermediateDir += *config; intermediateDir += "/"; + std::string outDir; + std::string targetNameFull; + if(ttype == cmTarget::OBJECT_LIBRARY) + { + outDir = intermediateDir; + targetNameFull = this->Target->GetName(); + targetNameFull += ".lib"; + } + else + { + outDir = this->Target->GetDirectory(config->c_str()) + "/"; + targetNameFull = this->Target->GetFullName(config->c_str()); + } this->ConvertToWindowsSlash(intermediateDir); - std::string outDir = this->Target->GetDirectory(config->c_str()); this->ConvertToWindowsSlash(outDir); this->WritePlatformConfigTag("OutDir", config->c_str(), 3); *this->BuildFileStream << outDir - << "\\" << "\n"; this->WritePlatformConfigTag("IntDir", config->c_str(), 3); @@ -1253,11 +1263,15 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( *this->BuildFileStream << configName << "\n"; this->WriteString("$(IntDir)\n", 3); - this->WriteString("", 3); - *this->BuildFileStream << this->Target->GetDirectory(configName.c_str()) - << "/" - << this->Target->GetPDBName(configName.c_str()) - << "\n"; + if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY) + { + // TODO: PDB for object library? + this->WriteString("", 3); + *this->BuildFileStream << this->Target->GetDirectory(configName.c_str()) + << "/" + << this->Target->GetPDBName(configName.c_str()) + << "\n"; + } this->WriteString("\n", 2); } @@ -1568,7 +1582,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1); *this->BuildFileStream << "\n"; // output cl compile flags - if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY) + if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY) { this->WriteClOptions(*i, includes); // output rc compile flags -- cgit v0.12 From 34e4985eed3589a4f7ad7dfc14a7a8aa10c8ff97 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 14 Mar 2012 17:46:56 -0400 Subject: Xcode: Re-factor code into GetObjectsNormalDirectory method ...in preparation for calling it from more than one location. Required to support OBJECT_LIBRARY targets in Xcode. --- Source/cmGlobalXCodeGenerator.cxx | 31 ++++++++++++++++++++++--------- Source/cmGlobalXCodeGenerator.h | 5 +++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index a6a9200..7660ffa 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3046,6 +3046,26 @@ void cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- +std::string +cmGlobalXCodeGenerator::GetObjectsNormalDirectory( + const std::string &projName, + const std::string &configName, + const cmTarget *t) const +{ + std::string dir = + t->GetMakefile()->GetCurrentOutputDirectory(); + dir += "/"; + dir += projName; + dir += ".build/"; + dir += configName; + dir += "/"; + dir += t->GetName(); + dir += ".build/Objects-normal/"; + + return dir; +} + +//---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector& targets) @@ -3169,15 +3189,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // then remove those exectuables as well if(this->Architectures.size() > 1) { - std::string universal = - t->GetMakefile()->GetCurrentOutputDirectory(); - universal += "/"; - universal += this->CurrentProject; - universal += ".build/"; - universal += configName; - universal += "/"; - universal += t->GetName(); - universal += ".build/Objects-normal/"; + std::string universal = this->GetObjectsNormalDirectory( + this->CurrentProject, configName, t); for( std::vector::iterator arch = this->Architectures.begin(); arch != this->Architectures.end(); ++arch) diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index b9cf775..393cd47 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -200,6 +200,11 @@ protected: std::vector XCodeObjects; cmXCodeObject* RootObject; private: + std::string GetObjectsNormalDirectory( + const std::string &projName, + const std::string &configName, + const cmTarget *t) const; + void addObject(cmXCodeObject *obj); std::string PostBuildMakeTarget(std::string const& tName, std::string const& configName); -- cgit v0.12 From c403f27a2de2327f5c895972e16a81d80968c40c Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 14:40:58 -0400 Subject: Add $ expression to use an object library For now do not allow an OBJECT library to reference other object libraries. Teach cmTarget::ComputeLinkImplementation to include the languages of object libraries used by a target. --- Source/cmGeneratorTarget.cxx | 74 ++++++++++++++++++++++++++++++ Source/cmGeneratorTarget.h | 5 ++ Source/cmLocalVisualStudio6Generator.cxx | 36 ++++++++++++++- Source/cmLocalVisualStudio6Generator.h | 2 + Source/cmLocalVisualStudio7Generator.cxx | 72 +++++++++++++++++++++++++++-- Source/cmMakefileTargetGenerator.cxx | 3 ++ Source/cmTarget.cxx | 42 ++++++++++++++++- Source/cmTarget.h | 7 +++ Source/cmVisualStudio10TargetGenerator.cxx | 44 ++++++++++++++++++ 9 files changed, 278 insertions(+), 7 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 369eb5c..c9911a5 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -24,6 +24,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t) this->LocalGenerator = this->Makefile->GetLocalGenerator(); this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); this->ClassifySources(); + this->LookupObjectLibraries(); } //---------------------------------------------------------------------------- @@ -93,3 +94,76 @@ void cmGeneratorTarget::ClassifySources() this->Target->GetBacktrace()); } } + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::LookupObjectLibraries() +{ + std::vector const& objLibs = + this->Target->GetObjectLibraries(); + for(std::vector::const_iterator oli = objLibs.begin(); + oli != objLibs.end(); ++oli) + { + std::string const& objLibName = *oli; + if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str())) + { + if(objLib->GetType() == cmTarget::OBJECT_LIBRARY) + { + if(this->Target->GetType() != cmTarget::EXECUTABLE && + this->Target->GetType() != cmTarget::STATIC_LIBRARY && + this->Target->GetType() != cmTarget::SHARED_LIBRARY && + this->Target->GetType() != cmTarget::MODULE_LIBRARY) + { + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, + "Only executables and non-OBJECT libraries may " + "reference target objects.", + this->Target->GetBacktrace()); + return; + } + this->Target->AddUtility(objLib->GetName()); + this->ObjectLibraries.push_back(objLib); + } + else + { + cmOStringStream e; + e << "Objects of target \"" << objLibName + << "\" referenced but is not an OBJECT library."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + return; + } + } + else + { + cmOStringStream e; + e << "Objects of target \"" << objLibName + << "\" referenced but no such target exists."; + this->GlobalGenerator->GetCMakeInstance() + ->IssueMessage(cmake::FATAL_ERROR, e.str(), + this->Target->GetBacktrace()); + return; + } + } +} + +//---------------------------------------------------------------------------- +void cmGeneratorTarget::UseObjectLibraries(std::vector& objs) +{ + for(std::vector::const_iterator + ti = this->ObjectLibraries.begin(); + ti != this->ObjectLibraries.end(); ++ti) + { + cmTarget* objLib = *ti; + cmGeneratorTarget* ogt = + this->GlobalGenerator->GetGeneratorTarget(objLib); + for(std::vector::const_iterator + si = ogt->ObjectSources.begin(); + si != ogt->ObjectSources.end(); ++si) + { + std::string obj = ogt->ObjectDirectory; + obj += ogt->Objects[*si]; + objs.push_back(obj); + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index b083ba1..6319d82 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -48,8 +48,13 @@ public: time config name placeholder if needed for the generator. */ std::string ObjectDirectory; + std::vector ObjectLibraries; + + void UseObjectLibraries(std::vector& objs); + private: void ClassifySources(); + void LookupObjectLibraries(); cmGeneratorTarget(cmGeneratorTarget const&); void operator=(cmGeneratorTarget const&); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index f53ad0e..5b99dfd 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -1428,6 +1428,16 @@ void cmLocalVisualStudio6Generator staticLibOptionsRelWithDebInfo += " "; staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo; } + std::string objects; + this->OutputObjects(target, "LIB", objects); + if(!objects.empty()) + { + objects = "\n" + objects; + staticLibOptionsDebug += objects; + staticLibOptionsRelease += objects; + staticLibOptionsMinSizeRel += objects; + staticLibOptionsRelWithDebInfo += objects; + } } // Add the export symbol definition for shared library objects. @@ -1587,7 +1597,7 @@ void cmLocalVisualStudio6Generator std::string flagsDebug = " "; std::string flagsDebugRel = " "; if(target.GetType() >= cmTarget::EXECUTABLE && - target.GetType() <= cmTarget::MODULE_LIBRARY) + target.GetType() <= cmTarget::OBJECT_LIBRARY) { const char* linkLanguage = target.GetLinkerLanguage(); if(!linkLanguage) @@ -1742,6 +1752,8 @@ void cmLocalVisualStudio6Generator ItemVector const& linkLibs = cli.GetItems(); std::vector const& linkDirs = cli.GetDirectories(); + this->OutputObjects(target, "LINK", options); + // Build the link options code. for(std::vector::const_iterator d = linkDirs.begin(); d != linkDirs.end(); ++d) @@ -1786,6 +1798,28 @@ void cmLocalVisualStudio6Generator } } +//---------------------------------------------------------------------------- +void cmLocalVisualStudio6Generator +::OutputObjects(cmTarget& target, const char* tool, + std::string& options) +{ + // VS 6 does not support per-config source locations so we + // list object library content on the link line instead. + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + std::vector objs; + gt->UseObjectLibraries(objs); + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + options += "# ADD "; + options += tool; + options += "32 "; + options += this->ConvertToOptionallyRelativeOutputPath(oi->c_str()); + options += "\n"; + } +} + std::string cmLocalVisualStudio6Generator ::GetTargetDirectory(cmTarget const&) const diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index d36d633..a680633 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -87,6 +87,8 @@ private: void ComputeLinkOptions(cmTarget& target, const char* configName, const std::string extraOptions, std::string& options); + void OutputObjects(cmTarget& target, const char* tool, + std::string& options); std::string GetTargetIncludeOptions(cmTarget &target); std::vector Configurations; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2f145a6..363d370 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -39,6 +39,7 @@ public: LocalGenerator(e) {} typedef cmComputeLinkInformation::ItemVector ItemVector; void OutputLibraries(std::ostream& fout, ItemVector const& libs); + void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0); private: cmLocalVisualStudio7Generator* LocalGenerator; }; @@ -1033,6 +1034,15 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\tGetVersion() < VS8) + { + cmOStringStream libdeps; + this->Internal->OutputObjects(libdeps, &target); + if(!libdeps.str().empty()) + { + fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n"; + } + } std::string libflags; if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS")) { @@ -1093,8 +1103,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()) - << " "; + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < VS8) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; temp = target.GetDirectory(configName); @@ -1174,8 +1188,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()) - << " "; + << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + if(this->GetVersion() < VS8) + { + this->Internal->OutputObjects(fout, &target, " "); + } + fout << " "; this->Internal->OutputLibraries(fout, cli.GetItems()); fout << "\"\n"; temp = target.GetDirectory(configName); @@ -1263,6 +1281,30 @@ cmLocalVisualStudio7GeneratorInternals //---------------------------------------------------------------------------- void +cmLocalVisualStudio7GeneratorInternals +::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep) +{ + // VS < 8 does not support per-config source locations so we + // list object library content on the link line instead. + cmLocalVisualStudio7Generator* lg = this->LocalGenerator; + cmGeneratorTarget* gt = + lg->GetGlobalGenerator()->GetGeneratorTarget(t); + std::vector objs; + gt->UseObjectLibraries(objs); + const char* sep = isep? isep : ""; + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string rel = lg->Convert(oi->c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); + fout << sep << lg->ConvertToXMLOutputPath(rel.c_str()); + sep = " "; + } +} + +//---------------------------------------------------------------------------- +void cmLocalVisualStudio7Generator ::OutputLibraryDirectories(std::ostream& fout, std::vector const& dirs) @@ -1344,7 +1386,27 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, this->WriteGroup(&sg, target, fout, libName, configs); } - //} + if(this->GetVersion() >= VS8) + { + // VS >= 8 support per-config source locations so we + // list object library content as external objects. + cmGeneratorTarget* gt = + this->GlobalGenerator->GetGeneratorTarget(&target); + std::vector objs; + gt->UseObjectLibraries(objs); + if(!objs.empty()) + { + // TODO: Separate sub-filter for each object library used? + fout << "\t\t\n"; + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str()); + fout << "\t\t\t\n"; + } + fout << "\t\t\n"; + } + } fout << "\t\n"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d0cfd99..a0e0481 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -174,6 +174,9 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // Generate this object file's rule file. this->WriteObjectRuleFiles(**si); } + + // Add object library contents as external objects. + this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects); } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 9e86681..708a989 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1724,7 +1724,15 @@ void cmTarget::AddSources(std::vector const& srcs) for(std::vector::const_iterator i = srcs.begin(); i != srcs.end(); ++i) { - this->AddSource(i->c_str()); + const char* src = i->c_str(); + if(src[0] == '$' && src[1] == '<') + { + this->ProcessSourceExpression(*i); + } + else + { + this->AddSource(src); + } } } @@ -1743,6 +1751,24 @@ cmSourceFile* cmTarget::AddSource(const char* s) } //---------------------------------------------------------------------------- +void cmTarget::ProcessSourceExpression(std::string const& expr) +{ + if(strncmp(expr.c_str(), "$') + { + std::string objLibName = expr.substr(17, expr.size()-18); + this->ObjectLibraries.push_back(objLibName); + } + else + { + cmOStringStream e; + e << "Unrecognized generator expression:\n" + << " " << expr; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + +//---------------------------------------------------------------------------- struct cmTarget::SourceFileFlags cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) { @@ -4542,7 +4568,21 @@ void cmTarget::ComputeLinkImplementation(const char* config, // This target needs runtime libraries for its source languages. std::set languages; + // Get languages used in our source files. this->GetLanguages(languages); + // Get languages used in object library sources. + for(std::vector::iterator i = this->ObjectLibraries.begin(); + i != this->ObjectLibraries.end(); ++i) + { + if(cmTarget* objLib = this->Makefile->FindTargetToUse(i->c_str())) + { + if(objLib->GetType() == cmTarget::OBJECT_LIBRARY) + { + objLib->GetLanguages(languages); + } + } + } + // Copy the set of langauges to the link implementation. for(std::set::iterator li = languages.begin(); li != languages.end(); ++li) { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index e2502f0..d41c827 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -117,6 +117,10 @@ public: */ std::vector const& GetSourceFiles(); void AddSourceFile(cmSourceFile* sf); + std::vector const& GetObjectLibraries() const + { + return this->ObjectLibraries; + } /** Get sources that must be built before the given source. */ std::vector const* GetSourceDepends(cmSourceFile* sf); @@ -549,6 +553,7 @@ private: std::vector PostBuildCommands; TargetType TargetTypeValue; std::vector SourceFiles; + std::vector ObjectLibraries; LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType PrevLinkedLibraries; bool LinkLibrariesAnalyzed; @@ -590,6 +595,8 @@ private: void MaybeInvalidatePropertyCache(const char* prop); + void ProcessSourceExpression(std::string const& expr); + // The cmMakefile instance that owns this target. This should // always be set. cmMakefile* Makefile; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index db37dfc..054b86b 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -635,6 +635,25 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteGroupSources("Midl", idls, sourceGroups); this->WriteGroupSources("CustomBuild", customBuild, sourceGroups); + // Add object library contents as external objects. + std::vector objs; + this->GeneratorTarget->UseObjectLibraries(objs); + if(!objs.empty()) + { + this->WriteString("\n", 1); + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + this->WriteString("ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\">\n"; + this->WriteString("Object Libraries\n", 3); + this->WriteString("\n", 2); + } + this->WriteString("\n", 1); + } + this->WriteString("\n", 1); for(std::set::iterator g = groupsUsed.begin(); g != groupsUsed.end(); ++g) @@ -658,6 +677,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("\n", 2); } } + if(!objs.empty()) + { + this->WriteString("\n", 2); + std::string guidName = "SG_Filter_Object Libraries"; + this->GlobalGenerator->CreateGUID(guidName.c_str()); + this->WriteString("", 3); + std::string guid = + this->GlobalGenerator->GetGUID(guidName.c_str()); + (*this->BuildFileStream) << "{" << guid << "}" + << "\n"; + this->WriteString("\n", 2); + } this->WriteString("\n", 1); this->WriteGroupSources("None", none, sourceGroups); this->WriteString("\n", 0); @@ -873,6 +904,19 @@ void cmVisualStudio10TargetGenerator::WriteCLSources() (*this->BuildFileStream ) << " />\n"; } } + + // Add object library contents as external objects. + std::vector objs; + this->GeneratorTarget->UseObjectLibraries(objs); + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + this->WriteString("ConvertToWindowsSlash(obj); + (*this->BuildFileStream ) << obj << "\" />\n"; + } + this->WriteString("\n", 1); } -- cgit v0.12 From 69d3d1835c5f4bdf9fbe5e920517a74d82482455 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 14:41:34 -0400 Subject: Test OBJECT library success cases Add "ObjectLibrary" test to build and use OBJECT libraries. Build multiple object libraries in separate directories with different flags. Use a custom command to generate a source file in one OBJECT library. Reference the OBJECT libraries for inclusion in a STATIC library, a SHARED library, and an EXECUTABLE target. Use the static and shared libraries each in executables that end up using the object library symbols. Verify that object library symbols are exported from the shared library. --- Tests/CMakeLists.txt | 1 + Tests/ObjectLibrary/A/CMakeLists.txt | 17 +++++++++++++++++ Tests/ObjectLibrary/A/a.h | 6 ++++++ Tests/ObjectLibrary/A/a1.c.in | 2 ++ Tests/ObjectLibrary/A/a2.c | 2 ++ Tests/ObjectLibrary/B/CMakeLists.txt | 15 +++++++++++++++ Tests/ObjectLibrary/B/b.h | 11 +++++++++++ Tests/ObjectLibrary/B/b1.c | 2 ++ Tests/ObjectLibrary/B/b1_vs6.c | 1 + Tests/ObjectLibrary/B/b2.c | 2 ++ Tests/ObjectLibrary/B/b2_vs6.c | 1 + Tests/ObjectLibrary/CMakeLists.txt | 16 ++++++++++++++++ Tests/ObjectLibrary/c.c | 19 +++++++++++++++++++ Tests/ObjectLibrary/main.c | 16 ++++++++++++++++ 14 files changed, 111 insertions(+) create mode 100644 Tests/ObjectLibrary/A/CMakeLists.txt create mode 100644 Tests/ObjectLibrary/A/a.h create mode 100644 Tests/ObjectLibrary/A/a1.c.in create mode 100644 Tests/ObjectLibrary/A/a2.c create mode 100644 Tests/ObjectLibrary/B/CMakeLists.txt create mode 100644 Tests/ObjectLibrary/B/b.h create mode 100644 Tests/ObjectLibrary/B/b1.c create mode 100644 Tests/ObjectLibrary/B/b1_vs6.c create mode 100644 Tests/ObjectLibrary/B/b2.c create mode 100644 Tests/ObjectLibrary/B/b2_vs6.c create mode 100644 Tests/ObjectLibrary/CMakeLists.txt create mode 100644 Tests/ObjectLibrary/c.c create mode 100644 Tests/ObjectLibrary/main.c diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index cf4dc44..7baed2c 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -199,6 +199,7 @@ IF(BUILD_TESTING) ADD_TEST_MACRO(CxxOnly CxxOnly) ADD_TEST_MACRO(IPO COnly/COnly) ADD_TEST_MACRO(OutDir runtime/OutDir) + ADD_TEST_MACRO(ObjectLibrary UseCshared) ADD_TEST_MACRO(NewlineArgs NewlineArgs) ADD_TEST_MACRO(SetLang SetLang) ADD_TEST_MACRO(ExternalOBJ ExternalOBJ) diff --git a/Tests/ObjectLibrary/A/CMakeLists.txt b/Tests/ObjectLibrary/A/CMakeLists.txt new file mode 100644 index 0000000..e0a620e --- /dev/null +++ b/Tests/ObjectLibrary/A/CMakeLists.txt @@ -0,0 +1,17 @@ +# Add -fPIC so objects can be used in shared libraries. +# TODO: Need property for this. +if(CMAKE_SHARED_LIBRARY_C_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS} ${CMAKE_C_FLAGS}") +endif() + +add_definitions(-DA) + +add_custom_command( + OUTPUT a1.c + DEPENDS a1.c.in + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/a1.c.in + ${CMAKE_CURRENT_BINARY_DIR}/a1.c + ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(A OBJECT a1.c a2.c) diff --git a/Tests/ObjectLibrary/A/a.h b/Tests/ObjectLibrary/A/a.h new file mode 100644 index 0000000..6bfbc82 --- /dev/null +++ b/Tests/ObjectLibrary/A/a.h @@ -0,0 +1,6 @@ +#ifndef A +# error "A not defined" +#endif +#ifdef B +# error "B must not be defined" +#endif diff --git a/Tests/ObjectLibrary/A/a1.c.in b/Tests/ObjectLibrary/A/a1.c.in new file mode 100644 index 0000000..d1eaf58 --- /dev/null +++ b/Tests/ObjectLibrary/A/a1.c.in @@ -0,0 +1,2 @@ +#include "a.h" +int a1(void) { return 0; } diff --git a/Tests/ObjectLibrary/A/a2.c b/Tests/ObjectLibrary/A/a2.c new file mode 100644 index 0000000..d8f225e --- /dev/null +++ b/Tests/ObjectLibrary/A/a2.c @@ -0,0 +1,2 @@ +#include "a.h" +int a2(void) { return 0; } diff --git a/Tests/ObjectLibrary/B/CMakeLists.txt b/Tests/ObjectLibrary/B/CMakeLists.txt new file mode 100644 index 0000000..498d45d --- /dev/null +++ b/Tests/ObjectLibrary/B/CMakeLists.txt @@ -0,0 +1,15 @@ +if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6") + # VS 6 generator does not use per-target object locations. + set(vs6 _vs6) +endif() + +# Add -fPIC so objects can be used in shared libraries. +# TODO: Need property for this. +if(CMAKE_SHARED_LIBRARY_C_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS} ${CMAKE_C_FLAGS}") +endif() + +add_definitions(-DB) +add_library(B OBJECT b1.c b2.c) +add_library(Bexport OBJECT b1${vs6}.c b2${vs6}.c) +set_property(TARGET Bexport PROPERTY COMPILE_DEFINITIONS Bexport) diff --git a/Tests/ObjectLibrary/B/b.h b/Tests/ObjectLibrary/B/b.h new file mode 100644 index 0000000..632004d --- /dev/null +++ b/Tests/ObjectLibrary/B/b.h @@ -0,0 +1,11 @@ +#ifdef A +# error "A must not be defined" +#endif +#ifndef B +# error "B not defined" +#endif +#if defined(_WIN32) && defined(Bexport) +# define EXPORT_B __declspec(dllexport) +#else +# define EXPORT_B +#endif diff --git a/Tests/ObjectLibrary/B/b1.c b/Tests/ObjectLibrary/B/b1.c new file mode 100644 index 0000000..fdeffe4 --- /dev/null +++ b/Tests/ObjectLibrary/B/b1.c @@ -0,0 +1,2 @@ +#include "b.h" +EXPORT_B int b1(void) { return 0; } diff --git a/Tests/ObjectLibrary/B/b1_vs6.c b/Tests/ObjectLibrary/B/b1_vs6.c new file mode 100644 index 0000000..b606e10 --- /dev/null +++ b/Tests/ObjectLibrary/B/b1_vs6.c @@ -0,0 +1 @@ +#include "b1.c" diff --git a/Tests/ObjectLibrary/B/b2.c b/Tests/ObjectLibrary/B/b2.c new file mode 100644 index 0000000..6e0d17c --- /dev/null +++ b/Tests/ObjectLibrary/B/b2.c @@ -0,0 +1,2 @@ +#include "b.h" +EXPORT_B int b2(void) { return 0; } diff --git a/Tests/ObjectLibrary/B/b2_vs6.c b/Tests/ObjectLibrary/B/b2_vs6.c new file mode 100644 index 0000000..d96a43e --- /dev/null +++ b/Tests/ObjectLibrary/B/b2_vs6.c @@ -0,0 +1 @@ +#include "b2.c" diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt new file mode 100644 index 0000000..1a07d1d --- /dev/null +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.8) +project(ObjectLibrary C) + +add_subdirectory(A) +add_subdirectory(B) + +add_library(Cstatic STATIC c.c $ $) +add_executable(UseCstatic main.c) +target_link_libraries(UseCstatic Cstatic) + +add_library(Cshared SHARED c.c $ $) +add_executable(UseCshared main.c) +set_property(TARGET UseCshared PROPERTY COMPILE_DEFINITIONS SHARED_C) +target_link_libraries(UseCshared Cshared) + +add_executable(UseCinternal main.c c.c $ $) diff --git a/Tests/ObjectLibrary/c.c b/Tests/ObjectLibrary/c.c new file mode 100644 index 0000000..968095b --- /dev/null +++ b/Tests/ObjectLibrary/c.c @@ -0,0 +1,19 @@ +#if defined(_WIN32) && defined(Cshared_EXPORTS) +# define EXPORT_C __declspec(dllexport) +#else +# define EXPORT_C +#endif + +extern int a1(void); +extern int a2(void); +extern int b1(void); +extern int b2(void); +EXPORT_C int c(void) +{ + return 0 + + a1() + + a2() + + b1() + + b2() + ; +} diff --git a/Tests/ObjectLibrary/main.c b/Tests/ObjectLibrary/main.c new file mode 100644 index 0000000..6819f1c --- /dev/null +++ b/Tests/ObjectLibrary/main.c @@ -0,0 +1,16 @@ +#if defined(_WIN32) && defined(SHARED_C) +# define IMPORT_C __declspec(dllimport) +#else +# define IMPORT_C +#endif +extern IMPORT_C int b1(void); +extern IMPORT_C int b2(void); +extern IMPORT_C int c(void); +int main(void) +{ + return 0 + + c() + + b1() + + b2() + ; +} -- cgit v0.12 From 5683101669e677b5b8d7b50d817da54156afd626 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 14:51:30 -0400 Subject: Test OBJECT library failure cases Add "RunCMake.ObjectLibrary" test to verify that unsupported use cases are rejected with errors: * An OBJECT library may not reference another object library * An OBJECT library may not be referenced in target_link_libraries * An OBJECT library may not contain non-compiling sources * An OBJECT library may not have pre/post build/link commands * An OBJECT library may not be installed, exported, or imported Also verify that invalid $ expressions are diagnosed. --- Tests/RunCMake/CMakeLists.txt | 2 ++ Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt | 1 + Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt | 8 ++++++++ Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake | 1 + Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt | 1 + Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt | 8 ++++++++ Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake | 1 + .../ObjectLibrary/BadSourceExpression1-result.txt | 1 + .../ObjectLibrary/BadSourceExpression1-stderr.txt | 6 ++++++ Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake | 1 + .../ObjectLibrary/BadSourceExpression2-result.txt | 1 + .../ObjectLibrary/BadSourceExpression2-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake | 1 + .../ObjectLibrary/BadSourceExpression3-result.txt | 1 + .../ObjectLibrary/BadSourceExpression3-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake | 2 ++ Tests/RunCMake/ObjectLibrary/CMakeLists.txt | 3 +++ Tests/RunCMake/ObjectLibrary/Export-result.txt | 1 + Tests/RunCMake/ObjectLibrary/Export-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/Export.cmake | 2 ++ Tests/RunCMake/ObjectLibrary/Import-result.txt | 1 + Tests/RunCMake/ObjectLibrary/Import-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/Import.cmake | 1 + Tests/RunCMake/ObjectLibrary/Install-result.txt | 1 + Tests/RunCMake/ObjectLibrary/Install-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/Install.cmake | 2 ++ Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt | 1 + Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake | 2 ++ Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt | 1 + Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt | 6 ++++++ Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake | 3 +++ Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt | 1 + Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt | 6 ++++++ Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake | 3 +++ Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt | 1 + Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt | 4 ++++ Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake | 2 ++ Tests/RunCMake/ObjectLibrary/PostBuild-result.txt | 1 + Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt | 5 +++++ Tests/RunCMake/ObjectLibrary/PostBuild.cmake | 4 ++++ Tests/RunCMake/ObjectLibrary/PreBuild-result.txt | 1 + Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt | 5 +++++ Tests/RunCMake/ObjectLibrary/PreBuild.cmake | 4 ++++ Tests/RunCMake/ObjectLibrary/PreLink-result.txt | 1 + Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt | 5 +++++ Tests/RunCMake/ObjectLibrary/PreLink.cmake | 4 ++++ Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 17 +++++++++++++++++ Tests/RunCMake/ObjectLibrary/a.c | 1 + Tests/RunCMake/ObjectLibrary/bad.def | 0 Tests/RunCMake/ObjectLibrary/bad.obj | 0 51 files changed, 148 insertions(+) create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/CMakeLists.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Export-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Export-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Export.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/Import-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Import-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Import.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/Install-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Install-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/Install.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/PostBuild-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PostBuild.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/PreBuild-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PreBuild.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/PreLink-result.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt create mode 100644 Tests/RunCMake/ObjectLibrary/PreLink.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/a.c create mode 100644 Tests/RunCMake/ObjectLibrary/bad.def create mode 100644 Tests/RunCMake/ObjectLibrary/bad.obj diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 63fc9f8..0b79efa 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -40,5 +40,7 @@ macro(add_RunCMake_test test) ) endmacro() +add_RunCMake_test(ObjectLibrary) + add_RunCMake_test(build_command) add_RunCMake_test(find_package) diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt new file mode 100644 index 0000000..b31225b --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at BadObjSource1.cmake:1 \(add_library\): + OBJECT library "A" contains: + + bad.def + + but may contain only headers and sources that compile. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake b/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake new file mode 100644 index 0000000..aa3514d --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake @@ -0,0 +1 @@ +add_library(A OBJECT a.c bad.def) diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt new file mode 100644 index 0000000..906cf0b --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at BadObjSource2.cmake:1 \(add_library\): + OBJECT library "A" contains: + + bad.obj + + but may contain only headers and sources that compile. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake b/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake new file mode 100644 index 0000000..7957c99 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake @@ -0,0 +1 @@ +add_library(A OBJECT a.c bad.obj) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt new file mode 100644 index 0000000..a1cac36 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at BadSourceExpression1.cmake:1 \(add_library\): + Unrecognized generator expression: + + \$ +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake new file mode 100644 index 0000000..020c9a0 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake @@ -0,0 +1 @@ +add_library(A STATIC a.c $) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt new file mode 100644 index 0000000..f1fcbe8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadSourceExpression2.cmake:1 \(add_library\): + Objects of target "DoesNotExist" referenced but no such target exists. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake new file mode 100644 index 0000000..ed5dc43 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake @@ -0,0 +1 @@ +add_library(A STATIC a.c $) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt new file mode 100644 index 0000000..ad14a35 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at BadSourceExpression3.cmake:2 \(add_library\): + Objects of target "NotObjLib" referenced but is not an OBJECT library. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake new file mode 100644 index 0000000..c3d9a62 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake @@ -0,0 +1,2 @@ +add_library(NotObjLib STATIC a.c) +add_library(A STATIC a.c $) diff --git a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt new file mode 100644 index 0000000..a7f0779 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8) +project(${RunCMake_TEST} C) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/Export-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Export-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt new file mode 100644 index 0000000..bdadca4 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Export.cmake:2 \(export\): + export given OBJECT library "A" which may not be exported. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/Export.cmake b/Tests/RunCMake/ObjectLibrary/Export.cmake new file mode 100644 index 0000000..a3f104e --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Export.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +export(TARGETS A FILE AExport.cmake) diff --git a/Tests/RunCMake/ObjectLibrary/Import-result.txt b/Tests/RunCMake/ObjectLibrary/Import-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Import-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt b/Tests/RunCMake/ObjectLibrary/Import-stderr.txt new file mode 100644 index 0000000..74b496a --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Import-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Import.cmake:1 \(add_library\): + The OBJECT library type may not be used for IMPORTED libraries. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/Import.cmake b/Tests/RunCMake/ObjectLibrary/Import.cmake new file mode 100644 index 0000000..806b44a --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Import.cmake @@ -0,0 +1 @@ +add_library(A OBJECT IMPORTED) diff --git a/Tests/RunCMake/ObjectLibrary/Install-result.txt b/Tests/RunCMake/ObjectLibrary/Install-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Install-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt b/Tests/RunCMake/ObjectLibrary/Install-stderr.txt new file mode 100644 index 0000000..d2f9f4a --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Install-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at Install.cmake:2 \(install\): + install TARGETS given OBJECT library "A" which may not be installed. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/Install.cmake b/Tests/RunCMake/ObjectLibrary/Install.cmake new file mode 100644 index 0000000..c1d214b --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/Install.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +install(TARGETS A DESTINATION lib) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt new file mode 100644 index 0000000..90e828b --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at LinkObjLHS.cmake:2 \(target_link_libraries\): + Object library target "AnObjLib" may not link to anything. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake new file mode 100644 index 0000000..5d7831a --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake @@ -0,0 +1,2 @@ +add_library(AnObjLib OBJECT a.c) +target_link_libraries(AnObjLib OtherLib) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt new file mode 100644 index 0000000..8809f89 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at LinkObjRHS1.cmake:3 \(target_link_libraries\): + Target "AnObjLib" of type OBJECT_LIBRARY may not be linked into another + target. One may link only to STATIC or SHARED libraries, or to executables + with the ENABLE_EXPORTS property set. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake new file mode 100644 index 0000000..113d6a8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake @@ -0,0 +1,3 @@ +add_library(A STATIC a.c) +add_library(AnObjLib OBJECT a.c) +target_link_libraries(A AnObjLib) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt new file mode 100644 index 0000000..3295fca --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt @@ -0,0 +1,6 @@ +CMake Error at LinkObjRHS2.cmake:1 \(add_library\): + Target "A" links to OBJECT library "AnObjLib" but this is not allowed. One + may link only to STATIC or SHARED libraries, or to executables with the + ENABLE_EXPORTS property set. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake new file mode 100644 index 0000000..6163729 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake @@ -0,0 +1,3 @@ +add_library(A SHARED a.c) +target_link_libraries(A AnObjLib) +add_library(AnObjLib OBJECT a.c) diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt b/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt b/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt new file mode 100644 index 0000000..d67b4ae --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at ObjWithObj.cmake:2 \(add_library\): + Only executables and non-OBJECT libraries may reference target objects. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake b/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake new file mode 100644 index 0000000..d0ef34b --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake @@ -0,0 +1,2 @@ +add_library(A OBJECT a.c) +add_library(B OBJECT $) diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt b/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt b/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt new file mode 100644 index 0000000..4b067bb --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at PostBuild.cmake:2 \(add_custom_command\): + Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or + POST_BUILD commands. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild.cmake b/Tests/RunCMake/ObjectLibrary/PostBuild.cmake new file mode 100644 index 0000000..dea9a09 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PostBuild.cmake @@ -0,0 +1,4 @@ +add_library(A OBJECT a.c) +add_custom_command(TARGET A POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "A post-build" + ) diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt b/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt b/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt new file mode 100644 index 0000000..3b27a6d --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at PreBuild.cmake:2 \(add_custom_command\): + Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or + POST_BUILD commands. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild.cmake b/Tests/RunCMake/ObjectLibrary/PreBuild.cmake new file mode 100644 index 0000000..e4424c1 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreBuild.cmake @@ -0,0 +1,4 @@ +add_library(A OBJECT a.c) +add_custom_command(TARGET A PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E echo "A pre-build" + ) diff --git a/Tests/RunCMake/ObjectLibrary/PreLink-result.txt b/Tests/RunCMake/ObjectLibrary/PreLink-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreLink-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt b/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt new file mode 100644 index 0000000..947b9f1 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt @@ -0,0 +1,5 @@ +CMake Error at PreLink.cmake:2 \(add_custom_command\): + Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or + POST_BUILD commands. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/ObjectLibrary/PreLink.cmake b/Tests/RunCMake/ObjectLibrary/PreLink.cmake new file mode 100644 index 0000000..b889055 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/PreLink.cmake @@ -0,0 +1,4 @@ +add_library(A OBJECT a.c) +add_custom_command(TARGET A PRE_LINK + COMMAND ${CMAKE_COMMAND} -E echo "A pre-link" + ) diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake new file mode 100644 index 0000000..a74eaa8 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -0,0 +1,17 @@ +include(RunCMake) + +run_cmake(BadSourceExpression1) +run_cmake(BadSourceExpression2) +run_cmake(BadSourceExpression3) +run_cmake(BadObjSource1) +run_cmake(BadObjSource2) +run_cmake(Export) +run_cmake(Import) +run_cmake(Install) +run_cmake(LinkObjLHS) +run_cmake(LinkObjRHS1) +run_cmake(LinkObjRHS2) +run_cmake(ObjWithObj) +run_cmake(PostBuild) +run_cmake(PreBuild) +run_cmake(PreLink) diff --git a/Tests/RunCMake/ObjectLibrary/a.c b/Tests/RunCMake/ObjectLibrary/a.c new file mode 100644 index 0000000..af20d3f --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/a.c @@ -0,0 +1 @@ +int a(void) { return 0; } diff --git a/Tests/RunCMake/ObjectLibrary/bad.def b/Tests/RunCMake/ObjectLibrary/bad.def new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/ObjectLibrary/bad.obj b/Tests/RunCMake/ObjectLibrary/bad.obj new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From db7ef82402bed3d941bea73d266ac5919f4eee15 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2012 15:02:42 -0400 Subject: Test OBJECT library language propagation Teach the RunCMake.ObjectLibrary test to verify that languages used in an OBJECT library are propagated to targets that use it so that the languages can be included in link analysis. --- Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake | 15 +++++++++++++++ Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake | 1 + Tests/RunCMake/ObjectLibrary/a.cxx | 1 + 3 files changed, 17 insertions(+) create mode 100644 Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake create mode 100644 Tests/RunCMake/ObjectLibrary/a.cxx diff --git a/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake b/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake new file mode 100644 index 0000000..0796c21 --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake @@ -0,0 +1,15 @@ +enable_language(CXX) +add_library(A OBJECT a.cxx) +add_library(B STATIC a.c $) + +# Verify that object library languages are propagated. +export(TARGETS B NAMESPACE Exp FILE BExport.cmake) +include(${CMAKE_CURRENT_BINARY_DIR}/BExport.cmake) +get_property(configs TARGET ExpB PROPERTY IMPORTED_CONFIGURATIONS) +foreach(c ${configs}) + get_property(langs TARGET ExpB PROPERTY IMPORTED_LINK_INTERFACE_LANGUAGES_${c}) + list(FIND langs CXX pos) + if(${pos} LESS 0) + message(FATAL_ERROR "Target export does not list object library languages.") + endif() +endforeach() diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake index a74eaa8..55db14d 100644 --- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake +++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake @@ -6,6 +6,7 @@ run_cmake(BadSourceExpression3) run_cmake(BadObjSource1) run_cmake(BadObjSource2) run_cmake(Export) +run_cmake(ExportLanguages) run_cmake(Import) run_cmake(Install) run_cmake(LinkObjLHS) diff --git a/Tests/RunCMake/ObjectLibrary/a.cxx b/Tests/RunCMake/ObjectLibrary/a.cxx new file mode 100644 index 0000000..ae9c87c --- /dev/null +++ b/Tests/RunCMake/ObjectLibrary/a.cxx @@ -0,0 +1 @@ +extern "C" int acxx(void) { return 0; } -- cgit v0.12 From c3242500b62c3f81af46e086cc2225b53c023167 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 14 Mar 2012 09:24:26 -0400 Subject: Test OBJECT library use without other sources Reference OBJECT libraries for inclusion in targets that have no other sources to verify that the linker language propagates correctly from the object libraries. Test with a STATIC library, a SHARED library, and an EXECUTABLE target. Use the static and shared libraries each in executables that end up using the object library symbols. In VS 6, 7, and 7.1 add a dummy object file to convince the IDE to build the targets without sources. In Xcode add a dummy source file to convince it to build targets without sources. --- Tests/ObjectLibrary/AB.def | 5 +++++ Tests/ObjectLibrary/CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++++++ Tests/ObjectLibrary/dummy.c | 1 + Tests/ObjectLibrary/dummy.obj | Bin 0 -> 498 bytes Tests/ObjectLibrary/mainAB.c | 22 ++++++++++++++++++++++ 5 files changed, 64 insertions(+) create mode 100644 Tests/ObjectLibrary/AB.def create mode 100644 Tests/ObjectLibrary/dummy.c create mode 100644 Tests/ObjectLibrary/dummy.obj create mode 100644 Tests/ObjectLibrary/mainAB.c diff --git a/Tests/ObjectLibrary/AB.def b/Tests/ObjectLibrary/AB.def new file mode 100644 index 0000000..3f2b5c0 --- /dev/null +++ b/Tests/ObjectLibrary/AB.def @@ -0,0 +1,5 @@ +EXPORTS +a1 +a2 +b1 +b2 diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt index 1a07d1d..8723415 100644 --- a/Tests/ObjectLibrary/CMakeLists.txt +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -14,3 +14,39 @@ set_property(TARGET UseCshared PROPERTY COMPILE_DEFINITIONS SHARED_C) target_link_libraries(UseCshared Cshared) add_executable(UseCinternal main.c c.c $ $) + +if("${CMAKE_GENERATOR}" MATCHES "^Visual Studio (6|7|7 .NET 2003)$") + # VS 6 and 7 generators do not add objects as sources so we need a + # dummy object to convince the IDE to build the targets below. + set(dummy dummy.obj) # In MinGW: gcc -c dummy.c -o dummy.obj +elseif("${CMAKE_GENERATOR}" MATCHES "Xcode") + # Xcode does not seem to support targets without sources. + set(dummy dummy.c) +endif() + +# Test static library without its own sources. +add_library(ABstatic STATIC ${dummy} $ $) +add_executable(UseABstatic mainAB.c) +target_link_libraries(UseABstatic ABstatic) + +# Test module definition file to export object library symbols in the test +# below if the platform needs and supports it. +set(ABshared_SRCS $) +if(CMAKE_LINK_DEF_FILE_FLAG OR NOT WIN32) + list(APPEND ABshared_SRCS $ AB.def) +else() + set(NO_A NO_A) + list(APPEND ABshared_SRCS $) +endif() + +# Test shared library without its own sources. +add_library(ABshared SHARED ${dummy} ${ABshared_SRCS}) +add_executable(UseABshared mainAB.c) +set_property(TARGET UseABshared PROPERTY COMPILE_DEFINITIONS SHARED_B ${NO_A}) +target_link_libraries(UseABshared ABshared) + +# Test executable without its own sources. +add_library(ABmain OBJECT mainAB.c) +add_executable(UseABinternal ${dummy} + $ $ $ + ) diff --git a/Tests/ObjectLibrary/dummy.c b/Tests/ObjectLibrary/dummy.c new file mode 100644 index 0000000..2b17d81 --- /dev/null +++ b/Tests/ObjectLibrary/dummy.c @@ -0,0 +1 @@ +int dummy(void) {return 0;} diff --git a/Tests/ObjectLibrary/dummy.obj b/Tests/ObjectLibrary/dummy.obj new file mode 100644 index 0000000..77f6f2f Binary files /dev/null and b/Tests/ObjectLibrary/dummy.obj differ diff --git a/Tests/ObjectLibrary/mainAB.c b/Tests/ObjectLibrary/mainAB.c new file mode 100644 index 0000000..556898b --- /dev/null +++ b/Tests/ObjectLibrary/mainAB.c @@ -0,0 +1,22 @@ +#if defined(_WIN32) && defined(SHARED_B) +# define IMPORT_B __declspec(dllimport) +#else +# define IMPORT_B +#endif +extern IMPORT_B int b1(void); +extern IMPORT_B int b2(void); +#ifndef NO_A +extern int a1(void); +extern int a2(void); +#endif +int main(void) +{ + return 0 +#ifndef NO_A + + a1() + + a2() +#endif + + b1() + + b2() + ; +} -- cgit v0.12 From cd146c650e092dcbf91adf60ef697608c2ac7fa2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Mar 2012 08:53:27 -0400 Subject: Document OBJECT library type in add_library command Describe the OBJECT library signature of add_library and the $ expressions needed to use object libraries. Also document the what is not allowed for object library targets. --- Source/cmAddLibraryCommand.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h index 9ca9cbe..b1ae202 100644 --- a/Source/cmAddLibraryCommand.h +++ b/Source/cmAddLibraryCommand.h @@ -112,6 +112,26 @@ public: "(and its per-configuration version IMPORTED_LOCATION_) " "which specifies the location of the main library file on disk. " "See documentation of the IMPORTED_* properties for more information." + "\n" + "The signature\n" + " add_library( OBJECT ...)\n" + "creates a special \"object library\" target. " + "An object library compiles source files but does not archive or link " + "their object files into a library. " + "Instead other targets created by add_library or add_executable may " + "reference the objects using an expression of the form " + "$ as a source, where \"objlib\" is the " + "object library name. " + "For example:\n" + " add_library(... $ ...)\n" + " add_executable(... $ ...)\n" + "will include objlib's object files in a library and an executable " + "along with those compiled from their own sources. " + "Object libraries may contain only sources (and headers) that compile " + "to object files. " + "They may contain custom commands generating such sources, but not " + "PRE_BUILD, PRE_LINK, or POST_BUILD commands. " + "Object libraries cannot be imported, exported, installed, or linked." ; } -- cgit v0.12 From a2514f15fae34abb6f29dddf6f5cfe8b171a8035 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 13 Mar 2012 09:24:54 -0400 Subject: Simplify cmNinjaTargetGenerator using cmGeneratorTarget Replace the classification of source files in this generator using that computed by cmGeneratorTarget. --- Source/cmNinjaTargetGenerator.cxx | 76 +++++++++++++++++++-------------------- Source/cmNinjaTargetGenerator.h | 5 ++- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index b9f997d..23662d9 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -14,6 +14,7 @@ #include "cmGlobalNinjaGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" #include "cmNinjaNormalTargetGenerator.h" #include "cmNinjaUtilityTargetGenerator.h" #include "cmSystemTools.h" @@ -60,6 +61,8 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target) static_cast(Makefile->GetLocalGenerator())), Objects() { + this->GeneratorTarget = + this->GetGlobalGenerator()->GetGeneratorTarget(target); } cmNinjaTargetGenerator::~cmNinjaTargetGenerator() @@ -231,9 +234,9 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath()); // Add a dependency on the link definitions file, if any. - if(!this->ModuleDefinitionFile.empty()) + if(!this->GeneratorTarget->ModuleDefinitionFile.empty()) { - result.push_back(this->ModuleDefinitionFile); + result.push_back(this->GeneratorTarget->ModuleDefinitionFile); } return result; @@ -377,12 +380,26 @@ cmNinjaTargetGenerator << this->GetTargetName() << "\n\n"; - // For each source files of this target. - for(std::vector::const_iterator i = - this->GetTarget()->GetSourceFiles().begin(); - i != this->GetTarget()->GetSourceFiles().end(); - ++i) - this->WriteObjectBuildStatement(*i); + for(std::vector::const_iterator + si = this->GeneratorTarget->CustomCommands.begin(); + si != this->GeneratorTarget->CustomCommands.end(); ++si) + { + cmCustomCommand const* cc = (*si)->GetCustomCommand(); + this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget()); + } + // TODO: this->GeneratorTarget->OSXContent + for(std::vector::const_iterator + si = this->GeneratorTarget->ExternalObjects.begin(); + si != this->GeneratorTarget->ExternalObjects.end(); ++si) + { + this->Objects.push_back(this->GetSourceFilePath(*si)); + } + for(std::vector::const_iterator + si = this->GeneratorTarget->ObjectSources.begin(); + si != this->GeneratorTarget->ObjectSources.end(); ++si) + { + this->WriteObjectBuildStatement(*si); + } this->GetBuildFileStream() << "\n"; } @@ -391,26 +408,10 @@ void cmNinjaTargetGenerator ::WriteObjectBuildStatement(cmSourceFile* source) { - if (cmCustomCommand *cc = source->GetCustomCommand()) - this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget()); - cmNinjaDeps emptyDeps; std::string comment; const char* language = source->GetLanguage(); - // If we cannot get the language this is probably a non-source file provided - // in the list (typically an header file). - if (!language) { - if (source->GetPropertyAsBool("EXTERNAL_OBJECT")) - this->Objects.push_back(this->GetSourceFilePath(source)); - if(cmSystemTools::UpperCase(source->GetExtension()) == "DEF") - this->ModuleDefinitionFile = GetSourceFilePath(source); - return; - } - - if (source->GetPropertyAsBool("HEADER_FILE_ONLY")) - return; - std::string rule = this->LanguageCompilerRule(language); cmNinjaDeps outputs; @@ -435,21 +436,16 @@ cmNinjaTargetGenerator std::back_inserter(orderOnlyDeps), MapToNinjaPath()); } - // Add order-only dependency on any header file with a custom command. - { - const std::vector& sources = - this->GetTarget()->GetSourceFiles(); - for(std::vector::const_iterator si = sources.begin(); - si != sources.end(); ++si) { - if (!(*si)->GetLanguage()) { - if (cmCustomCommand* cc = (*si)->GetCustomCommand()) { - const std::vector& ccoutputs = cc->GetOutputs(); - std::transform(ccoutputs.begin(), ccoutputs.end(), - std::back_inserter(orderOnlyDeps), MapToNinjaPath()); - } - } + // Add order-only dependencies on custom command outputs. + for(std::vector::const_iterator + si = this->GeneratorTarget->CustomCommands.begin(); + si != this->GeneratorTarget->CustomCommands.end(); ++si) + { + cmCustomCommand const* cc = (*si)->GetCustomCommand(); + const std::vector& ccoutputs = cc->GetOutputs(); + std::transform(ccoutputs.begin(), ccoutputs.end(), + std::back_inserter(orderOnlyDeps), MapToNinjaPath()); } - } // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of @@ -482,7 +478,7 @@ void cmNinjaTargetGenerator ::AddModuleDefinitionFlag(std::string& flags) { - if(this->ModuleDefinitionFile.empty()) + if(this->GeneratorTarget->ModuleDefinitionFile.empty()) { return; } @@ -499,6 +495,6 @@ cmNinjaTargetGenerator // vs6's "cl -link" pass it to the linker. std::string flag = defFileFlag; flag += (this->LocalGenerator->ConvertToLinkReference( - this->ModuleDefinitionFile.c_str())); + this->GeneratorTarget->ModuleDefinitionFile.c_str())); this->LocalGenerator->AppendFlags(flags, flag.c_str()); } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 3e70a2c..f639116 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -20,6 +20,7 @@ class cmTarget; class cmGlobalNinjaGenerator; class cmGeneratedFileStream; +class cmGeneratorTarget; class cmMakefile; class cmSourceFile; class cmCustomCommand; @@ -112,13 +113,11 @@ protected: private: cmTarget* Target; + cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; cmLocalNinjaGenerator* LocalGenerator; /// List of object files for this target. cmNinjaDeps Objects; - - // The windows module definition source file (.def), if any. - std::string ModuleDefinitionFile; }; #endif // ! cmNinjaTargetGenerator_h -- cgit v0.12 From f5b06cda0f187929ac68ed64595c22d4e6ec773c Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 13 Mar 2012 09:30:23 -0400 Subject: Pre-compute object file names before Ninja generation Implement cmGlobalGenerator::ComputeTargetObjects in the Ninja generator to pre-compute all the object file names. Use the results during generation instead of re-computing it later. --- Source/cmGlobalNinjaGenerator.cxx | 29 +++++++++++++++++++++++++++++ Source/cmGlobalNinjaGenerator.h | 6 ++++++ Source/cmLocalNinjaGenerator.cxx | 31 ------------------------------- Source/cmLocalNinjaGenerator.h | 3 --- Source/cmNinjaTargetGenerator.cxx | 5 ++++- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 7c1529b..03c8be9 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -14,6 +14,7 @@ #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorTarget.h" #include "cmVersion.h" const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja"; @@ -500,6 +501,34 @@ bool cmGlobalNinjaGenerator::HasRule(const std::string &name) } //---------------------------------------------------------------------------- +// Private virtual overrides + +// TODO: Refactor to combine with cmGlobalUnixMakefileGenerator3 impl. +void cmGlobalNinjaGenerator::ComputeTargetObjects(cmGeneratorTarget* gt) const +{ + cmTarget* target = gt->Target; + + // Compute full path to object file directory for this target. + std::string dir_max; + dir_max += gt->Makefile->GetCurrentOutputDirectory(); + dir_max += "/"; + dir_max += gt->LocalGenerator->GetTargetDirectory(*target); + dir_max += "/"; + gt->ObjectDirectory = dir_max; + + // Compute the name of each object file. + for(std::vector::iterator + si = gt->ObjectSources.begin(); + si != gt->ObjectSources.end(); ++si) + { + cmSourceFile* sf = *si; + std::string objectName = gt->LocalGenerator + ->GetObjectFileNameWithoutTarget(*sf, dir_max); + gt->Objects[sf] = objectName; + } +} + +//---------------------------------------------------------------------------- // Private methods void cmGlobalNinjaGenerator::OpenBuildFileStream() diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 39df826..3217581 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -18,6 +18,7 @@ class cmLocalGenerator; class cmGeneratedFileStream; +class cmGeneratorTarget; /** * \class cmGlobalNinjaGenerator @@ -236,6 +237,11 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; } private: + + /// @see cmGlobalGenerator::ComputeTargetObjects + virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const; + +private: // In order to access the AddDependencyToAll() functions and co. friend class cmLocalNinjaGenerator; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 78072b5..425b219 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -117,37 +117,6 @@ cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator() return static_cast(this->GetGlobalGenerator()); } -// TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it. -std::string -cmLocalNinjaGenerator -::GetObjectFileName(const cmTarget& target, - const cmSourceFile& source) -{ - // Make sure we never hit this old case. - if(source.GetProperty("MACOSX_PACKAGE_LOCATION")) - { - std::string msg = "MACOSX_PACKAGE_LOCATION set on source file: "; - msg += source.GetFullPath(); - this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, - msg.c_str()); - } - - // Start with the target directory. - std::string obj = this->GetTargetDirectory(target); - obj += "/"; - - // Get the object file name without the target directory. - std::string dir_max; - dir_max += this->Makefile->GetCurrentOutputDirectory(); - dir_max += "/"; - dir_max += obj; - std::string objectName = - this->GetObjectFileNameWithoutTarget(source, dir_max, 0); - // Append the object name to the target directory. - obj += objectName; - return obj; -} - //---------------------------------------------------------------------------- // Virtual protected methods. diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index 28b431d..ea44b2f 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -59,9 +59,6 @@ public: const char* GetConfigName() const { return this->ConfigName.c_str(); } - std::string GetObjectFileName(const cmTarget& target, - const cmSourceFile& source); - /// @return whether we are processing the top CMakeLists.txt file. bool isRootMakefile() const; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 23662d9..cc67434 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -256,7 +256,10 @@ cmNinjaTargetGenerator std::string path = this->LocalGenerator->GetHomeRelativeOutputPath(); if(!path.empty()) path += "/"; - path += this->LocalGenerator->GetObjectFileName(*this->Target, *source); + std::string const& objectName = this->GeneratorTarget->Objects[source]; + path += this->LocalGenerator->GetTargetDirectory(*this->Target); + path += "/"; + path += objectName; return path; } -- cgit v0.12 From 61124de4c06b1195e79ee71326b902baf23c4c32 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 13 Mar 2012 10:05:07 -0400 Subject: Build object library targets in Ninja Treat OBJECT libraries as STATIC libraries but leave out the archive step. The object files will be left behind for reference by other targets later. --- Source/cmGlobalNinjaGenerator.cxx | 1 + Source/cmNinjaNormalTargetGenerator.cxx | 40 ++++++++++++++++++++++++++++----- Source/cmNinjaNormalTargetGenerator.h | 1 + Source/cmNinjaTargetGenerator.cxx | 4 +++- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 03c8be9..9cbd502 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -664,6 +664,7 @@ cmGlobalNinjaGenerator target->GetFullPath(configName).c_str())); break; + case cmTarget::OBJECT_LIBRARY: case cmTarget::UTILITY: { std::string path = ng->ConvertToNinjaPath( target->GetMakefile()->GetStartOutputDirectory()); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 9242181..6859445 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -43,10 +43,13 @@ cmNinjaNormalTargetGenerator(cmTarget* target) this->TargetNamePDB, GetLocalGenerator()->GetConfigName()); - // on Windows the output dir is already needed at compile time - // ensure the directory exists (OutDir test) - std::string outpath = target->GetDirectory(this->GetConfigName()); - cmSystemTools::MakeDirectory(outpath.c_str()); + if(target->GetType() != cmTarget::OBJECT_LIBRARY) + { + // on Windows the output dir is already needed at compile time + // ensure the directory exists (OutDir test) + std::string outpath = target->GetDirectory(this->GetConfigName()); + cmSystemTools::MakeDirectory(outpath.c_str()); + } } cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() @@ -67,8 +70,15 @@ void cmNinjaNormalTargetGenerator::Generate() // Write the build statements this->WriteObjectBuildStatements(); - this->WriteLinkRule(); - this->WriteLinkStatement(); + if(this->GetTarget()->GetType() == cmTarget::OBJECT_LIBRARY) + { + this->WriteObjectLibStatement(); + } + else + { + this->WriteLinkRule(); + this->WriteLinkStatement(); + } this->GetBuildFileStream() << "\n"; this->GetRulesFileStream() << "\n"; @@ -467,3 +477,21 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), this->GetTarget()); } + +//---------------------------------------------------------------------------- +void cmNinjaNormalTargetGenerator::WriteObjectLibStatement() +{ + // Write a phony output that depends on all object files. + cmNinjaDeps outputs; + this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs); + cmNinjaDeps depends = this->GetObjects(); + cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(), + "Object library " + + this->GetTargetName(), + outputs, + depends); + + // Add aliases for the target name. + this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(), + this->GetTarget()); +} diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h index 99f5a13..1702caf 100644 --- a/Source/cmNinjaNormalTargetGenerator.h +++ b/Source/cmNinjaNormalTargetGenerator.h @@ -32,6 +32,7 @@ private: void WriteLanguagesRules(); void WriteLinkRule(); void WriteLinkStatement(); + void WriteObjectLibStatement(); std::vector ComputeLinkCmd(); private: diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index cc67434..2a78405 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -34,6 +34,7 @@ cmNinjaTargetGenerator::New(cmTarget* target) case cmTarget::SHARED_LIBRARY: case cmTarget::STATIC_LIBRARY: case cmTarget::MODULE_LIBRARY: + case cmTarget::OBJECT_LIBRARY: return new cmNinjaNormalTargetGenerator(target); case cmTarget::UTILITY: @@ -221,7 +222,8 @@ ComputeDefines(cmSourceFile *source, const std::string& language) cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const { // Static libraries never depend on other targets for linking. - if (this->Target->GetType() == cmTarget::STATIC_LIBRARY) + if (this->Target->GetType() == cmTarget::STATIC_LIBRARY || + this->Target->GetType() == cmTarget::OBJECT_LIBRARY) return cmNinjaDeps(); cmComputeLinkInformation* cli = -- cgit v0.12 From 51997cb6dc93eff826e95ac326eb9af6763eaa32 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 15 Mar 2012 08:56:40 -0400 Subject: Ninja: Honor $ source expressions Add objects from object libraries referenced using this syntax to the set of objects linked in a target. --- Source/cmNinjaTargetGenerator.cxx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 2a78405..675a160 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -406,6 +406,17 @@ cmNinjaTargetGenerator this->WriteObjectBuildStatement(*si); } + { + // Add object library contents as external objects. + std::vector objs; + this->GeneratorTarget->UseObjectLibraries(objs); + for(std::vector::iterator oi = objs.begin(); + oi != objs.end(); ++oi) + { + this->Objects.push_back(ConvertToNinjaPath(oi->c_str())); + } + } + this->GetBuildFileStream() << "\n"; } -- cgit v0.12 From be01f3b098a69570cc382501a3895f424c4a608f Mon Sep 17 00:00:00 2001 From: David Cole Date: Thu, 15 Mar 2012 12:05:31 -0400 Subject: Xcode: Re-factor some existing methods into "FromPath" variants ...to avoid depending on cmSourceFile instances. Prep work for supporting OBJECT_LIBRARY in the Xcode generator. --- Source/cmGlobalXCodeGenerator.cxx | 158 ++++++++++++++++++++++++++------------ Source/cmGlobalXCodeGenerator.h | 6 ++ 2 files changed, 116 insertions(+), 48 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7660ffa..4ba0350 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -561,15 +561,43 @@ cmXCodeObject* cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- -cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf) +cmStdString +GetGroupMapKeyFromPath(cmTarget& cmtarget, const std::string& fullpath) { cmStdString key(cmtarget.GetName()); key += "-"; - key += sf->GetFullPath(); + key += fullpath; return key; } //---------------------------------------------------------------------------- +cmStdString +GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf) +{ + return GetGroupMapKeyFromPath(cmtarget, sf->GetFullPath()); +} + +//---------------------------------------------------------------------------- +cmXCodeObject* +cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( + const std::string &fullpath, + cmTarget& cmtarget, + const std::string &lang) +{ + // Using a map and the full path guarantees that we will always get the same + // fileRef object for any given full path. + // + cmXCodeObject* fileRef = + this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang); + + cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); + buildFile->SetComment(fileRef->GetComment()); + buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef)); + + return buildFile; +} + +//---------------------------------------------------------------------------- cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, cmSourceFile* sf, @@ -603,14 +631,16 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, flags += flagsBuild.GetString(); } - // Using a map and the full path guarantees that we will always get the same - // fileRef object for any given full path. - // - cmXCodeObject* fileRef = this->CreateXCodeFileReference(sf, cmtarget); + const char* lang = + this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); + if (!lang) + { + lang = ""; + } - cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - buildFile->SetComment(fileRef->GetComment()); - buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef)); + cmXCodeObject* buildFile = + this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang); + cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject(); cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); @@ -662,36 +692,12 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, } //---------------------------------------------------------------------------- -cmXCodeObject* -cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, - cmTarget& cmtarget) +std::string +GetSourcecodeValueFromFileExtension(const std::string& _ext, + const std::string& lang) { - std::string fname = sf->GetFullPath(); - cmXCodeObject* fileRef = this->FileRefs[fname]; - if(!fileRef) - { - fileRef = this->CreateObject(cmXCodeObject::PBXFileReference); - std::string comment = fname; - //comment += " in "; - //std::string gname = group->GetObject("name")->GetString(); - //comment += gname.substr(1, gname.size()-2); - fileRef->SetComment(fname.c_str()); - this->FileRefs[fname] = fileRef; - } - cmStdString key = GetGroupMapKey(cmtarget, sf); - cmXCodeObject* group = this->GroupMap[key]; - cmXCodeObject* children = group->GetObject("children"); - if (!children->HasObject(fileRef)) - { - children->AddObject(fileRef); - } - fileRef->AddAttribute("fileEncoding", this->CreateString("4")); - - const char* lang = - this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); + std::string ext = cmSystemTools::LowerCase(_ext); std::string sourcecode = "sourcecode"; - std::string ext = sf->GetExtension(); - ext = cmSystemTools::LowerCase(ext); if(ext == "o") { @@ -726,25 +732,25 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, { sourcecode += ".cpp.h"; } - else if(lang && strcmp(lang, "CXX") == 0) + else if(ext == "png" || ext == "gif" || ext == "jpg") { - sourcecode += ".cpp.cpp"; + sourcecode = "image"; } - else if(lang && strcmp(lang, "C") == 0) + else if(ext == "txt") { - sourcecode += ".c.c"; + sourcecode += ".text"; } - else if(lang && strcmp(lang, "Fortran") == 0) + else if(lang == "CXX") { - sourcecode += ".fortran.f90"; + sourcecode += ".cpp.cpp"; } - else if(ext == "png" || ext == "gif" || ext == "jpg") + else if(lang == "C") { - sourcecode = "image"; + sourcecode += ".c.c"; } - else if(ext == "txt") + else if(lang == "Fortran") { - sourcecode += ".text"; + sourcecode += ".fortran.f90"; } //else // { @@ -754,11 +760,51 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, // // valid lastKnownFileType value. // } + return sourcecode; +} + +//---------------------------------------------------------------------------- +cmXCodeObject* +cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( + const std::string &fullpath, + cmTarget& cmtarget, + const std::string &lang) +{ + std::string fname = fullpath; + cmXCodeObject* fileRef = this->FileRefs[fname]; + if(!fileRef) + { + fileRef = this->CreateObject(cmXCodeObject::PBXFileReference); + std::string comment = fname; + fileRef->SetComment(fname.c_str()); + this->FileRefs[fname] = fileRef; + } + cmStdString key = GetGroupMapKeyFromPath(cmtarget, fullpath); + cmXCodeObject* group = this->GroupMap[key]; + cmXCodeObject* children = group->GetObject("children"); + if (!children->HasObject(fileRef)) + { + children->AddObject(fileRef); + } + fileRef->AddAttribute("fileEncoding", this->CreateString("4")); + + // Compute the extension. + std::string ext; + std::string realExt = + cmSystemTools::GetFilenameLastExtension(fullpath); + if(!realExt.empty()) + { + // Extension without the leading '.'. + ext = realExt.substr(1); + } + + std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang); + fileRef->AddAttribute("lastKnownFileType", this->CreateString(sourcecode.c_str())); // Store the file path relative to the top of the source tree. - std::string path = this->RelativeToSource(sf->GetFullPath().c_str()); + std::string path = this->RelativeToSource(fullpath.c_str()); std::string name = cmSystemTools::GetFilenameName(path.c_str()); const char* sourceTree = (cmSystemTools::FileIsFullPath(path.c_str())? "" : "SOURCE_ROOT"); @@ -773,6 +819,22 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, } //---------------------------------------------------------------------------- +cmXCodeObject* +cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, + cmTarget& cmtarget) +{ + const char* lang = + this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); + if (!lang) + { + lang = ""; + } + + return this->CreateXCodeFileReferenceFromPath( + sf->GetFullPath(), cmtarget, lang); +} + +//---------------------------------------------------------------------------- bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname) { if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" || diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 393cd47..2004514 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -153,6 +153,12 @@ private: std::vector& generators); void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); + cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string &fullpath, + cmTarget& cmtarget, + const std::string &lang); + cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string &fullpath, + cmTarget& cmtarget, + const std::string &lang); cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf, cmTarget& cmtarget); cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen, -- cgit v0.12 From b063599603bd3d2d3cc57495d0d060ac90f0f308 Mon Sep 17 00:00:00 2001 From: David Cole Date: Thu, 15 Mar 2012 14:15:44 -0400 Subject: Add a default source group for object files. --- Source/cmMakefile.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index aba2e38..56e3305 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -782,6 +782,7 @@ void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg) "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"); this->AddSourceGroup("CMake Rules", "\\.rule$"); this->AddSourceGroup("Resources", "\\.plist$"); + this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$"); #endif this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); -- cgit v0.12 From 247a132422bd3f1c97f5fcf8457d5a105ab65687 Mon Sep 17 00:00:00 2001 From: David Cole Date: Wed, 14 Mar 2012 17:36:31 -0400 Subject: Allow txt files as ExtraSources in object library targets Necessary for the Xcode generator, in which the CMakeLists.txt files are added as sources merely for convenient access, without any associated custom command. --- Source/cmGeneratorTarget.cxx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 369eb5c..b5fcae2 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -74,7 +74,10 @@ void cmGeneratorTarget::ClassifySources() else { this->ExtraSources.push_back(sf); - if(isObjLib) { badObjLib.push_back(sf); } + if(isObjLib && cmSystemTools::LowerCase(sf->GetExtension()) != "txt") + { + badObjLib.push_back(sf); + } } } -- cgit v0.12 From 8045e1711907951ec1cb574d7e39c0dcf6471302 Mon Sep 17 00:00:00 2001 From: David Cole Date: Tue, 13 Mar 2012 16:41:28 -0400 Subject: Pre-compute object file names before Xcode generation --- Source/cmGlobalXCodeGenerator.cxx | 49 +++++++++++++++++++++++++++++++++++++++ Source/cmGlobalXCodeGenerator.h | 2 ++ 2 files changed, 51 insertions(+) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 4ba0350..8181886 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -19,6 +19,7 @@ #include "cmComputeLinkInformation.h" #include "cmSourceFile.h" #include "cmCustomCommandGenerator.h" +#include "cmGeneratorTarget.h" #include @@ -3611,3 +3612,51 @@ bool cmGlobalXCodeGenerator::IsMultiConfig() // Newer Xcode versions are multi config: return true; } + + //---------------------------------------------------------------------------- +void +cmGlobalXCodeGenerator +::ComputeTargetObjects(cmGeneratorTarget* gt) const +{ + // Count the number of object files with each name. Warn about duplicate + // names since Xcode names them uniquely automatically with a numeric suffix + // to avoid exact duplicate file names. Note that Mac file names are not + // typically case sensitive, hence the LowerCase. + std::map counts; + for(std::vector::const_iterator + si = gt->ObjectSources.begin(); + si != gt->ObjectSources.end(); ++si) + { + cmSourceFile* sf = *si; + std::string objectName = + cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()); + objectName += ".o"; + + std::string objectNameLower = cmSystemTools::LowerCase(objectName); + counts[objectNameLower] += 1; + if (2 == counts[objectNameLower]) + { + // TODO: emit warning about duplicate name? + } + + gt->Objects[sf] = objectName; + } + + const char* configName = this->GetCMakeCFGIntDir(); + std::string dir = this->GetObjectsNormalDirectory( + this->CurrentProject, configName, gt->Target); + if(this->XcodeVersion >= 21) + { + dir += "$(CURRENT_ARCH)/"; + } + else + { +#ifdef __ppc__ + dir += "ppc/"; +#endif +#ifdef __i386 + dir += "i386/"; +#endif + } + gt->ObjectDirectory = dir; +} diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 2004514..800963b 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -206,6 +206,8 @@ protected: std::vector XCodeObjects; cmXCodeObject* RootObject; private: + void ComputeTargetObjects(cmGeneratorTarget* gt) const; + std::string GetObjectsNormalDirectory( const std::string &projName, const std::string &configName, -- cgit v0.12 From e8ea61587463f18dd552dc84a55d2091adff3071 Mon Sep 17 00:00:00 2001 From: David Cole Date: Thu, 15 Mar 2012 14:31:32 -0400 Subject: Build object library targets in Xcode Treat OBJECT libraries as STATIC libraries. The Xcode project file format provides no way to avoid running the libtool so hide the resulting .a away next to the object files as it should never be referenced. The object files will be left behind for reference by other targets later. --- Source/cmGlobalXCodeGenerator.cxx | 60 +++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 8181886..e358bdf 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -409,6 +409,8 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, // this will make sure that when the next target is built // things are up-to-date if((target.GetType() == cmTarget::EXECUTABLE || +// Nope - no post-build for OBJECT_LIRBRARY +// target.GetType() == cmTarget::OBJECT_LIBRARY || target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::MODULE_LIBRARY)) @@ -1548,7 +1550,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string defFlags; bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) || (target.GetType() == cmTarget::MODULE_LIBRARY)); - bool binary = ((target.GetType() == cmTarget::STATIC_LIBRARY) || + bool binary = ((target.GetType() == cmTarget::OBJECT_LIBRARY) || + (target.GetType() == cmTarget::STATIC_LIBRARY) || (target.GetType() == cmTarget::EXECUTABLE) || shared); @@ -1635,7 +1638,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, } const char* linkFlagsProp = "LINK_FLAGS"; - if(target.GetType() == cmTarget::STATIC_LIBRARY) + if(target.GetType() == cmTarget::OBJECT_LIBRARY || + target.GetType() == cmTarget::STATIC_LIBRARY) { linkFlagsProp = "STATIC_LIBRARY_FLAGS"; } @@ -1689,11 +1693,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::string pnprefix; std::string pnbase; std::string pnsuffix; - target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); - // Store the product name for all target types. - buildSettings->AddAttribute("PRODUCT_NAME", - this->CreateString(pnbase.c_str())); + target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName); // Set attributes to specify the proper name for the target. std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory(); @@ -1717,17 +1718,44 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CreateString(pndir.c_str())); pndir = target.GetDirectory(configName); } + buildSettings->AddAttribute("EXECUTABLE_PREFIX", this->CreateString(pnprefix.c_str())); buildSettings->AddAttribute("EXECUTABLE_SUFFIX", this->CreateString(pnsuffix.c_str())); } + else if(target.GetType() == cmTarget::OBJECT_LIBRARY) + { + pnprefix = "lib"; + pnbase = target.GetName(); + pnsuffix = ".a"; + + if(this->XcodeVersion >= 21) + { + std::string pncdir = this->GetObjectsNormalDirectory( + this->CurrentProject, configName, &target); + buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", + this->CreateString(pncdir.c_str())); + } + else + { + buildSettings->AddAttribute("OBJROOT", + this->CreateString(pndir.c_str())); + pndir = this->GetObjectsNormalDirectory( + this->CurrentProject, configName, &target); + } + } + + // Store the product name for all target types. + buildSettings->AddAttribute("PRODUCT_NAME", + this->CreateString(pnbase.c_str())); buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir.c_str())); // Handle settings for each target type. switch(target.GetType()) { + case cmTarget::OBJECT_LIBRARY: case cmTarget::STATIC_LIBRARY: { buildSettings->AddAttribute("LIBRARY_STYLE", @@ -2231,6 +2259,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget) { switch(cmtarget.GetType()) { + case cmTarget::OBJECT_LIBRARY: case cmTarget::STATIC_LIBRARY: return "archive.ar"; case cmTarget::MODULE_LIBRARY: @@ -2254,6 +2283,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget) { switch(cmtarget.GetType()) { + case cmTarget::OBJECT_LIBRARY: case cmTarget::STATIC_LIBRARY: return "com.apple.product-type.library.static"; case cmTarget::MODULE_LIBRARY: @@ -2311,7 +2341,17 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget, { fileRef->AddAttribute("explicitFileType", this->CreateString(fileType)); } - std::string fullName = cmtarget.GetFullName(defConfig.c_str()); + std::string fullName; + if(cmtarget.GetType() == cmTarget::OBJECT_LIBRARY) + { + fullName = "lib"; + fullName += cmtarget.GetName(); + fullName += ".a"; + } + else + { + fullName = cmtarget.GetFullName(defConfig.c_str()); + } fileRef->AddAttribute("path", this->CreateString(fullName.c_str())); fileRef->AddAttribute("refType", this->CreateString("0")); fileRef->AddAttribute("sourceTree", @@ -2516,7 +2556,8 @@ void cmGlobalXCodeGenerator } // Skip link information for static libraries. - if(cmtarget->GetType() == cmTarget::STATIC_LIBRARY) + if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY || + cmtarget->GetType() == cmTarget::STATIC_LIBRARY) { return; } @@ -2664,6 +2705,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, std::vector classes = cmtarget.GetSourceFiles(); + // Put cmSourceFile instances in proper groups: for(std::vector::const_iterator s = classes.begin(); s != classes.end(); s++) { @@ -3197,6 +3239,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( cmTarget* t =target->GetTarget(); if(t->GetType() == cmTarget::EXECUTABLE || +// Nope - no post-build for OBJECT_LIRBRARY +// t->GetType() == cmTarget::OBJECT_LIBRARY || t->GetType() == cmTarget::STATIC_LIBRARY || t->GetType() == cmTarget::SHARED_LIBRARY || t->GetType() == cmTarget::MODULE_LIBRARY) -- cgit v0.12 From 63d1be8b0007feafa69b16fb9c8682c992017c9a Mon Sep 17 00:00:00 2001 From: David Cole Date: Fri, 16 Mar 2012 10:14:33 -0400 Subject: Xcode: Honor $ source expressions Add objects from object libraries referenced using this syntax to the set of objects linked in a target. --- Source/cmGlobalXCodeGenerator.cxx | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index e358bdf..f17a50d 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -295,6 +295,10 @@ void cmGlobalXCodeGenerator::Generate() } this->ForceLinkerLanguages(); this->cmGlobalGenerator::Generate(); + if(cmSystemTools::GetErrorOccuredFlag()) + { + return; + } for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it) { cmLocalGenerator* root = it->second[0]; @@ -945,6 +949,20 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, } } + // Add object library contents as external objects. (Equivalent to + // the externalObjFiles above, except each one is not a cmSourceFile + // within the target.) + std::vector objs; + this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string obj = *oi; + cmXCodeObject* xsf = + this->CreateXCodeSourceFileFromPath(obj, cmtarget, ""); + externalObjFiles.push_back(xsf); + } + // some build phases only apply to bundles and/or frameworks bool isFrameworkTarget = cmtarget.IsFrameworkOnApple(); bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE"); @@ -2719,6 +2737,21 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, cmStdString key = GetGroupMapKey(cmtarget, sf); this->GroupMap[key] = pbxgroup; } + + // Put OBJECT_LIBRARY objects in proper groups: + std::vector objs; + this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + for(std::vector::const_iterator + oi = objs.begin(); oi != objs.end(); ++oi) + { + std::string const& source = *oi; + cmSourceGroup& sourceGroup = + mf->FindSourceGroup(source.c_str(), sourceGroups); + cmXCodeObject* pbxgroup = + this->CreateOrGetPBXGroup(cmtarget, &sourceGroup); + cmStdString key = GetGroupMapKeyFromPath(cmtarget, source); + this->GroupMap[key] = pbxgroup; + } } } } -- cgit v0.12