summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Hoffman <bill.hoffman@kitware.com>2005-02-17 22:54:14 (GMT)
committerBill Hoffman <bill.hoffman@kitware.com>2005-02-17 22:54:14 (GMT)
commite9300434776a64567a65b6d414bcf98614321ba2 (patch)
tree94c37f27044ae655262878f5d5b3d90223d1f711
parent28f2dfb75244339d49e33fafb7103f5774222d2b (diff)
downloadCMake-e9300434776a64567a65b6d414bcf98614321ba2.zip
CMake-e9300434776a64567a65b6d414bcf98614321ba2.tar.gz
CMake-e9300434776a64567a65b6d414bcf98614321ba2.tar.bz2
ENH: more tests are passing, relative paths, and external objects are the ones left now
-rw-r--r--Source/cmGlobalGenerator.cxx2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx318
-rw-r--r--Source/cmGlobalXCodeGenerator.h8
-rw-r--r--Source/cmXCodeObject.h20
4 files changed, 258 insertions, 90 deletions
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 2f740d1..9b6e020 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -745,7 +745,7 @@ void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
}
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
- cmLocalGenerator* gen)
+ cmLocalGenerator* gen)
{
cmLocalGenerator* cur = gen->GetParent();
while(cur && cur != root)
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index c4e765c..7b6099e 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -24,9 +24,6 @@
//TODO
-// custom commands
-// custom targets
-// ALL_BUILD
// RUN_TESTS
// add a group for Sources Headers, and other cmake group stuff
@@ -195,23 +192,49 @@ void cmGlobalXCodeGenerator::Generate()
std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
{
+ cmLocalGenerator* root = it->second[0];
+ cmMakefile* mf = root->GetMakefile();
// add a ALL_BUILD target to the first makefile of each project
- it->second[0]->GetMakefile()->
- AddUtilityCommand("ALL_BUILD", "echo",
+ mf->AddUtilityCommand("ALL_BUILD", "echo",
"\"Build all projects\"",false,srcs);
- cmTarget* allbuild =
- it->second[0]->GetMakefile()->FindTarget("ALL_BUILD");
+ cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
+
+ std::string dir = root->ConvertToRelativeOutputPath(
+ mf->GetCurrentOutputDirectory());
+ m_CurrentXCodeHackMakefile = dir;
+ m_CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
+ std::string makecommand = "make -C ";
+ makecommand += dir;
+ makecommand += " -f ";
+ makecommand += m_CurrentXCodeHackMakefile;
+ mf->AddUtilityCommand("XCODE_DEPEND_HELPER", makecommand.c_str(),
+ "",
+ false,srcs);
+ cmTarget* xcodedephack = mf->FindTarget("XCODE_DEPEND_HELPER");
// now make the allbuild depend on all the non-utility targets
// in the project
for(std::vector<cmLocalGenerator*>::iterator i = it->second.begin();
i != it->second.end(); ++i)
{
cmLocalGenerator* lg = *i;
+ if(this->IsExcluded(root, *i))
+ {
+ continue;
+ }
cmTargets& tgts = lg->GetMakefile()->GetTargets();
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
{
cmTarget& target = l->second;
- if(target.GetType() < cmTarget::UTILITY)
+ // make all exe, shared libs and modules depend
+ // on the XCODE_DEPEND_HELPER target
+ if((target.GetType() == cmTarget::EXECUTABLE ||
+ target.GetType() == cmTarget::SHARED_LIBRARY ||
+ target.GetType() == cmTarget::MODULE_LIBRARY))
+ {
+ target.AddUtility(xcodedephack->GetName());
+ }
+
+ if(target.IsInAll())
{
allbuild->AddUtility(target.GetName());
}
@@ -291,11 +314,14 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
sourcecode += ext;
sourcecode += ext;
}
+ else if(sf->GetSourceExtension() == "mm")
+ {
+ sourcecode += ".cpp.objcpp";
+ }
else if(strcmp(lang, "C") == 0)
{
sourcecode += ".c.c";
}
- // default to c++
else
{
sourcecode += ".cpp.cpp";
@@ -331,6 +357,15 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
}
m_DoneAllBuild = true;
}
+ // make sure ALL_BUILD is only done once
+ if(l->first == "XCODE_DEPEND_HELPER")
+ {
+ if(m_DoneXCodeHack)
+ {
+ continue;
+ }
+ m_DoneXCodeHack = true;
+ }
if(cmtarget.GetType() == cmTarget::UTILITY ||
cmtarget.GetType() == cmTarget::INSTALL_FILES ||
cmtarget.GetType() == cmTarget::INSTALL_PROGRAMS)
@@ -542,6 +577,8 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
// have all depend on all outputs
makefileStream << "all: ";
+ std::map<const cmCustomCommand*, cmStdString> tname;
+ int count = 0;
for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
i != commands.end(); ++i)
{
@@ -555,7 +592,9 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
}
else
{
- makefileStream << "\\\n\t" << target.GetName();
+ char c = '1' + count++;
+ tname[&cc] = std::string(target.GetName()) + c;
+ makefileStream << "\\\n\t" << tname[&cc];
}
}
}
@@ -577,9 +616,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
}
else
{
- // if no outputs then use the target name as this must
- // be a utility target
- makefileStream << target.GetName() << ": ";
+ makefileStream << tname[&cc] << ": ";
}
for(std::vector<std::string>::const_iterator d = cc.GetDepends().begin();
d != cc.GetDepends().end(); ++d)
@@ -918,6 +955,23 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
cmXCodeObject* dependTarget)
{
+ // make sure a target does not depend on itself
+ if(target == dependTarget)
+ {
+ return;
+ }
+ // now avoid circular references if dependTarget already
+ // depends on target then skip it. Circular references crashes
+ // xcode
+ cmXCodeObject* dependTargetDepends = dependTarget->GetObject("dependencies");
+ if(dependTargetDepends)
+ {
+ if(dependTargetDepends->HasObject(target->GetPBXTargetDependency()))
+ {
+ return;
+ }
+ }
+
cmXCodeObject* targetdep = dependTarget->GetPBXTargetDependency();
if(!targetdep)
{
@@ -939,7 +993,7 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
this->CreateObjectReference(container));
dependTarget->SetPBXTargetDependency(targetdep);
}
-
+
cmXCodeObject* depends = target->GetObject("dependencies");
if(!depends)
{
@@ -947,46 +1001,28 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
}
else
{
- depends->AddObject(targetdep);
+ depends->AddUniqueObject(targetdep);
}
}
-void cmGlobalXCodeGenerator::AddLinkTarget(cmXCodeObject* target ,
- cmXCodeObject* dependTarget )
-{
- cmXCodeObject* ref = dependTarget->GetObject("productReference");
-
- cmXCodeObject* buildfile = this->CreateObject(cmXCodeObject::PBXBuildFile);
- buildfile->AddAttribute("fileRef", ref);
- cmXCodeObject* settings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- buildfile->AddAttribute("settings", settings);
-
- cmXCodeObject* buildPhases = target->GetObject("buildPhases");
- cmXCodeObject* frameworkBuildPhase =
- buildPhases->GetObject(cmXCodeObject::PBXFrameworksBuildPhase);
- cmXCodeObject* files = frameworkBuildPhase->GetObject("files");
- files->AddObject(buildfile);
-}
void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
- const char* library)
+ const char* library,
+ cmTarget* dtarget)
{
// if the library is a full path then create a file reference
// and build file and add them to the PBXFrameworksBuildPhase
// for the target
+ std::string file = library;
if(cmSystemTools::FileIsFullPath(library))
{
- std::string libPath = library;
- cmXCodeObject* fileRef =
- this->CreateObject(cmXCodeObject::PBXFileReference);
+ target->AddDependLibrary(library);
+ std::string dir;
+ cmSystemTools::SplitProgramPath(library, dir, file);
// add the library path to the search path for the target
cmXCodeObject* bset = target->GetObject("buildSettings");
if(bset)
{
- std::string dir;
- std::string file;
- cmSystemTools::SplitProgramPath(library, dir, file);
cmXCodeObject* spath = bset->GetObject("LIBRARY_SEARCH_PATHS");
if(spath)
{
@@ -1006,58 +1042,67 @@ void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
this->CreateString(libs.c_str()));
}
}
-
- if(libPath[libPath.size()-1] == 'a')
- {
- fileRef->AddAttribute("lastKnownFileType",
- this->CreateString("archive.ar"));
- }
- else
+ cmsys::RegularExpression libname("^lib([^/]*)(\\.a|\\.dylib).*");
+ if(libname.find(file))
{
- fileRef->AddAttribute("lastKnownFileType",
- this->CreateString("compiled.mach-o.dylib"));
+ file = libname.match(1);
}
- fileRef->AddAttribute("name",
- this->CreateString(
- cmSystemTools::GetFilenameName(libPath).c_str()));
-
- fileRef->AddAttribute("path", this->CreateString(libPath.c_str()));
- fileRef->AddAttribute("refType", this->CreateString("0"));
- fileRef->AddAttribute("sourceTree", this->CreateString("<absolute>"));
- cmXCodeObject* buildfile = this->CreateObject(cmXCodeObject::PBXBuildFile);
- buildfile->AddAttribute("fileRef", this->CreateObjectReference(fileRef));
- cmXCodeObject* settings =
- this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- buildfile->AddAttribute("settings", settings);
- // get the framework build phase from the target
- cmXCodeObject* buildPhases = target->GetObject("buildPhases");
- cmXCodeObject* frameworkBuildPhase =
- buildPhases->GetObject(cmXCodeObject::PBXFrameworksBuildPhase);
- cmXCodeObject* files = frameworkBuildPhase->GetObject("files");
- files->AddObject(buildfile);
- m_ExternalGroupChildren->AddObject(fileRef);
}
else
{
- // if the library is not a full path then add it with a -l flag
- // to the settings of the target
- cmXCodeObject* settings = target->GetObject("buildSettings");
- cmXCodeObject* ldflags = settings->GetObject("OTHER_LDFLAGS");
- std::string link = ldflags->GetString();
- cmSystemTools::ReplaceString(link, "\"", "");
- cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
- // if the library is not already in the form required by the compiler
- // add a -l infront of the name
- link += " ";
- if(!reg.find(library))
+ if(dtarget)
{
- link += "-l";
+ target->AddDependLibrary(this->GetTargetFullPath(dtarget).c_str());
}
- link += library;
- ldflags->SetString(link.c_str());
}
+
+ // if the library is not a full path then add it with a -l flag
+ // to the settings of the target
+ cmXCodeObject* settings = target->GetObject("buildSettings");
+ cmXCodeObject* ldflags = settings->GetObject("OTHER_LDFLAGS");
+ std::string link = ldflags->GetString();
+ cmSystemTools::ReplaceString(link, "\"", "");
+ cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)");
+ // if the library is not already in the form required by the compiler
+ // add a -l infront of the name
+ link += " ";
+ if(!reg.find(file))
+ {
+ link += "-l";
+ }
+ link += file;
+ ldflags->SetString(link.c_str());
}
+
+std::string cmGlobalXCodeGenerator::GetTargetFullPath(cmTarget* target)
+{
+ std::string libPath;
+ cmXCodeObject* xtarget = this->FindXCodeTarget(target);
+ cmXCodeObject* bset = xtarget->GetObject("buildSettings");
+ cmXCodeObject* spath = bset->GetObject("SYMROOT");
+ libPath = spath->GetString();
+ libPath = libPath.substr(1, libPath.size()-2);
+ if(target->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ libPath += "lib";
+ libPath += target->GetName();
+ libPath += ".a";
+ }
+ else if(target->GetType() == cmTarget::SHARED_LIBRARY)
+ {
+ libPath += "lib";
+ libPath += target->GetName();
+ libPath += ".dylib";
+ }
+ else
+ {
+ libPath += target->GetName();
+ }
+ return libPath;
+}
+
+
void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
cmTarget* cmtarget = target->GetcmTarget();
@@ -1079,7 +1124,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
this->AddDependTarget(target, dptarget);
if(cmtarget->GetType() != cmTarget::STATIC_LIBRARY)
{
- this->AddLinkTarget(target, dptarget);
+ this->AddLinkLibrary(target, t->GetName(), t);
}
}
else
@@ -1104,7 +1149,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
else
{
- std::cerr << "Error External Util???: " << i->c_str() << "\n";
+ std::cerr << "Error Utility: " << i->c_str() << "\n";
+ std::cerr << "Is on the target " << cmtarget->GetName() << "\n";
+ std::cerr << "But it has no xcode target created yet??\n";
+ std::cerr << "Current project is "
+ << m_CurrentMakefile->GetProjectName() << "\n";
}
}
}
@@ -1113,7 +1162,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
// add this to build settings of target SYMROOT = /tmp/;
//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* ,
+void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>&
generators
)
@@ -1187,17 +1236,30 @@ void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* ,
this->CreateString("0"));
std::vector<cmXCodeObject*> targets;
m_DoneAllBuild = false;
+ m_DoneXCodeHack = false;
for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
i != generators.end(); ++i)
{
- this->CreateXCodeTargets(*i, targets);
+ if(!this->IsExcluded(root, *i))
+ {
+ this->CreateXCodeTargets(*i, targets);
+ }
}
- cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // loop over all targets and add link and depend info
for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
i != targets.end(); ++i)
{
cmXCodeObject* t = *i;
this->AddDependAndLinkInformation(t);
+ }
+ // now create xcode depend hack makefile
+ this->CreateXCodeDependHackTarget(targets);
+ // now add all targets to the root object
+ cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i)
+ {
+ cmXCodeObject* t = *i;
allTargets->AddObject(t);
cmXCodeObject* productRef = t->GetObject("productReference");
if(productRef)
@@ -1208,6 +1270,89 @@ void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* ,
m_RootObject->AddAttribute("targets", allTargets);
}
+
+//----------------------------------------------------------------------------
+void
+cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
+ std::vector<cmXCodeObject*>& targets)
+{
+ cmGeneratedFileStream makefileStream(m_CurrentXCodeHackMakefile.c_str());
+ if(!makefileStream)
+ {
+ cmSystemTools::Error("Could not create",
+ m_CurrentXCodeHackMakefile.c_str());
+ return;
+ }
+
+ // one more pass for external depend information not handled
+ // correctly by xcode
+ makefileStream << "# DO NOT EDIT\n";
+ makefileStream << "# This makefile makes sure all linkable targets are \n";
+ makefileStream
+ << "# up-to-date with anything they link to,avoiding a bug in XCode 1.5\n";
+ makefileStream << "all: ";
+ for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i)
+ {
+ cmXCodeObject* target = *i;
+ cmTarget* t =target->GetcmTarget();
+ if(t->GetType() == cmTarget::EXECUTABLE ||
+ t->GetType() == cmTarget::SHARED_LIBRARY ||
+ t->GetType() == cmTarget::MODULE_LIBRARY)
+ {
+ makefileStream << "\\\n\t"
+ << this->GetTargetFullPath(target->GetcmTarget());
+ }
+ }
+ makefileStream << "\n\n";
+ makefileStream
+ << "# For each target create a dummy rule "
+ "so the target does not have to exist\n";
+ std::set<cmStdString> emitted;
+ for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i)
+ {
+ cmXCodeObject* target = *i;
+ std::vector<cmStdString> const& deplibs = target->GetDependLibraries();
+ for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
+ d != deplibs.end(); ++d)
+ {
+ if(emitted.insert(*d).second)
+ {
+ makefileStream << *d << ":\n";
+ }
+ }
+ }
+ makefileStream << "\n\n";
+ makefileStream <<
+ "# Each linkable target depends on everything it links to.\n";
+ makefileStream
+ << "#And the target is removed if it is older than what it linkes to\n";
+
+ for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
+ i != targets.end(); ++i)
+ {
+ cmXCodeObject* target = *i;
+ cmTarget* t =target->GetcmTarget();
+ if(t->GetType() == cmTarget::EXECUTABLE ||
+ t->GetType() == cmTarget::SHARED_LIBRARY ||
+ t->GetType() == cmTarget::MODULE_LIBRARY)
+ {
+ std::vector<cmStdString> const& deplibs = target->GetDependLibraries();
+ std::string tfull = this->GetTargetFullPath(target->GetcmTarget());
+ makefileStream << tfull << ": ";
+ for(std::vector<cmStdString>::const_iterator d = deplibs.begin();
+ d != deplibs.end(); ++d)
+ {
+ makefileStream << "\\\n\t" << *d;
+ }
+ makefileStream << "\n";
+ makefileStream << "\t/bin/rm -f " << tfull << "\n";
+ makefileStream << "\n\n";
+ }
+ }
+}
+
//----------------------------------------------------------------------------
void
cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
@@ -1218,6 +1363,7 @@ cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root,
{
return;
}
+
this->CreateXCodeObjects(root,
generators);
std::string xcodeDir = root->GetMakefile()->GetStartOutputDirectory();
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index a8f73d0..67528df 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -109,11 +109,11 @@ private:
void CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
void AddDependTarget(cmXCodeObject* target,
cmXCodeObject* dependTarget);
- void AddLinkTarget(cmXCodeObject* target,
- cmXCodeObject* dependTarget);
void AddLinkLibrary(cmXCodeObject* target,
- const char*);
+ const char* lib, cmTarget* dtarget = 0);
void ConfigureOutputPaths();
+ void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
+ std::string GetTargetFullPath(cmTarget*);
private:
std::vector<cmXCodeObject*> m_XCodeObjects;
cmXCodeObject* m_RootObject;
@@ -125,6 +125,8 @@ private:
std::string m_ExecutableOutputPath;
cmLocalGenerator* m_CurrentLocalGenerator;
bool m_DoneAllBuild;
+ bool m_DoneXCodeHack;
+ std::string m_CurrentXCodeHackMakefile;
};
#endif
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index b1e2997..bd9d6e4 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -49,6 +49,17 @@ public:
{
m_List.push_back(value);
}
+ bool HasObject(cmXCodeObject* o)
+ {
+ return !(std::find(m_List.begin(), m_List.end(), o) == m_List.end());
+ }
+ void AddUniqueObject(cmXCodeObject* value)
+ {
+ if(std::find(m_List.begin(), m_List.end(), value) == m_List.end())
+ {
+ m_List.push_back(value);
+ }
+ }
static void Indent(int level, std::ostream& out);
void Print(std::ostream& out);
static void PrintList(std::vector<cmXCodeObject*> const&, std::ostream& out);
@@ -97,6 +108,14 @@ public:
}
void CopyAttributes(cmXCodeObject* );
+ void AddDependLibrary(const char* l)
+ {
+ m_DependLibraries.push_back(l);
+ }
+ std::vector<cmStdString> const& GetDependLibraries()
+ {
+ return m_DependLibraries;
+ }
private:
cmTarget* m_cmTarget;
Type m_Type;
@@ -106,6 +125,7 @@ private:
cmXCodeObject* m_Object;
cmXCodeObject* m_PBXTargetDependency;
std::vector<cmXCodeObject*> m_List;
+ std::vector<cmStdString> m_DependLibraries;
std::map<cmStdString, cmXCodeObject*> m_ObjectAttributes;
};
#endif