summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2022-04-12 22:37:16 +0300
committerOleg Oshmyan <chortos@inbox.lv>2022-04-12 22:37:16 +0300
commitc5ee66dfb4b10c3c499aa804c6d1abb195c696e1 (patch)
tree790ee6df58e9add7e2576913381321f44a67323c
parentcbeea94fc70a6322ecce4c4ff30bef2a9028c18a (diff)
downloadlibass-c5ee66dfb4b10c3c499aa804c6d1abb195c696e1.tar.bz2
libass-c5ee66dfb4b10c3c499aa804c6d1abb195c696e1.tar.xz
Fix linking against static FriBidi on Windows
On Windows, symbols from dynamic-link libraries are replaced by pointers that are filled at runtime after loading the libraries. These pointers are given names prefixed by __imp_ and declared in an "import library" that accompanies the main library and is statically linked into consumers that want to use the DLL. For a function symbol, an additional stub function is generated with the original name that simply forwards to a matching __imp_ function-pointer call. In C, an imported function can be declared in two ways: void foo(); ends up calling the stub and wasting a jump at runtime; while __declspec(dllimport) void foo(); replaces foo() calls by (*__imp_foo)() at compile-time (not link-time), which ends up being a simple optimization. For imported objects, stubs are impossible, so only the __imp_ pointers exist and dllimport is mandatory. Many libraries, including libass, export only functions and avoid dllimport in their header files for simplicity. In contrast, FriBidi exports some functions and some objects, so it cannot neglect dllimport. Its solution is to declare all symbols in its header files with dllimport except if FRIBIDI_LIB_STATIC is defined. When libass is compiled without FRIBIDI_LIB_STATIC and linked against a FriBidi static library, references to FriBidi imports try to use __imp_ symbols (due to the dllimport declarations), but they do not exist, so the linking step fails. In general, libass cannot know whether it will be linked to static or dynamic FriBidi. For example, one can build a static libass.lib to embed in a larger project that uses a shared FriBidi.dll. So we cannot tell on our own, without the builder's input, whether we would need to go through __imp_ object pointers or reference objects directly. However, libass does not use any objects from FriBidi. We use only functions, and functions are always safe to use without dllimport, because at link-time the symbol is sure to resolve either to the actual function in the static library or to the stub function in the import library. As a result, we can simply always define FRIBIDI_LIB_STATIC to drop the dllimport declarations, and we will always produce static and dynamic libraries that work equally well with static and dynamic FriBidi. This logic is Windows-specific, and it is plausible that FRIBIDI_LIB_STATIC may break other platforms, so define it only on Windows. Note: FriBidi tries to add the FRIBIDI_LIB_STATIC macro when using `pkg-config --static --cflags`. However, this works only in one of the many pkg-config implementations, pkgconf, and notably not [yet] in the original freedesktop.org pkg-config. Even if it did work consistently, we would still need either to assume we always want --static or to make a possibly incorrect guess as to what kind of linking will ultimately be used for FriBidi. And even if --static is always fine on Windows, we might want to avoid it on other platforms, complicating build logic that people using other build systems would need to replicate.
-rw-r--r--libass/ass_compat.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/libass/ass_compat.h b/libass/ass_compat.h
index ae16bb7..38df913 100644
--- a/libass/ass_compat.h
+++ b/libass/ass_compat.h
@@ -26,6 +26,12 @@
#define inline __inline
#endif
+// Work around build failures on Windows with static FriBidi.
+// Possible because we only use FriBidi functions, not objects.
+#if defined(_WIN32) && !defined(FRIBIDI_LIB_STATIC)
+#define FRIBIDI_LIB_STATIC
+#endif
+
#ifndef HAVE_STRDUP
char *ass_strdup_fallback(const char *s); // definition in ass_utils.c
#define strdup ass_strdup_fallback