| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst or https://cmake.org/licensing for details. */ | |
| #include "cmLocalXCodeGenerator.h" | |
| #include <memory> | |
| #include <ostream> | |
| #include <utility> | |
| #include "cmGeneratorExpression.h" | |
| #include "cmGeneratorTarget.h" | |
| #include "cmGlobalXCodeGenerator.h" | |
| #include "cmMakefile.h" | |
| #include "cmSourceFile.h" | |
| #include "cmStringAlgorithms.h" | |
| #include "cmSystemTools.h" | |
| class cmGlobalGenerator; | |
| cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg, | |
| cmMakefile* mf) | |
| : cmLocalGenerator(gg, mf) | |
| { | |
| // the global generator does this, so do not | |
| // put these flags into the language flags | |
| this->EmitUniversalBinaryFlags = false; | |
| } | |
| cmLocalXCodeGenerator::~cmLocalXCodeGenerator() = default; | |
| std::string cmLocalXCodeGenerator::GetTargetDirectory( | |
| cmGeneratorTarget const* target, | |
| cmStateEnums::IntermediateDirKind /*kind*/) const | |
| { | |
| return cmStrCat(target->GetName(), ".dir"); | |
| } | |
| void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags, | |
| std::string const& rawFlag) const | |
| { | |
| cmGlobalXCodeGenerator const* gg = | |
| static_cast<cmGlobalXCodeGenerator const*>(this->GlobalGenerator); | |
| gg->AppendFlag(flags, rawFlag); | |
| } | |
| void cmLocalXCodeGenerator::Generate() | |
| { | |
| cmLocalGenerator::Generate(); | |
| for (auto const& target : this->GetGeneratorTargets()) { | |
| target->HasMacOSXRpathInstallNameDir(""); | |
| } | |
| } | |
| void cmLocalXCodeGenerator::AddGeneratorSpecificInstallSetup(std::ostream& os) | |
| { | |
| // First check if we need to warn about incompatible settings | |
| for (auto const& target : this->GetGeneratorTargets()) { | |
| target->HasMacOSXRpathInstallNameDir(""); | |
| } | |
| // CMakeIOSInstallCombined.cmake needs to know the location of the top of | |
| // the build directory | |
| os << "set(CMAKE_BINARY_DIR \"" << this->GetBinaryDirectory() << "\")\n\n"; | |
| if (this->Makefile->PlatformIsAppleEmbedded()) { | |
| std::string platformName; | |
| switch (this->Makefile->GetAppleSDKType()) { | |
| case cmMakefile::AppleSDK::IPhoneOS: | |
| platformName = "iphoneos"; | |
| break; | |
| case cmMakefile::AppleSDK::IPhoneSimulator: | |
| platformName = "iphonesimulator"; | |
| break; | |
| case cmMakefile::AppleSDK::AppleTVOS: | |
| platformName = "appletvos"; | |
| break; | |
| case cmMakefile::AppleSDK::AppleTVSimulator: | |
| platformName = "appletvsimulator"; | |
| break; | |
| case cmMakefile::AppleSDK::WatchOS: | |
| platformName = "watchos"; | |
| break; | |
| case cmMakefile::AppleSDK::WatchSimulator: | |
| platformName = "watchsimulator"; | |
| break; | |
| case cmMakefile::AppleSDK::XROS: | |
| platformName = "xros"; | |
| break; | |
| case cmMakefile::AppleSDK::XRSimulator: | |
| platformName = "xrsimulator"; | |
| break; | |
| case cmMakefile::AppleSDK::MacOS: | |
| break; | |
| } | |
| if (!platformName.empty()) { | |
| // The effective platform name is just the platform name with a hyphen | |
| // prepended. We can get the SUPPORTED_PLATFORMS from the project file | |
| // at runtime, so we don't need to compute that here. | |
| /* clang-format off */ | |
| os << | |
| "if(NOT PLATFORM_NAME)\n" | |
| " if(NOT \"$ENV{PLATFORM_NAME}\" STREQUAL \"\")\n" | |
| " set(PLATFORM_NAME \"$ENV{PLATFORM_NAME}\")\n" | |
| " endif()\n" | |
| " if(NOT PLATFORM_NAME)\n" | |
| " set(PLATFORM_NAME " << platformName << ")\n" | |
| " endif()\n" | |
| "endif()\n\n" | |
| "if(NOT EFFECTIVE_PLATFORM_NAME)\n" | |
| " if(NOT \"$ENV{EFFECTIVE_PLATFORM_NAME}\" STREQUAL \"\")\n" | |
| " set(EFFECTIVE_PLATFORM_NAME \"$ENV{EFFECTIVE_PLATFORM_NAME}\")\n" | |
| " endif()\n" | |
| " if(NOT EFFECTIVE_PLATFORM_NAME)\n" | |
| " set(EFFECTIVE_PLATFORM_NAME -" << platformName << ")\n" | |
| " endif()\n" | |
| "endif()\n\n"; | |
| /* clang-format off */ | |
| } | |
| } | |
| } | |
| void cmLocalXCodeGenerator::ComputeObjectFilenames( | |
| std::map<cmSourceFile const*, cmObjectLocations>& mapping, | |
| std::string const& config, | |
| cmGeneratorTarget const*) | |
| { | |
| // Count the number of object files with each name. Warn about duplicate | |
| // names since Xcode names them uniquely automatically with a numeric suffix | |
| // to avoid exact duplicate file names. Note that Mac file names are not | |
| // typically case sensitive, hence the LowerCase. | |
| std::map<std::string, int> counts; | |
| for (auto& si : mapping) { | |
| cmSourceFile const* sf = si.first; | |
| std::string shortObjectName = this->GetShortObjectFileName(*sf); | |
| std::string longObjectName = cmStrCat( | |
| cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o"); | |
| std::string longObjectNameLower = cmSystemTools::LowerCase(longObjectName); | |
| counts[longObjectNameLower] += 1; | |
| if (2 == counts[longObjectNameLower]) { | |
| // TODO: emit warning about duplicate name? | |
| } | |
| si.second.ShortLoc.emplace(shortObjectName); | |
| si.second.LongLoc.Update(longObjectName); | |
| this->FillCustomInstallObjectLocations(*sf, config, ".o", si.second.InstallLongLoc); | |
| } | |
| } | |
| void cmLocalXCodeGenerator::AddXCConfigSources(cmGeneratorTarget* target) | |
| { | |
| auto xcconfig = target->GetProperty("XCODE_XCCONFIG"); | |
| if (!xcconfig) { | |
| return; | |
| } | |
| auto configs = target->Makefile->GetGeneratorConfigs( | |
| cmMakefile::IncludeEmptyConfig); | |
| for (auto& config : configs) { | |
| auto file = cmGeneratorExpression::Evaluate( | |
| *xcconfig, | |
| this, config); | |
| if (!file.empty()) { | |
| auto* xcconfig_sf = target->AddSource(file); | |
| xcconfig_sf->SetSpecialSourceType(cmSourceFile::SpecialSourceType::XcodeXCConfigFile); | |
| } | |
| } | |
| } |