diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef86d55..8bb165e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,8 +74,10 @@ jobs: ts: [nts, ts] os: ['2022'] include: - # PHP 7.4-8.3 use VS16, PHP 8.4 uses VS17. - # windows-2022 runners have both toolsets. + # PHP 7.4 requires VC15 (v141 toolset, MSVC 14.1x). + # PHP 8.0-8.3 use VS16, PHP 8.4 uses VS17. + # windows-2022 runners have vs16/vs17 but NOT vc15, + # so we install the v141 component for PHP 7.4. - php: '7.4' vs: vs16 - php: '8.0' @@ -92,6 +94,20 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install VC15 (v141) toolset for PHP 7.4 + if: matrix.php == '7.4' + shell: pwsh + run: | + Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\" + $installPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" + $component = "Microsoft.VisualStudio.Component.VC.v141.x86.x64" + $args = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$installPath`"", + '--add', $component, '--quiet', '--norestart', '--nocache') + $process = Start-Process -FilePath cmd.exe -ArgumentList $args -Wait -PassThru -WindowStyle Hidden + if ($process.ExitCode -ne 0) { + Write-Warning "vs_installer exited with code $($process.ExitCode)" + } + - name: Setup PHP SDK id: setup uses: php/setup-php-sdk@v0.12 diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml new file mode 100644 index 0000000..021c59c --- /dev/null +++ b/.github/workflows/windows-build.yml @@ -0,0 +1,100 @@ +name: Windows Build + +on: + push: + branches: ['**'] + paths: + - 'ext/**' + - '.github/workflows/windows-build.yml' + pull_request: + branches: ['**'] + paths: + - 'ext/**' + - '.github/workflows/windows-build.yml' + +jobs: + build-windows: + name: Windows - PHP ${{ matrix.php }} ${{ matrix.ts }} ${{ matrix.arch }} + runs-on: windows-${{ matrix.os }} + defaults: + run: + shell: cmd + strategy: + fail-fast: false + matrix: + php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4'] + arch: [x64] + ts: [nts, ts] + os: ['2022'] + include: + # PHP 7.4 requires VC15 (v141 toolset, MSVC 14.1x). + # PHP 8.0-8.3 use VS16, PHP 8.4 uses VS17. + # windows-2022 runners have vs16/vs17 but NOT vc15, + # so we install the v141 component for PHP 7.4. + - php: '7.4' + vs: vs16 + - php: '8.0' + vs: vs16 + - php: '8.1' + vs: vs16 + - php: '8.2' + vs: vs16 + - php: '8.3' + vs: vs16 + - php: '8.4' + vs: vs17 + + steps: + - uses: actions/checkout@v4 + + - name: Install VC15 (v141) toolset for PHP 7.4 + if: matrix.php == '7.4' + shell: pwsh + run: | + Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\" + $installPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" + $component = "Microsoft.VisualStudio.Component.VC.v141.x86.x64" + $args = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$installPath`"", + '--add', $component, '--quiet', '--norestart', '--nocache') + $process = Start-Process -FilePath cmd.exe -ArgumentList $args -Wait -PassThru -WindowStyle Hidden + if ($process.ExitCode -ne 0) { + Write-Warning "vs_installer exited with code $($process.ExitCode)" + } + + - name: Setup PHP SDK + id: setup + uses: php/setup-php-sdk@v0.12 + with: + version: ${{ matrix.php }} + arch: ${{ matrix.arch }} + ts: ${{ matrix.ts }} + + - name: Enable MSVC Developer Command Prompt + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: ${{ matrix.arch }} + toolset: ${{ steps.setup.outputs.toolset }} + + - name: phpize + working-directory: ext\mariadb_profiler + run: phpize + + - name: configure + working-directory: ext\mariadb_profiler + run: configure --enable-mariadb_profiler --with-prefix=%INSTALL_DIR% + + - name: nmake + working-directory: ext\mariadb_profiler + run: nmake + + - name: Verify DLL exists + shell: pwsh + run: | + $dll = Get-ChildItem -Path ext\mariadb_profiler -Recurse -Filter "php_mariadb_profiler.dll" | + Select-Object -First 1 + if (-not $dll) { + Write-Error "php_mariadb_profiler.dll not found" + exit 1 + } + Write-Host "Built DLL: $($dll.FullName)" + Write-Host "Size: $([math]::Round($dll.Length / 1KB, 1)) KB" diff --git a/ext/mariadb_profiler/php_mariadb_profiler_compat.h b/ext/mariadb_profiler/php_mariadb_profiler_compat.h index 35aa96d..bcc8bb9 100644 --- a/ext/mariadb_profiler/php_mariadb_profiler_compat.h +++ b/ext/mariadb_profiler/php_mariadb_profiler_compat.h @@ -242,6 +242,27 @@ static inline struct tm *profiler_localtime_r(const time_t *timep, struct tm *re # define LOCK_UN 8 # endif +/* + * Map a Windows error code to errno. + * PHP's internal _dosmaperr() is not exported for use by extensions, + * so we provide our own minimal mapping for the error codes we handle. + */ +static inline void profiler_dosmaperr(unsigned long winerr) +{ + switch (winerr) { + case ERROR_ACCESS_DENIED: errno = EACCES; break; + case ERROR_INVALID_HANDLE: errno = EBADF; break; + case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; + case ERROR_LOCK_VIOLATION: errno = EACCES; break; + case ERROR_SHARING_VIOLATION: errno = EACCES; break; + case ERROR_FILE_NOT_FOUND: errno = ENOENT; break; + case ERROR_PATH_NOT_FOUND: errno = ENOENT; break; + case ERROR_ALREADY_EXISTS: errno = EEXIST; break; + case ERROR_FILE_EXISTS: errno = EEXIST; break; + default: errno = EINVAL; break; + } +} + static inline int profiler_flock(int fd, int operation) { HANDLE h = (HANDLE)_get_osfhandle(fd); @@ -257,7 +278,7 @@ static inline int profiler_flock(int fd, int operation) if (UnlockFileEx(h, 0, MAXDWORD, MAXDWORD, &ov)) { return 0; } - _dosmaperr(GetLastError()); + profiler_dosmaperr(GetLastError()); return -1; } @@ -275,7 +296,7 @@ static inline int profiler_flock(int fd, int operation) if ((operation & LOCK_NB) && lasterr == ERROR_LOCK_VIOLATION) { errno = EWOULDBLOCK; } else { - _dosmaperr(lasterr); + profiler_dosmaperr(lasterr); } } return -1;