summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalXCodeGenerator.cxx
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 /Source/cmGlobalXCodeGenerator.cxx
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 ...
Diffstat (limited to 'Source/cmGlobalXCodeGenerator.cxx')
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx333
1 files changed, 267 insertions, 66 deletions
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;
+}