Skip to content

Commit 3ae9a3b

Browse files
committed
Add FFI::addLibraryPath utility
In favor of the `VIPSHOME` env. Resolves: #232.
1 parent efbf4c4 commit 3ae9a3b

File tree

2 files changed

+51
-25
lines changed

2 files changed

+51
-25
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ To your `php.ini`.
7373
require __DIR__ . '/vendor/autoload.php';
7474
use Jcupitt\Vips;
7575

76+
// handy for Windows
77+
Vips\FFI::addLibraryPath("C:/vips-dev-8.16/bin");
78+
7679
// check libvips version
7780
echo 'libvips version: ' . Vips\Config::version() . PHP_EOL;
7881

src/FFI.php

+48-25
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ class FFI
7979
*/
8080
private static bool $ffi_inited = false;
8181

82+
/**
83+
* A list of paths where libvips might reside.
84+
*
85+
* @internal
86+
*/
87+
private static array $libraryPaths = [
88+
"" // system library
89+
];
90+
8291
/**
8392
* Look up these once.
8493
*
@@ -169,6 +178,30 @@ public static function atLeast(int $x, int $y, int $z = 0): bool
169178
self::$library_micro >= $z);
170179
}
171180

181+
/**
182+
* Adds a directory to the search path for shared libraries.
183+
*
184+
* This method has no effect if FFI handles are already initialized or
185+
* if the specified path is already included.
186+
*
187+
* @param string $path The path of the library.
188+
* @return bool `true` if the path was added; otherwise, `false`.
189+
*/
190+
public static function addLibraryPath(string $path): bool
191+
{
192+
// Already initialized.
193+
if (self::$ffi_inited) {
194+
return false;
195+
}
196+
197+
if (!in_array($path, self::$libraryPaths)) {
198+
self::$libraryPaths[] = $path;
199+
return true;
200+
}
201+
202+
return false;
203+
}
204+
172205
/**
173206
* Shut down libvips. Call this just before process exit.
174207
*
@@ -208,14 +241,16 @@ private static function libraryName(string $name, int $abi): string
208241
}
209242

210243
private static function libraryLoad(
211-
array $libraryPaths,
212244
string $libraryName,
213245
string $interface
214246
): ?\FFI {
215247
Utils::debugLog("trying to open", ["libraryName" => $libraryName]);
216-
foreach ($libraryPaths as $path) {
248+
foreach (self::$libraryPaths as $path) {
217249
Utils::debugLog("trying path", ["path" => $path]);
218250
try {
251+
if ($path !== '') {
252+
$path .= '/';
253+
}
219254
$library = \FFI::cdef($interface, $path . $libraryName);
220255
Utils::debugLog("success", []);
221256
return $library;
@@ -252,37 +287,25 @@ private static function init(): void
252287

253288
$is_64bits = PHP_INT_SIZE === 8;
254289

255-
$libraryPaths = [
256-
"" // system library
257-
];
258-
259-
$vipshome = getenv("VIPSHOME");
260-
if ($vipshome) {
261-
// lib<qual>/ predicates lib/
262-
$libraryPaths[] = $vipshome . ($is_64bits ? "/lib64/" : "/lib32/");
263-
// lib/ is always searched
264-
$libraryPaths[] = $vipshome . "/lib/";
265-
}
266-
267290
if (PHP_OS_FAMILY === "OSX" || PHP_OS_FAMILY === "Darwin") {
268291
// Homebrew on Apple Silicon
269-
$libraryPaths[] = "/opt/homebrew/lib/";
292+
self::$libraryPaths[] = "/opt/homebrew/lib";
270293
// See https://github.com/Homebrew/brew/issues/13481#issuecomment-1207203483
271-
$libraryPaths[] = "/usr/local/lib/";
294+
self::$libraryPaths[] = "/usr/local/lib";
272295
}
273296

274-
$vips = self::libraryLoad($libraryPaths, $vips_libname, <<<'CPP'
297+
$vips = self::libraryLoad($vips_libname, <<<'CPP'
275298
int vips_init (const char *argv0);
276299
const char *vips_error_buffer (void);
277300
int vips_version(int flag);
278301
CPP);
279302

280303
if ($vips === null) {
281304
// drop the "" (system path) member
282-
array_shift($libraryPaths);
305+
array_shift(self::$libraryPaths);
283306
$msg = "Unable to open library '$vips_libname'";
284-
if (!empty($libraryPaths)) {
285-
$msg .= " in any of ['" . implode("', '", $libraryPaths) . "']";
307+
if (!empty(self::$libraryPaths)) {
308+
$msg .= " in any of ['" . implode("', '", self::$libraryPaths) . "']";
286309
}
287310
$msg .= ". Make sure that you've installed libvips and that '$vips_libname'";
288311
$msg .= " is on your system's library search path.";
@@ -777,13 +800,13 @@ private static function init(): void
777800
* one that libvips itself is using, and they will share runtime types.
778801
*/
779802
self::$glib =
780-
self::libraryLoad($libraryPaths, $vips_libname, $glib_decls) ??
781-
self::libraryLoad($libraryPaths, $glib_libname, $glib_decls);
803+
self::libraryLoad($vips_libname, $glib_decls) ??
804+
self::libraryLoad($glib_libname, $glib_decls);
782805
self::$gobject =
783-
self::libraryLoad($libraryPaths, $vips_libname, $gobject_decls) ??
784-
self::libraryLoad($libraryPaths, $gobject_libname, $gobject_decls);
806+
self::libraryLoad($vips_libname, $gobject_decls) ??
807+
self::libraryLoad($gobject_libname, $gobject_decls);
785808

786-
self::$vips = self::libraryLoad($libraryPaths, $vips_libname, $vips_decls);
809+
self::$vips = self::libraryLoad($vips_libname, $vips_decls);
787810

788811
# Useful for debugging
789812
# self::$vips->vips_leak_set(1);

0 commit comments

Comments
 (0)