I have created a Cocoa Touch Static Library using Xcode 4 and I want to use it in a MonoTouch project. How do I proceed?
Here is the content of my Static Library :
MyClass.h
MyClass.m
I built using "Build For Archiving" after following THIS BLOG POST and I took the libMyLib.a it generated and added it to a new MonoTouch Binding Project.
Then I replaced the content of libMyLib.linkwith.cs, because THIS BLOG POST said so.
[assembly: LinkWith ("libMyLib.a", LinkTarget.ArmV6 | LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, Frameworks="CoreGraphics QuartzCore UIKit")]
Then I added this to ApiDefinition.cs
I left StructsAndEnums.cs empty.
Then I built with Release and took the dll from the bin folder and added it to the root of a MonoTouch iPad project, and added it to the references.
Then, after following the instructions in THIS ARTICLE, I set the mtouch arguments to this
-gcc_flags "-L${ProjectDir} -lMyLib -force_load -ObjC"
Then I tried to run the project and I got this error in the Build Output
error MT5201: Native linking failed. Please review user flags provided to gcc: "-L/Users/herpderp/Projects/TestProject/TestProject" "-lMyLib" -force_load "/Users/herpderp/Projects/TestProject/TestProject/libMyLib.a" "-L/Users/herpderp/Projects/TestProject/TestProject" "-lMyLib" "-force_load" "-ObjC"
This directory contains a full sample showing various ways of integrating Objective-C libraries with MonoTouch:
https://github.com/xamarin/monotouch-samples/tree/master/BindingSample
The error message for MT5201 tells you there was an error while doing the native link step. That's 100% sure. The second part ask to to review your gcc_flags, which is the most common reason, for the failure. However it's not 100% sure this is the issue. When you seek help you should always paste the lines above any error (as they might be useful).
The error is likely about the duplication of the options given to the native linker. This occurs because you did supplied them twice (i.e. in your binding project and in your main project).
From the Binding Objective-C Types article you linked:
Or you can take advantage of the assembly-level LinkWithAttribute, that you can embed in your contract files...
It means the additional mtouch arguments are not needed with you use LinkWith attribute. Since you're using this way (the best one :-) to bind your static library you can skip this step (from your main project).
By doing so you do yourself (and anyone using your library) a favor since they are less risky to get out-of-sync (e.g. library update or different build configuration).
Related
I know of familiar tutorials on this, but introduction of framework XCode 6 template has changed the game.
I already watched WWDC 2014 video about building modern frameworks but it talks more about building extensions, framework & app all inside single project. It does not specify if the framework I make with it is truly reusable across any project.
I am building framework the XCode 6 way (File->New Project->Framework and Library->Cocoa Touch Framework), but when I import it inside my test app project (separate from framework project) - I keep getting various errors.
Example: Include of non-modular header inside framework, and so on.
I know this is not what it says, and there are quite some missing steps in whatever I am doing. The older tricks may have worked for everyone, but I simply don't find which way to follow after XCode 6.
For example, there is some folder structure that a framework needs, but XCode 6 doesn't comply to it while building it. Is it right? If not, how can I change the way the XCode builds framework folder hierarchy?
Do I go back to old school or am I screwing some tiny thing in XCode 6 that I am unable to create a reusable framework?
I am not sure if you are trying to build a framework with Objective-C or Swift as your question doesn't state it. I've encountered errors you are mentioning with Swift so I'll give you my method to build Swift frameworks.
I found the process for Objective-C to be very straightforward and well documented, so I'll skip this.
As for Swift, there are a few things to consider. First, Swift static libraries are not supported, so you must exclusively use a framework (aka dynamic library) when linking an app to a library.
Here are the steps:
Create the Framework using New > Project under IOS > Framework & Library, select Cocoa Touch Framework
To avoid the "ld: warning: directory not found for option..." goto Library Search Paths in Build Settings for your target and delete the paths.
You can't mix Objective-C with Swift so don't even consider adding the Swift-Header bridge file in your code.
There are some cases in swift where you need to import code from unexposed Frameworks. I've successfully used the module-map inside the framework to deal with these case.
I also select CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES in the Build Settings to solve 'include of non-modular header inside framework module'. That seems to work
I make sure that the header file that gets generated is marked as Public (not Project). Click on the file and you'll see the selection in the inspector under 'Target Membership'
You may run into some bizarre error messages when building. Xcode has a tendency to report linker errors when your code can't compile correctly resulting in missing files the linker needs to output its binaries. Sometimes XCode won't show the errors in the files you are compiling and you need to go manually on the build output and go back to the files. Some other time, you'll get a problem where you need to delete the cache. Those issues I call XCode blues and deal with it constantly. I found this type of problems happens more often when building libraries. The rest should work as expected.
Base on this question
Why don't iOS framework dependencies need to be explicitly linked to a static library
I read the selected answer and still don't understand so I made an example project
Test Project on Github
In the test project, I remove all framework from Link Binary With Libraries and File navigation for both main project and the static library (including Foundation.framework and UIKit.framework too), basically, both project link to 0 frameworks.
Questions are
In static library, it's including MapKit/MapKit.h without referencing the Mapkit.framework to the project, why is its still working?
In main project, I remove UIKit.framework and Foundation.framework from the project, why is it still working?
Since it's working for now, will there be any issue later?
Thank you for your comment.
P.S. By working, I mean I can run on the simulator and I can archive the main project without any error.
Edit 25/07/2014
I tried with the real app that I'm working on, it's the same.
I highlight Foundation, UIKit, CoreData and 10 another frameworks in File Navigation, well, all of them.
Uncheck the target in Utilities Panel --> Target Membership
Build : Pass, Run : Pass
Every functionality of my app is still working as expected. I don't get this.
Check your project build settings. Underneath LLVM 5.1 — Language — Modules you should see the option 'Link Frameworks Automatically'. In your case it sounds like it's set to 'YES', the default.
In that case, instead of producing an error when you reference a class that the compiler doesn't know, it'll figure out which Framework contains that class and link it. In your code it'll be MKMapView or one of the other MapKit classes that triggers the linkage.
EDIT: from the relevant 'What's New?' document:
Auto Linking is enabled for frameworks imported by code modules. When
a source file includes a header from a framework that supports
modules, the compiler generates extra information in the object file
to automatically link in that framework. The result is that, in most
cases, you will not need to specify a separate list of the frameworks
to link with your target when you use a framework API that supports
modules.
Another way of looking at it is that the compiler is smart enough to mutate #import to #import when the framework has been built appropriately. All system frameworks have been.
To elaborate #Tommy's answer, a framework that supports modules satisfies the following 2 conditions:
Under Build Settings > Packaging
Define Modules is set to YES
Module Map File exists.
So, if you're certain that the framework you're using in your code modularizes like that, you can choose to not explicitly add it in the link phase as it will be automatically added as long as in the project file, under Apple Clang - Language - Modules, The option Link Frameworks Automatically is set to YES.
I have a sub project within Xcode which creates a static library referenced by the parent project. All has been well until the release of iOS 7.1 and Xcode 5.1, suddenly I'm getting the following warning.
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: -dynamic not specified the following flags are invalid: -ObjC
warning: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: file: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/usr/lib/libsqlite3.0.dylib is a dynamic library, not added to the static library
Does anybody know what I need to do to fix this warning?
I think the solutions lies in the basic concept of dynamic and static libraries. as far as libraries go, dynamic libraries (libsqlite3.0.dylib in your case) are system libraries and you do not need to add them to your static library! all you need to do is to add their reference in your final Target you want to use them in (your application).
so, in short: Try removing the reference to sqlite3.0.dylib from your static library (I'm guessing another project you are using inside your top level application) and add it to your application (not static library) and you're probably good to go. (solved my problem)
[Edit]:
please commit your project's git or do whatever you do to make a backup from your project, there is a chance that Xcode may break your project with no reason after removing these dynamic libraries and NO, deleting project's Derived data won't solve the problem.
I'm trying to build Assimp for iOS, it compiles fine, with no errors, however, when I try to use it in my project I get a lot of errors (154 to be exact) during linking. Judging after the method signatures, the errors are C++ related, however, I would like to use the C interface. I've tested with lipo and the library is compiled for my arch, it's actually a fat library. They are linker errors, should be easy to fix, alas, my lack of experience doesn't help. Here is a screenshot with the errors (first rows, as there are more than 100 in total).
How should I debug this? What went wrong?
EDIT: Thanks to #Zadr I managed to narrow it down to 8 errors:
_crc32 sounds very familiar, but still can't find the reason behind all this.
The library you're building was linked against one version of libstdc++, and you're trying to link against a different version.
In the project settings, there should be a "C++ standard library" field. Change that from the default option (clang's libc++, iirc) to the other option (gcc's).
In addition to what #zadr has already mentioned, you should also link libz.dylib for the last 8 errors to go away. I'm almost certain those functions are related with it and I know for sure Assimp uses libz.
First Tell Me if You have to Putted any framework as copy-paste ?? in most of cases this type of issue created.
Generally this Types of Error Occur when your class .m file is not store/putted under Compile Sources
In This case you need to add manually this .m file to Compile Sources
Following step Describe how to put .m file in Compile Sources manually
Select Project Form Project Manager
|
|
Targets
|
|
Build Phases
|
|
Compile Sources
|
|
Click on '+' button and add .m file in it
This is Step For how to put file manually in Compile Sources.
Sorry, my English is not very well.
I'm using cordova 1.6.1.
I created a new cordova-based project and I extended it to add a plugin.I build a static library with the plugin I created and try to run the projet including this library (the library can be found in the build settings of xcode), without the sources in the plugins folder
The following errors occur when I run my application :
[INFO] ClientChannel(1) initializing...
CDVPlugin class MNClientChannelPlugin (pluginName: MNClientChannelPlugin) does not exist.
ERROR: Plugin 'MNClientChannelPlugin' not found, or is not a CDVPlugin. Check your plugin mapping in Cordova.plist.
Some comments on these errors :
1) The first line is a log from The JavaScript code that I wrote, this indicates that the "initialize" function is launched. This function call a init function of a Plugin named MNClientChannelPlugin.
2) & 3) These logs come from the native iOS cordova sdk (Called from the getCommandInstance (2) and the execute (3) functions of CDVViewController.mm)
In the Codova.plist, I put MNClientChannelPlugin as a key and as a value. With this configuration, it works when I put MNClientChannelPlugin source (.mm & .h) in the Plugins folder but not when I created a static library with MNClientChannelPlugin.mm. (I included this library in my project and let the .h header in the Plugins folder).
Cordova seems to doesn't find the source in the library...
The Cordova plugins are in the Cordova.Framework and not in the
Plugins folder with .m and .h files so it seems possible to create
plugins, package them in a library and use them in a cordova-based
project but I it doesn't work for me...
I have looked at the archives and the commits but did not find any
solution. Does anyone know what could be the issue ?
Right, I've found a solution to this.
Here's the problem:
Your MNClientChannelPlugin is held in a static library
Your main project references the static library
The linker is clever enough to only link in classes that are actually used by your main project.
As far as the linker knows, MNClientChannelPlugin is NOT used by your project as it isn't referenced anywhere.
It's not referenced anywhere because the class is only loaded if your phonegap app happens to request a MNClientChannelPlugin instance.
Ergo the class is not linked into your final binary and you get the error above.
The solution is to force the linker to include the MNClientChannelPlugin object.
The easy was is to add -all_load to the 'other linker flags' for your main project. This will have the knock-on effect of linking every class in every static library in your project. It does work though.
The better was is to use -force_load with the name of your static library. Here's a post with help on this, though I haven't tried it myself:
xcode-project-target-settings-syntax-for-linker-flag-force-load-on-iphone
If you were using Pushwoosh (which I assume you were), the instructions clearly state that you should copy and paste this code:
<key>PushNotification</key>
<string>PushNotification</string>
to Plugins in “Cordova.plist. So if you have the above error which I once had it means that you did not copy and paste it to the Plugins. Moving the key and string values to the right location should annihilate the error.
Happy hacking!!!