How to integrate MuPDF in iOS project - ios

How can I integrate the mupdf library into an existing iOS project? I can run the provided source on my device and simulator, but I can't seem to manage to add it to my project correctly. I tried linking and importing the compiled static libraries but it only works in the simulator, even if I use lipo to build a fat library with all the architectures (armv7 armv7s arm64 i386). In this case the error is
file was built for archive which is not the architecture being linked (armv7s)
Ideally i would like to have it added as a submodule for ease of upgrading, I tried that too, but i can't get xcode to recognize where the built libraries are.

I was able to generate and integrate the MuPDF library for all architectures.
I wrote a small step-by-step tutorial on this post.
I hope it will help you !
Cheers

The easiest way is probably to use the MuPDF CocoaPod. There is an example application based on that pod.

Related

Do we need to create iOS Universal Frameworks for CocoaPods and Carthage?

Is my understanding correct, that we need to manually create Universal Frameworks/Libraries only if we distribute our libs by providing binaries (let's say directly download .framework)? So if we distribute using CocoaPods or Carthage, these tools will create Universal Frameworks/Libraries from our source code by themselves, right?
As I understand, CocoaPods & Carthage allow to hide source code by distributing only binaries.
Does that mean that in this case we need to create Universal Frameworks/Libraries by ourselves before using these services?
What's the best way to create Universal Frameworks/Libraries in 2020, XCFramework?
Thanks.
If you distribute your source code with CocoaPods or Carthage, these systems will make your source code compiling either into .framework or into static library on the consumer side while the consumer’s project builds. Consumers will have access to your source code.
Yes.
If your framework is intended to be used in Mac Catalyst apps - then XCFramework is the only choice. Otherwise, you can still ship fat framework - old, but gold.
UPDATE:
With AppleSilicon, XCFramework becomes the only format in which you should ship your prebuilt framework, because even iOS simulator now should support both x86_64 and arm64 architectures.

How to build dynamic Framework for iOS with no Embedded Binaries?

I try to generate framework named AfTestFramework for ios. I created through Xcode Cocoa Touch Framework with some basic code, ran it and got:
So far so good.
I created new Test Application and drag # dropped AfTestFramework.framework into the project, like crashlytics does (see below)
After building project and running I got Library not loaded ... Reason: image not found:
dyld: Library not loaded:
#rpath/AfTestFramework.framework/AfTestFramework Referenced from:
/var/containers/Bundle/Application/9B12D0AD-94AA-4119-A5DE-6BCAA806FA9F/TestAvoidEmbedded1.app/TestAvoidEmbedded1 Reason: image not found
I know the solution is to attach this framework to Embedded Binaries but I look for the way to avoid this approach.
Further, It demands to create 2 Frameworks: for Simulator and for Release otherwise I cannot release application with my framework, that looks a bit messy and weird.
I found that following frameworks work without Embedded Binaries:
crashlytics
firebase
facebook
Chartboost
ans so on.
So far I didn't find any description, I know also that its something new.
I started to play with xcodebuild like:
xcodebuild -sdk "iphoneos10.1" "ARCHS=arm64 armv7 armv7s" "VALID_ARCHS=arm64 armv7 armv7s" "ONLY_ACTIVE_ARCH=NO" -target AfTestFramework -configuration "Release" clean build
but no success.
Can somebody spread the light on this problem?
If you add a dynamic Framework to your iOS project, you must add it to the Embedded Binaries. In opposite to static libraries are dynamic libraries loaded at runtime. Thus the dynamic linker must access them on the device.
The only possible way to add the code inside of the framework without embedding the framework is to bind it statically to your app. For that you should create a static library from the framework. (Probably, libtool(1) may help you with that.) But anyway you may run into other problems, if the framework needs its bundle structure for loading resources etc.
I'm not quite sure what you are trying to achieve but it sounds like you are trying to create a framework which has a dependency on another framework.
So when used, it would be something like app -> your-framework -> some-other-framework.
I would strongly recommend looking at carthage as a solution to our problem. Carthage is an OS X native dependency manager that is designed to manage dependencies for you.
Firstly you need to check that the framework your framework uses is Carthage friendly. For now I'll assume so.
In your frameworks project you would add a Cartfile where you declare your dependency on the other framework, then use Carthage to download and build the other framework. You then add the built framework to your project as you would with any Apple supplied framework. You DO NOT need to embed the framework and generally speaking it's not recommended to do so. Carthage will handle this issue.
In the app project you would then also add a Cartfile, but you only need to specify your project in it. When Carthage builds the framework, it will automatically locate the other framework, download and build it as well. Then in the apps build phases you simple specify linking agains both frameworks and add a carthage-copy script phase to include them in the Frameworks directory of the finished app.
With regard to building for simulator and release. You don't need to build multiple targets. For a start, using Carthage means that the frameworks are only built when you need them, so this removes any requirement for you to supply binaries.
When telling Carthage to build the dependencies, by default it builds Release binaries. Building Debug frameworks for testing is just a matter of add --configuration Debug to Carthage's command line arguments.
Finally - to be fair, there are also two other package managers out there: Ruby based CocoaPods which is an older manager and for Swift, the Swift Package Manager. Personally I prefer Carthage for reasons I explain in a blog post here.
this is old but if its useful for future reference:
you can do
$lipo -create <path to simulator framework> <path to device framework> -output <path to the output framework>

Symbols not found for architecture when building Cocoa Framework used in Static Library subproject

I built a pretty simple Cocoa Framework in Xcode for use on an iOS device (not simulator). I dropped this framework into another project that builds a static library. When I build this static library it succeeds without error. No problems yet.
NOW:
I have an actual iOS app project that includes the static library project as a subproject.
When I try building this app I get 'no symbols found for architecture' errors regarding the two classes I am trying to use that are defined in my cocoa framework:
I'm not only building the framework for the active architecture:
I've verified that it is indeed built for both armv7 and arm64 in Terminal:
Kevins-MBP-2:ASI.framework kevin$ lipo -info ASI
Architectures in the fat file: ASI are: armv7 arm64
The only way to get this building successfully is if I also drop my cocoa framework into the iOS app project, in addition to it already existing in my static library project. I feel like I shouldn't have to have the framework in both projects. Only the static library actually uses the framework. The iOS app project does not need to know about the framework.
Static libraries don't contain dependent libraries, so whenever you link against a static library you need to supply the dependent libraries they use to the linker.
Basically you do need to also link the executable against this Cocoa Framework as you have stated in the last sentence of your question.

handling dependencies for iOS Framework project

I've created iOS Framework project using this method: https://github.com/jverkoey/iOS-Framework
Works pretty neat but I'm a little confused on how to include libraries/frameworks that are needed by my framework to work and, in particular, how to do it so that in case 3rd party client app that uses my framework can include these libs as well without conflicts.
Let's say my framework code needs these two things:
FacebookSDK.framework
libFlurry.a
The first one is an iOS Framework. When I add it to "Link Binary With Libraries" phase in my Framework and try compile the client project that uses my framework the linker complains about missing symbols - I need to add FacebookSDK to the client project which is great: there is no possibility of conflicts if client apps wants to use Facebook.
However when I do the same with Flurry static library I get duplicate symbols error when compiling client project. Which confuses me a bit, because isn't FacebookSDK.framework just a packaged static library?
ukaszs-iMac:FacebookSDK.framework lukasz$ file Versions/A/FacebookSDK
Versions/A/FacebookSDK: Mach-O universal binary with 3 architectures
Versions/A/FacebookSDK (for architecture i386): current ar archive random library
Versions/A/FacebookSDK (for architecture armv7): current ar archive random library
Versions/A/FacebookSDK (for architecture cputype (12) cpusubtype (11)): current ar archive random library
So my questions are:
why a library embedded in framework (like Facebook) is not linked to my Framework project product, whereas library included as .a file is?
how to include .a file in my framework so that it does not produce duplicate symbols error when client app using my framework also needs this particular static library?
For the use case you are describing, you should be linking to these external libraries from your application, NOT your own framework. It can be one or the other, but it can't be both.
If you decide that these dependancies belong as the responsibility of the application, you would remove them from "Link Binary With Libraries" and any other explicit linking configuration, and just project your framework project with the path to these frameworks and libraries so it can find the symbols (but not link against them) at compile time (i.e. the path to the libraries should be included LIBRARY_SEARCH_PATHS).
Use cocoapods , it's easy (http://cocoapods.org/)
Your application developers will have to include the podfile and download the dependencies.
While developing your SDK use a reference application/demo app on top of the SDK to simulate this.
You shouldn't link anything when building your framework but just create a *.a binary with your framework's objects.
Also you should not include code from other libraries in your framework as client applications may be adding the same libraries directly or requiring different versions of them, thus creating conflicts.
Off course you can reference *.h header files from other libraries in your framework in order to compile your objects.
As a result the installation steps for your framework should detail other required frameworks/libraries needed, their supported versions, how to add resource files (if any), etc. Just some of the many reasons why you may want to consider Creating a CocoaPods' podspec instead.
You should use CocoaPods. Your dependency on Facebook can be done by linking against the CocoaPod.
If you want to include that particular version of Facebook in your pod, you can put it in your repo and use the vendored_frameworks property to refer to it.
Similarly if you wanted to vendor libFlurry.a, you could do so using s.vendored_libraries.
For system libraries, you don't need to vendor them, e.g. libZ.a.
I strongly recommend creating your CocoaPod using pod lib create YourPodName. They've recently changed the mechanism for how this works and it's really nice.
You can create an Example project that shows how to use your code in context of an app.
Then one of the other neat things I just learned about, someone can do pod try YourPodName and it will automatically download, integrate and run the Xcode project.
CocoaPods is worth the trouble.
I am building my framework project using CocoaPods.
The framework uses some 3rd libs from CocoaPods.
Podfile specifies to install dependency on target of the framework.
When I build the framework, it includes all libs in the binary.
If I add use_frameworks! in Podfile, when the framework is built, it will not include 3rd party libs.
Use CocoaPods dependancy manager. Here's a good guide,
7 miniute video tutorial
Mostly if you install third party frameworks you can install with cocoapods (which is really nice, I would definitely do that) or they offer you to download the framework and include it in your Project.
If you decide to download the library and include it there is normally a list of frameworks you need in the "Getting started" guide.
Means: Offer them to install using cocoapods and to download your library but do not include anything else, give them a list what they need.

zxing in xcode 4.5 and ios 6

As many of you noticed; zxing does not work in latest xcode (4.5/ios 6)
Here is use case:
checkout latest version from trunk (as some fixes were already added)
create single view application in xcode 4.5 with ios 6.0
use README to add dependencies, paths etc (just follow step by step)
add zxingcontroller call to class (renamed to mm)
Compilation fails both for simulator and device
It shows 31 error like this one:
Undefined symbols for architecture i386:
"std::string::c_str() const", referenced from
all 31 errors are similar, difference is in symbols name
May be somebody knows how to solve it with this use case?
p.s. if you have app from previous Xcode, it works. Problem is only if you create new app in Xcode 4.5
The issue you have encountered seems to be C++ standard library related.
Actually, whenever you see linker failures in relationship with standard library objects (e.g. std::string), you should check the project settings on all linked libraries and the app-project itself. They usually need to match!
The original ScanTest (which builds ZXingWidget as a subproject) uses the following settings and those need to match your App build-settings if you use the library as is.
For making sure, I created a brand-new project using Xcode 4.5. That project uses ZXingWidget as a prebuilt library but not as a subproject - I dont like subprojects for stuff that is not my own - though this specialty wont influence the results.
The important setting is C++ Standard Library - make sure that is set towards Compiler Default
Little clarification
Actually, you do not need to use C++ Standard Library, you may as well use LLVM C++ standard library with C++11 support. But you will have to use that exact same library in all projects, sub-projects and libraries that link with your project. So if you insist on using the more recent version of that library (C++11 support), then you will have to build the ZXing library with those settings as well.
Last but not least, make sure your Architectures and Valid Architecture settings are matching over all projects and sub projects (fixing the common armv7s linker issue).
First, make sure your Architectures setting is set towards armv7 armv7s within all projects. Then also edit the project settings of all projects towards Valid Architecture armv7s armv7.
You might also want to switch the "Other Warning Flag" -Werror off. Seems to be necessary in Xcode versions > 4.5 (LLVM compiler > 4.1).
It works for me, have you enabled -lstdc++ in your list of Other Linker Flags in the Build Settings tab of the project target? It sounds like it is not recognizing the c++ symbols needed for zXing to build. If this is the case, the above advice should help.

Resources