diff options
Diffstat (limited to 'Source/cmGlobalXCodeGenerator.cxx')
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 495 |
1 files changed, 234 insertions, 261 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 3503e19..ee5fc00 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -34,17 +34,17 @@ class cmXcodeVersionParser : public cmXMLParser { public: cmXcodeVersionParser(): Version("1.5") {} - void StartElement(const char* , const char** ) + void StartElement(const std::string&, const char**) { this->Data = ""; } - void EndElement(const char* name) + void EndElement(const std::string& name) { - if(strcmp(name, "key") == 0) + if(name == "key") { this->Key = this->Data; } - else if(strcmp(name, "string") == 0) + else if(name == "string") { if(this->Key == "CFBundleShortVersionString") { @@ -116,7 +116,8 @@ public: class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const; + virtual cmGlobalGenerator* CreateGlobalGenerator( + const std::string& name) const; virtual void GetDocumentation(cmDocumentationEntry& entry) const { cmGlobalXCodeGenerator::GetDocumentation(entry); } @@ -152,9 +153,9 @@ cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() //---------------------------------------------------------------------------- cmGlobalGenerator* cmGlobalXCodeGenerator::Factory -::CreateGlobalGenerator(const char* name) const +::CreateGlobalGenerator(const std::string& name) const { - if (strcmp(name, GetActualName())) + if (name != GetActualName()) return 0; #if defined(CMAKE_BUILD_WITH_CMAKE) cmXcodeVersionParser parser; @@ -201,16 +202,19 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory } //---------------------------------------------------------------------------- -bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts) +bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, + cmMakefile* mf) { if(this->XcodeVersion >= 30) { - this->PlatformToolset = ts; + this->GeneratorToolset = ts; + mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", + this->GeneratorToolset.c_str()); return true; } else { - return cmGlobalGenerator::SetGeneratorToolset(ts); + return cmGlobalGenerator::SetGeneratorToolset(ts, mf); } } @@ -238,11 +242,6 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const& } } mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); - if(!this->PlatformToolset.empty()) - { - mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", - this->PlatformToolset.c_str()); - } this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES"); @@ -260,11 +259,11 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const& void cmGlobalXCodeGenerator::GenerateBuildCommand( std::vector<std::string>& makeCommand, - const char* makeProgram, - const char* projectName, - const char* /*projectDir*/, - const char* targetName, - const char* config, + const std::string& makeProgram, + const std::string& projectName, + const std::string& /*projectDir*/, + const std::string& targetName, + const std::string& config, bool /*fast*/, std::vector<std::string> const& makeOptions) { @@ -283,10 +282,11 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( makeCommand.push_back(projectArg); bool clean = false; - if ( targetName && strcmp(targetName, "clean") == 0 ) + std::string realTarget = targetName; + if ( realTarget == "clean" ) { clean = true; - targetName = "ALL_BUILD"; + realTarget = "ALL_BUILD"; } if(clean) { @@ -297,14 +297,9 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( makeCommand.push_back("build"); } makeCommand.push_back("-target"); - // if it is a null string for config don't use it - if(config && *config == 0) - { - config = 0; - } - if (targetName && strlen(targetName)) + if (!realTarget.empty()) { - makeCommand.push_back(targetName); + makeCommand.push_back(realTarget); } else { @@ -318,7 +313,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( else { makeCommand.push_back("-configuration"); - makeCommand.push_back(config?config:"Debug"); + makeCommand.push_back(!config.empty()?config:"Debug"); } makeCommand.insert(makeCommand.end(), makeOptions.begin(), makeOptions.end()); @@ -336,7 +331,7 @@ cmLocalGenerator *cmGlobalXCodeGenerator::CreateLocalGenerator() //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::Generate() { - std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it; + std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it; // make sure extra targets are added before calling // the parent generate which will call trace depends for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it) @@ -346,7 +341,6 @@ void cmGlobalXCodeGenerator::Generate() // add ALL_BUILD, INSTALL, etc this->AddExtraTargets(root, it->second); } - this->ForceLinkerLanguages(); this->cmGlobalGenerator::Generate(); if(cmSystemTools::GetErrorOccuredFlag()) { @@ -415,7 +409,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, std::string listfile = mf->GetStartDirectory(); listfile += "/"; listfile += "CMakeLists.txt"; - allbuild->AddSource(listfile.c_str()); + allbuild->AddSourceCMP0049(listfile.c_str()); // Add XCODE depend helper std::string dir = mf->GetCurrentOutputDirectory(); @@ -498,7 +492,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, listfile = lg->GetMakefile()->GetStartDirectory(); listfile += "/"; listfile += "CMakeLists.txt"; - target.AddSource(listfile.c_str()); + target.AddSourceCMP0049(listfile.c_str()); } } } @@ -569,7 +563,7 @@ void cmGlobalXCodeGenerator::addObject(cmXCodeObject *obj) { if(obj->GetType() == cmXCodeObject::OBJECT) { - cmStdString id = obj->GetId(); + std::string id = obj->GetId(); // If this is a duplicate id, it's an error: // @@ -613,7 +607,7 @@ cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type) //---------------------------------------------------------------------------- cmXCodeObject* -cmGlobalXCodeGenerator::CreateString(const char* s) +cmGlobalXCodeGenerator::CreateString(const std::string& s) { cmXCodeObject* obj = this->CreateObject(cmXCodeObject::STRING); obj->SetString(s); @@ -630,17 +624,17 @@ cmXCodeObject* cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- -cmStdString +std::string GetGroupMapKeyFromPath(cmTarget& cmtarget, const std::string& fullpath) { - cmStdString key(cmtarget.GetName()); + std::string key(cmtarget.GetName()); key += "-"; key += fullpath; return key; } //---------------------------------------------------------------------------- -cmStdString +std::string GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf) { return GetGroupMapKeyFromPath(cmtarget, sf->GetFullPath()); @@ -651,13 +645,14 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang) + const std::string &lang, + cmSourceFile* sf) { // 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); + this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang, sf); cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); buildFile->SetComment(fileRef->GetComment()); @@ -696,15 +691,11 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, flags += flagsBuild.GetString(); } - const char* lang = + std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); - if (!lang) - { - lang = ""; - } cmXCodeObject* buildFile = - this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang); + this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang, sf); cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject(); cmXCodeObject* settings = @@ -713,22 +704,23 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, // Is this a resource file in this target? Add it to the resources group... // - cmTarget::SourceFileFlags tsFlags = cmtarget.GetTargetSourceFileFlags(sf); - bool isResource = (tsFlags.Type == cmTarget::SourceFileTypeResource); + cmGeneratorTarget::SourceFileFlags tsFlags = + this->GetGeneratorTarget(&cmtarget)->GetTargetSourceFileFlags(sf); + bool isResource = tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource; // Is this a "private" or "public" framework header file? // Set the ATTRIBUTES attribute appropriately... // if(cmtarget.IsFrameworkOnApple()) { - if(tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Private")); settings->AddAttribute("ATTRIBUTES", attrs); isResource = true; } - else if(tsFlags.Type == cmTarget::SourceFileTypePublicHeader) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader) { cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST); attrs->AddObject(this->CreateString("Public")); @@ -835,7 +827,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string &fullpath, cmTarget& cmtarget, - const std::string &lang) + const std::string &lang, + cmSourceFile* sf) { std::string fname = fullpath; cmXCodeObject* fileRef = this->FileRefs[fname]; @@ -846,7 +839,7 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( fileRef->SetComment(fname.c_str()); this->FileRefs[fname] = fileRef; } - cmStdString key = GetGroupMapKeyFromPath(cmtarget, fullpath); + std::string key = GetGroupMapKeyFromPath(cmtarget, fullpath); cmXCodeObject* group = this->GroupMap[key]; cmXCodeObject* children = group->GetObject("children"); if (!children->HasObject(fileRef)) @@ -855,36 +848,49 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( } 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); - } - - // If fullpath references a directory, then we need to specify - // lastKnownFileType as folder in order for Xcode to be able to open the - // contents of the folder (Xcode 4.6 does not like explicitFileType=folder). - if(cmSystemTools::FileIsDirectory(fullpath.c_str())) + bool useLastKnownFileType = false; + std::string fileType; + if(sf) { - fileRef->AddAttribute("lastKnownFileType", - this->CreateString("folder")); + if(const char* e = sf->GetProperty("XCODE_EXPLICIT_FILE_TYPE")) + { + fileType = e; + } + else if(const char* l = sf->GetProperty("XCODE_LAST_KNOWN_FILE_TYPE")) + { + useLastKnownFileType = true; + fileType = l; + } } - else + if(fileType.empty()) { - bool keepLastKnownFileType = false; - std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, - lang, keepLastKnownFileType); - const char* attribute = keepLastKnownFileType ? - "lastKnownFileType" : - "explicitFileType"; - fileRef->AddAttribute(attribute, - this->CreateString(sourcecode.c_str())); + // If fullpath references a directory, then we need to specify + // lastKnownFileType as folder in order for Xcode to be able to + // open the contents of the folder. + // (Xcode 4.6 does not like explicitFileType=folder). + if(cmSystemTools::FileIsDirectory(fullpath.c_str())) + { + fileType = "folder"; + useLastKnownFileType = true; + } + else + { + // Compute the extension without leading '.'. + std::string ext = cmSystemTools::GetFilenameLastExtension(fullpath); + if(!ext.empty()) + { + ext = ext.substr(1); + } + + fileType = GetSourcecodeValueFromFileExtension( + ext, lang, useLastKnownFileType); + } } + fileRef->AddAttribute(useLastKnownFileType? "lastKnownFileType" + : "explicitFileType", + this->CreateString(fileType)); + // Store the file path relative to the top of the source tree. std::string path = this->RelativeToSource(fullpath.c_str()); std::string name = cmSystemTools::GetFilenameName(path.c_str()); @@ -905,15 +911,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf, cmTarget& cmtarget) { - const char* lang = + std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); - if (!lang) - { - lang = ""; - } return this->CreateXCodeFileReferenceFromPath( - sf->GetFullPath(), cmtarget, lang); + sf->GetFullPath(), cmtarget, lang, sf); } //---------------------------------------------------------------------------- @@ -973,6 +975,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++) { cmTarget& cmtarget = l->second; + cmGeneratorTarget* gtgt = this->GetGeneratorTarget(&cmtarget); // make sure ALL_BUILD, INSTALL, etc are only done once if(this->SpecialTargetEmitted(l->first.c_str())) @@ -994,9 +997,14 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // organize the sources std::vector<cmSourceFile*> classes; - cmtarget.GetSourceFiles(classes); + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); + gtgt->ComputeObjectMapping(); + std::vector<cmXCodeObject*> externalObjFiles; std::vector<cmXCodeObject*> headerFiles; std::vector<cmXCodeObject*> resourceFiles; @@ -1011,21 +1019,24 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); if(filetype && - strcmp(filetype->GetString(), "compiled.mach-o.objfile") == 0) + filetype->GetString() == "compiled.mach-o.objfile") { - externalObjFiles.push_back(xsf); + if ((*i)->GetObjectLibrary().empty()) + { + externalObjFiles.push_back(xsf); + } } else if(this->IsHeaderFile(*i) || - (tsFlags.Type == cmTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == cmTarget::SourceFileTypePublicHeader)) + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader)) { headerFiles.push_back(xsf); } - else if(tsFlags.Type == cmTarget::SourceFileTypeResource) + else if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { resourceFiles.push_back(xsf); } @@ -1034,7 +1045,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // Include this file in the build if it has a known language // and has not been listed as an ignored extension for this // generator. - if(this->CurrentLocalGenerator->GetSourceFileLanguage(**i) && + if(!this->CurrentLocalGenerator->GetSourceFileLanguage(**i).empty() && !this->IgnoreFile((*i)->GetExtension().c_str())) { sourceFiles.push_back(xsf); @@ -1048,13 +1059,13 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // the externalObjFiles above, except each one is not a cmSourceFile // within the target.) std::vector<std::string> objs; - this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + gtgt->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, ""); + this->CreateXCodeSourceFileFromPath(obj, cmtarget, "", 0); externalObjFiles.push_back(xsf); } } @@ -1132,15 +1143,15 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*> contentBuildPhases; if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<cmStdString, std::vector<cmSourceFile*> > + typedef std::map<std::string, std::vector<cmSourceFile*> > mapOfVectorOfSourceFiles; mapOfVectorOfSourceFiles bundleFiles; for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); i != classes.end(); ++i) { - cmTarget::SourceFileFlags tsFlags = - cmtarget.GetTargetSourceFileFlags(*i); - if(tsFlags.Type == cmTarget::SourceFileTypeMacContent) + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(*i); + if(tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { bundleFiles[tsFlags.MacFolder].push_back(*i); } @@ -1221,7 +1232,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, void cmGlobalXCodeGenerator::ForceLinkerLanguages() { // This makes sure all targets link using the proper language. - for(std::map<cmStdString, cmTarget*>::const_iterator + for(TargetMap::const_iterator ti = this->TotalTargets.begin(); ti != this->TotalTargets.end(); ++ti) { this->ForceLinkerLanguage(*ti->second); @@ -1239,12 +1250,12 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) return; } - const char* llang = cmtarget.GetLinkerLanguage("NOCONFIG"); - if(!llang) { return; } + std::string llang = cmtarget.GetLinkerLanguage("NOCONFIG"); + if(llang.empty()) { return; } // If the language is compiled as a source trust Xcode to link with it. cmTarget::LinkImplementation const* impl = - cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget); + cmtarget.GetLinkImplementation("NOCONFIG"); for(std::vector<std::string>::const_iterator li = impl->Languages.begin(); li != impl->Languages.end(); ++li) { @@ -1268,8 +1279,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget) } if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str())) { - sf->SetProperty("LANGUAGE", llang); - cmtarget.AddSourceFile(sf); + sf->SetProperty("LANGUAGE", llang.c_str()); + cmtarget.AddSource(fname); } } @@ -1364,7 +1375,10 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, } std::vector<cmSourceFile*> classes; - cmtarget.GetSourceFiles(classes); + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } // add all the sources std::vector<cmCustomCommand> commands; for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); @@ -1479,32 +1493,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, const & commands, const char* name) { - - // collect multiple outputs of custom commands into a set - // which will be used for every configuration - std::map<cmStdString, cmStdString> multipleOutputPairs; - for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); - i != commands.end(); ++i) - { - cmCustomCommand const& cc = *i; - if(!cc.GetCommandLines().empty()) - { - const std::vector<std::string>& outputs = cc.GetOutputs(); - if(!outputs.empty()) - { - // If there are more than one outputs treat the - // first as the primary output and make the rest depend on it. - std::vector<std::string>::const_iterator o = outputs.begin(); - std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str()); - for(++o; o != outputs.end(); ++o) - { - std::string currentOutput=this->ConvertToRelativeForMake(o->c_str()); - multipleOutputPairs[currentOutput] = primaryOutput; - } - } - } - } - + bool haveMultipleOutputPairs = false; std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory(); dir += "/CMakeScripts"; cmSystemTools::MakeDirectory(dir.c_str()); @@ -1524,7 +1513,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, target, commands, currentConfig->c_str(), - multipleOutputPairs); + haveMultipleOutputPairs); } std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); @@ -1534,7 +1523,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase, makecmd += " -f "; makecmd += this->ConvertToRelativeForMake( (makefile+"$CONFIGURATION").c_str()); - if(!multipleOutputPairs.empty()) + if(haveMultipleOutputPairs) { makecmd += " cmake_check_multiple_outputs"; } @@ -1552,10 +1541,8 @@ void cmGlobalXCodeGenerator cmTarget& target, std::vector<cmCustomCommand> const & commands, - const char* configName, - const std::map<cmStdString, - cmStdString>& multipleOutputPairs - ) + const std::string& configName, + bool& haveMultipleOutputPairs) { std::string makefileName=makefileBasename; if(this->XcodeVersion > 20) @@ -1576,15 +1563,16 @@ void cmGlobalXCodeGenerator // have all depend on all outputs makefileStream << "all: "; - std::map<const cmCustomCommand*, cmStdString> tname; + std::map<const cmCustomCommand*, std::string> tname; int count = 0; + std::map<std::string, std::string> multipleOutputPairs; for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommand const& cc = *i; - if(!cc.GetCommandLines().empty()) + cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile); + if(ccg.GetNumberOfCommands() > 0) { - const std::vector<std::string>& outputs = cc.GetOutputs(); + const std::vector<std::string>& outputs = ccg.GetOutputs(); if(!outputs.empty()) { for(std::vector<std::string>::const_iterator o = outputs.begin(); @@ -1593,13 +1581,23 @@ void cmGlobalXCodeGenerator makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); } + + // If there is more than one output treat the first as the + // primary output and make the rest depend on it. + std::vector<std::string>::const_iterator o = outputs.begin(); + std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str()); + for(++o; o != outputs.end(); ++o) + { + std::string currentOutput=this->ConvertToRelativeForMake(o->c_str()); + multipleOutputPairs[currentOutput] = primaryOutput; + } } else { cmOStringStream str; str << "_buildpart_" << count++ ; - tname[&cc] = std::string(target.GetName()) + str.str(); - makefileStream << "\\\n\t" << tname[&cc]; + tname[&ccg.GetCC()] = std::string(target.GetName()) + str.str(); + makefileStream << "\\\n\t" << tname[&ccg.GetCC()]; } } } @@ -1607,12 +1605,11 @@ void cmGlobalXCodeGenerator for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); i != commands.end(); ++i) { - cmCustomCommand const& cc = *i; - if(!cc.GetCommandLines().empty()) + cmCustomCommandGenerator ccg(*i, configName, this->CurrentMakefile); + if(ccg.GetNumberOfCommands() > 0) { - cmCustomCommandGenerator ccg(cc, configName, this->CurrentMakefile); makefileStream << "\n"; - const std::vector<std::string>& outputs = cc.GetOutputs(); + const std::vector<std::string>& outputs = ccg.GetOutputs(); if(!outputs.empty()) { // There is at least one output, start the rule for it @@ -1623,11 +1620,11 @@ void cmGlobalXCodeGenerator else { // There are no outputs. Use the generated force rule name. - makefileStream << tname[&cc] << ": "; + makefileStream << tname[&ccg.GetCC()] << ": "; } for(std::vector<std::string>::const_iterator d = - cc.GetDepends().begin(); - d != cc.GetDepends().end(); ++d) + ccg.GetDepends().begin(); + d != ccg.GetDepends().end(); ++d) { std::string dep; if(this->CurrentLocalGenerator @@ -1639,11 +1636,11 @@ void cmGlobalXCodeGenerator } makefileStream << "\n"; - if(const char* comment = cc.GetComment()) + if(const char* comment = ccg.GetComment()) { std::string echo_cmd = "echo "; echo_cmd += (this->CurrentLocalGenerator-> - EscapeForShell(comment, cc.GetEscapeAllowMakeVars())); + EscapeForShell(comment, ccg.GetCC().GetEscapeAllowMakeVars())); makefileStream << "\t" << echo_cmd.c_str() << "\n"; } @@ -1655,10 +1652,11 @@ void cmGlobalXCodeGenerator cmSystemTools::ReplaceString(cmd2, "/./", "/"); cmd2 = this->ConvertToRelativeForMake(cmd2.c_str()); std::string cmd; - if(cc.GetWorkingDirectory()) + std::string wd = ccg.GetWorkingDirectory(); + if(!wd.empty()) { cmd += "cd "; - cmd += this->ConvertToRelativeForMake(cc.GetWorkingDirectory()); + cmd += this->ConvertToRelativeForMake(wd.c_str()); cmd += " && "; } cmd += cmd2; @@ -1674,7 +1672,7 @@ void cmGlobalXCodeGenerator makefileStream << "\n# Dependencies of multiple outputs to their primary outputs \n"; - for(std::map<cmStdString, cmStdString>::const_iterator o = + for(std::map<std::string, std::string>::const_iterator o = multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) { makefileStream << o->first << ": " << o->second << "\n"; @@ -1683,7 +1681,7 @@ void cmGlobalXCodeGenerator makefileStream << "\n" "cmake_check_multiple_outputs:\n"; - for(std::map<cmStdString, cmStdString>::const_iterator o = + for(std::map<std::string, std::string>::const_iterator o = multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o) { makefileStream << "\t@if [ ! -f " @@ -1691,12 +1689,15 @@ void cmGlobalXCodeGenerator << o->second << "; fi\n"; } } + + haveMultipleOutputPairs = + haveMultipleOutputPairs || !multipleOutputPairs.empty(); } //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, - cmXCodeObject* buildSettings, - const char* configName) + cmXCodeObject* buildSettings, + const std::string& configName) { if(target.GetType() == cmTarget::INTERFACE_LIBRARY) { @@ -1712,12 +1713,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, (target.GetType() == cmTarget::EXECUTABLE) || shared); - const char* lang = target.GetLinkerLanguage(configName); + std::string lang = target.GetLinkerLanguage(configName); std::string cflags; - if(lang) + if(!lang.empty()) { // for c++ projects get the c flags as well - if(strcmp(lang, "CXX") == 0) + if(lang == "CXX") { this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName); this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, @@ -1743,7 +1744,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { cmSystemTools::Error ("CMake can not determine linker language for target: ", - target.GetName()); + target.GetName().c_str()); return; } @@ -1809,7 +1810,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CurrentLocalGenerator-> AppendFlags(extraLinkOptions, targetLinkFlags); } - if(configName && *configName) + if(!configName.empty()) { std::string linkFlagsVar = "LINK_FLAGS_"; linkFlagsVar += cmSystemTools::UpperCase(configName); @@ -2093,7 +2094,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, std::vector<std::string> includes; this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C", configName); - std::set<cmStdString> emitted; + std::set<std::string> emitted; emitted.insert("/System/Library/Frameworks"); for(std::vector<std::string>::iterator i = includes.begin(); i != includes.end(); ++i) @@ -2176,7 +2177,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, const char* debugStr = "YES"; // We can't set the Xcode flag differently depending on the language, // so put them back in this case. - if( (lang && strcmp(lang, "CXX") == 0) && gflag != gflagc ) + if( (lang == "CXX") && gflag != gflagc ) { cflags += " "; cflags += gflagc; @@ -2199,7 +2200,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, this->CreateString("NO")); buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN", this->CreateString("NO")); - if(lang && strcmp(lang, "CXX") == 0) + if(lang == "CXX") { flags += " "; flags += defFlags; @@ -2362,18 +2363,18 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target, { if(i->first.find("XCODE_ATTRIBUTE_") == 0) { - cmStdString attribute = i->first.substr(16); + std::string attribute = i->first.substr(16); // Handle [variant=<config>] condition explicitly here. - cmStdString::size_type beginVariant = + std::string::size_type beginVariant = attribute.find("[variant="); - if (beginVariant != cmStdString::npos) + if (beginVariant != std::string::npos) { - cmStdString::size_type endVariant = + std::string::size_type endVariant = attribute.find("]", beginVariant+9); - if (endVariant != cmStdString::npos) + if (endVariant != std::string::npos) { // Compare the variant to the configuration. - cmStdString variant = + std::string variant = attribute.substr(beginVariant+9, endVariant-beginVariant-9); if (variant == configName) { @@ -2426,7 +2427,7 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXAggregateTarget); - target->SetComment(cmtarget.GetName()); + target->SetComment(cmtarget.GetName().c_str()); cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); std::vector<cmXCodeObject*> emptyContentVector; @@ -2439,8 +2440,8 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) } else { - const char* theConfig = - this->CurrentMakefile->GetDefinition("CMAKE_BUILD_TYPE"); + std::string theConfig = + this->CurrentMakefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); this->CreateBuildSettings(cmtarget, buildSettings, theConfig); @@ -2457,7 +2458,11 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) if(cmtarget.GetType() == cmTarget::UTILITY) { std::vector<cmSourceFile*> sources; - cmtarget.GetSourceFiles(sources); + if (!cmtarget.GetConfigCommonSourceFiles(sources)) + { + return 0; + } + for(std::vector<cmSourceFile*>::const_iterator i = sources.begin(); i != sources.end(); ++i) { @@ -2643,7 +2648,7 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget, fileRef->AddAttribute("refType", this->CreateString("0")); fileRef->AddAttribute("sourceTree", this->CreateString("BUILT_PRODUCTS_DIR")); - fileRef->SetComment(cmtarget.GetName()); + fileRef->SetComment(cmtarget.GetName().c_str()); target->AddAttribute("productReference", this->CreateObjectReference(fileRef)); if(const char* productType = this->GetTargetProductType(cmtarget)) @@ -2676,8 +2681,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget const* t) } //---------------------------------------------------------------------------- -std::string cmGlobalXCodeGenerator::GetOrCreateId(const char* name, - const char* id) +std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, + const std::string& id) { std::string guidStoreName = name; guidStoreName += "_GUID_CMAKE"; @@ -2690,7 +2695,7 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const char* name, } this->CMakeInstance->AddCacheEntry(guidStoreName.c_str(), - id, "Stored Xcode object GUID", cmCacheManager::INTERNAL); + id.c_str(), "Stored Xcode object GUID", cmCacheManager::INTERNAL); return id; } @@ -2759,7 +2764,7 @@ void cmGlobalXCodeGenerator ::AppendBuildSettingAttribute(cmXCodeObject* target, const char* attribute, const char* value, - const char* configName) + const std::string& configName) { if(this->XcodeVersion < 21) { @@ -2782,9 +2787,9 @@ void cmGlobalXCodeGenerator for(std::vector<cmXCodeObject*>::iterator i = list.begin(); i != list.end(); ++i) { - if(configName) + if(!configName.empty()) { - if(strcmp((*i)->GetObject("name")->GetString(), configName) == 0) + if((*i)->GetObject("name")->GetString() == configName) { cmXCodeObject* settings = (*i)->GetObject("buildSettings"); this->AppendOrAddBuildSetting(settings, attribute, value); @@ -2830,11 +2835,7 @@ void cmGlobalXCodeGenerator i != this->CurrentConfigurationTypes.end(); ++i) { // Get the current configuration name. - const char* configName = i->c_str(); - if(!*configName) - { - configName = 0; - } + std::string configName = *i; if(this->XcodeVersion >= 50) { @@ -2842,7 +2843,7 @@ void cmGlobalXCodeGenerator std::string linkObjs; const char* sep = ""; std::vector<std::string> objs; - this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs); + this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs, ""); for(std::vector<std::string>::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -2974,13 +2975,15 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")) { std::string plist = this->ComputeInfoPListLocation(cmtarget); - cmSourceFile* sf = mf->GetOrCreateSource(plist.c_str(), true); - cmtarget.AddSourceFile(sf); + mf->GetOrCreateSource(plist, true); + cmtarget.AddSource(plist); } std::vector<cmSourceFile*> classes; - cmtarget.GetSourceFiles(classes); - + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } // Put cmSourceFile instances in proper groups: for(std::vector<cmSourceFile*>::const_iterator s = classes.begin(); s != classes.end(); s++) @@ -2992,13 +2995,13 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, mf->FindSourceGroup(source.c_str(), sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(cmtarget, sourceGroup); - cmStdString key = GetGroupMapKey(cmtarget, sf); + std::string 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); + this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs, ""); for(std::vector<std::string>::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -3007,7 +3010,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, mf->FindSourceGroup(source.c_str(), sourceGroups); cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(cmtarget, sourceGroup); - cmStdString key = GetGroupMapKeyFromPath(cmtarget, source); + std::string key = GetGroupMapKeyFromPath(cmtarget, source); this->GroupMap[key] = pbxgroup; } } @@ -3015,7 +3018,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, } cmXCodeObject *cmGlobalXCodeGenerator -::CreatePBXGroup(cmXCodeObject *parent, cmStdString name) +::CreatePBXGroup(cmXCodeObject *parent, std::string name) { cmXCodeObject* parentChildren = NULL; if(parent) @@ -3039,8 +3042,8 @@ cmXCodeObject *cmGlobalXCodeGenerator cmXCodeObject* cmGlobalXCodeGenerator ::CreateOrGetPBXGroup(cmTarget& cmtarget, cmSourceGroup* sg) { - cmStdString s; - cmStdString target; + std::string s; + std::string target; const char *targetFolder= cmtarget.GetProperty("FOLDER"); if(targetFolder) { target = targetFolder; @@ -3049,7 +3052,7 @@ cmXCodeObject* cmGlobalXCodeGenerator target += cmtarget.GetName(); s = target + "/"; s += sg->GetFullName(); - std::map<cmStdString, cmXCodeObject* >::iterator it = + std::map<std::string, cmXCodeObject* >::iterator it = this->GroupNameMap.find(s); if(it != this->GroupNameMap.end()) { @@ -3066,7 +3069,7 @@ cmXCodeObject* cmGlobalXCodeGenerator { std::vector<std::string> tgt_folders = cmSystemTools::tokenize(target, "/"); - cmStdString curr_tgt_folder; + std::string curr_tgt_folder; for(std::vector<std::string>::size_type i = 0; i < tgt_folders.size();i++) { if (i != 0) @@ -3093,7 +3096,7 @@ cmXCodeObject* cmGlobalXCodeGenerator // If it's the default source group (empty name) then put the source file // directly in the tgroup... // - if (cmStdString(sg->GetFullName()) == "") + if (std::string(sg->GetFullName()) == "") { this->GroupNameMap[s] = tgroup; return tgroup; @@ -3104,12 +3107,12 @@ cmXCodeObject* cmGlobalXCodeGenerator { std::vector<std::string> folders = cmSystemTools::tokenize(sg->GetFullName(), "\\"); - cmStdString curr_folder = target; + std::string curr_folder = target; curr_folder += "/"; for(std::vector<std::string>::size_type i = 0; i < folders.size();i++) { curr_folder += folders[i]; - std::map<cmStdString, cmXCodeObject* >::iterator i_folder = + std::map<std::string, cmXCodeObject* >::iterator i_folder = this->GroupNameMap.find(curr_folder); //Create new folder if(i_folder == this->GroupNameMap.end()) @@ -3372,10 +3375,10 @@ void cmGlobalXCodeGenerator buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET", this->CreateString(deploymentTarget)); } - if(!this->PlatformToolset.empty()) + if(!this->GeneratorToolset.empty()) { buildSettings->AddAttribute("GCC_VERSION", - this->CreateString(this->PlatformToolset.c_str())); + this->CreateString(this->GeneratorToolset.c_str())); } // Put this last so it can override existing settings @@ -3489,14 +3492,14 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( makefileStream << "# For each target create a dummy rule " "so the target does not have to exist\n"; - std::set<cmStdString> emitted; + std::set<std::string> emitted; for(std::vector<cmXCodeObject*>::iterator i = targets.begin(); i != targets.end(); ++i) { cmXCodeObject* target = *i; - std::map<cmStdString, cmXCodeObject::StringVec> const& deplibs = + std::map<std::string, cmXCodeObject::StringVec> const& deplibs = target->GetDependLibraries(); - for(std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator ci + for(std::map<std::string, cmXCodeObject::StringVec>::const_iterator ci = deplibs.begin(); ci != deplibs.end(); ++ci) { for(cmXCodeObject::StringVec::const_iterator d = ci->second.begin(); @@ -3521,11 +3524,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( ct = this->CurrentConfigurationTypes.begin(); ct != this->CurrentConfigurationTypes.end(); ++ct) { - const char* configName = 0; - if(!ct->empty()) - { - configName = ct->c_str(); - } + std::string configName = *ct; for(std::vector<cmXCodeObject*>::iterator i = targets.begin(); i != targets.end(); ++i) { @@ -3552,12 +3551,12 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::string trel = this->ConvertToRelativeForMake(tfull.c_str()); // Add this target to the post-build phases of its dependencies. - std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator + std::map<std::string, cmXCodeObject::StringVec>::const_iterator y = target->GetDependTargets().find(*ct); if(y != target->GetDependTargets().end()) { - std::vector<cmStdString> const& deptgts = y->second; - for(std::vector<cmStdString>::const_iterator d = deptgts.begin(); + std::vector<std::string> const& deptgts = y->second; + for(std::vector<std::string>::const_iterator d = deptgts.begin(); d != deptgts.end(); ++d) { makefileStream << this->PostBuildMakeTarget(*d, *ct) << ": " @@ -3569,12 +3568,12 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( makefileStream << trel << ":"; // List dependencies if any exist. - std::map<cmStdString, cmXCodeObject::StringVec>::const_iterator + std::map<std::string, cmXCodeObject::StringVec>::const_iterator x = target->GetDependLibraries().find(*ct); if(x != target->GetDependLibraries().end()) { - std::vector<cmStdString> const& deplibs = x->second; - for(std::vector<cmStdString>::const_iterator d = deplibs.begin(); + std::vector<std::string> const& deplibs = x->second; + for(std::vector<std::string>::const_iterator d = deplibs.begin(); d != deplibs.end(); ++d) { makefileStream << "\\\n\t" << @@ -3799,14 +3798,14 @@ std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p) //---------------------------------------------------------------------------- void cmGlobalXCodeGenerator -::AppendDirectoryForConfig(const char* prefix, - const char* config, - const char* suffix, +::AppendDirectoryForConfig(const std::string& prefix, + const std::string& config, + const std::string& suffix, std::string& dir) { if(this->XcodeVersion > 20) { - if(config) + if(!config.empty()) { dir += prefix; dir += config; @@ -3816,12 +3815,13 @@ cmGlobalXCodeGenerator } //---------------------------------------------------------------------------- -std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix, - const char* varNameLang, - const char* varNameSuffix, - const char* default_flags) +std::string cmGlobalXCodeGenerator::LookupFlags( + const std::string& varNamePrefix, + const std::string& varNameLang, + const std::string& varNameSuffix, + const std::string& default_flags) { - if(varNameLang) + if(!varNameLang.empty()) { std::string varName = varNamePrefix; varName += varNameLang; @@ -3973,38 +3973,11 @@ bool cmGlobalXCodeGenerator::IsMultiConfig() return true; } - //---------------------------------------------------------------------------- -void -cmGlobalXCodeGenerator -::ComputeTargetObjects(cmGeneratorTarget* gt) const +//---------------------------------------------------------------------------- +void cmGlobalXCodeGenerator +::ComputeTargetObjectDirectory(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; - std::vector<cmSourceFile*> objectSources; - gt->GetObjectSources(objectSources); - for(std::vector<cmSourceFile*>::const_iterator - si = objectSources.begin(); - si != 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->AddObject(sf, objectName); - } - - const char* configName = this->GetCMakeCFGIntDir(); + std::string configName = this->GetCMakeCFGIntDir(); std::string dir = this->GetObjectsNormalDirectory( "$(PROJECT_NAME)", configName, gt->Target); if(this->XcodeVersion >= 21) |