lazarus-ccr/components/iphonelazext/xcodeproject.pas
skalogryz 48d0e7d2f2 iphonelazext: started the extension
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1115 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2010-01-05 20:32:23 +00:00

950 lines
23 KiB
ObjectPascal

{
*****************************************************************************
* *
* This file is part of the iPhone Laz Extension *
* *
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
}
unit XCodeProject;
{$mode objfpc}{$H+}
// todo: re-write, using RTTI
{$TYPEINFO ON}
interface
uses
contnrs, Classes, SysUtils, TypInfo;
const
UTF8Mark = '// !$*UTF8*$!';
FileType_AppWrapper = 'wrapper.application';
FileType_Bundle = FileType_AppWrapper;
FileType_PList = 'text.plist.xml';
// sourceTree = BUILT_PRODUCTS_DIR
type
TXCodeObjectID = string[24];
TStringValues = class(TStringList);
{ TXCodeObject }
TXCodeObject = class(TObject)
private
fOwner : TXCodeObject;
fChild : TFPList;
fValues : TStringList;
fID : TXCodeObjectID;
protected
procedure AddObject(const AName: String; AObject: TXCodeObject);
function GetChild(i: Integer): TXCodeObject;
function GetCount: Integer;
procedure Clear;
function GetValue(const AName: String): String;
procedure SetValue(const AName: String; const AValue: String);
public
class function isa: ShortString; virtual; abstract;
constructor Create;
destructor Destroy; override;
property Child[i: integer]: TXCodeObject read GetChild;
property ChildCount: Integer read GetCount;
property Owner: TXCodeObject read fOwner;
property ID: TXCodeObjectID read fID;
property StrValue[const AName: String]: String read GetValue write SetValue;
function GetChildObject(const AName: String): TXCodeObject;
function GetObjectArray(const AName: String): TFPObjectList;
function GetStringArray(const AName: String): TStringList;
function GetStringValues(const AName: String): TStringValues;
end;
TXCodeObjectClass = class of TXCodeObject;
{ TPBXFileReference }
TPBXFileReference = class(TXCodeObject)
private
function GetExplicitFileType: string;
function GetPath: String;
function GetSourceTree: String;
procedure SetExplicitFileType(const AValue: string);
procedure SetPath(const AValue: String);
procedure SetSourceTree(const AValue: String);
public
class function isa: ShortString; override;
property explicitFileType: string read GetExplicitFileType write SetExplicitFileType;
property path : String read GetPath write SetPath;
property sourceTree: String read GetSourceTree write SetSourceTree;
end;
// 0A7E1DA610EAD478000D7855 /* iPhoneApp.app */ =
{isa = PBXFileReference;
explicitFileType = wrapper.application;
includeInIndex = 0;
path = iPhoneApp.app;
sourceTree = BUILT_PRODUCTS_DIR; }
{isa = PBXFileReference;
lastKnownFileType = text.plist.xml;
path = "iPhoneApp-Info.plist"; sourceTree = "<group>"; }
TXCodeBuildPhase = class(TXCodeObject);
{ TPBXShellScriptBuildPhase }
TPBXShellScriptBuildPhase = class(TXCodeBuildPhase)
private
function GetBuildMask: Integer;
function GetShellPath: string;
function GetShellScript: String;
procedure SetBuildMask(const AValue: Integer);
procedure SetShellPath(const AValue: string);
procedure SetShellScript(const AValue: String);
public
constructor Create;
class function isa: ShortString; override;
property BuildActionMask : Integer read GetBuildMask write SetBuildMask;
property ShellPath : string read GetShellPath write SetShellPath;
property ShellScript : String read GetShellScript write SetShellScript;
end;
{ TPBXBuildFile }
TPBXBuildFile = class(TXCodeObject)
public
fileRef : TPBXFileReference;
constructor Create;
destructor Destroy; override;
class function isa: ShortString; override;
end;
{ TXCBuildConfiguration }
TXCBuildConfiguration = class(TXCodeObject)
private
function GetName: String;
procedure SetName(const AValue: String);
function GetBuildSettings: TStringValues;
public
class function isa: ShortString; override;
constructor Create;
destructor Destroy; override;
property name: String read GetName write SetName;
property Settings: TStringValues read GetBuildSettings;
end;
{ TXCConfigurationList }
TXCConfigurationList = class(TXCodeObject)
private
fConfigs : TFPObjectList;
protected
function GetConfig(i: integer): TXCBuildConfiguration;
function GetCount: Integer;
function GetName: string;
procedure SetName(const AValue: string);
function GetVisible: Boolean;
procedure SetVisible(AVisible: Boolean);
public
class function isa: ShortString; override;
constructor Create;
destructor Destroy; override;
function AddList: TXCBuildConfiguration;
property Config[i: Integer] : TXCBuildConfiguration read GetConfig;
property ConfigCount: Integer read GetCount;
property defaultVisible: Boolean read GetVisible write SetVisible;
property defaulConfigName: string read GetName write SetName;
end;
{ TPBXNativeTarget }
TPBXNativeTarget = class(TXCodeObject)
private
fConfigList : TXCConfigurationList;
fRef : TPBXFileReference;
function GetName: String;
function GetProductFile: TPBXFileReference;
function GetProductName: String;
function GetProductType: String;
procedure SetName(const AValue: String);
procedure SetProductName(const AValue: String);
procedure SetProductType(const AValue: String);
function GetConfigList: TXCConfigurationList;
public
constructor Create;
class function isa: ShortString; override;
function AddBuildConfig: TXCBuildConfiguration;
function AddScriptPhase: TPBXShellScriptBuildPhase;
property name: String read GetName write SetName;
property productName: String read GetProductName write SetProductName;
property productType: String read GetProductType write SetProductType;
property productFile: TPBXFileReference read GetProductFile;
end;
{ TPBXProject }
TPBXProject = class(TXCodeObject)
private
fConfigList : TXCConfigurationList;
function GetDirPath: string;
function GetRoot: String;
procedure SetDirPath(const AValue: string);
procedure SetRoot(const AValue: String);
protected
function GetConfigList: TXCConfigurationList;
function GetTargets: TFPObjectList;
function GetVersion: String;
procedure SetVersion(const AVersion: string);
public
constructor Create;
class function isa: ShortString; override;
function AddTarget: TPBXNativeTarget;
function AddBuildConfig: TXCBuildConfiguration;
property DirPath: string read GetDirPath write SetDirPath;
property Root: String read GetRoot write SetRoot;
property compatibilityVersion: String read GetVersion write SetVersion;
end;
{ TPBXGroup }
TPBXGroup = class(TXCodeObject)
protected
function GetPath: String;
procedure SetPath(const APath: String);
function GetSourceTree: String;
procedure SetSourceTree(const ATree: String);
public
class function isa: ShortString; override;
property Path: String read GetPath write SetPath;
property sourceTree: String read GetSourceTree write SetSourceTree;
end;
procedure WritePBXProjFile(RootObject: TXCodeObject; Dst: TStream);
procedure WritePBXProjFile(RootObject: TXCodeObject; const FileName: String);
implementation
const
BoolVal : array[Boolean] of String = ('false', 'true');
function isQuotedStr(const s: string): Boolean;
begin
Result:=(length(s)>=2) and (s[1] = '"') and (s[length(s)]='"');
end;
function QuotedStr(const s: string): String;
begin
if isQuotedStr(s) then Result:=s
else Result:='"'+s+'"';
end;
function UnquoteStr(const s: string): String;
begin
if not isQuotedStr(s) then Result:=s
else Result:=Copy(s, 2, length(s)-2);
end;
function GetBoolValue(xobj: TXCodeObject; const AName: String): boolean;
begin
Result:=xobj.StrValue[AName]=BoolVal[True];
end;
procedure SetBoolValue(xobj: TXCodeObject; const AName: String; AValue: Boolean);
begin
xobj.StrValue[AName]:=BoolVal[AValue];
end;
{ TXCConfigurationList }
function TXCConfigurationList.GetName: string;
begin
Result:=StrValue['defaultConfigurationName'];
end;
procedure TXCConfigurationList.SetName(const AValue: string);
begin
StrValue['defaultConfigurationName']:=AValue;
end;
function TXCConfigurationList.GetVisible: Boolean;
begin
Result:=GetBoolValue(Self, 'defaultConfigurationIsVisible');
end;
procedure TXCConfigurationList.SetVisible(AVisible: Boolean);
begin
SetBoolValue(Self, 'defaultConfigurationIsVisible', AVisible);
end;
function TXCConfigurationList.GetConfig(i: integer): TXCBuildConfiguration;
begin
Result:=TXCBuildConfiguration(fConfigs[i]);
end;
function TXCConfigurationList.GetCount: Integer;
begin
Result:=fConfigs.Count;
end;
class function TXCConfigurationList.isa: ShortString;
begin
Result:='XCConfigurationList';
end;
constructor TXCConfigurationList.Create;
begin
inherited Create;
fConfigs:=GetObjectArray('buildConfigurations');
end;
destructor TXCConfigurationList.Destroy;
begin
inherited Destroy;
end;
function TXCConfigurationList.AddList: TXCBuildConfiguration;
begin
Result:=TXCBuildConfiguration.Create;
AddObject('', Result);
fConfigs.Add(Result);
end;
{ TXCBuildConfiguration }
constructor TXCBuildConfiguration.Create;
begin
inherited Create;
GetStringValues('buildSettings');
end;
destructor TXCBuildConfiguration.Destroy;
begin
inherited Destroy;
end;
function TXCBuildConfiguration.GetName: String;
begin
Result:=GetValue('name');
end;
procedure TXCBuildConfiguration.SetName(const AValue: String);
begin
SetValue('name', AValue);
end;
function TXCBuildConfiguration.getBuildSettings: TStringValues;
begin
Result:=GetStringValues('buildSettings');
end;
class function TXCBuildConfiguration.isa: ShortString;
begin
Result:='XCBuildConfiguration';
end;
{ TPBXGroup }
function TPBXGroup.GetPath: String;
begin
Result:=StrValue['Path'];
end;
procedure TPBXGroup.SetPath(const APath: String);
begin
StrValue['Path']:=APath;
end;
function TPBXGroup.GetSourceTree: String;
begin
Result:=StrValue['sourceTree'];
end;
procedure TPBXGroup.SetSourceTree(const ATree: String);
begin
StrValue['sourceTree']:=ATree;
end;
class function TPBXGroup.isa: ShortString;
begin
Result:='PBXGroup';
end;
{ TPBXFileReference }
class function TPBXFileReference.isa: ShortString;
begin
Result:='PBXFileReference';
end;
function TPBXFileReference.GetExplicitFileType: string;
begin
Result:=GetValue('explicitFileType');
end;
function TPBXFileReference.GetPath: String;
begin
Result:=GetValue('path');
end;
function TPBXFileReference.GetSourceTree: String;
begin
Result:=GetValue('sourceTree');
end;
procedure TPBXFileReference.SetExplicitFileType(const AValue: string);
begin
SetValue('explicitFileType', AValue);
end;
procedure TPBXFileReference.SetPath(const AValue: String);
begin
SetValue('path', AValue);
end;
procedure TPBXFileReference.SetSourceTree(const AValue: String);
begin
SetValue('sourceTree', AValue);
end;
{ TPBXBuildFile }
constructor TPBXBuildFile.Create;
begin
fileRef:=TPBXFileReference.Create;
end;
destructor TPBXBuildFile.Destroy;
begin
inherited Destroy;
end;
class function TPBXBuildFile.isa: ShortString;
begin
Result:='PBXBuildFile';
end;
{ TXCodeObject }
procedure TXCodeObject.AddObject(const AName: String; AObject: TXCodeObject);
begin
AObject.fOwner:=Self;
fChild.Add(AObject);
if AName<>'' then
fValues.AddObject(AName, AObject);
end;
function TXCodeObject.GetChild(i: Integer): TXCodeObject;
begin
Result:=TXCodeObject(fChild[i]);
end;
function TXCodeObject.GetCount: Integer;
begin
Result:=fChild.Count;
end;
procedure TXCodeObject.Clear;
var
i : integer;
begin
for i:=0 to fValues.Count-1 do begin
if Assigned(fValues.Objects[i]) and not (fValues.Objects[i] is TXCodeObject) then
fValues.Objects[i].Free;
end;
fValues.Clear;
for i:=0 to fChild.Count-1 do
TObject(fChild[i]).Free;
fChild.Clear;
end;
function TXCodeObject.GetValue(const AName: String): String;
begin
Result:=fValues.Values[AName];
end;
procedure TXCodeObject.SetValue(const AName, AValue: String);
begin
fValues.Values[AName]:=Avalue;
end;
constructor TXCodeObject.Create;
var
q : Qword;
begin
inherited;
fChild:=TFPList.Create;
fValues:=TStringList.Create;
Q:=PtrUInt(Self);
fID:=hexStr(q, 24);
end;
destructor TXCodeObject.Destroy;
begin
Clear;
fChild.Free;
fValues.Free;
inherited Destroy;
end;
function TXCodeObject.GetChildObject(const AName: String): TXCodeObject;
var
i : integer;
begin
Result:=nil;
i:=fValues.IndexOfName(AName);
if i>=0 then
if fValues.Objects[i] is TXCodeObject then
Result:=TXCodeObject(fValues.Objects[i]);
end;
function TXCodeObject.GetObjectArray(const AName: String): TFPObjectList;
var
i : integer;
begin
i:=fValues.IndexOfName(AName);
if i<0 then begin
Result:=TFPObjectList.Create(false);
fValues.AddObject(AName, Result);
end else begin
if not (fValues.Objects[i] is TFPObjectList) then
Result:=nil
else
Result:= TFPObjectList(fValues.Objects[i]);
end;
end;
function TXCodeObject.GetStringArray(const AName: String): TStringList;
var
i : integer;
begin
i:=fValues.IndexOfName(AName);
if i<0 then begin
Result:=TStringList.Create;
fValues.AddObject(AName, Result);
end else begin
if not (fValues.Objects[i] is TStringList) then
Result:=nil
else
Result:= TStringList(fValues.Objects[i]);
end;
end;
function TXCodeObject.GetStringValues(const AName: String): TStringValues;
var
i : integer;
begin
i:=fValues.IndexOfName(AName);
if i<0 then begin
Result:=TStringValues.Create;
fValues.Values[AName]:='?';
i:=fValues.IndexOfName(AName);
fValues.Objects[i]:=Result;
//i:=fValues.AddObject(AName + ' = ', Result);
end else begin
if not (fValues.Objects[i] is TStringValues) then
Result:=nil
else
Result:= TStringValues(fValues.Objects[i]);
end;
end;
type
{ TPBXWriter }
TPBXWriter = class(TObject)
private
fDst : TStream;
fPrefix : String;
fIndent : String;
protected
procedure WriteItems(data:TObject;arg:pointer);
public
constructor Create(Dst: TStream);
destructor Destroy; override;
procedure Indent;
procedure Unindent;
procedure WriteLn(const utf8: AnsiString);
end;
{ TPBXWriter }
procedure TPBXWriter.WriteItems(data: TObject; arg: pointer);
var
list : TFPList;
i : Integer;
j : Integer;
k : Integer;
xobj : TXCodeObject;
vobj : TObject;
sublist : TFPObjectList;
st : TStringList;
prefix : String;
begin
list:=TFPList(data);
if not Assigned(list) or (list.Count=0) then Exit;
for i:=0 to list.Count-1 do begin
xobj:=TXCodeObject(list[i]);
Self.WriteLn( xobj.ID + ' = {');
Self.Indent;
Self.Writeln('isa = ' + xobj.isa+';');
for j:=0 to xobj.fValues.Count - 1 do begin
vobj:=xobj.fValues.Objects[j];
if not Assigned(vobj) then begin
prefix:=xobj.fValues.Names[j] + ' = ';
Writeln(prefix + xobj.fValues.ValueFromIndex[j]+';')
end else begin
if vobj is TXCodeObject then begin
prefix:=xobj.fValues[j] + ' = ';
Writeln(prefix + TXCodeObject(vobj).ID+';')
end else if vobj is TStringValues then begin
st:=TStringValues(vobj);
prefix:=xobj.fValues.Names[j]+' = ';
Self.Writeln(prefix + ' {');
Self.Indent;
for k:=0 to st.Count-1 do
Self.WritelN(st.Names[k] + ' = ' + st.ValueFromIndex[k] + ';' );
Self.Unindent;
Self.Writeln('};')
end else if vobj is TStringList then begin
prefix:=xobj.fValues[j] + ' = ';
st:=TStringValues(vobj);
Self.Writeln(prefix + ' (');
Self.Indent;
for k:=0 to st.Count-1 do
Self.WritelN(' ' + st[k] + ',' );
Self.Unindent;
Self.Writeln(');')
end else if vobj is TFPObjectList then begin
prefix:=xobj.fValues[j] + ' = ';
sublist:=TFPObjectList(vobj);
Self.Writeln(prefix + '(');
Self.Indent;
for k:=0 to sublist.Count-1 do
Self.WritelN(TXCodeObject(sublist[k]).ID+',');
Self.Unindent;
Self.Writeln(');')
end;
end;
end;
Self.Unindent;
Self.WritelN('};');
end;
end;
constructor TPBXWriter.Create(Dst: TStream);
begin
inherited Create;
fDst:=Dst;
fIndent:=#9;
end;
destructor TPBXWriter.Destroy;
begin
inherited Destroy;
end;
procedure TPBXWriter.Indent;
begin
fPrefix:=fPrefix+fIndent;
end;
procedure TPBXWriter.Unindent;
begin
fPrefix:=Copy(fPrefix,1, length(fPrefix)-length(fIndent));
end;
procedure TPBXWriter.WriteLn(const utf8: AnsiString);
const
LF : string = #10;
begin
if utf8='' then Exit;
if fPrefix<>'' then fDst.Write(fPrefix[1], length(fPrefix));
fDst.Write(utf8[1], length(utf8));
fDst.Write(LF[1], length(LF));
end;
procedure WritePBXProjFile(RootObject: TXCodeObject; Dst: TStream);
var
lists : TFPHashObjectList; // list of TFPList
items : TFPList;
p : TXCodeObject;
stack : TFPList;
i : Integer;
xobjcount : Integer;
wr : TPBXWriter;
begin
if RootObject=nil then Exit;
lists:=TFPHashObjectList.Create(True);
stack:=TFPList.Create;
xobjcount:=1;
stack.Add(RootObject);
while stack.Count > 0 do begin
p:= TXCodeObject(stack[0]);
items:=TFPList(lists.Find(p.isa));
if not Assigned(items) then begin
items:=TFPList.Create;
lists.Add(p.isa, items);
end;
items.Add(p);
inc(xobjcount, p.ChildCount);
for i:=0 to p.ChildCount-1 do stack.Add(p.Child[i]);
stack.Delete(0);
end;
stack.Free;
wr:=TPBXWriter.Create(Dst);
wr.WriteLn(UTF8Mark);
wr.WriteLn('{');
wr.Indent;
wr.WriteLn('archiveVersion = 1;');
wr.WriteLn('classes = {};');
wr.WriteLn('objectVersion = 45;');
wr.WriteLn('objects = { ');
wr.Indent;
lists.ForEachCall(@wr.WriteItems, nil);
wr.Unindent;
wr.WriteLn('};');
wr.WriteLn('rootObject = '+RootObject.ID+';');
wr.Unindent;
wr.WriteLn('}');
wr.Free;
lists.Free;
end;
procedure WritePBXProjFile(RootObject: TXCodeObject; const FileName: String);
var
fs : TFileStream;
begin
fs:=TFileStream.Create(FileName, fmCreate);
WritePBXProjFile(RootOBject, fs);
fs.Free;
end;
{ TXCProject }
function TPBXProject.GetDirPath: string;
begin
Result:=UnquoteStr(StrValue['projectDirPath']);
end;
function TPBXProject.GetRoot: String;
begin
Result:=UnquoteStr(StrValue['projectRoot']);
end;
procedure TPBXProject.SetDirPath(const AValue: string);
begin
StrValue['projectDirPath']:=QuotedStr(AValue);
end;
procedure TPBXProject.SetRoot(const AValue: String);
begin
StrValue['projectRoot']:=QuotedStr(AValue);
end;
function TPBXProject.GetConfigList: TXCConfigurationList;
begin
if not Assigned(fConfigList) then begin
fConfigList:=TXCConfigurationList.Create;
AddObject('buildConfigurationList', fConfigList);
end;
Result:=fConfigList;
end;
function TPBXProject.GetTargets: TFPObjectList;
begin
Result:=GetObjectArray('targets');
end;
function TPBXProject.GetVersion: String;
begin
Result:=GetValue('compatibilityVersion');
end;
procedure TPBXProject.SetVersion(const AVersion: string);
begin
SetValue('compatibilityVersion', AVersion);
end;
constructor TPBXProject.Create;
begin
inherited Create;
Root:='';
DirPath:='';
end;
class function TPBXProject.isa: ShortString;
begin
Result:='PBXProject';
end;
function TPBXProject.AddTarget: TPBXNativeTarget;
var
list : TFPObjectList;
begin
// adding a target forces configuration list
//if fConfigList=nil then GetConfigList;
list:=GetObjectArray('targets');
Result:=TPBXNativeTarget.Create;
AddObject('', Result);
list.Add(Result);
end;
function TPBXProject.AddBuildConfig: TXCBuildConfiguration;
begin
Result:=GetConfigList.AddList;
end;
{ TPBXNativeTarget }
function TPBXNativeTarget.GetName: String;
begin
Result:=GetValue('name');
end;
function TPBXNativeTarget.GetProductFile: TPBXFileReference;
begin
if not Assigned(fRef) then begin
fRef:=TPBXFileReference.Create;
AddObject('productReference', fRef);
end;
Result:=fRef;
end;
procedure TPBXNativeTarget.SetName(const AValue: String);
begin
SetValue('name', AValue);
end;
function TPBXNativeTarget.GetProductName: String;
begin
Result:=GetValue('productName');
end;
procedure TPBXNativeTarget.SetProductName(const AValue: String);
begin
SetValue('productName', AValue);
end;
function TPBXNativeTarget.GetProductType: String;
begin
Result:=GetValue('productType');
end;
procedure TPBXNativeTarget.SetProductType(const AValue: String);
begin
SetValue('productType', AValue)
end;
function TPBXNativeTarget.GetConfigList: TXCConfigurationList;
begin
if not Assigned(fConfigList) then begin
fConfigList:=TXCConfigurationList.Create;
AddObject('buildConfigurationList', fConfigList);
end;
Result:=fConfigList;
end;
constructor TPBXNativeTarget.Create;
begin
inherited Create;
productType := '"com.apple.product-type.application"';
GetObjectArray('buildPhases');
GetObjectArray('buildRules');
GetObjectArray('dependencies');
end;
class function TPBXNativeTarget.isa: ShortString;
begin
Result:='PBXNativeTarget';
end;
function TPBXNativeTarget.AddBuildConfig: TXCBuildConfiguration;
begin
Result:=GetConfigList.AddList;
end;
function TPBXNativeTarget.AddScriptPhase: TPBXShellScriptBuildPhase;
begin
Result:=TPBXShellScriptBuildPhase.Create;
AddObject('', Result);
GetObjectArray('buildPhases').Add(Result);
end;
{ TPBXShellScriptBuildPhase }
function TPBXShellScriptBuildPhase.GetBuildMask: Integer;
begin
Result:=StrToIntDef( GetValue('buildActionMask'), 0);
end;
procedure TPBXShellScriptBuildPhase.SetBuildMask(const AValue: Integer);
begin
SetValue('buildActionMask', IntToStr(AValue));
end;
function TPBXShellScriptBuildPhase.GetShellPath: string;
begin
Result:=GetValue('shellPath');
end;
procedure TPBXShellScriptBuildPhase.SetShellPath(const AValue: string);
begin
SetValue('shellPath', AValue);
end;
function TPBXShellScriptBuildPhase.GetShellScript: String;
begin
Result:=UnquoteStr(GetValue('shellScript'));
end;
procedure TPBXShellScriptBuildPhase.SetShellScript(const AValue: String);
begin
SetValue('shellScript', QuotedStr(AValue));
end;
constructor TPBXShellScriptBuildPhase.Create;
begin
inherited Create;
ShellPath:='/bin/sh';
GetObjectArray('files');
GetObjectArray('inputPaths');
GetObjectArray('outputPaths');
end;
class function TPBXShellScriptBuildPhase.isa: ShortString;
begin
Result:='PBXShellScriptBuildPhase';
end;
end.