Skip to content

Commit 4c82f94

Browse files
committed
Add FFI::addLibraryPath utility
In favor of the `VIPSHOME` env. Resolves: #232.
1 parent a8dc307 commit 4c82f94

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
// fast thumbnail generator
7780
$image = Vips\Image::thumbnail('somefile.jpg', 128);
7881
$image->writeToFile('tiny.jpg');

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;
@@ -256,37 +291,25 @@ private static function init(): void
256291

257292
$is_64bits = PHP_INT_SIZE === 8;
258293

259-
$libraryPaths = [
260-
"" // system library
261-
];
262-
263-
$vipshome = getenv("VIPSHOME");
264-
if ($vipshome) {
265-
// lib<qual>/ predicates lib/
266-
$libraryPaths[] = $vipshome . ($is_64bits ? "/lib64/" : "/lib32/");
267-
// lib/ is always searched
268-
$libraryPaths[] = $vipshome . "/lib/";
269-
}
270-
271294
if (PHP_OS_FAMILY === "OSX" || PHP_OS_FAMILY === "Darwin") {
272295
// Homebrew on Apple Silicon
273-
$libraryPaths[] = "/opt/homebrew/lib/";
296+
self::$libraryPaths[] = "/opt/homebrew/lib";
274297
// See https://github.com/Homebrew/brew/issues/13481#issuecomment-1207203483
275-
$libraryPaths[] = "/usr/local/lib/";
298+
self::$libraryPaths[] = "/usr/local/lib";
276299
}
277300

278-
$vips = self::libraryLoad($libraryPaths, $vips_libname, <<<'CPP'
301+
$vips = self::libraryLoad($vips_libname, <<<'CPP'
279302
int vips_init (const char *argv0);
280303
const char *vips_error_buffer (void);
281304
int vips_version(int flag);
282305
CPP);
283306

284307
if ($vips === null) {
285308
// drop the "" (system path) member
286-
array_shift($libraryPaths);
309+
array_shift(self::$libraryPaths);
287310
$msg = "Unable to open library '$vips_libname'";
288-
if (!empty($libraryPaths)) {
289-
$msg .= " in any of ['" . implode("', '", $libraryPaths) . "']";
311+
if (!empty(self::$libraryPaths)) {
312+
$msg .= " in any of ['" . implode("', '", self::$libraryPaths) . "']";
290313
}
291314
$msg .= ". Make sure that you've installed libvips and that '$vips_libname'";
292315
$msg .= " is on your system's library search path.";
@@ -781,13 +804,13 @@ private static function init(): void
781804
* one that libvips itself is using, and they will share runtime types.
782805
*/
783806
self::$glib =
784-
self::libraryLoad($libraryPaths, $vips_libname, $glib_decls) ??
785-
self::libraryLoad($libraryPaths, $glib_libname, $glib_decls);
807+
self::libraryLoad($vips_libname, $glib_decls) ??
808+
self::libraryLoad($glib_libname, $glib_decls);
786809
self::$gobject =
787-
self::libraryLoad($libraryPaths, $vips_libname, $gobject_decls) ??
788-
self::libraryLoad($libraryPaths, $gobject_libname, $gobject_decls);
810+
self::libraryLoad($vips_libname, $gobject_decls) ??
811+
self::libraryLoad($gobject_libname, $gobject_decls);
789812

790-
self::$vips = self::libraryLoad($libraryPaths, $vips_libname, $vips_decls);
813+
self::$vips = self::libraryLoad($vips_libname, $vips_decls);
791814

792815
# Useful for debugging
793816
# self::$vips->vips_leak_set(1);

0 commit comments

Comments
 (0)