@@ -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,39 @@ 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,
185+ * if the specified path is non-existent, or if the path is already
186+ * included.
187+ *
188+ * @param string $path The path of the library.
189+ * @return bool `true` if the path was added; otherwise, `false`.
190+ */
191+ public static function addLibraryPath (string $ path ): bool
192+ {
193+ // Already initialized.
194+ if (self ::$ ffi_inited ) {
195+ return false ;
196+ }
197+ 198+ $ path = realpath ($ path );
199+ if ($ path === false ) {
200+ return false ;
201+ }
202+ 203+ $ path .= DIRECTORY_SEPARATOR ;
204+ 205+ if (in_array ($ path , self ::$ libraryPaths )) {
206+ return false ;
207+ }
208+ 209+ self ::$ libraryPaths [] = $ path ;
210+ 211+ return true ;
212+ }
213+ 172214 /**
173215 * Shut down libvips. Call this just before process exit.
174216 *
@@ -208,12 +250,11 @@ private static function libraryName(string $name, int $abi): string
208250 }
209251
210252 private static function libraryLoad (
211- array $ libraryPaths ,
212253 string $ libraryName ,
213254 string $ interface
214255 ): ?\FFI {
215256 Utils::debugLog ("trying to open " , ["libraryName " => $ libraryName ]);
216- foreach ($ libraryPaths as $ path ) {
257+ foreach (self :: $ libraryPaths as $ path ) {
217258 Utils::debugLog ("trying path " , ["path " => $ path ]);
218259 try {
219260 $ library = \FFI ::cdef ($ interface , $ path . $ libraryName );
@@ -252,37 +293,25 @@ private static function init(): void
252293
253294 $ is_64bits = PHP_INT_SIZE === 8 ;
254295
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- 267296 if (PHP_OS_FAMILY === "OSX " || PHP_OS_FAMILY === "Darwin " ) {
268297 // Homebrew on Apple Silicon
269- $ libraryPaths [] = "/opt/homebrew/lib/ " ;
298+ self :: addLibraryPath ( "/opt/homebrew/lib " ) ;
270299 // See https://github.com/Homebrew/brew/issues/13481#issuecomment-1207203483
271- $ libraryPaths [] = "/usr/local/lib/ " ;
300+ self :: addLibraryPath ( "/usr/local/lib " ) ;
272301 }
273302
274- $ vips = self ::libraryLoad ($ libraryPaths , $ vips_libname , <<<'CPP'
303+ $ vips = self ::libraryLoad ($ vips_libname , <<<'CPP'
275304 int vips_init (const char *argv0);
276305 const char *vips_error_buffer (void);
277306 int vips_version(int flag);
278307 CPP);
279308
280309 if ($ vips === null ) {
281310 // drop the "" (system path) member
282- array_shift ($ libraryPaths );
311+ array_shift (self :: $ libraryPaths );
283312 $ msg = "Unable to open library ' $ vips_libname' " ;
284- if (!empty ($ libraryPaths )) {
285- $ msg .= " in any of [' " . implode ("', ' " , $ libraryPaths ) . "'] " ;
313+ if (!empty (self :: $ libraryPaths )) {
314+ $ msg .= " in any of [' " . implode ("', ' " , self :: $ libraryPaths ) . "'] " ;
286315 }
287316 $ msg .= ". Make sure that you've installed libvips and that ' $ vips_libname' " ;
288317 $ msg .= " is on your system's library search path. " ;
@@ -777,13 +806,13 @@ private static function init(): void
777806 * one that libvips itself is using, and they will share runtime types.
778807 */
779808 self ::$ glib =
780- self ::libraryLoad ($ libraryPaths , $ vips_libname , $ glib_decls ) ??
781- self ::libraryLoad ($ libraryPaths , $ glib_libname , $ glib_decls );
809+ self ::libraryLoad ($ vips_libname , $ glib_decls ) ??
810+ self ::libraryLoad ($ glib_libname , $ glib_decls );
782811 self ::$ gobject =
783- self ::libraryLoad ($ libraryPaths , $ vips_libname , $ gobject_decls ) ??
784- self ::libraryLoad ($ libraryPaths , $ gobject_libname , $ gobject_decls );
812+ self ::libraryLoad ($ vips_libname , $ gobject_decls ) ??
813+ self ::libraryLoad ($ gobject_libname , $ gobject_decls );
785814
786- self ::$ vips = self ::libraryLoad ($ libraryPaths , $ vips_libname , $ vips_decls );
815+ self ::$ vips = self ::libraryLoad ($ vips_libname , $ vips_decls );
787816
788817 # Useful for debugging
789818 # self::$vips->vips_leak_set(1);
0 commit comments