Develop an ebook reader on iPhone/iPad using MuPDF library - ios

Can I develop an ebook reader on iphone/ipad using MuPDF library?
Do you have any good idea? Please help me with some good tutorials.

Sorry for the late answer but it could help people a day or another.
As I had to integrate the MuPDF library into one of my (Swift) project, I generated
the static fat libraries and integrate them into Xcode.
Here you go with a step-by-step quick tutorial:
How to build the static fat library:
git clone --recursive git://git.ghostscript.com/mupdf.git
Go to mupdf/platform/ios
Open MuPDF.xcodeproj with Xcode.
Configure the scheme of the MuPDF target to Release.
Build and run the app on an iPhone simulator.
This will generate the library for platforms i386 and x86_64
Build and Run the app on a real iPhone device - use your own bundle id, certificate and provisioning profile.
This will generate the library for platforms armv7 and arm64
Go to mupdf/build/
You will find two folders that contains all built librairies: release-ios-i386-x86_64 and release-ios-armv7-arm64
Now you need to create fat libraries with all 4 architectures for the mupdf one and all its dependencies.
lipo -create ./*/libcurl.a -output 'libcurl.a' ; lipo -create ./*/libfreetype.a -output 'libfreetype.a' ; lipo -create ./*/libjbig2dec.a -output 'libjbig2dec.a' ; lipo -create ./*/libjpeg.a -output 'libjpeg.a' ; lipo -create ./*/libmujs.a -output 'libmujs.a' ; lipo -create ./*/libmupdf.a -output 'libmupdf.a' ; lipo -create ./*/libopenjpeg.a -output 'libopenjpeg.a' ; lipo -create ./*/libz.a -output 'libz.a'
How to integrate MuPDF into your project:
Add/import into your project:
All header files from mupdf/include/mupdf
All obj-c classes from mupdf/platform/ios/classes
The common.[h,m] files from mupdf/platform/ios
Add/import the previously generated fat libraries (8 files)
Configure the Library Search Path by adding the path to your library files.
For example $(inherited) $(PROJECT_DIR)/External/MuPDF/lib/
You should now be able to build and run your app with the library included.
Use the sample project to understand how the library works or any online tutorial.
Pro Tip:
The final fat libraries are pretty big all together (~ 46mb).
You could easily reduce the final size of your app by importing:
Under a release folder just the lib.a from mupdf/build/release-ios-armv7-arm64
Under a debug folder the big generated fat librairies from mupdf/build/
Set different Library Search Path for Debug and Release config.
Once done, you will be able to build and run on Debug on every simulator and devices. But only on devices for Release. Which in the end you need as your app, through, the AppStore
should only run on real devices. There is no need to include debug-simulator architecture static librairies.
Here is a screenshot of all imported files into my Xcode project:

It is certainly possible to develop an ebook reader on iphone/ipad using MuPDF.
MuPDF is licensed both under the GNU GPL and under the Artifex commercial license. We have commercial licensees who do use MuPDF to implement ebook readers on ipad.
We also release a version of MuPDF for iOS via the iTunes app store (search for MuPDF) - so despite their sometimes unclear and arbitrary rules about what they will and won't allow, Apple clearly have no problem with "duplicating functionality" as a previous respondent suggested.
As to help with tutorials etc:
in the MuPDF source we have a doc directory that contains example source showing how to open/render/close a PDF file. We also have examples there that show how to work in multi-threaded worlds.
we have example android/iOS/windows/linux viewers in the source too.
we have simple command line tools (again with full source) that show how to render PDFs etc.
I would hope that this is enough to get a competent programmer moving.
While the GNU GPL version is released unsupported, we do offer support contracts to those who want them. Alternatively, pop along to the #ghostscript irc channel and we may be able to help with simple queries (though there is a limit to how much time we can invest in helping any single free user). Or, ask specific questions on here.

Related

Lipo Error while creating Universal frameworks in xcode 12

I am facing problem while making universal frameworks in xcode 12. following is the command that i ran:-
lipo -create build/simulator/FrameworkName.framework/FrameworkName build/devices/FrameworkName.framework/FrameworkName -output build/universal/FrameworkName.framework/FrameworkName
And following is the error that i am facing:-
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: build/simulator/FrameworkName.framework/FrameworkName and build/devices/FrameworkName.framework/FrameworkName have the same architectures (arm64) and can't be in the same fat output file
when i googled this error i found solution to set my 'Architectures', in 'Build Settings', to Standard, however it was already set to standard find the screenshot attached
Note: I was following this tutorial:- https://medium.com/#anuragajwani/how-to-build-universal-ios-frameworks-74b6b07bf31d
The error tells you that both your frameworks in build/simulator and build/device folders have been built for the same architecture (arm64, which is a device architecture). You can verify this by yourself, by looking inside the .framework file: FrameworkName.framework/Modules/FrameworkName.swiftmodule.
It is possible, that one of the folders (or both) contain more than one architecture like this:
Personally, I like to build my 'fat' frameworks outside the Xcode.app folders (just to make sure I have complete control over what is where). First, run your framework for simulator (select any simulator as build target). After the process has completed, go to Products folder in Xcode Navigator, click Show in Finder on FrameworkName.framework file. Copy the shown .framework somewhere more convenient (e.g. Desktop/simulator folder)
Then, build the framework again, only this time for device (select Any iOS device as build target). Copy second .framework somewhere like Desktop/iphone folder.
Create empty Desktop/universal folder for output framework. Copy .framework file there from Desktop/iphone folder and remove Desktop/universal/FrameworkName.framework/Framework executable file. This file will later be replaced by lipo.
Next, do the lipo magic:
lipo -create ~/Desktop/iphone/FrameworkName.framework/FrameworkName ~/Desktop/simulator/FrameworkName.framework/FrameworkName -output ~/Desktop/universal/FrameworkName.framework/FrameworkName
Last step, go to Desktop/simulator/FrameworkName.framework/Modules/FrameworkName.swiftmodule copy all files that start with x86_64 prefix, and paste them to Desktop/universal/FrameworkName.framework/Modules/FrameworkName.swiftmodule. Now your Desktop/universal/FrameworkName.framework contains both device and simulator architectures. Congrats, you've got your 'fat' library!
Disclaimer: Yes, I realise there are easier ways to do this with various scripts and terminal commands, but all of them do pretty much the same thing. Once you try to do this manually step by step, it will help you understand what goes where, and what are architectures and how they can be combined.
Disclaimer 2: Starting from Xcode 12, Apple insists you build .xcframeworks instead of 'fat' libraries. See here

Will the compiler strip the unrelated arch symbols from dependent static library in product binary file?

I'm a new in framework development, here is my case. I build a private static library to provide it to the vendors to link it.
Currently, I build my library with arch armv7 and arm64 only, this should be work for vendors to debug it in iOS device and archive their apps, but not for debugging in iOS Simulator. The simulator needs the x86_64 ( and even i386 in iPhone 5 Simulator). It isn't friendly to disable the ability to debug it in a simulator. I'm considering to provide a fat architecture of static library for them.
Here is the action
lipo -create libSignatureLibary_armv6.a libSignatureLibary_armv7.a libSignatureLibary_i368.a -output libSignatureLibary.a
After the merge operation, the output library has a double size than the single one.
The question is, will the compiler/Xcode strip the i386 and x86_64 arch symbols from final app product binary? If not, the fat arch library will increase the product app's size directly, right? Should I build two versions of the library for vendors, one for debugging, another for archiving? What's the right solution for this case?
I don't know what keywords I should research, I didn't have an existing product app linking it to verify this, either. (Maybe I should build a new later.)
Don't worry, the linker only uses the .o (relocatable object file, it is the output file of assembler, when you build a static library, a .m file will be translated to a .o file. The static library is a collection of relocatable object files) files for target arch in the static library, so it will strip the x86_64 and i386 .o files when building product binary.
Also the linker won't link the .o file which is not referenced directly or indirectly by compiled files into executable file.

How to integrate MuPDF 1.3 in iOS Project

There is build-in PDF render engine for iOS, but it doesn't solve the "Transparency Flattening" issue. Hence I try to integrate MuPDF 1.3 into project.
I tried to use reference the MuPDF project, and it failed.
Then I build debug static libraries for each architecture, and use "Library Search Paths" and "Other Link Flags" to separate the linked library while building binary of different architecture, but XCode keeps showing "Undefined symbols for architecture armxxx".
Finally, I built the release version static library of MuPDF, which should compatible for all architecture, and XCode still keeps showing same thing as before.
Does there anyone integrate and compile MuPDF 1.3 successfully? Please give me some hint.
Thanks a lot.
Sorry for the late answer but it could help people a day or another.
As I had to integrate the MuPDF library into one of my (Swift) project, I generated
the static fat libraries and integrate them into Xcode.
Here you go with a step-by-step quick tutorial:
How to build the static fat library:
git clone --recursive git://git.ghostscript.com/mupdf.git
Go to mupdf/platform/ios
Open MuPDF.xcodeproj with Xcode.
Configure the scheme of the MuPDF target to Release.
Build and run the app on an iPhone simulator.
This will generate the library for platforms i386 and x86_64
Build and Run the app on a real iPhone device - use your own bundle id, certificate and provisioning profile.
This will generate the library for platforms armv7 and arm64
Go to mupdf/build/
You will find two folders that contains all built librairies: release-ios-i386-x86_64 and release-ios-armv7-arm64
Now you need to create fat libraries with all 4 architectures for the mupdf one and all its dependencies.
lipo -create ./*/libcurl.a -output 'libcurl.a' ; lipo -create ./*/libfreetype.a -output 'libfreetype.a' ; lipo -create ./*/libjbig2dec.a -output 'libjbig2dec.a' ; lipo -create ./*/libjpeg.a -output 'libjpeg.a' ; lipo -create ./*/libmujs.a -output 'libmujs.a' ; lipo -create ./*/libmupdf.a -output 'libmupdf.a' ; lipo -create ./*/libopenjpeg.a -output 'libopenjpeg.a' ; lipo -create ./*/libz.a -output 'libz.a'
How to integrate MuPDF into your project:
Add/import into your project:
All header files from mupdf/include/mupdf
All obj-c classes from mupdf/platform/ios/classes
The common.[h,m] files from mupdf/platform/ios
Add/import the previously generated fat libraries (8 files)
Configure the Library Search Path by adding the path to your library files.
For example $(inherited) $(PROJECT_DIR)/External/MuPDF/lib/
You should now be able to build and run your app with the library included.
Use the sample project to understand how the library works or any online tutorial.
Pro Tip:
The final fat libraries are pretty big all together (~ 46mb).
You could easily reduce the final size of your app by importing:
Under a release folder just the lib.a from mupdf/build/release-ios-armv7-arm64
Under a debug folder the big generated fat librairies from mupdf/build/
Set different Library Search Path for Debug and Release config.
Once done, you will be able to build and run on Debug on every simulator and devices. But only on devices for Release. Which in the end you need as your app, through, the AppStore
should only run on real devices. There is no need to include debug-simulator architecture static librairies.
Here is a screenshot of all imported files into my Xcode project:
The easiest way is probably to use the MuPDF CocoaPod, which I just created. There is an example application based on that pod.

Check supported architectures of framework in Objective-C

As requested by Apple in the next February (February 2014), every app submitted to AppStore needs to support Arm64 architecture. In my project, I used many static libraries (*.a) and I can check if these libs support arm64 arch. However, I don't know if some frameworks such as Facebook.framework supports this new arch. How can I check it?
Each framework is really just a directory - not even like a package directory, but a plain directory you can browse directly into with Finder. Go into the .framework folder, at the top level you'll find a file with the same name as the framework (for older frameworks that file may be located under a folder called Versions/A within the .framework folder).
That file is really a static library (.a) file, just without the extension. Check it as you would any static library (using file or lipo -info) and you'll see what binaries the file contains.
You'll also know through XCode though. If you switch your project to support arm64 and the libraries you are linking to do not have arm64 support, XCode will not finish linking when compiling for a device.
Check below command in Terminal
lipo -info yourlib.a
Output like :
Architectures in the fat file: yourlib.a are: i386 x86_64 armv7 arm64
In case Framework.framework
Go to inside framework like below
cd /Your_Path_/CocoaLumberjack.framework
then run command
lipo -info CocoaLumberjack

I want to know how to make a makefile for iOS "fat" library

I want to create a (non-xcode) makefile to create a fat library (emulator + device(s)) that can be imported into an XCode project using a makefile that calls the basic command line tools directly (not running XCODE from the command line, but the MAC Gcc and it's related utilities) - this is for .m, .mm, .c, and .cpp source files.
Ideal would be to find an example that works for a simple library (not by calling a makefile generator that makes an almost non human readable makefile)
anyway anyone know of such a thing or appropriate mechanism for doing the same?
Also an ability to extract the complier flags from an XCode project would be real handy :)
The purpose is I want to add a module to my cross platform libraries so I can integrate them into an iOS project.
Thanks!!
You can extract the compiler flags by viewing the build details or, more simply, running xcodebuild from the command line.
To create a fat binary, you either take advantage of the compiler toolchain's built-in support on the Mac OS X platform by passing multiple -arch arguments, like so:
clang -arch i386 -arch x86_64 -framework Foundation simple.m -o simple
Alternatively, you build the binary once for each desired architecture, then wrap all those binaries into a single fat binary using lipo. This is handy when working with ported Unix software; just change the build result directory each time, then smash them all together after building with lipo. Assuming you have simple-i386 and simple-x86_64, you would then do:
lipo simple-i386 simple-x86_64 -create -output simple
This would create a fat binary named simple containing simple-i386 and simple-x86_64.
Ok - I found this which is a great HOWTO o building a fat library using XCODE that outlines the process and how to create the projects
http://blog.boreal-kiss.net/2011/03/15/how-to-create-universal-static-libraries-on-xcode-4/
being a newbie to XCode and iOS development I had to discover a few things.
you can view the actual command line output of a build to see what the gcc flags are.
View->Navigators->Log - then control click on the messages list to "expand all Transcripts"
to see what stdout and stderr from the chosen build's build output.
You can execute an "external build tool" with your .bashrc and .bash_profile environment settings by making the command and arguments a login shell: "bash --login -c 'mybuildtool [my tools args] $(ACTION)', and thus bypass having to deal with the hard to maintain MacOSX launchd settings etc. this works for things like using ruby and rake as well as make etc.

Resources