Files
cmake/Source/cmLocalXCodeGenerator.cxx
T
Ben Boeckel bbdc2fd908 cmSourceFile: internally track CMake-managed source files
These source file types don't necessarily show up in the CMake code, but
are side effects of other behaviors in CMake. Support tracking them
specially so that heuristics are not required to figure out if a given
`cmSourceFile` is one of them.
2025-09-08 11:59:57 -04:00

166 lines
5.4 KiB
C++

/* 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,
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);
}
}
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);
}
}
}