allow building and linking with shared instead of static libs

This commit is contained in:
henderkes 2026-02-19 21:26:18 +07:00
parent 8c4e3d58a3
commit cf69c02624
15 changed files with 35 additions and 55 deletions

View File

@ -79,6 +79,7 @@ SPC_MICRO_PATCHES=static_extensions_win32,cli_checks,disable_huge_page,vcruntime
SPC_LIBC=musl SPC_LIBC=musl
; uncomment to link libc dynamically on musl ; uncomment to link libc dynamically on musl
; SPC_MUSL_DYNAMIC=true ; SPC_MUSL_DYNAMIC=true
SPC_STATIC_LIBS=true
; Recommended: specify your target here. Zig toolchain will be used. ; Recommended: specify your target here. Zig toolchain will be used.
; examples: ; examples:
@ -97,7 +98,7 @@ LD=${SPC_LINUX_DEFAULT_LD}
; default compiler flags, used in CMake toolchain file, openssl and pkg-config build ; default compiler flags, used in CMake toolchain file, openssl and pkg-config build
SPC_DEFAULT_C_FLAGS="-fPIC -Os" SPC_DEFAULT_C_FLAGS="-fPIC -Os"
SPC_DEFAULT_CXX_FLAGS="-fPIC -Os" SPC_DEFAULT_CXX_FLAGS="-fPIC -Os"
SPC_DEFAULT_LD_FLAGS="" SPC_DEFAULT_LD_FLAGS="-Wl,--as-needed"
; upx executable path ; upx executable path
UPX_EXEC=${PKG_ROOT_PATH}/bin/upx UPX_EXEC=${PKG_ROOT_PATH}/bin/upx
; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches ; phpmicro patches, for more info, see: https://github.com/easysoft/phpmicro/tree/master/patches
@ -115,7 +116,7 @@ SPC_CMD_VAR_PHP_EMBED_TYPE="static"
; EXTRA_CFLAGS for `configure` and `make` php ; EXTRA_CFLAGS for `configure` and `make` php
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}" SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="-g -fstack-protector-strong -fno-ident -fPIE ${SPC_DEFAULT_C_FLAGS}"
; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so ; EXTRA_LDFLAGS for `make` php, can use -release to set a soname for libphp.so
SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="" SPC_CMD_VAR_PHP_MAKE_EXTRA_LDFLAGS="-Wl,--as-needed"
; optional, path to openssl conf. This affects where openssl will look for the default CA. ; optional, path to openssl conf. This affects where openssl will look for the default CA.
; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls ; default on Debian/Alpine: /etc/ssl, default on RHEL: /etc/pki/tls

View File

@ -862,17 +862,13 @@
}, },
"openssl": { "openssl": {
"source": "openssl", "source": "openssl",
"static-libs-unix": [ "pkg-configs": [
"libssl.a", "openssl"
"libcrypto.a"
], ],
"static-libs-windows": [ "static-libs-windows": [
"libssl.lib", "libssl.lib",
"libcrypto.lib" "libcrypto.lib"
], ],
"headers": [
"openssl"
],
"lib-depends": [ "lib-depends": [
"zlib" "zlib"
] ]
@ -974,10 +970,10 @@
}, },
"unixodbc": { "unixodbc": {
"source": "unixodbc", "source": "unixodbc",
"static-libs-unix": [ "pkg-configs": [
"libodbc.a", "odbc",
"libodbccr.a", "odbccr",
"libodbcinst.a" "odbcinst"
], ],
"lib-depends": [ "lib-depends": [
"libiconv" "libiconv"

View File

@ -42,8 +42,9 @@ class openssl extends BSDLibraryBase
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"./Configure no-shared {$extra} " . "./Configure " .
'--prefix=/ ' . // use prefix=/ (getenv('SPC_STATIC_LIBS') ? 'no-shared' : '') .
" {$extra} " . '--prefix=/ ' . // use prefix=/
"--libdir={$lib} " . "--libdir={$lib} " .
'--openssldir=/etc/ssl ' . '--openssldir=/etc/ssl ' .
'BSD-' . arch2gnu($this->builder->getOption('arch')) 'BSD-' . arch2gnu($this->builder->getOption('arch'))

View File

@ -316,7 +316,7 @@ class LinuxBuilder extends UnixBuilderBase
*/ */
private function getMakeExtraVars(): array private function getMakeExtraVars(): array
{ {
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs')); $config = (new SPCConfigUtil($this, ['libs_only_deps' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
$static = SPCTarget::isStatic() ? '-all-static' : ''; $static = SPCTarget::isStatic() ? '-all-static' : '';
$lib = BUILD_LIB_PATH; $lib = BUILD_LIB_PATH;
return array_filter([ return array_filter([

View File

@ -59,8 +59,9 @@ class openssl extends LinuxLibraryBase
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"{$env} ./Configure no-shared {$extra} " . "./Configure " .
'--prefix=' . BUILD_ROOT_PATH . ' ' . (getenv('SPC_STATIC_LIBS') ? 'no-shared' : '') .
" {$extra} " . '--prefix=' . BUILD_ROOT_PATH . ' ' .
'--libdir=' . BUILD_LIB_PATH . ' ' . '--libdir=' . BUILD_LIB_PATH . ' ' .
"--openssldir={$openssl_dir} " . "--openssldir={$openssl_dir} " .
"{$zlib_extra}" . "{$zlib_extra}" .

View File

@ -43,7 +43,9 @@ class openssl extends MacOSLibraryBase
shell()->cd($this->source_dir)->initializeEnv($this) shell()->cd($this->source_dir)->initializeEnv($this)
->exec( ->exec(
"./Configure no-shared {$extra} " . "./Configure " .
(getenv('SPC_STATIC_LIBS') ? 'no-shared' : '') .
" {$extra} " .
'--prefix=' . BUILD_ROOT_PATH . ' ' . // use prefix=/ '--prefix=' . BUILD_ROOT_PATH . ' ' . // use prefix=/
'--libdir=lib ' . '--libdir=lib ' .
'--openssldir=/etc/ssl ' . '--openssldir=/etc/ssl ' .

View File

@ -20,11 +20,6 @@ trait brotli
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon'); FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlidec.pc', 'Libs: -L${libdir} -lbrotlidec', 'Libs: -L${libdir} -lbrotlidec -lbrotlicommon');
FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon'); FileSystem::replaceFileLineContainsString(BUILD_LIB_PATH . '/pkgconfig/libbrotlienc.pc', 'Libs: -L${libdir} -lbrotlienc', 'Libs: -L${libdir} -lbrotlienc -lbrotlicommon');
shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a'); shell()->cd(BUILD_ROOT_PATH . '/lib')->exec('ln -sf libbrotlicommon.a libbrotli.a');
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libbrotli') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
if (file_exists(BUILD_BIN_PATH . '/brotli')) { if (file_exists(BUILD_BIN_PATH . '/brotli')) {
unlink(BUILD_BIN_PATH . '/brotli'); unlink(BUILD_BIN_PATH . '/brotli');

View File

@ -17,12 +17,6 @@ trait libargon2
$this->patchPkgconfPrefix(['libargon2.pc']); $this->patchPkgconfPrefix(['libargon2.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'libargon2') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
if (file_exists(BUILD_BIN_PATH . '/argon2')) { if (file_exists(BUILD_BIN_PATH . '/argon2')) {
unlink(BUILD_BIN_PATH . '/argon2'); unlink(BUILD_BIN_PATH . '/argon2');
} }

View File

@ -27,11 +27,5 @@ trait liblz4
->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH); ->exec("make install PREFIX='' DESTDIR=" . BUILD_ROOT_PATH);
$this->patchPkgconfPrefix(['liblz4.pc']); $this->patchPkgconfPrefix(['liblz4.pc']);
foreach (FileSystem::scanDirFiles(BUILD_ROOT_PATH . '/lib/', false, true) as $filename) {
if (str_starts_with($filename, 'liblz4') && (str_contains($filename, '.so') || str_ends_with($filename, '.dylib'))) {
unlink(BUILD_ROOT_PATH . '/lib/' . $filename);
}
}
} }
} }

View File

@ -93,8 +93,6 @@ trait postgresql
// remove dynamic libs // remove dynamic libs
shell()->cd($this->source_dir . '/build') shell()->cd($this->source_dir . '/build')
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so.*")
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.so")
->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib"); ->exec("rm -rf {$this->getBuildRootPath()}/lib/*.dylib");
FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber'); FileSystem::replaceFileStr("{$this->getLibDir()}/pkgconfig/libpq.pc", '-lldap', '-lldap -llber');

View File

@ -33,7 +33,7 @@ class openssl extends WindowsLibraryBase
->execWithWrapper( ->execWithWrapper(
$this->builder->makeSimpleWrapper($this->perl), $this->builder->makeSimpleWrapper($this->perl),
'Configure zlib VC-WIN64A ' . 'Configure zlib VC-WIN64A ' .
'no-shared ' . (getenv('SPC_STATIC_LIBS') ? 'no-shared' : '') .
'--prefix=' . quote(BUILD_ROOT_PATH) . ' ' . '--prefix=' . quote(BUILD_ROOT_PATH) . ' ' .
'--with-zlib-lib=' . quote(BUILD_LIB_PATH) . ' ' . '--with-zlib-lib=' . quote(BUILD_LIB_PATH) . ' ' .
'--with-zlib-include=' . quote(BUILD_INCLUDE_PATH) . ' ' . '--with-zlib-include=' . quote(BUILD_INCLUDE_PATH) . ' ' .

View File

@ -61,8 +61,9 @@ class PkgConfigUtil
*/ */
public static function getCflags(string $pkg_config_str): string public static function getCflags(string $pkg_config_str): string
{ {
$static = getenv('SPC_STATIC_LIBS') ? '--static' : '';
// get other things // get other things
$result = self::execWithResult("pkg-config --static --cflags-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config $static --cflags-only-other {$pkg_config_str}");
return trim($result); return trim($result);
} }
@ -78,11 +79,12 @@ class PkgConfigUtil
public static function getLibsArray(string $pkg_config_str): array public static function getLibsArray(string $pkg_config_str): array
{ {
// Use this instead of shell() to avoid unnecessary outputs // Use this instead of shell() to avoid unnecessary outputs
$result = self::execWithResult("pkg-config --static --libs-only-l {$pkg_config_str}"); $static = getenv('SPC_STATIC_LIBS') ? '--static' : '';
$result = self::execWithResult("pkg-config $static --libs-only-l {$pkg_config_str}");
$libs = explode(' ', trim($result)); $libs = explode(' ', trim($result));
// get other things // get other things
$result = self::execWithResult("pkg-config --static --libs-only-other {$pkg_config_str}"); $result = self::execWithResult("pkg-config $static --libs-only-other {$pkg_config_str}");
// convert libxxx.a to -L{path} -lxxx // convert libxxx.a to -L{path} -lxxx
$exp = explode(' ', trim($result)); $exp = explode(' ', trim($result));
foreach ($exp as $item) { foreach ($exp as $item) {

View File

@ -20,13 +20,10 @@ class SPCConfigUtil
private bool $libs_only_deps; private bool $libs_only_deps;
private bool $absolute_libs;
/** /**
* @param array{ * @param array{
* no_php?: bool, * no_php?: bool,
* libs_only_deps?: bool, * libs_only_deps?: bool
* absolute_libs?: bool
* } $options Options pass to spc-config * } $options Options pass to spc-config
*/ */
public function __construct(?BuilderBase $builder = null, array $options = []) public function __construct(?BuilderBase $builder = null, array $options = [])
@ -36,7 +33,6 @@ class SPCConfigUtil
} }
$this->no_php = $options['no_php'] ?? false; $this->no_php = $options['no_php'] ?? false;
$this->libs_only_deps = $options['libs_only_deps'] ?? false; $this->libs_only_deps = $options['libs_only_deps'] ?? false;
$this->absolute_libs = $options['absolute_libs'] ?? false;
} }
/** /**
@ -77,7 +73,7 @@ class SPCConfigUtil
ob_get_clean(); ob_get_clean();
$ldflags = $this->getLdflagsString(); $ldflags = $this->getLdflagsString();
$cflags = $this->getIncludesString($libraries); $cflags = $this->getIncludesString($libraries);
$libs = $this->getLibsString($libraries, !$this->absolute_libs); $libs = $this->getLibsString($libraries);
// additional OS-specific libraries (e.g. macOS -lresolv) // additional OS-specific libraries (e.g. macOS -lresolv)
if ($extra_libs = SPCTarget::getRuntimeLibs()) { if ($extra_libs = SPCTarget::getRuntimeLibs()) {
@ -256,7 +252,7 @@ class SPCConfigUtil
return '-L' . BUILD_LIB_PATH; return '-L' . BUILD_LIB_PATH;
} }
private function getLibsString(array $libraries, bool $use_short_libs = true): string private function getLibsString(array $libraries): string
{ {
$lib_names = []; $lib_names = [];
$frameworks = []; $frameworks = [];
@ -316,8 +312,8 @@ class SPCConfigUtil
if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') { if (in_array('imap', $libraries) && SPCTarget::getLibc() === 'glibc') {
$lib_names[] = '-lcrypt'; $lib_names[] = '-lcrypt';
} }
if (!$use_short_libs) { if (getenv('SPC_STATIC_LIBS')) {
$lib_names = array_map(fn ($l) => $this->getFullLibName($l), $lib_names); $lib_names = array_map(fn ($l) => $this->getStaticLibname($l), $lib_names);
} }
return implode(' ', $lib_names); return implode(' ', $lib_names);
} }
@ -331,7 +327,7 @@ class SPCConfigUtil
return '-l' . substr($lib, 3, -2); return '-l' . substr($lib, 3, -2);
} }
private function getFullLibName(string $lib) private function getStaticLibname(string $lib)
{ {
if (!str_starts_with($lib, '-l')) { if (!str_starts_with($lib, '-l')) {
return $lib; return $lib;
@ -339,7 +335,7 @@ class SPCConfigUtil
$libname = substr($lib, 2); $libname = substr($lib, 2);
$staticLib = BUILD_LIB_PATH . '/' . "lib{$libname}.a"; $staticLib = BUILD_LIB_PATH . '/' . "lib{$libname}.a";
if (file_exists($staticLib)) { if (file_exists($staticLib)) {
return $staticLib; return "-l:lib{$libname}.a";
} }
return $lib; return $lib;
} }

View File

@ -133,8 +133,8 @@ class UnixAutoconfExecutor extends Executor
private function getDefaultConfigureArgs(): array private function getDefaultConfigureArgs(): array
{ {
return [ return [
'--disable-shared', getenv('SPC_STATIC_LIBS') ? '--disable-shared' : '--enable-shared',
'--enable-static', getenv('SPC_STATIC_LIBS') ? '--enable-static' : '--disable-static',
"--prefix={$this->library->getBuildRootPath()}", "--prefix={$this->library->getBuildRootPath()}",
'--with-pic', '--with-pic',
'--enable-pic', '--enable-pic',

View File

@ -151,7 +151,7 @@ class UnixCMakeExecutor extends Executor
'-DCMAKE_INSTALL_LIBDIR=lib', '-DCMAKE_INSTALL_LIBDIR=lib',
'-DCMAKE_INSTALL_INCLUDEDIR=include', '-DCMAKE_INSTALL_INCLUDEDIR=include',
'-DPOSITION_INDEPENDENT_CODE=ON', '-DPOSITION_INDEPENDENT_CODE=ON',
'-DBUILD_SHARED_LIBS=OFF', '-DBUILD_SHARED_LIBS=' . getenv('SPC_STATIC_LIBS') ? 'OFF' : 'ON',
"-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}", "-DCMAKE_TOOLCHAIN_FILE={$this->makeCmakeToolchainFile()}",
]); ]);
} }