Xcode6 blocks some static libs in static lib, but not others - ios

Until xcode6, we had:
library target "appshared" builds a static lib and embeds multiple other static libs
Multiple apps embed static lib appshared, and automatically get the embedded static libs too
Now, with Xcode6, and a new 3rd party static lib (from MixPanel, who never quite seem to know what they're doing with packaging iOS binaries), score refuses to embed the new static lib, saying:
"can't locate file for -l[library name]
file: -l[library name] is not an object file (not allowed in a library)"
What's wrong with this new library, and ... any ideas what I have to ask the provider to fix in their build setup? (they don't share the source, sadly)

facepalm
It's a bug in Xcode 6 - nothing to do with the particular library.
Xcode no longer supports spaces in folder names, even though this has been a core requirement from Apple Corp for all Mac software for > 15 years; apparently, they don't test this for Xcode any more, and someone wrote some very bad code (probably: used the wrong (20 years old) method calls for manipulating file paths; if they'd used the correct ones, space-handling is automatic and implemented by the OS, IME!)
Solution: when you drag/drop libraries into Xcode 6, if there is a space in the folder name, Xcode will corrupt the build settings, and add a library-import-path for each word in the folder name.
You have to edit your Build Settings, find your library search paths, and you'll see it has lots of stupid values. Delete those, put the real path, and surround it in double-quotes.
All will then work fine.

Related

Linking the correct variant of an iOS static library using Xcode

I have an iOS static library.
As a matter of fact, I have four variants of it:
Debug-iphoneos/libopende.a
Debug-iphonesimulator/libopende.a
Release-iphoneos/libopende.a
Release-iphonesimulator/libopende.a
I want to link my iOS app against this static library using Xcode.
To do so, I go to Build Phases, and in Link Binary With Libraries, I click the '+' to add one, using Add Other.
Now I have the problem of which variant I should be adding. So I just pick one of the .a files, and hope Xcode is smart enough to find the others?
Anyways, if I do this, the linking fails saying it can't find libopende.a file.
So, is it even possible to do what I want, without first building a 'Framework' instead of a set of static libraries?
Ok, so when linking against a static iOS library, you need to know that:
It does not matter which .a file you add in the Build Phases - Link Binary With Libraries panel. Any of the four .a files will do, it only takes the file name, not its path.
To actually differentiate between library variants for Debug/Release Device/Simulator, you need to specify the correct library paths in the Build Settings - Library Search Paths.

I would like to use a UNIX command-line program (Berkeleys SPICE) in an iOS app. What is the process to compile it into a usable library?

I am trying to use Berkeley's SPICE tool in an iOS app, but am having trouble compiling it for iOS.
It is a command-line program that I can call from a terminal like:
./spice3f5 <arguments>
Which works well, and I would like this functionality in my iOS app, but I don't think I can just copy the executable over to Xcode and call it from Swift.
I've done some research and found the following:
There is an updated version of SPICE called ngspice, which is relatively new (2014 release)
I'm fairly sure there are apps out there than have used either SPICE or ngspice, so I'm sure it can be done somehow.
I have read an article about a guy who says that ngspice has been compiled as a shared library(ctrl+f "ngspice"), and he made an app with it. I have emailed him but he unfortunately he has not responded.
The reason I am asking here is because when googling for "ngspice iOS", I came across this thread which has a lot of smart people trying to compile a static library, which seems way out of my scope. I learned that dynamic libraries are allowed as of iOS8. So would it be easier to compile a *.dylib than it is a static library?
How would I goabout using ngspice or SPICE in an iOS app?
Thanks
The difference between a static and a dynamic library is essentially where they live, a static library will live inside the binary of your app, and an dynamic library will live on the system (iPhone) that runs your app. there isn't much difference as far as difficulty goes. If you wanted to go the dynamic route on os x for example, you might compile a .dylib file in a separate project first. Then copy your new .dylib file into /usr/lib or a similar location that is part of your system's path. Then you would need to copy the associated header files that know how to talk to your new .dylib file into your /usr/include folder. At this point you could import said header files in xcode using angle brackets like so:
#import <my_dylib_header_file.h>
in static world however, you would simply drag your .dylib file into xcode then copy the associated header files into your source folder and then import using quotes like so:
#import "my_dylib_header_file.h"
the advantage of doing the import statically is that the library becomes baked into your final product, as opposed to a dynamic link, which will require that the dylib is installed on the system prior to the binary being able to run properly (think DLL's on windows). The disadvantage of a static import is that the final binary is larger, as it contains more code.
The advantage of a dynamic import is that the binary is smaller, and dylib can be updated without updating the binary itself.
However based on your questions I don't think any of this matters for your project. You have the source code. Which means creating a dylib is entirely unnecessary for your purpose, you can treat the source code like a static library by simply adding it to your xcode project. If I were you I would add the spice source code to my xcode project and forget about creating a dylib. From there I would import the files and make calls to them from swift. There are lots of threads out there that explain how call c functions or objective-c classes from swift so I wont go into that here, instead I'll refer you to another answer: Swift: How to call a C function loaded from a dylib

How can I use a private method in MapKit on iOS? [duplicate]

I'm searching through the whole internet since a few hours now, and I just can't find the informations I'm looking for.
I would like to mess around with the private apis, see whats possible, etc., but I can't even compile something.
So I've got a few pretty basic questions:
Do I have to dump the headers? Because I downloaded a sample, where the API is loaded with
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
I would like to use the objc-syntax (if possible) rather than using C (as mentioned above), if there are any opportunities.
How do I make Xcode compile, if I import the private APIs? Do I have to add other link flags? (because I read about two different opinions)
I added a private framework and created a new Folder "Headers" and put all the headers files in there, so the framework shows up correctly in Xcode. Do I have to import the whole .framework, or only the headers from the framework I would like to use? After I imported the framework, I get 20+ errors, unknown type names, and many more.
And, finally, I've read about entitlements (which seem to be new in iOS 7). How do I use these entitlements and when do I use them?
Could someone please just type a few lines as an example?
Background
In order to use methods in any framework, you can choose to either reference those frameworks statically or dynamically. I haven't seen anything in your question that suggests you need to use dynamic linking, so I'm going to avoid that (it's slightly more complicated for a beginner). (&ddagger;)
To statically reference APIs in a framework, you would import the relevant headers, and then configure your Xcode project to link to the framework. These two steps only change slightly for Private APIs.
Private APIs usually don't provide you with the headers (*.h) that describe the APIs. I say "usually", because sometimes, an API that's private on iOS is actually public on Mac OS X, so to use it, you simply copy the OS X version of the header into your project.
Generating Headers
Probably more common, though, is that you have to generate the header yourself. If you know which header you need, often you can find it posted online under someone's github account. If not, you need a tool like class-dump, or class-dump-z. Run the class dump tool on the private framework, by finding it on your Mac:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
class-dump -H -o ~/Headers/7.0/MusicLibrary/ MusicLibrary
Then, go into ~/Headers/7.0/MusicLibrary/ and find lots of dumped header files. Copy (only) the header(s) you need into your Xcode iOS project directory. Then, from inside Xcode, right click on a source folder in your Project Navigator view, select "Add files to <Project Name> ...". Pick the dumped header file you need to include in your project.
Linking
In order to successfully link against the API, you also need to add the framework to your Xcode Build Phases. From your project Target settings, select Build Phases then Link Binary with Libraries. You normally choose a public framework from the default list that the iOS SDK provides you. However, you can choose to browse your Mac for 3rd-party frameworks, or private frameworks, too. For private frameworks, you're just going to have to navigate to a folder location like this
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
and then pick the *.framework directory.
Then, simply use the APIs like you would use any public/private API. #import the header file, call the APIs, instantiate the classes, etc.
The use of this code:
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
is an attempt to dynamically open a private framework. That's not necessary, if you know at compile time which framework you want to use, and have it present on your Mac to let Xcode link against.
Entitlements
Entitlements are not new to iOS 7. They have existed for quite some time, and are one technique iOS uses to prevent unauthorized usage of some private APIs. iOS will check to see if your app has been granted a particular entitlement (by name), and if it does not have that entitlement, calling the protected API will fail (usually silently, although sometimes you'll see a message in the Console log).
See here for an example of granting your (jailbreak) app an entitlement.
(&ddagger;) Update: iOS 9.3 has brought some changes with respect to Private APIs, and static vs dynamic linking. Please see this Stack Overflow question here for more.

iPhone private API compiling

I'm searching through the whole internet since a few hours now, and I just can't find the informations I'm looking for.
I would like to mess around with the private apis, see whats possible, etc., but I can't even compile something.
So I've got a few pretty basic questions:
Do I have to dump the headers? Because I downloaded a sample, where the API is loaded with
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
I would like to use the objc-syntax (if possible) rather than using C (as mentioned above), if there are any opportunities.
How do I make Xcode compile, if I import the private APIs? Do I have to add other link flags? (because I read about two different opinions)
I added a private framework and created a new Folder "Headers" and put all the headers files in there, so the framework shows up correctly in Xcode. Do I have to import the whole .framework, or only the headers from the framework I would like to use? After I imported the framework, I get 20+ errors, unknown type names, and many more.
And, finally, I've read about entitlements (which seem to be new in iOS 7). How do I use these entitlements and when do I use them?
Could someone please just type a few lines as an example?
Background
In order to use methods in any framework, you can choose to either reference those frameworks statically or dynamically. I haven't seen anything in your question that suggests you need to use dynamic linking, so I'm going to avoid that (it's slightly more complicated for a beginner). (&ddagger;)
To statically reference APIs in a framework, you would import the relevant headers, and then configure your Xcode project to link to the framework. These two steps only change slightly for Private APIs.
Private APIs usually don't provide you with the headers (*.h) that describe the APIs. I say "usually", because sometimes, an API that's private on iOS is actually public on Mac OS X, so to use it, you simply copy the OS X version of the header into your project.
Generating Headers
Probably more common, though, is that you have to generate the header yourself. If you know which header you need, often you can find it posted online under someone's github account. If not, you need a tool like class-dump, or class-dump-z. Run the class dump tool on the private framework, by finding it on your Mac:
cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
class-dump -H -o ~/Headers/7.0/MusicLibrary/ MusicLibrary
Then, go into ~/Headers/7.0/MusicLibrary/ and find lots of dumped header files. Copy (only) the header(s) you need into your Xcode iOS project directory. Then, from inside Xcode, right click on a source folder in your Project Navigator view, select "Add files to <Project Name> ...". Pick the dumped header file you need to include in your project.
Linking
In order to successfully link against the API, you also need to add the framework to your Xcode Build Phases. From your project Target settings, select Build Phases then Link Binary with Libraries. You normally choose a public framework from the default list that the iOS SDK provides you. However, you can choose to browse your Mac for 3rd-party frameworks, or private frameworks, too. For private frameworks, you're just going to have to navigate to a folder location like this
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk/System/Library/PrivateFrameworks/
and then pick the *.framework directory.
Then, simply use the APIs like you would use any public/private API. #import the header file, call the APIs, instantiate the classes, etc.
The use of this code:
char *framework = "/System/Library/PrivateFrameworks/...";
dlopen(...);
is an attempt to dynamically open a private framework. That's not necessary, if you know at compile time which framework you want to use, and have it present on your Mac to let Xcode link against.
Entitlements
Entitlements are not new to iOS 7. They have existed for quite some time, and are one technique iOS uses to prevent unauthorized usage of some private APIs. iOS will check to see if your app has been granted a particular entitlement (by name), and if it does not have that entitlement, calling the protected API will fail (usually silently, although sometimes you'll see a message in the Console log).
See here for an example of granting your (jailbreak) app an entitlement.
(&ddagger;) Update: iOS 9.3 has brought some changes with respect to Private APIs, and static vs dynamic linking. Please see this Stack Overflow question here for more.

Xcode - debugging library built outside project

I have a C library whose code resides in say /repos1/clib. I build that from the command line using the latest iOS sdk to create clib.a (including a debug build for the simulator) which I copy to an iOS project say in /repos2/proj.
I have been using this setup for several years. The old C library very occasionally might require some debugging and I was pleased by the fact that Xcode simply stepped into the library code that was outside the project (inside repos1) without having to do any setup - it just worked.
But this was up until a few Xcode versions ago. I am not sure exactly when it changed - perhaps when they moved from gcc to llvm? - since I very seldom needed to debug the C code, but for a while now I only get dissasembly when I try to debug the C library from the iOS project (including at least references to the C file name & line number). For the few times I need to debug it is very inconvenient (I create a temp project that includes the C code).
So, any idea why it worked before and doesn't now? Where should I look? Could it be the way I build the C library, maybe there was a flag in gcc I was using that does not have an equivalent in llvm (I can find and post the old build command I was using if it is relevant)? Is the issue in Xcode and there is a way to tell it where to look for the sources?
Thanks!
Edit: To make it clear, I can add the C library either as the source or as a subproject in Xcode, however for reasons that are out of scope this is not helpful for this specific project. So, can it work like it used to with older Xcode versions? If not, it would still be interesting to know why not.
The recommended approach is to create a library project in Xcode, one for iOS (there is a template for it), then when you get that to build add that project to your app, make sure the lib is a dependency and gets linked. There are many tutorials on the web how to do this.
Then as iOS evolves and new architectures (armv7s) arrive you simply update both projects.
I was struggling with the same issue.
I tried resetting in library/application project all options related to symbol stripping and copy application project to same truecrypt drive as library project but it didn't help.
In my case it appeared it was an app project issue. Same library could be debugged in another app project with source code so that was a clue.
I had more than one version of the same library in app project and set only target membership to choose which should be used. Not sure if that could affect my app project somehow.
Nevertheless after deleting all libraries and copying them to app project again I was able to debug libraries with access to source code.

Resources