lazarus-ccr/components/iphonelazext/xcodeutils.pas

191 lines
4.9 KiB
ObjectPascal

unit XcodeUtils;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, PlistFile, LazFilesUtils;
const
iPhoneOSplatform = 'iPhoneOS.platform';
// file names should utf8 encoded
// Scanning Xcode platform for available SDKs
type
TSDKFoundEvent = procedure (const Version: String;
const DeviceSDKName, DeviceSDKPath, SimSDKName, SimSDKPath: String) of object;
function ScanForSDK(const PlatformDir: String; FoundProc: TSDKFoundEvent): Boolean;
// Scanning for Templates
function XibTemplateDir(const PlatformDir: AnsiString): AnsiString;
type
TScanTemplateProc = procedure ( const TemplateName, XibFileName,
Description, IconFileName: AnsiString) of object;
procedure ScanForXibTemplates(const TemplateDir: AnsiString; Callback: TScanTemplateProc);
implementation
type
TSDKDescription = record
FullPath : String; {full SDK path}
Name : String;
Alternate : String; {alternate SDK -> iphonesimulator for iphoneos}
Version : String;
isSim : Boolean; {true for real iPhoneOS, false for iPhoneSimulator}
end;
function ReadSDKSettings(const FileName: String; var Descr: TSDKDescription): Boolean;
var
plist : TPListFile;
begin
Result:=False;
plist:=TPListFile.Create;
try
plistfile.LoadFromFile(FileName, plist);
Descr.Name:=GetStr(plist, 'CanonicalName');
Descr.Alternate:=GetStr(plist, 'AlternateSDK');
Descr.Version:=GetStr(plist, 'Version');
finally
plist.Free;
end;
end;
function isSDKDir(const SDKDir: String; var d: TSDKDescription): Boolean;
var
plist : String;
begin
plist := IncludeTrailingPathDelimiter(SDKDir)+'SDKSettings.plist';
Result:=FileExists(plist);
if not Result then Exit;
ReadSDKSettings(plist, d);
d.FullPath:=SDKDir;
end;
function ScanForSDK(const PlatformDir: String; FoundProc: TSDKFoundEvent): Boolean;
const
PlatformName: array [Boolean] of String = ('iPhoneOS.platform','iPhoneSimulator.platform');
SDKSubDir = PathDelim+'Developer'+PathDelim+'SDKs'+PathDelim;
var
isSim : Boolean;
dir : String;
sr : TSearchRec;
sdks : array of TSDKDescription;
descr : TSDKDescription;
cnt : Integer;
simname : String;
simpath : String;
i,j : Integer;
procedure AddDescription(const d: TSDKDescription);
begin
if cnt = length(sdks) then begin
if cnt = 0 then SetLength(sdks, 16)
else SetLength(sdks, cnt*2);
end;
sdks[cnt]:=d;
inc(cnt);
end;
begin
Result:=Assigned(FoundProc);
if not Result then Exit;
cnt:=0;
for isSim:=false to true do begin
dir := IncludeTrailingPathDelimiter(PlatformDir) + PlatformName[isSim] + SDKSubDir;
if FindFirst(dir+'*', faAnyFile, sr)=0 then begin
repeat
if (sr.Attr and faDirectory>0) and (ExtractFileExt(sr.Name) = '.sdk') then
if isSDKDir( dir + sr.Name, descr) then begin
descr.isSim:=isSim;
AddDescription(descr);
end;
until FindNext(sr)<>0;
FindClose(sr);
end;
end;
for i:=0 to cnt-1 do
if not sdks[i].isSim then begin
simname:='';
simpath:='';
for j:=0 to cnt-1 do
if (sdks[j].isSim) and (sdks[i].Alternate=sdks[j].Name) then begin
simname:=sdks[j].Name;
simpath:=sdks[j].FullPath;
end;
FoundProc(sdks[i].Version, sdks[i].Name, sdks[i].FullPath, simname, simpath);
end;
Result:=True;
end;
function XibTemplateDir(const PlatformDir: AnsiString): AnsiString;
const
TemplatePath = 'Developer/Library/Xcode/File Templates/User Interface';
begin
Result:=IncludeTrailingPathDelimiter(PlatformDir)+TemplatePath;
end;
procedure ScanForXibTemplates(const TemplateDir: AnsiString; Callback: TScanTemplateProc);
var
dirs : TStringList;
files : TStringList;
i,j : Integer;
plist : TPListFile;
xib : AnsiString;
name : AnsiString;
descr : AnsiString;
const
XibTemplateMask = '*.pbfiletemplate';
IconFile = 'TemplateIcon.tiff';
begin
if not Assigned(Callback) or not DirectoryExists(TemplateDir) then Exit;
dirs:=TStringList.Create;
files:=TStringList.Create;
try
EnumFilesAtDir( TemplateDir, XibTemplateMask, dirs );
for i:=0 to dirs.Count-1 do begin
if DirectoryExists(dirs[i]) then begin
files.Clear;
EnumFilesAtDir(dirs[i], files);
xib:='';
for j:=0 to files.Count-1 do
if AnsiLowerCase(ExtractFileExt(files[j]))='.plist' then begin
plist:=TPListFile.Create;
plistfile.LoadFromFile(files[j],plist);
xib:=GetStr(plist, 'MainTemplateFile');
descr:=GetStr(plist, 'Description');
name:=ChangeFileExt(xib, '');
Break;
end;
if xib<>'' then begin
xib:=IncludeTrailingPathDelimiter(dirs[i])+xib;
Callback(name, xib, descr, IncludeTrailingPathDelimiter(dirs[i])+IconFile);
end;
end;
end;
finally
dirs.Free;
files.Free;
end;
end;
end.