From 12c2780d5cf280c013a2a1700e2f9f6e27250591 Mon Sep 17 00:00:00 2001 From: skalogryz Date: Tue, 22 Mar 2016 14:54:36 +0000 Subject: [PATCH] iphonelazext: updating existing xcode project, instead of recreating it from scratch git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4582 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/iphonelazext/ideext.pas | 15 ++++---- components/iphonelazext/iphoneextstr.pas | 1 + components/iphonelazext/pbx/xcodeproj.pas | 37 ++++++++++++++++++-- components/iphonelazext/xcodetemplate.pas | 42 ++++++++++++++++++----- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/components/iphonelazext/ideext.pas b/components/iphonelazext/ideext.pas index 74b253343..e8063d611 100644 --- a/components/iphonelazext/ideext.pas +++ b/components/iphonelazext/ideext.pas @@ -383,7 +383,7 @@ var build : TFPStringHashTable; dir : string; projdir : string; - proj : TStringList; + //proj : TStringList; projname : string; ext : string; @@ -442,7 +442,7 @@ begin ForceDirectories(projdir); projname:=IncludeTrailingPathDelimiter(projdir)+'project.pbxproj'; - proj:=TStringList.Create; + //proj:=TStringList.Create; templates:=nil; try templates:=TStringList.Create; @@ -467,18 +467,21 @@ begin templates.Values['mainfile']:=LazarusIDE.ActiveProject.MainFile.Filename; templates.Values['projoptions']:=opt; - PrepareTemplateFile(proj, templates, ProjOptions.ResFiles); - proj.SaveToFile(projname); + if not UpdateProject(projName, templates, ProjOptions.ResFiles) then + IDEMsg(Format(strXcodeUpdFailed,[projdir])) + else + IDEMsg(Format(strXcodeUpdated,[projdir])); + //PrepareTemplateFile(proj, templates, ProjOptions.ResFiles); + //proj.SaveToFile(projname); except on e: exception do ShowMessage(e.Message); end; - proj.Free; + //proj.Free; templates.Free; build.Free; - IDEMsg(Format(strXcodeUpdated,[projdir])); end; procedure SimRunDirect; diff --git a/components/iphonelazext/iphoneextstr.pas b/components/iphonelazext/iphoneextstr.pas index fd575373b..7ad133883 100644 --- a/components/iphonelazext/iphoneextstr.pas +++ b/components/iphonelazext/iphoneextstr.pas @@ -32,6 +32,7 @@ resourcestring strPtrOptAppIDHint = 'It''s recommended by Apple to use domain-structured identifier i.e. "com.mycompany.myApplication"'; strXcodeUpdated = 'Xcode project updated (%s)'; + strXcodeUpdFailed = 'Failed to update Xcode project (%s)'; strWNoSDKSelected = 'Warning: SDK is not selected using %s'; strWNoSDK = 'Warning: No SDK available. Linking might fail.'; diff --git a/components/iphonelazext/pbx/xcodeproj.pas b/components/iphonelazext/pbx/xcodeproj.pas index 742ca7fae..5bf063f63 100644 --- a/components/iphonelazext/pbx/xcodeproj.pas +++ b/components/iphonelazext/pbx/xcodeproj.pas @@ -294,6 +294,7 @@ type function ProjectLoadFromStream(st: TStream; var prj: PBXProject): Boolean; function ProjectLoadFromFile(const fn: string; var prj: PBXProject): Boolean; +function ProjectSaveToFile(prj: PBXProject; const fn: string): Boolean; // serializes a PBX project to the string, using PBXContainer structure function ProjectWrite(prj: PBXProject): string; @@ -376,14 +377,25 @@ const CFG_DEVICE_IPHONE = '1'; CFG_DEVICE_IPAD = '2'; +procedure SetNewStr(kv: TPBXKeyValue; const aname, avalue: string); + implementation +procedure SetNewStr(kv: TPBXKeyValue; const aname, avalue: string); +begin + if Assigned(kv) then begin + if kv.FindIndexOf(aname)<0 then + kv.AddStr(aname, avalue); + end; +end; + 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); + + SetNewStr(cfg.buildSettings, CFG_IOSTRG, targetiOS); + SetNewStr(cfg.buildSettings, CFG_SDKROOT, 'iphoneos'); + SetNewStr(cfg.buildSettings, CFG_DEVICE, CFG_DEVICE_ALL); end; { PBXLegacyTarget } @@ -649,6 +661,25 @@ begin end; end; +function ProjectSaveToFile(prj: PBXProject; const fn: string): Boolean; +var + fs : TFileStream; + s : string; +begin + s:=ProjectWrite(prj); + try + fs:=TFileStream.Create(fn, fmCreate); + try + if length(s)>0 then fs.Write(s[1], length(s)); + finally + fs.Free; + end; + except + Result:=false; + end; + +end; + function ProjectWrite(prj: PBXProject): string; var info : TPBXFileInfo; diff --git a/components/iphonelazext/xcodetemplate.pas b/components/iphonelazext/xcodetemplate.pas index 12d30e570..2ee3be623 100644 --- a/components/iphonelazext/xcodetemplate.pas +++ b/components/iphonelazext/xcodetemplate.pas @@ -24,6 +24,8 @@ uses procedure PrepareTemplateFile_(Src, TemplateValues: TStrings; BuildSettings: TFPStringHashTable); procedure PrepareTemplateFile(Src, TemplateValues, ResFiles: TStrings); procedure PrepareTemplateFile(prj: PBXProject; TemplateValues, ResFiles: TStrings); +function UpdateProject(const ProjFileName: string; TemplateValues, ResFiles: TStrings): Boolean; + procedure UpdateBldConfig(const proj: PBXProject; optName, optVal: string); procedure UpdateMainFile(const proj: PBXProject; mainfile: string); procedure UpdateCompileOpts(const proj: PBXProject; options: string); @@ -430,7 +432,9 @@ begin // it would be amd-32 for iPhone5 (and earlier) // and amd-64 for iPhone6 (and later) // Release requires to have a fat binary 32+64 amd, if target is less than iphone6 - if cfg.name='Debug' then cfg.buildSettings.AddStr('ONLY_ACTIVE_ARCH','YES'); + if (cfg.name='Debug') then begin + SetNewStr(cfg.buildSettings, 'ONLY_ACTIVE_ARCH', 'YES'); + end; end; // adding application type @@ -443,12 +447,13 @@ begin // Debug cfg:=trg.buildConfigurationList.findConfig('Debug', true); - cfg.buildSettings.AddStr('INFOPLIST_FILE', '$(SRCROOT)/'+plist); - cfg.buildSettings.AddStr('PRODUCT_NAME', trg.productName); - // Build + SetNewStr(cfg.buildSettings, 'INFOPLIST_FILE', '$(SRCROOT)/'+plist); + SetNewStr(cfg.buildSettings, 'PRODUCT_NAME', trg.productName); + + // Release cfg:=trg.buildConfigurationList.findConfig('Release', true); - cfg.buildSettings.AddStr('INFOPLIST_FILE', '$(SRCROOT)/'+plist); - cfg.buildSettings.AddStr('PRODUCT_NAME', trg.productName); + SetNewStr(cfg.buildSettings, 'INFOPLIST_FILE', '$(SRCROOT)/'+plist); + SetNewStr(cfg.buildSettings, 'PRODUCT_NAME', trg.productName); if trg.buildConfigurationList.defaultConfigurationName = '' then trg.buildConfigurationList.defaultConfigurationName:='Debug'; @@ -457,8 +462,7 @@ begin if not Assigned(trg.productReference) then begin fr:=FileRefCreate(bundle, FILETYPE_MACHO, SRCTREE_PRODUCT); trg.productReference:=fr; - end; (* else - fr:=trg.productReference;*) + end; // Creating "content" for the directory. It should also contain .plist pgrp:=prj.mainGroup.findGroup(targetName, true); // name must match to the target name! @@ -505,5 +509,27 @@ begin UpdateCompileOpts(prj, TemplateValues.Values['projoptions']); end; +function UpdateProject(const ProjFileName: string; TemplateValues, ResFiles: TStrings): Boolean; +var + prj : PBXProject; +begin + if FileExists(ProjFileName) then begin + prj:=nil; + Result:=ProjectLoadFromFile(ProjFileName, prj); + if not Result then begin + prj.Free; + Exit; + end; + end else + prj:=ProjectCreate3_2; + + try + PrepareTemplateFile(prj, TemplateValues, Resfiles); + Result:=ProjectSaveToFile(prj, ProjFileName); + finally + prj.Free; + end; +end; + end.