From fa61182de8a6ce967420077417b5253abdba2d56 Mon Sep 17 00:00:00 2001 From: David Cole Date: Tue, 14 Aug 2007 11:45:15 -0400 Subject: ENH: Improvements to the Xcode generator. Build frameworks using native Copy Headers and Copy Bundle Resources phases. Fix bugs: eliminate folders with no names, ensure source files show up in multiple targets, remove empty utility targets from Sources subtrees, ensure that fileRefs only show up once in each grouping folder. --- Source/cmGlobalXCode21Generator.cxx | 1 + Source/cmGlobalXCodeGenerator.cxx | 527 +++++++++++++++++++------------ Source/cmGlobalXCodeGenerator.h | 11 +- Source/cmLocalUnixMakefileGenerator3.cxx | 19 +- Source/cmLocalXCodeGenerator.cxx | 20 ++ Source/cmXCode21Object.cxx | 20 +- Source/cmXCode21Object.h | 16 + Source/cmXCodeObject.cxx | 34 +- Tests/Framework/CMakeLists.txt | 41 ++- Tests/Framework/fooBoth.h | 1 + Tests/Framework/fooNeither.h | 1 + Tests/Framework/fooPrivate.h | 1 + Tests/Framework/fooPublic.h | 1 + Tests/Framework/test.lua | 1 + 14 files changed, 468 insertions(+), 226 deletions(-) create mode 100644 Tests/Framework/fooBoth.h create mode 100644 Tests/Framework/fooNeither.h create mode 100644 Tests/Framework/fooPrivate.h create mode 100644 Tests/Framework/fooPublic.h diff --git a/Source/cmGlobalXCode21Generator.cxx b/Source/cmGlobalXCode21Generator.cxx index 88eecbd..82aa52a 100644 --- a/Source/cmGlobalXCode21Generator.cxx +++ b/Source/cmGlobalXCode21Generator.cxx @@ -17,6 +17,7 @@ #include "cmGlobalXCode21Generator.h" #include "cmXCode21Object.h" +//---------------------------------------------------------------------------- cmGlobalXCode21Generator::cmGlobalXCode21Generator() { this->XcodeVersion = 21; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index f4c6411..d872637 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -25,6 +25,7 @@ PURPOSE. See the above copyright notices for more information. #include "cmSourceFile.h" #include "cmOrderLinkDirectories.h" +//---------------------------------------------------------------------------- #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmXMLParser.h" @@ -61,7 +62,6 @@ public: }; #endif - //---------------------------------------------------------------------------- cmGlobalXCodeGenerator::cmGlobalXCodeGenerator() { @@ -69,6 +69,7 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator() this->RootObject = 0; this->MainGroupChildren = 0; this->SourcesGroupChildren = 0; + this->ResourcesGroupChildren = 0; this->CurrentMakefile = 0; this->CurrentLocalGenerator = 0; this->XcodeVersion = 15; @@ -266,6 +267,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, std::vector& gens) { cmMakefile* mf = root->GetMakefile(); + // Add ALL_BUILD const char* no_working_directory = 0; std::vector no_depends; @@ -273,7 +275,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, no_working_directory, "echo", "Build all projects"); cmTarget* allbuild = mf->FindTarget("ALL_BUILD", false); - + // Add XCODE depend helper std::string dir = mf->GetCurrentOutputDirectory(); cmCustomCommandLine makecommand; @@ -326,7 +328,6 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, } } - //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::CreateReRunCMakeFile(cmLocalGenerator* root) { @@ -373,6 +374,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects() this->GroupMap.clear(); this->GroupNameMap.clear(); this->TargetGroup.clear(); + this->FileRefs.clear(); } //---------------------------------------------------------------------------- @@ -420,37 +422,109 @@ cmXCodeObject* cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- +bool IsResource(cmSourceFile* sf) +{ + const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"); + + bool isResource = + (sf->GetPropertyAsBool("FRAMEWORK_RESOURCE") || + (location && cmStdString(location) == "Resources")); + + return isResource; +} + +//---------------------------------------------------------------------------- +cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf) +{ + cmStdString key(cmtarget.GetName()); + key += "-"; + key += sf->GetFullPath(); + return key; +} + +//---------------------------------------------------------------------------- cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, cmSourceFile* sf, cmTarget& cmtarget) { + // Add flags from target and source file properties. std::string flags; - // Add flags from source file properties. if(cmtarget.GetProperty("COMPILE_FLAGS")) { lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS")); } lg->AppendFlags(flags, sf->GetProperty("COMPILE_FLAGS")); cmSystemTools::ReplaceString(flags, "\"", "\\\""); - cmXCodeObject* fileRef = - this->CreateObject(cmXCodeObject::PBXFileReference); - cmXCodeObject* group = this->GroupMap[sf]; + // Using a map and the full path guarantees that we will always get the same + // fileRef object for any given full path. + // + 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"); - children->AddObject(fileRef); + if (!children->HasObject(fileRef)) + { + children->AddObject(fileRef); + } + cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - std::string fname = sf->GetFullPath(); - std::string comment = fname; - comment += " in "; - std::string gname = group->GetObject("name")->GetString(); - comment += gname.substr(1, gname.size()-2); - buildFile->SetComment(comment.c_str()); - fileRef->SetComment(fname.c_str()); + buildFile->SetComment(fileRef->GetComment()); buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef)); + cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); settings->AddAttribute("COMPILER_FLAGS", this->CreateString(flags.c_str())); + + // Is this a resource file in this target? Add it to the resources group... + // + bool isResource = IsResource(sf); + + // Is this a "private" or "public" framework header file? + // Set the ATTRIBUTES attribute appropriately... + // + if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY && + cmtarget.GetPropertyAsBool("FRAMEWORK")) + { + if(sf->GetPropertyAsBool("FRAMEWORK_PRIVATE_HEADER")) + { + cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); + attrs->AddObject(this->CreateString("Private")); + settings->AddAttribute("ATTRIBUTES", attrs); + isResource = true; + } + else if(sf->GetPropertyAsBool("FRAMEWORK_PUBLIC_HEADER")) + { + cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); + attrs->AddObject(this->CreateString("Public")); + settings->AddAttribute("ATTRIBUTES", attrs); + isResource = true; + } + } + + // Add the fileRef to the top level Resources group/folder if it is not + // already there. + // + if(isResource && this->ResourcesGroupChildren && + !this->ResourcesGroupChildren->HasObject(fileRef)) + { + this->ResourcesGroupChildren->AddObject(fileRef); + } + buildFile->AddAttribute("settings", settings); fileRef->AddAttribute("fileEncoding", this->CreateString("4")); const char* lang = @@ -524,7 +598,7 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname) { if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" || - tname == "install" || tname == "RUN_TESTS" ) + tname == "install" || tname == "package" || tname == "RUN_TESTS" ) { if(this->TargetDoneSet.find(tname) != this->TargetDoneSet.end()) { @@ -536,7 +610,7 @@ bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname) return false; } - +//---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) { this->CurrentLocalGenerator = gen; @@ -572,18 +646,18 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) } } - //---------------------------------------------------------------------------- -void +void cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, - std::vector& + std::vector& targets) { this->SetCurrentLocalGenerator(gen); cmTargets &tgts = this->CurrentMakefile->GetTargets(); for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) - { + { cmTarget& cmtarget = l->second; + // make sure ALL_BUILD, INSTALL, etc are only done once if(this->SpecialTargetEmitted(l->first.c_str())) { @@ -597,31 +671,22 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, continue; } - // create source build phase - cmXCodeObject* sourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); - sourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - sourceBuildPhase->SetComment("Sources"); - cmXCodeObject* buildFiles = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - sourceBuildPhase->AddAttribute("files", buildFiles); - sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - std::vector const &classes = l->second.GetSourceFiles(); - // add all the sources + // organize the sources + std::vector const &classes = cmtarget.GetSourceFiles(); std::vector externalObjFiles; std::vector headerFiles; - std::vector specialBundleFiles; - for(std::vector::const_iterator i = classes.begin(); + std::vector resourceFiles; + std::vector sourceFiles; + for(std::vector::const_iterator i = classes.begin(); i != classes.end(); ++i) { cmXCodeObject* xsf = - this->CreateXCodeSourceFile(this->CurrentLocalGenerator, + this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, cmtarget); cmXCodeObject* fr = xsf->GetObject("fileRef"); cmXCodeObject* filetype = fr->GetObject()->GetObject("lastKnownFileType"); + if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0) { externalObjFiles.push_back(xsf); @@ -630,76 +695,106 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, { headerFiles.push_back(xsf); } + else if(IsResource(*i)) + { + resourceFiles.push_back(xsf); + } else { - buildFiles->AddObject(xsf); + sourceFiles.push_back(xsf); } } - // create header build phase - cmXCodeObject* headerBuildPhase = - this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); - headerBuildPhase->SetComment("Headers"); - headerBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for(std::vector::iterator i = headerFiles.begin(); - i != headerFiles.end(); ++i) - { - buildFiles->AddObject(*i); - } - headerBuildPhase->AddAttribute("files", buildFiles); - headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - - // create framework build phase - cmXCodeObject* frameworkBuildPhase = - this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); - frameworkBuildPhase->SetComment("Frameworks"); - frameworkBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - frameworkBuildPhase->AddAttribute("files", buildFiles); - for(std::vector::iterator i = externalObjFiles.begin(); - i != externalObjFiles.end(); ++i) - { - buildFiles->AddObject(*i); - } - frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - cmXCodeObject* buildPhases = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - this->CreateCustomCommands(buildPhases, sourceBuildPhase, - headerBuildPhase, frameworkBuildPhase, - cmtarget); - targets.push_back(this->CreateXCodeTarget(l->second, buildPhases)); - - // copy files build phase - typedef std::map > - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for(std::vector::const_iterator i = classes.begin(); - i != classes.end(); ++i) + + // some build phases only apply to bundles and/or frameworks + bool isFrameworkTarget = cmtarget.GetType() == cmTarget::SHARED_LIBRARY && + cmtarget.GetPropertyAsBool("FRAMEWORK"); + bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE"); + + cmXCodeObject* buildFiles = 0; + + // create source build phase + cmXCodeObject* sourceBuildPhase = 0; + if (!sourceFiles.empty()) + { + sourceBuildPhase = + this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); + sourceBuildPhase->SetComment("Sources"); + sourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for(std::vector::iterator i = sourceFiles.begin(); + i != sourceFiles.end(); ++i) + { + buildFiles->AddObject(*i); + } + sourceBuildPhase->AddAttribute("files", buildFiles); + sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create header build phase - only for framework targets + cmXCodeObject* headerBuildPhase = 0; + if (!headerFiles.empty() && isFrameworkTarget) { - const char* resLoc = (*i)->GetProperty("MACOSX_PACKAGE_LOCATION"); - if ( !resLoc ) + headerBuildPhase = + this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); + headerBuildPhase->SetComment("Headers"); + headerBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for(std::vector::iterator i = headerFiles.begin(); + i != headerFiles.end(); ++i) { - continue; + buildFiles->AddObject(*i); } - bundleFiles[resLoc].push_back(*i); + headerBuildPhase->AddAttribute("files", buildFiles); + headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); } - mapOfVectorOfSourceFiles::iterator mit; - for ( mit = bundleFiles.begin(); mit != bundleFiles.end(); ++ mit ) + + // create resource build phase - only for framework or bundle targets + cmXCodeObject* resourceBuildPhase = 0; + if (!resourceFiles.empty() && (isFrameworkTarget || isBundleTarget)) { - cmXCodeObject* copyFilesBuildPhase; - if ( mit->first == "Resources" ) + resourceBuildPhase = + this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); + resourceBuildPhase->SetComment("Resources"); + resourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for(std::vector::iterator i = resourceFiles.begin(); + i != resourceFiles.end(); ++i) { - copyFilesBuildPhase - = this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); + buildFiles->AddObject(*i); } - else + resourceBuildPhase->AddAttribute("files", buildFiles); + resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create vector of "non-resource content file" build phases - only for + // framework or bundle targets + std::vector contentBuildPhases; + if (isFrameworkTarget || isBundleTarget) + { + typedef std::map > + mapOfVectorOfSourceFiles; + mapOfVectorOfSourceFiles bundleFiles; + for(std::vector::const_iterator i = classes.begin(); + i != classes.end(); ++i) { - copyFilesBuildPhase - = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + const char* contentLoc = (*i)->GetProperty("MACOSX_PACKAGE_LOCATION"); + if ( !contentLoc || cmStdString(contentLoc) == "Resources" ) + { + continue; + } + bundleFiles[contentLoc].push_back(*i); + } + mapOfVectorOfSourceFiles::iterator mit; + for ( mit = bundleFiles.begin(); mit != bundleFiles.end(); ++ mit ) + { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); copyFilesBuildPhase->SetComment("Copy files"); copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); @@ -712,73 +807,58 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, } copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(ostr.str().c_str())); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + std::vector::iterator sfIt; + for ( sfIt = mit->second.begin(); sfIt != mit->second.end(); ++ sfIt ) + { + cmXCodeObject* xsf = + this->CreateXCodeSourceFile(this->CurrentLocalGenerator, + *sfIt, cmtarget); + buildFiles->AddObject(xsf); + } + contentBuildPhases.push_back(copyFilesBuildPhase); } - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildPhases->AddObject(copyFilesBuildPhase); + } + + // create framework build phase + cmXCodeObject* frameworkBuildPhase = 0; + if (!externalObjFiles.empty()) + { + frameworkBuildPhase = + this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); + frameworkBuildPhase->SetComment("Frameworks"); + frameworkBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - std::vector::iterator sfIt; - for ( sfIt = mit->second.begin(); sfIt != mit->second.end(); ++ sfIt ) + frameworkBuildPhase->AddAttribute("files", buildFiles); + for(std::vector::iterator i = externalObjFiles.begin(); + i != externalObjFiles.end(); ++i) { - cmXCodeObject* xsf = - this->CreateXCodeSourceFile(this->CurrentLocalGenerator, - *sfIt, cmtarget); - buildFiles->AddObject(xsf); + buildFiles->AddObject(*i); } + frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); } - if (cmtarget.GetType() == cmTarget::SHARED_LIBRARY && - cmtarget.GetPropertyAsBool("FRAMEWORK")) - { - this->AddFrameworkPhases(&cmtarget, buildPhases); - } - } -} -//---------------------------------------------------------------------------- -void cmGlobalXCodeGenerator::AddFrameworkPhases(cmTarget* target, - cmXCodeObject* buildPhases) -{ - const char* headers = target->GetProperty("FRAMEWORK_PUBLIC_HEADERS"); - if(!headers) - { - return; - } - - cmXCodeObject* copyHeaders = - this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); - copyHeaders->SetComment("Copy files"); - copyHeaders->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - copyHeaders->AddAttribute("dstSubfolderSpec", - this->CreateString("6")); - copyHeaders->AddAttribute("dstPath", - this->CreateString("Headers")); - buildPhases->AddObject(copyHeaders); - cmXCodeObject* headersToCopy = - this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyHeaders->AddAttribute("files", headersToCopy); - std::vector headersVec; - cmSystemTools::ExpandListArgument(headers, - headersVec); - cmCustomCommandLines commandLines; - std::vector depends; - for(std::vector::iterator i = headersVec.begin(); - i != headersVec.end(); ++i) - { - cmCustomCommandLine line; - cmSourceFile* sf = this->CurrentMakefile->GetOrCreateSource(i->c_str()); - cmXCodeObject* xsf = - this->CreateXCodeSourceFile(this->CurrentLocalGenerator, - sf, *target); - //std::cerr << "copy header " << sf->GetFullPath() << "\n"; - headersToCopy->AddObject(xsf); + // create list of build phases and create the XCode target + cmXCodeObject* buildPhases = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + + this->CreateCustomCommands(buildPhases, sourceBuildPhase, + headerBuildPhase, resourceBuildPhase, + contentBuildPhases, + frameworkBuildPhase, cmtarget); + + targets.push_back(this->CreateXCodeTarget(cmtarget, buildPhases)); } } //---------------------------------------------------------------------------- cmXCodeObject* -cmGlobalXCodeGenerator::CreateBuildPhase(const char* name, +cmGlobalXCodeGenerator::CreateBuildPhase(const char* name, const char* name2, cmTarget& cmtarget, const std::vector& @@ -812,6 +892,10 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, cmXCodeObject* headerBuildPhase, cmXCodeObject* + resourceBuildPhase, + std::vector + contentBuildPhases, + cmXCodeObject* frameworkBuildPhase, cmTarget& cmtarget) { @@ -846,15 +930,19 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, cmXCodeObject* preBuildPhase = this->CreateBuildPhase("CMake PreBuild Rules", "preBuildCommands", cmtarget, prebuild); - // create prebuild phase + // create prelink phase cmXCodeObject* preLinkPhase = this->CreateBuildPhase("CMake PreLink Rules", "preLinkCommands", cmtarget, prelink); - // create prebuild phase + // create postbuild phase cmXCodeObject* postBuildPhase = this->CreateBuildPhase("CMake PostBuild Rules", "postBuildPhase", cmtarget, postbuild); - // the order here is the order they will be built in + + // The order here is the order they will be built in. + // The order "headers, resources, sources" mimics a native project generated + // from an xcode template... + // if(preBuildPhase) { buildPhases->AddObject(preBuildPhase); @@ -863,14 +951,23 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, { buildPhases->AddObject(cmakeRulesBuildPhase); } - if(sourceBuildPhase) - { - buildPhases->AddObject(sourceBuildPhase); - } if(headerBuildPhase) { buildPhases->AddObject(headerBuildPhase); } + if(resourceBuildPhase) + { + buildPhases->AddObject(resourceBuildPhase); + } + std::vector::iterator cit; + for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end(); ++cit) + { + buildPhases->AddObject(*cit); + } + if(sourceBuildPhase) + { + buildPhases->AddObject(sourceBuildPhase); + } if(preLinkPhase) { buildPhases->AddObject(preLinkPhase); @@ -1312,27 +1409,33 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { fileType = "wrapper.framework"; productType = "com.apple.product-type.framework"; - break; + + const char* version = target.GetProperty("FRAMEWORK_VERSION"); + buildSettings->AddAttribute("FRAMEWORK_VERSION", + this->CreateString(version)); } - fileType = "compiled.mach-o.dylib"; - productType = "com.apple.product-type.library.dynamic"; + else + { + fileType = "compiled.mach-o.dylib"; + productType = "com.apple.product-type.library.dynamic"; - buildSettings->AddAttribute("LIBRARY_STYLE", + // Add the flags to create a shared library. + std::string createFlags = + this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang, "_FLAGS", + "-dynamiclib"); + if(!createFlags.empty()) + { + extraLinkOptions += " "; + extraLinkOptions += createFlags; + } + } + + buildSettings->AddAttribute("LIBRARY_STYLE", this->CreateString("DYNAMIC")); - buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", + buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", this->CreateString("1")); - buildSettings->AddAttribute("DYLIB_CURRENT_VERSION", + buildSettings->AddAttribute("DYLIB_CURRENT_VERSION", this->CreateString("1")); - - // Add the flags to create a shared library. - std::string createFlags = - this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang, "_FLAGS", - "-dynamiclib"); - if(!createFlags.empty()) - { - extraLinkOptions += " "; - extraLinkOptions += createFlags; - } break; } case cmTarget::EXECUTABLE: @@ -1577,7 +1680,8 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) target->SetComment(cmtarget.GetName()); cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); - this->CreateCustomCommands(buildPhases, 0, 0, 0, cmtarget); + std::vector emptyContentVector; + this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0, cmtarget); target->AddAttribute("buildPhases", buildPhases); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); @@ -1785,7 +1889,6 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target, } } - //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attribute, @@ -2042,6 +2145,17 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { cmTarget& cmtarget = l->second; + + // Same skipping logic here as in CreateXCodeTargets so that we do not + // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source + // groups: + // + if(cmtarget.GetType() == cmTarget::UTILITY || + cmtarget.GetType() == cmTarget::GLOBAL_TARGET) + { + continue; + } + // add the soon to be generated Info.plist file as a source for a // MACOSX_BUNDLE file if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")) @@ -2053,29 +2167,9 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, this->CurrentMakefile->GetOrCreateSource(plistFile.c_str(), true); cmtarget.AddSourceFile(sf); } + std::vector classes = cmtarget.GetSourceFiles(); - // add framework copy headers - if (cmtarget.GetType() == cmTarget::SHARED_LIBRARY && - cmtarget.GetPropertyAsBool("FRAMEWORK")) - { - const char* headers = cmtarget.GetProperty("FRAMEWORK_PUBLIC_HEADERS"); - if(!headers) - { - return; - } - std::vector headersVec; - cmSystemTools::ExpandListArgument(headers, - headersVec); - cmCustomCommandLines commandLines; - std::vector depends; - for(std::vector::iterator h = headersVec.begin(); - h != headersVec.end(); ++h) - { - cmSourceFile* sf - = this->CurrentMakefile->GetOrCreateSource(h->c_str()); - classes.push_back(sf); - } - } + for(std::vector::const_iterator s = classes.begin(); s != classes.end(); s++) { @@ -2086,11 +2180,13 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, mf->FindSourceGroup(source.c_str(), sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(cmtarget, &sourceGroup); - this->GroupMap[sf] = pbxgroup; + cmStdString key = GetGroupMapKey(cmtarget, sf); + this->GroupMap[key] = pbxgroup; } } } } + //---------------------------------------------------------------------------- cmXCodeObject* cmGlobalXCodeGenerator ::CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg) @@ -2098,7 +2194,7 @@ cmXCodeObject* cmGlobalXCodeGenerator cmStdString s = cmtarget.GetName(); s += "/"; s += sg->GetName(); - std::map::iterator i = + std::map::iterator i = this->GroupNameMap.find(s); if(i != this->GroupNameMap.end()) { @@ -2125,7 +2221,16 @@ cmXCodeObject* cmGlobalXCodeGenerator tgroup->AddAttribute("sourceTree", this->CreateString("")); this->SourcesGroupChildren->AddObject(tgroup); } - + + // If it's the default source group (empty name) then put the source file + // directly in the tgroup... + // + if (cmStdString(sg->GetName()) == "") + { + this->GroupNameMap[s] = tgroup; + return tgroup; + } + cmXCodeObject* tgroupChildren = tgroup->GetObject("children"); cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup); cmXCodeObject* groupChildren = @@ -2151,6 +2256,7 @@ void cmGlobalXCodeGenerator this->ClearXCodeObjects(); this->RootObject = 0; this->SourcesGroupChildren = 0; + this->ResourcesGroupChildren = 0; this->MainGroupChildren = 0; cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); @@ -2209,9 +2315,22 @@ void cmGlobalXCodeGenerator } sourcesGroup->AddAttribute("sourceTree", this->CreateString("")); this->MainGroupChildren->AddObject(sourcesGroup); + + cmXCodeObject* resourcesGroup = this->CreateObject(cmXCodeObject::PBXGroup); + this->ResourcesGroupChildren = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + resourcesGroup->AddAttribute("name", this->CreateString("Resources")); + resourcesGroup->AddAttribute("children", this->ResourcesGroupChildren); + if(this->XcodeVersion == 15) + { + resourcesGroup->AddAttribute("refType", this->CreateString("4")); + } + resourcesGroup->AddAttribute("sourceTree", this->CreateString("")); + this->MainGroupChildren->AddObject(resourcesGroup); + // now create the cmake groups this->CreateGroups(root, generators); - + cmXCodeObject* productGroup = this->CreateObject(cmXCodeObject::PBXGroup); productGroup->AddAttribute("name", this->CreateString("Products")); if(this->XcodeVersion == 15) @@ -2533,7 +2652,7 @@ cmGlobalXCodeGenerator::OutputXCodeProject(cmLocalGenerator* root, if(this->XcodeVersion > 20) { xcodeDir += "proj"; - } + } cmSystemTools::MakeDirectory(xcodeDir.c_str()); std::string xcodeProjFile = xcodeDir + "/project.pbxproj"; cmGeneratedFileStream fout(xcodeProjFile.c_str()); @@ -2609,6 +2728,7 @@ std::string cmGlobalXCodeGenerator::ConvertToRelativeForXCode(const char* p) } } +//---------------------------------------------------------------------------- std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p) { std::string ret = p; @@ -2622,6 +2742,7 @@ std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p) return ret; } +//---------------------------------------------------------------------------- void cmGlobalXCodeGenerator:: GetTargetObjectFileDirectories(cmTarget* target, std::vector& diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 306b7ea..aa4f3be 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -65,9 +65,6 @@ public: const char* config, bool ignoreErrors, bool fast); - - // add extra build phases for a framework target - void AddFrameworkPhases(cmTarget*, cmXCodeObject* buildPhases); /** * Generate the all required files for building this project/tree. This @@ -101,9 +98,11 @@ private: void CreateCustomCommands(cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, cmXCodeObject* headerBuildPhase, + cmXCodeObject* resourceBuildPhase, + std::vector contentBuildPhases, cmXCodeObject* frameworkBuildPhase, cmTarget& cmtarget); - + void AddCommandsToBuildPhase(cmXCodeObject* buildphase, cmTarget& target, std::vector @@ -184,6 +183,7 @@ protected: private: cmXCodeObject* MainGroupChildren; cmXCodeObject* SourcesGroupChildren; + cmXCodeObject* ResourcesGroupChildren; cmMakefile* CurrentMakefile; cmLocalGenerator* CurrentLocalGenerator; std::vector CurrentConfigurationTypes; @@ -193,9 +193,10 @@ private: std::set TargetDoneSet; std::vector CurrentOutputDirectoryComponents; std::vector ProjectOutputDirectoryComponents; - std::map GroupMap; + std::map GroupMap; std::map GroupNameMap; std::map TargetGroup; + std::map FileRefs; std::vector Architectures; }; diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index bdddd9b..e9a24c7 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1704,19 +1704,26 @@ cmLocalUnixMakefileGenerator3 target.GetExecutableNames(targetName, targetNameReal, targetNameImport, targetNamePDB, this->ConfigurationName.c_str()); std::string obj; + + // Construct the full path version of the names. + // + // If target is a MACOSX_BUNDLE target, then the package location is + // relative to "${targetDir}/${targetName}.app/Contents"... else it is + // relative to "${targetDir}"... + // + obj = target.GetDirectory(); + obj += "/"; if ( target.GetPropertyAsBool("MACOSX_BUNDLE") ) { - // Construct the full path version of the names. - obj = target.GetDirectory(); - obj += "/"; obj += targetName + ".app/Contents/"; - obj += fileTargetDirectory; } else { - // Framework not handled yet - abort(); + // Emit warning here...? MACOSX_PACKAGE_LOCATION is "most useful" in a + // MACOSX_BUNDLE... } + obj += fileTargetDirectory; + obj = cmSystemTools::RelativePath (this->Makefile->GetHomeOutputDirectory(), obj.c_str()); obj += "/"; diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 7f60402..a942de7 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -1,7 +1,24 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ #include "cmLocalXCodeGenerator.h" #include "cmGlobalXCodeGenerator.h" #include "cmSourceFile.h" +//---------------------------------------------------------------------------- cmLocalXCodeGenerator::cmLocalXCodeGenerator() { // the global generator does this, so do not @@ -9,10 +26,12 @@ cmLocalXCodeGenerator::cmLocalXCodeGenerator() this->EmitUniversalBinaryFlags = false; } +//---------------------------------------------------------------------------- cmLocalXCodeGenerator::~cmLocalXCodeGenerator() { } +//---------------------------------------------------------------------------- std::string cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const { @@ -20,6 +39,7 @@ cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const return ""; } +//---------------------------------------------------------------------------- void cmLocalXCodeGenerator:: GetTargetObjectFileDirectories(cmTarget* target, std::vector& diff --git a/Source/cmXCode21Object.cxx b/Source/cmXCode21Object.cxx index 0a70d78..6ee6936 100644 --- a/Source/cmXCode21Object.cxx +++ b/Source/cmXCode21Object.cxx @@ -1,6 +1,23 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ #include "cmXCode21Object.h" #include "cmSystemTools.h" +//---------------------------------------------------------------------------- cmXCode21Object::cmXCode21Object(PBXType ptype, Type type) :cmXCodeObject(ptype, type) { @@ -24,7 +41,7 @@ void cmXCode21Object::PrintComment(std::ostream& out) out << " */"; } - +//---------------------------------------------------------------------------- void cmXCode21Object::PrintList(std::vector const& v, std::ostream& out, PBXType t) { @@ -56,6 +73,7 @@ void cmXCode21Object::PrintList(std::vector const& v, out << "/* End " << PBXTypeNames[t] << " section */\n"; } +//---------------------------------------------------------------------------- void cmXCode21Object::PrintList(std::vector const& v, std::ostream& out) { diff --git a/Source/cmXCode21Object.h b/Source/cmXCode21Object.h index 752e225..b942f22 100644 --- a/Source/cmXCode21Object.h +++ b/Source/cmXCode21Object.h @@ -1,3 +1,19 @@ +/*========================================================================= + + Program: CMake - Cross-Platform Makefile Generator + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. + See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ #ifndef cmXCode21Object_h #define cmXCode21Object_h diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index 76a01b2..6cfb87b 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -17,6 +17,7 @@ #include "cmXCodeObject.h" #include "cmSystemTools.h" +//---------------------------------------------------------------------------- const char* cmXCodeObject::PBXTypeNames[] = { "PBXGroup", "PBXBuildStyle", "PBXProject", "PBXHeadersBuildPhase", "PBXSourcesBuildPhase", "PBXFrameworksBuildPhase", "PBXNativeTarget", @@ -30,12 +31,12 @@ const char* cmXCodeObject::PBXTypeNames[] = { "None" }; +//---------------------------------------------------------------------------- cmXCodeObject::~cmXCodeObject() { this->Version = 15; } - //---------------------------------------------------------------------------- cmXCodeObject::cmXCodeObject(PBXType ptype, Type type) { @@ -143,7 +144,33 @@ void cmXCodeObject::Print(std::ostream& out) object->ObjectAttributes.end(); ++j) { cmXCodeObject::Indent(4 *indentFactor, out); - out << j->first << " = " << j->second->String << ";"; + + if(j->second->TypeValue == STRING) + { + out << j->first << " = " << j->second->String << ";"; + } + else if(j->second->TypeValue == OBJECT_LIST) + { + out << j->first << " = ("; + for(unsigned int k = 0; k < j->second->List.size(); k++) + { + if(j->second->List[k]->TypeValue == STRING) + { + out << j->second->List[k]->String << ", "; + } + else + { + out << "List_" << k << "_TypeValue_IS_NOT_STRING, "; + } + } + out << ");"; + } + else + { + out << j->first << " = error_unexpected_TypeValue_" << + j->second->TypeValue << ";"; + } + out << separator; } cmXCodeObject::Indent(3 *indentFactor, out); @@ -189,7 +216,7 @@ void cmXCodeObject::PrintList(std::vector const& objs, out << "};\n"; } - +//---------------------------------------------------------------------------- void cmXCodeObject::CopyAttributes(cmXCodeObject* copy) { this->ObjectAttributes = copy->ObjectAttributes; @@ -198,6 +225,7 @@ void cmXCodeObject::CopyAttributes(cmXCodeObject* copy) this->Object = copy->Object; } +//---------------------------------------------------------------------------- void cmXCodeObject::SetString(const char* s) { std::string ss = s; diff --git a/Tests/Framework/CMakeLists.txt b/Tests/Framework/CMakeLists.txt index 8264505..f1f82cb 100644 --- a/Tests/Framework/CMakeLists.txt +++ b/Tests/Framework/CMakeLists.txt @@ -1,11 +1,29 @@ project(Framework) -add_library(foo SHARED foo.cxx foo.h) +add_library(foo SHARED + foo.cxx + foo.h + foo2.h + fooPublic.h + fooPrivate.h + fooNeither.h + fooBoth.h + test.lua +) set_target_properties(foo PROPERTIES FRAMEWORK TRUE - FRAMEWORK_PUBLIC_HEADERS "foo.h;foo2.h" - FRAMEWORK_VERSION ver2 - FRAMEWORK_RESOURCES "test.lua" + FRAMEWORK_VERSION ver3 +) +# fooNeither.h is marked neither public nor private... +# fooBoth.h is marked both public and private... (private wins...) +set_source_files_properties(foo.h foo2.h fooPublic.h fooBoth.h PROPERTIES + FRAMEWORK_PUBLIC_HEADER TRUE +) +set_source_files_properties(fooPrivate.h fooBoth.h PROPERTIES + FRAMEWORK_PRIVATE_HEADER TRUE +) +set_source_files_properties(test.lua PROPERTIES + FRAMEWORK_RESOURCE TRUE ) add_executable(bar bar.cxx) target_link_libraries(bar foo) @@ -16,12 +34,19 @@ target_link_libraries(bar foo) # a framework... The framework properties only apply when the library type # is SHARED. # -add_library(fooStatic STATIC foo.cxx foo.h) +add_library(fooStatic STATIC + foo.cxx + foo.h + foo2.h + fooPublic.h + fooPrivate.h + fooNeither.h + fooBoth.h + test.lua +) set_target_properties(fooStatic PROPERTIES FRAMEWORK TRUE - FRAMEWORK_PUBLIC_HEADERS "foo.h;foo2.h" - FRAMEWORK_VERSION ver2 - FRAMEWORK_RESOURCES "test.lua" + FRAMEWORK_VERSION none ) add_executable(barStatic bar.cxx) target_link_libraries(barStatic fooStatic) diff --git a/Tests/Framework/fooBoth.h b/Tests/Framework/fooBoth.h new file mode 100644 index 0000000..5a0f330 --- /dev/null +++ b/Tests/Framework/fooBoth.h @@ -0,0 +1 @@ +fooBothh diff --git a/Tests/Framework/fooNeither.h b/Tests/Framework/fooNeither.h new file mode 100644 index 0000000..04736a1 --- /dev/null +++ b/Tests/Framework/fooNeither.h @@ -0,0 +1 @@ +fooNeitherh diff --git a/Tests/Framework/fooPrivate.h b/Tests/Framework/fooPrivate.h new file mode 100644 index 0000000..dc8cb34 --- /dev/null +++ b/Tests/Framework/fooPrivate.h @@ -0,0 +1 @@ +fooPrivateh diff --git a/Tests/Framework/fooPublic.h b/Tests/Framework/fooPublic.h new file mode 100644 index 0000000..f0469de --- /dev/null +++ b/Tests/Framework/fooPublic.h @@ -0,0 +1 @@ +fooPublich diff --git a/Tests/Framework/test.lua b/Tests/Framework/test.lua index e69de29..ce5c3eb 100644 --- a/Tests/Framework/test.lua +++ b/Tests/Framework/test.lua @@ -0,0 +1 @@ +test.lua -- cgit v0.12