Xcode: Write shared schemes based on the default files generated by Xcode

Issue: #15441
This commit is contained in:
Gusts Kaksis 2017-01-18 16:20:09 +02:00 committed by Brad King
parent 32cb4172bd
commit ffb8817b37
5 changed files with 284 additions and 0 deletions

View File

@ -639,6 +639,7 @@ if(APPLE)
set(SRCS ${SRCS}
cmXCodeObject.cxx
cmXCode21Object.cxx
cmXCodeScheme.cxx
cmGlobalXCodeGenerator.cxx
cmGlobalXCodeGenerator.h
cmLocalXCodeGenerator.cxx

View File

@ -28,6 +28,7 @@
#include "cmTarget.h"
#include "cmXCode21Object.h"
#include "cmXCodeObject.h"
#include "cmXCodeScheme.h"
#include "cm_auto_ptr.hxx"
#include "cmake.h"
@ -3327,6 +3328,15 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
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->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool(
"XCODE_GENERATE_SCHEME") &&
this->XcodeVersion >= 70) {
this->OutputXCodeSharedSchemes(xcodeDir, root);
}
this->ClearXCodeObjects();
// Since this call may have created new cache entries, save the cache:
@ -3335,6 +3345,24 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
root->GetBinaryDirectory());
}
void 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,
root->GetCurrentSourceDirectory());
}
}
}
void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
cmLocalGenerator*,
std::vector<cmLocalGenerator*>&)

View File

@ -165,6 +165,9 @@ private:
std::vector<cmLocalGenerator*>& generators);
void OutputXCodeProject(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
// Write shared scheme files for all the native targets
void OutputXCodeSharedSchemes(const std::string& xcProjDir,
cmLocalGenerator* root);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,

206
Source/cmXCodeScheme.cxx Normal file
View File

@ -0,0 +1,206 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmXCodeScheme.h"
#include <iomanip>
#include <sstream>
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmXMLSafe.h"
cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
const std::vector<std::string>& configList,
unsigned int xcVersion)
: TargetName(xcObj->GetTarget()->GetName())
, TargetId(xcObj->GetId())
, ConfigList(configList)
, XcodeVersion(xcVersion)
{
}
void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
const std::string sourceRoot)
{
// Create shared scheme sub-directory tree
//
std::string xcodeSchemeDir = xcProjDir;
xcodeSchemeDir += "/xcshareddata/xcschemes";
cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
std::string xcodeSchemeFile = xcodeSchemeDir;
xcodeSchemeFile += "/";
xcodeSchemeFile += this->TargetName;
xcodeSchemeFile += ".xcscheme";
cmGeneratedFileStream fout(xcodeSchemeFile.c_str());
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
}
std::string xcProjRelDir = xcProjDir.substr(sourceRoot.size() + 1);
WriteXCodeXCScheme(fout, xcProjRelDir);
}
void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
const std::string& xcProjDir)
{
cmXMLWriter xout(fout);
xout.StartDocument();
xout.StartElement("Scheme");
xout.BreakAttributes();
xout.Attribute("LastUpgradeVersion", WriteVersionString());
xout.Attribute("version", "1.3");
WriteBuildAction(xout, xcProjDir);
WriteTestAction(xout, FindConfiguration("Debug"));
WriteLaunchAction(xout, FindConfiguration("Debug"), xcProjDir);
WriteProfileAction(xout, FindConfiguration("Release"));
WriteAnalyzeAction(xout, FindConfiguration("Debug"));
WriteArchiveAction(xout, FindConfiguration("Release"));
xout.EndElement();
}
void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
const std::string& xcProjDir)
{
xout.StartElement("BuildAction");
xout.BreakAttributes();
xout.Attribute("parallelizeBuildables", "YES");
xout.Attribute("buildImplicitDependencies", "YES");
xout.StartElement("BuildActionEntries");
xout.StartElement("BuildActionEntry");
xout.BreakAttributes();
xout.Attribute("buildForTesting", "YES");
xout.Attribute("buildForRunning", "YES");
xout.Attribute("buildForProfiling", "YES");
xout.Attribute("buildForArchiving", "YES");
xout.Attribute("buildForAnalyzing", "YES");
xout.StartElement("BuildableReference");
xout.BreakAttributes();
xout.Attribute("BuildableIdentifier", "primary");
xout.Attribute("BlueprintIdentifier", this->TargetId);
xout.Attribute("BuildableName", this->TargetName);
xout.Attribute("BlueprintName", this->TargetName);
xout.Attribute("ReferencedContainer", "container:" + xcProjDir);
xout.EndElement();
xout.EndElement(); // BuildActionEntry
xout.EndElement(); // BuildActionEntries
xout.EndElement(); // BuildAction
}
void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
std::string configuration)
{
xout.StartElement("TestAction");
xout.BreakAttributes();
xout.Attribute("buildConfiguration", configuration);
xout.Attribute("selectedDebuggerIdentifier",
"Xcode.DebuggerFoundation.Debugger.LLDB");
xout.Attribute("selectedLauncherIdentifier",
"Xcode.DebuggerFoundation.Launcher.LLDB");
xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
xout.StartElement("Testables");
xout.EndElement();
xout.StartElement("AdditionalOptions");
xout.EndElement();
xout.EndElement(); // TestAction
}
void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
std::string configuration,
const std::string& xcProjDir)
{
xout.StartElement("LaunchAction");
xout.BreakAttributes();
xout.Attribute("buildConfiguration", configuration);
xout.Attribute("selectedDebuggerIdentifier",
"Xcode.DebuggerFoundation.Debugger.LLDB");
xout.Attribute("selectedLauncherIdentifier",
"Xcode.DebuggerFoundation.Launcher.LLDB");
xout.Attribute("launchStyle", "0");
xout.Attribute("useCustomWorkingDirectory", "NO");
xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
xout.Attribute("debugDocumentVersioning", "YES");
xout.Attribute("debugServiceExtension", "internal");
xout.Attribute("allowLocationSimulation", "YES");
xout.StartElement("MacroExpansion");
xout.StartElement("BuildableReference");
xout.BreakAttributes();
xout.Attribute("BuildableIdentifier", "primary");
xout.Attribute("BlueprintIdentifier", this->TargetId);
xout.Attribute("BuildableName", this->TargetName);
xout.Attribute("BlueprintName", this->TargetName);
xout.Attribute("ReferencedContainer", "container:" + xcProjDir);
xout.EndElement();
xout.EndElement(); // MacroExpansion
xout.StartElement("AdditionalOptions");
xout.EndElement();
xout.EndElement(); // LaunchAction
}
void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
std::string configuration)
{
xout.StartElement("ProfileAction");
xout.BreakAttributes();
xout.Attribute("buildConfiguration", configuration);
xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
xout.Attribute("savedToolIdentifier", "");
xout.Attribute("useCustomWorkingDirectory", "NO");
xout.Attribute("debugDocumentVersioning", "YES");
xout.EndElement();
}
void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout,
std::string configuration)
{
xout.StartElement("AnalyzeAction");
xout.BreakAttributes();
xout.Attribute("buildConfiguration", configuration);
xout.EndElement();
}
void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
std::string configuration)
{
xout.StartElement("ArchiveAction");
xout.BreakAttributes();
xout.Attribute("buildConfiguration", configuration);
xout.Attribute("revealArchiveInOrganizer", "YES");
xout.EndElement();
}
std::string cmXCodeScheme::WriteVersionString()
{
std::ostringstream v;
v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10;
return v.str();
}
std::string cmXCodeScheme::FindConfiguration(const std::string& name)
{
// Try to find the desired configuration by name,
// and if it's not found return first from the list
//
if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) ==
this->ConfigList.end() &&
this->ConfigList.size() > 0)
return this->ConfigList[0];
return name;
}

46
Source/cmXCodeScheme.h Normal file
View File

@ -0,0 +1,46 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#ifndef cmXCodeScheme_h
#define cmXCodeScheme_h
#include <cmConfigure.h> // IWYU pragma: keep
#include "cmGlobalXCodeGenerator.h"
#include "cmSystemTools.h"
#include "cmXCodeObject.h"
#include "cmXMLWriter.h"
/** \class cmXCodeScheme
* \brief Write shared schemes for native targets in Xcode project.
*/
class cmXCodeScheme
{
public:
cmXCodeScheme(cmXCodeObject* xcObj,
const std::vector<std::string>& configList,
unsigned int xcVersion);
void WriteXCodeSharedScheme(const std::string& xcProjDir,
const std::string sourceRoot);
private:
const std::string& TargetName;
const std::string& TargetId;
const std::vector<std::string>& ConfigList;
const unsigned int XcodeVersion;
void WriteXCodeXCScheme(std::ostream& fout, const std::string& xcProjDir);
void WriteBuildAction(cmXMLWriter& xout, const std::string& xcProjDir);
void WriteTestAction(cmXMLWriter& xout, std::string configuration);
void WriteLaunchAction(cmXMLWriter& xout, std::string configuration,
const std::string& xcProjDir);
void WriteProfileAction(cmXMLWriter& xout, std::string configuration);
void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration);
void WriteArchiveAction(cmXMLWriter& xout, std::string configuration);
std::string WriteVersionString();
std::string FindConfiguration(const std::string& name);
};
#endif