I am currently building an iOS app written in Objective-C and Swift containing the openssl and openldap frameworks, which builds and runs without any issues.
However, when I try to archive the app for release, the below errors occur:
Here is some additional information:
The Xcode version is 7.3.1 (7D1014)
The project is an Xcworkspace (contains a podfile, but the frameworks are not integrated through Cocoapods)
UPDATE:
After further testing, another makefile error occurred (similar issue in any case)
This image illustrates all the frameworks and libraries used and the errors that occur.
Here is the build log:
I appreciate any assistance and would be happy to provide any additional information.
Note: I am still looking for answers in order to solve this issue
I'd actually recommend something completely different. Making opens and openldap as standalone universal static libraries that you just link to. Presumably, this is what Makefile-openssl and Makefile-openldap are doing (making the universal lib)
"Why would I do such craziness?" you may be thinking. The code for openssl and openldap are not changing ... unless you have a unique case where you have forked the code and have some modification (which would probably be a bad thing). Thus there is no need to continually re-build it.
"Ahh but what about if I want to update the version?" you may be thinking. Then get the latest source and build it once. Done.
The benefits are that you are not wasting time building those libraries. While you could say it is not big deal right now, as projects get bigger, you're just wasting time re-building libraries that are not in active development. Additionally, you don't have to worry about any weird build issue like this.
For some projects I've been working on, I've convinced them to even make a pre-built library of all the cocoa pods libs we need in the project. Which has had the added benefit of keeping our main project a bit cleaner of the pods nastiness (I know some people will disagree) in your project.
Related
I am having an issue with SqlCipher and Akavache on iOS. When I add the Akavache library to my project with an existing implementation of SqlCipher I get a number of duplicate sqlite errors during linking.
What is the current behavior?
When I build iOS with Link SDK assemblies I receive the following
Sqlite Linking Errors
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem
Install/Implement SqlCipher
Install Akavache
Build Xamarin.iOS project
What is the expected behavior?
That Akavache Sqlite and SqlCipher Sqlite just work together.
Which versions of Akavache, and which platform / OS are affected by this issue? Did this work in previous versions of Akavache?
Akavache 5.0.0
iOS 10.3
I wouldn't know. SqlCipher was implemented months ago, and we are just now adding Akavache to the project.
Other information (e.g. stacktraces, related issues, suggestions how to fix)
Linking is set to SDK Asemblies only
This is a Xamarin Forms project and the Android Linking does not produce the same result.
I am actually able to execute the code on Android and have proven that the technologies play nice (from what I can tell)
I contacted SqlCipher and the recommended approach is to fork Akavache and swamp the following line of code with another
implementation.
https://github.com/akavache/Akavache/blob/develop/src/Akavache.Sqlite3/SQLite.cs#L224
Before I go down the road of maintaining a fork, I was wondering if there is better way?
What you're effectively doing here is adding Akavache, which contains a custom SQLite build, to an app which already contains a custom SQLite build. And because of the way iOS linking is done, that's a problem.
I doubt you actually need a "fork" of Akavache. What you really need, IMO, is an implementation of Batteries_V2.Init() which talks to the SQLCipher instance you already have in your app.
This is doable, as SQLitePCL.raw already contains multiple implementations of this "bundle" concept, and uses bait and switch to change from one to another.
Your question is equivalent to one I get from time to time: "How do I use a custom SQLite build with SQLitePCL.raw?" The only difference in your situation is that you already have such a custom build as part of your app. Anyway, it's similar, and unfortunately, SQLitePCL.raw doesn't make this as easy as it should.
Anyway, explaining how to bridge the gap between Akavache and your existing SQLCipher build is probably beyond the scope of this SO answer, but I might be able to help you head in the right direction. You can post an issue on https://github.com/ericsink/SQLitePCL.raw and I will see it.
I have minimal interest in adding Cipher support to Akavache. If you can find a non-terrible way to do it then release it on GitHub for others. Akavache already has an encryption API via http://kent-boogaart.com/blog/password-protected-encryption-provider-for-akavache
It's a little concerning that the authors of Sqlite Cipher are recommending removing that line as it means you'll also run into and experience problems with the greater Sqlite ecosystem, including azure mobile services.
I am developing an app for IOS,and I have to use some framework.
as you know Cocoa pods and Carthage are dependancy manager for iOS and mac OS
my question is "why we have to use dependancy manager?, instead of using dependancy manager just clone that project[was written by other programmer and can be used as framework] and drag and drop to your project ??"
Thanks for your answers
Few things that you need to think about is:
Updating your dependencies when new versions came out.
Updating dependencies for multiple platforms.
Interdependent frameworks and different framework versions for dependant frameworks.
Basically, time that you will spend on maintaining dependancies for your project will grow as your project grows. Dependancy managers allow you to avoid all this unnecessary and boring work.
There are a lot of other reasons to use DM instead of just importing frameworks. More about you can find here. And here.
At some point you might want to use 3rd party code to get extra features or something, you can copy the source code but how you will update it in the future? keep coping it again!!
Also some of your 3rd party code might depend on other 3rd part code, and if you copied it twice, you will get duplicate symbols.
Dependency managers handle all this for you.
My advice is to use Carthage or submodules, but do not use CocoPods, anything that touches the project file is not a good practice with Apple.
Why Libraries are Your Friend
While you aren’t strictly required to use third-party libraries or
frameworks, they can definitely save you a lot of time and let you
focus on polishing your app instead of typing out countless lines of
code that you simply don’t need to write.
You can use third-party frameworks and libraries without a dependency
manager too, and you can get hands-on tutorials about them right here
on this site. For example, there’s our Alamofire tutorial, and our
SwiftyJSON tutorial.
Without a dependency manager, you simply add each library’s code to
your project manually. However, this approach has several
disadvantages:
Updating a library to a new version can be difficult, especially if several libraries must be updated together because one depends on
another.
Including a library in your project makes it tempting to make local changes to the code, making it harder to update to a newer version
later.
Determining the current versions of libraries used in your app can be hard to do, especially if you don’t proactively keep track of them.
Finding new libraries can be difficult without a central location to see all the available libraries.
CocoaPods helps you overcome all of these issues and more. It fetches library code, resolves dependencies between libraries, helps
you search for and discover new libraries, and even sets up the right
environment to build your project with minimum hassle.
Courtesy
https://www.raywenderlich.com/97014/use-cocoapods-with-swift
Every time I meteor build, I have to open XCode and do the following:
remove and add an item from "Link Binary With Libraries" (Facebook SDK)
add a URL Type (custom URL scheme for my app)
add a "Required device capabilities" to "Custom iOS Target Properties"
How can I edit my Meteor project to have these steps done automatically, and to auto add things to AndroidManifest.xml?
In some way use mobile-config.js or cordova-build-override?
I'm happy to see another guy who is trying to build a hybrid application using Meteor / extending a Meteor Cordova iOS app, since I'm facing the very same issues. So I'm very happy to share my experiences and approaches with you. :-)
So far, I ended up with the following approach:
I created a base template for my iOS app using meteor build (not meteor run ios-device, since I did not know if Meteor does some optimizations for production code).
Then, I copied the whole Xcode project under /platforms/ios to another loaction and used this new project as my "master" project from then on. This project is being enriched with native code, e.g. it also includes the Cocoa Pods I'm needing.
Of course, I also did not want to copy files each and every time I trigger a new Meteor build. At least, I would like to have the Staging/www folder updated, as this is happening quite frequently.
So my first (rather naive) approach was
delete the Staging/www folder in the master project
replace it with a relative link (using Xcode's linking functionality) to the Staging/www folder inside the .meteor/local/.../ios/ project
This approach did not work, since the shell script used in the Meteor Xcode project can't handle these links.
My second approach is to create a symlink on the filesystem level instead. This works as it should, and I'm able to build the project in Xcode as it should.
I could have followed the same approach for the Cordova plugins folder, but I've decided to replace the plugins manually in order to get a better control over them, even it means a bit more effort then.
Having the symlink in place also means that Xcode's version management (and also SVN which I am using for everything) will ignore everything below Staging/www, which is good in my opinion, because I'm already versioning the webapp code in the Meteor project itself.
BTW: I've started a discussion thread on hybrid mobile app on the Meteor forums as well, but so far it did not get too much attraction:
https://forums.meteor.com/t/building-a-hybrid-meteor-cordova-app-share-experiences/8212
Maybe we could follow up on Meteor-specific things there, to have the Meteor community participate in the discussion?
EDIT: I would also like to share an approach that failed completely, at least for me, maybe I was too dumb... Before I used Meteor's Xcode template as the starting point, I also tried it "the other way round", i.e. I started with my already existing Xcode app project and tried to include Meteor's / Cordova's part by hand. Using this approach, I never managed to set everything up correctly. I had lots of troubles and also had to tweak a lot of the compiler / linker flags to even get the code compiling. This grew me a lot of gray hairs. But even after I managed to get everything to compile, Meteor hang during startup - and I never figured out why.
One remaining problem I'm still facing is that Meteor's hot code push functionality seems to have some severe issues on iOS, that are also documented as GitHub issues. It can happen that the iOS app gets completely broken and needs to be reinstalled. I tried the mdg:reload-on-resume package, but this did not work as it should and made things even worse. As far as I can tell from the GitHub discussions, one should better disable hot code push until the Meteor team has addressed these issues. Breaking the app completely due to code pushes is not what my users would expect.
Unfortunately plist values (and assumably AndroidManifest.xml as well) can only be changed by a plugin:
Add entry to iOS .plist file via Cordova config.xml
Using iOS 8, Xcode 6.
Let's say I have 2 dynamic frameworks, frameworkA and frameworkB and they are both dependent on libC. In addition, I have an app that uses both frameworkA and frameworkB. My original thought was to make frameworkA and frameworkB umbrella frameworks and libC a subframework. However, Apple advises against umbrella framework and this post describes why umbrella framework is a bad idea due to potential linker conflict issue.
My second option is to use cocoapods (still new to this so a bit fuzzy on details) to use libC as a pod which then gets compiled into frameworkA and frameworkB. However, it occurred to me that both frameworks still has its own copy of the libC. Since the app uses both frameworks, will this result in a linker conflict issue as well? Is there a better way to solve this problem?
UPDATE
#Rob The projects I work on do require complex dependency management but I kept the problem domain simple in the question to try to better understand how and if using cocoapods can help solve the linker conflict issue with umbrella frameworks. I work with a team of developers who write libraries and can depend on each other's base libraries that provide versioned common APIs. We are required to package and deliver as few libraries as possible to a different organization that is building an app with our libraries and one of their key requirement is that we deliver a dynamic framework.
The best way to solve most problems is to put all the code in a project and compile it. When you have specialized problems that make that problematic, then you should look at other solutions, such as static libraries, and finally frameworks.
Static libraries can make sense if you have a code base that has pieces which require different build requirements. If all the pieces have the same build settings, then just "add files" them into your project from a "common" directory and build your project. Static libraries can be attractive if your build times are very significant and some pieces never change and you want to be able to "clean" without rebuilding those parts. But wait until you start having that problem before you go making complicated multi-package projects.
If you sell closed-source libraries, then frameworks are very attractive. You should strongly avoid adding third-party dependencies for the reasons you note. If you must, the best way is to help your customers package all the pieces as frameworks and have them link everything at the end. But that adds a lot of annoyance; so make sure you really need that third-party piece.
You might also consider frameworks if you have a very large piece of reusable code that has its own lifecycle separate from the main products. But again, keep it simple. Avoid third party stuff inside of it, and if you must have third party stuff, then have the consumers link it at the end.
(This isn't a new solution, BTW. When you use curl, if you want SSL, you need to also download and build OpenSSL and link them together yourself. Curl doesn't come with OpenSSL built in.)
But in the vast majority of cases, this is all overkill. Don't jump to frameworks. Don't jump to libraries. Just put all the code in the project and compile it. 90% of your problems will evaporate. iOS projects in particular just aren't that big usually. What problem is a framework solving?
If you have a lot of code that your organization uses repeatedly in lots of products, then I have heard many teams have good luck using internal CocoaPods to manage that. But that's just to simplify checking the code out. It still all goes into a project and you compile it together into one binary; no frameworks needed. Dynamic frameworks are a nice feature in for certain kinds of problems that were really painful before. But, for most situations, they're just complexity looking for a problem.
(If you have one of those specialized problems, edit your question and I'm happy to discuss further how you might approach it.)
EDIT: (You fall into that "specialized problem," so let's talk about it. I did, too, for many years inside of a large multi-team Mac and iOS dev environment. And we tried just about every different solution, including Frameworks. They're only new on iOS.)
Within an org like you describe, I would strongly recommend packaging each dependency as its own framework (AFNetworking, JSONKit, etc) and each of your pieces as a framework, and then have the app devs link all of them together at the end. In this way, it is identical to other dynamic libraries (libcurl, openssl, etc.) which require the app dev to link everything together.
In no case should dynamic frameworks include other frameworks that could otherwise be required (i.e. frameworks should never package "third party" stuff). That will explode. You cannot make that not explode. You'll either have bloat, build conflicts, or runtime conflicts. It's like merge conflicts. There's a point at which a developer has to make a choice. App-level linking is making that choice.
Making components over-dependent on other components is the source of decades of trouble, from Windows DLL Hell to iOS apps with competing crash handlers. All the best component systems look like Legos, where the end user assembles small pieces that have minimal dependencies. As much as possible, make your internal frameworks rely on nothing but Cocoa. This has some tangible design influences:
Avoid directly requiring logging or analytic engines. Provide a delegate interface that can be adapted to the engines of the caller.
Avoid trivial categories (methods that save just a few lines of code). Just write the code directly.
Avoid adding framework dependencies that aren't buying you a lot. Don't add AFNetworking just to save a few lines of code over NSURLConnection. Of course if you're heavily relying on the features of another framework, that's different. But as a framework developer your threshold should be quite high before requiring another framework.
Strongly avoid being clever in the build or version control. I've seen too many cases where people want to make everything "automatic" for the app-level developer, and so make the system really complicated. Just say "you need to link this and import this and put this in your app delegate startup." Don't create complicated build and version control systems to save 2 minutes on the first build or two lines of initialization logic. These things blow up and waste hours to work around. Don't get clever with +load magic. Just make it clear and consistent.
And of course, good luck. Supporting other devs is always an interesting challenge.
I have a large (thousands of files) product that I am porting to iOS. I have an existing build structure that constructs about 50 static libraries that can then be used by a platform-specific [G]UI. Some of the libraries are 3rd-party tools like zip, ICU, and Xerces. The portable build process is managed by GNU autotools, and I have created some shell scripting to build the code for i386 (simulator), armv6 and armv7. All of this is being done on Apple's Lion with the 5.1 iOS SDK and Xcode4.
The problem I have is that it's a pain to bring these libraries into an Xcode4 project. Drag&Dropping the libraries is tedious. I've been resisting creating a "project" for the libraries in Xcode because I already have a cross-platform build system that works. I'd like to have a "simple" way to type in the list of libraries and their location(s); my searches here show solutions for Xcode3, but they don't seem to apply to Xcode4.
I am able to build an iOS app that uses these libraries, but the thrust of my question is really: How do I avoid all the drag&dropping and retain my portable build structure so that others using my libraries aren't tearing their hair out? If this were an iOS-only app, I'd just use Xcode4 for everything, of course. But since it is multi-platform and "portable" I really want to keep the process simple, where "simple" applies to both the maintenance of the packaging and to the user/developer who is working with my libraries.
An alternate question might be: is there a safe way for me to generate Xcode4 meta-files so that the end result of my autotools-driven-build just looks like a native Xcode4 project?
Two thoughts:
1) It use to be the case that Xcode supported AppleScript pretty well - I use to do such tasks with AppleScripts. Early versions of Xcode 4 were quite lacking in this support though. Not sure if you can do it with 4.4 - you might ask on the AppleScript implementors list on Apple's listserv group.
2) If you put all the libraries (or perhaps links) into one folder, then in Xcode click on the Target, BuildPhase, Link Binary with Libraries, tap the + key, navigate to your folder, then select all libraries and tap OK, you're done. [Well, almost, then in the GUI pane on left you need to select them all again and move them into the Frameworks folder, which due to this annoying bug, I keep at the top of my projects.]