diff options
Diffstat (limited to 'Source/cmGlobalXCodeGenerator.cxx')
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 2122 |
1 files changed, 1124 insertions, 998 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 903796123..3002b2a68 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -2,15 +2,21 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGlobalXCodeGenerator.h" -#include "cmsys/RegularExpression.hxx" -#include <assert.h> +#include <cassert> +#include <cstdio> +#include <cstring> #include <iomanip> #include <sstream> -#include <stdio.h> -#include <string.h> +#include <cm/memory> + +#include "cmsys/RegularExpression.hxx" + +#include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" +#include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" +#include "cmCustomCommandLines.h" #include "cmDocumentationEntry.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" @@ -19,6 +25,7 @@ #include "cmLocalGenerator.h" #include "cmLocalXCodeGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" @@ -29,13 +36,17 @@ #include "cmXCode21Object.h" #include "cmXCodeObject.h" #include "cmXCodeScheme.h" -#include "cm_auto_ptr.hxx" #include "cmake.h" struct cmLinkImplementation; -#if defined(CMAKE_BUILD_WITH_CMAKE) -#include "cmXMLParser.h" +#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__) +# define HAVE_APPLICATION_SERVICES +# include <ApplicationServices/ApplicationServices.h> +#endif + +#if !defined(CMAKE_BOOTSTRAP) +# include "cmXMLParser.h" // parse the xml file storing the installed version of Xcode on // the machine @@ -46,8 +57,11 @@ public: : Version("1.5") { } - void StartElement(const std::string&, const char**) { this->Data = ""; } - void EndElement(const std::string& name) + void StartElement(const std::string&, const char**) override + { + this->Data = ""; + } + void EndElement(const std::string& name) override { if (name == "key") { this->Key = this->Data; @@ -57,7 +71,7 @@ public: } } } - void CharacterDataHandler(const char* data, int length) + void CharacterDataHandler(const char* data, int length) override { this->Data.append(data, length); } @@ -79,7 +93,7 @@ class cmGlobalXCodeGenerator::BuildObjectListOrString public: BuildObjectListOrString(cmGlobalXCodeGenerator* gen, bool buildObjectList) : Generator(gen) - , Group(0) + , Group(nullptr) , Empty(true) { if (buildObjectList) { @@ -107,9 +121,8 @@ public: { if (this->Group) { return this->Group; - } else { - return this->Generator->CreateString(this->String); } + return this->Generator->CreateString(this->String); } }; @@ -117,20 +130,34 @@ class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory { public: cmGlobalGenerator* CreateGlobalGenerator(const std::string& name, - cmake* cm) const CM_OVERRIDE; + cmake* cm) const override; - void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE + void GetDocumentation(cmDocumentationEntry& entry) const override { cmGlobalXCodeGenerator::GetDocumentation(entry); } - void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE + std::vector<std::string> GetGeneratorNames() const override { + std::vector<std::string> names; names.push_back(cmGlobalXCodeGenerator::GetActualName()); + return names; } - bool SupportsToolset() const CM_OVERRIDE { return true; } - bool SupportsPlatform() const CM_OVERRIDE { return false; } + std::vector<std::string> GetGeneratorNamesWithPlatform() const override + { + return std::vector<std::string>(); + } + + bool SupportsToolset() const override { return true; } + bool SupportsPlatform() const override { return false; } + + std::vector<std::string> GetKnownPlatforms() const override + { + return std::vector<std::string>(); + } + + std::string GetDefaultPlatformName() const override { return std::string(); } }; cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( @@ -140,10 +167,10 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( this->VersionString = version_string; this->XcodeVersion = version_number; - this->RootObject = 0; - this->MainGroupChildren = 0; - this->CurrentMakefile = 0; - this->CurrentLocalGenerator = 0; + this->RootObject = nullptr; + this->MainGroupChildren = nullptr; + this->CurrentMakefile = nullptr; + this->CurrentLocalGenerator = nullptr; this->XcodeBuildCommandInitialized = false; this->ObjectDirArchDefault = "$(CURRENT_ARCH)"; @@ -160,21 +187,25 @@ cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( const std::string& name, cmake* cm) const { - if (name != GetActualName()) - return 0; -#if defined(CMAKE_BUILD_WITH_CMAKE) + if (name != GetActualName()) { + return nullptr; + } +#if !defined(CMAKE_BOOTSTRAP) cmXcodeVersionParser parser; std::string versionFile; { std::string out; - std::string::size_type pos; - if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0, - 0, 0, cmSystemTools::OUTPUT_NONE) && - (pos = out.find(".app/"), pos != std::string::npos)) { - versionFile = out.substr(0, pos + 5) + "Contents/version.plist"; + bool commandResult = cmSystemTools::RunSingleCommand( + "xcode-select --print-path", &out, nullptr, nullptr, nullptr, + cmSystemTools::OUTPUT_NONE); + if (commandResult) { + std::string::size_type pos = out.find(".app/"); + if (pos != std::string::npos) { + versionFile = out.substr(0, pos + 5) + "Contents/version.plist"; + } } } - if (!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str())) { + if (!versionFile.empty() && cmSystemTools::FileExists(versionFile)) { parser.ParseFile(versionFile.c_str()); } else if (cmSystemTools::FileExists( "/Applications/Xcode.app/Contents/version.plist")) { @@ -190,14 +221,14 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator( sscanf(version_string.c_str(), "%u.%u", &v[0], &v[1]); unsigned int version_number = 10 * v[0] + v[1]; - if (version_number < 30) { - cm->IssueMessage(cmake::FATAL_ERROR, + if (version_number < 50) { + cm->IssueMessage(MessageType::FATAL_ERROR, "Xcode " + version_string + " not supported."); - return CM_NULLPTR; + return nullptr; } - CM_AUTO_PTR<cmGlobalXCodeGenerator> gg( - new cmGlobalXCodeGenerator(cm, version_string, version_number)); + auto gg = cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string, + version_number); return gg.release(); #else std::cerr << "CMake should be built with cmake to use Xcode, " @@ -211,9 +242,8 @@ bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf) // The Xcode generator knows how to lookup its build tool // directly instead of needing a helper module to do it, so we // do not actually need to put CMAKE_MAKE_PROGRAM into the cache. - if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { - mf->AddDefinition("CMAKE_MAKE_PROGRAM", - this->GetXcodeBuildCommand().c_str()); + if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) { + mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetXcodeBuildCommand()); } return true; } @@ -229,16 +259,11 @@ std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand() std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand() { - if (this->XcodeVersion >= 40) { - std::string makeProgram = cmSystemTools::FindProgram("xcodebuild"); - if (makeProgram.empty()) { - makeProgram = "xcodebuild"; - } - return makeProgram; - } else { - // Use cmakexbuild wrapper to suppress environment dump from output. - return cmSystemTools::GetCMakeCommand() + "xbuild"; + std::string makeProgram = cmSystemTools::FindProgram("xcodebuild"); + if (makeProgram.empty()) { + makeProgram = "xcodebuild"; } + return makeProgram; } bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, @@ -254,13 +279,12 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts, " " << ts << "\n" "that was specified."; /* clang-format on */ - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); return false; } this->GeneratorToolset = ts; if (!this->GeneratorToolset.empty()) { - mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", - this->GeneratorToolset.c_str()); + mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset); } return true; } @@ -269,7 +293,7 @@ void cmGlobalXCodeGenerator::EnableLanguage( std::vector<std::string> const& lang, cmMakefile* mf, bool optional) { mf->AddDefinition("XCODE", "1"); - mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str()); + mf->AddDefinition("XCODE_VERSION", this->VersionString); if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { mf->AddCacheDefinition( "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", @@ -283,46 +307,87 @@ void cmGlobalXCodeGenerator::EnableLanguage( this->ComputeArchitectures(mf); } -void cmGlobalXCodeGenerator::GenerateBuildCommand( - std::vector<std::string>& makeCommand, const std::string& makeProgram, - const std::string& projectName, const std::string& /*projectDir*/, - const std::string& targetName, const std::string& config, bool /*fast*/, - bool /*verbose*/, std::vector<std::string> const& makeOptions) +bool cmGlobalXCodeGenerator::Open(const std::string& bindir, + const std::string& projectName, bool dryRun) +{ + bool ret = false; + +#ifdef HAVE_APPLICATION_SERVICES + std::string url = bindir + "/" + projectName + ".xcodeproj"; + + if (dryRun) { + return cmSystemTools::FileExists(url, false); + } + + CFStringRef cfStr = CFStringCreateWithCString( + kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8); + if (cfStr) { + CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr, + kCFURLPOSIXPathStyle, true); + if (cfUrl) { + OSStatus err = LSOpenCFURLRef(cfUrl, nullptr); + ret = err == noErr; + CFRelease(cfUrl); + } + CFRelease(cfStr); + } +#endif + + return ret; +} + +std::vector<cmGlobalGenerator::GeneratedMakeCommand> +cmGlobalXCodeGenerator::GenerateBuildCommand( + const std::string& makeProgram, const std::string& projectName, + const std::string& /*projectDir*/, + std::vector<std::string> const& targetNames, const std::string& config, + bool /*fast*/, int jobs, bool /*verbose*/, + std::vector<std::string> const& makeOptions) { + GeneratedMakeCommand makeCommand; // now build the test - makeCommand.push_back( + makeCommand.Add( this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand())); - makeCommand.push_back("-project"); - std::string projectArg = projectName; - projectArg += ".xcode"; - projectArg += "proj"; - makeCommand.push_back(projectArg); - - bool clean = false; - std::string realTarget = targetName; - if (realTarget == "clean") { - clean = true; - realTarget = "ALL_BUILD"; + if (!projectName.empty()) { + makeCommand.Add("-project"); + std::string projectArg = cmStrCat(projectName, ".xcodeproj"); + makeCommand.Add(projectArg); } - if (clean) { - makeCommand.push_back("clean"); + if (cmContains(targetNames, "clean")) { + makeCommand.Add("clean"); + makeCommand.Add("-target", "ALL_BUILD"); } else { - makeCommand.push_back("build"); + makeCommand.Add("build"); + if (targetNames.empty() || + ((targetNames.size() == 1) && targetNames.front().empty())) { + makeCommand.Add("-target", "ALL_BUILD"); + } else { + for (const auto& tname : targetNames) { + if (!tname.empty()) { + makeCommand.Add("-target", tname); + } + } + } } - makeCommand.push_back("-target"); - if (!realTarget.empty()) { - makeCommand.push_back(realTarget); - } else { - makeCommand.push_back("ALL_BUILD"); + + makeCommand.Add("-configuration", (config.empty() ? "Debug" : config)); + + if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { + makeCommand.Add("-jobs"); + if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) { + makeCommand.Add(std::to_string(jobs)); + } } - makeCommand.push_back("-configuration"); - makeCommand.push_back(!config.empty() ? config : "Debug"); - makeCommand.insert(makeCommand.end(), makeOptions.begin(), - makeOptions.end()); + + if (this->XcodeVersion >= 70) { + makeCommand.Add("-hideShellScriptEnvironment"); + } + makeCommand.Add(makeOptions.begin(), makeOptions.end()); + return { std::move(makeCommand) }; } -///! Create a local generator appropriate to this Global Generator +//! Create a local generator appropriate to this Global Generator cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) { return new cmLocalXCodeGenerator(this, mf); @@ -330,15 +395,45 @@ cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) void cmGlobalXCodeGenerator::AddExtraIDETargets() { - 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) { - cmLocalGenerator* root = it->second[0]; + for (auto keyVal : this->ProjectMap) { + cmLocalGenerator* root = keyVal.second[0]; this->SetGenerationRoot(root); // add ALL_BUILD, INSTALL, etc - this->AddExtraTargets(root, it->second); + this->AddExtraTargets(root, keyVal.second); + } +} + +void cmGlobalXCodeGenerator::ComputeTargetOrder() +{ + size_t index = 0; + auto const& lgens = this->GetLocalGenerators(); + for (cmLocalGenerator* lgen : lgens) { + auto const& targets = lgen->GetGeneratorTargets(); + for (cmGeneratorTarget const* gt : targets) { + this->ComputeTargetOrder(gt, index); + } + } + assert(index == this->TargetOrderIndex.size()); +} + +void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, + size_t& index) +{ + std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0); + auto insertion = this->TargetOrderIndex.insert(value); + if (!insertion.second) { + return; + } + auto entry = insertion.first; + + auto& deps = this->GetTargetDirectDepends(gt); + for (auto& d : deps) { + this->ComputeTargetOrder(d, index); } + + entry->second = index++; } void cmGlobalXCodeGenerator::Generate() @@ -347,12 +442,25 @@ void cmGlobalXCodeGenerator::Generate() if (cmSystemTools::GetErrorOccuredFlag()) { return; } - std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it; - for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) { - cmLocalGenerator* root = it->second[0]; + + this->ComputeTargetOrder(); + + for (auto keyVal : this->ProjectMap) { + cmLocalGenerator* root = keyVal.second[0]; + + bool generateTopLevelProjectOnly = + root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + + if (generateTopLevelProjectOnly) { + cmStateSnapshot snp = root->GetStateSnapshot(); + if (snp.GetBuildsystemDirectoryParent().IsValid()) { + continue; + } + } + this->SetGenerationRoot(root); // now create the project - this->OutputXCodeProject(root, it->second); + this->OutputXCodeProject(root, keyVal.second); } } @@ -367,9 +475,9 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root) this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), this->ProjectOutputDirectoryComponents); - this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory(); - this->CurrentXCodeHackMakefile += "/CMakeScripts"; - cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str()); + this->CurrentXCodeHackMakefile = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts"); + cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile); this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make"; } @@ -378,54 +486,52 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( { std::string target = tName; std::replace(target.begin(), target.end(), ' ', '_'); - std::string out = "PostBuild." + target; - out += "." + configName; + std::string out = cmStrCat("PostBuild.", target, '.', configName); return out; } #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" +#define OBJECT_LIBRARY_ARTIFACT_DIR std::string() void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) { cmMakefile* mf = root->GetMakefile(); - // Add ALL_BUILD - const char* no_working_directory = 0; + const char* no_working_directory = nullptr; + std::vector<std::string> no_byproducts; std::vector<std::string> no_depends; - cmTarget* allbuild = - mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory, - "echo", "Build all projects"); + + // Add ALL_BUILD + cmTarget* allbuild = mf->AddUtilityCommand( + "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory, + no_byproducts, no_depends, + cmMakeSingleCommandLine({ "echo", "Build all projects" })); cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); root->AddGeneratorTarget(allBuildGt); - // Refer to the main build configuration file for easy editing. - std::string listfile = root->GetCurrentSourceDirectory(); - listfile += "/"; - listfile += "CMakeLists.txt"; - allBuildGt->AddSource(listfile); - // Add XCODE depend helper std::string dir = root->GetCurrentBinaryDirectory(); - cmCustomCommandLine makeHelper; - makeHelper.push_back("make"); - makeHelper.push_back("-C"); - makeHelper.push_back(dir); - makeHelper.push_back("-f"); - makeHelper.push_back(this->CurrentXCodeHackMakefile); - makeHelper.push_back(""); // placeholder, see below + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { "make", "-C", dir, "-f", this->CurrentXCodeHackMakefile, + "OBJDIR=$(OBJDIR)", /* placeholder, see below */ "" }); // Add ZERO_CHECK - bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION"); - if (regenerate) { + bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION"); + bool generateTopLevelProjectOnly = + mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); + bool isTopLevel = + !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid(); + if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) { this->CreateReRunCMakeFile(root, gens); std::string file = - this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str()); + this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile); cmSystemTools::ReplaceString(file, "\\ ", " "); - cmTarget* check = - mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends, - no_working_directory, "make", "-f", file.c_str()); + cmTarget* check = mf->AddUtilityCommand( + CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, true, + no_working_directory, no_byproducts, no_depends, + cmMakeSingleCommandLine({ "make", "-f", file })); cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); root->AddGeneratorTarget(checkGt); @@ -433,25 +539,14 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // now make the allbuild depend on all the non-utility targets // in the project - for (std::vector<cmLocalGenerator*>::iterator i = gens.begin(); - i != gens.end(); ++i) { - cmLocalGenerator* lg = *i; - if (this->IsExcluded(root, *i)) { - continue; - } - - std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets(); - for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); - l != tgts.end(); l++) { - cmGeneratorTarget* target = *l; - + for (auto& gen : gens) { + for (auto target : gen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } - std::string targetName = target->GetName(); - - if (regenerate && (targetName != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) { + if (regenerate && + (target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) { target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET); } @@ -459,33 +554,19 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // run the depend check makefile as a post build rule // this will make sure that when the next target is built // things are up-to-date - if (target->GetType() == cmStateEnums::OBJECT_LIBRARY || - (this->XcodeVersion < 50 && - (target->GetType() == cmStateEnums::EXECUTABLE || - target->GetType() == cmStateEnums::STATIC_LIBRARY || - target->GetType() == cmStateEnums::SHARED_LIBRARY || - target->GetType() == cmStateEnums::MODULE_LIBRARY))) { - makeHelper[makeHelper.size() - 1] = // fill placeholder + if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) { + commandLines.front().back() = // fill placeholder this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)"); - cmCustomCommandLines commandLines; - commandLines.push_back(makeHelper); - std::vector<std::string> no_byproducts; - lg->GetMakefile()->AddCustomCommandToTarget( + gen->GetMakefile()->AddCustomCommandToTarget( target->GetName(), no_byproducts, no_depends, commandLines, - cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true, - false, "", false, cmMakefile::AcceptObjectLibraryCommands); + cmCustomCommandType::POST_BUILD, "Depend check for xcode", + dir.c_str(), true, false, "", "", false, + cmObjectLibraryCommands::Accept); } - if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY && - !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) { + if (!this->IsExcluded(gens[0], target)) { allbuild->AddUtility(target->GetName()); } - - // Refer to the build configuration file for easy editing. - listfile = lg->GetCurrentSourceDirectory(); - listfile += "/"; - listfile += "CMakeLists.txt"; - target->AddSource(listfile); } } } @@ -494,47 +575,60 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens) { std::vector<std::string> lfiles; - for (std::vector<cmLocalGenerator*>::const_iterator gi = gens.begin(); - gi != gens.end(); ++gi) { - std::vector<std::string> const& lf = (*gi)->GetMakefile()->GetListFiles(); - lfiles.insert(lfiles.end(), lf.begin(), lf.end()); + for (auto gen : gens) { + cmAppend(lfiles, gen->GetMakefile()->GetListFiles()); } // sort the array - std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>()); - std::vector<std::string>::iterator new_end = - std::unique(lfiles.begin(), lfiles.end()); - lfiles.erase(new_end, lfiles.end()); - this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory(); - this->CurrentReRunCMakeMakefile += "/CMakeScripts"; - cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str()); + std::sort(lfiles.begin(), lfiles.end()); + lfiles.erase(std::unique(lfiles.begin(), lfiles.end()), lfiles.end()); + + cmake* cm = this->GetCMakeInstance(); + if (cm->DoWriteGlobVerifyTarget()) { + lfiles.emplace_back(cm->GetGlobVerifyStamp()); + } + + this->CurrentReRunCMakeMakefile = + cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts"); + cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile); this->CurrentReRunCMakeMakefile += "/ReRunCMake.make"; - cmGeneratedFileStream makefileStream( - this->CurrentReRunCMakeMakefile.c_str()); + cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile); makefileStream.SetCopyIfDifferent(true); makefileStream << "# Generated by CMake, DO NOT EDIT\n\n"; + makefileStream << "TARGETS:= \n"; makefileStream << "empty:= \n"; makefileStream << "space:= $(empty) $(empty)\n"; makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n"; - for (std::vector<std::string>::const_iterator i = lfiles.begin(); - i != lfiles.end(); ++i) { + for (const auto& lfile : lfiles) { makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard " - << this->ConvertToRelativeForMake(i->c_str()) << "))\n"; + << this->ConvertToRelativeForMake(lfile) << "))\n"; } + makefileStream << "\n"; - std::string checkCache = root->GetBinaryDirectory(); - checkCache += "/"; - checkCache += cmake::GetCMakeFilesDirectoryPostSlash(); - checkCache += "cmake.check_cache"; + std::string checkCache = + cmStrCat(root->GetBinaryDirectory(), "/CMakeFiles/cmake.check_cache"); - makefileStream << "\n" - << this->ConvertToRelativeForMake(checkCache.c_str()) + if (cm->DoWriteGlobVerifyTarget()) { + makefileStream << ".NOTPARALLEL:\n\n"; + makefileStream << ".PHONY: all VERIFY_GLOBS\n\n"; + makefileStream << "all: VERIFY_GLOBS " + << this->ConvertToRelativeForMake(checkCache) << "\n\n"; + makefileStream << "VERIFY_GLOBS:\n"; + makefileStream << "\t" + << this->ConvertToRelativeForMake( + cmSystemTools::GetCMakeCommand()) + << " -P " + << this->ConvertToRelativeForMake(cm->GetGlobVerifyScript()) + << "\n\n"; + } + + makefileStream << this->ConvertToRelativeForMake(checkCache) << ": $(TARGETS)\n"; makefileStream << "\t" << this->ConvertToRelativeForMake( - cmSystemTools::GetCMakeCommand().c_str()) + cmSystemTools::GetCMakeCommand()) << " -H" << this->ConvertToRelativeForMake(root->GetSourceDirectory()) << " -B" @@ -556,8 +650,8 @@ void cmGlobalXCodeGenerator::SortXCodeObjects() void cmGlobalXCodeGenerator::ClearXCodeObjects() { this->TargetDoneSet.clear(); - for (unsigned int i = 0; i < this->XCodeObjects.size(); ++i) { - delete this->XCodeObjects[i]; + for (auto& obj : this->XCodeObjects) { + delete obj; } this->XCodeObjects.clear(); this->XCodeObjectIDs.clear(); @@ -571,7 +665,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects() void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj) { if (obj->GetType() == cmXCodeObject::OBJECT) { - std::string id = obj->GetId(); + const std::string& id = obj->GetId(); // If this is a duplicate id, it's an error: // @@ -649,9 +743,58 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath( return buildFile; } +class XCodeGeneratorExpressionInterpreter + : public cmGeneratorExpressionInterpreter +{ +public: + XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile, + cmLocalGenerator* localGenerator, + cmGeneratorTarget* headTarget, + const std::string& lang) + : cmGeneratorExpressionInterpreter( + localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang) + , SourceFile(sourceFile) + { + } + + XCodeGeneratorExpressionInterpreter( + XCodeGeneratorExpressionInterpreter const&) = delete; + XCodeGeneratorExpressionInterpreter& operator=( + XCodeGeneratorExpressionInterpreter const&) = delete; + + using cmGeneratorExpressionInterpreter::Evaluate; + + const std::string& Evaluate(const char* expression, + const std::string& property) + { + const std::string& processed = + this->cmGeneratorExpressionInterpreter::Evaluate(expression, property); + if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) { + std::ostringstream e; + /* clang-format off */ + e << + "Xcode does not support per-config per-source " << property << ":\n" + " " << expression << "\n" + "specified for source:\n" + " " << this->SourceFile->ResolveFullPath() << "\n"; + /* clang-format on */ + this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str()); + } + + return processed; + } + +private: + cmSourceFile* SourceFile = nullptr; +}; + cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt) { + std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); + + XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt, lang); + // Add flags from target and source file properties. std::string flags; const char* srcfmt = sf->GetProperty("Fortran_FORMAT"); @@ -665,29 +808,30 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( default: break; } - if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) { - cmGeneratorExpression ge; - std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE"; - CM_AUTO_PTR<cmCompiledGeneratorExpression> compiledExpr = ge.Parse(cflags); - const char* processed = compiledExpr->Evaluate(lg, configName); - if (compiledExpr->GetHadContextSensitiveCondition()) { - std::ostringstream e; - /* clang-format off */ - e << - "Xcode does not support per-config per-source COMPILE_FLAGS:\n" - " " << cflags << "\n" - "specified for source:\n" - " " << sf->GetFullPath() << "\n"; - /* clang-format on */ - lg->IssueMessage(cmake::FATAL_ERROR, e.str()); - } - lg->AppendFlags(flags, processed); + const std::string COMPILE_FLAGS("COMPILE_FLAGS"); + if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) { + lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS)); + } + const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); + if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) { + lg->AppendCompileOptions( + flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); } // Add per-source definitions. BuildObjectListOrString flagsBuild(this, false); - this->AppendDefines(flagsBuild, sf->GetProperty("COMPILE_DEFINITIONS"), - true); + const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); + if (const char* compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) { + this->AppendDefines( + flagsBuild, + genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(), + true); + } + + if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { + this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true); + } + if (!flagsBuild.IsEmpty()) { if (!flags.empty()) { flags += ' '; @@ -695,10 +839,18 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( flags += flagsBuild.GetString(); } - std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); + // Add per-source include directories. + std::vector<std::string> includes; + const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES"); + if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) { + lg->AppendIncludeDirectories( + includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES), + *sf); + } + lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true)); cmXCodeObject* buildFile = - this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf); + this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf); cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); settings->AddAttributeIfNotEmpty("COMPILER_FLAGS", @@ -724,13 +876,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( const char* extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES"); if (extraFileAttributes) { // Expand the list of attributes. - std::vector<std::string> attributes; - cmSystemTools::ExpandListArgument(extraFileAttributes, attributes); + std::vector<std::string> attributes = cmExpandedList(extraFileAttributes); // Store the attributes. - for (std::vector<std::string>::const_iterator ai = attributes.begin(); - ai != attributes.end(); ++ai) { - attrs->AddObject(this->CreateString(*ai)); + for (const auto& attribute : attributes) { + attrs->AddObject(this->CreateString(attribute)); } } @@ -740,6 +890,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( return buildFile; } +void cmGlobalXCodeGenerator::AddXCodeProjBuildRule( + cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const +{ + std::string listfile = + cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(), + "/CMakeLists.txt"); + cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource( + listfile, false, cmSourceFileLocationKind::Known); + if (!cmContains(sources, srcCMakeLists)) { + sources.push_back(srcCMakeLists); + } +} + std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, const std::string& lang, bool& keepLastKnownFileType) @@ -779,6 +942,10 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext, sourcecode += ".cpp.cpp"; } else if (lang == "C") { sourcecode += ".c.c"; + } else if (lang == "OBJCXX") { + sourcecode += ".cpp.objcpp"; + } else if (lang == "OBJC") { + sourcecode += ".c.objc"; } else if (lang == "Fortran") { sourcecode += ".fortran.f90"; } else if (lang == "ASM") { @@ -852,11 +1019,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( 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 path = this->RelativeToSource(fullpath); std::string name = cmSystemTools::GetFilenameName(path); const char* sourceTree = - (cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>" - : "SOURCE_ROOT"); + cmSystemTools::FileIsFullPath(path) ? "<absolute>" : "SOURCE_ROOT"; fileRef->AddAttribute("name", this->CreateString(name)); fileRef->AddAttribute("path", this->CreateString(path)); fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree)); @@ -868,7 +1034,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference( { std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf); - return this->CreateXCodeFileReferenceFromPath(sf->GetFullPath(), target, + return this->CreateXCodeFileReferenceFromPath(sf->ResolveFullPath(), target, lang, sf); } @@ -895,7 +1061,7 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen) this->CurrentConfigurationTypes.clear(); this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes); if (this->CurrentConfigurationTypes.empty()) { - this->CurrentConfigurationTypes.push_back(""); + this->CurrentConfigurationTypes.emplace_back(); } } @@ -903,21 +1069,23 @@ struct cmSourceFilePathCompare { bool operator()(cmSourceFile* l, cmSourceFile* r) { - return l->GetFullPath() < r->GetFullPath(); + return l->ResolveFullPath() < r->ResolveFullPath(); } }; struct cmCompareTargets { - bool operator()(std::string const& a, std::string const& b) const + bool operator()(cmXCodeObject* l, cmXCodeObject* r) const { + std::string const& a = l->GetTarget()->GetName(); + std::string const& b = r->GetTarget()->GetName(); if (a == "ALL_BUILD") { return true; } if (b == "ALL_BUILD") { return false; } - return strcmp(a.c_str(), b.c_str()) < 0; + return a < b; } }; @@ -925,298 +1093,282 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - std::vector<cmGeneratorTarget*> tgts = + std::vector<cmGeneratorTarget*> gts = this->CurrentLocalGenerator->GetGeneratorTargets(); - typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets> - cmSortedTargets; - cmSortedTargets sortedTargets; - for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); - l != tgts.end(); l++) { - sortedTargets[(*l)->GetName()] = *l; + std::sort(gts.begin(), gts.end(), + [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { + return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; + }); + for (auto gtgt : gts) { + if (!this->CreateXCodeTarget(gtgt, targets)) { + return false; + } } - for (cmSortedTargets::iterator l = sortedTargets.begin(); - l != sortedTargets.end(); l++) { - cmGeneratorTarget* gtgt = l->second; - - std::string targetName = gtgt->GetName(); + std::sort(targets.begin(), targets.end(), cmCompareTargets()); + return true; +} - // make sure ALL_BUILD, INSTALL, etc are only done once - if (this->SpecialTargetEmitted(targetName)) { - continue; - } +bool cmGlobalXCodeGenerator::CreateXCodeTarget( + cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets) +{ + std::string targetName = gtgt->GetName(); - if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - continue; - } + // make sure ALL_BUILD, INSTALL, etc are only done once + if (this->SpecialTargetEmitted(targetName)) { + return true; + } - if (gtgt->GetType() == cmStateEnums::UTILITY || - gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { - cmXCodeObject* t = this->CreateUtilityTarget(gtgt); - if (!t) { - return false; - } - targets.push_back(t); - continue; - } + if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { + return true; + } - // organize the sources - std::vector<cmSourceFile*> classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { + if (gtgt->GetType() == cmStateEnums::UTILITY || + gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { + cmXCodeObject* t = this->CreateUtilityTarget(gtgt); + if (!t) { return false; } - std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); + targets.push_back(t); + return true; + } - gtgt->ComputeObjectMapping(); + // organize the sources + std::vector<cmSourceFile*> classes; + if (!gtgt->GetConfigCommonSourceFiles(classes)) { + return false; + } - std::vector<cmXCodeObject*> externalObjFiles; - std::vector<cmXCodeObject*> headerFiles; - std::vector<cmXCodeObject*> resourceFiles; - std::vector<cmXCodeObject*> sourceFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - cmXCodeObject* xsf = - this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt); - cmXCodeObject* fr = xsf->GetObject("fileRef"); - cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); + // Add CMakeLists.txt file for user convenience. + this->AddXCodeProjBuildRule(gtgt, classes); - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); + // Add the Info.plist we are about to generate for an App Bundle. + if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { + std::string plist = this->ComputeInfoPListLocation(gtgt); + cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( + plist, true, cmSourceFileLocationKind::Known); + classes.push_back(sf); + } - if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { - if ((*i)->GetObjectLibrary().empty()) { - externalObjFiles.push_back(xsf); - } - } else if (this->IsHeaderFile(*i) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePrivateHeader) || - (tsFlags.Type == - cmGeneratorTarget::SourceFileTypePublicHeader)) { - headerFiles.push_back(xsf); - } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { - resourceFiles.push_back(xsf); - } else if (!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY")) { - // 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).empty() && - !this->IgnoreFile((*i)->GetExtension().c_str())) { - sourceFiles.push_back(xsf); - } - } - } + std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); - if (this->XcodeVersion < 50) { - // Add object library contents as external objects. (Equivalent to - // the externalObjFiles above, except each one is not a cmSourceFile - // within the target.) - std::vector<cmSourceFile const*> objs; - gtgt->GetExternalObjects(objs, ""); - for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - if ((*oi)->GetObjectLibrary().empty()) { - continue; - } - std::string const& obj = (*oi)->GetFullPath(); - cmXCodeObject* xsf = - this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0); - externalObjFiles.push_back(xsf); - } - } + gtgt->ComputeObjectMapping(); - // some build phases only apply to bundles and/or frameworks - bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); - bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); - bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); + std::vector<cmXCodeObject*> externalObjFiles; + std::vector<cmXCodeObject*> headerFiles; + std::vector<cmXCodeObject*> resourceFiles; + std::vector<cmXCodeObject*> sourceFiles; + for (auto sourceFile : classes) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + cmXCodeObject* fr = xsf->GetObject("fileRef"); + cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); - cmXCodeObject* buildFiles = 0; + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); - // 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<cmXCodeObject*>::iterator i = sourceFiles.begin(); - i != sourceFiles.end(); ++i) { - buildFiles->AddObject(*i); + if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { + if (sourceFile->GetObjectLibrary().empty()) { + externalObjFiles.push_back(xsf); + } + } else if (this->IsHeaderFile(sourceFile) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePrivateHeader) || + (tsFlags.Type == + cmGeneratorTarget::SourceFileTypePublicHeader)) { + headerFiles.push_back(xsf); + } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { + resourceFiles.push_back(xsf); + } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY") && + !gtgt->IsSourceFilePartOfUnityBatch( + sourceFile->ResolveFullPath())) { + // 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(*sourceFile) + .empty() && + !this->IgnoreFile(sourceFile->GetExtension().c_str())) { + sourceFiles.push_back(xsf); } - 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) { - headerBuildPhase = - this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); - headerBuildPhase->SetComment("Headers"); - headerBuildPhase->AddAttribute("buildActionMask", + // some build phases only apply to bundles and/or frameworks + bool isFrameworkTarget = gtgt->IsFrameworkOnApple(); + bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE"); + bool isCFBundleTarget = gtgt->IsCFBundleOnApple(); + + cmXCodeObject* buildFiles = nullptr; + + // create source build phase + cmXCodeObject* sourceBuildPhase = nullptr; + if (!sourceFiles.empty()) { + sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase); + sourceBuildPhase->SetComment("Sources"); + sourceBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& sourceFile : sourceFiles) { + buildFiles->AddObject(sourceFile); + } + sourceBuildPhase->AddAttribute("files", buildFiles); + sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create header build phase - only for framework targets + cmXCodeObject* headerBuildPhase = nullptr; + if (!headerFiles.empty() && isFrameworkTarget) { + headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase); + headerBuildPhase->SetComment("Headers"); + headerBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& headerFile : headerFiles) { + buildFiles->AddObject(headerFile); + } + headerBuildPhase->AddAttribute("files", buildFiles); + headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } + + // create resource build phase - only for framework or bundle targets + cmXCodeObject* resourceBuildPhase = nullptr; + if (!resourceFiles.empty() && + (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { + resourceBuildPhase = + this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); + resourceBuildPhase->SetComment("Resources"); + resourceBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (std::vector<cmXCodeObject*>::iterator i = headerFiles.begin(); - i != headerFiles.end(); ++i) { - buildFiles->AddObject(*i); - } - headerBuildPhase->AddAttribute("files", buildFiles); - headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (auto& resourceFile : resourceFiles) { + buildFiles->AddObject(resourceFile); } + resourceBuildPhase->AddAttribute("files", buildFiles); + resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - // create resource build phase - only for framework or bundle targets - cmXCodeObject* resourceBuildPhase = 0; - if (!resourceFiles.empty() && - (isFrameworkTarget || isBundleTarget || isCFBundleTarget)) { - resourceBuildPhase = - this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase); - resourceBuildPhase->SetComment("Resources"); - resourceBuildPhase->AddAttribute("buildActionMask", - this->CreateString("2147483647")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (std::vector<cmXCodeObject*>::iterator i = resourceFiles.begin(); - i != resourceFiles.end(); ++i) { - buildFiles->AddObject(*i); + // create vector of "non-resource content file" build phases - only for + // framework or bundle targets + std::vector<cmXCodeObject*> contentBuildPhases; + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + using mapOfVectorOfSourceFiles = + std::map<std::string, std::vector<cmSourceFile*>>; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } - 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<cmXCodeObject*> contentBuildPhases; - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*> > - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { - bundleFiles[tsFlags.MacFolder].push_back(*i); + } + for (auto const& keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("6")); + std::ostringstream ostr; + if (gtgt->IsFrameworkOnApple()) { + // dstPath in frameworks is relative to Versions/<version> + ostr << keySources.first; + } else if (keySources.first != "MacOS") { + if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) { + ostr << keySources.first; + } else { + // dstPath in bundles is relative to Contents/MacOS + ostr << "../" << keySources.first; } } - 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")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("6")); - std::ostringstream ostr; - if (gtgt->IsFrameworkOnApple()) { - // dstPath in frameworks is relative to Versions/<version> - ostr << mit->first; - } else if (mit->first != "MacOS") { - if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) { - ostr << mit->first; - } else { - // dstPath in bundles is relative to Contents/MacOS - ostr << "../" << mit->first; - } - } - copyFilesBuildPhase->AddAttribute("dstPath", - this->CreateString(ostr.str())); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - std::vector<cmSourceFile*>::iterator sfIt; - for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, *sfIt, gtgt); - buildFiles->AddObject(xsf); - } - contentBuildPhases.push_back(copyFilesBuildPhase); + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(ostr.str())); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); } + contentBuildPhases.push_back(copyFilesBuildPhase); } + } - // create vector of "resource content file" build phases - only for - // framework or bundle targets - if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { - typedef std::map<std::string, std::vector<cmSourceFile*> > - mapOfVectorOfSourceFiles; - mapOfVectorOfSourceFiles bundleFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); - if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { - bundleFiles[tsFlags.MacFolder].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")); - copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", - this->CreateString("7")); - copyFilesBuildPhase->AddAttribute("dstPath", - this->CreateString(mit->first)); - copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); - buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - copyFilesBuildPhase->AddAttribute("files", buildFiles); - std::vector<cmSourceFile*>::iterator sfIt; - for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) { - cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, *sfIt, gtgt); - buildFiles->AddObject(xsf); - } - contentBuildPhases.push_back(copyFilesBuildPhase); + // create vector of "resource content file" build phases - only for + // framework or bundle targets + if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) { + using mapOfVectorOfSourceFiles = + std::map<std::string, std::vector<cmSourceFile*>>; + mapOfVectorOfSourceFiles bundleFiles; + for (auto sourceFile : classes) { + cmGeneratorTarget::SourceFileFlags tsFlags = + gtgt->GetTargetSourceFileFlags(sourceFile); + if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - - // create framework build phase - cmXCodeObject* frameworkBuildPhase = 0; - if (!externalObjFiles.empty()) { - frameworkBuildPhase = - this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase); - frameworkBuildPhase->SetComment("Frameworks"); - frameworkBuildPhase->AddAttribute("buildActionMask", + for (auto const& keySources : bundleFiles) { + cmXCodeObject* copyFilesBuildPhase = + this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); + copyFilesBuildPhase->SetComment("Copy files"); + copyFilesBuildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); + copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", + this->CreateString("7")); + copyFilesBuildPhase->AddAttribute("dstPath", + this->CreateString(keySources.first)); + copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); - frameworkBuildPhase->AddAttribute("files", buildFiles); - for (std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin(); - i != externalObjFiles.end(); ++i) { - buildFiles->AddObject(*i); + copyFilesBuildPhase->AddAttribute("files", buildFiles); + for (auto sourceFile : keySources.second) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); + buildFiles->AddObject(xsf); } - frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", - this->CreateString("0")); + contentBuildPhases.push_back(copyFilesBuildPhase); } + } - // create list of build phases and create the Xcode target - cmXCodeObject* buildPhases = - this->CreateObject(cmXCodeObject::OBJECT_LIST); + // create framework build phase + cmXCodeObject* frameworkBuildPhase = nullptr; + if (!externalObjFiles.empty()) { + 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 (auto& externalObjFile : externalObjFiles) { + buildFiles->AddObject(externalObjFile); + } + frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + } - this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, - resourceBuildPhase, contentBuildPhases, - frameworkBuildPhase, gtgt); + // create list of build phases and create the Xcode target + cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); - targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); - } + this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase, + resourceBuildPhase, contentBuildPhases, + frameworkBuildPhase, gtgt); + + targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases)); return true; } void cmGlobalXCodeGenerator::ForceLinkerLanguages() { - for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) { - std::vector<cmGeneratorTarget*> tgts = - this->LocalGenerators[i]->GetGeneratorTargets(); + for (auto localGenerator : this->LocalGenerators) { // All targets depend on the build-system check target. - for (std::vector<cmGeneratorTarget*>::const_iterator ti = tgts.begin(); - ti != tgts.end(); ++ti) { + for (auto tgt : localGenerator->GetGeneratorTargets()) { // This makes sure all targets link using the proper language. - this->ForceLinkerLanguage(*ti); + this->ForceLinkerLanguage(tgt); } } } @@ -1236,10 +1388,9 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) } // If the language is compiled as a source trust Xcode to link with it. - cmLinkImplementation const* impl = gtgt->GetLinkImplementation("NOCONFIG"); - for (std::vector<std::string>::const_iterator li = impl->Languages.begin(); - li != impl->Languages.end(); ++li) { - if (*li == llang) { + for (auto const& Language : + gtgt->GetLinkImplementation("NOCONFIG")->Languages) { + if (Language == llang) { return; } } @@ -1248,15 +1399,11 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) // linker language. This should convince Xcode to choose the proper // language. cmMakefile* mf = gtgt->Target->GetMakefile(); - std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(); - fname += cmake::GetCMakeFilesDirectory(); - fname += "/"; - fname += gtgt->GetName(); - fname += "-CMakeForceLinker"; - fname += "."; - fname += cmSystemTools::LowerCase(llang); + std::string fname = cmStrCat( + gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/", + gtgt->GetName(), "-CMakeForceLinker.", cmSystemTools::LowerCase(llang)); { - cmGeneratedFileStream fout(fname.c_str()); + cmGeneratedFileStream fout(fname); fout << "\n"; } if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) { @@ -1267,18 +1414,16 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf) { - const std::vector<std::string>& hdrExts = - this->CMakeInstance->GetHeaderExtensions(); - return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) != - hdrExts.end()); + return cmContains(this->CMakeInstance->GetHeaderExtensions(), + sf->GetExtension()); } cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase( const char* name, const char* name2, cmGeneratorTarget* target, const std::vector<cmCustomCommand>& commands) { - if (commands.size() == 0 && strcmp(name, "CMake ReRun") != 0) { - return 0; + if (commands.empty() && strcmp(name, "CMake ReRun") != 0) { + return nullptr; } cmXCodeObject* buildPhase = this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase); @@ -1297,7 +1442,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase( void cmGlobalXCodeGenerator::CreateCustomCommands( cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase, cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase, - std::vector<cmXCodeObject*> contentBuildPhases, + std::vector<cmXCodeObject*> const& contentBuildPhases, cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt) { std::vector<cmCustomCommand> const& prebuild = gtgt->GetPreBuildCommands(); @@ -1306,23 +1451,14 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY && !gtgt->IsFrameworkOnApple()) { - cmCustomCommandLines cmd; - cmd.resize(1); - cmd[0].push_back(cmSystemTools::GetCMakeCommand()); - cmd[0].push_back("-E"); - cmd[0].push_back("cmake_symlink_library"); - std::string str_file = "$<TARGET_FILE:"; - str_file += gtgt->GetName(); - str_file += ">"; - std::string str_so_file = "$<TARGET_SONAME_FILE:"; - str_so_file += gtgt->GetName(); - str_so_file += ">"; - std::string str_link_file = "$<TARGET_LINKER_FILE:"; - str_link_file += gtgt->GetName(); - str_link_file += ">"; - cmd[0].push_back(str_file); - cmd[0].push_back(str_so_file); - cmd[0].push_back(str_link_file); + std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>'); + std::string str_so_file = + cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>'); + std::string str_link_file = + cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>'); + cmCustomCommandLines cmd = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library", + str_file, str_so_file, str_link_file }); cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(), std::vector<std::string>(), @@ -1338,10 +1474,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( } // add all the sources std::vector<cmCustomCommand> commands; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - if ((*i)->GetCustomCommand()) { - commands.push_back(*(*i)->GetCustomCommand()); + for (auto sourceFile : classes) { + if (sourceFile->GetCustomCommand()) { + commands.push_back(*sourceFile->GetCustomCommand()); } } // create prebuild phase @@ -1373,10 +1508,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (resourceBuildPhase) { buildPhases->AddObject(resourceBuildPhase); } - std::vector<cmXCodeObject*>::iterator cit; - for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end(); - ++cit) { - buildPhases->AddObject(*cit); + for (auto obj : contentBuildPhases) { + buildPhases->AddObject(obj); } if (sourceBuildPhase) { buildPhases->AddObject(sourceBuildPhase); @@ -1438,7 +1571,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlagRegex(const char* exp, std::string::size_type offset = 0; - while (regex.find(flags.c_str() + offset)) { + while (regex.find(&flags[offset])) { const std::string::size_type startPos = offset + regex.start(matchIndex); const std::string::size_type endPos = offset + regex.end(matchIndex); const std::string::size_type size = endPos - startPos; @@ -1465,7 +1598,7 @@ void cmGlobalXCodeGenerator::FilterConfigurationAttribute( return; } - std::string::size_type endVariant = attribute.find("]", beginVariant + 9); + std::string::size_type endVariant = attribute.find(']', beginVariant + 9); if (endVariant == std::string::npos) { // There is no terminating bracket. return; @@ -1489,32 +1622,23 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( cmXCodeObject* buildphase, cmGeneratorTarget* target, std::vector<cmCustomCommand> const& commands, const char* name) { - std::string dir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); - dir += "/CMakeScripts"; - cmSystemTools::MakeDirectory(dir.c_str()); - std::string makefile = dir; - makefile += "/"; - makefile += target->GetName(); - makefile += "_"; - makefile += name; - makefile += ".make"; - - for (std::vector<std::string>::const_iterator currentConfig = - this->CurrentConfigurationTypes.begin(); - currentConfig != this->CurrentConfigurationTypes.end(); - currentConfig++) { + std::string dir = cmStrCat( + this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), "/CMakeScripts"); + cmSystemTools::MakeDirectory(dir); + std::string makefile = + cmStrCat(dir, '/', target->GetName(), '_', name, ".make"); + + for (const auto& currentConfig : this->CurrentConfigurationTypes) { this->CreateCustomRulesMakefile(makefile.c_str(), target, commands, - *currentConfig); + currentConfig); } std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); - cdir = this->ConvertToRelativeForMake(cdir.c_str()); - std::string makecmd = "make -C "; - makecmd += cdir; - makecmd += " -f "; - makecmd += - this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str()); - makecmd += " all"; + cdir = this->ConvertToRelativeForMake(cdir); + std::string makecmd = + cmStrCat("make -C ", cdir, " -f ", + this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")), + " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\") all"); buildphase->AddAttribute("shellScript", this->CreateString(makecmd)); buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); } @@ -1523,9 +1647,8 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( const char* makefileBasename, cmGeneratorTarget* target, std::vector<cmCustomCommand> const& commands, const std::string& configName) { - std::string makefileName = makefileBasename; - makefileName += configName; - cmGeneratedFileStream makefileStream(makefileName.c_str()); + std::string makefileName = cmStrCat(makefileBasename, configName); + cmGeneratedFileStream makefileStream(makefileName); if (!makefileStream) { return; } @@ -1541,38 +1664,35 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( makefileStream << "all: "; std::map<const cmCustomCommand*, std::string> tname; int count = 0; - for (std::vector<cmCustomCommand>::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator); + for (auto const& command : commands) { + cmCustomCommandGenerator ccg(command, configName, + this->CurrentLocalGenerator); if (ccg.GetNumberOfCommands() > 0) { const std::vector<std::string>& outputs = ccg.GetOutputs(); if (!outputs.empty()) { - for (std::vector<std::string>::const_iterator o = outputs.begin(); - o != outputs.end(); ++o) { - makefileStream << "\\\n\t" - << this->ConvertToRelativeForMake(o->c_str()); + for (auto const& output : outputs) { + makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output); } } else { std::ostringstream str; str << "_buildpart_" << count++; - tname[&ccg.GetCC()] = std::string(target->GetName()) + str.str(); + tname[&ccg.GetCC()] = target->GetName() + str.str(); makefileStream << "\\\n\t" << tname[&ccg.GetCC()]; } } } makefileStream << "\n\n"; - for (std::vector<cmCustomCommand>::const_iterator i = commands.begin(); - i != commands.end(); ++i) { - cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator); + for (auto const& command : commands) { + cmCustomCommandGenerator ccg(command, configName, + this->CurrentLocalGenerator); if (ccg.GetNumberOfCommands() > 0) { makefileStream << "\n"; const std::vector<std::string>& outputs = ccg.GetOutputs(); if (!outputs.empty()) { // There is at least one output, start the rule for it const char* sep = ""; - for (std::vector<std::string>::const_iterator oi = outputs.begin(); - oi != outputs.end(); ++oi) { - makefileStream << sep << this->ConvertToRelativeForMake(oi->c_str()); + for (auto const& output : outputs) { + makefileStream << sep << this->ConvertToRelativeForMake(output); sep = " "; } makefileStream << ": "; @@ -1580,22 +1700,20 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( // There are no outputs. Use the generated force rule name. makefileStream << tname[&ccg.GetCC()] << ": "; } - for (std::vector<std::string>::const_iterator d = - ccg.GetDepends().begin(); - d != ccg.GetDepends().end(); ++d) { + for (auto const& d : ccg.GetDepends()) { std::string dep; - if (this->CurrentLocalGenerator->GetRealDependency(*d, configName, + if (this->CurrentLocalGenerator->GetRealDependency(d, configName, dep)) { - makefileStream << "\\\n" - << this->ConvertToRelativeForMake(dep.c_str()); + makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep); } } makefileStream << "\n"; if (const char* comment = ccg.GetComment()) { - std::string echo_cmd = "echo "; - echo_cmd += (this->CurrentLocalGenerator->EscapeForShell( - comment, ccg.GetCC().GetEscapeAllowMakeVars())); + std::string echo_cmd = + cmStrCat("echo ", + (this->CurrentLocalGenerator->EscapeForShell( + comment, ccg.GetCC().GetEscapeAllowMakeVars()))); makefileStream << "\t" << echo_cmd << "\n"; } @@ -1604,12 +1722,12 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( // Build the command line in a single string. std::string cmd2 = ccg.GetCommand(c); cmSystemTools::ReplaceString(cmd2, "/./", "/"); - cmd2 = this->ConvertToRelativeForMake(cmd2.c_str()); + cmd2 = this->ConvertToRelativeForMake(cmd2); std::string cmd; std::string wd = ccg.GetWorkingDirectory(); if (!wd.empty()) { cmd += "cd "; - cmd += this->ConvertToRelativeForMake(wd.c_str()); + cmd += this->ConvertToRelativeForMake(wd); cmd += " && "; } cmd += cmd2; @@ -1620,6 +1738,25 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile( } } +void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute( + cmGeneratorTarget* target, cmXCodeObject* buildSettings, + const std::string& configName) +{ + // For now, only EXECUTABLE is concerned + if (target->GetType() != cmStateEnums::EXECUTABLE) { + return; + } + + const char* PICValue = target->GetLinkPIEProperty(configName); + if (PICValue == nullptr) { + // POSITION_INDEPENDENT_CODE is not set + return; + } + + buildSettings->AddAttribute( + "LD_NO_PIE", this->CreateString(cmIsOn(PICValue) ? "NO" : "YES")); +} + void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, cmXCodeObject* buildSettings, const std::string& configName) @@ -1639,15 +1776,17 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::set<std::string> languages; gtgt->GetLanguages(languages, configName); std::map<std::string, std::string> cflags; - for (std::set<std::string>::iterator li = languages.begin(); - li != languages.end(); ++li) { - std::string const& lang = *li; + for (auto const& lang : languages) { std::string& flags = cflags[lang]; // Add language-specific flags. this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang, configName); + if (gtgt->IsIPOEnabled(lang, configName)) { + this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); + } + // Add shared-library flags if needed. this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang, configName); @@ -1661,10 +1800,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string llang = gtgt->GetLinkerLanguage(configName); if (binary && llang.empty()) { cmSystemTools::Error( - "CMake can not determine linker language for target: ", - gtgt->GetName().c_str()); + "CMake can not determine linker language for target: " + + gtgt->GetName()); return; } + std::string const& langForPreprocessor = llang; if (gtgt->IsIPOEnabled(llang, configName)) { const char* ltoValue = @@ -1672,6 +1812,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue)); } + // Handle PIE linker configuration + this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName); + // Add define flags this->CurrentLocalGenerator->AppendFlags( defFlags, this->CurrentMakefile->GetDefineFlags()); @@ -1680,12 +1823,15 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, BuildObjectListOrString ppDefs(this, true); this->AppendDefines( ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\""); - if (const char* exportMacro = gtgt->GetExportMacro()) { + if (const std::string* exportMacro = gtgt->GetExportMacro()) { // Add the export symbol definition for shared library objects. - this->AppendDefines(ppDefs, exportMacro); + this->AppendDefines(ppDefs, exportMacro->c_str()); } std::vector<std::string> targetDefines; - gtgt->GetCompileDefinitions(targetDefines, configName, "C"); + if (!langForPreprocessor.empty()) { + gtgt->GetCompileDefinitions(targetDefines, configName, + langForPreprocessor); + } this->AppendDefines(ppDefs, targetDefines); buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); @@ -1707,7 +1853,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY || gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) { this->CurrentLocalGenerator->GetStaticLibraryFlags( - extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt); + extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt); } else { const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS"); if (targetLinkFlags) { @@ -1715,12 +1861,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, targetLinkFlags); } if (!configName.empty()) { - std::string linkFlagsVar = "LINK_FLAGS_"; - linkFlagsVar += cmSystemTools::UpperCase(configName); + std::string linkFlagsVar = + cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName)); if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) { this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags); } } + std::vector<std::string> opts; + gtgt->GetLinkOptions(opts, configName, llang); + // LINK_OPTIONS are escaped. + this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts); } // Set target-specific architectures. @@ -1737,9 +1887,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, } else { cmXCodeObject* archObjects = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (std::vector<std::string>::iterator i = archs.begin(); - i != archs.end(); i++) { - archObjects->AddObject(this->CreateString(*i)); + for (auto& arch : archs) { + archObjects->AddObject(this->CreateString(arch)); } buildSettings->AddAttribute("ARCHS", archObjects); } @@ -1754,8 +1903,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, const char* version = gtgt->GetProperty("VERSION"); const char* soversion = gtgt->GetProperty("SOVERSION"); if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) { - version = 0; - soversion = 0; + version = nullptr; + soversion = nullptr; } if (version && !soversion) { soversion = version; @@ -1799,8 +1948,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, pnbase = gtgt->GetName(); pnsuffix = ".a"; - std::string pncdir = - this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt); + std::string pncdir = this->GetObjectsDirectory( + this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR); buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", this->CreateString(pncdir)); } @@ -1827,7 +1976,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // so let it replace the framework name. This avoids creating // a per-configuration Info.plist file. this->CurrentLocalGenerator->GenerateFrameworkInfoPList( - gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); + gtgt, "$(EXECUTABLE_NAME)", plist); buildSettings->AddAttribute("INFOPLIST_FILE", this->CreateString(plist)); buildSettings->AddAttribute("MACH_O_TYPE", @@ -1868,7 +2017,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // a per-configuration Info.plist file. The cfbundle plist // is very similar to the application bundle plist this->CurrentLocalGenerator->GenerateAppleInfoPList( - gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); + gtgt, "$(EXECUTABLE_NAME)", plist); buildSettings->AddAttribute("INFOPLIST_FILE", this->CreateString(plist)); } else { @@ -1902,7 +2051,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // so let it replace the framework name. This avoids creating // a per-configuration Info.plist file. this->CurrentLocalGenerator->GenerateFrameworkInfoPList( - gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); + gtgt, "$(EXECUTABLE_NAME)", plist); buildSettings->AddAttribute("INFOPLIST_FILE", this->CreateString(plist)); } else { @@ -1940,7 +2089,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // so let it replace the executable name. This avoids creating // a per-configuration Info.plist file. this->CurrentLocalGenerator->GenerateAppleInfoPList( - gtgt, "$(EXECUTABLE_NAME)", plist.c_str()); + gtgt, "$(EXECUTABLE_NAME)", plist); buildSettings->AddAttribute("INFOPLIST_FILE", this->CreateString(plist)); } @@ -1948,9 +2097,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, default: break; } - if (this->XcodeVersion < 40) { - buildSettings->AddAttribute("PREBINDING", this->CreateString("NO")); - } BuildObjectListOrString dirs(this, true); BuildObjectListOrString fdirs(this, true); @@ -1959,30 +2105,32 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, const bool emitSystemIncludes = this->XcodeVersion >= 83; std::vector<std::string> includes; - this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C", - configName); + if (!langForPreprocessor.empty()) { + this->CurrentLocalGenerator->GetIncludeDirectories( + includes, gtgt, langForPreprocessor, configName); + } std::set<std::string> emitted; emitted.insert("/System/Library/Frameworks"); - for (std::vector<std::string>::iterator i = includes.begin(); - i != includes.end(); ++i) { - if (this->NameResolvesToFramework(*i)) { - std::string frameworkDir = *i; - frameworkDir += "/../"; + for (auto& include : includes) { + if (this->NameResolvesToFramework(include)) { + std::string frameworkDir = cmStrCat(include, "/../"); frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir); if (emitted.insert(frameworkDir).second) { std::string incpath = this->XCodeEscapePath(frameworkDir); if (emitSystemIncludes && - gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) { + gtgt->IsSystemIncludeDirectory(frameworkDir, configName, + langForPreprocessor)) { sysfdirs.Add(incpath); } else { fdirs.Add(incpath); } } } else { - std::string incpath = this->XCodeEscapePath(*i); + std::string incpath = this->XCodeEscapePath(include); if (emitSystemIncludes && - gtgt->IsSystemIncludeDirectory(*i, configName)) { + gtgt->IsSystemIncludeDirectory(include, configName, + langForPreprocessor)) { sysdirs.Add(incpath); } else { dirs.Add(incpath); @@ -1991,13 +2139,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, } // Add framework search paths needed for linking. if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) { - std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths(); - for (std::vector<std::string>::const_iterator fdi = fwDirs.begin(); - fdi != fwDirs.end(); ++fdi) { - if (emitted.insert(*fdi).second) { - std::string incpath = this->XCodeEscapePath(*fdi); + for (auto const& fwDir : cli->GetFrameworkPaths()) { + if (emitted.insert(fwDir).second) { + std::string incpath = this->XCodeEscapePath(fwDir); if (emitSystemIncludes && - gtgt->IsSystemIncludeDirectory(*fdi, configName)) { + gtgt->IsSystemIncludeDirectory(fwDir, configName, + langForPreprocessor)) { sysfdirs.Add(incpath); } else { fdirs.Add(incpath); @@ -2025,27 +2172,25 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // system include directory awareness. We need to also keep on setting // HEADER_SEARCH_PATHS to work around a missing compile options flag for // GNU assembly files (#16449) - for (std::set<std::string>::iterator li = languages.begin(); - li != languages.end(); ++li) { + for (auto const& language : languages) { std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags( - includes, gtgt, *li, true, false, configName); + includes, gtgt, language, true, false, configName); if (!includeFlags.empty()) { - cflags[*li] += " " + includeFlags; + cflags[language] += " " + includeFlags; } } } bool same_gflags = true; std::map<std::string, std::string> gflags; - std::string const* last_gflag = 0; + std::string const* last_gflag = nullptr; std::string optLevel = "0"; // Minimal map of flags to build settings. - for (std::set<std::string>::iterator li = languages.begin(); - li != languages.end(); ++li) { - std::string& flags = cflags[*li]; - std::string& gflag = gflags[*li]; + for (auto const& language : languages) { + std::string& flags = cflags[language]; + std::string& gflag = gflags[language]; std::string oflag = this->ExtractFlagRegex("(^| )(-Ofast|-Os|-O[0-9]*)( |$)", 2, flags); if (oflag.size() == 2) { @@ -2070,16 +2215,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, if (!same_gflags) { // We can't set the Xcode flag differently depending on the language, // so put them back in this case. - for (std::set<std::string>::iterator li = languages.begin(); - li != languages.end(); ++li) { - cflags[*li] += " "; - cflags[*li] += gflags[*li]; + for (auto const& language : languages) { + cflags[language] += " "; + cflags[language] += gflags[language]; } debugStr = "NO"; } else if (last_gflag && (last_gflag->empty() || *last_gflag == "-g0")) { debugStr = "NO"; } + // extract C++ stdlib + for (auto const& language : languages) { + if (language != "CXX" && language != "OBJCXX") { + continue; + } + std::string& flags = cflags[language]; + + auto stdlib = + this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags); + if (stdlib.size() > 8) { + const auto cxxLibrary = stdlib.substr(8); + if (language == "CXX" || + !buildSettings->GetObject("CLANG_CXX_LIBRARY")) { + buildSettings->AddAttribute("CLANG_CXX_LIBRARY", + this->CreateString(cxxLibrary)); + } + } + } + buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES", this->CreateString("YES")); buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS", @@ -2090,25 +2253,30 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CreateString("NO")); buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN", this->CreateString("NO")); - for (std::set<std::string>::iterator li = languages.begin(); - li != languages.end(); ++li) { - std::string flags = cflags[*li] + " " + defFlags; - if (*li == "CXX") { - buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS", - this->CreateString(flags)); - } else if (*li == "Fortran") { + + for (auto const& language : languages) { + std::string flags = cflags[language] + " " + defFlags; + if (language == "CXX" || language == "OBJCXX") { + if (language == "CXX" || + !buildSettings->GetObject("OTHER_CPLUSPLUSFLAGS")) { + buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS", + this->CreateString(flags)); + } + } else if (language == "Fortran") { buildSettings->AddAttribute("IFORT_OTHER_FLAGS", this->CreateString(flags)); - } else if (*li == "C") { - buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags)); - } else if (*li == "Swift") { + } else if (language == "C" || language == "OBJC") { + if (language == "C" || !buildSettings->GetObject("OTHER_CFLAGS")) { + buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags)); + } + } else if (language == "Swift") { buildSettings->AddAttribute("OTHER_SWIFT_FLAGS", this->CreateString(flags)); } } // Add Fortran source format attribute if property is set. - const char* format = 0; + const char* format = nullptr; const char* tgtfmt = gtgt->GetProperty("Fortran_FORMAT"); switch (cmOutputConverter::GetFortranFormat(tgtfmt)) { case cmOutputConverter::FortranFormatFixed: @@ -2162,9 +2330,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // runpath dirs needs to be unique to prevent corruption std::set<std::string> unique_dirs; - for (std::vector<std::string>::const_iterator i = runtimeDirs.begin(); - i != runtimeDirs.end(); ++i) { - std::string runpath = *i; + for (auto runpath : runtimeDirs) { runpath = this->ExpandCFGIntDir(runpath, configName); if (unique_dirs.find(runpath) == unique_dirs.end()) { @@ -2221,20 +2387,26 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION", this->CreateString(vso.str())); } + + // Precompile Headers + std::string pchHeader = gtgt->GetPchHeader(configName, llang); + if (!pchHeader.empty()) { + buildSettings->AddAttribute("GCC_PREFIX_HEADER", + this->CreateString(pchHeader)); + buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER", + this->CreateString("YES")); + } + // put this last so it can override existing settings // Convert "XCODE_ATTRIBUTE_*" properties directly. { - std::vector<std::string> const& props = gtgt->GetPropertyKeys(); - for (std::vector<std::string>::const_iterator i = props.begin(); - i != props.end(); ++i) { - if (i->find("XCODE_ATTRIBUTE_") == 0) { - std::string attribute = i->substr(16); + for (auto const& prop : gtgt->GetPropertyKeys()) { + if (prop.find("XCODE_ATTRIBUTE_") == 0) { + std::string attribute = prop.substr(16); this->FilterConfigurationAttribute(configName, attribute); if (!attribute.empty()) { - cmGeneratorExpression ge; - std::string processed = - ge.Parse(gtgt->GetProperty(*i)) - ->Evaluate(this->CurrentLocalGenerator, configName); + std::string processed = cmGeneratorExpression::Evaluate( + gtgt->GetProperty(prop), this->CurrentLocalGenerator, configName); buildSettings->AddAttribute(attribute, this->CreateString(processed)); } @@ -2268,8 +2440,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( target->SetComment(gtgt->GetName()); cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST); std::vector<cmXCodeObject*> emptyContentVector; - this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0, - gtgt); + this->CreateCustomCommands(buildPhases, nullptr, nullptr, nullptr, + emptyContentVector, nullptr, gtgt); target->AddAttribute("buildPhases", buildPhases); this->AddConfigurations(target, gtgt); cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST); @@ -2280,16 +2452,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( this->XCodeObjectMap[gtgt] = target; // Add source files without build rules for editing convenience. - if (gtgt->GetType() == cmStateEnums::UTILITY) { + if (gtgt->GetType() == cmStateEnums::UTILITY && + gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { std::vector<cmSourceFile*> sources; if (!gtgt->GetConfigCommonSourceFiles(sources)) { - return 0; + return nullptr; } - for (std::vector<cmSourceFile*>::const_iterator i = sources.begin(); - i != sources.end(); ++i) { - if (!(*i)->GetPropertyAsBool("GENERATED")) { - this->CreateXCodeFileReference(*i, gtgt); + // Add CMakeLists.txt file for user convenience. + this->AddXCodeProjBuildRule(gtgt, sources); + + for (auto sourceFile : sources) { + if (!sourceFile->GetIsGenerated()) { + this->CreateXCodeFileReference(sourceFile, gtgt); } } } @@ -2302,34 +2477,28 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target, cmGeneratorTarget* gtgt) { - std::string configTypes = - this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES"); - std::vector<std::string> configVectorIn; - std::vector<std::string> configVector; - configVectorIn.push_back(configTypes); - cmSystemTools::ExpandList(configVectorIn, configVector); + std::vector<std::string> const configVector = cmExpandedList( + this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES")); cmXCodeObject* configlist = this->CreateObject(cmXCodeObject::XCConfigurationList); cmXCodeObject* buildConfigurations = this->CreateObject(cmXCodeObject::OBJECT_LIST); configlist->AddAttribute("buildConfigurations", buildConfigurations); - std::string comment = "Build configuration list for "; - comment += cmXCodeObject::PBXTypeNames[target->GetIsA()]; - comment += " \""; - comment += gtgt->GetName(); - comment += "\""; + std::string comment = cmStrCat("Build configuration list for ", + cmXCodeObject::PBXTypeNames[target->GetIsA()], + " \"", gtgt->GetName(), '"'); configlist->SetComment(comment); target->AddAttribute("buildConfigurationList", this->CreateObjectReference(configlist)); - for (unsigned int i = 0; i < configVector.size(); ++i) { + for (auto const& i : configVector) { cmXCodeObject* config = this->CreateObject(cmXCodeObject::XCBuildConfiguration); buildConfigurations->AddObject(config); cmXCodeObject* buildSettings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); - this->CreateBuildSettings(gtgt, buildSettings, configVector[i]); - config->AddAttribute("name", this->CreateString(configVector[i])); - config->SetComment(configVector[i]); + this->CreateBuildSettings(gtgt, buildSettings, i); + config->AddAttribute("name", this->CreateString(i)); + config->SetComment(i); config->AddAttribute("buildSettings", buildSettings); } if (!configVector.empty()) { @@ -2349,9 +2518,8 @@ const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar( (target->GetType() == cmStateEnums::STATIC_LIBRARY || target->GetType() == cmStateEnums::OBJECT_LIBRARY)) { return "OTHER_LIBTOOLFLAGS"; - } else { - return "OTHER_LDFLAGS"; } + return "OTHER_LDFLAGS"; } const char* cmGlobalXCodeGenerator::GetTargetFileType( @@ -2368,12 +2536,13 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType( return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework" : "archive.ar"); case cmStateEnums::MODULE_LIBRARY: - if (target->IsXCTestOnApple()) + if (target->IsXCTestOnApple()) { return "wrapper.cfbundle"; - else if (target->IsCFBundleOnApple()) + } + if (target->IsCFBundleOnApple()) { return "wrapper.plug-in"; - else - return "compiled.mach-o.executable"; + } + return "compiled.mach-o.executable"; case cmStateEnums::SHARED_LIBRARY: return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework" @@ -2383,7 +2552,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType( default: break; } - return 0; + return nullptr; } const char* cmGlobalXCodeGenerator::GetTargetProductType( @@ -2401,12 +2570,13 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType( ? "com.apple.product-type.framework" : "com.apple.product-type.library.static"); case cmStateEnums::MODULE_LIBRARY: - if (target->IsXCTestOnApple()) + if (target->IsXCTestOnApple()) { return "com.apple.product-type.bundle.unit-test"; - else if (target->IsCFBundleOnApple()) + } else if (target->IsCFBundleOnApple()) { return "com.apple.product-type.bundle"; - else + } else { return "com.apple.product-type.tool"; + } case cmStateEnums::SHARED_LIBRARY: return (target->GetPropertyAsBool("FRAMEWORK") ? "com.apple.product-type.framework" @@ -2418,14 +2588,14 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType( default: break; } - return 0; + return nullptr; } cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases) { if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { - return 0; + return nullptr; } cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget); target->AddAttribute("buildPhases", buildPhases); @@ -2444,9 +2614,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget( } std::string fullName; if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { - fullName = "lib"; - fullName += gtgt->GetName(); - fullName += ".a"; + fullName = cmStrCat("lib", gtgt->GetName(), ".a"); } else { fullName = gtgt->GetFullName(defConfig); } @@ -2469,13 +2637,12 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget( cmGeneratorTarget const* t) { if (!t) { - return 0; + return nullptr; } - std::map<cmGeneratorTarget const*, cmXCodeObject*>::const_iterator const i = - this->XCodeObjectMap.find(t); + auto const i = this->XCodeObjectMap.find(t); if (i == this->XCodeObjectMap.end()) { - return 0; + return nullptr; } return i->second; } @@ -2483,8 +2650,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget( std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, const std::string& id) { - std::string guidStoreName = name; - guidStoreName += "_GUID_CMAKE"; + std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); const char* storedGUID = this->CMakeInstance->GetCacheDefinition(guidStoreName); @@ -2539,9 +2705,7 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings, if (!attr) { settings->AddAttribute(attribute, this->CreateString(value)); } else { - std::string oldValue = attr->GetString(); - oldValue += " "; - oldValue += value; + std::string oldValue = cmStrCat(attr->GetString(), ' ', value); attr->SetString(oldValue); } } @@ -2557,18 +2721,10 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( target->GetObject("buildConfigurationList")->GetObject(); cmXCodeObject* buildConfigs = configurationList->GetObject("buildConfigurations"); - std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList(); - // each configuration and the target itself has a buildSettings in it - // list.push_back(target); - for (std::vector<cmXCodeObject*>::iterator i = list.begin(); i != list.end(); - ++i) { - if (!configName.empty()) { - if ((*i)->GetObject("name")->GetString() == configName) { - cmXCodeObject* settings = (*i)->GetObject("buildSettings"); - this->AppendOrAddBuildSetting(settings, attribute, value); - } - } else { - cmXCodeObject* settings = (*i)->GetObject("buildSettings"); + for (auto obj : buildConfigs->GetObjectList()) { + if (configName.empty() || + obj->GetObject("name")->GetString() == configName) { + cmXCodeObject* settings = obj->GetObject("buildSettings"); this->AppendOrAddBuildSetting(settings, attribute, value); } } @@ -2586,35 +2742,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } // Add dependencies on other CMake targets. - TargetDependSet const& deps = this->GetTargetDirectDepends(gt); - for (TargetDependSet::const_iterator i = deps.begin(); i != deps.end(); - ++i) { - if (cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) { + for (const auto& dep : this->GetTargetDirectDepends(gt)) { + if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) { this->AddDependTarget(target, dptarget); } } // Loop over configuration types and set per-configuration info. - for (std::vector<std::string>::iterator i = - this->CurrentConfigurationTypes.begin(); - i != this->CurrentConfigurationTypes.end(); ++i) { - // Get the current configuration name. - std::string configName = *i; - - if (this->XcodeVersion >= 50) { + for (auto const& configName : this->CurrentConfigurationTypes) { + { // Add object library contents as link flags. std::string linkObjs; const char* sep = ""; std::vector<cmSourceFile const*> objs; gt->GetExternalObjects(objs, configName); - for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - if ((*oi)->GetObjectLibrary().empty()) { + for (auto sourceFile : objs) { + if (sourceFile->GetObjectLibrary().empty()) { continue; } linkObjs += sep; sep = " "; - linkObjs += this->XCodeEscapePath((*oi)->GetFullPath()); + linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath()); } this->AppendBuildSettingAttribute( target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName); @@ -2634,28 +2782,22 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) cmComputeLinkInformation& cli = *pcli; // Add dependencies directly on library files. - { - std::vector<std::string> const& libDeps = cli.GetDepends(); - for (std::vector<std::string>::const_iterator j = libDeps.begin(); - j != libDeps.end(); ++j) { - target->AddDependLibrary(configName, *j); - } + for (auto const& libDep : cli.GetDepends()) { + target->AddDependLibrary(configName, libDep); } // add the library search paths { - std::vector<std::string> const& libDirs = cli.GetDirectories(); std::string linkDirs; - for (std::vector<std::string>::const_iterator libDir = libDirs.begin(); - libDir != libDirs.end(); ++libDir) { - if (libDir->size() && *libDir != "/usr/lib") { + for (auto const& libDir : cli.GetDirectories()) { + if (!libDir.empty() && libDir != "/usr/lib") { // Now add the same one but append // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it: linkDirs += " "; linkDirs += this->XCodeEscapePath( - *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"); + libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)"); linkDirs += " "; - linkDirs += this->XCodeEscapePath(*libDir); + linkDirs += this->XCodeEscapePath(libDir); } } this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS", @@ -2666,20 +2808,18 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) { std::string linkLibs; const char* sep = ""; - typedef cmComputeLinkInformation::ItemVector ItemVector; - ItemVector const& libNames = cli.GetItems(); - for (ItemVector::const_iterator li = libNames.begin(); - li != libNames.end(); ++li) { + for (auto const& libName : cli.GetItems()) { linkLibs += sep; sep = " "; - if (li->IsPath) { - linkLibs += this->XCodeEscapePath(li->Value); - } else if (!li->Target || - li->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) { - linkLibs += li->Value; + if (libName.IsPath) { + linkLibs += this->XCodeEscapePath(libName.Value); + } else if (!libName.Target || + libName.Target->GetType() != + cmStateEnums::INTERFACE_LIBRARY) { + linkLibs += libName.Value; } - if (li->Target && !li->Target->IsImported()) { - target->AddDependTarget(configName, li->Target->GetName()); + if (libName.Target && !libName.Target->IsImported()) { + target->AddDependTarget(configName, libName.Target->GetName()); } } this->AppendBuildSettingAttribute( @@ -2691,17 +2831,12 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) bool cmGlobalXCodeGenerator::CreateGroups( std::vector<cmLocalGenerator*>& generators) { - for (std::vector<cmLocalGenerator*>::iterator i = generators.begin(); - i != generators.end(); ++i) { - cmMakefile* mf = (*i)->GetMakefile(); + for (auto& generator : generators) { + cmMakefile* mf = generator->GetMakefile(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); - std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets(); - for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin(); - l != tgts.end(); l++) { - cmGeneratorTarget* gtgt = *l; - + for (auto gtgt : generator->GetGeneratorTargets()) { // Same skipping logic here as in CreateXCodeTargets so that we do not - // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source + // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: // if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) { @@ -2710,34 +2845,44 @@ bool cmGlobalXCodeGenerator::CreateGroups( if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) { continue; } - - // add the soon to be generated Info.plist file as a source for a - // MACOSX_BUNDLE file - if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { - std::string plist = this->ComputeInfoPListLocation(gtgt); - mf->GetOrCreateSource(plist, true); - gtgt->AddSource(plist); + if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { + continue; } - std::vector<cmGeneratorTarget::AllConfigSource> const& sources = - gtgt->GetAllConfigSources(); + auto addSourceToGroup = [this, mf, gtgt, + &sourceGroups](std::string const& source) { + cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups); + cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); + std::string key = GetGroupMapKeyFromPath(gtgt, source); + this->GroupMap[key] = pbxgroup; + }; // Put cmSourceFile instances in proper groups: - for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si = - sources.begin(); - si != sources.end(); ++si) { - cmSourceFile const* sf = si->Source; - if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) { + for (auto const& si : gtgt->GetAllConfigSources()) { + cmSourceFile const* sf = si.Source; + if (!sf->GetObjectLibrary().empty()) { // Object library files go on the link line instead. continue; } - // Add the file to the list of sources. - std::string const& source = sf->GetFullPath(); - cmSourceGroup* sourceGroup = - mf->FindSourceGroup(source.c_str(), sourceGroups); - cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup); - std::string key = GetGroupMapKeyFromPath(gtgt, source); - this->GroupMap[key] = pbxgroup; + addSourceToGroup(sf->GetFullPath()); + } + + // Add CMakeLists.txt file for user convenience. + { + std::string listfile = + cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(), + "/CMakeLists.txt"); + cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( + listfile, false, cmSourceFileLocationKind::Known); + addSourceToGroup(sf->ResolveFullPath()); + } + + // Add the Info.plist we are about to generate for an App Bundle. + if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) { + std::string plist = this->ComputeInfoPListLocation(gtgt); + cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource( + plist, true, cmSourceFileLocationKind::Known); + addSourceToGroup(sf->ResolveFullPath()); } } } @@ -2745,19 +2890,21 @@ bool cmGlobalXCodeGenerator::CreateGroups( } cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent, - std::string name) + const std::string& name) { - cmXCodeObject* parentChildren = NULL; - if (parent) + cmXCodeObject* parentChildren = nullptr; + if (parent) { parentChildren = parent->GetObject("children"); + } cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup); cmXCodeObject* groupChildren = this->CreateObject(cmXCodeObject::OBJECT_LIST); group->AddAttribute("name", this->CreateString(name)); group->AddAttribute("children", groupChildren); group->AddAttribute("sourceTree", this->CreateString("<group>")); - if (parentChildren) + if (parentChildren) { parentChildren->AddObject(group); + } return group; } @@ -2768,25 +2915,21 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( std::string target; const std::string targetFolder = gtgt->GetEffectiveFolderName(); if (!targetFolder.empty()) { - target = targetFolder; - target += "/"; + target = cmStrCat(targetFolder, '/'); } target += gtgt->GetName(); - s = target + "/"; - s += sg->GetFullName(); - std::map<std::string, cmXCodeObject*>::iterator it = - this->GroupNameMap.find(s); + s = cmStrCat(target, '/', sg->GetFullName()); + auto it = this->GroupNameMap.find(s); if (it != this->GroupNameMap.end()) { return it->second; } it = this->TargetGroup.find(target); - cmXCodeObject* tgroup = 0; + cmXCodeObject* tgroup = nullptr; if (it != this->TargetGroup.end()) { tgroup = it->second; } else { - std::vector<std::string> tgt_folders = - cmSystemTools::tokenize(target, "/"); + std::vector<std::string> tgt_folders = cmTokenize(target, "/"); std::string curr_tgt_folder; for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size(); i++) { @@ -2811,30 +2954,26 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( // If it's the default source group (empty name) then put the source file // directly in the tgroup... // - if (std::string(sg->GetFullName()) == "") { + if (sg->GetFullName().empty()) { this->GroupNameMap[s] = tgroup; return tgroup; } // It's a recursive folder structure, let's find the real parent group - if (std::string(sg->GetFullName()) != std::string(sg->GetName())) { - std::vector<std::string> folders = - cmSystemTools::tokenize(sg->GetFullName(), "\\"); - 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<std::string, cmXCodeObject*>::iterator i_folder = - this->GroupNameMap.find(curr_folder); + if (sg->GetFullName() != sg->GetName()) { + std::string curr_folder = cmStrCat(target, '/'); + for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) { + curr_folder += folder; + auto const i_folder = this->GroupNameMap.find(curr_folder); // Create new folder if (i_folder == this->GroupNameMap.end()) { - cmXCodeObject* group = this->CreatePBXGroup(tgroup, folders[i]); + cmXCodeObject* group = this->CreatePBXGroup(tgroup, folder); this->GroupNameMap[curr_folder] = group; tgroup = group; } else { tgroup = i_folder->second; } - curr_folder = curr_folder + "\\"; + curr_folder += "\\"; } return tgroup; } @@ -2847,15 +2986,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { this->ClearXCodeObjects(); - this->RootObject = 0; - this->MainGroupChildren = 0; + this->RootObject = nullptr; + this->MainGroupChildren = nullptr; cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO")); cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST); - for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { + for (const std::string& CurrentConfigurationType : + this->CurrentConfigurationTypes) { cmXCodeObject* buildStyle = this->CreateObject(cmXCodeObject::PBXBuildStyle); - const char* name = this->CurrentConfigurationTypes[i].c_str(); + const std::string& name = CurrentConfigurationType; buildStyle->AddAttribute("name", this->CreateString(name)); buildStyle->SetComment(name); cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); @@ -2885,10 +3025,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->RootObject = this->CreateObject(cmXCodeObject::PBXProject); this->RootObject->SetComment("Project object"); - std::string project_id = "PROJECT_"; - project_id += root->GetProjectName(); + std::string project_id = cmStrCat("PROJECT_", root->GetProjectName()); this->RootObject->SetId( - this->GetOrCreateId(project_id.c_str(), this->RootObject->GetId())); + this->GetOrCreateId(project_id, this->RootObject->GetId())); group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP); this->RootObject->AddAttribute("mainGroup", @@ -2904,15 +3043,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( v << std::setfill('0') << std::setw(4) << XcodeVersion * 10; group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str())); this->RootObject->AddAttribute("attributes", group); - if (this->XcodeVersion >= 32) - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.2")); - else if (this->XcodeVersion >= 31) - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.1")); - else - this->RootObject->AddAttribute("compatibilityVersion", - this->CreateString("Xcode 3.0")); + this->RootObject->AddAttribute("compatibilityVersion", + this->CreateString("Xcode 3.2")); // Point Xcode at the top of the source tree. { std::string pdir = @@ -2924,12 +3056,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateObject(cmXCodeObject::XCConfigurationList); cmXCodeObject* buildConfigurations = this->CreateObject(cmXCodeObject::OBJECT_LIST); - typedef std::vector<std::pair<std::string, cmXCodeObject*> > Configs; + using Configs = std::vector<std::pair<std::string, cmXCodeObject*>>; Configs configs; - const char* defaultConfigName = "Debug"; - for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { - const char* name = this->CurrentConfigurationTypes[i].c_str(); - if (0 == i) { + std::string defaultConfigName; + for (const auto& name : this->CurrentConfigurationTypes) { + if (defaultConfigName.empty()) { defaultConfigName = name; } cmXCodeObject* config = @@ -2937,15 +3068,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( config->AddAttribute("name", this->CreateString(name)); configs.push_back(std::make_pair(name, config)); } - for (Configs::iterator c = configs.begin(); c != configs.end(); ++c) { - buildConfigurations->AddObject(c->second); + if (defaultConfigName.empty()) { + defaultConfigName = "Debug"; + } + for (auto& config : configs) { + buildConfigurations->AddObject(config.second); } configlist->AddAttribute("buildConfigurations", buildConfigurations); - std::string comment = "Build configuration list for PBXProject"; - comment += " \""; - comment += this->CurrentProject; - comment += "\""; + std::string comment = cmStrCat("Build configuration list for PBXProject \"", + this->CurrentProject, '"'); configlist->SetComment(comment); configlist->AddAttribute("defaultConfigurationIsVisible", this->CreateString("0")); @@ -2971,7 +3103,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( buildSettings->AddAttribute("ARCHS", this->CreateString(archs)); } if (deploymentTarget && *deploymentTarget) { - buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET", + buildSettings->AddAttribute(GetDeploymentPlatform(root->GetMakefile()), this->CreateString(deploymentTarget)); } if (!this->GeneratorToolset.empty()) { @@ -2983,6 +3115,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( if (const char* vers = this->CurrentMakefile->GetDefinition( "CMAKE_Swift_LANGUAGE_VERSION")) { swiftVersion = vers; + } else if (this->XcodeVersion >= 102) { + swiftVersion = "4.0"; } else if (this->XcodeVersion >= 83) { swiftVersion = "3.0"; } else { @@ -2992,57 +3126,48 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateString(swiftVersion)); } - std::string symroot = root->GetCurrentBinaryDirectory(); - symroot += "/build"; + std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build"); buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot)); - for (Configs::iterator i = configs.begin(); i != configs.end(); ++i) { + for (auto& config : configs) { cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings); // Put this last so it can override existing settings // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. - std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions(); - for (std::vector<std::string>::const_iterator d = vars.begin(); - d != vars.end(); ++d) { - if (d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) { - std::string attribute = d->substr(22); - this->FilterConfigurationAttribute(i->first, attribute); + for (const auto& var : this->CurrentMakefile->GetDefinitions()) { + if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) { + std::string attribute = var.substr(22); + this->FilterConfigurationAttribute(config.first, attribute); if (!attribute.empty()) { - cmGeneratorExpression ge; - std::string processed = - ge.Parse(this->CurrentMakefile->GetDefinition(*d)) - ->Evaluate(this->CurrentLocalGenerator, i->first); + std::string processed = cmGeneratorExpression::Evaluate( + this->CurrentMakefile->GetDefinition(var), + this->CurrentLocalGenerator, config.first); buildSettingsForCfg->AddAttribute(attribute, this->CreateString(processed)); } } } // store per-config buildSettings into configuration object - i->second->AddAttribute("buildSettings", buildSettingsForCfg); + config.second->AddAttribute("buildSettings", buildSettingsForCfg); } this->RootObject->AddAttribute("buildConfigurationList", this->CreateObjectReference(configlist)); std::vector<cmXCodeObject*> targets; - for (std::vector<cmLocalGenerator*>::iterator i = generators.begin(); - i != generators.end(); ++i) { - if (!this->CreateXCodeTargets(*i, targets)) { + for (auto& generator : generators) { + if (!this->CreateXCodeTargets(generator, targets)) { return false; } } // 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; + for (auto t : targets) { this->AddDependAndLinkInformation(t); } 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; + for (auto t : targets) { allTargets->AddObject(t); cmXCodeObject* productRef = t->GetObject("productReference"); if (productRef) { @@ -3053,19 +3178,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( return true; } -std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory( +std::string cmGlobalXCodeGenerator::GetObjectsDirectory( const std::string& projName, const std::string& configName, - const cmGeneratorTarget* t) const + const cmGeneratorTarget* t, const std::string& variant) const { - std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory(); - dir += "/"; - dir += projName; - dir += ".build/"; - dir += configName; - dir += "/"; - dir += t->GetName(); - dir += ".build/Objects-normal/"; - + std::string dir = cmStrCat( + t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName, + ".build/", configName, '/', t->GetName(), ".build/", variant); return dir; } @@ -3075,15 +3194,19 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES"); const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT"); if (osxArch && sysroot) { - cmSystemTools::ExpandListArgument(std::string(osxArch), - this->Architectures); + cmExpandList(std::string(osxArch), this->Architectures); } if (this->Architectures.empty()) { // With no ARCHS we use ONLY_ACTIVE_ARCH. // Look up the arch that Xcode chooses in this case. - if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) { + if (const char* arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) { this->ObjectDirArchDefault = arch; + // We expect only one arch but choose the first just in case. + std::string::size_type pos = this->ObjectDirArchDefault.find(';'); + if (pos != std::string::npos) { + this->ObjectDirArchDefault = this->ObjectDirArchDefault.substr(0, pos); + } } } @@ -3104,10 +3227,9 @@ void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf) void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( std::vector<cmXCodeObject*>& targets) { - cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile.c_str()); + cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile); if (!makefileStream) { - cmSystemTools::Error("Could not create", - this->CurrentXCodeHackMakefile.c_str()); + cmSystemTools::Error("Could not create " + this->CurrentXCodeHackMakefile); return; } makefileStream.SetCopyIfDifferent(true); @@ -3131,13 +3253,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( "# link. This forces Xcode to relink the targets from scratch. It\n" "# does not seem to check these dependencies itself.\n"; /* clang-format on */ - for (std::vector<std::string>::const_iterator ct = - this->CurrentConfigurationTypes.begin(); - ct != this->CurrentConfigurationTypes.end(); ++ct) { - std::string configName = *ct; - for (std::vector<cmXCodeObject*>::iterator i = targets.begin(); - i != targets.end(); ++i) { - cmXCodeObject* target = *i; + for (const auto& configName : this->CurrentConfigurationTypes) { + for (auto target : targets) { cmGeneratorTarget* gt = target->GetTarget(); if (gt->GetType() == cmStateEnums::EXECUTABLE || @@ -3146,7 +3263,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { // Declare an entry point for the target post-build phase. - makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct) + makefileStream << this->PostBuildMakeTarget(gt->GetName(), configName) << ":\n"; } @@ -3155,26 +3272,22 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { std::string tfull = gt->GetFullPath(configName); - std::string trel = this->ConvertToRelativeForMake(tfull.c_str()); + std::string trel = this->ConvertToRelativeForMake(tfull); // Add this target to the post-build phases of its dependencies. - std::map<std::string, cmXCodeObject::StringVec>::const_iterator y = - target->GetDependTargets().find(*ct); + auto const y = target->GetDependTargets().find(configName); if (y != target->GetDependTargets().end()) { - 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) << ": " - << trel << "\n"; + for (auto const& deptgt : y->second) { + makefileStream << this->PostBuildMakeTarget(deptgt, configName) + << ": " << trel << "\n"; } } std::vector<cmGeneratorTarget*> objlibs; gt->GetObjectLibrariesCMP0026(objlibs); - for (std::vector<cmGeneratorTarget*>::const_iterator it = - objlibs.begin(); - it != objlibs.end(); ++it) { - makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct) + for (auto objLib : objlibs) { + makefileStream << this->PostBuildMakeTarget(objLib->GetName(), + configName) << ": " << trel << "\n"; } @@ -3182,30 +3295,24 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( makefileStream << trel << ":"; // List dependencies if any exist. - std::map<std::string, cmXCodeObject::StringVec>::const_iterator x = - target->GetDependLibraries().find(*ct); + auto const x = target->GetDependLibraries().find(configName); if (x != target->GetDependLibraries().end()) { - std::vector<std::string> const& deplibs = x->second; - for (std::vector<std::string>::const_iterator d = deplibs.begin(); - d != deplibs.end(); ++d) { - std::string file = this->ConvertToRelativeForMake(d->c_str()); + for (auto const& deplib : x->second) { + std::string file = this->ConvertToRelativeForMake(deplib); makefileStream << "\\\n\t" << file; dummyRules.insert(file); } } - for (std::vector<cmGeneratorTarget*>::const_iterator it = - objlibs.begin(); - it != objlibs.end(); ++it) { + for (auto objLib : objlibs) { - const std::string objLibName = (*it)->GetName(); - std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, - configName, *it); - d += "lib"; - d += objLibName; - d += ".a"; + const std::string objLibName = objLib->GetName(); + std::string d = cmStrCat( + this->GetObjectsDirectory(this->CurrentProject, configName, objLib, + OBJECT_LIBRARY_ARTIFACT_DIR), + "lib", objLibName, ".a"); - std::string dependency = this->ConvertToRelativeForMake(d.c_str()); + std::string dependency = this->ConvertToRelativeForMake(d); makefileStream << "\\\n\t" << dependency; dummyRules.insert(dependency); } @@ -3213,23 +3320,17 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // Write the action to remove the target if it is out of date. makefileStream << "\n"; makefileStream << "\t/bin/rm -f " - << this->ConvertToRelativeForMake(tfull.c_str()) - << "\n"; + << this->ConvertToRelativeForMake(tfull) << "\n"; // if building for more than one architecture - // then remove those exectuables as well + // then remove those executables as well if (this->Architectures.size() > 1) { - std::string universal = this->GetObjectsNormalDirectory( - this->CurrentProject, configName, gt); - for (std::vector<std::string>::iterator arch = - this->Architectures.begin(); - arch != this->Architectures.end(); ++arch) { - std::string universalFile = universal; - universalFile += *arch; - universalFile += "/"; - universalFile += gt->GetFullName(configName); + std::string universal = this->GetObjectsDirectory( + this->CurrentProject, configName, gt, "$(OBJDIR)/"); + for (const auto& architecture : this->Architectures) { + std::string universalFile = cmStrCat(universal, architecture, '/', + gt->GetFullName(configName)); makefileStream << "\t/bin/rm -f " - << this->ConvertToRelativeForMake( - universalFile.c_str()) + << this->ConvertToRelativeForMake(universalFile) << "\n"; } } @@ -3241,51 +3342,33 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( makefileStream << "\n\n" << "# For each target create a dummy rule" << "so the target does not have to exist\n"; - for (std::set<std::string>::const_iterator it = dummyRules.begin(); - it != dummyRules.end(); ++it) { - makefileStream << *it << ":\n"; + for (auto const& dummyRule : dummyRules) { + makefileStream << dummyRule << ":\n"; } } void cmGlobalXCodeGenerator::OutputXCodeProject( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { - if (generators.size() == 0) { + if (generators.empty()) { return; } - // Skip local generators that are excluded from this project. - for (std::vector<cmLocalGenerator*>::iterator g = generators.begin(); - g != generators.end(); ++g) { - if (this->IsExcluded(root, *g)) { - continue; - } - } - if (!this->CreateXCodeObjects(root, generators)) { return; } - std::string xcodeDir = root->GetCurrentBinaryDirectory(); - xcodeDir += "/"; - xcodeDir += root->GetProjectName(); - xcodeDir += ".xcodeproj"; - cmSystemTools::MakeDirectory(xcodeDir.c_str()); + std::string xcodeDir = cmStrCat(root->GetCurrentBinaryDirectory(), '/', + root->GetProjectName(), ".xcodeproj"); + cmSystemTools::MakeDirectory(xcodeDir); std::string xcodeProjFile = xcodeDir + "/project.pbxproj"; - cmGeneratedFileStream fout(xcodeProjFile.c_str()); + cmGeneratedFileStream fout(xcodeProjFile); fout.SetCopyIfDifferent(true); if (!fout) { return; } this->WriteXCodePBXProj(fout, root, generators); - // Since the lowest available Xcode version for testing was 7.0, - // I'm setting this as a limit then - if (this->XcodeVersion >= 70) { - if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || - root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) { - this->OutputXCodeSharedSchemes(xcodeDir); - this->OutputXCodeWorkspaceSettings(xcodeDir); - } - } + bool hasGeneratedSchemes = this->OutputXCodeSharedSchemes(xcodeDir, root); + this->OutputXCodeWorkspaceSettings(xcodeDir, hasGeneratedSchemes); this->ClearXCodeObjects(); @@ -3295,35 +3378,67 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( root->GetBinaryDirectory()); } -void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( - const std::string& xcProjDir) +bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( + const std::string& xcProjDir, cmLocalGenerator* root) { - for (std::vector<cmXCodeObject*>::const_iterator i = - this->XCodeObjects.begin(); - i != this->XCodeObjects.end(); ++i) { - cmXCodeObject* obj = *i; - if (obj->GetType() == cmXCodeObject::OBJECT && - (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || - obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { - cmXCodeScheme schm(obj, this->CurrentConfigurationTypes, - this->XcodeVersion); - schm.WriteXCodeSharedScheme(xcProjDir, - this->RelativeToSource(xcProjDir.c_str())); + // collect all tests for the targets + std::map<std::string, cmXCodeScheme::TestObjects> testables; + + for (auto obj : this->XCodeObjects) { + if (obj->GetType() != cmXCodeObject::OBJECT || + obj->GetIsA() != cmXCodeObject::PBXNativeTarget) { + continue; + } + + if (!obj->GetTarget()->IsXCTestOnApple()) { + continue; + } + + const char* testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE"); + if (!testee) { + continue; + } + + testables[testee].push_back(obj); + } + + // generate scheme + bool ret = false; + + // Since the lowest available Xcode version for testing was 6.4, + // I'm setting this as a limit then + if (this->XcodeVersion >= 64) { + for (auto obj : this->XCodeObjects) { + if (obj->GetType() == cmXCodeObject::OBJECT && + (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || + obj->GetIsA() == cmXCodeObject::PBXAggregateTarget) && + (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || + obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) { + const std::string& targetName = obj->GetTarget()->GetName(); + cmXCodeScheme schm(obj, testables[targetName], + this->CurrentConfigurationTypes, + this->XcodeVersion); + schm.WriteXCodeSharedScheme(xcProjDir, + this->RelativeToSource(xcProjDir)); + ret = true; + } } } + + return ret; } void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( - const std::string& xcProjDir) + const std::string& xcProjDir, bool hasGeneratedSchemes) { - std::string xcodeSharedDataDir = xcProjDir; - xcodeSharedDataDir += "/project.xcworkspace/xcshareddata"; + std::string xcodeSharedDataDir = + cmStrCat(xcProjDir, "/project.xcworkspace/xcshareddata"); cmSystemTools::MakeDirectory(xcodeSharedDataDir); - std::string workspaceSettingsFile = xcodeSharedDataDir; - workspaceSettingsFile += "/WorkspaceSettings.xcsettings"; + std::string workspaceSettingsFile = + cmStrCat(xcodeSharedDataDir, "/WorkspaceSettings.xcsettings"); - cmGeneratedFileStream fout(workspaceSettingsFile.c_str()); + cmGeneratedFileStream fout(workspaceSettingsFile); fout.SetCopyIfDifferent(true); if (!fout) { return; @@ -3336,8 +3451,15 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( xout.StartElement("plist"); xout.Attribute("version", "1.0"); xout.StartElement("dict"); - xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded"); - xout.Element("false"); + if (this->XcodeVersion >= 100) { + xout.Element("key", "BuildSystemType"); + xout.Element("string", "Original"); + } + if (hasGeneratedSchemes) { + xout.Element("key", + "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded"); + xout.Element("false"); + } xout.EndElement(); // dict xout.EndElement(); // plist xout.EndDocument(); @@ -3358,12 +3480,7 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout, cmXCodeObject::Indent(1, fout); fout << "};\n"; cmXCodeObject::Indent(1, fout); - if (this->XcodeVersion >= 32) - fout << "objectVersion = 46;\n"; - else if (this->XcodeVersion >= 31) - fout << "objectVersion = 45;\n"; - else - fout << "objectVersion = 44;\n"; + fout << "objectVersion = 46;\n"; cmXCode21Object::PrintList(this->XCodeObjects, fout); cmXCodeObject::Indent(1, fout); fout << "rootObject = " << this->RootObject->GetId() @@ -3402,31 +3519,30 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry) entry.Brief = "Generate Xcode project files."; } -std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p) +std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake( + std::string const& p) { return cmSystemTools::ConvertToOutputPath(p); } -std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p) +std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p) { // We force conversion because Xcode breakpoints do not work unless // they are in a file named relative to the source tree. - return cmOutputConverter::ForceToRelativePath( + return cmSystemTools::ForceToRelativePath( cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p); } -std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p) +std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p) { - return this->CurrentLocalGenerator->ConvertToRelativePath( + return this->CurrentLocalGenerator->MaybeConvertToRelativePath( cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p); } std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p) { if (p.find(' ') != std::string::npos) { - std::string t = "\""; - t += p; - t += "\""; + std::string t = cmStrCat('"', p, '"'); return t; } return p; @@ -3448,9 +3564,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags( const std::string& varNameSuffix, const std::string& default_flags) { if (!varNameLang.empty()) { - std::string varName = varNamePrefix; - varName += varNameLang; - varName += varNameSuffix; + std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix); if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) { if (*varValue) { return varValue; @@ -3470,8 +3584,7 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs, } // Expand the list of definitions. - std::vector<std::string> defines; - cmSystemTools::ExpandListArgument(defines_list, defines); + std::vector<std::string> defines = cmExpandedList(defines_list); // Store the definitions in the string. this->AppendDefines(defs, defines, dflag); @@ -3483,11 +3596,9 @@ void cmGlobalXCodeGenerator::AppendDefines( { // GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions. std::string def; - for (std::vector<std::string>::const_iterator di = defines.begin(); - di != defines.end(); ++di) { + for (auto const& define : defines) { // Start with -D if requested. - def = dflag ? "-D" : ""; - def += *di; + def = cmStrCat(dflag ? "-D" : "", define); // Append the flag with needed escapes. std::string tmp; @@ -3497,7 +3608,7 @@ void cmGlobalXCodeGenerator::AppendDefines( } void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, - std::string const& flag) + std::string const& flag) const { // Short-circuit for an empty flag. if (flag.empty()) { @@ -3529,17 +3640,13 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, } // Flag value with escaped quotes and backslashes. - for (const char* c = flag.c_str(); *c; ++c) { - if (*c == '\'') { - if (this->XcodeVersion >= 40) { - flags += "'\\''"; - } else { - flags += "\\'"; - } - } else if (*c == '\\') { + for (auto c : flag) { + if (c == '\'') { + flags += "'\\''"; + } else if (c == '\\') { flags += "\\\\"; } else { - flags += *c; + flags += c; } } @@ -3552,11 +3659,9 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation( cmGeneratorTarget* target) { - std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory(); - plist += cmake::GetCMakeFilesDirectory(); - plist += "/"; - plist += target->GetName(); - plist += ".dir/Info.plist"; + std::string plist = + cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/CMakeFiles/", target->GetName(), ".dir/Info.plist"); return plist; } @@ -3572,7 +3677,7 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation( std::string* reason) const { if (this->ObjectDirArch.find('$') != std::string::npos) { - if (reason != CM_NULLPTR) { + if (reason != nullptr) { *reason = " under Xcode with multiple architectures"; } return false; @@ -3587,10 +3692,10 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const "XCODE_EMIT_EFFECTIVE_PLATFORM_NAME"); if (!epnValue) { - return mf->PlatformIsAppleIos(); + return mf->PlatformIsAppleEmbedded(); } - return cmSystemTools::IsOn(epnValue); + return cmIsOn(epnValue); } bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const @@ -3604,8 +3709,29 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( { std::string configName = this->GetCMakeCFGIntDir(); std::string dir = - this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt); - dir += this->ObjectDirArch; - dir += "/"; + cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt, + "$(OBJECT_FILE_DIR_normal:base)/"), + this->ObjectDirArch, '/'); gt->ObjectDirectory = dir; } + +std::string cmGlobalXCodeGenerator::GetDeploymentPlatform(const cmMakefile* mf) +{ + switch (mf->GetAppleSDKType()) { + case cmMakefile::AppleSDK::AppleTVOS: + case cmMakefile::AppleSDK::AppleTVSimulator: + return "TVOS_DEPLOYMENT_TARGET"; + + case cmMakefile::AppleSDK::IPhoneOS: + case cmMakefile::AppleSDK::IPhoneSimulator: + return "IPHONEOS_DEPLOYMENT_TARGET"; + + case cmMakefile::AppleSDK::WatchOS: + case cmMakefile::AppleSDK::WatchSimulator: + return "WATCHOS_DEPLOYMENT_TARGET"; + + case cmMakefile::AppleSDK::MacOS: + default: + return "MACOSX_DEPLOYMENT_TARGET"; + } +} |