mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-02-07 12:44:20 +00:00
libiconv-darwin: add support for static builds
This commit is contained in:
parent
67dea634b9
commit
067ad05942
@ -0,0 +1,72 @@
|
||||
From a3e945c630180e9aa182603207238302e58fe8fe Mon Sep 17 00:00:00 2001
|
||||
From: Randy Eckenrode <randy@largeandhighquality.com>
|
||||
Date: Sat, 25 May 2024 19:03:58 -0400
|
||||
Subject: [PATCH 1/2] Support static module loading
|
||||
|
||||
---
|
||||
citrus/citrus_module.c | 21 ++++++++++++++++++---
|
||||
1 file changed, 18 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/citrus/citrus_module.c b/citrus/citrus_module.c
|
||||
index 5103d30..c22c9da 100644
|
||||
--- a/citrus/citrus_module.c
|
||||
+++ b/citrus/citrus_module.c
|
||||
@@ -324,22 +324,36 @@ out:
|
||||
return (path[0] ? path : NULL);
|
||||
}
|
||||
|
||||
+#if defined(ENABLE_STATIC)
|
||||
+#include "static-modules.h"
|
||||
+#endif
|
||||
+
|
||||
void *
|
||||
_citrus_find_getops(_citrus_module_t handle, const char *modname,
|
||||
const char *ifname)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
void *p;
|
||||
-
|
||||
+#if defined(ENABLE_STATIC)
|
||||
+ const struct getops_pair* res = lookup_getops(modname, strlen(modname));
|
||||
+ p = res ? res->opsfn : NULL;
|
||||
+#else
|
||||
snprintf(name, sizeof(name), "_citrus_%s_%s_getops",
|
||||
modname, ifname);
|
||||
p = dlsym((void *)handle, name);
|
||||
+#endif
|
||||
return (p);
|
||||
}
|
||||
|
||||
int
|
||||
_citrus_load_module(_citrus_module_t *rhandle, const char *encname)
|
||||
{
|
||||
+#if defined(ENABLE_STATIC)
|
||||
+ if (is_known_encoding(encname, strnlen(encname, MAX_WORD_LENGTH)) > MAX_HASH_VALUE) {
|
||||
+ return (EINVAL);
|
||||
+ }
|
||||
+ *rhandle = (_citrus_module_t)encodings;
|
||||
+#else
|
||||
const char *p;
|
||||
char path[PATH_MAX];
|
||||
void *handle;
|
||||
@@ -368,14 +382,15 @@ _citrus_load_module(_citrus_module_t *rhandle, const char *encname)
|
||||
}
|
||||
|
||||
*rhandle = (_citrus_module_t)handle;
|
||||
-
|
||||
+#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
_citrus_unload_module(_citrus_module_t handle)
|
||||
{
|
||||
-
|
||||
+#if !defined(ENABLE_STATIC)
|
||||
if (handle)
|
||||
dlclose((void *)handle);
|
||||
+#endif
|
||||
}
|
||||
--
|
||||
2.44.1
|
||||
|
@ -19,6 +19,19 @@ i18nmoduledir = prefix_libdir / 'i18n'
|
||||
esdbdir = prefix_datadir / 'i18n/esdb'
|
||||
csmapperdir = prefix_datadir / 'i18n/csmapper'
|
||||
|
||||
is_static = get_option('default_library') == 'static'
|
||||
static_suffix = is_static ? '_static' : ''
|
||||
|
||||
# Generators
|
||||
if is_static
|
||||
gperf_bin = find_program('gperf', required : true)
|
||||
gperf = generator(
|
||||
gperf_bin,
|
||||
arguments : ['@INPUT@', '--output-file=@OUTPUT@'],
|
||||
output : '@BASENAME@.h'
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
# Libraries
|
||||
libcharset = library(
|
||||
@ -37,15 +50,16 @@ install_headers(
|
||||
)
|
||||
|
||||
libiconv = library(
|
||||
'iconv',
|
||||
'iconv' + static_suffix,
|
||||
build_rpath : fs.parent(libcharset.full_path()),
|
||||
c_args : [
|
||||
f'-D_PATH_I18NMODULE="@i18nmoduledir@"',
|
||||
f'-D_PATH_ESDB="@esdbdir@"',
|
||||
f'-D_PATH_CSMAPPER="@csmapperdir@"'
|
||||
f'-D_PATH_CSMAPPER="@csmapperdir@"',
|
||||
is_static ? '-DENABLE_STATIC=1' : [ ]
|
||||
],
|
||||
darwin_versions : '7',
|
||||
install : true,
|
||||
install : not is_static,
|
||||
include_directories : ['citrus', 'libcharset'],
|
||||
link_args : ['-Wl,-reexport_library', fs.name(libcharset.full_path())],
|
||||
link_depends : [libcharset],
|
||||
@ -84,6 +98,7 @@ libiconv = library(
|
||||
'citrus/iconvctl.c',
|
||||
'citrus/iconvlist.c',
|
||||
'citrus/iconv.c',
|
||||
is_static ? gperf.process('static-modules.gperf') : [ ]
|
||||
],
|
||||
soversion : '2'
|
||||
)
|
||||
@ -99,19 +114,6 @@ install_man(
|
||||
)
|
||||
|
||||
|
||||
# Binaries
|
||||
executable(
|
||||
'iconv',
|
||||
install : true,
|
||||
include_directories : ['citrus', 'libcharset'],
|
||||
link_with : [libiconv],
|
||||
sources : [
|
||||
'iconv/iconv.c'
|
||||
]
|
||||
)
|
||||
install_man('iconv/iconv.1')
|
||||
|
||||
|
||||
# Data
|
||||
## csmapper
|
||||
csmapper_modules = [
|
||||
@ -216,6 +218,7 @@ libiconv_modules = [
|
||||
'mapper_zone'
|
||||
]
|
||||
|
||||
modules = [ ]
|
||||
foreach module : libiconv_modules
|
||||
module_source = module.to_lower()
|
||||
module_path = 'libiconv_modules' / module
|
||||
@ -230,14 +233,19 @@ foreach module : libiconv_modules
|
||||
# See: https://github.com/apple-oss-distributions/libiconv/blob/81be60a93521c931a01aab9c747dd2b078bc0679/libiconv.xcodeproj/project.pbxproj#L2549-L2556
|
||||
# See also: https://cgit.freebsd.org/src/tree/lib/libiconv_modules/mapper_parallel/Makefile?id=9241ebc796c11cf133c550f188f324bd2c12d89a
|
||||
if module == 'mapper_parallel'
|
||||
# Skip including mapper_parallel since it’s the same as mapper_serial, which would result in duplicate symbols.
|
||||
if is_static
|
||||
continue
|
||||
endif
|
||||
|
||||
module_source = 'mapper_serial'
|
||||
module_path = 'libiconv_modules/mapper_serial'
|
||||
endif
|
||||
|
||||
library(
|
||||
modules += library(
|
||||
module,
|
||||
darwin_versions : '1',
|
||||
install : true,
|
||||
install : not is_static,
|
||||
install_dir : i18nmoduledir,
|
||||
include_directories : [module_path, 'citrus', 'libcharset'] + extra_headers,
|
||||
link_with : [libiconv],
|
||||
@ -249,6 +257,38 @@ foreach module : libiconv_modules
|
||||
endforeach
|
||||
|
||||
|
||||
# Bundle the modules into libiconv.a
|
||||
if is_static
|
||||
objects = [libiconv.extract_all_objects(recursive : true)]
|
||||
foreach module : modules
|
||||
objects += module.extract_all_objects(recursive : true)
|
||||
endforeach
|
||||
|
||||
libiconv = static_library(
|
||||
'iconv',
|
||||
install : true,
|
||||
objects : objects
|
||||
)
|
||||
endif
|
||||
|
||||
|
||||
# Binaries
|
||||
executable(
|
||||
'iconv',
|
||||
install : true,
|
||||
include_directories : ['citrus', 'libcharset'],
|
||||
link_with : [
|
||||
libiconv,
|
||||
# Darwin’s system `iconv` relies on the reexported symbols from libiconv
|
||||
is_static ? libcharset : [ ]
|
||||
],
|
||||
sources : [
|
||||
'iconv/iconv.c'
|
||||
]
|
||||
)
|
||||
install_man('iconv/iconv.1')
|
||||
|
||||
|
||||
# Tests
|
||||
if get_option('tests') == true
|
||||
## Only required for running the tests
|
||||
@ -259,7 +299,11 @@ if get_option('tests') == true
|
||||
suite,
|
||||
dependencies : [atf],
|
||||
include_directories : ['citrus', 'libcharset'],
|
||||
link_with : [libiconv],
|
||||
link_with : [
|
||||
libiconv,
|
||||
# Make sure the libcharset reexport is working by relying on libiconv to provide its symbols.
|
||||
is_static ? libcharset : [ ]
|
||||
],
|
||||
sources : [test_src]
|
||||
)
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
atf,
|
||||
gperf,
|
||||
libiconvReal,
|
||||
meson,
|
||||
ninja,
|
||||
@ -10,6 +11,9 @@
|
||||
gitUpdater,
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (stdenv) hostPlatform;
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libiconv";
|
||||
version = "99";
|
||||
@ -19,6 +23,9 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"dev"
|
||||
];
|
||||
|
||||
# Propagate `out` only when there are dylibs to link (i.e., don’t propagate when doing a static build).
|
||||
propagatedBuildOutputs = lib.optionalString (!hostPlatform.isStatic) "out";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "apple-oss-distributions";
|
||||
repo = "libiconv";
|
||||
@ -26,7 +33,11 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
hash = "sha256-TGt6rsU52ztfW2rCqwnhMAExLbexI/59IoDOGY+XGu0=";
|
||||
};
|
||||
|
||||
inherit (libiconvReal) setupHooks;
|
||||
setupHooks =
|
||||
libiconvReal.setupHooks
|
||||
++ lib.optionals hostPlatform.isStatic [ ./static-setup-hook.sh ];
|
||||
|
||||
patches = lib.optionals hostPlatform.isStatic [ ./0001-Support-static-module-loading.patch ];
|
||||
|
||||
postPatch =
|
||||
''
|
||||
@ -41,30 +52,42 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
header
|
||||
|
||||
cp ${./nixpkgs_test.c} tests/libiconv/nixpkgs_test.c
|
||||
''
|
||||
+ lib.optionalString hostPlatform.isStatic ''
|
||||
cp ${./static-modules.gperf} static-modules.gperf
|
||||
'';
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
];
|
||||
nativeBuildInputs =
|
||||
[
|
||||
meson
|
||||
ninja
|
||||
]
|
||||
# Dynamic builds use `dlopen` to load modules, but static builds have to link them all.
|
||||
# `gperf` is used to generate a lookup table from module to ops functions.
|
||||
++ lib.optionals hostPlatform.isStatic [ gperf ];
|
||||
|
||||
mesonBuildType = "release";
|
||||
|
||||
mesonFlags = [ (lib.mesonBool "tests" finalAttrs.doInstallCheck) ];
|
||||
|
||||
postInstall = lib.optionalString stdenv.isDarwin ''
|
||||
${stdenv.cc.targetPrefix}install_name_tool "$out/lib/libiconv.2.dylib" \
|
||||
-change '@rpath/libcharset.1.dylib' "$out/lib/libcharset.1.dylib"
|
||||
'';
|
||||
postInstall =
|
||||
lib.optionalString (stdenv.isDarwin && !hostPlatform.isStatic) ''
|
||||
${stdenv.cc.targetPrefix}install_name_tool "$out/lib/libiconv.2.dylib" \
|
||||
-change '@rpath/libcharset.1.dylib' "$out/lib/libcharset.1.dylib"
|
||||
''
|
||||
# Move the static library to the `dev` output
|
||||
+ lib.optionalString hostPlatform.isStatic ''
|
||||
moveToOutput lib "$dev"
|
||||
'';
|
||||
|
||||
# Tests have to be run in `installCheckPhase` because libiconv expects to `dlopen`
|
||||
# modules from `$out/lib/i18n`.
|
||||
nativeInstallCheckInputs = [ pkg-config ];
|
||||
installCheckInputs = [ atf ];
|
||||
|
||||
doInstallCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
doInstallCheck = stdenv.buildPlatform.canExecute hostPlatform;
|
||||
|
||||
# Can’t use `mesonCheckPhase` because it runs the wrong hooks for `installCheckPhase`.
|
||||
installCheckPhase = ''
|
||||
|
73
pkgs/by-name/li/libiconv-darwin/static-modules.gperf
Normal file
73
pkgs/by-name/li/libiconv-darwin/static-modules.gperf
Normal file
@ -0,0 +1,73 @@
|
||||
%language=ANSI-C
|
||||
%compare-strncmp
|
||||
%pic
|
||||
%readonly-tables
|
||||
%{
|
||||
#include "citrus_namespace.h"
|
||||
#include "citrus_types.h"
|
||||
#include "citrus_module.h"
|
||||
#include "citrus_hash.h"
|
||||
|
||||
#include "citrus_iconv.h"
|
||||
#include "citrus_mapper.h"
|
||||
#include "citrus_stdenc.h"
|
||||
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(BIG5);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(DECHanyu);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(DECKanji);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(EUC);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(EUCTW);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(GBK2K);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(HZ);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(ISO2022);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(JOHAB);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(MSKanji);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(UES);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(UTF1632);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(UTF7);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(UTF8);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(UTF8MAC);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(VIQR);
|
||||
extern _CITRUS_STDENC_GETOPS_FUNC(ZW);
|
||||
|
||||
extern _CITRUS_ICONV_GETOPS_FUNC(iconv_none);
|
||||
extern _CITRUS_ICONV_GETOPS_FUNC(iconv_std);
|
||||
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_646);
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_none);
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_parallel);
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_serial);
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_std);
|
||||
extern _CITRUS_MAPPER_GETOPS_FUNC(mapper_zone);
|
||||
%}
|
||||
%define lookup-function-name lookup_getops
|
||||
%define hash-function-name is_known_encoding
|
||||
%define string-pool-name encodings
|
||||
%struct-type
|
||||
struct getops_pair { int name; void* opsfn; };
|
||||
%%
|
||||
BIG5, _citrus_BIG5_stdenc_getops
|
||||
DECHanyu, _citrus_DECHanyu_stdenc_getops
|
||||
DECKanji, _citrus_DECKanji_stdenc_getops
|
||||
EUC, _citrus_EUC_stdenc_getops
|
||||
EUCTW, _citrus_EUCTW_stdenc_getops
|
||||
GBK2K, _citrus_GBK2K_stdenc_getops
|
||||
HZ, _citrus_HZ_stdenc_getops
|
||||
ISO2022, _citrus_ISO2022_stdenc_getops
|
||||
JOHAB, _citrus_JOHAB_stdenc_getops
|
||||
MSKanji, _citrus_MSKanji_stdenc_getops
|
||||
UES, _citrus_UES_stdenc_getops
|
||||
UTF1632, _citrus_UTF1632_stdenc_getops
|
||||
UTF7, _citrus_UTF7_stdenc_getops
|
||||
UTF8, _citrus_UTF8_stdenc_getops
|
||||
UTF8MAC, _citrus_UTF8MAC_stdenc_getops
|
||||
VIQR, _citrus_VIQR_stdenc_getops
|
||||
ZW, _citrus_ZW_stdenc_getops
|
||||
iconv_none, _citrus_iconv_none_iconv_getops
|
||||
iconv_std, _citrus_iconv_std_iconv_getops
|
||||
mapper_646, _citrus_mapper_646_mapper_getops
|
||||
mapper_none, _citrus_mapper_none_mapper_getops
|
||||
mapper_serial, _citrus_mapper_serial_mapper_getops
|
||||
mapper_parallel, _citrus_mapper_parallel_mapper_getops
|
||||
mapper_std, _citrus_mapper_std_mapper_getops
|
||||
mapper_zone, _citrus_mapper_zone_mapper_getops
|
5
pkgs/by-name/li/libiconv-darwin/static-setup-hook.sh
Normal file
5
pkgs/by-name/li/libiconv-darwin/static-setup-hook.sh
Normal file
@ -0,0 +1,5 @@
|
||||
# Darwin’s dynamic libiconv reexports libcharset, so reproduce that in static builds.
|
||||
if [ -z "${dontAddExtraLibs-}" ]; then
|
||||
getHostRole
|
||||
export NIX_LDFLAGS${role_post}+=" -lcharset"
|
||||
fi
|
Loading…
Reference in New Issue
Block a user