diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2005-02-17 22:54:14 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2005-02-17 22:54:14 (GMT) |
commit | e9300434776a64567a65b6d414bcf98614321ba2 (patch) | |
tree | 94c37f27044ae655262878f5d5b3d90223d1f711 | |
parent | 28f2dfb75244339d49e33fafb7103f5774222d2b (diff) | |
download | CMake-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.cxx | 2 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 318 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 8 | ||||
-rw-r--r-- | Source/cmXCodeObject.h | 20 |
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 |