How to use the static library in embedded private and iOS apps

What should be the correct way to use classes in a static library in a private structure, application, and extension? My sample project can be found here https://github.com/keithyipkw/framework

In the second commit, the SDK was associated with .a. application launch caused an error

Ld /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/FrameworkApp.app/FrameworkApp normal x86_64 cd /Users/keithyip/Documents/Workspace/FrameworkApp export IPHONEOS_DEPLOYMENT_TARGET=8.4 export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.4.sdk -L/Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator -F/Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator -filelist /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Intermediates/FrameworkApp.build/Debug-iphonesimulator/FrameworkApp.build/Objects-normal/x86_64/FrameworkApp.LinkFileList -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -fobjc-link-runtime -Xlinker -no_implicit_dylibs -mios-simulator-version-min=8.4 /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/SDK.framework/SDK -Xlinker -dependency_info -Xlinker /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Intermediates/FrameworkApp.build/Debug-iphonesimulator/FrameworkApp.build/Objects-normal/x86_64/FrameworkApp_dependency_info.dat -o /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/FrameworkApp.app/FrameworkApp Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_GAI", referenced from: objc-class-ref in AppDelegate.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 

The character is global in .a but local in the SDK

 $ nm -a /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/SDK.framework/SDK | grep '_OBJC_CLASS_$_GAI' 00000000000d94e0 s _OBJC_CLASS_$_GAI 

In the third commit, I added the .a option to the application. The application works, but with warnings

 objc[3743]: Class GAI is implemented in both /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/SDK.framework/SDK and /Users/keithyip/Library/Developer/CoreSimulator/Devices/752A7B8E-405E-4403-BDD8-A168613774B1/data/Containers/Bundle/Application/D16B5121-2DA9-452B-9574-95B35AE3E197/FrameworkApp.app/FrameworkApp. One of the two will be used. Which one is undefined. 

I checked the binary SDK and applications according to the file paths in the warning

 $ nm -a /Users/keithyip/Library/Developer/Xcode/DerivedData/FrameworkApp-bpzqozighjdtncegosucvgelzagc/Build/Products/Debug-iphonesimulator/SDK.framework/SDK | grep '_OBJC_CLASS_$_GAI' 00000000000d94e0 s _OBJC_CLASS_$_GAI $ nm -a /Users/keithyip/Library/Developer/CoreSimulator/Devices/752A7B8E-405E-4403-BDD8-A168613774B1/data/Containers/Bundle/Application/D16B5121-2DA9-452B-9574-95B35AE3E197/FrameworkApp.app/FrameworkApp | grep '_OBJC_CLASS_$_GAI' 0000000100032c88 s _OBJC_CLASS_$_GAI 

Digging deeper with nm -m, libGoogleAnalyticsServices.a is different from other static libraries. Linking to other libraries in a dynamic library is no problem.

 0000000000002b20 (__DATA,__objc_data) private external _OBJC_CLASS_$_GAI 

It seems impossible to keep the characters public.

 clang: error: invalid argument '-keep_private_externs' not allowed with '-dynamiclib' 
+6
source share
3 answers

Usually you can simply link the static library to the dynamic library. However, in this case, the characters in .a are private external (visibility = hidden), it is impossible to include libGoogleAnalyticsServices.a in the dynamic library and use characters outside the dynamic library on iOS. Possible solutions to this problem:

  • Change dynamic library to static library
  • Recover Code To Remove GA From Dynamic Library
  • Create wrapper classes for GA so that called users do not need to reference GA

If someone faces a similar situation in the future, other options

  1. Ask the seller to expose the characters
  2. Check if there is an equivalent of "objcopy - globalize-symbols" for iOS. The closest is objconv as I write this. It supports OS X, but not iOS. objcopy equivalent for Mac / iPhone?
+4
source

Took your project and tried a few things. The only thing that seems to work would be to use the compilation -flat_namespace . By default, everything runs with a two-level namespace.

If you use the -flat_namespace option, the linker allows you to use the -undefined suppress , which prevents an error with undefined characters. The result will be that all of them will be fully resolved when the last link is executed, and you will contact the assembly of the application in google.a.

Unfortunately, the google library is not built flat, so this will not work if you cannot get a flat build.

The only thing that definitely works is to change the SDK target to a static target. Assuming that you have posted and are making only this change, it compiles and runs without errors. So this is your best choice or to avoid the problem in other ways, as you noted in your comments.

+2
source

I ran into a similar problem, with the exception of OS X: I created a framework with dylib inside and linked in a static library. I wanted to make symbols public in a static library accessible to applications using the framework. Although I set the correct visibility attributes for the static classes / methods of the library that I wanted to export, these characters were removed from the final library.

One workaround was to write some code in a dynamic library to reference these characters in a static lib; this ended up with the linker not cutting out export symbols from the static lib.

The ultimate solution was to create a static library as a relocatable object file; the resulting dynamic library had all the export symbols from the static library that I wanted, and a bit of reference code in the dynamic library was not required.

0
source

All Articles