-
-
Notifications
You must be signed in to change notification settings - Fork 340
build frankenphp and embed after shared extensions #871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ker doesn't drop libphp.a symbols that extensions need
2833314 to
460eb02
Compare
|
I don't know how to get macos to work :( |
|
Do we have any other scenario of exporting dynamic symbols? |
|
I don't think so. Only for things that use libphp.a. The php code itself (libphp.so, cli, fpm, likely micro) uses all necessary symbols so they aren't stripped. |
|
I can't think of any other uses for this, but I think it might be clearer to separate it into "exporting the archive's symbol list to a file" and "getting dynamic symbol parameters from the symbol file." Also, I don't see the point of caching this arguments, as we only need to read the file at most twice. |
|
I had considered splitting it up before, but found that I can't think of a situation where it makes sense to use for anything but libphp.a. We don't want to export symbols from anything but core php code - extensions will pull in the library symbols they need themselves. |
|
How about: // after building embed
SystemUtil::exportDynamicSymbols(BUILD_LIB_PATH . '/libphp.a');
// use symbols in sanity check, frankenphp builds, etc.
$dyn_symbols = SystemUtil::getDynamicExportedSymbols(BUILD_LIB_PATH . '/libphp.a');
$exportDynamicSymbols = function (string $lib_file) {
// check
if (!is_file($lib_file)) {
throw new WrongUsageException("The lib archive file {$lib_file} does not exist, please build it first.");
}
// shell out
$cmd = 'nm -g --defined-only -P ' . escapeshellarg($lib_file) . ' | grep -vE ".o]?:$" | grep -vE "^@?$" | awk -F "[\t| ]" "{print $1}"';
$result = shell()->execWithResult($cmd);
if ($result[0] !== 0) {
throw new ExecutionException($cmd, 'Failed to get defined symbols from ' . $lib_file);
}
$defined = array_unique($result[1]);
sort($defined);
// export
if (SPCTarget::getTargetOS() === 'Linux') {
file_put_contents("{$lib_file}.dynsym", "{\n" . implode(";\n", array_map(fn ($x) => " {$x}", $defined)) . ";\n};\n");
} else {
file_put_contents("{$lib_file}.dynsym", implode("\n", $defined) . "\n");
}
};
$getDynamicExportedSymbols = function (string $lib_file): ?string {
$symbol_file = "{$lib_file}.dynsym";
if (!is_file($symbol_file)) {
return null;
}
$argument = "-Wl,--dynamic-list={$symbol_file}";
if (ToolchainManager::getToolchainClass() === ZigToolchain::class) {
$argument = '-Wl,--export-dynamic'; // https://github.com/ziglang/zig/issues/24662
}
if (SPCTarget::getTargetOS() !== 'Linux') {
$argument = "-Wl,-exported_symbols_list,{$symbol_file}";
}
return $argument;
}; |
|
I think the idea is good, but $cmd = 'nm -g --defined-only -P ' . escapeshellarg($lib_file) . ' | grep -vE ".o]?:$" | grep -vE "^@?$" | awk -F "[\t| ]" "{print $1}"';is overkill. Keep some good old php code in there to keep it debuggable. |
make sure the linker doesn't drop libphp.a symbols that extensions need
What does this PR do?
previously, if we built libphp.a, the linker cleans up dead symbols when creating the executable. This is undesirable, because when you try to load shared extensions with frankenphp, it will fail to load them with undefined references to
zend_ini_display_cb...and other functions.Now, instead of marking all symbols as dynamic, which massively bloats the executable size, we loop through all shared extensions, figure out what symbols they need, match that against what libphp.a provides and then mark those as export-dynamic.
Keep in mind that this does still increase the executable size a little! But it only takes effect when people build shared extensions.