Adding OCHamcrest to an IOS Project - xcode

The documentation for the project says just add the framework and the linker flags and you are good to go. Hours and hours of wasted time later, I have figured out that that's not true. If you do that, the project does not see the header files. You have to put the framework somewhere were the compiler will find the headers. In my case, that worked when I dropped the framework into /Developer/Library/Frameworks and then told it to recurse in searching that framework directory (do not fiddle around with the headers search directories).
Then the problem I get is that the link fails with the message:
ld: framework not found OCHamcrestIOS
I noticed that the documentation for the project says that it was updated for Xcode 4. I pulled down the binary of the framework after checking out the code and wasting a ton of time unable to build the IOS version of the framework.
The documentation is here.
I also noticed in that documentation that the cocoa instructions tell you to put a copy files phase into the build. I tried that. Didn't change the outcome.
The last time I fell into a sink hole it was because the library was C++ code. Maybe that's still the problem.
Barring a rapid solution here, I am going to go back to using STAsserts, as sickening as that prospect is, this is far, far worse.
Update: reinstalled Xcode. Still doesn't work. There are cheap ways to make this work, like add the header files to the project. Did a blog post about this that brought out a person with the same experience.

I use a number of frameworks in my projects. Some from other people and some are mine. Looking at the documentation I would suggest that the copy phase stuff is not for iOS development. So I would not do that. I downloaded the latest zip from https://github.com/jonreid/OCHamcrest and it appears to contain a ready to go iOS static library. (Not on my mac so I cannot test to confirm).
Anyway, the way I include static libs is to
Select the project (XCode 4).
Select the target I want to add the library to.
Select the Build phases tab.
Expand Link binary with Libraries.
Click the [+] button to add a framework.
Click the [Add Other ...] button and navigate to the directory containing the <lib>.framework directory and select that.
Thats all. The targets search paths will be updated to include the framework directory and the framework will be listed on the left under the project. Expanding it will show the headers.
The problem you mention sound like a couple of things. Firstly the framework not found sounds like the framework has not been included in the target. When you select the framework in the project list on the left, you should be able to see it's Target Membership displayed on the right. Check it's on for the target you are compiling.
Secondly building frameworks is not a trivial task so don't attempt it unless you have the scripts to do it. I say this because building a iOS static framework means compiling for both simulator and devices, combining the compiled lib files into a universal one, and then storing it and the header in a specific directory strucuture.
The downloaded zip from OCHamcrest though, appears to have the correct OCHamcrestiOS.framework in it. So if you store that directory somewhere and link to it using the steps I've outlined above it should work just fine.

So the solution I adopted for now, after much thrashing around, was to include the framework in the project.
Create a group inside the Xcode project called Third Party.
Link it to a folder called thirdparty.
Go to the Add Files in Xcode and pick the framework.
Drag it over to the dependencies.
Run the tests, they pass!
This is maybe preferable anyway because referencing it in /System/Library/Frameworks would present some versioning issues, and this can be setup very quickly. Furthermore, we have a continuous integration server, and having to get in there and sync versions whenever something changes is not so great.
Thanks for checking it out, Derek.

Related

Swift: App Installation Failed Could Not Inspect The Application Package (When Using Frameworks with XCode 6)

I'm having difficulties running a compiled app on an iPhone 6 (iOS8). It works fine in the simulator.
I get this error message:
App installation failed
Could not inspect the application package
Originally there were error messages - such as the one here but I fixed this temporarily by moving the output into the correct location. However even though all of the libraries are being codesign'ed correctly and are now found I am unable to use the app on my device.
There seems to be no further error messages and therefore no way of debugging anything. How exactly do normal iOS developers debug problems which give no error messages?
I guess the underlying problem is that my project is getting quite complex, there are a lot of moving pieces: a few cocoapods, Alamofire, ReactiveCocoa, and Moya.
I have a few general questions:
Where can I find information that documents the use of frameworks in XCode 6?
What is the difference between "Build Phases -> Link Binary With Libraries", "Build Phases -> Copy Files", "General -> Embedded Binaries" and "General -> Linked Frameworks and Libraries"?
Everything is compiling completely fine for the simulator, including the cocoapods, but I note that there are libPod.a files and wonder whether they need to be compiled into the app?
Mostly I am hoping to find some way of finding out why the application package can't be inspected. Surely whatever software that inspects this must be able to be debugged?!!
Edit:
For the record, (1) there is no file called Resources in the root folder as I get nothing back when I do this "find . -name Resources" so it cannot be that issue, (2) I have run "Product -> Clean" and then tried to build again and this does not solve the problem either, (3) the Info.plist does contain a CFBundleName which is set to "${PRODUCT_NAME}" currently (which I believe is set elsewhere.)
I managed to fix this. I am not sure exactly what the solution was, but effectively what I did was to remove all of the cocoapods, detach all of the extra projects that were being used to compile frameworks, and then completely clean the build folder (by holding Alt while going to Product > Clean.)
I then added each of the frameworks back and made sure that each of them would compile.
I checked the build output and near the bottom of each I was able to find the location in which the frameworks were being built.
I then went back to the parent app, and was able to change the framework search paths to include the folders that the frameworks were being built in.
I may have changed a couple of other paths, too, though I cannot remember completely.
I think that basically the issue was a combination of (1) a very dirty build path, (2) leftover files and bad configuration causing issues, (3) frameworks being built in the wrong location.
check your "Copy Bundle Resources",delete info.plist if it contained.
It's work for me in Xcode 6.4

In Xcode, moving a framework into a group removes it from Link Binary With Libraries

In Xcode, when I add a framework directly in Build Phases->Link Binary With Libraries, the framework appears at the root level of the project. If I drag the framework into the Frameworks group, the link to the framework appears red in Link Binary With Libraries. I have to re-drag the framework back into Link Binary with Libraries for it to appear black again. Why is it doing this? Usually moving files around in group should not result in removing it.
Is there a way to make the framework appear in the Frameworks group when adding it?
It's just a visual issue and won't actually affect the link phase. If you leave the Build Phases section and return (directly, or later), the framework's name will be black as you'd expect it to be. There's no need to re-drag or re-add a framework. In Xcode 4, there's no way to have Xcode put the framework in the correct group automatically.

Making framework private with install_name_tool being ignored

I have written a simple application using the GPhoto2 Framework, and this works so long as the framework is in the location where it was originally compiled. I would like to move this inside the app bundle, though, so it does not need separate installation, so I need to make it work relative to this main executable.
Unfortunately the framework is not an Xcode project. It uses a script to build, so I cannot simply change the installation directory build setting, which is the solution that I have frequently seen while searching for an answer. Being quite new to Xcode and Mac programming it is also beyond my abilities to know how to convert the framework into an Xcode project.
The other advice I came across was to use install_name_tool to update the library ID and dependencies, replacing the absolute paths with ones of the form "#executable_path/../Frameworks/GPhoto2.framework". The framework is not a single binary, but contains a number of .dylib and .so libraries, but updating all of these has only been half successful.
I have set Xcode to copy the framework into the app bundle when it builds it. Then if I remove the framework from its originally compiled location the application fails to load, with the report generated by OS X saying the libgphoto2 library can no longer be found, as to be expected.
If I then use install_name_tool to update the references in all of the framework libraries inside the app bundle, and also in the app binary itself, then the application will load but fails to find any camera connected. Using otool I am able to verify that all references have correctly been changed.
But if I replace a copy of the framework to its original location it then works properly again, recognizing connected cameras, regardless of whether that framework uses relative or absolute locations. Clearly it is still looking at this location despite loading. I have even tried removing each of the individual library files from the framework in its original location in turn to see if the problem was just the result of a dependency in of these, but no matter which is missing the app will not work.
Incidentally, if I build the app using an updated version of the framework, it fails saying it cannot find the library "#executable_path/../Frameworks/GPhoto2.framework/prefix/lib/libgphoto2.2.dylib"
Am I doing something wrong or missing a step, or is what I am trying to do impossible for frameworks created outside Xcode?
In case someone comes across this future, the answer to my question was that I was doing nothing wrong. The problem was that the .so files were being loaded by libtool ltdl, at it requires absolute paths so these were being set at build time.
I patched the files gphoto2-abilities-list.c and gphoto2-port-info-list.c so that at runtime it would combine the relative library paths with the executable location. As a result I also needed to increase the FILENAME_MAX constant to allow it the mail application to run from, for example, the Desktop. But this, along with the use of install_name_tool allowed me to add GPhoto2 as a framework inside my application without needing any external dependencies.
The final problem of not being able to build my app in XCode with the framework after using install_name_tool remained, but for that I just used the original framework build, then after compilation I updated the references in the copied framework at the same time as I updated the ones in the main executable.

Best way to install a custom cocoa framework

I have a custom framework that, following the advice in Apple's Framework Programming Guide >> Installing your framework I install in /Library/Frameworks. I do this by adding a Run Script build phase with the following script:
cp -R build/Debug/MyFramework.framework /Library/Frameworks
In my projects I then link against /Library/Frameworks/MyFramework and import it in my classes like so:
#import <MyFramework/MyFramework.h>
This works very well, except that I always see the following message in my debugger console:
Loading program into debugger…
sharedlibrary apply-load-rules all
warning: Unable to read symbols for "/Users/elisevanlooij/Library/Frameworks/MyFramework.framework/Versions/A/MyFramework" (file not found).
warning: Unable to read symbols from "MyFramework" (not yet mapped into memory).
Program loaded.
Apparently, the compiler first looks in /Users/elisevanlooij/Library/Frameworks, can't find MyFramework, then looks in /Library/Frameworks, does find MyFramework and continues on its merry way. So far this has been more of an annoyance than a real problem, but when runnning unit tests, gdb stops on the (file not found) and refuses to continue. I have solved the problem by adding an extra line to the Run Script Phase
cp -R build/Debug/MyFramework.framework ~/Library/Frameworks
but it feels like sello-taping something that shouldn't be broken in the first place. How can I fix this?
In the past months, I've learned a lot more about frameworks, so I'm rewriting this answer. Please note that I'm talking about installing a framework as part of the development workflow.
The preferred location for installing a public framework (i.e. a framework that will be used by more than one of your apps or bundles) is /Library/Frameworks[link text] because "frameworks in this location are discovered automatically by the compiler at compile time and the dynamic linker at runtime."[Framework Programming Guide]. The most elegant way to do this is in the Deployment section of the Build settings.
As you work on your framework, there are times when you do want to update the framework when you do a build, and times when you don't. For that reason, I change the Deployment settings only in the Release Configuration. So:
Double-click on the framework target to bring up the Target info window and switch to the Build tab.
Select Release in the Configuration selectbox.
Scroll down to the Deployment section and enter the following values:
Deployment Location = YES (click the checkbox)
Installation Build Products Location = /
Installation Directory = /Library/Frameworks
The Installation Build Products Location serves as the root of the installation. Its default value is some /tmp directory: if you don't change it to the system root, you'll never see your installed framework since it's hiding in the /tmp.
Now you can work on your framework as you like in the Debug configuration without upsetting your other projects and when you are ready to publish all you need to do is switch to Release and do a Build.
Xcode 4 Warning
Since switching to Xcode 4, I've experienced a number of problems with my custom framework. Mostly, they are linking warnings in GDB that do not really interfere with the usefulness of the framework, except when running the built-in unit-test. I have submitted a technical support ticket to Apple a week ago, and they are still looking into it. When I get a working solution I will update this answer since the question has proven quite popular (1 kViews and counting).
There's not much reason to put a framework into Library/Frameworks, and it's a lot of work: You'd need to either do it for the user in an Installer package, which is a tremendous hassle to create and maintain, or have installation code in your app (which could only install to ~/L/F, unless you expend the time and effort necessary to make your app capable of installing to /L/F with root powers).
Much more common is what Apple calls a “private framework”. You'll bundle this into your application bundle.
Even frameworks intended for general use by any applications (e.g., Sparkle, Growl) are, in practice, built to be used as private frameworks, simply because the “right” way of installing a single copy of the framework to Library/Frameworks is such a hassle.
The conventional way to do this is to have your framework project and its clients share a common build directory. Xcode will search for framework headers and link against framework binaries in the build folder first, before any other location. So an app project that compiles and links against the header will pick up the most-recently-built one, rather than whatever's installed.
You can then remove the cp -r and instead use the Install Location build setting to place your build product in the final location, using xcodebuild install DSTROOT=/ at the command line. But you'll only need to do this when you're finished, not every time you rebuild the framework.
Naturally, when you distribute your framework it should be installed in /Library/Frameworks; however it seems odd to me that you're doing that with the test/debug versions of your framework.
My first instinct would be to install test versions under ~/Library, as it just makes setting up your test and debug environment that much simpler. If possible, I would expect the debug/test framework to be located in the build tree of the version I'm testing, in which case it's installed as a Private Framework for testing purposes. That would make your life much simpler when it comes time to deal with multiple versions of your framework.
Ultimately, it doesn't matter where the framework is located as long as your application or test suite loads the correct version. Choose the location that makes testing/debugging/development easiest.

Adding a framework in Xcode

Im trying to add a third party framework in Xcode but I'm getting an error that it can't be found
error: MKAbeFook/MKAbeFook.h: No Such File or Directory
I've added it in the Linked Frameworks group and added it to the Target for this project. I've also added it to a new Copy Files build phase for that target.
Basically I've followed the instructions here: http://pointlesscrap.net/mkabefook/desktop/gettingstarted
Any ideas where I'm going wrong?
Best way to diagnose this is to post the compiler invocation line, not just the error (you can just drag and drop the line from the Build Results window that says "Compiling foo.m"). My expectation is that you don't have a Frameworks Search Path set up for the location of the framework. Xcode usually adds that manually when you add the framework, but if you put it in certain kinds of places, or added it in certain ways, you need to manually point your target's Framework Search Paths at its directory.
Perhaps the author mistook MKFaceBook for MKAbeFook?
EDIT: Never mind, it looks like that is actully the name of the framework.

Resources