Linux: Load libfontconfig at runtime to allow the binaries to work for running kittens on servers without FontConfig
This commit is contained in:
parent
aaffec1cbc
commit
d3656bf7e9
@ -61,6 +61,9 @@ Detailed list of changes
|
|||||||
|
|
||||||
- Fix deleting images by row not calculating image bounds correctly (:iss:`5081`)
|
- Fix deleting images by row not calculating image bounds correctly (:iss:`5081`)
|
||||||
|
|
||||||
|
- Linux: Load libfontconfig at runtime to allow the binaries to work for
|
||||||
|
running kittens on servers without FontConfig
|
||||||
|
|
||||||
|
|
||||||
0.25.0 [2022-04-11]
|
0.25.0 [2022-04-11]
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "lineops.h"
|
#include "lineops.h"
|
||||||
#include "fonts.h"
|
#include "fonts.h"
|
||||||
#include <fontconfig/fontconfig.h>
|
#include <fontconfig/fontconfig.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include "emoji.h"
|
#include "emoji.h"
|
||||||
#include "freetype_render_ui_text.h"
|
#include "freetype_render_ui_text.h"
|
||||||
#ifndef FC_COLOR
|
#ifndef FC_COLOR
|
||||||
@ -18,10 +19,111 @@
|
|||||||
|
|
||||||
|
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
|
static void* libfontconfig_handle = NULL;
|
||||||
|
|
||||||
|
#define FcInit dynamically_loaded_fc_symbol.Init
|
||||||
|
#define FcFini dynamically_loaded_fc_symbol.Fini
|
||||||
|
#define FcCharSetAddChar dynamically_loaded_fc_symbol.CharSetAddChar
|
||||||
|
#define FcPatternDestroy dynamically_loaded_fc_symbol.PatternDestroy
|
||||||
|
#define FcObjectSetDestroy dynamically_loaded_fc_symbol.ObjectSetDestroy
|
||||||
|
#define FcPatternAddDouble dynamically_loaded_fc_symbol.PatternAddDouble
|
||||||
|
#define FcPatternAddString dynamically_loaded_fc_symbol.PatternAddString
|
||||||
|
#define FcFontMatch dynamically_loaded_fc_symbol.FontMatch
|
||||||
|
#define FcCharSetCreate dynamically_loaded_fc_symbol.CharSetCreate
|
||||||
|
#define FcPatternGetString dynamically_loaded_fc_symbol.PatternGetString
|
||||||
|
#define FcFontSetDestroy dynamically_loaded_fc_symbol.FontSetDestroy
|
||||||
|
#define FcPatternGetInteger dynamically_loaded_fc_symbol.PatternGetInteger
|
||||||
|
#define FcPatternAddBool dynamically_loaded_fc_symbol.PatternAddBool
|
||||||
|
#define FcFontList dynamically_loaded_fc_symbol.FontList
|
||||||
|
#define FcObjectSetBuild dynamically_loaded_fc_symbol.ObjectSetBuild
|
||||||
|
#define FcCharSetDestroy dynamically_loaded_fc_symbol.CharSetDestroy
|
||||||
|
#define FcConfigSubstitute dynamically_loaded_fc_symbol.ConfigSubstitute
|
||||||
|
#define FcDefaultSubstitute dynamically_loaded_fc_symbol.DefaultSubstitute
|
||||||
|
#define FcPatternAddInteger dynamically_loaded_fc_symbol.PatternAddInteger
|
||||||
|
#define FcPatternCreate dynamically_loaded_fc_symbol.PatternCreate
|
||||||
|
#define FcPatternGetBool dynamically_loaded_fc_symbol.PatternGetBool
|
||||||
|
#define FcPatternAddCharSet dynamically_loaded_fc_symbol.PatternAddCharSet
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
FcBool(*Init)(void);
|
||||||
|
void(*Fini)(void);
|
||||||
|
FcBool (*CharSetAddChar) (FcCharSet *fcs, FcChar32 ucs4);
|
||||||
|
void (*PatternDestroy) (FcPattern *p);
|
||||||
|
void (*ObjectSetDestroy) (FcObjectSet *os);
|
||||||
|
FcBool (*PatternAddDouble) (FcPattern *p, const char *object, double d);
|
||||||
|
FcBool (*PatternAddString) (FcPattern *p, const char *object, const FcChar8 *s);
|
||||||
|
FcPattern * (*FontMatch) (FcConfig *config, FcPattern *p, FcResult *result);
|
||||||
|
FcCharSet* (*CharSetCreate) (void);
|
||||||
|
FcResult (*PatternGetString) (const FcPattern *p, const char *object, int n, FcChar8 ** s);
|
||||||
|
void (*FontSetDestroy) (FcFontSet *s);
|
||||||
|
FcResult (*PatternGetInteger) (const FcPattern *p, const char *object, int n, int *i);
|
||||||
|
FcBool (*PatternAddBool) (FcPattern *p, const char *object, FcBool b);
|
||||||
|
FcFontSet * (*FontList) (FcConfig *config, FcPattern *p, FcObjectSet *os);
|
||||||
|
FcObjectSet * (*ObjectSetBuild) (const char *first, ...);
|
||||||
|
void (*CharSetDestroy) (FcCharSet *fcs);
|
||||||
|
FcBool (*ConfigSubstitute) (FcConfig *config, FcPattern *p, FcMatchKind kind);
|
||||||
|
void (*DefaultSubstitute) (FcPattern *pattern);
|
||||||
|
FcBool (*PatternAddInteger) (FcPattern *p, const char *object, int i);
|
||||||
|
FcPattern * (*PatternCreate) (void);
|
||||||
|
FcResult (*PatternGetBool) (const FcPattern *p, const char *object, int n, FcBool *b);
|
||||||
|
FcBool (*PatternAddCharSet) (FcPattern *p, const char *object, const FcCharSet *c);
|
||||||
|
} dynamically_loaded_fc_symbol = {0};
|
||||||
|
#define LOAD_FUNC(name) {\
|
||||||
|
*(void **) (&dynamically_loaded_fc_symbol.name) = dlsym(libfontconfig_handle, "Fc" #name); \
|
||||||
|
if (!dynamically_loaded_fc_symbol.name) { \
|
||||||
|
const char* error = dlerror(); \
|
||||||
|
fatal("Failed to load the function Fc" #name " with error: %s", error ? error : ""); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_fontconfig_lib(void) {
|
||||||
|
const char* libnames[] = {
|
||||||
|
#if defined(_KITTY_FONTCONFIG_LIBRARY)
|
||||||
|
_KITTY_FONTCONFIG_LIBRARY,
|
||||||
|
#else
|
||||||
|
"libfontconfig.so",
|
||||||
|
// some installs are missing the .so symlink, so try the full name
|
||||||
|
"libfontconfig.so.1",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
for (int i = 0; libnames[i]; i++) {
|
||||||
|
libfontconfig_handle = dlopen(libnames[i], RTLD_LAZY);
|
||||||
|
if (libfontconfig_handle) break;
|
||||||
|
}
|
||||||
|
if (libfontconfig_handle == NULL) { fatal("Failed to find and load fontconfig"); }
|
||||||
|
dlerror(); /* Clear any existing error */
|
||||||
|
LOAD_FUNC(Init);
|
||||||
|
LOAD_FUNC(Fini);
|
||||||
|
LOAD_FUNC(CharSetAddChar);
|
||||||
|
LOAD_FUNC(PatternDestroy);
|
||||||
|
LOAD_FUNC(ObjectSetDestroy);
|
||||||
|
LOAD_FUNC(PatternAddDouble);
|
||||||
|
LOAD_FUNC(PatternAddString);
|
||||||
|
LOAD_FUNC(FontMatch);
|
||||||
|
LOAD_FUNC(CharSetCreate);
|
||||||
|
LOAD_FUNC(PatternGetString);
|
||||||
|
LOAD_FUNC(FontSetDestroy);
|
||||||
|
LOAD_FUNC(PatternGetInteger);
|
||||||
|
LOAD_FUNC(PatternAddBool);
|
||||||
|
LOAD_FUNC(FontList);
|
||||||
|
LOAD_FUNC(ObjectSetBuild);
|
||||||
|
LOAD_FUNC(CharSetDestroy);
|
||||||
|
LOAD_FUNC(ConfigSubstitute);
|
||||||
|
LOAD_FUNC(DefaultSubstitute);
|
||||||
|
LOAD_FUNC(PatternAddInteger);
|
||||||
|
LOAD_FUNC(PatternCreate);
|
||||||
|
LOAD_FUNC(PatternGetBool);
|
||||||
|
LOAD_FUNC(PatternAddCharSet);
|
||||||
|
}
|
||||||
|
#undef LOAD_FUNC
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ensure_initialized(void) {
|
ensure_initialized(void) {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
|
load_fontconfig_lib();
|
||||||
if (!FcInit()) fatal("Failed to initialize fontconfig library");
|
if (!FcInit()) fatal("Failed to initialize fontconfig library");
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
@ -31,6 +133,8 @@ static void
|
|||||||
finalize(void) {
|
finalize(void) {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
FcFini();
|
FcFini();
|
||||||
|
dlclose(libfontconfig_handle);
|
||||||
|
libfontconfig_handle = NULL;
|
||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
setup.py
17
setup.py
@ -77,6 +77,7 @@ class Options(argparse.Namespace):
|
|||||||
egl_library: Optional[str] = os.getenv('KITTY_EGL_LIBRARY')
|
egl_library: Optional[str] = os.getenv('KITTY_EGL_LIBRARY')
|
||||||
startup_notification_library: Optional[str] = os.getenv('KITTY_STARTUP_NOTIFICATION_LIBRARY')
|
startup_notification_library: Optional[str] = os.getenv('KITTY_STARTUP_NOTIFICATION_LIBRARY')
|
||||||
canberra_library: Optional[str] = os.getenv('KITTY_CANBERRA_LIBRARY')
|
canberra_library: Optional[str] = os.getenv('KITTY_CANBERRA_LIBRARY')
|
||||||
|
fontconfig_library: Optional[str] = os.getenv('KITTY_FONTCONFIG_LIBRARY')
|
||||||
|
|
||||||
|
|
||||||
def emphasis(text: str) -> str:
|
def emphasis(text: str) -> str:
|
||||||
@ -296,6 +297,7 @@ def init_env(
|
|||||||
egl_library: Optional[str] = None,
|
egl_library: Optional[str] = None,
|
||||||
startup_notification_library: Optional[str] = None,
|
startup_notification_library: Optional[str] = None,
|
||||||
canberra_library: Optional[str] = None,
|
canberra_library: Optional[str] = None,
|
||||||
|
fontconfig_library: Optional[str] = None,
|
||||||
extra_logging: Iterable[str] = (),
|
extra_logging: Iterable[str] = (),
|
||||||
extra_include_dirs: Iterable[str] = (),
|
extra_include_dirs: Iterable[str] = (),
|
||||||
ignore_compiler_warnings: bool = False,
|
ignore_compiler_warnings: bool = False,
|
||||||
@ -381,6 +383,10 @@ def init_env(
|
|||||||
assert('"' not in canberra_library)
|
assert('"' not in canberra_library)
|
||||||
desktop_libs += [f'_KITTY_CANBERRA_LIBRARY="{canberra_library}"']
|
desktop_libs += [f'_KITTY_CANBERRA_LIBRARY="{canberra_library}"']
|
||||||
|
|
||||||
|
if fontconfig_library is not None:
|
||||||
|
assert('"' not in fontconfig_library)
|
||||||
|
desktop_libs += [f'_KITTY_FONTCONFIG_LIBRARY="{fontconfig_library}"']
|
||||||
|
|
||||||
if desktop_libs != []:
|
if desktop_libs != []:
|
||||||
library_paths['kitty/desktop.c'] = desktop_libs
|
library_paths['kitty/desktop.c'] = desktop_libs
|
||||||
|
|
||||||
@ -432,7 +438,7 @@ def kitty_env() -> Env:
|
|||||||
cppflags.append('-DGL_SILENCE_DEPRECATION')
|
cppflags.append('-DGL_SILENCE_DEPRECATION')
|
||||||
else:
|
else:
|
||||||
cflags.extend(pkg_config('fontconfig', '--cflags-only-I'))
|
cflags.extend(pkg_config('fontconfig', '--cflags-only-I'))
|
||||||
platform_libs = pkg_config('fontconfig', '--libs')
|
platform_libs = []
|
||||||
cflags.extend(pkg_config('harfbuzz', '--cflags-only-I'))
|
cflags.extend(pkg_config('harfbuzz', '--cflags-only-I'))
|
||||||
platform_libs.extend(pkg_config('harfbuzz', '--libs'))
|
platform_libs.extend(pkg_config('harfbuzz', '--libs'))
|
||||||
pylib = get_python_flags(cflags)
|
pylib = get_python_flags(cflags)
|
||||||
@ -810,7 +816,7 @@ def init_env_from_args(args: Options, native_optimizations: bool = False) -> Non
|
|||||||
global env
|
global env
|
||||||
env = init_env(
|
env = init_env(
|
||||||
args.debug, args.sanitize, native_optimizations, args.link_time_optimization, args.profile,
|
args.debug, args.sanitize, native_optimizations, args.link_time_optimization, args.profile,
|
||||||
args.egl_library, args.startup_notification_library, args.canberra_library,
|
args.egl_library, args.startup_notification_library, args.canberra_library, args.fontconfig_library,
|
||||||
args.extra_logging, args.extra_include_dirs, args.ignore_compiler_warnings,
|
args.extra_logging, args.extra_include_dirs, args.ignore_compiler_warnings,
|
||||||
args.build_universal_binary, args.extra_library_dirs
|
args.build_universal_binary, args.extra_library_dirs
|
||||||
)
|
)
|
||||||
@ -1470,6 +1476,13 @@ def option_parser() -> argparse.ArgumentParser: # {{{
|
|||||||
help='The filename argument passed to dlopen for libcanberra.'
|
help='The filename argument passed to dlopen for libcanberra.'
|
||||||
' This can be used to change the name of the loaded library or specify an absolute path.'
|
' This can be used to change the name of the loaded library or specify an absolute path.'
|
||||||
)
|
)
|
||||||
|
p.add_argument(
|
||||||
|
'--fontconfig-library',
|
||||||
|
type=str,
|
||||||
|
default=Options.fontconfig_library,
|
||||||
|
help='The filename argument passed to dlopen for libfontconfig.'
|
||||||
|
' This can be used to change the name of the loaded library or specify an absolute path.'
|
||||||
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
'--disable-link-time-optimization',
|
'--disable-link-time-optimization',
|
||||||
dest='link_time_optimization',
|
dest='link_time_optimization',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user