Xcode: Handling "duplicate symbol" for external libraries - ios

In our project we rely on 2 printer libraries: StarIO & Epson ePOS, and during compile i hit this error:
duplicate symbol _GetOnlineStatus in:
/Users/brendan/Development/xxxx/Frameworks/StarIO.framework/StarIO(StarIOPort.o)
/Users/brendan/Development/xxxx/xxxxApp/SDKs/Epson/libepos2.a(eposprint_common_status.o)
ld: 1 duplicate symbol for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see
invocation)
Need some help with the best way to resolve this issue please.

This situation can sometimes be challenging — since both libraries are seemingly using the same symbol and because the implementations could be different. The only reliable way to fix this is to have each library vendor use a prefix for each of their classes/symbols within their libraries.
Apart from that, since I assume you only have the compiled version of the epson library (libepos2.a) you'll either want to:
Rename the symbol(s) that clash in StarIO.framework
Combine both libraries.
Option 1:
If you decide to simply rename the symbol causing the issue do a search in StarIO.framework:
GetOnlineStatus
Then rename it everywhere (in 12 files) it shows up in that library to something slightly different:
StarIO_GetOnlineStatus
Located in the following:
StarIO.framework/Versions/A/Headers/SMPort.h
StarIO.framework/Versions/A/Headers/WBluetoothPort.h
StarIO.framework/Versions/A/Headers/BluetoothPort.h
StarIO.framework/Versions/A/Headers/starmicronics/StarIOPort.h
StarIO.framework/Versions/Current/Headers/SMPort.h
StarIO.framework/Versions/Current/Headers/WBluetoothPort.h
StarIO.framework/Versions/Current/Headers/BluetoothPort.h
StarIO.framework/Versions/Current/Headers/starmicronics/StarIOPort.h
StarIO.framework/Headers/SMPort.h
StarIO.framework/Headers/BluetoothPort.h
StarIO.framework/Headers/WBluetoothPort.h
StarIO.framework/Headers/starmicronics/StarIOPort.h
Option 2:
The other option would be to combine the two libraries into one, although that can be quite a bit more complicated and present other issues perhaps. For details on how to go about doing so please see this answer here on stackoverflow.

Related

Marking a symbol as undefined in iOS framework

I'm building an iOS framework using Swift and Objective-C (have to use both of them due to other constraints).
In my objective-c code, I need to use a symbol, call it MyUndefinedSymbol, that will be available during runtime, but not during compile and link time.
I defined the symbol as extern to silence compiler errors:
extern void MyUndefinedSymbol();
However, linker complains that MyUndefinedSymbol is not defined.
Question is: how do I make the linker ignore that undefined symbol?
Searching for this brought me many solutions, none of them workd.
The things I tried:
Using the -undefined linker flag. It is deprecated and won't allow enabling bitcode (which I need).
Using clang's -U flag.
Adding a weak_import attribute using __attribute__((weak_import))
Using --unresolved-symbols=ignore-all.
For future readers:
Seems like the right way to do it is exactly as #Martin R suggested - using dlsym() to load the symbol at runtime.
Note that dlsym will not work on symbols which are marked as "Internal".
You can find out if a symbol is internal by running nm -m on your library/binary.
In addition, solutions 1 and 2 from the questions itself should work if you disable bitcode.

Linker Error in iOS (duplicate symbols for architecture x86_64) when running on Xcode simulator

duplicate symbol _llvm.cmdline in:
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleInterchangeUtilities/Frameworks/GoogleInterchangeUtilities.framework/GoogleInterchangeUtilities(Descriptor.pb.o)
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleSymbolUtilities/Frameworks/GoogleSymbolUtilities.framework/GoogleSymbolUtilities(overload.o)
duplicate symbol _llvm.embedded.module in:
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleInterchangeUtilities/Frameworks/GoogleInterchangeUtilities.framework/GoogleInterchangeUtilities(Descriptor.pb.o)
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleSymbolUtilities/Frameworks/GoogleSymbolUtilities.framework/GoogleSymbolUtilities(overload.o)
A duplicate symbol error means that somewhere in your project being compiled, something that can only be defined once (like a function, const or class) is being defined twice, and hence the name, duplicated, so the compiler is unsure which definition to use.
However, it is highly likely that this is not a problem with you. These particular symbols, namely _llvm.cmdline and _llvm.embedded.moduleare not generally user-defined symbols and are generally created instead by a framework that you are using, people have encountered this error using frameworks by Twitter and Facebook as well. Looking at the paths to the two files where there are conflicting symbols confirms my suspicion. The errors are being generated in a file in the Google Utils framework.
Firstly, if you made any changes to these google framework files themselves, undo them, as your added or changed code may be the problem.
There are a few fixes that may work for you. The first is that this could be a cocoapods issue. Ensure that you have the default "Debug" and "Release" build configurations in your project, otherwise cocoapods will not handle this well. The next fix that I would suggest is to not include the GoogleInterchangeUtilities framework in the project. GoogleSymbolUtilities was in fact introduced to fix this error cropping up in other google frameworks, so try ONLY including googleSymbolUtilities in your project rather than both symbolutilities and interchangeutilities. Failing that, If there are other versions of these two google frameworks you can download, download a different version, as a fix might have been released or you can find a version before this bug occurred.
If none of these work for you then I would advise getting in touch with google to notify them of this issue, and then sitting tight for a fix.
You can try
Project-> Build Settings-> Enabled bit code (change it From Yes to No) i hope it works for you, if it doesn't please check your pods updated or not or if still your facing problem give some details about issue.

How do I resolve linker warning "ignoring linker optimzation hint at" in XCode?

A google search for "ignoring linker optimzation hint" practically turns up nothing. NOTE: "optimzation" is the exact spelling :)
I'm using a 3rd party WebRTC library (libjingle_peerconnection) from Pristine in one of my apps and I get warnings when I build for my iPhone 6. I'm not sure if this warning will pop up for other devices, however, it does not appear when I build for the simulator.
I have exactly 68 of these bad boys in my build output:
ld: warning: ignoring linker optimzation hint at _cftmdl_128_neon+0xF0 because ldrInfoC.offset == 0
I'm not sure if I should notify the maintainers or if this is something I can resolve myself.
If you're compiling the WebRTC library by yourself using build scripts, the warnings are generated because of a missing parameter in GYP_DEFINES.
In order to fix the warnings, the WebRTC library needs to be compiled again with the parameter clang_xcode=1 in the GYP_DEFINES setting, like below (only an example):
export GYP_DEFINES="$GYP_DEFINES OS=ios target_arch=arm64 clang_xcode=1"
More about the issue can be found here, on the Chromium forums:
https://bugs.chromium.org/p/webrtc/issues/detail?id=5182
--
If you're not compiling the WebRTC library yourself, and instead installing the WebRTC library from a 3rd party source, I don't believe there is a fix as the warnings are stemming from the static library.

Sphero with iOS 7

I'm having trouble with Sphero and iOS 7. Like it said to on the quick start guide, since the 1.6 release notes which were supposed to have instructions for starting a new project did not have said instructions, I used the "integrate into an existing project" tab, I set my deployment target to 6.0, brought in all the frameworks, and added the linker settings. When I launch it, I get this error:
Undefined symbols for architecture armv7:
"_OBJC_CLASS_$_RKMCStop", referenced from:
objc-class-ref in RobotKit(RKMacroObject.o)
"_OBJC_CLASS_$_RKMCWaitUntilStop", referenced from:
objc-class-ref in RobotKit(RKMacroObject.o)
objc-class-ref in RobotKit(RKRobotControl+MacroAdditions.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Can anybody help me? I would appreciate it a lot! Thanks in advance,
Joe
I guess I was wrong in assuming "The examples in this guide were built using Objective-C and have been tested with the current released OS and current version of Xcode" meant that the API was tested for the current version of iOS and Xcode.
Alright, so I was able to reproduce this error in my own project, so that's good. I don't think the problem is specific to iOS 7, but rather to their poor instructions for integration. But, I was able to get something working, so hopefully you can also. But, if you haven't yet really started, your best bet is probably cloning HelloWorld and putting your code in it. Moving on.
The version of the files they in the Frameworks directory appear to have a bug in it, and it's at a level that us developers can't fix. I'm filing an issue on GitHub (will update this later) for their info. Fix Number 1: Use the three files from the HelloWorld/Frameworks directory instead of the top-level frameworks directory.
That will get you building and running, but you'll get an error in your log because you're trying to use an external accessory without declaring permissions on it. So, head over to your Info.plist, and add a key: "Supported external accessory protocols", with item 0 being "com.orbotix.robotprotocol". Worth a thousand words:
From there, you just need to implement the rest of what they show in that sample. Easier said than done. I ended up making a handful of other changes to make my project look more like HelloWorld, but I'm not sure they're necessary. I've uploaded the initial, working state of my project to GitHub if you want to take a look / give it a try. It's here: SpheroSays on GitHub
Good luck!

Preventing "duplicate symbol" errors with iOS frameworks

Apple uses the following code in the header of all its framework classes.
#if !defined(__COREFOUNDATION_CFARRAY__)
#define __COREFOUNDATION_CFARRAY__ 1
...
#endif
Is this a recommended approach for eliminating "duplicate symbol" linker errors, when designing classes or categories for framework use, or are these left over protection from the use of #include instead of #import in c?
Research into this has lead me to this article on include guard
NOTE: this question is not asking how to fix a duplicate symbol error, but instead asking if there is any way of preventing your own code from causing the problem if its included more than once in a project.
You're right about the include guard - there's probably some compatibility reason it's not been removed from the source.
However, this won't really protect you against duplicate symbols much.
For example,
What if you have two third party library, each of which uses the SBJSON library (I had this happen to a colleague a few weeks ago).
Each of the libraries was compiled seperately so, from their point of view, SBJSON was only included once. However, when I came to link my app I couldn't because I had duplicate symbols.
I had to solve this by manually removing the symbols from one of the .a library files (This link shows it's quite a common problem!)
EDIT : This link is a much clearer step by step solution to the problem
Apple uses the following code in the header of all its framework classes.
Not necessarily for the ObjC APIs. But CoreFoundation, yes they use include guards. It's still idiomatic in many camps to use traditional #includes in C sources, and to use #import for objc sources (#import is a compiler extension, not traditional C).
Is this a recommended approach for eliminating "duplicate symbol" linker errors
No, it does not prevent linker errors; it can result in duplicate declaration errors during compile phases.
If you're getting duplicate symbol linker errors, the problem is something else, such as visibility of definition. For that, you should provide an example of your troubling program.

Resources