miduo_client/Assets/Scripts/Editor/XUPorter/XCProject.cs

890 lines
27 KiB
C#

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
namespace UnityEditor.XCodeEditor
{
public partial class XCProject : System.IDisposable
{
private PBXDictionary _datastore;
public PBXDictionary _objects;
//private PBXDictionary _configurations;
private PBXGroup _rootGroup;
//private string _defaultConfigurationName;
private string _rootObjectKey;
public string projectRootPath { get; private set; }
private FileInfo projectFileInfo;
public string filePath { get; private set; }
//private string sourcePathRoot;
private bool modified = false;
#region Data
// Objects
private PBXSortedDictionary<PBXBuildFile> _buildFiles;
private PBXSortedDictionary<PBXGroup> _groups;
private PBXSortedDictionary<PBXFileReference> _fileReferences;
private PBXDictionary<PBXNativeTarget> _nativeTargets;
private PBXDictionary<PBXFrameworksBuildPhase> _frameworkBuildPhases;
private PBXDictionary<PBXResourcesBuildPhase> _resourcesBuildPhases;
private PBXDictionary<PBXShellScriptBuildPhase> _shellScriptBuildPhases;
private PBXDictionary<PBXSourcesBuildPhase> _sourcesBuildPhases;
private PBXDictionary<PBXCopyFilesBuildPhase> _copyBuildPhases;
private PBXDictionary<PBXVariantGroup> _variantGroups;
private PBXDictionary<XCBuildConfiguration> _buildConfigurations;
private PBXSortedDictionary<XCConfigurationList> _configurationLists;
private PBXProject _project;
#endregion
#region Constructor
public XCProject()
{
}
public XCProject( string filePath ) : this()
{
if( !System.IO.Directory.Exists( filePath ) ) {
Debug.LogWarning( "XCode project path does not exist: " + filePath );
return;
}
if( filePath.EndsWith( ".xcodeproj" ) ) {
Debug.Log( "Opening project " + filePath );
this.projectRootPath = Path.GetDirectoryName( filePath );
this.filePath = filePath;
} else {
Debug.Log( "Looking for xcodeproj files in " + filePath );
string[] projects = System.IO.Directory.GetDirectories( filePath, "*.xcodeproj" );
if( projects.Length == 0 ) {
Debug.LogWarning( "Error: missing xcodeproj file" );
return;
}
this.projectRootPath = filePath;
//if the path is relative to the project, we need to make it absolute
if (!System.IO.Path.IsPathRooted(projectRootPath))
projectRootPath = Application.dataPath.Replace("Assets", "") + projectRootPath;
//Debug.Log ("projectRootPath adjusted to " + projectRootPath);
this.filePath = projects[ 0 ];
}
projectFileInfo = new FileInfo( Path.Combine( this.filePath, "project.pbxproj" ) );
string contents = projectFileInfo.OpenText().ReadToEnd();
PBXParser parser = new PBXParser();
_datastore = parser.Decode( contents );
if( _datastore == null ) {
throw new System.Exception( "Project file not found at file path " + filePath );
}
if( !_datastore.ContainsKey( "objects" ) ) {
Debug.Log( "Errore " + _datastore.Count );
return;
}
_objects = (PBXDictionary)_datastore["objects"];
modified = false;
_rootObjectKey = (string)_datastore["rootObject"];
if( !string.IsNullOrEmpty( _rootObjectKey ) ) {
_project = new PBXProject( _rootObjectKey, (PBXDictionary)_objects[ _rootObjectKey ] );
_rootGroup = new PBXGroup( _rootObjectKey, (PBXDictionary)_objects[ _project.mainGroupID ] );
}
else {
Debug.LogWarning( "error: project has no root object" );
_project = null;
_rootGroup = null;
}
}
#endregion
#region Properties
public PBXProject project {
get {
return _project;
}
}
public PBXGroup rootGroup {
get {
return _rootGroup;
}
}
public PBXSortedDictionary<PBXBuildFile> buildFiles {
get {
if( _buildFiles == null ) {
_buildFiles = new PBXSortedDictionary<PBXBuildFile>( _objects );
}
return _buildFiles;
}
}
public PBXSortedDictionary<PBXGroup> groups {
get {
if( _groups == null ) {
_groups = new PBXSortedDictionary<PBXGroup>( _objects );
}
return _groups;
}
}
public PBXSortedDictionary<PBXFileReference> fileReferences {
get {
if( _fileReferences == null ) {
_fileReferences = new PBXSortedDictionary<PBXFileReference>( _objects );
}
return _fileReferences;
}
}
public PBXDictionary<PBXVariantGroup> variantGroups {
get {
if( _variantGroups == null ) {
_variantGroups = new PBXDictionary<PBXVariantGroup>( _objects );
}
return _variantGroups;
}
}
public PBXDictionary<PBXNativeTarget> nativeTargets {
get {
if( _nativeTargets == null ) {
_nativeTargets = new PBXDictionary<PBXNativeTarget>( _objects );
}
return _nativeTargets;
}
}
public PBXDictionary<XCBuildConfiguration> buildConfigurations {
get {
if( _buildConfigurations == null ) {
_buildConfigurations = new PBXDictionary<XCBuildConfiguration>( _objects );
}
return _buildConfigurations;
}
}
public PBXSortedDictionary<XCConfigurationList> configurationLists {
get {
if( _configurationLists == null ) {
_configurationLists = new PBXSortedDictionary<XCConfigurationList>( _objects );
}
return _configurationLists;
}
}
public PBXDictionary<PBXFrameworksBuildPhase> frameworkBuildPhases {
get {
if( _frameworkBuildPhases == null ) {
_frameworkBuildPhases = new PBXDictionary<PBXFrameworksBuildPhase>( _objects );
}
return _frameworkBuildPhases;
}
}
public PBXDictionary<PBXResourcesBuildPhase> resourcesBuildPhases {
get {
if( _resourcesBuildPhases == null ) {
_resourcesBuildPhases = new PBXDictionary<PBXResourcesBuildPhase>( _objects );
}
return _resourcesBuildPhases;
}
}
public PBXDictionary<PBXShellScriptBuildPhase> shellScriptBuildPhases {
get {
if( _shellScriptBuildPhases == null ) {
_shellScriptBuildPhases = new PBXDictionary<PBXShellScriptBuildPhase>( _objects );
}
return _shellScriptBuildPhases;
}
}
public PBXDictionary<PBXSourcesBuildPhase> sourcesBuildPhases {
get {
if( _sourcesBuildPhases == null ) {
_sourcesBuildPhases = new PBXDictionary<PBXSourcesBuildPhase>( _objects );
}
return _sourcesBuildPhases;
}
}
public PBXDictionary<PBXCopyFilesBuildPhase> copyBuildPhases {
get {
if( _copyBuildPhases == null ) {
_copyBuildPhases = new PBXDictionary<PBXCopyFilesBuildPhase>( _objects );
}
return _copyBuildPhases;
}
}
#endregion
#region PBXMOD
public bool AddOtherCFlags( string flag )
{
return AddOtherCFlags( new PBXList( flag ) );
}
public bool AddOtherCFlags( PBXList flags )
{
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
buildConfig.Value.AddOtherCFlags( flags );
}
modified = true;
return modified;
}
public bool AddOtherLinkerFlagsWithForceLoad(string absoluteFilePath){
if (!File.Exists(absoluteFilePath)) {
return false;
}
AddOtherLinkerFlags ("-force_load");
System.Uri fileURI = new System.Uri( absoluteFilePath );
System.Uri rootURI = new System.Uri( ( projectRootPath + "/." ) );
string relativeFilePath = rootURI.MakeRelativeUri( fileURI ).ToString();
return AddOtherLinkerFlags (relativeFilePath);
}
public bool AddOtherLinkerFlags( string flag )
{
return AddOtherLinkerFlags( new PBXList( flag ) );
}
public bool AddOtherLinkerFlags( PBXList flags )
{
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
buildConfig.Value.AddOtherLinkerFlags( flags );
}
modified = true;
return modified;
}
public bool overwriteBuildSetting( string settingName, string newValue, string buildConfigName = "all") {
Debug.Log("overwriteBuildSetting " + settingName + " " + newValue + " " + buildConfigName);
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
//Debug.Log ("build config " + buildConfig);
XCBuildConfiguration b = buildConfig.Value;
if ( (string)b.data["name"] == buildConfigName || (string)buildConfigName == "all") {
//Debug.Log ("found " + b.data["name"] + " config");
buildConfig.Value.overwriteBuildSetting(settingName, newValue);
modified = true;
} else {
//Debug.LogWarning ("skipping " + buildConfigName + " config " + (string)b.data["name"]);
}
}
return modified;
}
public bool AddHeaderSearchPaths( string path )
{
return AddHeaderSearchPaths( new PBXList( path ) );
}
public bool AddHeaderSearchPaths( PBXList paths )
{
Debug.Log ("AddHeaderSearchPaths " + paths);
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
buildConfig.Value.AddHeaderSearchPaths( paths );
}
modified = true;
return modified;
}
public bool AddLibrarySearchPaths( string path )
{
return AddLibrarySearchPaths( new PBXList( path ) );
}
public bool AddLibrarySearchPaths( PBXList paths )
{
Debug.Log ("AddLibrarySearchPaths " + paths);
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
buildConfig.Value.AddLibrarySearchPaths( paths );
}
modified = true;
return modified;
}
public bool AddFrameworkSearchPaths( string path )
{
return AddFrameworkSearchPaths( new PBXList( path ) );
}
public bool AddFrameworkSearchPaths( PBXList paths )
{
foreach( KeyValuePair<string, XCBuildConfiguration> buildConfig in buildConfigurations ) {
buildConfig.Value.AddFrameworkSearchPaths( paths );
}
modified = true;
return modified;
}
public object GetObject( string guid )
{
return _objects[guid];
}
public PBXDictionary AddFile( string filePath, PBXGroup parent = null, string tree = "SOURCE_ROOT", bool createBuildFiles = true, bool weak = false )
{
//Debug.Log("AddFile " + filePath + ", " + parent + ", " + tree + ", " + (createBuildFiles? "TRUE":"FALSE") + ", " + (weak? "TRUE":"FALSE") );
PBXDictionary results = new PBXDictionary();
if (filePath == null) {
Debug.LogError ("AddFile called with null filePath");
return results;
}
string absPath = string.Empty;
if( Path.IsPathRooted( filePath ) ) {
Debug.Log( "Path is Rooted" );
absPath = filePath;
}
else if( tree.CompareTo( "SDKROOT" ) != 0) {
absPath = Path.Combine( Application.dataPath, filePath );
}
if( !( File.Exists( absPath ) || Directory.Exists( absPath ) ) && tree.CompareTo( "SDKROOT" ) != 0 ) {
Debug.Log( "Missing file: " + filePath );
return results;
}
else if( tree.CompareTo( "SOURCE_ROOT" ) == 0 ) {
Debug.Log( "Source Root File" );
System.Uri fileURI = new System.Uri( absPath );
System.Uri rootURI = new System.Uri( ( projectRootPath + "/." ) );
filePath = rootURI.MakeRelativeUri( fileURI ).ToString();
}
else if( tree.CompareTo("GROUP") == 0) {
Debug.Log( "Group File" );
filePath = System.IO.Path.GetFileName( filePath );
}
if( parent == null ) {
parent = _rootGroup;
}
//Check if there is already a file
PBXFileReference fileReference = GetFile( System.IO.Path.GetFileName( filePath ) );
if( fileReference != null ) {
Debug.Log("File already exists: " + filePath); //not a warning, because this is normal for most builds!
return null;
}
fileReference = new PBXFileReference( filePath, (TreeEnum)System.Enum.Parse( typeof(TreeEnum), tree ) );
parent.AddChild( fileReference );
fileReferences.Add( fileReference );
results.Add( fileReference.guid, fileReference );
//Create a build file for reference
if( !string.IsNullOrEmpty( fileReference.buildPhase ) && createBuildFiles ) {
switch( fileReference.buildPhase ) {
case "PBXFrameworksBuildPhase":
foreach( KeyValuePair<string, PBXFrameworksBuildPhase> currentObject in frameworkBuildPhases ) {
BuildAddFile(fileReference,currentObject,weak);
}
if ( !string.IsNullOrEmpty( absPath ) && ( tree.CompareTo( "SOURCE_ROOT" ) == 0 )) {
string libraryPath = Path.Combine( "$(SRCROOT)", Path.GetDirectoryName( filePath ) );
if (File.Exists(absPath)) {
this.AddLibrarySearchPaths( new PBXList( libraryPath ) );
} else {
this.AddFrameworkSearchPaths( new PBXList( libraryPath ) );
}
}
break;
case "PBXResourcesBuildPhase":
foreach( KeyValuePair<string, PBXResourcesBuildPhase> currentObject in resourcesBuildPhases ) {
Debug.Log( "Adding Resources Build File" );
BuildAddFile(fileReference,currentObject,weak);
}
break;
case "PBXShellScriptBuildPhase":
foreach( KeyValuePair<string, PBXShellScriptBuildPhase> currentObject in shellScriptBuildPhases ) {
Debug.Log( "Adding Script Build File" );
BuildAddFile(fileReference,currentObject,weak);
}
break;
case "PBXSourcesBuildPhase":
foreach( KeyValuePair<string, PBXSourcesBuildPhase> currentObject in sourcesBuildPhases ) {
Debug.Log( "Adding Source Build File" );
BuildAddFile(fileReference,currentObject,weak);
}
break;
case "PBXCopyFilesBuildPhase":
foreach( KeyValuePair<string, PBXCopyFilesBuildPhase> currentObject in copyBuildPhases ) {
Debug.Log( "Adding Copy Files Build Phase" );
BuildAddFile(fileReference,currentObject,weak);
}
break;
case null:
Debug.LogWarning( "File Not Supported: " + filePath );
break;
default:
Debug.LogWarning( "File Not Supported." );
return null;
}
}
return results;
}
public PBXNativeTarget GetNativeTarget( string name )
{
PBXNativeTarget naviTarget = null;
foreach( KeyValuePair<string, PBXNativeTarget> currentObject in nativeTargets ) {
string targetName = (string)currentObject.Value.data["name"];
if (targetName == name) {
naviTarget = currentObject.Value;
break;
}
}
return naviTarget;
}
public int GetBuildActionMask()
{
int buildActionMask = 0;
foreach( var currentObject in copyBuildPhases )
{
buildActionMask = (int)currentObject.Value.data["buildActionMask"];
break;
}
return buildActionMask;
}
public PBXCopyFilesBuildPhase AddEmbedFrameworkBuildPhase()
{
PBXCopyFilesBuildPhase phase = null;
PBXNativeTarget naviTarget = GetNativeTarget("Unity-iPhone");
if (naviTarget == null)
{
Debug.Log("Not found Correct NativeTarget.");
return phase;
}
//check if embed framework buildPhase exist
foreach( var currentObject in copyBuildPhases )
{
object nameObj = null;
if (currentObject.Value.data.TryGetValue("name", out nameObj))
{
string name = (string)nameObj;
if (name == "Embed Frameworks")
return currentObject.Value;
}
}
int buildActionMask = this.GetBuildActionMask();
phase = new PBXCopyFilesBuildPhase(buildActionMask);
var buildPhases = (ArrayList)naviTarget.data["buildPhases"];
buildPhases.Add(phase.guid);//add build phase
copyBuildPhases.Add(phase);
return phase;
}
public void AddEmbedFramework( string fileName)
{
Debug.Log( "Add Embed Framework: " + fileName );
//Check if there is already a file
PBXFileReference fileReference = GetFile( System.IO.Path.GetFileName( fileName ) );
if( fileReference == null ) {
Debug.Log("Embed Framework must added already: " + fileName);
return;
}
var embedPhase = this.AddEmbedFrameworkBuildPhase();
if (embedPhase == null)
{
Debug.Log("AddEmbedFrameworkBuildPhase Failed.");
return;
}
//create a build file
PBXBuildFile buildFile = new PBXBuildFile( fileReference );
buildFile.AddCodeSignOnCopy();
buildFiles.Add( buildFile );
embedPhase.AddBuildFile(buildFile);
}
private void BuildAddFile (PBXFileReference fileReference, KeyValuePair<string, PBXFrameworksBuildPhase> currentObject,bool weak)
{
PBXBuildFile buildFile = new PBXBuildFile( fileReference, weak );
buildFiles.Add( buildFile );
currentObject.Value.AddBuildFile( buildFile );
}
private void BuildAddFile (PBXFileReference fileReference, KeyValuePair<string, PBXResourcesBuildPhase> currentObject,bool weak)
{
PBXBuildFile buildFile = new PBXBuildFile( fileReference, weak );
buildFiles.Add( buildFile );
currentObject.Value.AddBuildFile( buildFile );
}
private void BuildAddFile (PBXFileReference fileReference, KeyValuePair<string, PBXShellScriptBuildPhase> currentObject,bool weak)
{
PBXBuildFile buildFile = new PBXBuildFile( fileReference, weak );
buildFiles.Add( buildFile );
currentObject.Value.AddBuildFile( buildFile );
}
private void BuildAddFile (PBXFileReference fileReference, KeyValuePair<string, PBXSourcesBuildPhase> currentObject,bool weak)
{
PBXBuildFile buildFile = new PBXBuildFile( fileReference, weak );
buildFiles.Add( buildFile );
currentObject.Value.AddBuildFile( buildFile );
}
private void BuildAddFile (PBXFileReference fileReference, KeyValuePair<string, PBXCopyFilesBuildPhase> currentObject,bool weak)
{
PBXBuildFile buildFile = new PBXBuildFile( fileReference, weak );
buildFiles.Add( buildFile );
currentObject.Value.AddBuildFile( buildFile );
}
public bool AddFolder( string folderPath, PBXGroup parent = null, string[] exclude = null, bool recursive = true, bool createBuildFile = true )
{
Debug.Log("Folder PATH: "+folderPath);
if( !Directory.Exists( folderPath ) ){
Debug.Log("Directory doesn't exist?");
return false;
}
if (folderPath.EndsWith(".lproj")){
Debug.Log("Ended with .lproj");
return AddLocFolder(folderPath, parent, exclude, createBuildFile);
}
DirectoryInfo sourceDirectoryInfo = new DirectoryInfo( folderPath );
if( exclude == null ){
Debug.Log("Exclude was null");
exclude = new string[] {};
}
if( parent == null ){
Debug.Log("Parent was null");
parent = rootGroup;
}
// Create group
PBXGroup newGroup = GetGroup( sourceDirectoryInfo.Name, null /*relative path*/, parent );
Debug.Log("New Group created");
foreach( string directory in Directory.GetDirectories( folderPath ) ) {
Debug.Log( "DIR: " + directory );
if( directory.EndsWith( ".bundle" ) ) {
// Treat it like a file and copy even if not recursive
// TODO also for .xcdatamodeld?
Debug.LogWarning( "This is a special folder: " + directory );
AddFile( directory, newGroup, "SOURCE_ROOT", createBuildFile );
continue;
}
if( recursive ) {
Debug.Log( "recursive" );
AddFolder( directory, newGroup, exclude, recursive, createBuildFile );
}
}
// Adding files.
string regexExclude = string.Format( @"{0}", string.Join( "|", exclude ) );
foreach( string file in Directory.GetFiles( folderPath ) ) {
if( Regex.IsMatch( file, regexExclude ) ) {
continue;
}
Debug.Log("Adding Files for Folder");
AddFile( file, newGroup, "SOURCE_ROOT", createBuildFile );
}
modified = true;
return modified;
}
// We support neither recursing into nor bundles contained inside loc folders
public bool AddLocFolder( string folderPath, PBXGroup parent = null, string[] exclude = null, bool createBuildFile = true)
{
DirectoryInfo sourceDirectoryInfo = new DirectoryInfo( folderPath );
if( exclude == null )
exclude = new string[] {};
if( parent == null )
parent = rootGroup;
// Create group as needed
System.Uri projectFolderURI = new System.Uri( projectFileInfo.DirectoryName );
System.Uri locFolderURI = new System.Uri( folderPath );
var relativePath = projectFolderURI.MakeRelativeUri( locFolderURI ).ToString();
PBXGroup newGroup = GetGroup( sourceDirectoryInfo.Name, relativePath, parent );
// Add loc region to project
string nom = sourceDirectoryInfo.Name;
string region = nom.Substring(0, nom.Length - ".lproj".Length);
project.AddRegion(region);
// Adding files.
string regexExclude = string.Format( @"{0}", string.Join( "|", exclude ) );
foreach( string file in Directory.GetFiles( folderPath ) ) {
if( Regex.IsMatch( file, regexExclude ) ) {
continue;
}
// Add a variant group for the language as well
var variant = new PBXVariantGroup(System.IO.Path.GetFileName( file ), null, "GROUP");
variantGroups.Add(variant);
// The group gets a reference to the variant, not to the file itself
newGroup.AddChild(variant);
AddFile( file, variant, "GROUP", createBuildFile );
}
modified = true;
return modified;
}
#endregion
#region Getters
public PBXFileReference GetFile( string name )
{
if( string.IsNullOrEmpty( name ) ) {
return null;
}
foreach( KeyValuePair<string, PBXFileReference> current in fileReferences ) {
if( !string.IsNullOrEmpty( current.Value.name ) && current.Value.name.CompareTo( name ) == 0 ) {
return current.Value;
}
}
return null;
}
public PBXGroup GetGroup( string name, string path = null, PBXGroup parent = null )
{
if( string.IsNullOrEmpty( name ) )
return null;
if( parent == null ) parent = rootGroup;
foreach( KeyValuePair<string, PBXGroup> current in groups ) {
if( string.IsNullOrEmpty( current.Value.name ) ) {
if( current.Value.path.CompareTo( name ) == 0 && parent.HasChild( current.Key ) ) {
return current.Value;
}
} else if( current.Value.name.CompareTo( name ) == 0 && parent.HasChild( current.Key ) ) {
return current.Value;
}
}
PBXGroup result = new PBXGroup( name, path );
groups.Add( result );
parent.AddChild( result );
modified = true;
return result;
}
#endregion
#region Mods
public void ApplyMod( string pbxmod )
{
XCMod mod = new XCMod( pbxmod );
foreach(var lib in mod.libs){
Debug.Log("Library: "+lib);
}
ApplyMod( mod );
}
public void ApplyMod( XCMod mod )
{
PBXGroup modGroup = this.GetGroup( mod.group );
Debug.Log( "Adding libraries..." );
foreach( XCModFile libRef in mod.libs ) {
string completeLibPath = System.IO.Path.Combine( "usr/lib", libRef.filePath );
Debug.Log ("Adding library " + completeLibPath);
this.AddFile( completeLibPath, modGroup, "SDKROOT", true, libRef.isWeak );
}
Debug.Log( "Adding frameworks..." );
PBXGroup frameworkGroup = this.GetGroup( "Frameworks" );
foreach( string framework in mod.frameworks ) {
string[] filename = framework.Split( ':' );
bool isWeak = ( filename.Length > 1 ) ? true : false;
string completePath = System.IO.Path.Combine( "System/Library/Frameworks", filename[0] );
this.AddFile( completePath, frameworkGroup, "SDKROOT", true, isWeak );
}
Debug.Log( "Adding files..." );
foreach( string filePath in mod.files ) {
string absoluteFilePath = System.IO.Path.Combine( mod.path, filePath );
this.AddFile( absoluteFilePath, modGroup );
}
Debug.Log( "Adding embed binaries..." );
if (mod.embed_binaries != null)
{
//1. Add LD_RUNPATH_SEARCH_PATHS for embed framework
this.overwriteBuildSetting("LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks", "Release");
this.overwriteBuildSetting("LD_RUNPATH_SEARCH_PATHS", "$(inherited) @executable_path/Frameworks", "Debug");
foreach( string binary in mod.embed_binaries ) {
string absoluteFilePath = System.IO.Path.Combine( mod.path, binary );
this.AddEmbedFramework(absoluteFilePath);
}
}
Debug.Log( "Adding folders..." );
foreach( string folderPath in mod.folders ) {
string absoluteFolderPath = System.IO.Path.Combine( Application.dataPath, folderPath );
Debug.Log ("Adding folder " + absoluteFolderPath);
this.AddFolder( absoluteFolderPath, modGroup, (string[])mod.excludes.ToArray( typeof(string) ) );
}
Debug.Log( "Adding headerpaths..." );
foreach( string headerpath in mod.headerpaths ) {
if (headerpath.Contains("$(inherited)")) {
Debug.Log ("not prepending a path to " + headerpath);
this.AddHeaderSearchPaths( headerpath );
} else {
string absoluteHeaderPath = System.IO.Path.Combine( mod.path, headerpath );
this.AddHeaderSearchPaths( absoluteHeaderPath );
}
}
Debug.Log( "Adding compiler flags..." );
foreach( string flag in mod.compiler_flags ) {
this.AddOtherCFlags( flag );
}
Debug.Log( "Adding linker flags..." );
foreach( string flag in mod.linker_flags ) {
this.AddOtherLinkerFlags( flag );
}
Debug.Log ("Adding plist items...");
string plistPath = this.projectRootPath + "/Info.plist";
XCPlist plist = new XCPlist (plistPath);
plist.Process(mod.plist);
this.Consolidate();
}
#endregion
#region Savings
public void Consolidate()
{
PBXDictionary consolidated = new PBXDictionary();
consolidated.Append<PBXBuildFile>( this.buildFiles );//sort!
consolidated.Append<PBXCopyFilesBuildPhase>( this.copyBuildPhases );
consolidated.Append<PBXFileReference>( this.fileReferences );//sort!
consolidated.Append<PBXFrameworksBuildPhase>( this.frameworkBuildPhases );
consolidated.Append<PBXGroup>( this.groups );//sort!
consolidated.Append<PBXNativeTarget>( this.nativeTargets );
consolidated.Add( project.guid, project.data );//TODO this should be named PBXProject?
consolidated.Append<PBXResourcesBuildPhase>( this.resourcesBuildPhases );
consolidated.Append<PBXShellScriptBuildPhase>( this.shellScriptBuildPhases );
consolidated.Append<PBXSourcesBuildPhase>( this.sourcesBuildPhases );
consolidated.Append<PBXVariantGroup>( this.variantGroups );
consolidated.Append<XCBuildConfiguration>( this.buildConfigurations );
consolidated.Append<XCConfigurationList>( this.configurationLists );
_objects = consolidated;
consolidated = null;
}
public void Backup()
{
string backupPath = Path.Combine( this.filePath, "project.backup.pbxproj" );
// Delete previous backup file
if( File.Exists( backupPath ) )
File.Delete( backupPath );
// Backup original pbxproj file first
File.Copy( System.IO.Path.Combine( this.filePath, "project.pbxproj" ), backupPath );
}
private void DeleteExisting(string path)
{
// Delete old project file
if( File.Exists( path ))
File.Delete( path );
}
private void CreateNewProject(PBXDictionary result, string path)
{
PBXParser parser = new PBXParser();
StreamWriter saveFile = File.CreateText( path );
saveFile.Write( parser.Encode( result, true ) );
saveFile.Close();
}
/// <summary>
/// Saves a project after editing.
/// </summary>
public void Save()
{
PBXDictionary result = new PBXDictionary();
result.Add( "archiveVersion", 1 );
result.Add( "classes", new PBXDictionary() );
result.Add( "objectVersion", 46 );
Consolidate();
result.Add( "objects", _objects );
result.Add( "rootObject", _rootObjectKey );
string projectPath = Path.Combine( this.filePath, "project.pbxproj" );
// Delete old project file, in case of an IOException 'Sharing violation on path Error'
DeleteExisting(projectPath);
// Parse result object directly into file
CreateNewProject(result,projectPath);
}
/**
* Raw project data.
*/
public Dictionary<string, object> objects {
get {
return null;
}
}
#endregion
public void Dispose()
{
}
}
}