iOS framework with dependencies - objective-c

I have created two iOS .frameworks
they both compile perfectly
my structure is as follows:
iPadProject
- framework1
- framework2
So Framework2 is included in framework1 and framework1 is included in the actual iPad Project
So my problem is, if I add both framework1 and framework2 into my iPadProject it won't compile because its whining about duplicate symbols from framework2 ( that's logical because it was already included in framework1)
But if i only include framework1 into my iPadProject when i access a method from framework1 that in his turn access a method from framework2 it crashes the application with "signal SIGABRT"

Do not nest static libraries, including iOS frameworks. As you've seen, it leads to major problems (it leads to even more problems when two frameworks each have their own version of the third). The final link step should link all libraries required; static libraries should never link other static libraries. There is no really good way to automate this; it just has to be part of the documentation for the framework.
You shouldn't be getting runtime exceptions, though, for failing to link a framework. You should be getting link-time failures that indicate that the symbol isn't defined. If you're getting a crash, that suggests you're doing something strange in your linking.

the problem is that because it is nested right now, the linker links f2 into f1 -- BUT only the parts of f2 that are needed by f1.
like
f2 has 5 symbols (f2_1 - 5)
f1 uses f2_1 and f2_2 but NOT 3,4,5
=> the linker throws it away
now the app needs f2_3, f2_4 and f2_5 but they aren't there... but nobody knows that at compile time.
now you try to resolve it by linking the app with f2 again but as before nobody at compile time the linker optimized out f2_3 - 5 and they are assumed to be in f1 and so are duplicates!
the way to solve this Rob Napier already mentioned. Don't nest Frameworks (mainly not static ones / 3rd part ones)
a workaround is to pass -all_load to the linker when f1 links in f2!

Related

Reference to ' ' is ambigous error in Xcode

I was working with a custom iOS framework project in Xcode.There I am getting a lot of errors mentioning "Reference to ' ' is ambigous".I am attaching the screenshot of errors.Please help me correcting this.
Adding more information to Jason's answer.
The error message makes me think you have two declarations of the same library functions. All of those references are from UIKit
mostly this can be occurring because of the header files. As you can see all the errors indicates that it is quoting the enum values. Enum values will always be in the .h files. Normally the reference headers(.h files) will be present inside the frameworks. It is a common mistake that sometimes these header files will be buried some where in our code by any third party frameworks. So kindly check your third party libraries.
I did face this issue once and after searching everywhere i could not able to find the solution. The only thing solved my issue was
Opening a fresh project and importing my files into that project. Actually it really took me less than 10 minutes to move to a new project and immediately my xcode was happy. This is definitely worth a try.
Actually This error was cleared when I shift from iOS SDK 6.1 to 7.1(or any version higher that 6.1)
The error message makes me think you have two declarations of the same library functions. All of those references are from UIKit. Check to make sure only one version of UIKit is referenced in your project (check the frameworks), and make sure any libraries you have included are linking the same UIKit version as the rest of the app.
Steps to fix from here:
Clean the project
Delete everything inside
'~/Library/Developer/Xcode/DerivedData/ModuleCache/' (the button
inside the organizer window did not work for me)
Clean once more
Build project
from here: Reference to 'X' is ambiguous
Clean your project and rebuild again.If it don't work then create a new project
Set value of Enable Module (C and objective-c) to No

Google maps iOS SDK breaks when a certain library is linked into the application

Background
I am exploring using the Google Maps iOS SDK in an application that will also tightly depend on another statically linked C++ library. I have accomplished Google's prescribed Hello World program successfully with one caveat: using the -ObjC linker flag causes linker errors with my other library. To remedy this, I've been using the -force_load /path/to/GoogleMaps instead in order to only target the GoogleMaps framework, which seems to work well.
The Problem
When I reference certain (not all) classes inside the static library in custom C++ classes in my app (even if I don't instantiate those classes in the app itself) I repeatably see this strange runtime error:
ClientParametersRequest failed, 3 attempts remaining (0 vs 5). (null)
ClientParametersRequest failed, 2 attempts remaining (0 vs 5). (null)
ClientParametersRequest failed, 1 attempts remaining (0 vs 5). (null)
ClientParametersRequest failed, 0 attempts remaining (0 vs 5). (null)
The result in the app is that the pin and default off-white google background appear, but no maps are downloaded.
If I delete the app from the simulator or device and comment out the static library code and run the app, the maps load and everything works fine. Then, if I add those lines back in and run the app, I don't see these errors and the maps still load fine.
If I delete the app and leave those lines in for the firstrun of the app, I get these errors, but if I then comment out the library code and re-run it, the maps begin to load and all is well. Adding back in the library code does not cause the error messages/runtime issue to come back.
This leads me to believe that the error is occurring in some sort of initialization routine that is never subsequently called. I checked the files in the app sandbox and some are missing until the maps load properly, which makes me think this is correct.
I have access to the source for the static library but obviously don't have access to the GoogleMaps SDK. There does not appear to be any clear documentation about what this error means, especially in my case where (null) is the final piece.
A few final notes that may or may not be relevant:
C++ Language Dialect: C++11 [-std=c++11]
C++ Standard Library: libc++
Thanks in advance for any help!

Static library with ARC support linked to non-ARC project causing linker errors

I have a non-ARC project that uses an ARC-enabled static library. This is a supported scenario, so that everything works fine. That is, until I run the code on a 4.x device, including the Simulator. In that case the code blows up with the following linker error:
dyld: lazy symbol binding failed: Symbol not found: _objc_storeStrong
Referenced from: /Users/zoul/Library/Application Support/iPhone Simulator/4.3.2/Applications/…/Demo.app/Demo
Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
This happens as soon as some of the ARC-enabled code attempts to call _objc_storeStrong function, like in an init method (self = [super init]). Converting the main project to ARC solves the problem, but I’d like to know if there are other solutions.
I assumed that the toolchain may have added the necessary libraries to link to, in order for ARC to work properly. So the linker transcript may contain this piece of information. If the project of the app itself is not ARC-enabled, you may not get these by default, but you could still link to them by defining them explicitly.
Looking at the build transcript you can indeed find the appropriate linker flag there: it’s called -fobjc-arc (just as the related compiler flag). When you add this setting to Other Linker Flags, the linker will include the ARC library with the main build product and the code should run fine.
I'm adding a new answer to this as the previous accepted solution no longer appears to work with Xcode 4.3.2. I can only assume that the -fobjc-arc linker flag was never supposed to be exposed and has now been removed.
This appears to be a known issue although the only thread I can find on this with somebody from Apple commenting on the devforums dates back to mid-2011. From that thread, it is suggested that manually linking the following file solves the issue:
${DEVROOT}/Platforms/iPhoneOS.platform/Developer/usr/lib/arc/libarclite_iphoneos.a
This requires you to be compiling using the latest compiler/SDK though. I'm submitting this answer without testing, please upvote if it works, downvote if it doesn't!

is there anywhere where I could start MobileSubstrate tweaks programming?

After a search here on the forum I found a question like that, and it redirected me to a tutorial which gave em some basic instructions on manipulating SpringBoard with CapitainHook.
To start I'd like to do it with normal %hooks only. Any hint where I could start?
This little introduction is meant for whoever has a minimal knowledge on Objective-C and knows what he is doing.
NOTE: I will refer to the theos install path as $THEOS. This could be ~/theos, /var/theos, /usr/theos... Yeah.
The most popular way of creating MobileSubstrate extensions, also known as tweaks, is using Dustin Howett's theos build suite. Details follow:
What is theos?
So, we should start with what theos is not:
The Operating System
A Greek God
A compiler
And of course, what theos doesn't do:
Teaches you how to code.
Creates tweaks without having you to think
Sets up a whole building environment and/or installs the iOS SDK.
Theos is a cross-platform suite of development tools for managing, developing, and deploying iOS software without the use of Xcode, featuring:
A robust build system driven by GNU Make, which makes its Makefiles easily deployable through everywhere with theos installed too.
NIC, a project templating system which creates ready-to-build empty projects for varying purposes.
Logos, a built-in preprocessor-based library of directives designed to make MobileSubstrate extension development easy and with optimal code generation.
Automated packaging: Theos is capable of directly creating DEB packages for distribution in Cydia, the most popular mean of package distribution in the jailbreak scene.
How to install theos?
On OSX: Have the iOS SDK installed and follow these instructions.
On iOS: Install the BigBoss Recommended Tools package from Cydia and run installtheos3.
On Linux: Find a mean to have the toolchain installed, and follow these instructions.
On Windows: Nothing is impossible, but if you actually manage to do so, please let me know. :P
How to use theos?
This is a very asked question and too vague. Since theos is a whole suite of development tools, it doesn't make sense to ask How to use it, but more specifically, to ask How to create software using theos.
First of all, always have the Theos Makefile Reference in hand. It covers the basics of creating a theos Makefile, and that includes solving your linking issues adding a framework or private framework to the project.
Now, you can either create your own Makefile from scratch, create your little theos clone/symlink and start coding, but theos makes this step easier. You can just use nic.pl.
A very simple example of running NIC to create something can be found here. It's very straight-forward and sets you up right-away for programming.
Now, here's where we start getting back to topic.
Creating a tweak with theos
First of all, do not run NIC when inside $THEOS/bin. NIC will create the project directory exactly where you're running it from, and it avoids any project being created in $THEOS/bin. Therefore, you'll end up with a simple error which can be avoided by creating the project directory somewhere decent.
Run $THEOS/bin/nic.pl and choose the iphone/tweak template. You will be prompted by simple information which you may well know well how to answer, except for the last field: MobileSubstrate bundle filter.
Since a big part of MobileSubstrate is not just the hooker (the library which switches original methods/functions with yours), but also the loader (the part which gets your hooking to be inserted into certain processes), you have to supply this basic information for the Loader to know where to load your tweak. This field is but the bundle identifier for the application where this project will be inserted.
com.apple.springboard, the default option is the bundle identifier for SpringBoard, the application which is:
The iOS Homescreen
The launcher/displayer of common applications
The iOS Status Bar
Handler of some high-level essential background processes
Therefore, there's where many tweaks take place, altering behavior from something as trivial as app launching to something like how the whole homescreen UI looks like.
Programming a tweak with Logos
Now, the directory generated by NIC will contain:
The Theos Makefile, where you'll change information related to compiling
The control file, where you'll change packaging-related information
A symbolic link (or shortcut) to $THEOS named theos/
The main code file, defaulted as Tweak.xm. It is already added to the Makefile for compiling, so you can start coding right-away with it!
On knowing what to do
Now, you don't have SpringBoard's source code laying around, and you can't guess what methods to hook from nowhere. Therefore, you need a SpringBoard header set. For that, you need to use a tool named class-dump-z and run it into the SpringBoard binary (which is inside the iOS filesystem) to obtain header files including all class declarations and its methods inside the application.
From that (a deal of guessing and logging a method call is involved) you can start messing around with what you want in a tweak.
Of course, if you are not hooking SpringBoard you can use class-dump-z as you would in other binaries, such as UIKit, MobileSafari, etc.
Note that for when reversing App Store apps, they'll be encrypted. You'll need to decrypt those (I am unfortunately not allowed to tell you how-to), and then just run class-dump-z on them.
On obtaining private headers
Stuff like preference bundles require the headers for private frameworks, in that case the Preferences framework's headers. Else you'll get endless missing declaration errors (as I guess you could assume).
Getting them has the same logic applied the previous step. Run class-dump-z on, at this case, the Preferences binary and throw the headers at your INCLUDEPATH. The INCLUDEPATH is where the compiler will go looking for headers you include like #include <stdio.h>. Yes, stdio.h is inside one of the directories which build a compiler's INCLUDEPATH!
When compiling with a theos Makefile, $THEOS/include counts as part of your INCLUDEPATH, which means, you can just throw your dumped headers over there and include them later.
(Note that class-dumped headers aren't always perfect, so you're likely to have a couple of header-related compilation errors which can be easily fixed with something like removing a #import directive or changing it, or adding a couple of declarations.)
Code tips
You can't link against SpringBoard, so whenever you require a class from SpringBoard you have to use either the Logos %c directive or the objc_getClass function, as defined at <objc/runtime.h> to get it. Example: [%c(SBUIController) sharedInstance], [objc_getClass("SBUIController") sharedInstance].
When not knowing what a method does or how something works in SpringBoard, try disassembling it with IDA or others. I use IDA Demo (<- noob!) for my disassembling.
Looking at example code is amazingly helpful for both learning and figuring out how something works inside SpringBoard or others (again..). Great people at GitHub to have a projects looked at are rpetrich, chpwn, DHowett, EvilPenguin, and of course way more.
To also find about how SpringBoard and other works (...), have a look at a class's article at the iPhone Dev Wiki!
Epilogue
Wait, where's the good part? Where do I learn about coding in Tweak.xm?
Well, the original question was actually How to start MobileSubstrate tweaks programming?. You're all setup, hopefully with all headers placed, ready to type in make and see your project magically compiled with theos.
All you need to do is now to actually dig into your headers or your disassembly and go hooking, calling, etc.!
Logos Reference contains exactly how to hook and use other features of Logos, and the MobileSubstrate article on the devwiki is also a great read.
In case there is any doubt, don't hesitate joining the irc.saurik.com #theos IRC channel. It's a great way to discuss theos-related topics and ask questions. I'm mostly there, along with other greatly smart people ;)
You are looking for Theos created by DHowett.. Theos allows you to make tweaks, but it doesn't give you everything you need. You don't get every header for iOS, so you have to class-dump-z the frameworks/private-frameworks from the iOS SDK. Get started here: http://iphonedevwiki.net/index.php/Theos/Getting_Started, or join irc.saurik.net #theos for more help. You can also look at my projects that use theos: https://github.com/evilpenguin
You sound like you're looking for theos. Take a look at this, it should help get you started.

Getting: "Compilation exited with code 134" when attempting to use "LLVM Optimizing Compiler" switch

I'm getting a "Compilation exited with code 134" when attempting to use the "LLVM Optimizing Compiler" switch for release iPhone builds, using MonoTouch 4.0.1.
I don't get much information from build output window at all - just:
"Compilation exited with code 134, command:"
MONO_PATH=(snip)/bin/iPhone/Release/LSiOS.app /Developer/MonoTouch/usr/bin/arm-darwin-mono --llvm --aot=mtriple=armv7-darwin,nimt-trampolines=2048,full,static,asmonly,nodebug,llvm-path=/Developer/MonoTouch/LLVM/bin/,outfile=/var/folders/03/033pAAGuHgGkIy4CorbVV++++TI/-Tmp-/tmp38107451.tmp/Newtonsoft.Json.MonoTouch.dll.7.s "(snip)/bin/iPhone/Release/LSiOS.app/Newtonsoft.Json.MonoTouch.dll"
Mono Ahead of Time compiler - compiling assembly (snip)/mscorlib.dll
What is odd is that in earlier command lines, there is a correlation between the DLL mentioned in the arm-darwin-mono command line and what is the compiling, but in this case it says "mscorlib.dll".
Any thoughts?
I have found a few cases (googling and from bugzilla.xamarin.com) where the error code 134 is related to Mono.Linker being too aggressive (removing something that's needed).
This is easy to confirm by turning off the linker, i.e. "Don't link" in Linker Options. If the build works then you can try isolating the assembly where the linker makes a mistake.
E.g. add a "--linkskip=mscorlib" to the mtouch extra parameters and re-enable linking. This will link everything (Link All) or all SDK (Link SDK assemblies) except the assembly you selected (mscorlib in the example). That's only a workaround and a bug report should be filled so the issue can be fixed properly (and get you all the linker advantages).
However be warned that there are other issues sharing the same error code, like:
http://ios.xamarin.com/Documentation/Troubleshoot#Error_134.3a_mtouch_failed_with_the_following_message.3a
YMMV
mtouch does its native builds in parallel so the logs can be confusing, e.g. you can see a bit of assembly X output followed by some assembly Y output.
Reading the full log might help you (or us) to pinpoint the issue.
I was having the exact same problem Scolestock. My app would build fine until I enabled llvm, then it was "Compilation exited with code 134, command" when trying to build the 7s for the app itself.
I'm elated to say that after 2 days of painstakingly whittling my app down to the core problem, I was able to isolate the issue to the usage of embedded dictionaries such as:
Dictionary<enum, Dictionary<enum, value>>
I was able to fix this by defining a class for the embedded dictionary and using that instead:
public class MyDefinition : Dictionary<enum, value>
{
}
...
public Dictionary<enum, MyDefinition>
Not sure if this will help you, but hopefully it'll help some poor soul who decides to use embedded dictionaries and runs into my same problem.