
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4430 8e941d3f-bd1b-0410-a28a-d453659cc2b4
767 lines
23 KiB
ObjectPascal
767 lines
23 KiB
ObjectPascal
unit xcodeproj;
|
|
{--------------------------------------------------------------------------------
|
|
* by Dmitry Boyarintsev - Oct 2014 *
|
|
* *
|
|
* license: free for use, but please leave a note to the origin of the library *
|
|
* *
|
|
* PBXcontainer unit is a library to read/write the pbx formatter file as a *
|
|
* whole The file structure is made to keep the reference in a complex objects *
|
|
* *
|
|
* Memory Management. *
|
|
* Cocoa is reference - counted library, thus the usage of an object *
|
|
* controlled natively by ref counting. *
|
|
* A bit trickier for pascal *
|
|
* Following rules are applied *
|
|
* * read-only property objects are freed by the host (obviously) *
|
|
* * other "freeing" operations are noted at "mmgr" comments *
|
|
* * any objects within key-value tables are freed *
|
|
* Alternative solution - implement ref counting! *
|
|
* *
|
|
* PBXShellScriptBuildPhase - the give script must be using MacOS line breaks *
|
|
* which are \n (#13). Using unix line breaks \r (#10) will cause issues *
|
|
* in Xcode. *
|
|
--------------------------------------------------------------------------------}
|
|
|
|
interface
|
|
|
|
{$ifdef fpc}{$mode delphi}{$endif}
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
typinfo, pbxcontainer;
|
|
|
|
type
|
|
{ XCBuildConfiguration }
|
|
|
|
XCBuildConfiguration = class(PBXObject)
|
|
private
|
|
fname : string;
|
|
fbuildSettings: TPBXKeyValue;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
published
|
|
property buildSettings : TPBXKeyValue read fbuildSettings;
|
|
property name: string read fname write fname;
|
|
end;
|
|
|
|
{ XCConfigurationList }
|
|
|
|
// mmgr: XCConfigurationList frees
|
|
// * content of buildConfigurations
|
|
XCConfigurationList = class(PBXObject)
|
|
private
|
|
fdefaultConfigurationIsVisible: string;
|
|
fdefaultConfigurationName: string;
|
|
fbuildConfigurations: TPBXObjectsList;
|
|
|
|
function GetConfigItem(i: integer): XCBuildConfiguration;
|
|
function GetCount: integer;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
function addConfig(const aname: string): XCBuildConfiguration;
|
|
function findConfig(const aname: string; aforce: Boolean = false): XCBuildConfiguration;
|
|
// Count and Items are just for convenience. MUST NOT BE in "published" section
|
|
property Count: integer read GetCount;
|
|
property Items[i: integer]: XCBuildConfiguration read GetConfigItem; default;
|
|
published
|
|
property buildConfigurations: TPBXObjectsList read fbuildConfigurations;
|
|
property defaultConfigurationIsVisible: string read fdefaultConfigurationIsVisible write fdefaultConfigurationIsVisible;
|
|
property defaultConfigurationName: string read fdefaultConfigurationName write fdefaultConfigurationName;
|
|
end;
|
|
|
|
{ PBXContainerItemProxy }
|
|
|
|
PBXContainerItemProxy = class(PBXObject)
|
|
private
|
|
FcontainerPortal : PBXObject;
|
|
fproxyType : string;
|
|
fremoteGlobalIDString: string;
|
|
fremoteInfo: string;
|
|
published
|
|
property containerPortal: PBXObject read fcontainerPortal write fcontainerPortal; // Object = 0AFA6EA519F60EFD004C8FD9 /* Project object */;
|
|
property proxyType: string read FproxyType write fproxyType;
|
|
property remoteGlobalIDString: string read fremoteGlobalIDString write fremoteGlobalIDString; //object = 0AFA6EAC19F60EFD004C8FD9;
|
|
property remoteInfo : string read fremoteInfo write fremoteInfo; // ttestGame;
|
|
end;
|
|
|
|
{ PBXFileReference }
|
|
|
|
// these files might not be physically present in for the project.
|
|
// i.e. a bundle .app file doesn't physically exists until it's actual "built" by the xcode
|
|
PBXFileReference = class(PBXObject)
|
|
private
|
|
FexplicitFileType: string;
|
|
FincludeInIndex: Boolean;
|
|
FlastKnownFileType: string;
|
|
Fname: string;
|
|
Fpath: string;
|
|
FsourceTree: string;
|
|
published
|
|
property explicitFileType: string read FexplicitFileType write FexplicitFileType;
|
|
property includeInIndex: Boolean read FincludeInIndex write FincludeInIndex;
|
|
property lastKnownFileType: string read flastKnownFileType write flastKnownFileType;
|
|
property name: string read Fname write Fname;
|
|
property path: string read Fpath write Fpath;
|
|
property sourceTree: string read FsourceTree write FsourceTree;
|
|
end;
|
|
|
|
{ PBXBuildFile }
|
|
|
|
PBXBuildFile = class(PBXObject)
|
|
private
|
|
fFileRef : PBXFileReference;
|
|
published
|
|
property fileRef : PBXFileReference read ffileRef write ffileRef; // obj
|
|
end;
|
|
|
|
{ PBXBuildPhase }
|
|
|
|
// mmgr: on free
|
|
// * content of files
|
|
PBXBuildPhase = class(PBXObject)
|
|
private
|
|
fbuildActionMask : Integer;
|
|
ffiles: TPBXObjectsList;
|
|
frunOnlyForDeploymentPostprocessing: Boolean;
|
|
fname: string;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
published
|
|
property buildActionMask: Integer read fbuildActionMask write fbuildActionMask;
|
|
property files: TPBXObjectsList read ffiles;
|
|
property name: string read fname write fname;
|
|
property runOnlyForDeploymentPostprocessing: Boolean read frunOnlyForDeploymentPostprocessing write frunOnlyForDeploymentPostprocessing;
|
|
end;
|
|
{ PBXFrameworksBuildPhase }
|
|
|
|
PBXFrameworksBuildPhase = class(PBXBuildPhase);
|
|
PBXResourcesBuildPhase = class(PBXBuildPhase);
|
|
PBXSourcesBuildPhase = class(PBXBuildPhase);
|
|
|
|
{ PBXShellScriptBuildPhase }
|
|
|
|
PBXShellScriptBuildPhase = class(PBXBuildPhase)
|
|
private
|
|
finputPaths: TPBXStringArray;
|
|
foutputPaths: TPBXStringArray;
|
|
fshellpath: string;
|
|
fshellScript: string;
|
|
fshowEnvVarsInLog: Boolean;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
published
|
|
property inputPaths: TPBXStringArray read finputPaths;
|
|
property outputPaths: TPBXStringArray read foutputPaths;
|
|
property shellPath: string read fshellpath write fshellPath;
|
|
property shellScript: string read fshellScript write fshellScript;
|
|
property showEnvVarsInLog: Boolean read fshowEnvVarsInLog write fshowEnvVarsInLog default true;
|
|
end;
|
|
|
|
{ PBXGroup }
|
|
|
|
// mmgt: PBXGroup owns children object (PBXGroup and PBXFileRefernece)
|
|
// and would free then on release;
|
|
// note, that PBXFileReference objects might be used in other places
|
|
PBXGroup = class(PBXObject)
|
|
private
|
|
fsourceTree : string;
|
|
fchildren: TPBXObjectsList;
|
|
fname: string;
|
|
fpath: string;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
function addSubGroup(const aname: string): PBXGroup;
|
|
function findGroup(const aname: string; aforce: Boolean = false): PBXGroup;
|
|
function findFileRefByPathName(const afilename: string): PBXFileReference;
|
|
published
|
|
property children: TPBXObjectsList read fchildren;
|
|
property name: string read fname write fname;
|
|
property path: string read fpath write fpath;
|
|
property sourceTree: string read fsourceTree write fsourceTree;
|
|
end;
|
|
|
|
PBXVariantGroup = class(PBXGroup);
|
|
|
|
{ PBXNativeTarget }
|
|
|
|
// mmgr: PBXNativeTarget
|
|
// * buildConfigurationList
|
|
// * contents of buildPhases
|
|
// * contents of buildRules
|
|
// * content of dependencies
|
|
PBXNativeTarget = class(PBXObject)
|
|
private
|
|
fbuildConfigurationList: XCConfigurationList;
|
|
fname : string;
|
|
fproductName : string;
|
|
fproductReference : PBXObject;
|
|
fproductType : string;
|
|
fbuildPhases : TPBXObjectsList;
|
|
fbuildRules : TPBXObjectsList;
|
|
fdependencies : TPBXObjectsList;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
published
|
|
property buildConfigurationList : XCConfigurationList read fbuildConfigurationList write fbuildConfigurationList; //= 0AFA6ED419F60F01004C8FD9 /* Build configuration list for PBXNativeTarget "ttestGame" */;
|
|
property buildPhases: TPBXObjectsList read fbuildPhases;
|
|
property buildRules: TPBXObjectsList read fbuildRules;
|
|
property dependencies: TPBXObjectsList read fdependencies;
|
|
property name: string read fname write fname;
|
|
property productName: string read fproductName write fproductName; // = ttestGame;
|
|
property productReference: PBXObject read fproductReference write fproductReference; // producut resulting file
|
|
property productType: string read fproductType write fproductType; // = "com.apple.product-type.application";
|
|
end;
|
|
|
|
{ PBXLegacyTarget }
|
|
|
|
PBXLegacyTarget = class(PBXObject)
|
|
private
|
|
fpassBuildSettingsInEnvironment : Boolean;
|
|
fbuildArgumentsString : string;
|
|
fbuildToolPath : string;
|
|
fbuildWorkingDirectory : string;
|
|
public
|
|
constructor Create; override;
|
|
published
|
|
property buildArgumentsString: string read fbuildArgumentsString write fbuildArgumentsString;
|
|
property buildToolPath: string read fbuildToolPath write fbuildToolPath;
|
|
property buildWorkingDirectory: string read fbuildWorkingDirectory write fbuildWorkingDirectory;
|
|
property passBuildSettingsInEnvironment: Boolean read fpassBuildSettingsInEnvironment write fpassBuildSettingsInEnvironment;
|
|
end;
|
|
|
|
{ PBXTargetDependency }
|
|
|
|
// mmgt:
|
|
// targetProxy - is freed
|
|
PBXTargetDependency = class(PBXObject)
|
|
private
|
|
ftargetProxy: PBXContainerItemProxy;
|
|
ftarget: PBXNativeTarget;
|
|
public
|
|
destructor Destroy; override;
|
|
published
|
|
property target : PBXNativeTarget read ftarget write ftarget;
|
|
property targetProxy: PBXContainerItemProxy read ftargetProxy write ftargetProxy; {* PBXContainerItemProxy *}
|
|
end;
|
|
|
|
{ PBXProject }
|
|
|
|
// mmgt: PBXProject frees the following property objects, if assigned:
|
|
// * mainGroup
|
|
// * buildConfigurationList
|
|
// * contents of targets
|
|
PBXProject = class(PBXObject)
|
|
private
|
|
fattributes : TPBXKeyValue;
|
|
fcompatibilityVersion : string;
|
|
fdevelopmentRegion : string;
|
|
fhasScannedForEncodings: Boolean;
|
|
fmainGroup: PBXGroup;
|
|
fknownRegions: TPBXStringArray;
|
|
fproductRefGroup: PBXGroup;
|
|
fprojectDirPath: string;
|
|
fprojectRoot : string;
|
|
ftargets: TPBXObjectsList;
|
|
fbuildConfigurationList: XCConfigurationList;
|
|
protected
|
|
class procedure _WriteEmpty(propnames: TStrings); override;
|
|
public
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
function addTarget(const aname: string): PBXNativeTarget;
|
|
published
|
|
property attributes: TPBXKeyValue read fattributes;
|
|
property buildConfigurationList: XCConfigurationList read fbuildConfigurationList write fbuildConfigurationList;
|
|
property compatibilityVersion: string read fcompatibilityVersion write fcompatibilityVersion;
|
|
property developmentRegion: string read fdevelopmentRegion write fdevelopmentRegion;
|
|
property hasScannedForEncodings: Boolean read fhasScannedForEncodings write fhasScannedForEncodings;
|
|
property knownRegions: TPBXStringArray read fknownRegions;
|
|
property mainGroup: PBXGroup read fmainGroup write fmainGroup;
|
|
property productRefGroup: PBXGroup read fproductRefGroup write fproductRefGroup;
|
|
property projectDirPath: string read fprojectDirPath write fprojectDirPath;
|
|
property projectRoot: string read fprojectRoot write fprojectRoot;
|
|
property targets: TPBXObjectsList read ftargets;
|
|
end;
|
|
|
|
function ProjectLoadFromStream(st: TStream; var prj: PBXProject): Boolean;
|
|
function ProjectLoadFromFile(const fn: string; var prj: PBXProject): Boolean;
|
|
|
|
// serializes a PBX project to the string, using PBXContainer structure
|
|
function ProjectWrite(prj: PBXProject): string;
|
|
|
|
// creates a minimum possible project
|
|
function ProjectCreateMin: PBXProject;
|
|
|
|
// creates main group and product groups
|
|
procedure ProjectDefaultGroups(prj: PBXProject);
|
|
|
|
// adds necessary flags for Xcode3.2 not to throw any warnings
|
|
procedure ProjectUpdateForXcode3_2(prj: PBXProject);
|
|
// creates a minimum project, defaults the structure and sets Xcode 3.2 compat flags
|
|
function ProjectCreate3_2: PBXProject;
|
|
|
|
function ProjectAddTarget(prj: PBXProject; const ATargetName: string): PBXNativeTarget;
|
|
// adds if doesn't exist
|
|
function ProjectForceTarget(prj: PBXProject; const ATargetName: string): PBXNativeTarget;
|
|
|
|
const
|
|
SCRIPT_RUNPATH = '/bin/sh';
|
|
SCRIPT_DEFAULT = '';
|
|
SCRIPT_DEFNAME = 'Run Script';
|
|
|
|
function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase;
|
|
|
|
const
|
|
//FILETYPE_SCRIPT = 'text.script.sh';
|
|
FILETYPE_EXEC = 'compiled.mach-o.executable';
|
|
FILETYPE_MACHO = FILETYPE_EXEC;
|
|
FILETYPE_BUNDLE = 'wrapper.application';
|
|
FILETYPE_PLIST = 'text.plist.xml';
|
|
FILETYPE_OBJC = 'sourcecode.c.objc';
|
|
|
|
function FileRefCreate(const afilename: string; const filetype: string = ''): PBXFileReference;
|
|
|
|
const
|
|
SRCTREE_ABSOLUTE = '<absolute>'; // path is absolute path
|
|
SRCTREE_GROUP = '<group>'; // path is relative to the parent group
|
|
SRCTREE_PRODUCT = 'BUILT_PRODUCTS_DIR'; // path is relative to the product build directory
|
|
SRCTREE_PROJECT = 'SOURCE_ROOT'; // path is relative for .xcodeproj directory location
|
|
SRCTREE_DEV = 'DEVELOPER_DIR'; // path is relative to developer dir
|
|
SRCTREE_SDK = 'SDKROOT'; // path is relative to selected SDK dir
|
|
|
|
function GroupCreate(const aname: string; const srcTree: string = SRCTREE_GROUP): PBXGroup;
|
|
//todo: need a rountine to update the path whenever the project is saved
|
|
function GroupCreateRoot(const projectfolder: string = ''): PBXGroup;
|
|
|
|
const
|
|
PRODTYPE_TOOL = 'com.apple.product-type.tool';
|
|
PRODTYPE_APP = 'com.apple.product-type.application'; // use it for OSX / iOS app targets
|
|
// prodtype of app type should have productReference to the result bundle! (.app) file
|
|
|
|
//
|
|
// PBXSourcesBuildPhase (sources) - is part of a PBXNativeTarget
|
|
// PBXNativeTarget - is part of Target
|
|
// PBXNativeTarget
|
|
//buildPhases = (
|
|
//0AA67B651A04929900CF0DD7 /* Sources */,
|
|
//0AA67B661A04929900CF0DD7 /* Frameworks */,
|
|
//0AA67B671A04929900CF0DD7 /* CopyFiles */,
|
|
//);
|
|
|
|
const
|
|
TARGET_IOS_8_0 = '8.0';
|
|
TARGET_IOS_8_1 = '8.1';
|
|
|
|
procedure ConfigIOS(cfg: XCBuildConfiguration; const targetiOS: string);
|
|
|
|
const
|
|
CFG_SDKROOT = 'SDKROOT';
|
|
CFG_IOSTRG = 'IPHONEOS_DEPLOYMENT_TARGET';
|
|
CFG_DEVICE = 'TARGET_DEVICE_FAMILY';
|
|
CFG_DEVICE_ALL = '1,2';
|
|
CFG_DEVICE_IPHONE = '1';
|
|
CFG_DEVICE_IPAD = '2';
|
|
|
|
implementation
|
|
|
|
procedure ConfigIOS(cfg: XCBuildConfiguration; const targetiOS: string);
|
|
begin
|
|
if not Assigned(cfg) then Exit;
|
|
cfg.buildSettings.AddStr(CFG_IOSTRG, targetiOS);
|
|
cfg.buildSettings.AddStr(CFG_SDKROOT, 'iphoneos');
|
|
cfg.buildSettings.AddStr(CFG_DEVICE, CFG_DEVICE_ALL);
|
|
end;
|
|
|
|
{ PBXLegacyTarget }
|
|
|
|
constructor PBXLegacyTarget.Create;
|
|
begin
|
|
inherited Create;
|
|
fpassBuildSettingsInEnvironment:=true;
|
|
end;
|
|
|
|
{ PBXTargetDependency }
|
|
|
|
destructor PBXTargetDependency.Destroy;
|
|
begin
|
|
ftargetProxy.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ PBXShellScriptBuildPhase }
|
|
|
|
constructor PBXShellScriptBuildPhase.Create;
|
|
begin
|
|
inherited Create;
|
|
finputPaths:=TPBXStringArray.Create;
|
|
foutputPaths:=TPBXStringArray.Create;
|
|
end;
|
|
|
|
destructor PBXShellScriptBuildPhase.Destroy;
|
|
begin
|
|
finputPaths.Free;
|
|
foutputPaths.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ PBXNativeTarget }
|
|
|
|
constructor PBXNativeTarget.Create;
|
|
begin
|
|
inherited Create;
|
|
fbuildPhases := TPBXObjectsList.Create(true);
|
|
fdependencies := TPBXObjectsList.Create(true);
|
|
fbuildRules := TPBXObjectsList.Create(true);
|
|
end;
|
|
|
|
destructor PBXNativeTarget.Destroy;
|
|
begin
|
|
fbuildConfigurationList.Free;
|
|
fbuildRules.Free;
|
|
fbuildPhases.Free;
|
|
fdependencies.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ PBXProject }
|
|
|
|
class procedure PBXProject._WriteEmpty(propnames: TStrings);
|
|
begin
|
|
propnames.Add('projectDirPath');
|
|
propnames.Add('projectRoot');
|
|
end;
|
|
|
|
constructor PBXProject.Create;
|
|
begin
|
|
inherited Create;
|
|
ftargets:=TPBXObjectsList.create(true);
|
|
fknownRegions:=TPBXStringArray.Create;
|
|
fattributes:=TPBXKeyValue.Create(true);
|
|
end;
|
|
|
|
destructor PBXProject.Destroy;
|
|
begin
|
|
fattributes.Free;
|
|
fknownRegions.Free;
|
|
ftargets.Free;
|
|
|
|
fmainGroup.Free;
|
|
fbuildConfigurationList.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function PBXProject.addTarget(const aname: string): PBXNativeTarget;
|
|
begin
|
|
Result:=PBXNativeTarget.Create;
|
|
targets.Add(Result);
|
|
Result._headerComment:=aname;
|
|
Result.name:=aname;
|
|
Result.productName:=aname;
|
|
end;
|
|
|
|
{ XCConfigurationList }
|
|
|
|
function XCConfigurationList.GetConfigItem(i: integer): XCBuildConfiguration;
|
|
begin
|
|
if (i<0) or (i>=fbuildConfigurations.Count) then Result:=nil
|
|
else Result:=XCBuildConfiguration(fbuildConfigurations[i]);
|
|
end;
|
|
|
|
function XCConfigurationList.GetCount: integer;
|
|
begin
|
|
Result:=fbuildConfigurations.Count;
|
|
end;
|
|
|
|
constructor XCConfigurationList.Create;
|
|
begin
|
|
inherited Create;
|
|
fbuildConfigurations:=TPBXObjectsList.Create(true);
|
|
end;
|
|
|
|
destructor XCConfigurationList.Destroy;
|
|
begin
|
|
fbuildConfigurations.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function XCConfigurationList.addConfig(const aname: string
|
|
): XCBuildConfiguration;
|
|
begin
|
|
Result:=XCBuildConfiguration.Create;
|
|
Result.name:=aname;
|
|
Result._headerComment:=aname;
|
|
fbuildConfigurations.Add(Result);
|
|
end;
|
|
|
|
function XCConfigurationList.findConfig(const aname: string; aforce: Boolean): XCBuildConfiguration;
|
|
var
|
|
i : integer;
|
|
begin
|
|
for i:=0 to fbuildConfigurations.Count-1 do begin
|
|
Result:=XCBuildConfiguration(fbuildConfigurations[i]);
|
|
if Result.name=aname then
|
|
Exit;
|
|
end;
|
|
if aforce then
|
|
Result:=addConfig(aname)
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
{ XCBuildConfiguration }
|
|
|
|
constructor XCBuildConfiguration.Create;
|
|
begin
|
|
inherited Create;
|
|
fbuildSettings:=TPBXKeyValue.Create(true);
|
|
end;
|
|
|
|
destructor XCBuildConfiguration.Destroy;
|
|
begin
|
|
fbuildSettings.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{ PBXGroup }
|
|
|
|
constructor PBXGroup.Create;
|
|
begin
|
|
inherited Create;
|
|
fchildren:=TPBXObjectsList.Create(true);
|
|
end;
|
|
|
|
destructor PBXGroup.Destroy;
|
|
begin
|
|
fchildren.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function PBXGroup.addSubGroup(const aname: string): PBXGroup;
|
|
begin
|
|
Result:=PBXGroup.Create;
|
|
fchildren.Add(Result);
|
|
Result.name:=aname;
|
|
Result._headerComment:=aname;
|
|
Result.sourceTree:=SRCTREE_GROUP;
|
|
end;
|
|
|
|
function PBXGroup.findGroup(const aname: string; aforce: Boolean = false): PBXGroup;
|
|
var
|
|
i : integer;
|
|
obj : TObject;
|
|
begin
|
|
for i:=0 to fchildren.Count-1 do begin
|
|
obj:=fchildren[i];
|
|
if (obj is PBXGroup) and (PBXGroup(obj).name=aname) then begin
|
|
Result:=PBXGroup(obj);
|
|
Exit;
|
|
end;
|
|
end;
|
|
if aforce then
|
|
Result:=addSubGroup(aname)
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
function PBXGroup.findFileRefByPathName(const afilename: string): PBXFileReference;
|
|
var
|
|
i : integer;
|
|
obj : TObject;
|
|
begin
|
|
for i:=0 to fchildren.Count-1 do begin
|
|
obj:=fchildren[i];
|
|
if (obj is PBXFileReference) and (PBXFileReference(obj).path=afilename) then begin
|
|
Result:=PBXFileReference(obj);
|
|
Exit;
|
|
end;
|
|
end;
|
|
Result:=nil;
|
|
end;
|
|
|
|
{ PBXBuildPhase }
|
|
|
|
constructor PBXBuildPhase.Create;
|
|
begin
|
|
inherited Create;
|
|
ffiles:=TPBXObjectsList.Create(true);
|
|
end;
|
|
|
|
destructor PBXBuildPhase.Destroy;
|
|
begin
|
|
ffiles.Free;
|
|
end;
|
|
|
|
function ProjectLoadFromStream(st: TStream; var prj: PBXProject): Boolean;
|
|
var
|
|
c : TPBXContainer;
|
|
info : TPBXFileInfo;
|
|
begin
|
|
prj:=nil;
|
|
c:= TPBXContainer.Create;
|
|
try
|
|
Result:=c.ReadFile(st, info);
|
|
if Result then begin
|
|
if not (info.rootObject is PBXProject) then begin
|
|
info.rootObject.Free;
|
|
end else begin
|
|
prj:=PBXProject(info.rootObject);
|
|
end;
|
|
end
|
|
finally
|
|
c.Free;
|
|
end;
|
|
end;
|
|
|
|
function ProjectLoadFromFile(const fn: string; var prj: PBXProject): Boolean;
|
|
var
|
|
fs :TFileStream;
|
|
begin
|
|
fs:=TFileStream.Create(fn, fmOpenRead or fmShareDenyNone);
|
|
try
|
|
Result:=ProjectLoadFromStream(fs, prj);
|
|
finally
|
|
fs.Free;
|
|
end;
|
|
end;
|
|
|
|
function ProjectWrite(prj: PBXProject): string;
|
|
var
|
|
info : TPBXFileInfo;
|
|
begin
|
|
info.archiveVersion:='1';
|
|
info.objectVersion:='46';
|
|
info.rootObject:=prj;
|
|
Result:=PBXWriteContainer(info);
|
|
end;
|
|
|
|
function ProjectCreateMin: PBXProject;
|
|
var
|
|
p : PBXProject;
|
|
cfg : XCBuildConfiguration;
|
|
begin
|
|
// requirements:
|
|
// * at least one build configuration
|
|
p := PBXProject.Create;
|
|
p._headerComment:='Project object';
|
|
|
|
p.buildConfigurationList:=XCConfigurationList.Create;
|
|
p.buildConfigurationList._headerComment:='Build configuration list for PBXProject';
|
|
p.buildConfigurationList.defaultConfigurationIsVisible:='0';
|
|
|
|
cfg:=p.buildConfigurationList.addConfig('Debug');
|
|
cfg:=p.buildConfigurationList.addConfig('Release');
|
|
// default name must be present
|
|
p.buildConfigurationList.defaultConfigurationName:='Release';
|
|
Result:=p;
|
|
end;
|
|
|
|
procedure ProjectDefaultGroups(prj: PBXProject);
|
|
var
|
|
prd : PBXGroup;
|
|
begin
|
|
if not Assigned(prj) then Exit;
|
|
if not Assigned(prj.mainGroup) then
|
|
prj.mainGroup:=GroupCreateRoot;
|
|
|
|
if not Assigned(prj.productRefGroup) then begin
|
|
prd:=prj.mainGroup.findGroup('Products');
|
|
if not Assigned(prd) then
|
|
prd:=prj.mainGroup.addSubGroup('Products');
|
|
prj.productRefGroup:=prd;
|
|
end;
|
|
end;
|
|
|
|
procedure ProjectUpdateForXcode3_2(prj: PBXProject);
|
|
begin
|
|
if not Assigned(prj) then Exit;
|
|
// without the attribute Xcode complains aboutt updating settings
|
|
prj.attributes.AddStr('LastUpgradeCheck','0600');
|
|
prj.compatibilityVersion:='Xcode 3.2';
|
|
end;
|
|
|
|
function ProjectCreate3_2: PBXProject;
|
|
begin
|
|
Result:=ProjectCreateMin;
|
|
ProjectDefaultGroups(Result);
|
|
ProjectUpdateForXcode3_2(Result);
|
|
end;
|
|
|
|
function ProjectAddTarget(prj: PBXProject; const ATargetName: string): PBXNativeTarget;
|
|
begin
|
|
Result:=nil;
|
|
if not Assigned(prj) then Exit;
|
|
Result:=prj.addTarget(ATargetName);
|
|
end;
|
|
|
|
function ProjectForceTarget(prj: PBXProject; const ATargetName: string): PBXNativeTarget;
|
|
var
|
|
i : integer;
|
|
begin
|
|
for i:=0 to prj.targets.Count-1 do begin
|
|
Result:=PBXNativeTarget(prj.targets[i]);
|
|
if Result.name=ATargetName then
|
|
Exit;
|
|
end;
|
|
Result:=ProjectAddTarget(prj, ATargetName);
|
|
end;
|
|
|
|
function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase;
|
|
begin
|
|
Result:=PBXShellScriptBuildPhase.Create;
|
|
Result.name:=SCRIPT_DEFNAME;
|
|
Result._headerComment:=SCRIPT_DEFNAME;
|
|
Result.shellScript:=SCRIPT_DEFAULT;
|
|
Result.shellPath:=SCRIPT_RUNPATH;
|
|
atarget.buildPhases.Add(Result);
|
|
end;
|
|
|
|
function FileRefCreate(const afilename: string; const filetype: string ): PBXFileReference;
|
|
begin
|
|
Result:=PBXFileReference.Create;
|
|
Result.path:=afilename;
|
|
Result._headerComment:=afilename;
|
|
Result.explicitFileType:=FILETYPE_EXEC;
|
|
end;
|
|
|
|
function GroupCreate(const aname, srcTree: string): PBXGroup;
|
|
begin
|
|
Result:=PBXGroup.Create;
|
|
Result.name:=aname;
|
|
Result.sourceTree:=srcTree;
|
|
Result._headerComment:=aname;
|
|
end;
|
|
|
|
function GroupCreateRoot(const projectfolder: string): PBXGroup;
|
|
begin
|
|
Result:=GroupCreate('', SRCTREE_GROUP);
|
|
Result.path:=projectfolder;
|
|
Result._headerComment:=projectfolder;
|
|
end;
|
|
|
|
initialization
|
|
PBXRegisterClass(PBXBuildFile);
|
|
PBXRegisterClass(PBXContainerItemProxy);
|
|
PBXRegisterClass(PBXFileReference);
|
|
PBXRegisterClass(PBXFrameworksBuildPhase);
|
|
PBXRegisterClass(PBXGroup);
|
|
PBXRegisterClass(PBXNativeTarget);
|
|
PBXRegisterClass(PBXProject);
|
|
PBXRegisterClass(PBXResourcesBuildPhase);
|
|
PBXRegisterClass(PBXSourcesBuildPhase);
|
|
PBXRegisterClass(PBXTargetDependency);
|
|
PBXRegisterClass(PBXVariantGroup);
|
|
PBXRegisterClass(XCBuildConfiguration);
|
|
PBXRegisterClass(XCConfigurationList);
|
|
PBXRegisterClass(PBXShellScriptBuildPhase);
|
|
|
|
end.
|
|
|
|
|
|
|