1044 lines
39 KiB
C#
1044 lines
39 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace ImaginationOverflow.UniversalDeepLinking.Editor.Xcode.PBX
|
|
{
|
|
internal class PBXObjectData
|
|
{
|
|
public string guid;
|
|
protected PBXElementDict m_Properties = new PBXElementDict();
|
|
|
|
internal void SetPropertiesWhenSerializing(PBXElementDict props)
|
|
{
|
|
m_Properties = props;
|
|
}
|
|
|
|
internal PBXElementDict GetPropertiesWhenSerializing()
|
|
{
|
|
return m_Properties;
|
|
}
|
|
|
|
/* Returns the internal properties dictionary which the user may manipulate directly.
|
|
If any of the properties are modified, UpdateVars() must be called before any other
|
|
operation affecting the given Xcode document is executed.
|
|
*/
|
|
internal PBXElementDict GetPropertiesRaw()
|
|
{
|
|
UpdateProps();
|
|
return m_Properties;
|
|
}
|
|
|
|
// returns null if it does not exist
|
|
protected string GetPropertyString(string name)
|
|
{
|
|
var prop = m_Properties[name];
|
|
if (prop == null)
|
|
return null;
|
|
|
|
return prop.AsString();
|
|
}
|
|
|
|
protected void SetPropertyString(string name, string value)
|
|
{
|
|
if (value == null)
|
|
m_Properties.Remove(name);
|
|
else
|
|
m_Properties.SetString(name, value);
|
|
}
|
|
|
|
protected List<string> GetPropertyList(string name)
|
|
{
|
|
var prop = m_Properties[name];
|
|
if (prop == null)
|
|
return null;
|
|
|
|
var list = new List<string>();
|
|
foreach (var el in prop.AsArray().values)
|
|
list.Add(el.AsString());
|
|
return list;
|
|
}
|
|
|
|
protected void SetPropertyList(string name, List<string> value)
|
|
{
|
|
if (value == null)
|
|
m_Properties.Remove(name);
|
|
else
|
|
{
|
|
var array = m_Properties.CreateArray(name);
|
|
foreach (string val in value)
|
|
array.AddString(val);
|
|
}
|
|
}
|
|
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker();
|
|
internal virtual PropertyCommentChecker checker { get { return checkerData; } }
|
|
internal virtual bool shouldCompact { get { return false; } }
|
|
|
|
public virtual void UpdateProps() { } // Updates the props from cached variables
|
|
public virtual void UpdateVars() { } // Updates the cached variables from underlying props
|
|
}
|
|
|
|
internal class PBXBuildFileData : PBXObjectData
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker((IEnumerable<string>)new string[1]
|
|
{
|
|
"fileRef/*"
|
|
});
|
|
public string fileRef;
|
|
public string compileFlags;
|
|
public bool weak;
|
|
public bool codeSignOnCopy;
|
|
public bool removeHeadersOnCopy;
|
|
public List<string> assetTags;
|
|
|
|
internal override PropertyCommentChecker checker
|
|
{
|
|
get
|
|
{
|
|
return PBXBuildFileData.checkerData;
|
|
}
|
|
}
|
|
|
|
internal override bool shouldCompact
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static PBXBuildFileData CreateFromFile(
|
|
string fileRefGUID,
|
|
bool weak,
|
|
string compileFlags)
|
|
{
|
|
PBXBuildFileData pbxBuildFileData = new PBXBuildFileData();
|
|
pbxBuildFileData.guid = PBXGUID.Generate();
|
|
pbxBuildFileData.SetPropertyString("isa", "PBXBuildFile");
|
|
pbxBuildFileData.fileRef = fileRefGUID;
|
|
pbxBuildFileData.compileFlags = compileFlags;
|
|
pbxBuildFileData.weak = weak;
|
|
pbxBuildFileData.codeSignOnCopy = false;
|
|
pbxBuildFileData.removeHeadersOnCopy = false;
|
|
pbxBuildFileData.assetTags = new List<string>();
|
|
return pbxBuildFileData;
|
|
}
|
|
|
|
private PBXElementDict UpdatePropsAttribute(
|
|
PBXElementDict settings,
|
|
bool value,
|
|
string attributeName)
|
|
{
|
|
PBXElementArray pbxElementArray = (PBXElementArray)null;
|
|
if (value && settings == null)
|
|
settings = this.m_Properties.CreateDict("settings");
|
|
if (settings != null && settings.Contains("ATTRIBUTES"))
|
|
pbxElementArray = settings["ATTRIBUTES"].AsArray();
|
|
if (value)
|
|
{
|
|
if (pbxElementArray == null)
|
|
pbxElementArray = settings.CreateArray("ATTRIBUTES");
|
|
if (!pbxElementArray.values.Any<PBXElement>((Func<PBXElement, bool>)(attr => attr is PBXElementString && attr.AsString() == attributeName)))
|
|
pbxElementArray.AddString(attributeName);
|
|
}
|
|
else if (pbxElementArray != null)
|
|
{
|
|
pbxElementArray.values.RemoveAll((Predicate<PBXElement>)(el => el is PBXElementString && el.AsString() == attributeName));
|
|
if (pbxElementArray.values.Count == 0)
|
|
settings.Remove("ATTRIBUTES");
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
this.SetPropertyString("fileRef", this.fileRef);
|
|
PBXElementDict settings = (PBXElementDict)null;
|
|
if (this.m_Properties.Contains("settings"))
|
|
settings = this.m_Properties["settings"].AsDict();
|
|
if (this.compileFlags != null && this.compileFlags != "")
|
|
{
|
|
if (settings == null)
|
|
settings = this.m_Properties.CreateDict("settings");
|
|
settings.SetString("COMPILER_FLAGS", this.compileFlags);
|
|
}
|
|
else
|
|
{
|
|
if (settings != null)
|
|
settings.Remove("COMPILER_FLAGS");
|
|
}
|
|
PBXElementDict pbxElementDict = this.UpdatePropsAttribute(this.UpdatePropsAttribute(this.UpdatePropsAttribute(settings, this.weak, "Weak"), this.codeSignOnCopy, "CodeSignOnCopy"), this.removeHeadersOnCopy, "RemoveHeadersOnCopy");
|
|
if (this.assetTags.Count > 0)
|
|
{
|
|
if (pbxElementDict == null)
|
|
pbxElementDict = this.m_Properties.CreateDict("settings");
|
|
PBXElementArray array = pbxElementDict.CreateArray("ASSET_TAGS");
|
|
foreach (string assetTag in this.assetTags)
|
|
array.AddString(assetTag);
|
|
}
|
|
else
|
|
{
|
|
if (pbxElementDict != null)
|
|
pbxElementDict.Remove("ASSET_TAGS");
|
|
}
|
|
if (pbxElementDict == null || pbxElementDict.values.Count != 0)
|
|
return;
|
|
this.m_Properties.Remove("settings");
|
|
}
|
|
|
|
public override void UpdateVars()
|
|
{
|
|
this.fileRef = this.GetPropertyString("fileRef");
|
|
this.compileFlags = (string)null;
|
|
this.weak = false;
|
|
this.assetTags = new List<string>();
|
|
if (!this.m_Properties.Contains("settings"))
|
|
return;
|
|
PBXElementDict pbxElementDict = this.m_Properties["settings"].AsDict();
|
|
if (pbxElementDict.Contains("COMPILER_FLAGS"))
|
|
this.compileFlags = pbxElementDict["COMPILER_FLAGS"].AsString();
|
|
if (pbxElementDict.Contains("ATTRIBUTES"))
|
|
{
|
|
foreach (PBXElement pbxElement in pbxElementDict["ATTRIBUTES"].AsArray().values)
|
|
{
|
|
if (pbxElement is PBXElementString && pbxElement.AsString() == "Weak")
|
|
this.weak = true;
|
|
if (pbxElement is PBXElementString && pbxElement.AsString() == "CodeSignOnCopy")
|
|
this.codeSignOnCopy = true;
|
|
if (pbxElement is PBXElementString && pbxElement.AsString() == "RemoveHeadersOnCopy")
|
|
this.removeHeadersOnCopy = true;
|
|
}
|
|
}
|
|
if (pbxElementDict.Contains("ASSET_TAGS"))
|
|
{
|
|
foreach (PBXElement pbxElement in pbxElementDict["ASSET_TAGS"].AsArray().values)
|
|
this.assetTags.Add(pbxElement.AsString());
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class PBXFileReferenceData : PBXObjectData
|
|
{
|
|
string m_Path = null;
|
|
string m_ExplicitFileType = null;
|
|
string m_LastKnownFileType = null;
|
|
|
|
public string path
|
|
{
|
|
get { return m_Path; }
|
|
set { m_ExplicitFileType = null; m_LastKnownFileType = null; m_Path = value; }
|
|
}
|
|
|
|
public string name;
|
|
public PBXSourceTree tree;
|
|
public bool isFolderReference
|
|
{
|
|
get { return m_LastKnownFileType != null && m_LastKnownFileType == "folder"; }
|
|
}
|
|
|
|
internal override bool shouldCompact { get { return true; } }
|
|
|
|
public static PBXFileReferenceData CreateFromFile(string path, string projectFileName,
|
|
PBXSourceTree tree)
|
|
{
|
|
string guid = PBXGUID.Generate();
|
|
|
|
PBXFileReferenceData fileRef = new PBXFileReferenceData();
|
|
fileRef.SetPropertyString("isa", "PBXFileReference");
|
|
fileRef.guid = guid;
|
|
fileRef.path = path;
|
|
fileRef.name = projectFileName;
|
|
fileRef.tree = tree;
|
|
return fileRef;
|
|
}
|
|
|
|
public static PBXFileReferenceData CreateFromFolderReference(string path, string projectFileName,
|
|
PBXSourceTree tree)
|
|
{
|
|
var fileRef = CreateFromFile(path, projectFileName, tree);
|
|
fileRef.m_LastKnownFileType = "folder";
|
|
return fileRef;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
string ext = null;
|
|
if (m_ExplicitFileType != null)
|
|
SetPropertyString("explicitFileType", m_ExplicitFileType);
|
|
else if (m_LastKnownFileType != null)
|
|
SetPropertyString("lastKnownFileType", m_LastKnownFileType);
|
|
else
|
|
{
|
|
if (name != null)
|
|
ext = Path.GetExtension(name);
|
|
else if (m_Path != null)
|
|
ext = Path.GetExtension(m_Path);
|
|
if (ext != null)
|
|
{
|
|
if (FileTypeUtils.IsFileTypeExplicit(ext))
|
|
SetPropertyString("explicitFileType", FileTypeUtils.GetTypeName(ext));
|
|
else
|
|
SetPropertyString("lastKnownFileType", FileTypeUtils.GetTypeName(ext));
|
|
}
|
|
}
|
|
if (m_Path == name)
|
|
SetPropertyString("name", null);
|
|
else
|
|
SetPropertyString("name", name);
|
|
if (m_Path == null)
|
|
SetPropertyString("path", "");
|
|
else
|
|
SetPropertyString("path", m_Path);
|
|
SetPropertyString("sourceTree", FileTypeUtils.SourceTreeDesc(tree));
|
|
}
|
|
|
|
public override void UpdateVars()
|
|
{
|
|
name = GetPropertyString("name");
|
|
m_Path = GetPropertyString("path");
|
|
if (name == null)
|
|
name = m_Path;
|
|
if (m_Path == null)
|
|
m_Path = "";
|
|
tree = FileTypeUtils.ParseSourceTree(GetPropertyString("sourceTree"));
|
|
m_ExplicitFileType = GetPropertyString("explicitFileType");
|
|
m_LastKnownFileType = GetPropertyString("lastKnownFileType");
|
|
}
|
|
|
|
public void SetFileTypeByExtension(string extension)
|
|
{
|
|
if (FileTypeUtils.IsFileTypeExplicit(extension))
|
|
{
|
|
SetPropertyString("explicitFileType", FileTypeUtils.GetTypeName(extension));
|
|
}
|
|
else
|
|
{
|
|
SetPropertyString("lastKnownFileType", FileTypeUtils.GetTypeName(extension));
|
|
}
|
|
}
|
|
}
|
|
|
|
class GUIDList : IEnumerable<string>
|
|
{
|
|
private List<string> m_List = new List<string>();
|
|
|
|
public GUIDList() { }
|
|
public GUIDList(List<string> data)
|
|
{
|
|
m_List = data;
|
|
}
|
|
|
|
public static implicit operator List<string>(GUIDList list) { return list.m_List; }
|
|
public static implicit operator GUIDList(List<string> data) { return new GUIDList(data); }
|
|
|
|
public void AddGUID(string guid) { m_List.Add(guid); }
|
|
public void RemoveGUID(string guid) { m_List.RemoveAll(x => x == guid); }
|
|
public bool Contains(string guid) { return m_List.Contains(guid); }
|
|
public int Count { get { return m_List.Count; } }
|
|
public void Clear() { m_List.Clear(); }
|
|
IEnumerator<string> IEnumerable<string>.GetEnumerator() { return m_List.GetEnumerator(); }
|
|
IEnumerator IEnumerable.GetEnumerator() { return m_List.GetEnumerator(); }
|
|
}
|
|
|
|
internal class XCConfigurationListData : PBXObjectData
|
|
{
|
|
public GUIDList buildConfigs;
|
|
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"buildConfigurations/*"
|
|
});
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public static XCConfigurationListData Create()
|
|
{
|
|
var res = new XCConfigurationListData();
|
|
res.guid = PBXGUID.Generate();
|
|
|
|
res.SetPropertyString("isa", "XCConfigurationList");
|
|
res.buildConfigs = new GUIDList();
|
|
res.SetPropertyString("defaultConfigurationIsVisible", "0");
|
|
|
|
return res;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
SetPropertyList("buildConfigurations", buildConfigs);
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
buildConfigs = GetPropertyList("buildConfigurations");
|
|
}
|
|
}
|
|
|
|
internal class PBXGroupData : PBXObjectData
|
|
{
|
|
public GUIDList children;
|
|
public PBXSourceTree tree;
|
|
public string name, path;
|
|
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"children/*"
|
|
});
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
// name must not contain '/'
|
|
public static PBXGroupData Create(string name, string path, PBXSourceTree tree)
|
|
{
|
|
if (name.Contains("/"))
|
|
throw new Exception("Group name must not contain '/'");
|
|
|
|
PBXGroupData gr = new PBXGroupData();
|
|
gr.guid = PBXGUID.Generate();
|
|
gr.SetPropertyString("isa", "PBXGroup");
|
|
gr.name = name;
|
|
gr.path = path;
|
|
gr.tree = PBXSourceTree.Group;
|
|
gr.children = new GUIDList();
|
|
|
|
return gr;
|
|
}
|
|
|
|
public static PBXGroupData CreateRelative(string name)
|
|
{
|
|
return Create(name, name, PBXSourceTree.Group);
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
// The name property is set only if it is different from the path property
|
|
SetPropertyList("children", children);
|
|
if (name == path)
|
|
SetPropertyString("name", null);
|
|
else
|
|
SetPropertyString("name", name);
|
|
if (path == "")
|
|
SetPropertyString("path", null);
|
|
else
|
|
SetPropertyString("path", path);
|
|
SetPropertyString("sourceTree", FileTypeUtils.SourceTreeDesc(tree));
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
children = GetPropertyList("children");
|
|
path = GetPropertyString("path");
|
|
name = GetPropertyString("name");
|
|
if (name == null)
|
|
name = path;
|
|
if (path == null)
|
|
path = "";
|
|
tree = FileTypeUtils.ParseSourceTree(GetPropertyString("sourceTree"));
|
|
}
|
|
}
|
|
|
|
internal class PBXVariantGroupData : PBXGroupData
|
|
{
|
|
|
|
public static PBXVariantGroupData Create(string name)
|
|
{
|
|
if (name.Contains("/"))
|
|
throw new Exception("Group name must not contain '/'");
|
|
|
|
PBXVariantGroupData gr = new PBXVariantGroupData();
|
|
gr.guid = PBXGUID.Generate();
|
|
gr.SetPropertyString("isa", "PBXVariantGroup");
|
|
gr.name = name;
|
|
gr.tree = PBXSourceTree.Group;
|
|
gr.children = new GUIDList();
|
|
|
|
return gr;
|
|
}
|
|
|
|
}
|
|
|
|
internal class PBXNativeTargetData : PBXObjectData
|
|
{
|
|
public GUIDList phases;
|
|
|
|
public string buildConfigList; // guid
|
|
public string name;
|
|
public GUIDList dependencies;
|
|
public string productReference; // guid
|
|
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"buildPhases/*",
|
|
"buildRules/*",
|
|
"dependencies/*",
|
|
"productReference/*",
|
|
"buildConfigurationList/*"
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public static PBXNativeTargetData Create(string name, string productRef,
|
|
string productType, string buildConfigList)
|
|
{
|
|
var res = new PBXNativeTargetData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXNativeTarget");
|
|
res.buildConfigList = buildConfigList;
|
|
res.phases = new GUIDList();
|
|
res.SetPropertyList("buildRules", new List<string>());
|
|
res.dependencies = new GUIDList();
|
|
res.name = name;
|
|
res.productReference = productRef;
|
|
res.SetPropertyString("productName", name);
|
|
res.SetPropertyString("productReference", productRef);
|
|
res.SetPropertyString("productType", productType);
|
|
return res;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
SetPropertyString("buildConfigurationList", buildConfigList);
|
|
SetPropertyString("name", name);
|
|
SetPropertyString("productReference", productReference);
|
|
SetPropertyList("buildPhases", phases);
|
|
SetPropertyList("dependencies", dependencies);
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
buildConfigList = GetPropertyString("buildConfigurationList");
|
|
name = GetPropertyString("name");
|
|
productReference = GetPropertyString("productReference");
|
|
phases = GetPropertyList("buildPhases");
|
|
dependencies = GetPropertyList("dependencies");
|
|
}
|
|
}
|
|
|
|
|
|
internal class FileGUIDListBase : PBXObjectData
|
|
{
|
|
public GUIDList files;
|
|
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"files/*",
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
SetPropertyList("files", files);
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
files = GetPropertyList("files");
|
|
}
|
|
}
|
|
|
|
internal class PBXSourcesBuildPhaseData : FileGUIDListBase
|
|
{
|
|
public static PBXSourcesBuildPhaseData Create()
|
|
{
|
|
var res = new PBXSourcesBuildPhaseData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXSourcesBuildPhase");
|
|
res.SetPropertyString("buildActionMask", "2147483647");
|
|
res.files = new List<string>();
|
|
res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0");
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXFrameworksBuildPhaseData : FileGUIDListBase
|
|
{
|
|
public const string ISA = "PBXFrameworksBuildPhase";
|
|
public string isa
|
|
{
|
|
get { return GetPropertyString("isa"); }
|
|
}
|
|
|
|
public static PBXFrameworksBuildPhaseData Create()
|
|
{
|
|
var res = new PBXFrameworksBuildPhaseData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXFrameworksBuildPhase");
|
|
res.SetPropertyString("buildActionMask", "2147483647");
|
|
res.files = new List<string>();
|
|
res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0");
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXResourcesBuildPhaseData : FileGUIDListBase
|
|
{
|
|
public static PBXResourcesBuildPhaseData Create()
|
|
{
|
|
var res = new PBXResourcesBuildPhaseData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXResourcesBuildPhase");
|
|
res.SetPropertyString("buildActionMask", "2147483647");
|
|
res.files = new List<string>();
|
|
res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0");
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXCopyFilesBuildPhaseData : FileGUIDListBase
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"files/*",
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public string name;
|
|
|
|
// name may be null
|
|
public static PBXCopyFilesBuildPhaseData Create(string name, string dstPath, string subfolderSpec)
|
|
{
|
|
var res = new PBXCopyFilesBuildPhaseData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXCopyFilesBuildPhase");
|
|
res.SetPropertyString("buildActionMask", "2147483647");
|
|
res.SetPropertyString("dstPath", dstPath);
|
|
res.SetPropertyString("dstSubfolderSpec", subfolderSpec);
|
|
res.files = new List<string>();
|
|
res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0");
|
|
res.name = name;
|
|
return res;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
SetPropertyList("files", files);
|
|
SetPropertyString("name", name);
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
files = GetPropertyList("files");
|
|
name = GetPropertyString("name");
|
|
}
|
|
}
|
|
|
|
internal class PBXShellScriptBuildPhaseData : FileGUIDListBase
|
|
{
|
|
public string name;
|
|
public string shellPath;
|
|
public string shellScript;
|
|
|
|
public static PBXShellScriptBuildPhaseData Create(string name, string shellPath, string shellScript)
|
|
{
|
|
var res = new PBXShellScriptBuildPhaseData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXShellScriptBuildPhase");
|
|
res.SetPropertyString("buildActionMask", "2147483647");
|
|
res.files = new List<string>();
|
|
res.SetPropertyString("runOnlyForDeploymentPostprocessing", "0");
|
|
res.name = name;
|
|
res.shellPath = shellPath;
|
|
res.shellScript = shellScript;
|
|
return res;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
base.UpdateProps();
|
|
SetPropertyString("name", name);
|
|
SetPropertyString("shellPath", shellPath);
|
|
SetPropertyString("shellScript", shellScript);
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
base.UpdateVars();
|
|
name = GetPropertyString("name");
|
|
shellPath = GetPropertyString("shellPath");
|
|
shellScript = GetPropertyString("shellScript");
|
|
}
|
|
}
|
|
|
|
internal class BuildConfigEntryData
|
|
{
|
|
public string name;
|
|
public List<string> val = new List<string>();
|
|
|
|
public static string ExtractValue(string src)
|
|
{
|
|
return PBXStream.UnquoteString(src.Trim().TrimEnd(','));
|
|
}
|
|
|
|
public void AddValue(string value)
|
|
{
|
|
if (!val.Contains(value))
|
|
val.Add(value);
|
|
}
|
|
|
|
public void RemoveValue(string value)
|
|
{
|
|
val.RemoveAll(v => v == value);
|
|
}
|
|
|
|
public void RemoveValueList(IEnumerable<string> values)
|
|
{
|
|
List<string> valueList = new List<string>(values);
|
|
if (valueList.Count == 0)
|
|
return;
|
|
for (int i = 0; i < val.Count - valueList.Count; i++)
|
|
{
|
|
bool match = true;
|
|
for (int j = 0; j < valueList.Count; j++)
|
|
{
|
|
if (val[i + j] != valueList[j])
|
|
{
|
|
match = false;
|
|
break;
|
|
}
|
|
}
|
|
if (match)
|
|
{
|
|
val.RemoveRange(i, valueList.Count);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static BuildConfigEntryData FromNameValue(string name, string value)
|
|
{
|
|
BuildConfigEntryData ret = new BuildConfigEntryData();
|
|
ret.name = name;
|
|
ret.AddValue(value);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
internal class XCBuildConfigurationData : PBXObjectData
|
|
{
|
|
protected SortedDictionary<string, BuildConfigEntryData> entries = new SortedDictionary<string, BuildConfigEntryData>();
|
|
public string name { get { return GetPropertyString("name"); } }
|
|
public string baseConfigurationReference; // may be null
|
|
|
|
// Note that QuoteStringIfNeeded does its own escaping. Double-escaping with quotes is
|
|
// required to please Xcode that does not handle paths with spaces if they are not
|
|
// enclosed in quotes.
|
|
static string EscapeWithQuotesIfNeeded(string name, string value)
|
|
{
|
|
if (name != "LIBRARY_SEARCH_PATHS" && name != "FRAMEWORK_SEARCH_PATHS")
|
|
return value;
|
|
if (!value.Contains(" "))
|
|
return value;
|
|
if (value.First() == '\"' && value.Last() == '\"')
|
|
return value;
|
|
return "\"" + value + "\"";
|
|
}
|
|
|
|
public void SetProperty(string name, string value)
|
|
{
|
|
entries[name] = BuildConfigEntryData.FromNameValue(name, EscapeWithQuotesIfNeeded(name, value));
|
|
}
|
|
|
|
public void AddProperty(string name, string value)
|
|
{
|
|
if (entries.ContainsKey(name))
|
|
entries[name].AddValue(EscapeWithQuotesIfNeeded(name, value));
|
|
else
|
|
SetProperty(name, value);
|
|
}
|
|
|
|
public void RemoveProperty(string name)
|
|
{
|
|
if (entries.ContainsKey(name))
|
|
entries.Remove(name);
|
|
}
|
|
|
|
public void RemovePropertyValue(string name, string value)
|
|
{
|
|
if (entries.ContainsKey(name))
|
|
entries[name].RemoveValue(EscapeWithQuotesIfNeeded(name, value));
|
|
}
|
|
|
|
public void RemovePropertyValueList(string name, IEnumerable<string> valueList)
|
|
{
|
|
if (entries.ContainsKey(name))
|
|
entries[name].RemoveValueList(valueList);
|
|
}
|
|
|
|
// name should be either release or debug
|
|
public static XCBuildConfigurationData Create(string name)
|
|
{
|
|
var res = new XCBuildConfigurationData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "XCBuildConfiguration");
|
|
res.SetPropertyString("name", name);
|
|
return res;
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
SetPropertyString("baseConfigurationReference", baseConfigurationReference);
|
|
|
|
var dict = m_Properties.CreateDict("buildSettings");
|
|
foreach (var kv in entries)
|
|
{
|
|
if (kv.Value.val.Count == 0)
|
|
continue;
|
|
else if (kv.Value.val.Count == 1)
|
|
dict.SetString(kv.Key, kv.Value.val[0]);
|
|
else // kv.Value.val.Count > 1
|
|
{
|
|
var array = dict.CreateArray(kv.Key);
|
|
foreach (var value in kv.Value.val)
|
|
array.AddString(value);
|
|
}
|
|
}
|
|
}
|
|
public override void UpdateVars()
|
|
{
|
|
baseConfigurationReference = GetPropertyString("baseConfigurationReference");
|
|
|
|
entries = new SortedDictionary<string, BuildConfigEntryData>();
|
|
if (m_Properties.Contains("buildSettings"))
|
|
{
|
|
var dict = m_Properties["buildSettings"].AsDict();
|
|
foreach (var key in dict.values.Keys)
|
|
{
|
|
var value = dict[key];
|
|
if (value is PBXElementString)
|
|
{
|
|
if (entries.ContainsKey(key))
|
|
entries[key].val.Add(value.AsString());
|
|
else
|
|
entries.Add(key, BuildConfigEntryData.FromNameValue(key, value.AsString()));
|
|
}
|
|
else if (value is PBXElementArray)
|
|
{
|
|
foreach (var pvalue in value.AsArray().values)
|
|
{
|
|
if (pvalue is PBXElementString)
|
|
{
|
|
if (entries.ContainsKey(key))
|
|
entries[key].val.Add(pvalue.AsString());
|
|
else
|
|
entries.Add(key, BuildConfigEntryData.FromNameValue(key, pvalue.AsString()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class PBXContainerItemProxyData : PBXObjectData
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"containerPortal/*"
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public static PBXContainerItemProxyData Create(string containerRef, string proxyType,
|
|
string remoteGlobalGUID, string remoteInfo)
|
|
{
|
|
var res = new PBXContainerItemProxyData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXContainerItemProxy");
|
|
res.SetPropertyString("containerPortal", containerRef); // guid
|
|
res.SetPropertyString("proxyType", proxyType);
|
|
res.SetPropertyString("remoteGlobalIDString", remoteGlobalGUID); // guid
|
|
res.SetPropertyString("remoteInfo", remoteInfo);
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXReferenceProxyData : PBXObjectData
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"remoteRef/*"
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public string path { get { return GetPropertyString("path"); } }
|
|
|
|
public static PBXReferenceProxyData Create(string path, string fileType,
|
|
string remoteRef, string sourceTree)
|
|
{
|
|
var res = new PBXReferenceProxyData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXReferenceProxy");
|
|
res.SetPropertyString("path", path);
|
|
res.SetPropertyString("fileType", fileType);
|
|
res.SetPropertyString("remoteRef", remoteRef);
|
|
res.SetPropertyString("sourceTree", sourceTree);
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXTargetDependencyData : PBXObjectData
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"target/*",
|
|
"targetProxy/*"
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public static PBXTargetDependencyData Create(string target, string targetProxy)
|
|
{
|
|
var res = new PBXTargetDependencyData();
|
|
res.guid = PBXGUID.Generate();
|
|
res.SetPropertyString("isa", "PBXTargetDependency");
|
|
res.SetPropertyString("target", target);
|
|
res.SetPropertyString("targetProxy", targetProxy);
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class ProjectReference
|
|
{
|
|
public string group; // guid
|
|
public string projectRef; // guid
|
|
|
|
public static ProjectReference Create(string group, string projectRef)
|
|
{
|
|
var res = new ProjectReference();
|
|
res.group = group;
|
|
res.projectRef = projectRef;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
internal class PBXProjectObjectData : PBXObjectData
|
|
{
|
|
private static PropertyCommentChecker checkerData = new PropertyCommentChecker(new string[]{
|
|
"buildConfigurationList/*",
|
|
"mainGroup/*",
|
|
"projectReferences/*/ProductGroup/*",
|
|
"projectReferences/*/ProjectRef/*",
|
|
"targets/*"
|
|
});
|
|
|
|
internal override PropertyCommentChecker checker { get { return checkerData; } }
|
|
|
|
public List<ProjectReference> projectReferences = new List<ProjectReference>();
|
|
public string mainGroup { get { return GetPropertyString("mainGroup"); } }
|
|
public List<string> targets = new List<string>();
|
|
public List<string> knownAssetTags = new List<string>();
|
|
public List<string> knownRegions = new List<string>();
|
|
public string buildConfigList;
|
|
// the name of the entitlements file required for some capabilities.
|
|
public string entitlementsFile;
|
|
public List<PBXCapabilityType.TargetCapabilityPair> capabilities = new List<PBXCapabilityType.TargetCapabilityPair>();
|
|
public Dictionary<string, string> teamIDs = new Dictionary<string, string>();
|
|
|
|
|
|
public void AddReference(string productGroup, string projectRef)
|
|
{
|
|
projectReferences.Add(ProjectReference.Create(productGroup, projectRef));
|
|
}
|
|
|
|
public override void UpdateProps()
|
|
{
|
|
m_Properties.values.Remove("projectReferences");
|
|
if (projectReferences.Count > 0)
|
|
{
|
|
var array = m_Properties.CreateArray("projectReferences");
|
|
foreach (var value in projectReferences)
|
|
{
|
|
var dict = array.AddDict();
|
|
dict.SetString("ProductGroup", value.group);
|
|
dict.SetString("ProjectRef", value.projectRef);
|
|
}
|
|
};
|
|
SetPropertyList("targets", targets);
|
|
SetPropertyList("knownRegions", knownRegions);
|
|
SetPropertyString("buildConfigurationList", buildConfigList);
|
|
if (knownAssetTags.Count > 0)
|
|
{
|
|
PBXElementDict attrs;
|
|
if (m_Properties.Contains("attributes"))
|
|
attrs = m_Properties["attributes"].AsDict();
|
|
else
|
|
attrs = m_Properties.CreateDict("attributes");
|
|
var tags = attrs.CreateArray("knownAssetTags");
|
|
foreach (var tag in knownAssetTags)
|
|
tags.AddString(tag);
|
|
}
|
|
|
|
// Enable the capabilities.
|
|
foreach (var cap in capabilities)
|
|
{
|
|
var attrs = m_Properties.Contains("attributes") ? m_Properties["attributes"].AsDict() : m_Properties.CreateDict("attributes");
|
|
var targAttr = attrs.Contains("TargetAttributes") ? attrs["TargetAttributes"].AsDict() : attrs.CreateDict("TargetAttributes");
|
|
var target = targAttr.Contains(cap.targetGuid) ? targAttr[cap.targetGuid].AsDict() : targAttr.CreateDict(cap.targetGuid);
|
|
var sysCap = target.Contains("SystemCapabilities") ? target["SystemCapabilities"].AsDict() : target.CreateDict("SystemCapabilities");
|
|
|
|
var capabilityId = cap.capability.id;
|
|
var currentCapability = sysCap.Contains(capabilityId) ? sysCap[capabilityId].AsDict() : sysCap.CreateDict(capabilityId);
|
|
currentCapability.SetString("enabled", "1");
|
|
}
|
|
|
|
// Set the team id
|
|
foreach (KeyValuePair<string, string> teamID in teamIDs)
|
|
{
|
|
var attrs = m_Properties.Contains("attributes") ? m_Properties["attributes"].AsDict() : m_Properties.CreateDict("attributes");
|
|
var targAttr = attrs.Contains("TargetAttributes") ? attrs["TargetAttributes"].AsDict() : attrs.CreateDict("TargetAttributes");
|
|
var target = targAttr.Contains(teamID.Key) ? targAttr[teamID.Key].AsDict() : targAttr.CreateDict(teamID.Key);
|
|
target.SetString("DevelopmentTeam", teamID.Value);
|
|
}
|
|
}
|
|
|
|
public override void UpdateVars()
|
|
{
|
|
projectReferences = new List<ProjectReference>();
|
|
if (m_Properties.Contains("projectReferences"))
|
|
{
|
|
var el = m_Properties["projectReferences"].AsArray();
|
|
foreach (var value in el.values)
|
|
{
|
|
PBXElementDict dict = value.AsDict();
|
|
if (dict.Contains("ProductGroup") && dict.Contains("ProjectRef"))
|
|
{
|
|
string group = dict["ProductGroup"].AsString();
|
|
string projectRef = dict["ProjectRef"].AsString();
|
|
projectReferences.Add(ProjectReference.Create(group, projectRef));
|
|
}
|
|
}
|
|
}
|
|
targets = GetPropertyList("targets");
|
|
knownRegions = GetPropertyList("knownRegions");
|
|
buildConfigList = GetPropertyString("buildConfigurationList");
|
|
|
|
// update knownAssetTags
|
|
knownAssetTags = new List<string>();
|
|
if (m_Properties.Contains("attributes"))
|
|
{
|
|
var el = m_Properties["attributes"].AsDict();
|
|
if (el.Contains("knownAssetTags"))
|
|
{
|
|
var tags = el["knownAssetTags"].AsArray();
|
|
foreach (var tag in tags.values)
|
|
knownAssetTags.Add(tag.AsString());
|
|
}
|
|
|
|
capabilities = new List<PBXCapabilityType.TargetCapabilityPair>();
|
|
teamIDs = new Dictionary<string, string>();
|
|
|
|
if (el.Contains("TargetAttributes"))
|
|
{
|
|
var targetAttr = el["TargetAttributes"].AsDict();
|
|
foreach (var attr in targetAttr.values)
|
|
{
|
|
if (attr.Key == "DevelopmentTeam")
|
|
{
|
|
teamIDs.Add(attr.Key, attr.Value.AsString());
|
|
}
|
|
|
|
if (attr.Key == "SystemCapabilities")
|
|
{
|
|
var caps = el["SystemCapabilities"].AsDict();
|
|
foreach (var cap in caps.values)
|
|
capabilities.Add(new PBXCapabilityType.TargetCapabilityPair(attr.Key, PBXCapabilityType.StringToPBXCapabilityType(cap.Value.AsString())));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace UnityModule.iOS.Xcode
|
|
|