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