| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- //https://castle-engine.io/modern_pascal
- program Make;
- {$mode objfpc}{$H+}
- uses
- Classes,
- SysUtils,
- StrUtils,
- FileUtil,
- Zipper,
- fphttpclient,
- RegExpr,
- openssl,
- LazUTF8,
- opensslsockets,
- eventlog,
- Process;
- function OutLog(const Knd: TEventType; const Msg: string): string;
- begin
- case Knd of
- etError: Result := #27'[91m%s'#27'[0m';
- etInfo: Result := #27'[32m%s'#27'[0m';
- etDebug: Result := #27'[33m%s'#27'[0m';
- end;
- Writeln(stderr, UTF8ToConsole(Result.Format([Msg])));
- end;
- function AddPackage(const Path: string): string;
- begin
- if RunCommand('lazbuild', ['--add-package-link', Path], Result, [poStderrToOutPut]) then
- OutLog(etDebug, 'Add package:'#9 + Path)
- else
- begin
- ExitCode += 1;
- OutLog(etError, Result);
- end;
- end;
- function SelectString(const Input, Reg: string): string;
- var
- Line: string;
- begin
- Result := EmptyStr;
- with TRegExpr.Create do
- begin
- Expression := Reg;
- for Line in Input.Split(LineEnding) do
- if Exec(Line) then
- begin
- if Result <> EmptyStr then
- Result += LineEnding;
- Result += Line;
- end;
- Free;
- end;
- end;
- function RunTest(const Path: String): string;
- begin
- OutLog(etDebug, #9'run:'#9 + Path);
- if RunCommand(Path, ['--all', '--format=plain'], Result, [poStderrToOutPut]) then
- OutLog(etInfo, #9'success!')
- else
- begin
- ExitCode += 1;
- OutLog(etError, Result);
- end;
- end;
- function AddDDL(const Path: String): string;
- const
- LibPath: string = '/usr/lib/';
- var
- List: array of string;
- Last: integer;
- begin
- OutLog(etDebug, #9'add:'#9 + Path);
- List := Path.Split(DirectorySeparator);
- Last := High(List);
- if not FileExists(LibPath + List[Last]) then
- if RunCommand('sudo', ['bash', '-c', 'cp %s %s; ldconfig --verbose'.Format([Path, LibPath])], Result, [poStderrToOutPut]) then
- OutLog(etInfo, #9'success!')
- else
- begin
- ExitCode += 1;
- OutLog(etError, Result);
- end;
- end;
- function BuildProject(const Path: string): string;
- var
- Text: string;
- begin
- OutLog(etDebug, 'Build from:'#9 + Path);
- if RunCommand('lazbuild',
- ['--build-all', '--recursive', '--no-write-project', Path], Result, [poStderrToOutPut]) then
- begin
- Result := SelectString(Result, 'Linking').Split(' ')[2].Replace(LineEnding, EmptyStr);
- OutLog(etInfo, #9'to:'#9 + Result);
- Text := ReadFileToString(Path.Replace('.lpi', '.lpr'));
- if Text.Contains('program') and Text.Contains('consoletestrunner') then
- RunTest(Result)
- else if Text.Contains('library') and Text.Contains('exports') then
- AddDDL(Result)
- end
- else
- begin
- ExitCode += 1;
- OutLog(etError, SelectString(Result, '(Fatal|Error|/ld(\.[a-z]+)?):'));
- end;
- end;
- function DownloadFile(const Uri: string): string;
- var
- OutFile: TStream;
- begin
- InitSSLInterface;
- Result := GetTempFileName;
- OutFile := TFileStream.Create(Result, fmCreate or fmOpenWrite);
- with TFPHttpClient.Create(nil) do
- begin
- try
- AddHeader('User-Agent', 'Mozilla/5.0 (compatible; fpweb)');
- AllowRedirect := True;
- Get(Uri, OutFile);
- OutLog(etDebug, 'Download from %s to %s'.Format([Uri, Result]));
- finally
- Free;
- OutFile.Free;
- end;
- end;
- end;
- procedure UnZip(const ZipFile, ZipPath: string);
- begin
- with TUnZipper.Create do
- begin
- try
- FileName := ZipFile;
- OutputPath := ZipPath;
- Examine;
- UnZipAllFiles;
- OutLog(etDebug, 'Unzip from'#9 + ZipFile + #9'to'#9 + ZipPath);
- DeleteFile(ZipFile);
- finally
- Free;
- end;
- end;
- end;
- function InstallOPM(const Path: string): string;
- begin
- Result :=
- {$IFDEF MSWINDOWS}
- GetEnvironmentVariable('APPDATA') + '\.lazarus\onlinepackagemanager\packages\'
- {$ELSE}
- GetEnvironmentVariable('HOME') + '/.lazarus/onlinepackagemanager/packages/'
- {$ENDIF}
- + Path;
- if not DirectoryExists(Result) then
- begin
- if ForceDirectories(Result) then
- UnZip(DownloadFile('https://packages.lazarus-ide.org/%s.zip'.Format([Path])), Result);
- end;
- end;
-
- procedure RetrieveSubmodules;
- var CommandOutput: string;
- begin
- if FileExists('.gitmodules') then
- if RunCommand('git', ['submodule', 'update', '--init',
- '--force', '--remote'], CommandOutput, [poStderrToOutPut]) then
- OutLog(etInfo, CommandOutput)
- else
- begin
- ExitCode += 1;
- OutLog(etError, CommandOutput);
- end;
- end;
- function BuildAll(const Target: string; const Dependencies: array of string): string;
- var
- List: TStringList;
- DT: TDateTime;
- begin
- DT := Time;
- // GitHub already retrieves submodules
- List := FindAllFiles(GetCurrentDir, '*.lpk');
- try
- for Result in Dependencies do
- List.AddStrings(FindAllFiles(InstallOPM(Result), '*.lpk'));
- for Result in List do
- AddPackage(Result);
- List := FindAllFiles(Target, '*.lpi');
- List.Sort;
- for Result in List do
- if not Result.Contains('backup') and not Result.Contains('/use/') then
- BuildProject(Result);
- finally
- List.Free;
- end;
- if not RunCommand('delp', ['-r', GetCurrentDir], Result, [poStderrToOutPut]) then
- OutLog(etError, Result);
- OutLog(etDebug, 'Duration:'#9 + FormatDateTime('hh:nn:ss', Time - DT));
- end;
- begin
- try
- BuildAll('.', ['UEControls']);
- OutLog(etDebug, '------------');
- case ExitCode of
- 0: OutLog(etInfo, 'No Errors 😊');
- else
- OutLog(etError, 'Errors:'#9 + ExitCode.ToString);
- end;
- OutLog(etDebug, '------------');
- except
- on E: Exception do
- Writeln(E.ClassName, #9, E.Message);
- end;
- end.
|