setup-php/src/scripts/win32.ps1

472 lines
16 KiB
PowerShell
Raw Normal View History

2019-09-06 06:47:43 +07:00
param (
2019-12-26 20:01:18 +07:00
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$version = '7.4',
[Parameter(Position = 1, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
2020-11-25 07:09:44 +07:00
$dist
2019-09-06 06:47:43 +07:00
)
2020-05-27 17:53:52 +07:00
# Function to log start of a operation.
2019-10-17 03:11:13 +07:00
Function Step-Log($message) {
2019-10-23 16:57:40 +07:00
printf "\n\033[90;1m==> \033[0m\033[37;1m%s \033[0m\n" $message
2019-10-17 03:11:13 +07:00
}
2020-05-27 17:53:52 +07:00
# Function to log result of a operation.
2019-10-17 03:11:13 +07:00
Function Add-Log($mark, $subject, $message) {
2020-10-17 05:43:36 +07:00
if ($mark -eq $tick) {
printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $mark $subject $message
} else {
printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $mark $subject $message
2020-11-25 07:09:44 +07:00
if($env:fail_fast -eq 'true') {
2020-10-17 05:43:36 +07:00
exit 1;
}
}
2019-10-17 03:11:13 +07:00
}
2020-06-03 15:07:25 +07:00
# Function to add a line to a powershell profile safely.
Function Add-ToProfile {
param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$input_profile,
[Parameter(Position = 1, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$search,
[Parameter(Position = 2, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$value
)
if($null -eq (Get-Content $input_profile | findstr $search)) {
Add-Content -Path $input_profile -Value $value
}
}
2020-05-27 17:53:52 +07:00
# Function to fetch PATH from the registry.
Function Get-PathFromRegistry {
2020-06-03 15:07:25 +07:00
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","User") + ";" +
[System.Environment]::GetEnvironmentVariable("Path","Machine")
Add-ToProfile $current_profile 'Get-PathFromRegistry' 'Function Get-PathFromRegistry { $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "User") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "Machine") }; Get-PathFromRegistry'
}
2020-05-27 17:53:52 +07:00
# Function to add a location to PATH.
Function Add-Path {
param(
[string]$PathItem
)
$newPath = (Get-ItemProperty -Path 'hkcu:\Environment' -Name PATH).Path.replace("$PathItem;", '')
$newPath = $PathItem + ';' + $newPath
Set-ItemProperty -Path 'hkcu:\Environment' -Name Path -Value $newPath
Get-PathFromRegistry
}
2020-09-06 15:47:06 +07:00
# Function to make sure printf is in PATH.
Function Add-Printf {
if (-not(Test-Path "C:\Program Files\Git\usr\bin\printf.exe")) {
if(Test-Path "C:\msys64\usr\bin\printf.exe") {
New-Item -Path $bin_dir\printf.exe -ItemType SymbolicLink -Value C:\msys64\usr\bin\printf.exe
} else {
2020-11-11 03:53:45 +07:00
Invoke-WebRequest -Uri "$github/shivammathur/printf/releases/latest/download/printf-x64.zip" -OutFile "$bin_dir\printf.zip"
2020-09-06 15:47:06 +07:00
Expand-Archive -Path $bin_dir\printf.zip -DestinationPath $bin_dir -Force
}
} else {
New-Item -Path $bin_dir\printf.exe -ItemType SymbolicLink -Value "C:\Program Files\Git\usr\bin\printf.exe"
}
}
2020-05-27 17:53:52 +07:00
# Function to get a clean Powershell profile.
Function Get-CleanPSProfile {
if(-not(Test-Path -LiteralPath $profile)) {
New-Item -Path $profile -ItemType "file" -Force
}
Set-Content $current_profile -Value ''
2020-06-03 15:07:25 +07:00
Add-ToProfile $profile $current_profile.replace('\', '\\') ". $current_profile"
}
2020-10-30 12:58:54 +07:00
# Function to install a powershell package from GitHub.
2020-11-08 14:36:21 +07:00
Function Install-PSPackage() {
2020-10-30 12:58:54 +07:00
param(
[Parameter(Position = 0, Mandatory = $true)]
$package,
[Parameter(Position = 1, Mandatory = $true)]
$psm1_path,
[Parameter(Position = 2, Mandatory = $true)]
$url,
[Parameter(Position = 3, Mandatory = $true)]
$cmdlet
2020-10-30 12:58:54 +07:00
)
$module_path = "$bin_dir\$psm1_path.psm1"
2020-07-15 11:15:40 +07:00
if(-not (Test-Path $module_path -PathType Leaf)) {
2020-10-30 12:58:54 +07:00
$zip_file = "$bin_dir\$package.zip"
2020-11-11 03:53:45 +07:00
Invoke-WebRequest -Uri $url -OutFile $zip_file
Expand-Archive -Path $zip_file -DestinationPath $bin_dir -Force
}
2020-06-03 15:07:25 +07:00
Import-Module $module_path
2020-10-30 12:58:54 +07:00
Add-ToProfile $current_profile "$package-search" "Import-Module $module_path"
if($null -eq (Get-Command $cmdlet -ErrorAction SilentlyContinue)) {
Install-Module -Name $cmdlet -Force
}
2020-03-16 12:48:01 +07:00
}
Function Add-ExtensionPrerequisites{
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$extension
)
$deps_dir = "$ext_dir\$extension-vc$installed.VCVersion-$arch"
$extensions_with_dependencies = ('imagick')
if($extensions_with_dependencies.Contains($extension)) {
if(-not(Test-Path $deps_dir)) {
New-Item $deps_dir -Type Directory 2>&1 | Out-Null
Install-PhpExtensionPrerequisite -Extension $extension -InstallPath $deps_dir -PhpPath $php_dir
}
Get-ChildItem -Recurse -Path $deps_dir | ForEach-Object {
New-Item -Itemtype SymbolicLink -Path $php_dir -Name $_.Name -Target $_.FullName -Force >$null 2>&1
}
}
}
2020-05-27 17:53:52 +07:00
# Function to add PHP extensions.
Function Add-Extension {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$extension,
[Parameter(Position = 1, Mandatory = $false)]
[ValidateNotNull()]
[ValidateSet('stable', 'beta', 'alpha', 'devel', 'snapshot')]
[string]
2020-07-14 15:42:50 +07:00
$stability = 'stable',
[Parameter(Position = 2, Mandatory = $false)]
[ValidateNotNull()]
[ValidatePattern('^\d+(\.\d+){0,2}$')]
[string]
$extension_version = ''
)
2019-10-11 06:11:25 +07:00
try {
$extension_info = Get-PhpExtension -Path $php_dir | Where-Object { $_.Name -eq $extension -or $_.Handle -eq $extension }
2020-01-30 13:33:30 +07:00
if ($null -ne $extension_info) {
switch ($extension_info.State) {
'Builtin' {
Add-Log $tick $extension "Enabled"
}
'Enabled' {
Add-Log $tick $extension "Enabled"
}
default {
Add-ExtensionPrerequisites $extension
Enable-PhpExtension -Extension $extension_info.Handle -Path $php_dir
Add-Log $tick $extension "Enabled"
}
2019-10-11 06:11:25 +07:00
}
}
else {
Add-ExtensionPrerequisites $extension
2020-02-14 16:39:56 +07:00
if($extension_version -ne '') {
Install-PhpExtension -Extension $extension -Version $extension_version -MinimumStability $stability -MaximumStability $stability -Path $php_dir -NoDependencies
2020-02-16 01:55:50 +07:00
} else {
Install-PhpExtension -Extension $extension -MinimumStability $stability -MaximumStability $stability -Path $php_dir -NoDependencies
2020-02-14 16:39:56 +07:00
}
2020-02-16 01:55:50 +07:00
2020-01-30 13:33:30 +07:00
Add-Log $tick $extension "Installed and enabled"
2019-10-11 06:11:25 +07:00
}
}
catch {
2019-12-09 09:39:03 +07:00
Add-Log $cross $extension "Could not install $extension on PHP $($installed.FullVersion)"
}
}
2020-05-27 17:53:52 +07:00
# Function to remove PHP extensions.
2019-12-26 20:01:18 +07:00
Function Remove-Extension() {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
2019-12-26 20:01:18 +07:00
[ValidateLength(1, [int]::MaxValue)]
[string]
$extension
)
2019-12-26 20:01:18 +07:00
if(php -m | findstr -i $extension) {
2020-05-07 04:57:00 +07:00
try {
Disable-PhpExtension $extension $php_dir
if (Test-Path $ext_dir\php_$extension.dll) {
Remove-Item $ext_dir\php_$extension.dll
}
Add-Log $tick ":$extension" "Removed"
} catch {
Add-Log $cross ":$extension" "Could not remove $extension on PHP $($installed.FullVersion)"
}
} else {
Add-Log $tick ":$extension" "Could not find $extension on PHP $($installed.FullVersion)"
2019-12-26 20:01:18 +07:00
}
}
2020-07-07 18:06:32 +07:00
Function Edit-ComposerConfig() {
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$tool_path
)
Copy-Item $tool_path -Destination "$tool_path.phar"
php -r "try {`$p=new Phar('$tool_path.phar', 0);exit(0);} catch(Exception `$e) {exit(1);}"
if ($? -eq $False) {
Add-Log "$cross" "composer" "Could not download composer"
exit 1;
}
2021-02-20 19:24:40 +07:00
if (-not(Test-Path $composer_json)) {
Set-Content -Path $composer_json -Value "{}"
}
2021-02-02 07:43:50 +07:00
composer -q config -g process-timeout 0
Write-Output $composer_bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
2020-07-07 18:06:32 +07:00
if (Test-Path env:COMPOSER_TOKEN) {
2021-02-02 07:43:50 +07:00
composer -q config -g github-oauth.github.com $env:COMPOSER_TOKEN
2020-07-07 18:06:32 +07:00
}
}
2020-09-28 12:28:02 +07:00
# Function to extract tool version.
Function Get-ToolVersion() {
Param (
[Parameter(Position = 0, Mandatory = $true)]
$tool,
[Parameter(Position = 1, Mandatory = $true)]
$param
)
2021-04-26 08:25:12 +07:00
$alp = "[a-zA-Z0-9]"
$version_regex = "[0-9]+((\.{1}$alp+)+)(\.{0})(-$alp+){0,1}"
2020-09-28 12:28:02 +07:00
if($tool -eq 'composer') {
if ($param -eq 'snapshot') {
$composer_version = (Select-String -Pattern "const\sBRANCH_ALIAS_VERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern $version_regex | ForEach-Object { $_.matches.Value }) + '+' + (Select-String -Pattern "const\sVERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern "[a-zA-Z0-9]+" -AllMatches | ForEach-Object { $_.matches[2].Value })
2020-09-28 12:28:02 +07:00
} else {
$composer_version = Select-String -Pattern "const\sVERSION" -Path $bin_dir\composer -Raw | Select-String -Pattern $version_regex | ForEach-Object { $_.matches.Value }
2020-09-28 12:28:02 +07:00
}
Set-Variable -Name 'composer_version' -Value $composer_version -Scope Global
return "$composer_version"
2020-09-28 12:28:02 +07:00
}
return . $tool $param 2> $null | ForEach-Object { $_ -replace "composer $version_regex", '' } | Select-String -Pattern $version_regex | Select-Object -First 1 | ForEach-Object { $_.matches.Value }
}
2020-05-27 17:53:52 +07:00
# Function to add tools.
2019-12-27 08:26:49 +07:00
Function Add-Tool() {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
$url,
[Parameter(Position = 1, Mandatory = $true)]
[ValidateNotNull()]
2020-09-28 12:28:02 +07:00
$tool,
[Parameter(Position = 2, Mandatory = $true)]
[ValidateNotNull()]
$ver_param
2019-12-27 08:26:49 +07:00
)
2020-06-03 15:07:25 +07:00
if (Test-Path $bin_dir\$tool) {
Remove-Item $bin_dir\$tool
2020-01-26 12:41:36 +07:00
}
if($url.Count -gt 1) {
$url = $url[0]
}
$tool_path = "$bin_dir\$tool"
if (($url | Split-Path -Extension) -eq ".exe") {
$tool_path = "$tool_path.exe"
}
try {
Invoke-WebRequest -Uri $url -OutFile $tool_path
} catch {
if($url -match '.*github.com.*releases.*latest.*') {
try {
$url = $url.replace("releases/latest/download", "releases/download/" + ([regex]::match((Invoke-WebRequest -Uri ($url.split('/release')[0] + "/releases")).Content, "([0-9]+\.[0-9]+\.[0-9]+)/" + ($url.Substring($url.LastIndexOf("/") + 1))).Groups[0].Value).split('/')[0])
Invoke-WebRequest -Uri $url -OutFile $tool_path
} catch { }
}
}
2020-06-03 15:07:25 +07:00
if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$tool(.exe|.phar)*$").Count -gt 0)) {
$bat_content = @()
$bat_content += "@ECHO off"
$bat_content += "setlocal DISABLEDELAYEDEXPANSION"
$bat_content += "SET BIN_TARGET=%~dp0/" + $tool
$bat_content += "php %BIN_TARGET% %*"
Set-Content -Path $bin_dir\$tool.bat -Value $bat_content
Add-ToolsHelper $tool
Add-ToProfile $current_profile $tool "New-Alias $tool $bin_dir\$tool.bat" >$null 2>&1
2020-09-28 12:28:02 +07:00
$tool_version = Get-ToolVersion $tool $ver_param
Add-Log $tick $tool "Added $tool $tool_version"
2020-01-26 12:41:36 +07:00
} else {
Add-Log $cross $tool "Could not add $tool"
}
}
2020-05-27 17:53:52 +07:00
# Function to setup a tool using composer.
Function Add-Composertool() {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$tool,
[Parameter(Position = 1, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$release,
[Parameter(Position = 2, Mandatory = $true)]
[ValidateNotNull()]
[ValidateLength(1, [int]::MaxValue)]
[string]
$prefix
)
if($tool -match "prestissimo|composer-prefetcher" -and $composer_version.split('.')[0] -ne "1") {
Write-Output "::warning:: Skipping $tool, as it does not support Composer $composer_version. Specify composer:v1 in tools to use $tool"
Add-Log $cross $tool "Skipped"
Return
}
2021-02-20 19:24:40 +07:00
if(Test-Path $composer_lock) {
Remove-Item -Path $composer_lock -Force
}
2021-04-26 08:25:12 +07:00
(composer global require $prefix$release 2>&1 | Tee-Object -FilePath $env:APPDATA\Composer\composer.log) >$null 2>&1
2020-09-28 12:28:02 +07:00
$json = findstr $prefix$tool $env:APPDATA\Composer\composer.json
2021-04-26 08:25:12 +07:00
$log = findstr $prefix$tool $env:APPDATA\Composer\composer.log
if(Test-Path $composer_bin\composer) {
Copy-Item -Path "$bin_dir\composer" -Destination "$composer_bin\composer" -Force
}
Add-ToolsHelper $tool
2020-09-28 12:28:02 +07:00
if($json) {
2021-04-26 08:25:12 +07:00
$tool_version = Get-ToolVersion "Write-Output" "$log"
2020-09-28 12:28:02 +07:00
Add-Log $tick $tool "Added $tool $tool_version"
} else {
Add-Log $cross $tool "Could not setup $tool"
2019-12-27 08:26:49 +07:00
}
}
2020-05-27 17:53:52 +07:00
# Function to handle request to add PECL.
Function Add-Pecl() {
Add-Log $tick "PECL" "Use extensions input to setup PECL extensions on windows"
2019-12-27 08:26:49 +07:00
}
2019-12-26 20:01:18 +07:00
# Variables
$tick = ([char]8730)
$cross = ([char]10007)
$php_dir = 'C:\tools\php'
$ext_dir = "$php_dir\ext"
2020-06-03 15:07:25 +07:00
$bin_dir = $php_dir
2020-10-30 12:58:54 +07:00
$github = 'https://github.com'
2021-04-13 18:25:32 +07:00
$php_builder = "$github/shivammathur/php-builder-windows"
$composer_bin = "$env:APPDATA\Composer\vendor\bin"
2021-02-20 19:24:40 +07:00
$composer_json = "$env:APPDATA\Composer\composer.json"
$composer_lock = "$env:APPDATA\Composer\composer.lock"
$current_profile = "$env:TEMP\setup-php.ps1"
2019-12-26 20:01:18 +07:00
$ProgressPreference = 'SilentlyContinue'
$jit_versions = '8.[0-9]'
$nightly_versions = '8.[1-9]'
2020-06-03 15:07:25 +07:00
$cert_source='CurrentUser'
2020-11-08 14:36:21 +07:00
$enable_extensions = ('openssl', 'curl', 'mbstring')
$arch = 'x64'
if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') {
$arch = 'x86'
}
2019-12-26 20:01:18 +07:00
$ts = $env:PHPTS -eq 'ts'
if($env:PHPTS -ne 'ts') {
$env:PHPTS = 'nts'
}
if($env:RUNNER -eq 'self-hosted') {
$bin_dir = 'C:\tools\bin'
$php_dir = "$php_dir$version"
$ext_dir = "$php_dir\ext"
2020-06-03 15:07:25 +07:00
$cert_source='Curl'
Get-CleanPSProfile >$null 2>&1
New-Item $bin_dir -Type Directory 2>&1 | Out-Null
Add-Path -PathItem $bin_dir
if($version -lt 5.6) {
Add-Log $cross "PHP" "PHP $version is not supported on self-hosted runner"
2020-06-07 04:11:28 +07:00
Start-Sleep 1
exit 1
}
2020-06-03 15:07:25 +07:00
if ((Get-InstalledModule).Name -notcontains 'VcRedist') {
Install-Module -Name VcRedist -Force
}
New-Item $php_dir -Type Directory 2>&1 | Out-Null
Add-Path -PathItem $php_dir
setx PHPROOT $php_dir >$null 2>&1
} else {
$current_profile = "$PSHOME\Profile.ps1"
2020-06-03 15:07:25 +07:00
if(-not(Test-Path -LiteralPath $current_profile)) {
New-Item -Path $current_profile -ItemType "file" -Force >$null 2>&1
}
}
2020-09-06 15:47:06 +07:00
. $dist\..\src\scripts\tools\add_tools.ps1
2020-09-06 15:47:06 +07:00
Add-Printf >$null 2>&1
2019-12-26 20:01:18 +07:00
Step-Log "Setup PhpManager"
Install-PSPackage PhpManager PhpManager\PhpManager "$github/mlocati/powershell-phpmanager/releases/latest/download/PhpManager.zip" Get-Php >$null 2>&1
2019-12-26 20:01:18 +07:00
Add-Log $tick "PhpManager" "Installed"
Step-Log "Setup PHP"
2019-12-26 20:01:18 +07:00
$installed = $null
if (Test-Path -LiteralPath $php_dir -PathType Container) {
try {
$installed = Get-Php -Path $php_dir
} catch { }
}
$status = "Installed"
2021-07-12 18:30:40 +07:00
$extra_version = ""
if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version -replace '^(\d+(\.\d+)*).*', '$1.'))) -or $ts -ne $installed.ThreadSafe) {
if ($version -lt '7.0' -and (Get-InstalledModule).Name -notcontains 'VcRedist') {
Install-PSPackage VcRedist VcRedist-main\VcRedist\VcRedist "$github/aaronparker/VcRedist/archive/main.zip" Get-VcList >$null 2>&1
2019-12-26 20:01:18 +07:00
}
2020-12-17 05:50:39 +07:00
try {
if ($version -match $nightly_versions) {
2021-04-13 18:25:32 +07:00
Invoke-WebRequest -UseBasicParsing -Uri $php_builder/releases/latest/download/Get-PhpNightly.ps1 -OutFile $php_dir\Get-PhpNightly.ps1 > $null 2>&1
& $php_dir\Get-PhpNightly.ps1 -Architecture $arch -ThreadSafe $ts -Path $php_dir > $null 2>&1
2021-07-12 18:30:40 +07:00
$extra_version = " ($(Get-Content $php_dir\COMMIT))"
2020-12-17 05:50:39 +07:00
} else {
Install-Php -Version $version -Architecture $arch -ThreadSafe $ts -InstallVC -Path $php_dir -TimeZone UTC -InitialPhpIni Production -Force > $null 2>&1
}
} catch { }
} else {
if($version -match $jit_versions) {
('opcache.enable=1', 'opcache.jit_buffer_size=256M', 'opcache.jit=1235') | ForEach-Object { $p=$_.split('='); Set-PhpIniKey -Key $p[0] -Value $p[1] -Path $php_dir }
}
if($env:update -eq 'true') {
Update-Php $php_dir >$null 2>&1
$status = "Updated to"
} else {
$status = "Found"
}
2019-12-26 20:01:18 +07:00
}
$installed = Get-Php -Path $php_dir
2020-12-17 05:50:39 +07:00
if($installed.MajorMinorVersion -ne $version) {
Add-Log $cross "PHP" "Could not setup PHP $version"
exit 1
}
2020-12-17 22:19:20 +07:00
('date.timezone=UTC', 'memory_limit=-1', 'xdebug.mode=coverage') | ForEach-Object { $p=$_.split('='); Set-PhpIniKey -Key $p[0] -Value $p[1] -Path $php_dir }
if($version -lt "5.5") {
2021-04-13 18:25:32 +07:00
('libeay32.dll', 'ssleay32.dll') | ForEach-Object { Invoke-WebRequest -Uri "$php_builder/releases/download/openssl-1.0.2u/$_" -OutFile $php_dir\$_ >$null 2>&1 }
} else {
2020-11-08 14:36:21 +07:00
$enable_extensions += ('opcache')
}
2020-11-08 14:36:21 +07:00
Enable-PhpExtension -Extension $enable_extensions -Path $php_dir
2020-06-03 15:07:25 +07:00
Update-PhpCAInfo -Path $php_dir -Source $cert_source
Copy-Item -Path $dist\..\src\configs\*.json -Destination $env:RUNNER_TOOL_CACHE
New-Item -ItemType Directory -Path $composer_bin -Force 2>&1 | Out-Null
2021-07-12 18:30:40 +07:00
Write-Output "::set-output name=php-version::$($installed.FullVersion)"
Add-Log $tick "PHP" "$status PHP $($installed.FullVersion)$extra_version"