Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
185 changes: 185 additions & 0 deletions .github/workflows/make.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//castle-engine.io/modern_pascal

program Make;
{$mode objfpc}{$H+}

uses
Classes,
SysUtils,
StrUtils,
FileUtil,
LazFileUtils,
Zipper,
fphttpclient,
RegExpr,
openssl,
LazUTF8,
opensslsockets,
eventlog,
Process;

function OutLog(const Knd: TEventType; const Msg: string): string; cdecl;
var Line: string;
begin
case Knd of
etError: Result := #27'[31m%s'#27'[0m';
etInfo: Result := #27'[32m%s'#27'[0m';
etDebug: Result := #27'[33m%s'#27'[0m';
end;
if Knd = etError then ExitCode += 1;
for Line in Msg.Split(LineEnding) do
if not Line.Contains('/usr/lib/lazarus/') and
not Line.Contains('/onlinepackagemanager/') and
not Line.Contains('/units/') then
Writeln(stderr, UTF8ToConsole(Result.Format([Line])));
end;

function SelectString(const Input, Reg: string): string; cdecl;
var Line: string;
begin
Result := EmptyStr;
with TRegExpr.Create do begin
Expression := Reg;
for Line in Input.Split(LineEnding) do
if Exec(Line) then Result += Line + LineEnding;
Free;
end;
end;

function RunShell(const Command: String): string; cdecl;
begin
OutLog(etDebug, #9'Run:'#9 + Command);
if not RunCommand(
{$IFDEF MSWINDOWS}
'pwsh', [
'-NoExit',
'-NonInteractive',
'-Command',
'$ErrorActionPreference = "stop"; Set-PSDebug -Strict; ' + Command + '; exit'
]
{$ELSE}
'bash', ['-c', 'set -euo pipefail; ' + Command]
{$ENDIF}
, Result, [poStderrToOutPut, poWaitOnExit]) then
OutLog(etError, Result);
end;

function AddPackage(const Path: string; const Link: boolean): string;
var Line: string;
begin
if Link then Line := '--add-package-link'
else Line := '--build-all --recursive --no-write-project';
Result := {$IFDEF MSWINDOWS}
'(cocoa|x11|_template)' {$ELSE}
'(cocoa|gdi|_template)' {$ENDIF};
OutLog(etDebug, 'AddPackage:'#9 + Path);
if SelectString(Path, Result) = EmptyStr then
RunShell('lazbuild %s %s'.Format([Line, Path]));
end;

function AddLibrary(const Path: String): string; cdecl;
begin
Result := '/usr/lib/';
OutLog(etDebug, 'AddLibrary:'#9 + Path);
if not FileExists(Result + ExtractFileName(Path)) then
RunShell('sudo cp %s %s; ldconfig'.Format([Path, Result]));
end;

function BuildProject(const Path: string): string; cdecl;
var Text: string;
begin
OutLog(etDebug, 'BuildProject from:'#9 + Path);
if not RunCommand('lazbuild',
['--build-all', '--recursive', '--no-write-project', Path], Result, [poStderrToOutPut, poWaitOnExit])
then OutLog(etError, SelectString(Result, '(Fatal|Error):'))
else begin
Result := SelectString(Result, 'Linking').Split(' ')[2].Replace(LineEnding, EmptyStr);
OutLog(etInfo, #9'to:'#9 + Result + #10);
Text := ReadFileToString(Path.Replace('.lpi', '.lpr'));
if Text.Contains('program') and Text.Contains('consoletestrunner') then
RunShell('%s --all --format=plain'.Format([Result]))
else if Text.Contains('library') and Text.Contains('exports') then
AddLibrary(Result);
end;
end;

function ExtractPackage(const ZipFile: string): string; cdecl;
begin
Result := GetEnvironmentVariable({$IFDEF MSWINDOWS}'APPDATA'{$ELSE}'HOME'{$ENDIF})
+ '/.lazarus/onlinepackagemanager/packages/'.Replace('/', DirectorySeparator)
+ ZipFile.Split('_')[1];
OutLog(etDebug, 'ExtPackage from:'#9 + ZipFile + #10#9'to:'#9 + Result);
if not DirectoryExists(Result) and ForceDirectories(Result) then
with TUnZipper.Create do begin
try
FileName := ZipFile;
OutputPath := Result;
Examine;
UnZipAllFiles;
DeleteFile(ZipFile);
finally
Free;
end;
end;
end;

function GetPackage(const Uri, Package: string): string; cdecl;
var FileStream: TStream;
begin
Result := '%s_%s'.Format([GetTempFileName, Package]);
OutLog(etDebug, 'GetPackage from'#9 + Uri + #10#9'to:'#9 + Result);
{$IFDEF MSWINDOWS}
RunShell('Invoke-WebRequest -Uri %s -OutFile %s'.Format([Uri + Package + '.zip', Result]));
{$ELSE}
InitSSLInterface;
FileStream := 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 + Package + '.zip', FileStream);
finally
Free;
FileStream.Free;
end;
end;
{$ENDIF}
end;

function BuildAll(const OutDep: array of string): string;
var
Item: string;
DT: TDateTime;
begin
DT := Time;
OutLog(etDebug, #10'#----------------------------------[GET OUT DEPENDENS]----------------------------------#'#10);
for Item in OutDep do
for Result in FindAllFiles(ExtractPackage(GetPackage('https://packages.lazarus-ide.org/', Item)), '*.lpk') do
AddPackage(Result, true);
OutLog(etDebug, #10'#----------------------------------[GET IN DEPENDENS]----------------------------------#'#10);
for Result in FindAllFiles(GetCurrentDir + DirectorySeparator, '*.lpk') do
AddPackage(Result, true);
OutLog(etDebug, #10'#----------------------------------[BUILD PROJECTS]----------------------------------#'#10);
for Result in FindAllFiles(GetCurrentDir, '*.lpi') do
if not Result.Contains(DirectorySeparator + 'use' + DirectorySeparator) then
BuildProject(Result);
OutLog(etDebug, #10'#----------------------------------[ RESULT ]----------------------------------#'#10);
OutLog(etDebug, 'Duration:'#9 + FormatDateTime('hh:nn:ss', Time - DT));
case ExitCode of
0: OutLog(etInfo, #9'Errors:'#9 + ExitCode.ToString);
else OutLog(etError, #9'Errors:'#9 + ExitCode.ToString);
end;
end;

begin
try
if ParamCount > 0 then
case ParamStr(1) of
'build': BuildAll(['BGRAControls']);
else OutLog(etError, ParamStr(1));
end;
except
on E: Exception do
OutLog(etError, E.ClassName + #9 + E.Message);
end;
end.
68 changes: 68 additions & 0 deletions .github/workflows/make.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env pwsh
#-------------------------------------------------------------------------------
# FILTERS AND FUNCTIONS
#-------------------------------------------------------------------------------

Filter Out-Log {
$(
If (! (Test-Path -Path Variable:LastExitCode)) {
"$(Get-Date -uformat '%y-%m-%d_%T')$([char]27)[33m {0}$([char]27)[0m" -f $_
} ElseIf ($LastExitCode -eq 0) {
"$(Get-Date -uformat '%y-%m-%d_%T')$([char]27)[32m {0}$([char]27)[0m" -f $_
} Else {
"$(Get-Date -uformat '%y-%m-%d_%T')$([char]27)[31m [{0}]`t{1}$([char]27)[0m" -f $LastExitCode, $_
}
) | Out-Host
}

Filter Get-Url {
'Get-Url {0}' -f $_ | Out-Log
$pattern = $_
$baseUrl = 'https://fossies.org/windows/misc/'
$baseUrl + (
(Invoke-WebRequest -Uri $baseUrl -UseBasicParsing).Links.href |
Where-Object { $_ -match '^{0}.*(exe|msi)$' -f $pattern }
)[-1]
}

Filter Get-Package {
$OutFile = '{0}.{1}' -f (New-TemporaryFile).FullName, (Split-Path -Path $_ -Leaf).Split('?')[0]
Invoke-WebRequest -OutFile $OutFile -Uri $_
'Get-Package from {0} to {1}' -f $_, $OutFile | Out-Log
$OutFile
}

Function Install-Package {
$Input | ForEach-Object {
If ((Split-Path -Path $_ -Leaf).Split('.')[-1] -eq 'msi') {
$arguments = @('/passive', '/package', $_ )
Start-Process -FilePath 'msiexec' -ArgumentList $arguments -Wait -NoNewWindow
} Else {
$arguments = @('/SP-', '/VERYSILENT', '/NORESTART', '/SUPPRESSMSGBOXES')
Start-Process -FilePath $_ -ArgumentList $arguments -Wait -NoNewWindow
}
'Install-Package {0}' -f $_ | Out-Log
Remove-Item $_
}
}

#-------------------------------------------------------------------------------
# MAIN ENDPOINT
#-------------------------------------------------------------------------------

$ErrorActionPreference = 'stop'
Set-PSDebug -Strict
@(
'https://download.lazarus-ide.org/Lazarus%20Windows%2064%20bits/Lazarus%204.6/lazarus-4.6-fpc-3.2.2-win64.exe'
'https://slproweb.com/download/Win64OpenSSL_Light-4_0_0.msi'
) | Get-Package | Install-Package
$env:PATH+=';{0}\OpenSSL-Win64\tools' -f $env:PROGRAMFILES
(Get-Command 'openssl').Source | Out-Log
$env:PATH+=';C:\Lazarus'
(Get-Command 'lazbuild').Source | Out-Log
$env:PATH+=';C:\Lazarus\fpc\3.2.2\bin\x86_64-win64'
(Get-Command 'instantfpc').Source | Out-Log
$env:INSTANTFPCOPTIONS='-FuC:\Lazarus\components\lazutils'
$env:DYLD_LIBRARY_PATH='{0}\OpenSSL-Win64\lib' -f $env:PROGRAMFILES
& instantfpc '.github/workflows/make.pas' build | Out-Log
Exit $LastExitCode
17 changes: 17 additions & 0 deletions .github/workflows/make.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
################################################################################

set -xeuo pipefail
if [[ -f '/etc/os-release' ]]; then
sudo bash -c '
apt-get update
apt-get install -y lazarus
' >/dev/null
declare -rx INSTANTFPCOPTIONS='-Fu/usr/lib/lazarus/*/components/lazutils'
elif [[ -f '/System/Library/CoreServices/SystemVersion.plist' ]]; then
brew install --cask lazarus >/dev/null
OPENSSL=$(brew --prefix openssl@1.1)
PATH+=":/Applications/Lazarus:${OPENSSL%\n}/bin"
declare -rx DYLD_LIBRARY_PATH="${OPENSSL%\n}/lib" \
INSTANTFPCOPTIONS='-Fu/Applications/Lazarus/components/lazutils'
fi
47 changes: 47 additions & 0 deletions .github/workflows/make.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
name: Make

on:
schedule:
- cron: '0 0 1 * *'
push:
branches:
- "**"
pull_request:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
make:
runs-on: ${{ matrix.os }}
timeout-minutes: 120
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
arch:
- x86_64

steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive

- name: Build on Unix
if: runner.os != 'Windows'
shell: bash
run: |
source '.github/workflows/make.sh'
instantfpc '.github/workflows/make.pas' build

- name: Build on Windows
if: runner.os == 'Windows'
shell: powershell
run: |
pwsh -File '.github/workflows/make.ps1'