diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 5740a631..54748575 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -38,6 +38,9 @@ jobs: - name: "windows-x64" os: "ubuntu-latest" filename: "spc-windows-x64.exe" + permissions: + id-token: write + attestations: write steps: - name: "Checkout" uses: "actions/checkout@v5" @@ -105,6 +108,12 @@ jobs: fi fi + - name: "Generate build provenance attestation" + if: github.event_name != 'pull_request' + uses: actions/attest-build-provenance@v4 + with: + subject-path: "${{ github.workspace }}/${{ matrix.operating-system.name == 'windows-x64' && 'spc.exe' || 'spc' }}" + - name: "Copy file" run: | if [ "${{ matrix.operating-system.name }}" != "windows-x64" ]; then diff --git a/src/StaticPHP/Doctor/Item/LinuxMuslCheck.php b/src/StaticPHP/Doctor/Item/LinuxMuslCheck.php index df3b5241..1fe7ed00 100644 --- a/src/StaticPHP/Doctor/Item/LinuxMuslCheck.php +++ b/src/StaticPHP/Doctor/Item/LinuxMuslCheck.php @@ -73,13 +73,20 @@ class LinuxMuslCheck $prefix = 'sudo '; logger()->warning('Current user is not root, using sudo for running command'); } + $sysEnv = ['CC' => 'gcc', 'CXX' => 'g++', 'AR' => 'ar', 'LD' => 'ld', 'RANLIB' => 'ranlib']; + $envFlags = ''; + foreach ($sysEnv as $k => $v) { + $envFlags .= "{$k}={$v} "; + } + $envFlags = rtrim($envFlags); $shell = shell()->cd(SOURCE_PATH . '/musl-wrapper') - ->exec('CC=gcc CXX=g++ AR=ar LD=ld ./configure --disable-gcc-wrapper') - ->exec('CC=gcc CXX=g++ AR=ar LD=ld make -j'); + ->setEnv($sysEnv) + ->exec('./configure --disable-gcc-wrapper') + ->exec('make -j'); if ($prefix !== '') { - f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install"); + f_passthru('cd ' . SOURCE_PATH . "/musl-wrapper && {$envFlags} {$prefix}make install"); } else { - $shell->exec("CC=gcc CXX=g++ AR=ar LD=ld {$prefix}make install"); + $shell->exec("{$prefix}make install"); } return true; } diff --git a/src/StaticPHP/Runtime/Executor/UnixCMakeExecutor.php b/src/StaticPHP/Runtime/Executor/UnixCMakeExecutor.php index 82fa468a..9fc00840 100644 --- a/src/StaticPHP/Runtime/Executor/UnixCMakeExecutor.php +++ b/src/StaticPHP/Runtime/Executor/UnixCMakeExecutor.php @@ -302,9 +302,12 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES "{$include}") set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES "{$include}") CMAKE; - // Whoops, linux may need CMAKE_AR sometimes + // pin AR/RANLIB so cmake uses zig-ar/zig-ranlib instead of system /usr/bin/ranlib (zig archives need it) if (PHP_OS_FAMILY === 'Linux') { - $toolchain .= "\nSET(CMAKE_AR \"ar\")"; + $ar = getenv('SPC_DEFAULT_AR') ?: getenv('AR') ?: 'ar'; + $ranlib = getenv('SPC_DEFAULT_RANLIB') ?: (getenv('RANLIB') ?: 'ranlib'); + $toolchain .= "\nSET(CMAKE_AR \"{$ar}\")"; + $toolchain .= "\nSET(CMAKE_RANLIB \"{$ranlib}\")"; } FileSystem::writeFile(SOURCE_PATH . '/toolchain.cmake', $toolchain); return $created = realpath(SOURCE_PATH . '/toolchain.cmake'); diff --git a/src/StaticPHP/Toolchain/ClangBrewToolchain.php b/src/StaticPHP/Toolchain/ClangBrewToolchain.php index 5d8963ef..23260954 100644 --- a/src/StaticPHP/Toolchain/ClangBrewToolchain.php +++ b/src/StaticPHP/Toolchain/ClangBrewToolchain.php @@ -15,6 +15,7 @@ class ClangBrewToolchain extends ClangNativeToolchain GlobalEnvManager::putenv("SPC_DEFAULT_CC={$homebrew_prefix}/opt/llvm/bin/clang"); GlobalEnvManager::putenv("SPC_DEFAULT_CXX={$homebrew_prefix}/opt/llvm/bin/clang++"); GlobalEnvManager::putenv("SPC_DEFAULT_AR={$homebrew_prefix}/opt/llvm/bin/llvm-ar"); + GlobalEnvManager::putenv("SPC_DEFAULT_RANLIB={$homebrew_prefix}/opt/llvm/bin/llvm-ranlib"); GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld'); GlobalEnvManager::addPathIfNotExists("{$homebrew_prefix}/opt/llvm/bin"); } diff --git a/src/StaticPHP/Toolchain/ClangNativeToolchain.php b/src/StaticPHP/Toolchain/ClangNativeToolchain.php index 27ae2b65..7602c3ed 100644 --- a/src/StaticPHP/Toolchain/ClangNativeToolchain.php +++ b/src/StaticPHP/Toolchain/ClangNativeToolchain.php @@ -21,6 +21,7 @@ class ClangNativeToolchain implements UnixToolchainInterface GlobalEnvManager::putenv('SPC_DEFAULT_CC=clang'); GlobalEnvManager::putenv('SPC_DEFAULT_CXX=clang++'); GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar'); + GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib'); GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld'); } diff --git a/src/StaticPHP/Toolchain/GccNativeToolchain.php b/src/StaticPHP/Toolchain/GccNativeToolchain.php index 7c339e69..9aecb7e0 100644 --- a/src/StaticPHP/Toolchain/GccNativeToolchain.php +++ b/src/StaticPHP/Toolchain/GccNativeToolchain.php @@ -18,6 +18,7 @@ class GccNativeToolchain implements UnixToolchainInterface GlobalEnvManager::putenv('SPC_DEFAULT_CC=gcc'); GlobalEnvManager::putenv('SPC_DEFAULT_CXX=g++'); GlobalEnvManager::putenv('SPC_DEFAULT_AR=ar'); + GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=ranlib'); GlobalEnvManager::putenv('SPC_DEFAULT_LD=ld'); } diff --git a/src/StaticPHP/Toolchain/ZigToolchain.php b/src/StaticPHP/Toolchain/ZigToolchain.php index 36e42d04..f9048ad3 100644 --- a/src/StaticPHP/Toolchain/ZigToolchain.php +++ b/src/StaticPHP/Toolchain/ZigToolchain.php @@ -16,6 +16,7 @@ class ZigToolchain implements UnixToolchainInterface GlobalEnvManager::putenv('SPC_DEFAULT_CC=zig-cc'); GlobalEnvManager::putenv('SPC_DEFAULT_CXX=zig-c++'); GlobalEnvManager::putenv('SPC_DEFAULT_AR=zig-ar'); + GlobalEnvManager::putenv('SPC_DEFAULT_RANLIB=zig-ranlib'); GlobalEnvManager::putenv('SPC_DEFAULT_LD=zig-ld.lld'); // Generate additional objects needed for zig toolchain diff --git a/src/globals/functions.php b/src/globals/functions.php index 549ef498..c824bd3d 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -256,10 +256,30 @@ function clean_spaces(string $string): string */ function deduplicate_flags(string $flags): string { - $tokens = preg_split('/\s+/', trim($flags)); + // Flags that take their value as a separate token. + static $paired = [ + '-Xclang', '-Xpreprocessor', '-Xlinker', '-Xassembler', + '-framework', '-arch', '-target', + '-include', '-imacros', '-isystem', '-isysroot', '-iquote', '-idirafter', + '-MT', '-MF', '-MQ', + ]; + + $tokens = preg_split('/\s+/', trim($flags)) ?: []; + + // Group paired flag+value into a single atom before dedup. + $atoms = []; + $n = count($tokens); + for ($i = 0; $i < $n; ++$i) { + if (in_array($tokens[$i], $paired, true) && $i + 1 < $n) { + $atoms[] = $tokens[$i] . ' ' . $tokens[$i + 1]; + ++$i; + } else { + $atoms[] = $tokens[$i]; + } + } // Reverse, unique, reverse back - keeps last occurrence of duplicates - $deduplicated = array_reverse(array_unique(array_reverse($tokens))); + $deduplicated = array_reverse(array_unique(array_reverse($atoms))); return implode(' ', $deduplicated); } diff --git a/src/globals/patch/spc_fix_avx512_cache_before_80400.patch‎ b/src/globals/patch/spc_fix_avx512_cache_before_80400.patch similarity index 100% rename from src/globals/patch/spc_fix_avx512_cache_before_80400.patch‎ rename to src/globals/patch/spc_fix_avx512_cache_before_80400.patch