libvips / php-vips

php binding for libvips
MIT License
615 stars 25 forks source link

FFI\\Exception(code: 0): Failed loading 'libvips.42.dylib' after upgrade to v2 on M1 Mac #178

Closed johnvoncolln closed 1 year ago

johnvoncolln commented 1 year ago

Have read through this issue and tried everything, but haven't had any luck...

[2022-12-05 16:49:29] local.ERROR: Failed loading 'libvips.42.dylib' {"userId":1245,"exception":"[object] (FFI\\Exception(code: 0): Failed loading 'libvips.42.dylib' at ...vendor/jcupitt/vips/src/FFI.php:739)
[stacktrace]
.../vendor/jcupitt/vips/src/FFI.php(739): FFI::cdef('// we need the ...', 'libvips.42.dyli...')
.../vendor/jcupitt/vips/src/FFI.php(116): Jcupitt\\Vips\\FFI::init()
/vendor/jcupitt/vips/src/Utils.php(100): Jcupitt\\Vips\\FFI::vips()
/vendor/jcupitt/vips/src/Image.php(709): Jcupitt\\Vips\\Utils::filenameGetFilename('/private/var/tm...')

I've enabled FFI as instructed.

I've removed the older vips php extension.

libvips is 8.13.3

php-vips is 2.1.0

php is 8.1

Any ideas on things I can try to troubleshoot? All out of ideas at the moment.

johnvoncolln commented 1 year ago

Ok, so in FFI.php, starting on line 729...

        Utils::debugLog("init", ["binding ..."]);
        self::$glib = \FFI::cdef($glib_decls, $glib_libname);
        self::$gobject = \FFI::cdef($gobject_decls, $gobject_libname);
        self::$vips = \FFI::cdef($vips_decls, $vips_libname);

For my particular situation, these three variables $glib_libname, $gobject_libname, $vips_libname, when the parameters are hard coded to the absolute path of the library /opt/homebrew/lib/libvips.42.dylib it works...

On the PHP website, the second parameter for FFI::cdef() is supposed to be:

The name of a shared library file, to be loaded and linked with the definitions.

It doesn't say the absolute path, so presumably my system doesn't know where to look for shared libraries. But it seems to work with the absolute path, so maybe we can change that?

I've changed this on 236:

        $vips = null;
        $libraryPath = null;
        foreach ($libraryPaths as $path) {
            Utils::debugLog("init", ["path" => $path]);

            try {
                $vips = \FFI::cdef(<<<EOS
                    int vips_init (const char *argv0);
                    const char *vips_error_buffer (void);
                    int vips_version(int flag);
                EOS, $path . $vips_libname);
                $libraryPath = $path;
                break;
            } catch (\FFI\Exception $e) {
                Utils::debugLog("init", ["msg" => "library load failed", "exception" => $e]);
        }

And also this on 729

        Utils::debugLog("init", ["binding ..."]);
        self::$glib = \FFI::cdef($glib_decls, $libraryPath . $glib_libname);
        self::$gobject = \FFI::cdef($gobject_decls, $libraryPath . $gobject_libname);
        self::$vips = \FFI::cdef($vips_decls, $libraryPath . $vips_libname);

I've tested on a Mac M1 Studio, Intel Macbook Pro and Ubuntu 20.04 LTS and it works, not sure about other systems - probably need to test on Windows.

Let me know if you want me to do a PR or maybe I need to just figure out how to configure php to see the shared libraries?

jcupitt commented 1 year ago

Hi @johnvoncolln, sorry for not having replied to this sooner.

It doesn't say the absolute path, so presumably my system doesn't know where to look for shared libraries. But it seems to work with the absolute path, so maybe we can change that?

I think php-vips is already doing what you want, isn't it? git master looks like this:

https://github.com/libvips/php-vips/blob/master/src/FFI.php#L247-L256

It's trying a set of absolute paths, one of which is the homebrew M1 area.

Could you check that you are using the latest php-vips? We're on 2.1.1 right now.

You probably found, but you can set a debug logger, eg.:

#!/usr/bin/env php
<?php

require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;

Vips\Config::setLogger(new Vips\DebugLogger());

$image = Vips\Image::newFromFile($argv[1], ['access' => 'sequential']);

Run with eg.:

$ ./debug.php ~/pics/k2.jpg

And you should be able to see it searching the various possible lib areas.

johnvoncolln commented 1 year ago

No problem at all! Thanks for helping me out.

my php-vips is at 2.1.0

After I revert back to original code in FFI.php and run it with debugger, this is the output:

[2022-12-08T09:33:22-06:00] debug: init {"library":"libvips.42.dylib"}
[2022-12-08T09:33:22-06:00] debug: init {"path":""}
[2022-12-08T09:33:22-06:00] debug: init {"msg":"library load failed","exception":{}}
[2022-12-08T09:33:22-06:00] debug: init {"path":"/opt/homebrew/Cellar/vips/8.13.3/lib64/"}
[2022-12-08T09:33:22-06:00] debug: init {"msg":"library load failed","exception":{}}
[2022-12-08T09:33:22-06:00] debug: init {"path":"/opt/homebrew/Cellar/vips/8.13.3/lib/"}
[2022-12-08T09:33:22-06:00] debug: init {"vips_init":0}
[2022-12-08T09:33:22-06:00] debug: init {"libvips version":[8,13,3]}
[2022-12-08T09:33:22-06:00] debug: init ["binding ..."]

So it looks like it's loading it where it's creating $vips and looping through the possible absolute paths:

$vips = \FFI::cdef(<<<EOS
                    int vips_init (const char *argv0);
                    const char *vips_error_buffer (void);
                    int vips_version(int flag);
                EOS, $path . $vips_libname);

But it fails later on here (line 729ish):

Utils::debugLog("init", ["binding ..."]);
        self::$glib = \FFI::cdef($glib_decls, $glib_libname);
        self::$gobject = \FFI::cdef($gobject_decls, $gobject_libname);
        self::$vips = \FFI::cdef($vips_decls, $vips_libname);

But your not specifying the absolute path, just the library name on the second parameter of FFI::cdef like you do on the first code block above: $path . $vips_libname

johnvoncolln commented 1 year ago

So if you're specifying the absolute path in one place, should you not be specifying it elsewhere?

AmitSonkhiya commented 1 year ago

Reporting the exact issue. Further, the issue related to not adding absolute path before FFI::cdef https://github.com/libvips/php-vips/issues/178#issuecomment-1342932354 also occurs.

PHP 8.2 libvips 8.14.2 jcupitt/vips 2.1 Mac M1 Silicon

My temporary workaround (added path):

$brew = '/opt/homebrew/lib/';
Utils::debugLog("init", ["binding ..."]);
self::$glib = \FFI::cdef($glib_decls,  $brew . $glib_libname);
self::$gobject = \FFI::cdef($gobject_decls, $brew . $gobject_libname);
self::$vips = \FFI::cdef($vips_decls, $brew . $vips_libname);
jcupitt commented 1 year ago

I've bought an M2 mac and made https://github.com/libvips/php-vips/pull/206 which I think fixes this. Any testing very welcome!

jcupitt commented 1 year ago

... let's close this issue and move discussion to that PR.