pkgglobals.pp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. {$mode objfpc}
  2. {$h+}
  3. unit pkgglobals;
  4. interface
  5. uses
  6. {$ifdef unix}
  7. baseunix,
  8. {$endif}
  9. SysUtils,
  10. Classes,
  11. fprepos;
  12. Const
  13. {$ifdef unix}
  14. ExeExt = '';
  15. AllFiles='*';
  16. {$else unix}
  17. ExeExt = '.exe';
  18. AllFiles='*.*';
  19. {$endif unix}
  20. Type
  21. TFPMKUnitDep=record
  22. package : string[12];
  23. reqver : string[8];
  24. undef : string[32];
  25. def : string[32];
  26. available: boolean;
  27. end;
  28. Const
  29. CmdLinePackageName='<cmdline>';
  30. CurrentDirPackageName='<currentdir>';
  31. // Dependencies for compiling the fpmkunit unit
  32. FPMKUnitDepDefaultCount=4;
  33. FPMKUnitDepsDefaults : array[0..FPMKUnitDepDefaultCount-1] of TFPMKUnitDep = (
  34. (package: 'hash';
  35. reqver : '2.2.2';
  36. undef : 'NO_UNIT_ZIPPER'),
  37. (package: 'paszlib';
  38. reqver : '2.2.2';
  39. undef : 'NO_UNIT_ZIPPER'),
  40. (package: 'fcl-process';
  41. reqver : '2.2.2';
  42. undef : 'NO_UNIT_PROCESS'),
  43. (package: 'fpmkunit';
  44. reqver : '2.2.2-1';
  45. undef : '')
  46. );
  47. Type
  48. TLogLevel = (vlError,vlWarning,vlInfo,vlCommands,vlDebug,vlProgres);
  49. TLogLevels = Set of TLogLevel;
  50. const
  51. DefaultLogLevels = [vlError,vlWarning, vlProgres];
  52. AllLogLevels = [vlError,vlWarning,vlCommands,vlInfo];
  53. type
  54. EPackagerError = class(Exception);
  55. // Logging
  56. Function StringToLogLevels (S : String) : TLogLevels;
  57. Function LogLevelsToString (V : TLogLevels): String;
  58. Procedure Log(Level: TLogLevel;Msg : String);
  59. Procedure Log(Level: TLogLevel;Fmt : String; const Args : array of const);
  60. Procedure Error(Msg : String);
  61. Procedure Error(Fmt : String; const Args : array of const);
  62. // Utils
  63. function maybequoted(const s:string):string;
  64. Function FixPath(const S : String) : string;
  65. Function DirectoryExistsLog(const ADir:string):Boolean;
  66. Function FileExistsLog(const AFileName:string):Boolean;
  67. procedure BackupFile(const AFileName: String);
  68. Procedure DeleteDir(const ADir:string);
  69. Procedure SearchFiles(SL:TStringList;const APattern:string);
  70. Function GetCompilerInfo(const ACompiler,AOptions:string):string; overload;
  71. Procedure GetCompilerInfo(const ACompiler, AOptions: string; out AVersion: string; out ACPU: TCpu; out aOS:TOS); overload;
  72. function IsSuperUser:boolean;
  73. var
  74. LogLevels : TLogLevels;
  75. FPMKUnitDeps : array of TFPMKUnitDep;
  76. Implementation
  77. // define use_shell to use sysutils.executeprocess
  78. // as alternate to using 'process' in getcompilerinfo
  79. {$IF defined(GO32v2) or defined(WATCOM) or defined(OS2)}
  80. {$DEFINE USE_SHELL}
  81. {$ENDIF GO32v2 or WATCOM or OS2}
  82. uses
  83. typinfo,
  84. {$IFNDEF USE_SHELL}
  85. process,
  86. {$ENDIF USE_SHELL}
  87. contnrs,
  88. uriparser,
  89. pkgmessages;
  90. function FPPkgGetVendorName:string;
  91. begin
  92. {$ifdef unix}
  93. result:='fpc';
  94. {$else}
  95. result:='FreePascal'
  96. {$endif}
  97. end;
  98. function FPPkgGetApplicationName:string;
  99. begin
  100. result:='fppkg';
  101. end;
  102. function StringToLogLevels(S: String): TLogLevels;
  103. Var
  104. I : integer;
  105. begin
  106. I:=GetEnumValue(TypeInfo(TLogLevels),'v'+S);
  107. If (I<>-1) then
  108. Result:=TLogLevels(I)
  109. else
  110. Raise EPackagerError.CreateFmt(SErrInvalidLogLevels,[S]);
  111. end;
  112. Function LogLevelsToString (V : TLogLevels): String;
  113. begin
  114. Result:=GetEnumName(TypeInfo(TLogLevels),Integer(V));
  115. Delete(Result,1,1);// Delete 'v'
  116. end;
  117. procedure Log(Level:TLogLevel;Msg: String);
  118. var
  119. Prefix : string;
  120. begin
  121. if not(Level in LogLevels) then
  122. exit;
  123. Prefix:='';
  124. case Level of
  125. vlWarning :
  126. Prefix:=SWarning;
  127. vlError :
  128. Prefix:=SError;
  129. { vlInfo :
  130. Prefix:='I: ';
  131. vlCommands :
  132. Prefix:='C: ';
  133. vlDebug :
  134. Prefix:='D: '; }
  135. end;
  136. Writeln(stdOut,Prefix,Msg);
  137. end;
  138. Procedure Log(Level:TLogLevel; Fmt:String; const Args:array of const);
  139. begin
  140. Log(Level,Format(Fmt,Args));
  141. end;
  142. procedure Error(Msg: String);
  143. begin
  144. Raise EPackagerError.Create(Msg);
  145. end;
  146. procedure Error(Fmt: String; const Args: array of const);
  147. begin
  148. Raise EPackagerError.CreateFmt(Fmt,Args);
  149. end;
  150. function maybequoted(const s:string):string;
  151. const
  152. {$IFDEF MSWINDOWS}
  153. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  154. '{', '}', '''', '`', '~'];
  155. {$ELSE}
  156. FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
  157. '{', '}', '''', ':', '\', '`', '~'];
  158. {$ENDIF}
  159. var
  160. s1 : string;
  161. i : integer;
  162. quoted : boolean;
  163. begin
  164. quoted:=false;
  165. s1:='"';
  166. for i:=1 to length(s) do
  167. begin
  168. case s[i] of
  169. '"' :
  170. begin
  171. quoted:=true;
  172. s1:=s1+'\"';
  173. end;
  174. ' ',
  175. #128..#255 :
  176. begin
  177. quoted:=true;
  178. s1:=s1+s[i];
  179. end;
  180. else begin
  181. if s[i] in FORBIDDEN_CHARS then
  182. quoted:=True;
  183. s1:=s1+s[i];
  184. end;
  185. end;
  186. end;
  187. if quoted then
  188. maybequoted:=s1+'"'
  189. else
  190. maybequoted:=s;
  191. end;
  192. Function FixPath(const S : String) : string;
  193. begin
  194. If (S<>'') then
  195. Result:=IncludeTrailingPathDelimiter(S)
  196. else
  197. Result:='';
  198. end;
  199. Function DirectoryExistsLog(const ADir:string):Boolean;
  200. begin
  201. result:=SysUtils.DirectoryExists(ADir);
  202. if result then
  203. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgFound])
  204. else
  205. Log(vlDebug,SDbgDirectoryExists,[ADir,SDbgNotFound]);
  206. end;
  207. Function FileExistsLog(const AFileName:string):Boolean;
  208. begin
  209. result:=SysUtils.FileExists(AFileName);
  210. if result then
  211. Log(vlDebug,SDbgFileExists,[AFileName,SDbgFound])
  212. else
  213. Log(vlDebug,SDbgFileExists,[AFileName,SDbgNotFound]);
  214. end;
  215. procedure BackupFile(const AFileName: String);
  216. Var
  217. BFN : String;
  218. begin
  219. BFN:=AFileName+'.bak';
  220. Log(vlDebug,SDbgBackupFile,[BFN]);
  221. If not RenameFile(AFileName,BFN) then
  222. Error(SErrBackupFailed,[AFileName,BFN]);
  223. end;
  224. Procedure DeleteDir(const ADir:string);
  225. var
  226. Info : TSearchRec;
  227. begin
  228. // Prevent accidently deleting all files in current or root dir
  229. if (ADir='') or (ADir=PathDelim) then
  230. exit;
  231. if FindFirst(ADir+PathDelim+AllFiles,faAnyFile, Info)=0 then
  232. try
  233. repeat
  234. if (Info.Attr and faDirectory)=faDirectory then
  235. begin
  236. if (Info.Name<>'.') and (Info.Name<>'..') then
  237. DeleteDir(ADir+PathDelim+Info.Name)
  238. end
  239. else
  240. DeleteFile(ADir+PathDelim+Info.Name);
  241. until FindNext(Info)<>0;
  242. finally
  243. FindClose(Info);
  244. end;
  245. RemoveDir(Adir);
  246. end;
  247. Procedure SearchFiles(SL:TStringList;const APattern:string);
  248. var
  249. Info : TSearchRec;
  250. ADir : string;
  251. begin
  252. ADir:=ExtractFilePath(APattern);
  253. if FindFirst(APattern,faAnyFile, Info)=0 then
  254. try
  255. repeat
  256. if (Info.Attr and faDirectory)=faDirectory then
  257. begin
  258. if (Info.Name<>'.') and (Info.Name<>'..') then
  259. SearchFiles(SL,ADir+Info.Name+PathDelim+ExtractFileName(APattern))
  260. end;
  261. SL.Add(ADir+Info.Name);
  262. until FindNext(Info)<>0;
  263. finally
  264. FindClose(Info);
  265. end;
  266. end;
  267. //
  268. // if use_shell defined uses sysutils.executeprocess else uses 'process'
  269. //
  270. function GetCompilerInfo(const ACompiler,AOptions:string):string;
  271. const
  272. BufSize = 1024;
  273. var
  274. {$IFDEF USE_SHELL}
  275. TmpFileName, ProcIDStr: shortstring;
  276. TmpFile: file;
  277. CmdLine2: string;
  278. {$ELSE USE_SHELL}
  279. S: TProcess;
  280. {$ENDIF USE_SHELL}
  281. Buf: array [0..BufSize - 1] of char;
  282. Count: longint;
  283. begin
  284. {$IFDEF USE_SHELL}
  285. Str (GetProcessID, ProcIDStr);
  286. TmpFileName := GetEnvironmentVariable ('TEMP');
  287. if TmpFileName <> '' then
  288. TmpFileName := TmpFileName + DirectorySeparator + 'fppkgout.' + ProcIDStr
  289. else
  290. TmpfileName := 'fppkgout.' + ProcIDStr;
  291. CmdLine2 := '/C ' + ACompiler + ' ' + AOptions + ' > ' + TmpFileName;
  292. SysUtils.ExecuteProcess (GetEnvironmentVariable ('COMSPEC'), CmdLine2);
  293. Assign (TmpFile, TmpFileName);
  294. Reset (TmpFile, 1);
  295. BlockRead (TmpFile, Buf, BufSize, Count);
  296. Close (TmpFile);
  297. {$ELSE USE_SHELL}
  298. S:=TProcess.Create(Nil);
  299. S.Commandline:=ACompiler+' '+AOptions;
  300. S.Options:=[poUsePipes];
  301. S.execute;
  302. Count:=s.output.read(buf,BufSize);
  303. S.Free;
  304. {$ENDIF USE_SHELL}
  305. SetLength(Result,Count);
  306. Move(Buf,Result[1],Count);
  307. end;
  308. Procedure GetCompilerInfo(const ACompiler, AOptions: string; out AVersion: string; out ACPU: TCpu; out aOS:TOS); overload;
  309. var
  310. infosl: TStringList;
  311. begin
  312. infosl:=TStringList.Create;
  313. infosl.Delimiter:=' ';
  314. infosl.DelimitedText:=GetCompilerInfo(ACompiler,AOptions);
  315. if infosl.Count<>3 then
  316. Raise EPackagerError.Create(SErrInvalidFPCInfo);
  317. AVersion:=infosl[0];
  318. ACPU:=StringToCPU(infosl[1]);
  319. AOS:=StringToOS(infosl[2]);
  320. end;
  321. function IsSuperUser:boolean;
  322. begin
  323. {$ifdef unix}
  324. result:=(fpGetUID=0);
  325. {$else unix}
  326. result:=false;
  327. {$endif unix}
  328. end;
  329. initialization
  330. OnGetVendorName:=@FPPkgGetVendorName;
  331. OnGetApplicationName:=@FPPkgGetApplicationName;
  332. end.