jackaudio / jack2

jack2 codebase
GNU General Public License v2.0
2.22k stars 376 forks source link

macOS dylib location/compatibility #640

Closed dyfer closed 3 years ago

dyfer commented 4 years ago

Hello, I've used a recent jack2 installer to get jack2 on macOS Catalina. I've noticed that the location of jack libraries is different from the ones in the old JackOSX package, and thus software compiled with jack support against JackOSX fails to start (JackTrip in this case). Is compatibility with clients compiled against old jack on macOS something that is possible to achieve?

falkTX commented 4 years ago

What exactly is different? both use /usr/local prefix

dyfer commented 4 years ago

Ah I see, JackOSX indeed has put libjack in /usr/local/lib. However, JackOSX also included a library (?) in /Library/Frameworks/Jackmp.framework/. I get the following when trying to start JackTrip: dyld: Library not loaded: /Library/Frameworks/Jackmp.framework/Versions/A/Jackmp

EDIT: I also see Jacknet.framework and Jackservermp.framework

falkTX commented 4 years ago

Right, that.. it is just a symlink to the jack dylib actually, so that it works as a framework. If you recompile jacktrip using -L/usr/local/lib -ljack you should have it working for both.

dyfer commented 4 years ago

Okay, thanks. I was setting this on a machine without build environment set up yet and was using downloaded binary of JackTrip.

I also naively tried to create a symlink from dylib in /usr/local/lib to the Frameworks location, not sure that's supposed to work, I got the information that expected Jackmp's compatibility version is 1.0.0, while the new libjack's version is 0.1.0...

Is there any way new jack2 could provide binary compatibility with software compiled for "old" jackosx?

falkTX commented 4 years ago

The version set for the library is a bit meaningless. For the framework stuff, I dont know how to create those, PR/patches welcome that do it in the build system.

Cant you recompile jacktrip instead? Or ask for new binaries.

dyfer commented 4 years ago

Thank you for prompt responses. Sure, I'll recompile eventually, however that's not feasible for everyone. A little bit more information - it seems that pkg_check_modules from cmake, when used to find jack (with jackosx installed), provides the Frameworks path instead of the /usr/local/lib for linking, so applications using that to set up build system end up with that dependency in Frameworks, and not in /usr/local/lib. I'll see if I can come up with a patch to create the framework. Do you know if there's a way to temporarily change the "version" in a dylib for testing?

falkTX commented 4 years ago

tbh, I would prefer to not have the framework stuff. It is something specific of macOS, and not really needed in the end. the updated jack2 installer has a pkg-config file, we should use that instead of manually specifying linker flags.

there is a native tool (install_name_tool) to change the path of dependencies for dylib files, so I guess that same tool can do it for versions.

dyfer commented 4 years ago

all right, thank you for the information!

dyfer commented 4 years ago

I've dug a bit more and while trying to build another software with jack/jackosx and I noticed that jack path found by cmake was indeed in /usr/local/lib and not in the Frameworks. However the resulting binary still depended on the Frameworks location. Then I checked libjack.dylib:

otool -L /usr/local/lib/libjack.dylib
/usr/local/lib/libjack.dylib:
    /Library/Frameworks/Jackmp.framework/Versions/A/Jackmp (compatibility version 1.0.0, current version 1.0.0)
(...)

Does that mean that there's no way to link against jackosx but drop that dependency on the framework?

falkTX commented 4 years ago

Really seems best to link against the new jack2 package.

the binary will keep working for the old installer because the lib-compat version is lower and /usr/local/lib/libjack.dylib is also present there, well if anyone cares about that anyway.

with apple-sillicon (arm64) coming soon, new binaries are going to be needed anyway.

dyfer commented 4 years ago

one more piece of information: jack1 installed via homebrew provides

-> otool -L libjack.dylib
libjack.dylib:
    /usr/local/opt/jack/lib/libjack.0.dylib (compatibility version 1.0.0, current version 1.28.0)

So software built using that version will not load the dylib from the current jack2. Could this be remedied by increasing jack2 dylib's version?

falkTX commented 4 years ago

I was not aware jack1 did that. ok, good enough of a reason to bump the version in jack2 as well. Done in ede462167563c3d3bb1c78e5a6773e52bf1a6ba3

Updated installer will appear in https://github.com/jackaudio/jack2-releases/releases in some minutes, please try it

dyfer commented 4 years ago

Thanks @falkTX It seems that the updated release provides libjack.1.dylib and no libjack.0.dylib. Software compiled against jack1, as well as jack2 version 1.9.16 does not work, as it seems to get linked against libjack.0.dylib, since libjack.dylib links there in both versions.

falkTX commented 4 years ago

errr, did not expect that, good to know. but in any case, does it work if you rename the library?

dyfer commented 4 years ago

but in any case, does it work if you rename the library?

Yes, both the versions compiled against jack1 as well as jack2 1.9.16 work once I copy libjack.1.dylib to libjack.0.dylib.

dyfer commented 4 years ago

Re: dylib/framework issue. I'd like to report another software that does not run with the current jack2 version: PureData. That might be one of very few major software packages on macOS that can use Jack directly.

falkTX commented 4 years ago

I am looking into this, but waf makes it complicated.

dyfer commented 4 years ago

Thanks! I'm learning about all this as I go. I've found this PR that made PD's weak linking optional, it mentions few details about the process, namely that weak linking to a Library is (possibly?) more straightforward than to a .dylib: https://github.com/pure-data/pure-data/issues/57

Edit: another major software that can use Jack directly on macOS is Ardour. Just checked and it does work with the new jack2.

falkTX commented 4 years ago

I think I have something that works in 0f2e3b2e830e7b9ea03bb67a00c1eec4deab0855 Binaries will appear at the usual place

dyfer commented 4 years ago

Thanks, will test soon. BTW is https://github.com/jackaudio/jack2/blob/develop/common/JackWeakAPI.c supposed to be included in the jack2 installation? I can't find it after installing jack2.

falkTX commented 4 years ago

It is not a header file, so it is not installed for use like that. I am not quite up to date of that file usage and target tbh.

A few recent projects have been using https://github.com/x42/weakjack/ which seems to work well. I have my own custom variant of this approach at https://github.com/falkTX/Carla/tree/master/source/jackbridge

dyfer commented 4 years ago

Thank you for pointers about this. Since you've pointed to two implementations, and I saw e.g. Ardour having its own, I gather there's no one preferred library/method to do weak linking, is that correct?

dyfer commented 4 years ago

I think I have something that works in 0f2e3b2 Binaries will appear at the usual place

libjack.0.dylib still seems to be missing

falkTX commented 4 years ago

Oh I missed that part. Indeed as seen in https://travis-ci.org/github/jackaudio/jack2-releases/jobs/736705699#L5729 there is no such symlink created.

Apart from the symlink, does it work regarding version now?

falkTX commented 4 years ago

FYI triggered a new build which should fix the missing symlink, in theory

dyfer commented 4 years ago

The new build seems to work now, the symlink is there

fanninpm commented 4 years ago

On a semi-unrelated note, I'm in the process of upgrading Homebrew's jack from v1 to v2. However, the 10.13 CI fails for a similar reason when it tries to test dependent packages (csound, darkice, dirt, ecasound, ltc-tools, moc, and qjackctl). Most of them fail with a message like:

dyld: Library not loaded: /usr/local/opt/jack/lib/libjack.0.dylib
  Referenced from: /usr/local/Cellar/darkice/1.4/bin/darkice
  Reason: Incompatible library version: darkice requires version 1.0.0 or later, but libjack.0.dylib provides version 0.1.0

I also find it odd that it doesn't fail on 10.14 or 10.15.

dyfer commented 4 years ago

@falkTX sorry, I think I checked a wrong build of my app (built against recent jack2). It seems that the lastest build still has compatibility version 0.1.0, so build done against jack1 does not start. However, libjack.0.dylib is again included.

falkTX commented 4 years ago

Then I dont quite get that logic. Compatibility version is the lower possible version it can target. The library then has a "current" version of 1.9.16, which obviously > 1.0.0. in in theory it ought to work... Or am I misunderstanding something on how macOS uses these values?

dyfer commented 4 years ago

Or am I misunderstanding something on how macOS uses these values?

I really don't know, sorry. FWIW my understanding is similar to yours, but I really have no experience with this. I'm happy to run more tests if that helps.

Here is output of app compiled for jack1:

~ % /<path>/scsynth -u 57110
dyld: Library not loaded: /usr/local/lib/libjack.0.dylib
  Referenced from: /<path>/scsynth
  Reason: Incompatible library version: scsynth requires version 1.0.0 or later, but libjack.0.dylib provides version 0.1.0

and just to be sure:

otool -L /usr/local/lib/libjack.0.dylib 
/usr/local/lib/libjack.0.dylib:
    /usr/local/lib/libjack.0.1.0.dylib (compatibility version 0.1.0, current version 1.9.16)

EDIT: It is also possible that I'm doing something wrong...

C0nsultant commented 4 years ago

The library then has a "current" version of 1.9.16

That may be the intended behaviour, but it currently is not the case. When building from the most recent HEAD https://github.com/jackaudio/jack2/commit/dc6c9959edb6c9807200aa7f1bbc894b59d74b64, wscript:VERSION is used as bld.env['JACK_VERSION'] and consequently clientlib.vnum. For a reason I do not understand yet, this value is not used when setting the -Wl,-current_version link flag. cnum used for -Wl,-compatibility_version is set to the getattr() fallback 0 derived from clientlib.vnum.

git checkout dc6c9959edb6c9807200aa7f1bbc894b59d74b64
./waf configure
./waf build --verbose

[ 60/250] Linking build/common/libjack.dylib 11:47:18 runner ['clang++', '-single_module', '-dynamiclib', ... '-Wl,-compatibility_version,0', '-Wl,-current_version,0.1.0', ...]

A dirty hack around this issue until it is resolved:

export LDFLAGS="-Wl,-compatibility_version,1 -Wl,-current_version,1.9.16"
./waf configure
./waf build --verbose
./waf install

[ 60/250] Linking build/common/libjack.dylib 11:47:18 runner ['clang++', '-single_module', '-dynamiclib', ... '-Wl,-compatibility_version,0', '-Wl,-current_version,0.1.0', ... '-Wl,-compatibility_version,1', '-Wl,-current_version,1.9.16']

otool -L build/common/libjack.dylib
build/common/libjack.dylib: /usr/local/lib/libjack.0.1.0.dylib (compatibility version 1.0.0, current version 1.9.16)

andersvincent commented 4 years ago

I seem to have encountered the same issue when trying to use jacktrip with the latest jack 2 installer on macOS. It looks like this: dyld: Library not loaded: /Library/Frameworks/Jackmp.framework/Versions/A/Jackmp Referenced from: /usr/local/bin/jacktrip Reason: image not found

Does anyone know if there is any binary out there that would solve this problem? Some previous version that would solve it? Tried a few older releases of the Jack 2 installer for macOS, but the problem persisted. I am asking since neither me nor the users I am working with have knowledge on how to build Jack 2 locally.

dyfer commented 4 years ago

@andersvincent the solution for jacktrip is to use JackOSX instead of jack2 for the time being. Links are provided on CCRMA's jacktrip website(s). On Catalina you can't use jackpilot, but you still can use qjackctl provided with JackOSX, AFAIU. As for building, the solution would be not to build jack2, but to build jacktrip with the new jack2 installed.

michaelcaterisano commented 3 years ago

the solution would be not to build jack2, but to build jacktrip with the new jack2 installed.

Has anyone figured out a good way to do this?

falkTX commented 3 years ago

ask the jacktrip maintainers to make a new release?

or just build it yourself, since the project is opensource (correct?)

michaelcaterisano commented 3 years ago

Hi @falkTX. I've tried building jacktrip with jack installed using Xcode but haven't had any luck. Have you had success building jacktrip with jack installed, and if so, how did you go about it?

dyfer commented 3 years ago

@michaelcaterisano the latest release of jacktrip should be compatible with both current jack2 and the old jackosx. Jacktrip is built using a script that needs qmake. Install.txt gives you instructions how to compile it. Also, for jacktrip questions, they should be probably asked on the jacktrip repository, as jacktrip is not a part of the jack project.

EDIT: I was referring to JackTrip version 1.3.0. It seems it's not yet posted to the github release page, but can be downloaded from https://ccrma.stanford.edu/software/jacktrip/osx/index.html

dyfer commented 3 years ago

@falkTX not sure if you want to keep this thread open - it is somewhat relevant until jack software on macOS stops being built against jackosx. That might only be PureData at the moment (though I haven't checked their status in the last month or so).

falkTX commented 3 years ago

Have the maintainers of PureData being notified? If yes, then I guess it is fine to close this one.

dyfer commented 3 years ago

Yes: https://github.com/pure-data/pure-data/issues/1190

falkTX commented 3 years ago

Alright, lets stop here then.