iphonelazext: update xcode projection generation. Reuse the existing file rather than recreating it everytime

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4435 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
skalogryz
2016-01-18 16:55:44 +00:00
parent 364c9a7fc6
commit 7b707a09f6
2 changed files with 110 additions and 28 deletions

View File

@ -129,6 +129,7 @@ type
public public
constructor Create; override; constructor Create; override;
destructor Destroy; override; destructor Destroy; override;
function AddFile(ref: PBXFileReference): PBXBuildFile;
published published
property buildActionMask: Integer read fbuildActionMask write fbuildActionMask; property buildActionMask: Integer read fbuildActionMask write fbuildActionMask;
property files: TPBXObjectsList read ffiles; property files: TPBXObjectsList read ffiles;
@ -141,6 +142,8 @@ type
PBXResourcesBuildPhase = class(PBXBuildPhase); PBXResourcesBuildPhase = class(PBXBuildPhase);
PBXSourcesBuildPhase = class(PBXBuildPhase); PBXSourcesBuildPhase = class(PBXBuildPhase);
PBXBuildPhaseClass = class of PBXBuildPhase;
{ PBXShellScriptBuildPhase } { PBXShellScriptBuildPhase }
PBXShellScriptBuildPhase = class(PBXBuildPhase) PBXShellScriptBuildPhase = class(PBXBuildPhase)
@ -316,6 +319,9 @@ const
SCRIPT_DEFNAME = 'Run Script'; SCRIPT_DEFNAME = 'Run Script';
function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase; function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase;
function TargetFindBuildPhase(atarget: PBXNativeTarget; aclass: PBXBuildPhaseClass; aforce: Boolean = false): PBXBuildPhase;
function TargetFindRunScript(atarget: PBXNativeTarget; aforce: Boolean = false): PBXShellScriptBuildPhase;
function TargetFindResources(atarget: PBXNativeTarget; aforce: Boolean = false): PBXResourcesBuildPhase;
const const
//FILETYPE_SCRIPT = 'text.script.sh'; //FILETYPE_SCRIPT = 'text.script.sh';
@ -325,7 +331,9 @@ const
FILETYPE_PLIST = 'text.plist.xml'; FILETYPE_PLIST = 'text.plist.xml';
FILETYPE_OBJC = 'sourcecode.c.objc'; FILETYPE_OBJC = 'sourcecode.c.objc';
function FileRefCreate(const afilename: string; const filetype: string = ''): PBXFileReference; // defaults to SRCTREE_GROUP for source related
function FileRefCreate(const afilename: string; const filetype: string = ''): PBXFileReference; overload;
function FileRefCreate(const afilename: string; const filetype, ASrcTreeRel: string): PBXFileReference; overload;
const const
SRCTREE_ABSOLUTE = '<absolute>'; // path is absolute path SRCTREE_ABSOLUTE = '<absolute>'; // path is absolute path
@ -597,6 +605,17 @@ begin
ffiles.Free; ffiles.Free;
end; end;
function PBXBuildPhase.AddFile(ref: PBXFileReference): PBXBuildFile;
begin
if not Assigned(ref) then begin
Result:=nil;
Exit;
end;
Result := PBXBuildFile.Create;
Result.fileRef:=ref;
ffiles.Add(Result);
end;
function ProjectLoadFromStream(st: TStream; var prj: PBXProject): Boolean; function ProjectLoadFromStream(st: TStream; var prj: PBXProject): Boolean;
var var
c : TPBXContainer; c : TPBXContainer;
@ -711,8 +730,41 @@ begin
Result:=ProjectAddTarget(prj, ATargetName); Result:=ProjectAddTarget(prj, ATargetName);
end; end;
function TargetFindBuildPhase(atarget: PBXNativeTarget; aclass: PBXBuildPhaseClass; aforce: Boolean = false): PBXBuildPhase;
var
i : integer;
begin
Result:=nil;
if not Assigned(atarget) then Exit;
for i:=0 to atarget.buildPhases.Count-1 do
if atarget.buildPhases[i] is aclass then begin
Result:=PBXBuildPhase(atarget.buildPhases[i]);
Break;
end;
if not Assigned(Result) and aforce then begin
Result:=aclass.Create;
atarget.buildPhases.Add(Result);
end;
end;
function TargetFindResources(atarget: PBXNativeTarget; aforce: Boolean = false): PBXResourcesBuildPhase;
begin
Result:=PBXResourcesBuildPhase(TargetFindBuildPhase(atarget, PBXResourcesBuildPhase, aforce));
end;
function TargetFindRunScript(atarget: PBXNativeTarget; aforce: Boolean = false): PBXShellScriptBuildPhase;
begin
Result:=PBXShellScriptBuildPhase(TargetFindBuildPhase(atarget, PBXShellScriptBuildPhase, false));
if not Assigned(Result) and aforce then
Result:=TargetAddRunScript(atarget);
end;
function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase; function TargetAddRunScript(atarget: PBXNativeTarget): PBXShellScriptBuildPhase;
begin begin
if not Assigned(atarget) then begin
Result:=nil;
Exit;
end;
Result:=PBXShellScriptBuildPhase.Create; Result:=PBXShellScriptBuildPhase.Create;
Result.name:=SCRIPT_DEFNAME; Result.name:=SCRIPT_DEFNAME;
Result._headerComment:=SCRIPT_DEFNAME; Result._headerComment:=SCRIPT_DEFNAME;
@ -722,11 +774,17 @@ begin
end; end;
function FileRefCreate(const afilename: string; const filetype: string ): PBXFileReference; function FileRefCreate(const afilename: string; const filetype: string ): PBXFileReference;
begin
Result:=FileRefCreate(afilename, filetype, SRCTREE_GROUP);
end;
function FileRefCreate(const afilename: string; const filetype, ASrcTreeRel: string): PBXFileReference;
begin begin
Result:=PBXFileReference.Create; Result:=PBXFileReference.Create;
Result.path:=afilename; Result.path:=afilename;
Result._headerComment:=afilename; Result._headerComment:=afilename;
Result.explicitFileType:=FILETYPE_EXEC; Result.explicitFileType:=FILETYPE_EXEC;
Result.sourceTree:=ASrcTreeRel;
end; end;
function GroupCreate(const aname, srcTree: string): PBXGroup; function GroupCreate(const aname, srcTree: string): PBXGroup;

View File

@ -372,14 +372,37 @@ var
begin begin
prj:=ProjectCreate3_2; prj:=ProjectCreate3_2;
PrepareTemplateFile(prj, TemplateValues, ResFiles); PrepareTemplateFile(prj, TemplateValues, ResFiles);
src.Text:=ProjectWrite(prj);
end; end;
function ReadBuildScriptFile(const fn: string): string;
var
fs : TFileStream;
begin
fs:=TFileStream.Create(fn, fmOpenRead or fmShareDenyNone);
try
if fs.Size=0 then begin
Result:='';
Exit;
end;
SetLength(Result, fs.Size);
fs.Read(Result[1], fs.Size);
// replacing line breaks with #13 for Xcode
Result:=StringReplace(Result, #13#10, #13, [rfReplaceAll]);
Result:=StringReplace(Result, #10#13, #13, [rfReplaceAll]);
Result:=StringReplace(Result, #10, #13, [rfReplaceAll]);
finally
fs.Free;
end;
end;
procedure PrepareTemplateFile(prj: PBXProject; TemplateValues, ResFiles: TStrings); procedure PrepareTemplateFile(prj: PBXProject; TemplateValues, ResFiles: TStrings);
var var
trg : PBXNativeTarget; trg : PBXNativeTarget;
cfg : XCBuildConfiguration; cfg : XCBuildConfiguration;
fr : PBXFileReference; fr : PBXFileReference;
fbld : PBXBuildFile;
grp : PBXGroup; grp : PBXGroup;
pgrp : PBXGroup; pgrp : PBXGroup;
scr : PBXShellScriptBuildPhase; scr : PBXShellScriptBuildPhase;
@ -390,6 +413,8 @@ var
bundle : string; bundle : string;
main : string; main : string;
fnm : string; fnm : string;
const
FILE_COPY_MASK = 2147483647;
begin begin
targetName:=TemplateValues.Values['targetname']; targetName:=TemplateValues.Values['targetname'];
bundle:=TemplateValues.Values['bundle']; bundle:=TemplateValues.Values['bundle'];
@ -425,16 +450,15 @@ begin
cfg.buildSettings.AddStr('INFOPLIST_FILE', '$(SRCROOT)/'+plist); cfg.buildSettings.AddStr('INFOPLIST_FILE', '$(SRCROOT)/'+plist);
cfg.buildSettings.AddStr('PRODUCT_NAME', trg.productName); cfg.buildSettings.AddStr('PRODUCT_NAME', trg.productName);
if trg.buildConfigurationList = '' then if trg.buildConfigurationList.defaultConfigurationName = '' then
trg.buildConfigurationList.defaultConfigurationName:='Debug'; trg.buildConfigurationList.defaultConfigurationName:='Debug';
// Adding the ".app" directory for the bundle and bind it to the target // Adding the ".app" directory for the bundle and bind it to the target
if not Assigned(trg.productReference) then begin if not Assigned(trg.productReference) then begin
fr:=FileRefCreate(bundle, FILETYPE_MACHO); fr:=FileRefCreate(bundle, FILETYPE_MACHO, SRCTREE_PRODUCT);
fr.sourceTree:= SRCTREE_PRODUCT;
trg.productReference:=fr; trg.productReference:=fr;
end else end; (* else
fr:=trg.productReference; fr:=trg.productReference;*)
// Creating "content" for the directory. It should also contain .plist // Creating "content" for the directory. It should also contain .plist
pgrp:=prj.mainGroup.findGroup(targetName, true); // name must match to the target name! pgrp:=prj.mainGroup.findGroup(targetName, true); // name must match to the target name!
@ -444,41 +468,41 @@ begin
// Thus at the same directar as .xcodeproj dir // Thus at the same directar as .xcodeproj dir
if not Assigned(grp.findFileRefByPathName(plist)) then if not Assigned(grp.findFileRefByPathName(plist)) then
begin begin
fr:=FileRefCreate(plist, FILETYPE_PLIST ); fr:=FileRefCreate(plist, FILETYPE_PLIST, SRCTREE_PROJECT );
fr.sourceTree:=SRCTREE_PROJECT;
fr.path:=plist;
grp.children.Add( fr ); grp.children.Add( fr );
end; end;
scr:=TargetAddRunScript(trg); if not Assigned(TargetFindRunScript(trg)) then begin
scr.shellScript:=BuildScript; scr:=TargetAddRunScript(trg);
scr.showEnvVarsInLog:=true; scr.shellScript:=BuildScript;
scr.showEnvVarsInLog:=true;
end;
// todo: removal of files!
if Assigned(ResFiles) and (ResFiles.Count>0) then begin if Assigned(ResFiles) and (ResFiles.Count>0) then begin
grp:=prj.mainGroup.addSubGroup('Resources'); // name must match to the target name! grp:=prj.mainGroup.findGroup('Resources', true); // name must match to the target name!
//grp:=pgrp.addSubGroup('Supporting Files'); // name must match! //grp:=pgrp.addSubGroup('Supporting Files'); // name must match!
res := PBXResourcesBuildPhase.Create; res := PBXResourcesBuildPhase(TargetFindBuildPhase(trg, PBXResourcesBuildPhase));
res.buildActionMask:=2147483647; if not Assigned(res) then begin
//res.name:='Resources'; res := PBXResourcesBuildPhase.Create;
trg.buildPhases.Add(res); //res.name:='Resources';
res.buildActionMask:=FILE_COPY_MASK;
trg.buildPhases.Add(res);
end;
for i:=0 to ResFiles.Count-1 do begin for i:=0 to ResFiles.Count-1 do begin
fnm:='../'+ResFiles[i]; fnm:='../'+ResFiles[i];
fr:=FileRefCreate(fnm, FILETYPE_MACHO); if not Assigned(grp.findFileRefByPathName(fnm)) then begin
fr.sourceTree:=SRCTREE_PROJECT; fr:=FileRefCreate(fnm, FILETYPE_MACHO, SRCTREE_PROJECT);
grp.children.add(fr); grp.children.add( fr );
res.AddFile(fr);
fbld := PBXBuildFile.Create; end;
fbld.fileRef:=fr;
res.files.Add(fbld);
end; end;
end; end;
UpdateMainFile(prj, main); UpdateMainFile(prj, main);
UpdateCompileOpts(prj, TemplateValues.Values['projoptions']); UpdateCompileOpts(prj, TemplateValues.Values['projoptions']);
src.Text:=ProjectWrite(prj);
end; end;
end. end.