summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Cole <david.cole@kitware.com>2012-03-20 13:34:35 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2012-03-20 13:34:35 (GMT)
commit31c0bc021940420fcf383bde390c59beb2cd9b9c (patch)
tree6b8507775944f1deca58394332891d8ff276610e
parentb06f7c077b15de1a2bf354b64092565d0e49d719 (diff)
parent93d5509b5b1c208f3ed28daf35f9384ab6918441 (diff)
downloadCMake-31c0bc021940420fcf383bde390c59beb2cd9b9c.zip
CMake-31c0bc021940420fcf383bde390c59beb2cd9b9c.tar.gz
CMake-31c0bc021940420fcf383bde390c59beb2cd9b9c.tar.bz2
Merge topic 'object-library'
93d5509 Merge branch 'ninja-object-library' into object-library 821037c Merge branch 'xcode-object-library' into object-library eb24c99 Merge branch 'object-library' into xcode-object-library 63d1be8 Xcode: Honor $<TARGET_OBJECTS:...> source expressions 020ba38 Merge branch 'object-library' into xcode-object-library e8ea615 Build object library targets in Xcode 8045e17 Pre-compute object file names before Xcode generation 247a132 Allow txt files as ExtraSources in object library targets b063599 Add a default source group for object files. be01f3b Xcode: Re-factor some existing methods into "FromPath" variants 2693dbe Merge branch 'object-library' into ninja-object-library 51997cb Ninja: Honor $<TARGET_OBJECTS:...> source expressions 23ec258 Merge branch 'object-library' into ninja-object-library 61124de Build object library targets in Ninja f5b06cd Pre-compute object file names before Ninja generation a2514f1 Simplify cmNinjaTargetGenerator using cmGeneratorTarget ...
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmAddLibraryCommand.cxx14
-rw-r--r--Source/cmAddLibraryCommand.h20
-rw-r--r--Source/cmComputeLinkDepends.cxx13
-rw-r--r--Source/cmExportCommand.cxx8
-rw-r--r--Source/cmGeneratorTarget.cxx172
-rw-r--r--Source/cmGeneratorTarget.h63
-rw-r--r--Source/cmGlobalGenerator.cxx57
-rw-r--r--Source/cmGlobalGenerator.h13
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx30
-rw-r--r--Source/cmGlobalNinjaGenerator.h6
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx38
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx70
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx333
-rw-r--r--Source/cmGlobalXCodeGenerator.h15
-rw-r--r--Source/cmInstallCommand.cxx11
-rw-r--r--Source/cmInstallTargetGenerator.cxx1
-rw-r--r--Source/cmLocalGenerator.cxx4
-rw-r--r--Source/cmLocalNinjaGenerator.cxx31
-rw-r--r--Source/cmLocalNinjaGenerator.h3
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx40
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h5
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx141
-rw-r--r--Source/cmLocalVisualStudio6Generator.h3
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx126
-rw-r--r--Source/cmLocalVisualStudio7Generator.h6
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx63
-rw-r--r--Source/cmLocalVisualStudioGenerator.h8
-rw-r--r--Source/cmMakefile.cxx18
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx26
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h1
-rw-r--r--Source/cmMakefileTargetGenerator.cxx137
-rw-r--r--Source/cmMakefileTargetGenerator.h8
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx40
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h1
-rw-r--r--Source/cmNinjaTargetGenerator.cxx96
-rw-r--r--Source/cmNinjaTargetGenerator.h5
-rw-r--r--Source/cmSourceGroup.cxx6
-rw-r--r--Source/cmSourceGroup.h1
-rw-r--r--Source/cmTarget.cxx44
-rw-r--r--Source/cmTarget.h10
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx10
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx124
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h4
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/ObjectLibrary/A/CMakeLists.txt17
-rw-r--r--Tests/ObjectLibrary/A/a.h6
-rw-r--r--Tests/ObjectLibrary/A/a1.c.in2
-rw-r--r--Tests/ObjectLibrary/A/a2.c2
-rw-r--r--Tests/ObjectLibrary/AB.def5
-rw-r--r--Tests/ObjectLibrary/B/CMakeLists.txt15
-rw-r--r--Tests/ObjectLibrary/B/b.h11
-rw-r--r--Tests/ObjectLibrary/B/b1.c2
-rw-r--r--Tests/ObjectLibrary/B/b1_vs6.c1
-rw-r--r--Tests/ObjectLibrary/B/b2.c2
-rw-r--r--Tests/ObjectLibrary/B/b2_vs6.c1
-rw-r--r--Tests/ObjectLibrary/CMakeLists.txt52
-rw-r--r--Tests/ObjectLibrary/c.c19
-rw-r--r--Tests/ObjectLibrary/dummy.c1
-rw-r--r--Tests/ObjectLibrary/dummy.objbin0 -> 498 bytes
-rw-r--r--Tests/ObjectLibrary/main.c16
-rw-r--r--Tests/ObjectLibrary/mainAB.c22
-rw-r--r--Tests/RunCMake/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt8
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt8
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake15
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/ObjectLibrary/a.c1
-rw-r--r--Tests/RunCMake/ObjectLibrary/a.cxx1
-rw-r--r--Tests/RunCMake/ObjectLibrary/bad.def0
-rw-r--r--Tests/RunCMake/ObjectLibrary/bad.obj0
-rwxr-xr-xbootstrap1
121 files changed, 1701 insertions, 477 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 18f9b8b..f9d1c03 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/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/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_<CONFIG>) "
"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(<name> OBJECT <src>...)\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 "
+ "$<TARGET_OBJECTS:objlib> as a source, where \"objlib\" is the "
+ "object library name. "
+ "For example:\n"
+ " add_library(... $<TARGET_OBJECTS:objlib> ...)\n"
+ " add_executable(... $<TARGET_OBJECTS:objlib> ...)\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."
;
}
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
new file mode 100644
index 0000000..4529d1c
--- /dev/null
+++ b/Source/cmGeneratorTarget.cxx
@@ -0,0 +1,172 @@
+/*============================================================================
+ 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();
+ this->LookupObjectLibraries();
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ClassifySources()
+{
+ bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY;
+ std::vector<cmSourceFile*> badObjLib;
+ std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::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);
+ if(isObjLib) { badObjLib.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);
+ 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()))
+ {
+ // 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);
+ if(isObjLib && cmSystemTools::LowerCase(sf->GetExtension()) != "txt")
+ {
+ badObjLib.push_back(sf);
+ }
+ }
+ }
+
+ if(!badObjLib.empty())
+ {
+ cmOStringStream e;
+ e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n";
+ for(std::vector<cmSourceFile*>::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());
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::LookupObjectLibraries()
+{
+ std::vector<std::string> const& objLibs =
+ this->Target->GetObjectLibraries();
+ for(std::vector<std::string>::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<std::string>& objs)
+{
+ for(std::vector<cmTarget*>::const_iterator
+ ti = this->ObjectLibraries.begin();
+ ti != this->ObjectLibraries.end(); ++ti)
+ {
+ cmTarget* objLib = *ti;
+ cmGeneratorTarget* ogt =
+ this->GlobalGenerator->GetGeneratorTarget(objLib);
+ for(std::vector<cmSourceFile*>::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
new file mode 100644
index 0000000..6319d82
--- /dev/null
+++ b/Source/cmGeneratorTarget.h
@@ -0,0 +1,63 @@
+/*============================================================================
+ 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<cmSourceFile*> CustomCommands;
+ std::vector<cmSourceFile*> ExtraSources;
+ std::vector<cmSourceFile*> HeaderSources;
+ std::vector<cmSourceFile*> ObjectSources;
+ std::vector<cmSourceFile*> ExternalObjects;
+ std::vector<cmSourceFile*> OSXContent;
+ std::string ModuleDefinitionFile;
+
+ std::map<cmSourceFile const*, std::string> Objects;
+ std::set<cmSourceFile const*> 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;
+
+ std::vector<cmTarget*> ObjectLibraries;
+
+ void UseObjectLibraries(std::vector<std::string>& objs);
+
+private:
+ void ClassifySources();
+ void LookupObjectLibraries();
+
+ cmGeneratorTarget(cmGeneratorTarget const&);
+ void operator=(cmGeneratorTarget const&);
+};
+
+#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index a988844..545f9e8 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 <cmsys/Directory.hxx>
@@ -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,55 @@ 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;
+ cmGeneratorTarget* gt = new cmGeneratorTarget(t);
+ this->GeneratorTargets[t] = gt;
+ this->ComputeTargetObjects(gt);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+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::ComputeTargetObjects(cmGeneratorTarget*) const
+{
+ // Implemented in generator subclasses that need this.
+}
void cmGlobalGenerator::CheckLocalGenerators()
{
@@ -1714,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 1a0e41a..80b948b 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;
@@ -183,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; }
@@ -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<cmStdString, std::vector<cmLocalGenerator*> >& GetProjectMap()
const {return this->ProjectMap;}
@@ -370,6 +374,13 @@ private:
typedef std::map<cmTarget *, TargetDependSet> TargetDependMap;
TargetDependMap TargetDependencies;
+ // Per-target generator information.
+ typedef std::map<cmTarget*, cmGeneratorTarget*> GeneratorTargetsType;
+ 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<cmStdString>
{
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 7c1529b..9cbd502 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<cmSourceFile*>::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()
@@ -635,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/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/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index a23c0d8..e63de9c 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,38 @@ void cmGlobalUnixMakefileGenerator3
}
//----------------------------------------------------------------------------
+void
+cmGlobalUnixMakefileGenerator3
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ cmTarget* target = gt->Target;
+ cmLocalUnixMakefileGenerator3* lg =
+ static_cast<cmLocalUnixMakefileGenerator3*>(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 += "/";
+ gt->ObjectDirectory = dir_max;
+
+ // Compute the name of each object file.
+ for(std::vector<cmSourceFile*>::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) {
@@ -378,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);
@@ -413,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.
@@ -587,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.
@@ -673,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;
@@ -982,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/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/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/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 449d090..7da4f86 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,64 @@ void cmGlobalVisualStudioGenerator::Generate()
}
//----------------------------------------------------------------------------
+void
+cmGlobalVisualStudioGenerator
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ cmLocalVisualStudioGenerator* lg =
+ static_cast<cmLocalVisualStudioGenerator*>(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<cmStdString, int> counts;
+ for(std::vector<cmSourceFile*>::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<cmSourceFile*>::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;
+ }
+
+ 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;
+}
+
+//----------------------------------------------------------------------------
bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
const std::string& regKeyBase,
std::string& nextAvailableSubKeyName);
@@ -315,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())
@@ -398,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/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<cmTarget*, cmStdString> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
private:
+ void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
class TargetSetMap: public std::map<cmTarget*, TargetSet> {};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 0bbe0a0..56228f5 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 <cmsys/auto_ptr.hxx>
@@ -303,6 +304,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];
@@ -417,6 +422,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))
@@ -570,15 +577,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,
@@ -612,14 +647,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);
@@ -671,36 +708,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")
{
@@ -735,25 +748,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
// {
@@ -763,11 +776,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())?
"<absolute>" : "SOURCE_ROOT");
@@ -782,6 +835,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" ||
@@ -889,6 +958,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<std::string> objs;
+ this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::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");
@@ -1494,7 +1577,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);
@@ -1581,7 +1665,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";
}
@@ -1635,11 +1720,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();
@@ -1663,17 +1745,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",
@@ -2177,6 +2286,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:
@@ -2200,6 +2310,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:
@@ -2257,7 +2368,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",
@@ -2462,7 +2583,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;
}
@@ -2610,6 +2732,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
std::vector<cmSourceFile*> classes = cmtarget.GetSourceFiles();
+ // Put cmSourceFile instances in proper groups:
for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
s != classes.end(); s++)
{
@@ -2623,6 +2746,21 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
cmStdString key = GetGroupMapKey(cmtarget, sf);
this->GroupMap[key] = pbxgroup;
}
+
+ // Put OBJECT_LIBRARY objects in proper groups:
+ std::vector<std::string> objs;
+ this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::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;
+ }
}
}
}
@@ -3055,6 +3193,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<cmXCodeObject*>& targets)
@@ -3123,6 +3281,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)
@@ -3178,15 +3338,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<std::string>::iterator arch =
this->Architectures.begin();
arch != this->Architectures.end(); ++arch)
@@ -3292,7 +3445,7 @@ cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
}
//----------------------------------------------------------------------------
-const char* cmGlobalXCodeGenerator::GetCMakeCFGInitDirectory()
+const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
{
return this->XcodeVersion >= 21 ?
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
@@ -3545,3 +3698,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<cmStdString, int> counts;
+ for(std::vector<cmSourceFile*>::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 45f62eb..800963b 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*);
@@ -153,6 +153,12 @@ private:
std::vector<cmLocalGenerator*>& generators);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& 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,
@@ -200,6 +206,13 @@ protected:
std::vector<cmXCodeObject*> XCodeObjects;
cmXCodeObject* RootObject;
private:
+ void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
+ 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);
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<std::string> 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<std::string> 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 a7f201c..13ede5d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1914,6 +1914,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/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<cmGlobalNinjaGenerator*>(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/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index fdf59b2..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());
@@ -2009,45 +2010,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<std::string>& objects);
- std::string GetObjectFileName(cmTarget& target,
- const cmSourceFile& source,
- std::string* nameWithoutTargetDir = 0,
- bool* hasSourceExtension = 0);
-
void AppendRuleDepend(std::vector<std::string>& depends,
const char* ruleFileName);
void AppendRuleDepends(std::vector<std::string>& depends,
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 678c5bf..5b99dfd 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"
@@ -126,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:
@@ -336,9 +338,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 +357,8 @@ void cmLocalVisualStudio6Generator
::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
std::ostream &fout, const char *libName)
{
+ cmGeneratorTarget* gt =
+ this->GlobalGenerator->GetGeneratorTarget(&target);
const std::vector<const cmSourceFile *> &sourceFiles =
sg->GetSourceFiles();
// If the group is empty, don't write it at all.
@@ -374,28 +375,6 @@ void cmLocalVisualStudio6Generator
this->WriteDSPBeginGroup(fout, name.c_str(), "");
}
- // Compute the maximum length configuration name.
- std::string config_max;
- for(std::vector<std::string>::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 cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
@@ -406,11 +385,9 @@ void cmLocalVisualStudio6Generator
std::string compileFlags;
std::vector<std::string> 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.
@@ -1264,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;
@@ -1275,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()));
@@ -1288,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;
@@ -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.
@@ -1456,7 +1466,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());
@@ -1555,7 +1566,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());
@@ -1565,13 +1576,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,
@@ -1588,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)
@@ -1743,6 +1752,8 @@ void cmLocalVisualStudio6Generator
ItemVector const& linkLibs = cli.GetItems();
std::vector<std::string> const& linkDirs = cli.GetDirectories();
+ this->OutputObjects(target, "LINK", options);
+
// Build the link options code.
for(std::vector<std::string>::const_iterator d = linkDirs.begin();
d != linkDirs.end(); ++d)
@@ -1787,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<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ for(std::vector<std::string>::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
@@ -1795,6 +1828,36 @@ cmLocalVisualStudio6Generator
return "";
}
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio6Generator
+::ComputeLongestObjectDirectory(cmTarget&) const
+{
+ // Compute the maximum length configuration name.
+ std::string config_max;
+ for(std::vector<std::string>::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..a680633 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;
@@ -86,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<std::string> Configurations;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index c5714cc..363d370 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"
@@ -38,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;
};
@@ -641,6 +643,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";
@@ -1000,6 +1004,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\t<Tool\n"
+ << "\t\t\t\tName=\"" << tool << "\"\n";
+ fout << "\t\t\t\tOutputFile=\""
+ << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
+ break;
+ }
case cmTarget::STATIC_LIBRARY:
{
std::string targetNameFull = target.GetFullName(configName);
@@ -1014,6 +1034,15 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"" << tool << "\"\n";
+ if(this->GetVersion() < 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"))
{
@@ -1074,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);
@@ -1155,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);
@@ -1244,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<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ const char* sep = isep? isep : "";
+ for(std::vector<std::string>::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<std::string> const& dirs)
@@ -1310,9 +1371,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
@@ -1328,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<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ if(!objs.empty())
+ {
+ // TODO: Separate sub-filter for each object library used?
+ fout << "\t\t<Filter Name=\"Object Libraries\">\n";
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str());
+ fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n";
+ }
+ fout << "\t\t</Filter>\n";
+ }
+ }
fout << "\t</Files>\n";
@@ -1352,8 +1430,7 @@ public:
cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
cmTarget& target,
cmSourceFile const& sf,
- std::vector<std::string>* configs,
- std::string const& dir_max);
+ std::vector<std::string>* configs);
std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
};
@@ -1361,13 +1438,14 @@ cmLocalVisualStudio7GeneratorFCInfo
::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
cmTarget& target,
cmSourceFile const& sf,
- std::vector<std::string>* configs,
- std::string const& dir_max)
+ std::vector<std::string>* 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 +1556,11 @@ cmLocalVisualStudio7GeneratorFCInfo
}
}
-
-void cmLocalVisualStudio7Generator
-::ComputeMaxDirectoryLength(std::string& maxdir,
- cmTarget& target)
-{
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio7Generator
+::ComputeLongestObjectDirectory(cmTarget& target) const
+{
std::vector<std::string> *configs =
static_cast<cmGlobalVisualStudio7Generator *>
(this->GlobalGenerator)->GetConfigurations();
@@ -1507,7 +1585,7 @@ void cmLocalVisualStudio7Generator
dir_max += "/";
dir_max += config_max;
dir_max += "/";
- maxdir = dir_max;
+ return dir_max;
}
void cmLocalVisualStudio7Generator
@@ -1530,19 +1608,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 cmSourceFile *>::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<cmSourceFile*> 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<cmStdString, int> counts;
- for(std::vector<cmSourceFile*>::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<cmSourceFile*>::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<cmCustomCommand>
MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran);
- // Safe object file name generation.
- void ComputeObjectNameRequirements(std::vector<cmSourceFile*> const&);
- bool SourceFileCompiles(const cmSourceFile* sf);
- std::set<const cmSourceFile*> NeedObjectName;
- friend class cmVisualStudio10TargetGenerator;
-
VSVersion Version;
};
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f90c35c..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();
@@ -853,6 +854,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<std::string> no_output;
cmCustomCommand cc(this, no_output, depends,
@@ -945,7 +954,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
outName += ".rule";
const char* dir =
this->LocalGenerator->GetGlobalGenerator()->
- GetCMakeCFGInitDirectory();
+ GetCMakeCFGIntDir();
if(dir && dir[0] == '$')
{
cmSystemTools::ReplaceString(outName, dir,
@@ -1912,8 +1921,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;
}
@@ -2865,7 +2877,7 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const & lang,
{
this->AddDefinition("CMAKE_CFG_INTDIR",
this->LocalGenerator->GetGlobalGenerator()
- ->GetCMakeCFGInitDirectory());
+ ->GetCMakeCFGIntDir());
this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this,
optional);
}
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<std::string> commands;
+ std::vector<std::string> 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 b9120c4..a0e0481 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<cmGlobalUnixMakefileGenerator3*>(
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"))
@@ -63,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:
@@ -131,58 +134,49 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// First generate the object rule files. Save a list of all object
// files for this target.
- const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
+ for(std::vector<cmSourceFile*>::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<std::string>& outputs = cc->GetOutputs();
- for(std::vector<std::string>::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<std::string>& outputs = cc->GetOutputs();
+ for(std::vector<std::string>::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<cmSourceFile*>::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<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ this->ExternalObjects.push_back((*si)->GetFullPath());
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
+ {
+ // Generate this object file's rule file.
+ this->WriteObjectRuleFiles(**si);
+ }
+
+ // Add object library contents as external objects.
+ this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
}
@@ -428,12 +422,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())
@@ -487,10 +479,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);
}
//----------------------------------------------------------------------------
@@ -1612,7 +1600,7 @@ void cmMakefileTargetGenerator
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator
-::AppendLinkDepends(std::vector<std::string>& depends)
+::AppendObjectDepends(std::vector<std::string>& depends)
{
// Add dependencies on the compiled object files.
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
@@ -1625,25 +1613,32 @@ 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<std::string>::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());
+}
- // Add a dependency on the link definitions file, if any.
- if(!this->ModuleDefinitionFile.empty())
- {
- depends.push_back(this->ModuleDefinitionFile);
- }
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::AppendLinkDepends(std::vector<std::string>& depends)
+{
+ this->AppendObjectDepends(depends);
- // Add dependencies on the external object files.
- for(std::vector<std::string>::const_iterator obj
- = this->ExternalObjects.begin();
- obj != this->ExternalObjects.end(); ++obj)
+ // 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())
{
- depends.push_back(*obj);
+ depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
}
// Add user-specified dependencies.
@@ -1971,7 +1966,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 +1983,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..e1e554b 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;
@@ -117,6 +118,9 @@ protected:
// append intertarget dependencies
void AppendTargetDepends(std::vector<std::string>& depends);
+ // Append object file dependencies.
+ void AppendObjectDepends(std::vector<std::string>& depends);
+
// Append link rule dependencies (objects, etc.).
void AppendLinkDepends(std::vector<std::string>& depends);
@@ -157,6 +161,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 +203,6 @@ protected:
std::vector<std::string> Objects;
std::vector<std::string> 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<cmStdString> ObjectFiles;
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<std::string> ComputeLinkCmd();
private:
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 9acbc67..4c4a53f 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"
@@ -33,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:
@@ -60,6 +62,8 @@ cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
Objects()
{
+ this->GeneratorTarget =
+ this->GetGlobalGenerator()->GetGeneratorTarget(target);
}
cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
@@ -218,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 =
@@ -231,9 +236,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;
@@ -253,7 +258,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;
}
@@ -377,12 +385,37 @@ cmNinjaTargetGenerator
<< this->GetTargetName()
<< "\n\n";
- // For each source files of this target.
- for(std::vector<cmSourceFile*>::const_iterator i =
- this->GetTarget()->GetSourceFiles().begin();
- i != this->GetTarget()->GetSourceFiles().end();
- ++i)
- this->WriteObjectBuildStatement(*i);
+ for(std::vector<cmSourceFile*>::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<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ this->Objects.push_back(this->GetSourceFilePath(*si));
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
+ {
+ this->WriteObjectBuildStatement(*si);
+ }
+
+ {
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ for(std::vector<std::string>::iterator oi = objs.begin();
+ oi != objs.end(); ++oi)
+ {
+ this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
+ }
+ }
this->GetBuildFileStream() << "\n";
}
@@ -391,26 +424,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 +452,16 @@ cmNinjaTargetGenerator
std::back_inserter(orderOnlyDeps), MapToNinjaPath());
}
- // Add order-only dependency on any header file with a custom command.
- {
- const std::vector<cmSourceFile*>& sources =
- this->GetTarget()->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
- si != sources.end(); ++si) {
- if (!(*si)->GetLanguage()) {
- if (cmCustomCommand* cc = (*si)->GetCustomCommand()) {
- const std::vector<std::string>& 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<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
+ {
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ const std::vector<std::string>& 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
@@ -493,7 +505,7 @@ void
cmNinjaTargetGenerator
::AddModuleDefinitionFlag(std::string& flags)
{
- if(this->ModuleDefinitionFile.empty())
+ if(this->GeneratorTarget->ModuleDefinitionFile.empty())
{
return;
}
@@ -510,6 +522,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
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<const cmSourceFile*>& cmSourceGroup::GetSourceFiles() const
}
//----------------------------------------------------------------------------
-std::vector<const cmSourceFile*>& 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<const cmSourceFile*>& GetSourceFiles() const;
- std::vector<const cmSourceFile*>& GetSourceFiles();
std::vector<cmSourceGroup> const& GetGroupChildren() const;
private:
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 2fbca80..a516cbc 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:
@@ -1727,7 +1729,15 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
for(std::vector<std::string>::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);
+ }
}
}
@@ -1746,6 +1756,24 @@ cmSourceFile* cmTarget::AddSource(const char* s)
}
//----------------------------------------------------------------------------
+void cmTarget::ProcessSourceExpression(std::string const& expr)
+{
+ if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 &&
+ expr[expr.size()-1] == '>')
+ {
+ 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)
{
@@ -4545,7 +4573,21 @@ void cmTarget::ComputeLinkImplementation(const char* config,
// This target needs runtime libraries for its source languages.
std::set<cmStdString> languages;
+ // Get languages used in our source files.
this->GetLanguages(languages);
+ // Get languages used in object library sources.
+ for(std::vector<std::string>::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<cmStdString>::iterator li = languages.begin();
li != languages.end(); ++li)
{
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index ff05cd3..d41c827 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 };
@@ -116,6 +117,10 @@ public:
*/
std::vector<cmSourceFile*> const& GetSourceFiles();
void AddSourceFile(cmSourceFile* sf);
+ std::vector<std::string> const& GetObjectLibraries() const
+ {
+ return this->ObjectLibraries;
+ }
/** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf);
@@ -548,6 +553,7 @@ private:
std::vector<cmCustomCommand> PostBuildCommands;
TargetType TargetTypeValue;
std::vector<cmSourceFile*> SourceFiles;
+ std::vector<std::string> ObjectLibraries;
LinkLibraryVectorType LinkLibraries;
LinkLibraryVectorType PrevLinkedLibraries;
bool LinkLibrariesAnalyzed;
@@ -589,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/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)
{
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 66f9a36..054b86b 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,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->ComputeObjectNames();
this->BuildFileStream = 0;
}
@@ -147,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())
{
@@ -358,6 +359,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
case cmTarget::MODULE_LIBRARY:
configType += "DynamicLibrary";
break;
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::STATIC_LIBRARY:
configType += "StaticLibrary";
break;
@@ -388,7 +390,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
mfcLine += useOfMfcValue + "</UseOfMfc>\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"))
{
@@ -421,12 +423,11 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
void cmVisualStudio10TargetGenerator::WriteCustomCommands()
{
this->SourcesVisited.clear();
- std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
{
- cmSourceFile* sf = *source;
- this->WriteCustomCommand(sf);
+ this->WriteCustomCommand(*si);
}
}
@@ -634,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<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ if(!objs.empty())
+ {
+ this->WriteString("<ItemGroup>\n", 1);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string obj = *oi;
+ this->WriteString("<Object Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\">\n";
+ this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
+ this->WriteString("</Object>\n", 2);
+ }
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+
this->WriteString("<ItemGroup>\n", 1);
for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
g != groupsUsed.end(); ++g)
@@ -657,6 +677,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("</Filter>\n", 2);
}
}
+ if(!objs.empty())
+ {
+ this->WriteString("<Filter Include=\"Object Libraries\">\n", 2);
+ std::string guidName = "SG_Filter_Object Libraries";
+ this->GlobalGenerator->CreateGUID(guidName.c_str());
+ this->WriteString("<UniqueIdentifier>", 3);
+ std::string guid =
+ this->GlobalGenerator->GetGUID(guidName.c_str());
+ (*this->BuildFileStream) << "{" << guid << "}"
+ << "</UniqueIdentifier>\n";
+ this->WriteString("</Filter>\n", 2);
+ }
this->WriteString("</ItemGroup>\n", 1);
this->WriteGroupSources("None", none, sourceGroups);
this->WriteString("</Project>\n", 0);
@@ -872,26 +904,20 @@ void cmVisualStudio10TargetGenerator::WriteCLSources()
(*this->BuildFileStream ) << " />\n";
}
}
- this->WriteString("</ItemGroup>\n", 1);
-}
-void cmVisualStudio10TargetGenerator::ComputeObjectNames()
-{
- // get the classes from the source lists then add them to the groups
- std::vector<cmSourceFile*>const & classes = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::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();
- }
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string obj = *oi;
+ this->WriteString("<Object Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\" />\n";
}
- // Compute which sources need unique object computation.
- this->LocalGenerator->ComputeObjectNameRequirements(classes);
+ this->WriteString("</ItemGroup>\n", 1);
}
bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
@@ -900,16 +926,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;
@@ -1030,20 +1051,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
- << "\\"
<< "</OutDir>\n";
this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
@@ -1277,11 +1307,15 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
*this->BuildFileStream << configName
<< "</AssemblerListingLocation>\n";
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
- << "/"
- << this->Target->GetPDBName(configName.c_str())
- << "</ProgramDataBaseFileName>\n";
+ if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
+ {
+ // TODO: PDB for object library?
+ this->WriteString("<ProgramDataBaseFileName>", 3);
+ *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
+ << "/"
+ << this->Target->GetPDBName(configName.c_str())
+ << "</ProgramDataBaseFileName>\n";
+ }
this->WriteString("</ClCompile>\n", 2);
}
@@ -1513,10 +1547,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");
@@ -1592,7 +1626,7 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1);
*this->BuildFileStream << "\n";
// output cl compile flags <ClCompile></ClCompile>
- if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY)
+ if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
{
this->WriteClOptions(*i, includes);
// output rc compile flags <ResourceCompile></ResourceCompile>
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<cmCustomCommand> & commands,
std::string const& configName);
- void ComputeObjectNames();
void WriteGroupSources(const char* name,
std::vector<cmSourceFile*> const& sources,
std::vector<cmSourceGroup>& );
@@ -87,9 +87,9 @@ private:
typedef cmVisualStudioGeneratorOptions Options;
typedef std::map<cmStdString, Options*> OptionsMap;
OptionsMap ClOptions;
- std::string ModuleDefinitionFile;
std::string PathToVcxproj;
cmTarget* Target;
+ cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
std::string Platform;
std::string GUID;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 5f125a4..c0b7cd6 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/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/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..8723415
--- /dev/null
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required(VERSION 2.8)
+project(ObjectLibrary C)
+
+add_subdirectory(A)
+add_subdirectory(B)
+
+add_library(Cstatic STATIC c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+add_executable(UseCstatic main.c)
+target_link_libraries(UseCstatic Cstatic)
+
+add_library(Cshared SHARED c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:Bexport>)
+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 $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+
+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} $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+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 $<TARGET_OBJECTS:A>)
+if(CMAKE_LINK_DEF_FILE_FLAG OR NOT WIN32)
+ list(APPEND ABshared_SRCS $<TARGET_OBJECTS:B> AB.def)
+else()
+ set(NO_A NO_A)
+ list(APPEND ABshared_SRCS $<TARGET_OBJECTS:Bexport>)
+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}
+ $<TARGET_OBJECTS:ABmain> $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>
+ )
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/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
--- /dev/null
+++ b/Tests/ObjectLibrary/dummy.obj
Binary files differ
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()
+ ;
+}
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()
+ ;
+}
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:
+
+ \$<BAD_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 $<BAD_EXPRESSION>)
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 $<TARGET_OBJECTS:DoesNotExist>)
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 $<TARGET_OBJECTS:NotObjLib>)
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/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 $<TARGET_OBJECTS:A>)
+
+# 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/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 $<TARGET_OBJECTS:A>)
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..55db14d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -0,0 +1,18 @@
+include(RunCMake)
+
+run_cmake(BadSourceExpression1)
+run_cmake(BadSourceExpression2)
+run_cmake(BadSourceExpression3)
+run_cmake(BadObjSource1)
+run_cmake(BadObjSource2)
+run_cmake(Export)
+run_cmake(ExportLanguages)
+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/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; }
diff --git a/Tests/RunCMake/ObjectLibrary/bad.def b/Tests/RunCMake/ObjectLibrary/bad.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/bad.def
diff --git a/Tests/RunCMake/ObjectLibrary/bad.obj b/Tests/RunCMake/ObjectLibrary/bad.obj
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/bad.obj
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 \