9

I am trying to link libssl.a and libcrypto.a static libraries in XCode command line project [under Link Binary With Libraries]. I have included Openssl header files in search path.

Compilation succeeds but execution fails with dyld: Library not loaded: /usr/local/ssl/lib/libcrypto.1.0.0.dylib.

Why does it look for dylib when I am linking it statically? How can this be fixed?

Any help would be appreciable.

jww
  • 97,681
  • 90
  • 411
  • 885
ZestyZest
  • 911
  • 13
  • 27

1 Answers1

12

Why does it look for dylib when I am linking it statically? How can this be fixed?

Apple's linker uses the dylib or share object if its available, regardless of of your linker flags like -rpath and -Bstatic. They even do it on iOS, where dylib's are not allowed!

Its kind of a well known problem once you know about it :) See, for example, Installing Crypto++ 5.6.2 on Mac OS X. Crypto++ has the same problems with Apple's tools.

The fix is to stop using -L and -l options, and to link the object file or archive directly. An archive is just a collection of object files, so you can use them interchangeably.

To specify the object files or archives for the linker, see Linking to an object file. Under Xcode, you add the fully specified archive name (like /usr/local/openssl-ios/lib/libcrypto.a) to Other Linker Flags (the OTHER_LDFLAGS Xcode option).

When adding the full archive to OTHER_LDFLAGS, I believe you just add it verbatim without any switches, like -l or -L. You may need -Wl (-Wl,/usr/local/openssl-ios/lib/libcrypto.a), but you don't use -l (-l/usr/local/openssl-ios/lib/libcrypto.a).

You use -Wl when the option is passed through the compiler driver to the linker. If the linker is invoked directly, then you don't need -Wl and should not use it.


A second option is to set GCC_LINK_WITH_DYNAMIC_LIBRARIES to YES. Apple does not appear to document it in Xcode Build Setting Reference, but its clearly under my copy of Xcode. See How to link a static library for iOS on Stack Overflow.

I seem to recall having problems with this in the past. Its one of those things that should work in theory, but does not work in practice.


A third option is to remove the dylib or shared object from all paths used under Xcode so Xcode does not accidentally find it when using -lcrypto.


A fourth option is use allow dynamic linking, but execute the program with DYLD_LIBRARY_PATH. Its OS X's equivalent to LD_LIBRARY_PATH, and ensures your copy of OpenSSL is loaded (like 1.0.2), and not the system's version of OpenSSL (0.9.8).

But I don't like this option because it requires users of your software to do something.


Another possibility due to the message dyld: Library not loaded: /usr/local/ssl/lib/libcrypto.1.0.0.dylib is to code sign your copy of the library. Its a little odd its found but not loaded, so I'm going to toss this out there in case its OS X's Code Signing or Gatekeeper Service...

To code sign your copy of the library under the MAC Developer program, just:

codesign -fs "Johnny Developer" /usr/local/ssl/lib/libcrypto.so
Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks a lot. 1) It works if i use -Wl,$path_to_lib.a in OTHER_LINKER_FLAGS even if I remove the libraries from "Link Binary With Library". How is it even possible? I hope the openssl preinstalled on MAC does not interfere? 2) Is openssl installed on MAC-OSX always by default? If it is would it make a difference if we use it directly (using NSTask) without going into the complication of statically or dynamically linking. – ZestyZest Jun 22 '15 at 05:17
  • It is picking up the right version. I have built the static library version 1.0.2a and the output of SSLeay_version is 1.0.2a 19 Mar. Also does it make sense if openssl is preinstalled always then we can directly call openssl functions through NSTask without linking it with a project? – ZestyZest Jun 22 '15 at 05:39
  • *"1.0.2a 19 Mar"* - 1.0.2c is the latest, and it has security bug fixes. *"Does it make sense if openssl is preinstalled..."* - Apple's version of OpenSSL is 0.9.8. It lacks most EC support, TLS 1.1 and TLS 1.2 (among others). You should probably avoid it. – jww Jun 22 '15 at 05:56
  • *"How is it even possible?"* - oh, my bad... Yes, that works. It works because your are specifying object files for the linker to link to. An archive is just a collection of object files. Even though you use that trick, be sure you use `-I...` to specify the header files for that particular library. – jww Jun 22 '15 at 06:01
  • I'm having a similar problem after upgrading from Xcode 9 to Xcode 10. My iOS app builds and launches, but I get a dyld error on launch of openssl.framework `image not found`... ?? I should mention that the upgrade of Xcode 10 (Swift 4.2) required a `pod repo update` and `pod install`. – jbm Oct 18 '18 at 18:36