@@ -79,6 +79,15 @@ class FFI
79
79
*/
80
80
private static bool $ ffi_inited = false ;
81
81
82
+ /**
83
+ * A list of paths where libvips might reside.
84
+ *
85
+ * @internal
86
+ */
87
+ private static array $ libraryPaths = [
88
+ "" // system library
89
+ ];
90
+
82
91
/**
83
92
* Look up these once.
84
93
*
@@ -169,6 +178,30 @@ public static function atLeast(int $x, int $y, int $z = 0): bool
169
178
self ::$ library_micro >= $ z );
170
179
}
171
180
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
+
172
205
/**
173
206
* Shut down libvips. Call this just before process exit.
174
207
*
@@ -208,14 +241,16 @@ private static function libraryName(string $name, int $abi): string
208
241
}
209
242
210
243
private static function libraryLoad (
211
- array $ libraryPaths ,
212
244
string $ libraryName ,
213
245
string $ interface
214
246
): ?\FFI {
215
247
Utils::debugLog ("trying to open " , ["libraryName " => $ libraryName ]);
216
- foreach ($ libraryPaths as $ path ) {
248
+ foreach (self :: $ libraryPaths as $ path ) {
217
249
Utils::debugLog ("trying path " , ["path " => $ path ]);
218
250
try {
251
+ if ($ path !== '' ) {
252
+ $ path .= '/ ' ;
253
+ }
219
254
$ library = \FFI ::cdef ($ interface , $ path . $ libraryName );
220
255
Utils::debugLog ("success " , []);
221
256
return $ library ;
@@ -252,37 +287,25 @@ private static function init(): void
252
287
253
288
$ is_64bits = PHP_INT_SIZE === 8 ;
254
289
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
-
267
290
if (PHP_OS_FAMILY === "OSX " || PHP_OS_FAMILY === "Darwin " ) {
268
291
// Homebrew on Apple Silicon
269
- $ libraryPaths [] = "/opt/homebrew/lib/ " ;
292
+ self :: $ libraryPaths [] = "/opt/homebrew/lib " ;
270
293
// See https://github.com/Homebrew/brew/issues/13481#issuecomment-1207203483
271
- $ libraryPaths [] = "/usr/local/lib/ " ;
294
+ self :: $ libraryPaths [] = "/usr/local/lib " ;
272
295
}
273
296
274
- $ vips = self ::libraryLoad ($ libraryPaths , $ vips_libname , <<<'CPP'
297
+ $ vips = self ::libraryLoad ($ vips_libname , <<<'CPP'
275
298
int vips_init (const char *argv0);
276
299
const char *vips_error_buffer (void);
277
300
int vips_version(int flag);
278
301
CPP);
279
302
280
303
if ($ vips === null ) {
281
304
// drop the "" (system path) member
282
- array_shift ($ libraryPaths );
305
+ array_shift (self :: $ libraryPaths );
283
306
$ 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 ) . "'] " ;
286
309
}
287
310
$ msg .= ". Make sure that you've installed libvips and that ' $ vips_libname' " ;
288
311
$ msg .= " is on your system's library search path. " ;
@@ -777,13 +800,13 @@ private static function init(): void
777
800
* one that libvips itself is using, and they will share runtime types.
778
801
*/
779
802
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 );
782
805
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 );
785
808
786
- self ::$ vips = self ::libraryLoad ($ libraryPaths , $ vips_libname , $ vips_decls );
809
+ self ::$ vips = self ::libraryLoad ($ vips_libname , $ vips_decls );
787
810
788
811
# Useful for debugging
789
812
# self::$vips->vips_leak_set(1);
0 commit comments