iOS static library debugging symbols not included in the app's dSYM file when archiving - ios

Problem description:
I have an Xcode workspace that references two Xcode projects. The first Xcode project (lib.xcodeproj) builds an iOS static library while the second project (app.xcodeproj) builds an iOS app that consumes the static library. app.xcodeproj references lib.xcodeproj, i.e. lib.xcodeproj is listed in app.xcodeprojs Link Binary With Libraries build phase.
So, the setup is as follows:
MyApp.xcworkspace
|
+-app.xcodeproj---+
| | Referenced via build phase
+-lib.xcodeproj <-+
If I open this workspace in Xcode and build an archive out of it (Productmenu -> Archive) everything compiles as expected and I end up with an .xcarchive. The same applies if I build via command line (xcodebuild archive -workspace MyApp.xcworkspace ...).
However, dumping the content of the dSYM file that is generated as part of the archive reveals that it does not contain the debugging symbols of the static library (lib.xcodeproj). To be more specific, executing the command
dwarfdump MyApp.xcarchive\dSYMs\MyApp.app.dSYM\Contents\Resources\DWARF\MyApp > dwarfdump.txt
generates a text file that confirms that all debugging symbols of the app itself are there but the debugging symbols of the static library are not.
This only happens when creating archives. Producing a build via Product menu -> Build produces a dSYM file containing all debugging symbols of the app AND the static library.
Now, this isn't exactly new. That behavior was already observed ages ago and I found three different SO posts describing the same behavior (here, here and here). However, these posts are more than 7 years ago!
What I would like to know:
How do other people create archives of apps that are using static libraries created in the same workspace?
Seems that without scripting and just with Xcode itself this is an unsolvable problem.
Analysis (for the curious reader):
I've analyzed this issue and strongly suspect it is a long lasting Xcode issue. Here's what I found:
Building the workspace via xcodebuild build -workspace MyApp.xcworkspace ... produces the following sequence of log entries:
CompileC <static library file 1>
CompileC <static library file 2>
...
Libtool <instructions to create the static library>
...
CompileC <app file 1>
CompileC <app file 2>
...
GenerateDSYMFile <instructions to create the dSYM file>
...
CodeSign <instructions to sign the app>
Building the workspace via xcodebuild archive -workspace MyApp.xcworkspace ... produces the following sequence of log entries:
CompileC <static library file 1>
CompileC <static library file 2>
...
Libtool <instructions to create the static library>
Strip <instructions to strip the debugging symbols from the static library>
...
CompileC <app file 1>
CompileC <app file 2>
...
GenerateDSYMFile <instructions to create the dSYM file>
Strip <instructions to strip the debugging symbols from the app>
...
CodeSign <instructions to sign the app>
From these two sequences we see that when an archive is created we get calls to the strip tool. This tool strips out the debugging symbols from a binary. So, when the dSYM file gets created the static library simply does not contain any debugging symbols anymore.
When GenerateDSYMFile is executed, all that is left are the debugging symbols within the app. These symbols are then also stripped. BUT they are stripped after the dSYM file already exists and not before as is the case with the static library.
Now, there are build settings designed to influence that behavior. I found the following and tested whether they have an effect:
Strip Debug Symbols During Copy (COPY_PHASE_STRIP): Made no difference, the sequence is unchanged
Strip Linked Product (STRIP_INSTALLED_PRODUCT): Made no difference, the sequence is unchanged
Strip Style (STRIP_STYLE): Changes the argument that is passed to the strip tool. But I cannot prevent the information from being stripped nonetheless.
So, with that information I dare to make the statement that the build process used by Xcode for this constellation is simply incorrect. The correct way would be to run GenerateDSYMFile and only after that run strip for the static library and the app.

Related

Xcode: bitcode not included when doing Single-object Prelink

I'm using Xcode to prelink a collection of object files (*.o) and static libraries (*.a), all containing bitcode, into a single static library using Single-Object Prelinking.
In doing so, the resulting prelinked file does not contain bitcode.
The prelinking command and options emitted by Xcode looks like this:
ld -r -arch arm64 -bitcode_bundle -bitcode_verify -syslibroot
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk
a.o
b.o
...
x.a
y.a
-o libABC-arm64-master.o
The documentation for the bitcode_bundle option indicates that it "requires all the object files, static libraries and user frameworks/dylibs contain bit-code". I have used otool to verify that all of the constituent files contain bitcode.
No errors are raised or logged the by the ld command, even when I test it directly from the command line, separately from Xcode.
I'm stumped. And any help or suggestions would be appreciated.
Update: In further testing, I can create a prelinked file containing only any single .o file, and the final prelinked file WILL contain bitcode. However, including any two of those .o files, each of which contains bitcode, causes the prelinked file to contain NO bitcode.
You probably should check for _LLVM section in the result library, not _bitcode:
otool -l lib.a | grep _LLVM
https://stackoverflow.com/a/33105733/13891048

ld: building for tvOS, but linking in object file built for iOS, for architecture arm64

I'm building a project (the target is a framework if it's important) for tvOS and getting the error from the linker:
ld: building for tvOS, but linking in object file built for iOS, for architecture arm64
I ran otool -l *.o in OBJECTS_FILE_DIR_normal and figured out one of .o files is actually built for iOS instead of tvOS.
The problem is that there is no corresponding source file (*.mm or *.cpp) for that .o. It is called <ProjectName>_lto.o and I don't see any compiler invocations for that file in the build log. It appears only once in linker command line:
-Xlinker -object_path_lto -Xlinker /Full/path/to/<ProjectName>.build/Debug-appletvos/tvOS.build/Objects-normal/arm64/<ProjectName>_lto.o
LLVM_LTO build settings is not set explicitly, but it defaults to NO. Setting it to NO explicitly doesn't help.
I'm using Xcode 8.3.2 (8E2002).
So my question is: why is this object file created at all and why is it created for wrong target platform?
Not sure if this should be the answer to my own question or the edit, as it doesn't answer the original question "why that _lto.o file is generated at all for wrong arch with LLVM_LTO=NO", but it may help others troubleshoot this issue.
So I decided to try enabling LTO in the project. LLVM_LTO=YES_THIN behaved identically to LLVM_LTO=NO. LLVM_LTO=YES made linker produce tons of warnings like the following:
ld: warning: Linking two modules of different target triples: /path/to/one/of/3rdpary/libs/libproblematic.a(file1.o)' is 'arm64-apple-ios7.0.0' whereas 'ld-temp.o' is 'arm64-apple-tvos9.0.0'
ld: warning: Linking two modules of different target triples: /path/to/one/of/3rdpary/libs/libproblematic.a(file2.o)' is 'arm64-apple-ios7.0.0' whereas 'ld-temp.o' is 'arm64-apple-tvos9.0.0'
But with all those warnings for some weird reason the link succeeded. The interesting thing is that if I run otool -l libproblematic.a, I only see cmd LC_VERSION_MIN_TVOS lines and no cmd LC_VERSION_MIN_IPHONEOS and linker didn't complain on any of the objects from that library that they were built for wrong target platform. Also file1, file2, etc. do not appear in the output of otool -l libproblematic.a.

How to Resolve Xcode Linker Warnings For Tests Target in App

The solution offered in Apple LLVM 6.0 Error: clang failed with exit code -1 may work to resolve this problem, but as I stated at the end of my problem statement is that I did not want to remove the Tests target unless that is the only solution. So, is there another solution?
When trying to build a new app in Xcode, I am getting a ton of linker warnings. The warnings are related to a target that was automatically created called Tests. The expanded view of some of the warnings look like the following:
Ld /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Products/Debug-iphoneos/My\ AppTests.xctest/My\ AppTests normal arm64
cd "/Users/me/iPhone Apps/myProducts/My App"
. . .
ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.2.sdk/Developer/Library/Frameworks'
and
GenerateDSYMFile /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Products/Debug-iphoneos/My\ AppTests.xctest.dSYM /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Products/Debug-iphoneos/My\ AppTests.xctest/My\ AppTests
cd "/Users/me/iPhone Apps/myProducts/My App"
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/dsymutil /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Products/Debug-iphoneos/My\ AppTests.xctest/My\ AppTests -o /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Products/Debug-iphoneos/My\ AppTests.xctest.dSYM
while processing /Users/me/Library/Developer/Xcode/DerivedData/My_App-ahfusfuifhsybmalxaykbmfrhylc/Build/Intermediates/My App.build/Debug-iphoneos/My AppTests.build/Objects-normal/arm64/My_AppTests.o:
warning: /Users/me/Library/Developer/Xcode/DerivedData/ModuleCache/3K6537SSXYD4O/UIKit-2LM3EQU7VVY4O.pcm: No such file or directory
...
warning: Could not resolve external type c:objc(cs)XCTestCase
...
warning: Could not resolve external type c:objc(cs)_XCTestCaseInterruptionException
What can I do to eliminate these warnings? Since I don't really understand how to use test cases yet, I'd rather not delete the target (but if that is the only option, I will).
For these messages:
warning: Could not resolve external type c:objc(cs) xXX
The problem happens when you have a Xcode 6 project updated to 7. The short answer is to change the Debug Information Format to "DWARF", on the target, for the Debug configuration only.
Go to Build Settings and search for Debug Information Format
Change the Debug setting from "DWARF with dSYM File" to "DWARF"
Leave the Release setting at "DWARF with dSYM File"
This is safe because you don't need dSYM files for Debug builds

Build successfully for iOS Device But Build Error for iOS Simulator

I have been facing this lingering issue. When I try to Build the project by selecting iOS device in my Xcode it builds the code with out any error but when I trying the same with iOS simulator it shows me the following error. Is there any way to avoid this library file when I build in Simulator? I have tried the following Link as well but i couldn't figure the exact solution.
Thanks In Advance.
6 duplicate symbols for architecture i386
ld: warning: ignoring file /Users/iOS-MobileTeam/Downloads/iOS/LibraryFiles/libANMobilePaymentLib.a, missing required architecture i386 in file /Users/iOS-MobileTeam/Downloads/iOS/LibraryFiles/libANMobilePaymentLib.a (2 slices)
duplicate symbol _des_set_key in:
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-524F6BE9122BCA82.o)
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-D9CE0CBEE0B3BA81.o)
duplicate symbol _des_encrypt in:
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-524F6BE9122BCA82.o)
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-D9CE0CBEE0B3BA81.o)
duplicate symbol _des_decrypt in:
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-524F6BE9122BCA82.o)
/Users/iOS-MobileTeam/Downloads/iOS/LineaSDK/libdtdev.a(des-D9CE0CBEE0B3BA81.o)
ld: 3 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Ignoring file /Users/iOS-MobileTeam/Downloads/iOS/LibraryFiles/libANMobilePaymentLib.a, missing required architecture i386 in file /Users/iOS-MobileTeam/Downloads/iOS/LibraryFiles/libANMobilePaymentLib.a (2 slices)
The static library is broken as it contains two separate object files containing the same symbols (functions).
It must be rebuilt, or if you don't have the source you could unpack it, remove the offending file, and then re-pack it (untested):
$ mv libdtdev.a libdtdev-old.a
$ mkdir xxx
$ cd xxx
$ ar x ../libdtdev-old.a
$ rm des-D9CE0CBEE0B3BA81.o
$ ar cr ../libdtdev.a *.o
$ cd ..
$ rm -rf xxx
However if the static library contains multiple architectures, this becomes much more complicated.
The issue is that your libANMobilePaymentLib.a static archive was not built properly. If that is a 3rd party library, you should ask the author to provide an updated version which addresses this issue, and trojanfoe's instructions on unpacking and repacking the archive without one of the des implementations is probably your best bet for a temporary workaround.
If you built the library yourself or want to pass on information to the author, the issue is that the library's i386 slice contains duplicates of the des_set_key, des_encrypt, and des_decrypt symbols. I suspect that this was caused by accidentally including des.c twice when building libANMobilePaymentLib.a. Another possibility is that the author of libANMobilePaymentLib.a intended those functions to be static and not exported.
Finally I found the fix for the above issue. all credit goes to #Khanh
How to ignore some static library for iOS simulator
The above link helped me to fix the issue.
Steps to Fix The Issue:
Go to Project Build Settings and search for other linker flags.
2.Expand The other linker flags section. There will be two modes Debug and Release
Place the cursor over Debug Mode a + symbol will appear.
Click the plus Symbol.
A new option will be added like Any Architecture | Any SDK.
Change that Any SDK to Any iOS Simulator SDK
Set -objC Value for Any iOS Simulator SDK

Apple Mach-O linker (id) warning : building for MacOSX, but linking against dylib built for iOS

Starting from some point in the past xCode 4 in complaining about linker problems:
ld: warning: building for MacOSX, but linking against dylib built for
iOS:
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/System/Library/Frameworks//CoreGraphics.framework/CoreGraphics
I have checked everything but still nothing suspicious in the config and it compiles and runs.
The only thing that I see it is double slashes before CoreGraphics.framework, why I do not know. Tried remove and add again library on "Build phases" that did not help.
Sometimes it's easier to debug Xcode problems by looking at the build log for the command lines it's using.
If you're building from the command line, you can get that message if you don't specify -miphoneos-version-min=
This compiles:
(where conftest.c just contains int main() {})
/Applications/Xcode5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 --sysroot /Applications/Xcode5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk --sysroot /Applications/Xcode5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk -miphoneos-version-min=6.0 conftest.c
And this gives the error:
/Applications/Xcode5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 --sysroot /Applications/Xcode5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk --sysroot /Applications/Xcode5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk conftest.c
ld: building for MacOSX, but linking against dylib built for iOS Simulator file '/Applications/Xcode5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/lib/libSystem.dylib' for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Check your Framework Search Paths for your Main target and your test Target.
I had a lot of crap in mine.
had old project written in XCode 4 and just started to use Unit Tests in XCode 5.
Here's the minimum I have to get my test project to run
Project Navigator > click on project at top >
Targets > Build Settings > Framework Search Paths
TARGET:my_project
$(inherited)
"$(SRCROOT)"
"$(SRCROOT)/my_project"
TEST:my_projectTests
"$(SDKROOT)/Developer/Library/Frameworks" <<XCTest.framework is here
"$(DEVELOPER_LIBRARY_DIR)/Frameworks"
"$(SRCROOT)/.."
"$(SRCROOT)" << Documents/my_project
"$(SRCROOT)/my_project" << Documents/my_project/my_project
where directory structure is
Documents/my_project
my_project.xcodeproj
/my_project
Note: If you drag a framework into XCode. XCode 5 has bad habit of hardcoding the path
/Users/gbxc/Documents/my_project
should be
"$(SRCROOT)" << Documents/my_project
"$(SRCROOT)/my_project" << Documents/my_project/my_project
so if you moved your project might get problems
Best way to check whats correct is to create a new single view project that runs tests ok.
Run the Test action
By default it fails but at least testing is running
then compare the Framework Search Paths.
If you're using Carthage and compiling a Mac app, search on your project's Framework Search Paths you might find something like $(PROJECT_DIR)/Carthage/Build/iOS.
Removing that fixed my issue.
This issue is due to include a wrong framework version in Xcode. The project is built for Mac OS X, but it uses iOS version's framework.

Resources