Can't load 3rd party library

I am trying to load the R library (R 4.0.0 available from https://cran.r-project.org) from my signed and notarized app.


But this is what I get on the console:

dyld: Library not loaded: /Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib
  Referenced from: /Users/hecht/Library/Developer/Xcode/DerivedData/JMP-dgmxmeayjbgthlckfcezeplzucmk/Build/Products/Debug/JMP.app/Contents/Frameworks/tkext//tkrproxy
  Reason: no suitable image found.  Did find:
  /Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib: code signature in (/Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib) not valid for use in process using Library Validation: mapping process has no Team ID and is not a platform binary
  /Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib: stat() failed with errno=1

/Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib: stat() failed with errno=1

I have checked that libR.dylib has LC_VERSION_MIN_MACOSX set:

% otool -l /Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib | grep -B 1 -A 3 LC_VERSION_MIN
Load command 8
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.13
      sdk 10.15


I have checked that the library's load path is absolute and doesn't include @rpath:

% otool -D /Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib                           
/Library/Frameworks/R.framework/Versions/Current/Resources/lib/libR.dylib:
/Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libR.dylib


My app has com.apple.security.cs.disable-library-validation set to YES.


What am I missing?

Replies

I download that installer package and took a look at the framework embedded within. It is very strangely structured. Consider this:

% codesign -d -vvv R.framework 
R.framework: code object is not signed at all

Contrast with this:

% codesign -d -vvv /System/Library/Frameworks/iTunesLibrary.framework 
Executable=/System/Library/Frameworks/iTunesLibrary.framework/Versions/Current/iTunesLibrary
Identifier=com.apple.iTunesLibrary
Format=bundle with Mach-O thin (x86_64)
…

The reason is that the main image of the R framework is not actually the code but rather a symlink to the code.

% ls -l R.framework/Versions/4.0
total 0
lrwxr-xr-x   1 quinn  staff    17 20 May 10:34 Headers -> Resources/include
drwxr-xr-x  32 quinn  staff  1024 24 Apr 11:20 PrivateHeaders
lrwxr-xr-x   1 quinn  staff    24 20 May 10:34 R -> Resources/lib/libR.dylib
drwxr-xr-x  18 quinn  staff   576 24 Apr 11:22 Resources

Which means the code is signed as a standalone Mach-O image rather than a bundle:

% codesign -d -vvv R.framework/Versions/Current/Resources/lib/libR.dylib
Executable=/Users/quinn/Desktop/R.framework/Versions/4.0/Resources/lib/libR.dylib
Identifier=libR
Format=Mach-O thin (x86_64)
…

Note that the

Format
field is
Mach-O thin
rather than
bundle with Mach-O thin
. This has all sorts of knock-on effects, for example, the other libraries used by the framework are not considered nested code because, not being bundled, there’s nowhere to nest that code.

I’m not entirely sure how that’s triggering the problem you’re seeing but it seems quite likely that this is involved. Unfortunately I don’t have the time to dig into this in more detail here on DevForums. If you’re like me to take a more in-depth look, please open a DTS tech support incident.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

You may be able to rebuild the R dylib from scratch, and then manually construct a proper framework. This is very easy to do.


Sometimes these open source packages have their Mac versions build by that one guy who had a Mac in 2003. Ever since then they rebuild using either a Linux cross-compiler or an VM running on Linux.


R is a GPL project, in case you didn't already know.

Quinn, thanks for the research on this. Very helpful!

Thanks John. We don't distribute R with our app. But we can optionally call it if the user has downloaded and installed it. So us building our own framework is not feasible.

OK. I get it. Maybe you can just call the R executable instead.