fix(windows): survive cmd.exe's 8191 character command line limit

- with big extension stacks (imagick) the link command lines exceed what
  cmd.exe allows and fail with 'The command line is too long'
- pass the collected LIBS_CLI/LIBS_CGI/LIBS_MICRO lib lists to link.exe
  through @response files, like php-src already does for its object lists
- compile the frankenphp -mthreads shim instead of generating a .bat:
  batch files run through cmd.exe and cap cgo link lines at 8191 chars,
  a real executable gets the full 32K and past that go writes a response
  file by itself; still probe-gated, still a stopgap for golang/go#80290
This commit is contained in:
m-this
2026-07-09 13:31:54 +02:00
parent 4d6f334cbb
commit c54fa78ad1
2 changed files with 84 additions and 12 deletions

View File

@@ -175,8 +175,9 @@ trait windows
}
}
$libs_cli = $this->makeLibsResponseFile($package, 'cli', "ws2_32.lib shell32.lib {$extra_libs}");
cmd()->cd($package->getSourceDir())
->exec("nmake /nologo {$debug_overrides}LIBS_CLI=\"ws2_32.lib shell32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= php.exe");
->exec("nmake /nologo {$debug_overrides}LIBS_CLI=\"{$libs_cli}\" EXTRA_LD_FLAGS_PROGRAM= php.exe");
$this->deployWindowsBinary($builder, $package, 'php-cli');
}
@@ -245,8 +246,9 @@ trait windows
}
}
$libs_cgi = $this->makeLibsResponseFile($package, 'cgi', "ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}");
cmd()->cd($package->getSourceDir())
->exec("nmake /nologo {$debug_overrides}LIBS_CGI=\"ws2_32.lib kernel32.lib advapi32.lib {$extra_libs}\" EXTRA_LD_FLAGS_PROGRAM= php-cgi.exe");
->exec("nmake /nologo {$debug_overrides}LIBS_CGI=\"{$libs_cgi}\" EXTRA_LD_FLAGS_PROGRAM= php-cgi.exe");
$this->deployWindowsBinary($builder, $package, 'php-cgi');
}
@@ -331,8 +333,9 @@ trait windows
$fake_cli = $package->getBuildOption('with-micro-fake-cli', false) ? ' /DPHP_MICRO_FAKE_CLI' : '';
$libs_micro = $this->makeLibsResponseFile($package, 'micro', "ws2_32.lib shell32.lib {$extra_libs}");
cmd()->cd($package->getSourceDir())
->exec("nmake /nologo {$debug_overrides}LIBS_MICRO=\"ws2_32.lib shell32.lib {$extra_libs}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" EXTRA_LD_FLAGS_PROGRAM= micro");
->exec("nmake /nologo {$debug_overrides}LIBS_MICRO=\"{$libs_micro}\" CFLAGS_MICRO=\"/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1{$fake_cli}\" EXTRA_LD_FLAGS_PROGRAM= micro");
$this->deployWindowsBinary($builder, $package, 'php-micro');
}
@@ -884,4 +887,17 @@ C_CODE;
$package->setOutput('PHP headers path for embed SAPI', $php_include_dir);
}
/**
* Write the collected lib list into a linker response file and return the @file
* token for the nmake command line. With big extension stacks (imagick alone pulls
* in ~60 static libs) the inline list can push the whole command past cmd.exe's
* 8191 character limit; link.exe reads @file without any length limit.
*/
private function makeLibsResponseFile(TargetPackage $package, string $sapi, string $libs): string
{
$file = "{$package->getSourceDir()}\\spc-libs-{$sapi}.rsp";
FileSystem::writeFile($file, $libs);
return "@{$file}";
}
}