@@ -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