linkeruikitgluon-mobilegraalvm-native-image

How to solve iOS Linker Error `ld: framework not found UIKit` when using `mvn gluonfx:sharedlib -Pios`?


I have a linker error when using Gluon to deploy to iOS.

Following the instructions in gluon-samples/HelloSharedLib and the instructions in the Gluon Documentation. I have the following versions installed. We have a paid Apple Developer account.

Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: /opt/homebrew/Cellar/maven/3.8.6/libexec
Java version: 17.0.3, vendor: GraalVM Community, runtime: /Library/Java/JavaVirtualMachines/graalvm-svm-java17-darwin-m1-gluon-22.1.0.1-Final/Contents/Home
Default locale: en_GB, platform encoding: UTF-8
OS name: "mac os x", version: "13.0.1", arch: "aarch64", family: "mac"
Xcode 14.2, Build version 14C18

I can build using mvn gluonfx:sharedlib without an issue on both arm64 and x86 Macs, but when I build with the -Pios flag the linking step fails with the following output (on both machines):


Process
=======
link

Command Line
============
clang /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/gvm/HelloSharedLib/dummy.o /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/gvm/tmp/SVM-1675269285429/hello.hellosharedlib.o -ljava -lnio -lzip -lnet -lprefs -ljvm -lfdlibm -lz -ldl -lj2pkcs11 -ljaas -lextnet -lstdc++ -w -fPIC -arch arm64 -mios-version-min=11.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.2.sdk -shared -undefined dynamic_lookup -lpthread -llibchelper -lffi -ldarwin -Wl,-framework,Foundation -Wl,-framework,UIKit -Wl,-framework,CoreGraphics -Wl,-framework,MobileCoreServices -Wl,-framework,OpenGLES -Wl,-framework,CoreText -Wl,-framework,QuartzCore -Wl,-framework,ImageIO -Wl,-framework,CoreBluetooth -Wl,-framework,CoreImage -Wl,-framework,CoreLocation -Wl,-framework,CoreMedia -Wl,-framework,CoreMotion -Wl,-framework,CoreVideo -Wl,-framework,Accelerate -Wl,-framework,AVFoundation -Wl,-framework,AudioToolbox -Wl,-framework,MediaPlayer -Wl,-framework,UserNotifications -Wl,-framework,ARKit -Wl,-framework,AVKit -Wl,-framework,SceneKit -Wl,-framework,StoreKit -Wl,-framework,ModelIO -Wl,-framework,WebKit -o /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib -L/Library/Java/JavaVirtualMachines/graalvm-svm-java17-darwin-m1-gluon-22.1.0.1-Final/Contents/Home/lib/svm/clibraries/27/ios-arm64 -L/redacted/path/.gluon/substrate/javaStaticSdk/18-ea+prep18-8/ios-arm64/staticjdk/lib/static

Output
======
ld: framework not found UIKit
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)

The only other lines in the log file that may be relevant are;

[Wed Feb 01 17:35:08 CET 2023][FINE] PB Command for compile-additional-sources: clang -c -DSUBSTRATE -xobjective-c -arch arm64 -mios-version-min=11.0 -I/Library/Java/JavaVirtualMachines/graalvm-svm-java17-darwin-m1-gluon-22.1.0.1-Final/Contents/Home/include -I/Library/Java/JavaVirtualMachines/graalvm-svm-java17-darwin-m1-gluon-22.1.0.1-Final/Contents/Home/include/darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.2.sdk -DGVM_17 -I/redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/gvm/HelloSharedLib dummy.c
[Wed Feb 01 17:35:08 CET 2023][FINE] Start process compile-additional-sources...
[Wed Feb 01 17:35:08 CET 2023][FINE] Result for compile-additional-sources: 0

Does anyone know the resolution?

Removing some offending frameworks will allow clang to create the library, but it will fail to link on deployment to the physical device.

dyld[21677]: Library not loaded: /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib
  Referenced from: <621E3E84-DB84-30F0-AB2A-74B6EEECA791> /private/var/containers/Bundle/Application/2321AEDA-A346-4C64-9657-617BB6AF6C14/Runner.app/Runner
  Reason: tried: '/usr/lib/system/introspection/HelloSharedLib.dylib' (errno=2, not in dyld cache), '/redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib' (errno=2), '/private/preboot/Cryptexes/OS/redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib' (errno=2), '/redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib' (errno=2), '/usr/local/lib/HelloSharedLib.dylib' (errno=2), '/usr/lib/HelloSharedLib.dylib' (errno=2, not in dyld cache)

If I try to deploy to sim, I get the expected message that the lib was compiled for a different target, so it looks like Xcode is at least trying to link the file.

If I deploy the shared lib for macOS that was built with mvn gluonfx:sharedlib, Xcode successfully links with the HelloSharedLib.dylib, so it seems like the error is in the hack of `clang` to create the dylib.

I checked for the UIKit and it is under the child directory/System/Library/Frameworks

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.2.sdk/...


Edit to add verbose output

Homebrew clang version 15.0.3
Target: arm64-apple-darwin22.1.0
Thread model: posix
InstalledDir: /opt/homebrew/opt/llvm/bin
 "/usr/bin/ld" -demangle -lto_library /opt/homebrew/Cellar/llvm/15.0.3/lib/libLTO.dylib -dynamic -dylib -arch arm64 -platform_version ios 11.0.0 16.2 -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX12.sdk -undefined dynamic_lookup -w -undefined dynamic_lookup -o /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/HelloSharedLib.dylib -L/Library/Java/JavaVirtualMachines/graalvm-svm-java17-darwin-m1-gluon-22.1.0.1-Final/Contents/Home/lib/svm/clibraries/27/ios-arm64 -L/redacted/path/.gluon/substrate/javaStaticSdk/18-ea+prep18-8/ios-arm64/staticjdk/lib/static /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/gvm/HelloSharedLib/dummy.o /redacted/path/github/gluon-samples/HelloSharedLib/target/gluonfx/arm64-ios/gvm/tmp/SVM-1675322770429/hello.hellosharedlib.o -ljava -lnio -lzip -lnet -lprefs -ljvm -lfdlibm -lz -ldl -lj2pkcs11 -ljaas -lextnet -lc++ -lpthread -llibchelper -lffi -ldarwin -framework Foundation -framework UIKit -framework CoreGraphics -framework MobileCoreServices -framework OpenGLES -framework CoreText -framework QuartzCore -framework ImageIO -framework CoreBluetooth -framework CoreImage -framework CoreLocation -framework CoreMedia -framework CoreMotion -framework CoreVideo -framework Accelerate -framework AVFoundation -framework AudioToolbox -framework MediaPlayer -framework UserNotifications -framework ARKit -framework AVKit -framework SceneKit -framework StoreKit -framework ModelIO -framework WebKit -lSystem
ld: framework not found UIKit
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)


Solution

  • Solved it.

    I've used LLVM installed via brew and set the flags recommended by this installation;

    LDFLAGS="-L/opt/homebrew/opt/llvm/lib"
    CPPFLAGS="-I/opt/homebrew/opt/llvm/include"
    PATH="/opt/homebrew/opt/llvm/bin:$PATH"
    

    These clash with the installation from either Xcode or Gluon (I'm unsure which) and caused the linker error.

    I removed the environment variables and restarted and the problem went away.

    Thank you José for your help, which ultimately led me to the solution.