Skip to content

Windows build

Windows build #24

Workflow file for this run

name: Windows build
on:
workflow_dispatch:
inputs:
flavors:
description: "flavors, comma splited, empty for 'min,lite,max-swow', available: min, lite, max[-eventengine, like swow/swoole/libev], custom"
required: false
default: ""
archs:
description: "archs, comma splited, empty for all, available: x64, arm64"
required: false
default: ""
sapis:
description: "SAPIs, comma splited, empty for all, available: micro, micro-cli, cli"
required: false
default: ""
phpVers:
description: "PHP versions, empty for all, available: 8.0, 8.1, 8.2"
required: false
default: ""
customExtensions:
description: "custom extensions, used for custom flavor build"
required: false
default: ""
customLibraries:
description: "custom libraries, used for custom flavor build"
required: false
default: ""
# schedule:
# - cron: "33 4 * * *"
jobs:
gen-jobs:
name: Generate jobs
runs-on: windows-latest
outputs:
jobs: ${{ steps.gen-jobs.outputs.jobs }}
steps:
- name: Generate jobs
id: gen-jobs
shell: php {0}
run: |
<?php
function arg2arr(string $arg): array
{
return array_filter(array_map("trim", explode(',', $arg)));
}
$flavors = arg2arr(<<<'ARG'
${{ github.event.inputs.flavors }}
ARG);
$archs = arg2arr(<<<'ARG'
${{ github.event.inputs.archs }}
ARG);
$sapis = arg2arr(<<<'ARG'
${{ github.event.inputs.sapis }}
ARG);
$phpVers = arg2arr(<<<'ARG'
${{ github.event.inputs.phpVers }}
ARG);
if (!$flavors) {
$flavors = ['min', 'lite', 'max-swow'];
}
if (!$archs) {
$archs = ['x64', 'arm64'];
}
if (!$sapis) {
$sapis = ['micro', 'micro-cli', 'cli'];
}
if (!$phpVers) {
$phpVers = ['8.0', '8.1', '8.2'];
}
$customLibraries = <<<'ARG'
${{ github.event.inputs.customLibraries }}
ARG;
$customExtensions = <<<'ARG'
${{ github.event.inputs.customExtensions }}
ARG;
$customLibraries = trim($customLibraries);
$customExtensions = trim($customExtensions);
foreach ($archs as $arch) {
foreach ($phpVers as $phpVer) {
if ($arch === 'arm64' && version_compare($phpVer, '8.2', '<')) {
// arm64 only supported on PHP 8.2+
echo "skip arm64 $phpVer\n";
continue;
}
$job = [
'flavors' => $flavors,
'customLibraries' => $customLibraries,
'customExtensions' => $customExtensions,
'arch' => $arch,
'sapis' => $sapis,
'phpVer' => $phpVer,
];
$jobs[] = $job;
}
}
if (!$jobs) {
echo "no jobs generated\n";
exit(1);
}
$json = json_encode($jobs);
file_put_contents(getenv('GITHUB_OUTPUT'), "jobs=$json");
# $jsonDebug = <<<'JSON'
# [{
# "flavors": [
# "min"
# ],
# "customLibraries": "",
# "customExtensions": "",
# "arch": "arm64",
# "sapis": [
# "micro"
# ],
# "phpVer": "8.2"
# }]
# JSON;
# $json = json_encode(json_decode($jsonDebug, true));
# file_put_contents(getenv('GITHUB_OUTPUT'), "jobs=$json");
build:
name: ${{ matrix.phpVer }} ${{ matrix.arch }} ${{ toJson(matrix.flavors) }}
runs-on: windows-latest
# TODO: use docker
# container: "ghcr.io/dixyes/prepared-lwmbs:windows-${{ matrix.arch }}-src"
needs:
- gen-jobs
strategy:
max-parallel: 3
fail-fast: false
matrix:
include: ${{ fromJson(needs.gen-jobs.outputs.jobs) }}
steps:
- name: Restore tools and sources
uses: actions/cache/restore@v3
id: cache-restore
with:
path: |
C:\tools\php-sdk-binary-tools
C:\build\bin
C:\build\downloads
C:\build\src
C:\build\versionFile
key: ${{ runner.os }}-build-v1-${{ matrix.arch }}-${{ hashFiles('C:\build\versionFile') }}
restore-keys: |
${{ runner.os }}-build-v1-${{ matrix.arch }}-
- name: Prepare tools and sources
id: prepare
shell: pwsh
run: |
${env:GITHUB_TOKEN} = "${{ secrets.GITHUB_TOKEN }}"
# prepare lwmbs
New-Item -ItemType Container -Force C:\lwmbs
Set-Location C:\lwmbs
git init
if (0 -Ne $lastexitcode) {
exit 1
}
git remote add origin https://github.com/${{ github.repository }}
if (0 -Ne $lastexitcode) {
exit 1
}
git fetch --depth 1 origin ${{ github.sha }}
if (0 -Ne $lastexitcode) {
exit 1
}
git checkout ${{ github.sha }}
if (0 -Ne $lastexitcode) {
exit 1
}
if ( '${{steps.cache-restore.outputs.cache-hit}}' -ne 'true' ) {
Write-Output "cache miss, prepare tools"
# install php-sdk-binary-tools
git clone --depth 1 --single-branch --branch master https://github.com/php/php-sdk-binary-tools C:\tools\php-sdk-binary-tools
if (0 -Ne $lastexitcode) {
exit 1
}
# prepare nasm
Invoke-WebRequest -Uri "https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/win64/nasm-2.15.05-win64.zip" `
-OutFile "nasm-2.15.05-win64.zip"
unzip nasm-2.15.05-win64.zip
if (0 -Ne $lastexitcode) {
exit 1
}
New-Item -ItemType Container -Force C:\build\bin
Move-Item nasm-2.15.05/*.exe C:\build\bin\
Move-Item nasm-2.15.05/rdoff/*.exe C:\build\bin\
# download source
Set-Location C:\build
php C:\lwmbs\fetch_source.php `
"" `
"" `
"--phpVer=${{ matrix.phpVer }}" `
"--versionFile=C:\build\versionFile"
if (0 -Ne $lastexitcode) {
exit 1
}
}
$srcHash = (Get-FileHash -Path C:\build\versionFile -Algorithm SHA256).Hash.ToLower()
Write-Output "srcHash=$srcHash" | Out-File -FilePath "${env:GITHUB_OUTPUT}" -Append
Write-Output "PATH=${env:PATH};C:\build\bin" | Out-File -FilePath "${env:GITHUB_ENV}" -Append
- name: Save tools and sources
uses: actions/cache/save@v3
if: steps.cache-restore.outputs.cache-hit != 'true'
with:
path: |
C:\tools\php-sdk-binary-tools
C:\build\bin
C:\build\downloads
C:\build\src
C:\build\versionFile
key: ${{ runner.os }}-build-v1-${{ matrix.arch }}-${{ steps.prepare.outputs.srcHash }}
- name: Make build commands
shell: php {0}
run: |
<?php
$matrix = <<<'EOF'
${{ toJson(matrix) }}
EOF;
$matrix = json_decode($matrix, true);
$customLibraries = $matrix['customLibraries'];
$customExtensions = $matrix['customExtensions'];
$commands = [];
@mkdir('C:\build');
$output = fopen('C:\build\build.ps1', 'w');
$writeps = function (...$args) use ($output) {
fwrite($output, sprintf(...$args));
fwrite(STDOUT, sprintf(...$args));
};
$writeps(<<<PWSH
# NOTE: to build these binaries on your machine, you may require php8.1+, vs, git, cmake, 7z(-zstd/nanazip better), perl
\$buildDir = "C:\\build"
\$phpSdkDir = "C:\\tools\\php-sdk-binary-tools"
\$lwmbsDir = "C:\\lwmbs"
\$vsVer = "17"
\$outDir = "C:\\out"
Set-Location -Path \$buildDir
New-Item -Path \$buildDir -ItemType Directory -Force
# # prepare source for specified php version
# # you may select only libraries and extensions you will use
# # we donot do this because in actions it was cached
# & php \${lwmbsDir}\\fetch_source.php `
# "" `
# "" `
# "--phpVer={$matrix['phpVer']}" `
# "--versionFile=\${buildDir}\\versionFile"
# \$ret=\$LASTEXITCODE
# if (\$ret -ne 0) {
# Write-Host "::error::fetch source failed"
# exit 1
# }
Write-Host "::group::Show versions"
Get-Content \${buildDir}\\versionFile
Get-FileHash -Path \${buildDir}\\versionFile -Algorithm SHA256
Write-Host "::endgroup::"
PWSH);
$maxLibraries = 'zstd,libssh2,curl,zlib,brotli,libffi,openssl,libzip,bzip2,nghttp2,onig,libyaml,xz,libxml2,libpng';
$maxExtensions = 'dom,xml,simplexml,xmlwriter,xmlreader,opcache,bcmath,pdo,phar,mysqlnd,mysqli,pdo,pdo_mysql,mbstring,mbregex,session,ctype,fileinfo,filter,tokenizer,curl,ffi,redis,sockets,openssl,zip,zlib,bz2,yaml,zstd,gd';
foreach ($matrix['flavors'] as $flavor) {
$libraries = match ($flavor) {
'min' => 'libffi',
'lite' => 'zstd,zlib,libffi,libzip,bzip2,xz,onig',
'max', 'max-swow' => $maxLibraries,
'max-libev' => "{$maxLibraries},libev",
'max-swoole' => "{$maxLibraries},libstdc++",
'custom' => $customLibraries,
};
$extensions = match ($flavor) {
'min' => 'ffi,filter,tokenizer,ctype',
'lite' => 'opcache,ffi,filter,tokenizer,ctype,iconv,mbstring,mbregex,sockets,zip,zstd,zlib,bz2,phar,fileinfo',
'max' => $maxExtensions,
'max-swow' => "{$maxExtensions},swow",
'max-swoole' => "{$maxExtensions},swoole",
'max-libev' => "{$maxExtensions},libev",
'custom' => $customExtensions,
};
$writeps("\n\n");
$writeps(<<<PWSH
# ----- "$flavor" flavor -----
Write-Host "::group::Build $flavor libs"
# rebuild libs for this flavor to avoid cache
& php \${lwmbsDir}\build_libs.php `
"$libraries" `
"--phpBinarySDKDir=\$phpSdkDir" `
"--vsVer=\$vsVer" `
"--arch={$matrix['arch']}" `
"--fresh"
\$ret=\$LASTEXITCODE
Write-Host "::endgroup::"
if (\$ret -ne 0) {
Write-Host "::error::failed build lib for $flavor"
} else {
PWSH);
foreach ($matrix['sapis'] as $sapi) {
$command = match ($sapi) {
'micro' => 'build_micro.php',
'micro-cli' => 'build_micro.php --fakeCli',
'cli' => 'build_cli.php',
};
$targetBin = match ($sapi) {
'micro', 'micro-cli' => "\\src\\php-src\\{$matrix['arch']}\\Release_TS\\micro.sfx",
'cli' => "\\src\\php-src\\{$matrix['arch']}\\Release_TS\\php.exe",
};
$binName = match ($sapi) {
'micro' => "micro.sfx",
'micro-cli' => "micro_cli.sfx",
'cli' => "php.exe",
};
$targetBinPDB = match ($sapi) {
'micro', 'micro-cli' => "\\src\\php-src\\{$matrix['arch']}\\Release_TS\\micro.pdb",
'cli' => "\\src\\php-src\\{$matrix['arch']}\\Release_TS\\php.pdb",
};
$binNamePDB = match ($sapi) {
'micro' => "micro.pdb",
'micro-cli' => "micro_cli.pdb",
'cli' => "php.pdb",
};
// $writeps("\n");
// $writeps("# cleam php build dir\n");
$writeps("\n\n");
$writeps(<<<PWSH
Write-Host "::group::Build $flavor $sapi"
# $sapi
& php \${lwmbsDir}\\$command `
"$libraries" `
"$extensions" `
"--phpBinarySDKDir=\$phpSdkDir" `
"--vsVer=\$vsVer" `
"--arch={$matrix['arch']}"
\$ret=\$LASTEXITCODE
Write-Host "::endgroup::"
if (\$ret -ne 0) {
Write-Host "::error::failed build $flavor $sapi"
} else {
# copy the built bin out
New-Item -Path "\$outDir\\{$flavor}" -ItemType Directory -Force
Copy-Item -Path \${buildDir}$targetBin -Destination "\$outDir\\{$flavor}\\$binName" -Force
Copy-Item -Path \${buildDir}$targetBinPDB -Destination "\$outDir\\{$flavor}\\$binNamePDB" -Force
}
PWSH);
}
$writeps("\n\n");
$writeps(<<<PWSH
Write-Host "::group::Dump $flavor licenses"
# dump licenses
New-Item -Path "\$outDir\\{$flavor}/\\licenses" -ItemType Directory -Force
& php \${lwmbsDir}\\dump_licenses.php `
"\$outDir\\{$flavor}/\\licenses" `
"$libraries" `
"$extensions"
# copy versionFile
Copy-Item -Path \${buildDir}\\versionFile -Destination "\$outDir\\{$flavor}\\versionFile" -Force
Write-Host "::endgroup::"
}
PWSH);
}
$writeps("\n");
- name: Build
shell: pwsh
run: |
# Get-Item C:\build\src\php-src\ext\swow
C:\build\build.ps1