17
Feb
11

How To: Cross compiling libraries for iOS (armv6/armv7/i386)

Update

So, if you’re a smart programmer, when you get asked to solve some new problem (“new” in the “I’ve never done this before” sense) you head over to Chrome (not Opera/Firefox, as I stated earlier, you’re SMART, not FASHION or OUTDATED), hit “CTRL + L” and start typing some keywords related to your problem, hit ENTER and wait for the amazing amount of resources Google (not Bing, because, as I stated earlier, you’re a programmer, not a no-brains) will hand you.

Among those resources, if you’re lucky enough, you’ll find out an OpenSource library that claims to solve exactly, or at least a piece of, your problem. This Library has binary downloadable packages for almost every OS you can imagine and even for OpenSolaris BUT, if you’re a mobile App developer (Android/iOS), they won’t give a fck!ng d@mn $h!t binary for your target OS.

Well, at this point, if you’re in a good day and helped that old lady cross the street a couple of hours earlier, this Library will be ready to compile through one configure script named, ehrm… “configure”.

If you’ve made it through here, maybe I can save your day. I’ve prepared one Bash script that is able to cross-compile one (or more) Static Library in different architectures (armv6/armv7/i386) and pack all different lib*.a into one single FAT FILE (or Universal Binary) so you can link against the same file when compiling for iPhone3G/3GS/4/Simulator.

Before we get our hands dirty, I’d like to clarify that:

  • Armv6 binaries are needed if you’re targeting iPhone3G (yes, they still exist, my co-worker uses one, can u believe it?);
  • Armv7 binaries are desirable if you’re targeting iPhone3GS/4 or iPad, since these new toys have Armv7 processors and, besides being able to rum Armv6 binaries, they probably will have a better performance using the better Armv7 architecture;
  • i386 binares are needed if you intent to run your code at the Simulator (ok, it is needed, right?!).

Let’s get this party started! (or: Compiling)

Basically, for each architecture, we’ll be:

  1. Pre-configuring the environment: setting some environment variables to values related to our current arch;
  2. Configuring the library through its own “configure” script;
  3. Compiling the library, hell yeah!

For explanation, I’ll be compiling the Leptonica and Tesseract-OCR libraries. My folder structure for this script is the following:

  • ./ – root dir
  • ./dependencies/ – folder where the final binary and headers will be placed;
  • ./leptonlib-1.67 – folder with the sources of the first library I wanna compile;
  • ./opencv/ – folder with the sources of the second library (that depends on the first one) I wanna compile;
  • ./build_dependencies.sh – the bash script I’m explaining you.

Initially we’ll be setting some globals:

GLOBAL_OUTDIR="`pwd`/dependencies"
mkdir -p $GLOBAL_OUTDIR/include $GLOBAL_OUTDIR/lib
OUTDIR="./outdir"
LEPTON_LIB="`pwd`/leptonlib-1.67"
TESSERACT_LIB="`pwd`/tesseract_ocr"

IOS_BASE_SDK="4.2"
IOS_DEPLOY_TGT="3.2"

  • $GLOBAL_OUTDIR is a common folder where includes and lib files from every library will be put into;
  • $OUTDIR is a folder name where, inside each lib dir, we’ll be putting the lib files that library generates, before moving them to the global one;
  • $LEPTON_LIB and $TESSERACT_LIB are the libraries I’m compiling;
  • $IOS_BASE_SDK is the iOS SDK version you’re compiling against;
  • $IOS_DEPLOY_TGT the iOS SDK minimum version you’ll allow your App to run.

Then, we’ll define a common function to be used for all architectures:

setenv_all()
{
        # Add internal libs
        export CFLAGS="$CFLAGS -I$GLOBAL_OUTDIR/include -L$GLOBAL_OUTDIR/lib"

        export CPP="$DEVROOT/usr/bin/cpp-4.2"
        export CXX="$DEVROOT/usr/bin/g++-4.2"
        export CXXCPP="$DEVROOT/usr/bin/cpp-4.2"
        export CC="$DEVROOT/usr/bin/gcc-4.2"
        export LD=$DEVROOT/usr/bin/ld
        export AR=$DEVROOT/usr/bin/ar
        export AS=$DEVROOT/usr/bin/as
        export NM=$DEVROOT/usr/bin/nm
        export RANLIB=$DEVROOT/usr/bin/ranlib
        export LDFLAGS="-L$SDKROOT/usr/lib/"

        export CPPFLAGS=$CFLAGS
        export CXXFLAGS=$CFLAGS
}

Note that $GLOBAL_OUTDIR is used as an include path (include sub-directory) and library path (lib sub-directory) so that if one of the libraries you’re compiling depend on each other (which is my case), they can link against each other.

And, finally a setenv function for each architecture:

setenv_arm6()
{
        unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS

        export DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk

        export CFLAGS="-arch armv6 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"

        setenv_all
}

setenv_arm7()
{
        unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS

        export DEVROOT=/Developer/Platforms/iPhoneOS.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk

        export CFLAGS="-arch armv7 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT -I$SDKROOT/usr/include/"

        setenv_all
}

setenv_i386()
{
        unset DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS

        export DEVROOT=/Developer/Platforms/iPhoneSimulator.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneSimulator$IOS_BASE_SDK.sdk

        export CFLAGS="-arch i386 -pipe -no-cpp-precomp -isysroot $SDKROOT -miphoneos-version-min=$IOS_DEPLOY_TGT"

        setenv_all
}

Just to follow the file structure, I’ll be dropping these functions now, they are responsible for merging lib*.a files from different architectures into a single one (using lipo) and merging lib*.a files from the same architecture into a single one (this one was particularly useful for my case, so you can skip it):

create_outdir_lipo()
{
        for lib_i386 in `find $OUTDIR/i386 -name "lib*\.a"`; do
                lib_arm6=`echo $lib_i386 | sed "s/i386/arm6/g"`
                lib_arm7=`echo $lib_i386 | sed "s/i386/arm7/g"`
                lib=`echo $lib_i386 | sed "s/i386\///g"`
                lipo -arch armv6 $lib_arm6 -arch armv7 $lib_arm7 -arch i386 $lib_i386 -create -output $lib
        done
}

merge_libfiles()
{
        DIR=$1
        LIBNAME=$2

        cd $DIR
        for i in `find . -name "lib*.a"`; do
                $AR -x $i
        done
        $AR -r $LIBNAME *.o
        rm -rf *.o __*
        cd -
}

Now that we’ve defined all the functions we’ll need, let’s compile the first library!

Leptonica

#######################
# LEPTONLIB
#######################
cd $LEPTON_LIB
rm -rf $OUTDIR
mkdir -p $OUTDIR/arm6 $OUTDIR/arm7 $OUTDIR/i386

Enter the library subdir, remove any old built files and re-create the $OUTDIR dir structure.

make clean 2> /dev/null
make distclean 2> /dev/null

Clean anything that might have happened earlier.

setenv_arm6
./configure --host=arm-apple-darwin6 --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff

Configure the environment for Armv6 architecture and call the library configure script. The following parameters are very important:

  • –host=arm-apple-darwin6: Defines the architecture;
  • –enable-shared=no: Builds the library as a statical one, since we can’t use dynamically linked libraries on iOS Applications;
  • The other ones are specific for this project and suited to my preferences.

make -j4
cp -rvf src/.libs/lib*.a $OUTDIR/arm6

Compiles the library in 4 separated tasks (faster and recommended on Core2Duo processors) and copies the generates lib*.a files to the architecture specific $OUTDIR subfolder.

It is very important to notice that your library may generate the Library files (lib*.a) in a different folder, so it is advisable that, after “make -j4″, you issue the following command to find your lib*.a files:

find . -name "lib*.a"

If your lib*.a files are in a different location, change the cp command argument “src/.libs/lib*.a” to your different location.

After this, we repeat the commands (with the appropriated different arguments) for the other architectures:

make clean 2> /dev/null
make distclean 2> /dev/null
setenv_arm7
./configure --host=arm-apple-darwin7 --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
make -j4
cp -rvf src/.libs/lib*.a $OUTDIR/arm7

make clean 2> /dev/null
make distclean 2> /dev/null
setenv_i386
./configure --enable-shared=no --disable-programs --without-zlib --without-libpng --without-jpeg --without-giflib --without-libtiff
make -j4
cp -rvf src/.libs/lib*.a $OUTDIR/i386

And now, let’s get to what we want: get the library files!

create_outdir_lipo
mkdir -p $GLOBAL_OUTDIR/include/leptonica && cp -rvf src/*.h $GLOBAL_OUTDIR/include/leptonica
mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $OUTDIR/lib*.a $GLOBAL_OUTDIR/lib
cd -

Create a FAT file (by the “lipo” tool… interesting) containing the binaries for the 3 archs, copy the desired Header files (.h) to the leptonica include folder inside $GLOBAL_OUTDIR and copy the generated FAT file to $GLOBAL_OUTDIR/lib.

Well, if you’re interested in compiling a single library, this is it! But, OpenSource libraries often are using another OpenSource libraries… what happened to be my case. So let’s get to the second one:

Tesseract-OCR

This is the library I REALLY want compiled.

#######################
# TESSERACT-OCR (v3)
#######################
cd $TESSERACT_LIB
rm -rf $OUTDIR
mkdir -p $OUTDIR/arm6 $OUTDIR/arm7 $OUTDIR/i386

make clean 2> /dev/null
make distclean 2> /dev/null
setenv_arm6
./configure --host=arm-apple-darwin6 --enable-shared=no --without-libtiff --with-liblepto="$GLOBAL_OUTDIR/include/leptonica"
make -j4
for i in `find . -name "lib*.a"`; do cp -rvf $i $OUTDIR/arm6; done
merge_libfiles $OUTDIR/arm6 libtesseract_all.a

make clean 2> /dev/null
make distclean 2> /dev/null
setenv_arm7
./configure --host=arm-apple-darwin7 --enable-shared=no --without-libtiff --with-liblepto="$GLOBAL_OUTDIR/include/leptonica"
make -j4
for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $OUTDIR/arm7; done
merge_libfiles $OUTDIR/arm7 libtesseract_all.a
make clean 2> /dev/null
make distclean 2> /dev/null
setenv_i386
./configure --enable-shared=no --without-libtiff --with-liblepto="$GLOBAL_OUTDIR/include/leptonica"
make -j4
for i in `find . -name "lib*.a" | grep -v arm`; do cp -rvf $i $OUTDIR/i386; done
merge_libfiles $OUTDIR/i386 libtesseract_all.a

create_outdir_lipo
mkdir -p $GLOBAL_OUTDIR/include/tesseract && cp -rvf api/apitypes.h api/baseapi.h ccmain/thresholder.h ccstruct/publictypes.h ccutil/ocrclass.h ccutil/unichar.h
 $GLOBAL_OUTDIR/include/tesseract
mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $OUTDIR/lib*.a $GLOBAL_OUTDIR/lib
cd -

Note that here I use “merge_libfiles”. The reason is that tesseract generates 15 (FIFTEEN!!!) libtesseract_*.a files, so I merge them into a single libtesseract_all.a.

It is also worthy to note that I’m using the custom configure argument:

--with-liblepto="$GLOBAL_OUTDIR/include/leptonica"

I had to modify the original configure script for tesseract v3.01 since it requires leptonica BUT would only check if it was present on your machine library paths and, since we’re not compiling for our machine, but to iOS architectures, it wouldn’t find a suitable leptonica to link against. The changes I’ve made are fairly simple and I’m making the modified file available as well.

Project Configuration

Now you have the include .h files and the libraries .a files, what about including ‘em at your project? Open Xcode and do as explained:

  1. Add the .h files as you would include any other source files: right-click your project at ” Groups and Files” -> Add -> Existing Files… -> Select the .h files (or the containing folder). I like to keep headers/sources I add this way organized within an “External Classes” group;
  2. Add the .a files so your application will link against them: at “Groups and Files”, expand Targets -> Expand {YOUR_PROJECT_NAME} ->Right-click Link With Binaries -> Add -> Existing Files… -> Select the .a files;
  3. Also, our pre-compiled libraries are generated with the better LLVM compiler, so we’ll set our application project to use LLVM and GCC so we can use libraries compiled with both compilers: at “Groups and Files”, double-click your project -> At Tab Build -> At Section Compiler Version -> Change C/C++ Compiler Version to: LLVM GCC 4.2.

That’s it, now you should be able to compile and run your own application.

Files for Download!

I really hope to be helping someone out there (let me know if so…) (really, I can get motivated to help out MORE):

Acknowledgements

Advertisement

68 Responses to “How To: Cross compiling libraries for iOS (armv6/armv7/i386)”


  1. 1 Quentin Liedtke
    March 4, 2011 at 1:16 pm

    Great article, thanks for this. I think there is an error in your shell script though.

    I think:
    cp -rvf $OUTDIR/lib*.a $GLOBAL_OUTDIR/lib
    should be:
    mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $OUTDIR/lib*.a $GLOBAL_OUTDIR/lib

    without making the directory first, it copies all lib*.a to a file named $GLOBAL_OUTDIR/lib.

    • March 4, 2011 at 3:42 pm

      Thanks for the tip. I thought that it would be implicit that you should have it created before, but adding the ‘mkdir -p’ made it bullet-proof.

      Thanks again!

  2. 3 Thuan
    March 6, 2011 at 1:38 pm

    Thanks for sharing your build scripts and this information, it’s helped me a lot! I’ve seen quite a few posts about cross compiling tesseract but most of them were out of date. Yours works with the latest 3.01. I did try your script with 3.00 which it seems to have compiled fine but it tried to copy some headers which don’t seem to exist in 3.00 but does in 3.01.

  3. 4 ngb
    March 12, 2011 at 2:16 am

    it compiles ok but i get linker errors when i try to use the libraries.
    am i missing something?

    Undefined symbols for architecture armv7:
    “TessBaseAPI::ClearAdaptiveClassifier()”, referenced from:
    -[OCRView freeMemory] in OCRView.o
    -[OCRView ocrImage:] in OCRView.o
    “TessBaseAPI::SimpleInit(char const*, char const*, bool)”, referenced from:
    -[OCRView startTesseract] in OCRView.o
    “TessBaseAPI::End()”, referenced from:
    -[OCRView dealloc] in OCRView.o
    “TessBaseAPI::SetVariable(char const*, char const*)”, referenced from:
    -[OCRView startTesseract] in OCRView.o
    “TessBaseAPI::TesseractRect(unsigned char const*, int, int, int, int, int, int)”, referenced from:
    -[OCRView ocrImage:] in OCRView.o
    ld: symbol(s) not found for architecture armv7
    collect2: ld returned 1 exit status

  4. 6 Benjamin Ng
    March 12, 2011 at 8:28 pm

    This is great stuff. Is it possible to provide the binary for this as well? I’m able to compile this using your instructions with no errors, but I get linker errors when I use this in my project. Would like to see if this is a compile problem with the library or my problem with an Xcode setting.

    • March 13, 2011 at 2:34 pm

      It seems that I’ve forgot to mention one crucial point: usage of LLVM. Please take a look at the “Project Configuration” section, 3rd Item and see if it solves yours problems. To avoid this kind of problems, I’ve also added the binaries for download as well.

      • 8 Benjamin Ng
        March 14, 2011 at 10:54 am

        Thanks for this. i’ve changed the compiler to LLVM-GCC 4.2 in xcode but i’m still getting linker errors.
        “ld: symbol(s) not found for architecture armv7″
        against the tesseract libraries and
        “file is universal but does not contain a(n) armv7 slice for architecture armv7″
        against the opencv/leptonica libraries.
        the same happens with the binaries you provided.

        I also noticed that the build_dependencies.sh file appears to build against gcc rather than llvm-gcc:
        export CPP=”$DEVROOT/usr/bin/cpp-4.2″
        export CXX=”$DEVROOT/usr/bin/g++-4.2″
        export CXXCPP=”$DEVROOT/usr/bin/cpp-4.2″
        export CC=”$DEVROOT/usr/bin/gcc-4.2″
        is this correct? if i point these to the llvm-gcc-4.2 files the compile doesnt complete successfully.

        is there anything else that i could be missing?

      • March 14, 2011 at 12:20 pm

        Hi Benjamin. I remember having to change from GCC 4.2 to LLVM-GCC 4.2 at Xcode due to linker errors I was having when trying to link against the generated libraries, so I’ve deduced they were using this compiler.

        Could you try checking the .a files with lipo?
        lipo -i libcv.a libcxcore.a liblept.a libtesseract_all.a
        My output was:
        Architectures in the fat file: libcv.a are: armv6 i386
        Architectures in the fat file: libcxcore.a are: armv6 i386
        Architectures in the fat file: liblept.a are: armv6 armv7 i386
        Architectures in the fat file: libtesseract_all.a are: armv6 armv7 i386

        As I’ve only copied OpenCV libraries, I’m using just the armv6 ones. But you can see that Leptonica an Tesseract are on armv6/7 and i386.
        Which version of Xcode are you using? I haven’t changed to 4.3 and still am using 3.2.5.

      • 10 Benjamin Ng
        March 20, 2011 at 5:12 am

        I checked these with lipo and get the same output as you get.
        Using xcode 4 with SDK 4.3. I have other similar libraries that link in without problem.

        Do you have an .xcodeproj file i can you to check against?
        Are there any other settings that you set to get it linking in properly?

    • 11 Benjamin Ng
      March 20, 2011 at 5:14 am

      I also tried this on xcode 3.2.5 with sdk 4.2, with same problems.
      thanks for your help btw.

  5. 12 Max Cantor
    March 13, 2011 at 4:37 am

    Wow, great post. Very helpful.

    Also, if you’re in Japan, as are many of my friends, anzen ni shite, and hope you’re ok.

    Have you been able to get libjpeg or libpng to build and to get leptonica built with jpeg or png support? I tried to do it using build_instructions.hs as a guide. I’m a bit stuck as libjpeg is building .la file instead of .a. any tips?

    thanks,
    max

    • March 13, 2011 at 2:48 pm

      Hi Max, thanks for the compliments and… I’m a Brazilian of Japanese descent :P

      About libjpeg, after issuing the “make” command, look at the “./.libs” hidden (maybe you used Finder and couldn’t see it) sub-directory, that’s where the libjpeg compilation scripts generates the libjpeg.a library file.

      If the file isn’t there, try using the “–enable-static” configure script parameter.

      If you still can’t find the .a file, try issuing the following command as it will search the file for you:
      find . -name “*.a”
      sample output:
      ./.libs/libjpeg.a

      You can also peek at the project supported configure script parameters by issuing:
      ./configure –help

      Regards,
      Suzuki

  6. 14 derp
    June 17, 2011 at 4:53 am

    Man, thanks for the tip, but after reading your first paragraph i must state openly that you are a freaking TWAT

    • June 17, 2011 at 6:35 am

      Cmon man! Will u deny that u found this at google?

      I was just trying to blog rather than just giving some steps that any (non-brainer or not) machine could follow.

  7. 16 Nikita
    July 1, 2011 at 6:07 pm

    Thank you so much! I was finally able to compile libpng with some help from your instructions. After 2 days of insane googling and dozens of different attempts, I was able to link it to my project thanks to this post.

  8. 17 jsd
    July 3, 2011 at 3:36 pm

    this was super helpful. i had a project that needed a static library and i wanted it to run on device and simulator. i didn’t know about lipo command, but i do now. thanks!

  9. 19 SS
    July 22, 2011 at 10:17 am

    Hi,

    I didn’t compile projects and just added dependencies (library and header folder) into project.
    After that included baseapi.h and got many errors:
    http://imageshack.us/photo/my-images/824/screenshot20110722at352.png

    Here is my project codebase:
    http://www.datafilehost.com/download-8654fb75.html

    How to solve the problem?

    Thank you, in advance.

    • July 22, 2011 at 10:39 am

      Hi SS,

      I can’t give you a certain answer and don’t have enough time to download your project, but if you downloaded the opencv_leptonica_tesseract_ios_42.zip file I’ve supplied and got these errors, I’d say that maybe you’re using the wrong iOS SDK version or haven’t changed your compiler to LLVM as indicated.

      Besides that, this article is sort of outdated, I’ll be writing a new one with instructions and pre-compiled libraries for iOS SDK 5 and Xcode 4.2 as soon as it leaves beta (with the updated versions of OpenCV, Leptonica and Tesseract as well).

      Regards

      • 21 SS
        July 22, 2011 at 10:41 am

        Thank you for answer.

        I use LLVM compiler and iOS SDK 4.2 as you mentioned in the post.

      • July 22, 2011 at 10:44 am

        OK, I’ll see if I get some free time at the end of the day and try to submit a full project with tesseract enabled on Xcode 4.2 and iOS SDK 5 beta3.

  10. 23 Daniel Dekkers
    August 12, 2011 at 7:41 am

    Hi, interesting post.

    We are creating a “meta build system” too at the moment but we are basing it on CMake, many libraries support it nowadays, although some have to be built with their own specific build system first. For instance Boost via Bjam.

    We got OpenGL, Glut, Boost, Bullet, Zlib, Libpng working at the moment, on Mac OS X and Windows.
    So we can build the libs from source, find them in our CMake script (using find_package()) and use them in our own apps.

    Every individual library seems to take some time, see for instance, a recent discussion on the Bullet forum:
    http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=7168
    We’ve had similar discussions about Zlib/Libpng. And Boost (although that one was relatively easy).

    I’m still a bit scared to dive into iOS (different architectures in general, as opposed to different compilers) until now but maybe now, i’ll have enough courage ;-)

    If you’re interested in discussing “Different architectures with CMake” let me know.

    Kind Regards, Daniel Dekkers (d.dekkers@cthrough.nl)

  11. 25 Tim
    August 14, 2011 at 9:30 pm

    Hi I’m trying to build for an iPhone 4 running 4.3 using xCode 4.0.1 and using GCC LLVM but I’m getting this error

    ld: in /Volumes/Tim’s TB Passport/CaseLoggr/dependencies/lib/libcxcore.a, file is universal but does not contain a(n) armv7 slice for architecture armv7
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    It works for the simulator but won’t compile for armv7

    Any idea what to do?

    Thanks

    • 26 Tim
      August 14, 2011 at 9:37 pm

      Oh and I’m using the library files from the zip link you gave

      • 27 Tim
        August 14, 2011 at 10:01 pm

        Okay I think I fixed that problem by not including the libxcore and libcv

        But now I have another problem. It works great in the simulator but when I run my app on my iPhone, it crashes at

        tess->TesseractRect() with an “EXC_BAD_ACCESS”

        Any ideas?

        Thanks!

      • August 15, 2011 at 10:42 am

        Ok, one (more) flaw at my post was that I didn’t explained how to correctly setup tesseract before using it.

        You’ve gotta setup its “tessdata” folder, where it will get its trained data to be able to recognize stuff. The code that shows how to do it is available at pastebin:
        http://goo.gl/qPmXS (goo.gl is to track its access…)

        Also, you’ve gotta add the “tessdata” folder, containing the “*.traineddata” files, in a different way at Xcode:

        1. Right-click your project/group at Xcode
        2. Add Files to “Your Project”
        3. Select the “tessdata” folder
        4. At the same window, check the “Create folder references for any added foldes”

        The last step is the most important one, as it instructs Xcode to add your “tessdata” folder as a regular folder (a resource, as well), not as a Xcode project group.

        If you have Xcode 4.2 and iOS SDK 5 (any beta version should do), you can download my full sample project (I’ll write another post with updated instructions for iOS 5 later…) available at:
        http://goo.gl/8r1HE (again, goo.gl is to track its usage…)

        Best regards,
        Suzuki

  12. 29 qfatboy
    September 3, 2011 at 9:57 am

    Thank you for your sh,it’s very helpful

  13. September 12, 2011 at 9:37 am

    Thanks for the library and the article. Saved my day!. Great job!.

  14. 33 venusbai
    September 22, 2011 at 4:29 pm

    Suzuki San, Are you sure there is a slash betwween “leptonlib” and “-1.67″ ? for the folder hierachy?

    “./leptonlib/-1.67 – folder with the sources of the first library I wanna compile;”

    I found these isn’t the slash in your script, like:

    “LEPTON_LIB=”`pwd`/leptonlib-1.67″

  15. 35 takashi
    September 26, 2011 at 5:02 pm

    ola,
    muito interessante ,tem como voce postar esse tutorial em portugues ?
    estu tentando compilar esse ettercap https://github.com/TheWorm/Ettercap-NG
    no iphone ,tenho o LIBPCAP 1.0.0-4 instado ,mas quando vou rodar o configure :

    iPhone:/TheWorm-Ettercap-NG-4df3b84 root#./configure –disable-gtk –disable-debug –enable-plugins
    …..
    Checking user defined options…

    checking if –enable-debug option was specified… no
    checking if –enable-plugins option was specified… yes
    checking for libpcap… yes
    checking for pcap_datalink_val_to_description in -lpcap… no
    configure: error: Incorrect libpcap version. libpcap >= 0.8.1 required

    alguma ideia???

    • October 4, 2011 at 10:40 am

      Fala Takashi!
      É bom falar um pouco nosso português por aqui, hehe.
      Bom, não adianta ter a libpcap compilada e instalada para o seu Desktop, ela deve ter sido configurada e compilada também para iOS e para o Emulador. Uma vez que você tenha feito isso, pode referenciar essa sua versão especial da libpcap no configure do Ettercap adicionando o seguinte parâmetro ao chamar o ./configure:

      –with-libpcap=DIR

      Vale lembrar também que se você quiser o Ettercap já compilado, pode baixá-lo pelo Cydia através da fonte:

      http://theworm.altervista.org/cydia/

      Boa sorte!

  16. 37 Mikado
    September 29, 2011 at 10:44 pm

    Hi Suzuki san,
    May I ask what is the version of the tesseract you are using for the sample project build against iOS 5.0, xcode 4.2?
    ‘coz I’d encountered some run-time error while trying to use traditional Chinese trainnedata (It’s error opening it, so it’s expected the versioning of tesseract and the traineddata is different)

    Thanks for your reply ^.^

    • October 4, 2011 at 10:33 am

      Hi Mikado,
      I beliebe the version I’ve used is v3.01 as it is available since 2010-11-29 and I remember downloading it freshly for the iOS 5 sample. I was looking for some define with the version inside the packaged headers but couldn’t find none.
      I see that tesseract has made available chinese traineddata for version 3.00 and above, have you tried using those?
      Hope it helps, regards

  17. 39 GVH
    October 1, 2011 at 3:25 am

    Awesome stuff! Thanks.

  18. 40 Jerry
    October 12, 2011 at 10:27 am

    I am getting some problems getting tesseract run on the simulator. I have tried a few different scripts to build the libraries but still no luck. When I build it it gives me the following error messages

    Undefined symbols for architecture i386:
    “TessBaseAPI::TesseractRect(unsigned char const*, int, int, int, int, int, int)”, referenced from:
    -[OCRDemoViewController ocrImage:] in OCRDemoViewController.o
    “TessBaseAPI::SimpleInit(char const*, char const*, bool)”, referenced from:
    -[OCRDemoViewController startTesseract] in OCRDemoViewController.o
    ld: symbol(s) not found for architecture i386
    collect2: ld returned 1 exit status

  19. 43 Paul
    October 18, 2011 at 7:43 am

    Hi Suzuki,
    how did you manage to compile opencv with XCode4.2/iOS5 ? it gives plenty of errors… thank you for any feedback from you!
    Paul

  20. October 24, 2011 at 6:54 am

    Hello Suzuki-san,
    I am trying to do something similar with iOS5.0 (compiling tesseract and then nhocr) I downloaded your project but in my $DEVTOOLS/usr/bin I don’t have either gcc-4.2, g++-4.2, cpp-4.2 I have replaced them by gcc, g++ and llvm-cpp-4.2 My configure is still choking though as it is not finding limits.h
    By the way once I am done with tesseract I want to try compiling nhocr in order to compare the 2.
    Waiting for your iOS5.0 article

  21. October 24, 2011 at 7:23 am

    my remaining problem with limits seems to be that the __arm__ preprocessor directive is not defined so in SDKROOT/usr/include/machine/limits.h it tries to find the i386 instead of the arm file.

  22. October 24, 2011 at 9:42 am

    me again, I progressed and the solution was to specify the CPP variable as “$DEVROOT/usr/bin/gcc -E $CPPFLAGS”
    this made sure that an arm compatible c preprocessor was used

  23. 49 venusbai
    October 25, 2011 at 7:36 pm

    Suzuki san:

    I noticed Google-tesseract-project released official 3.01 source code package(tesseract-3.01.tar.gz) 3 days ago with a different configure file.

    (http://code.google.com/p/tesseract-ocr/downloads/list)

    I want to build tesseract base on the newest package.I wonder is there something else need I to do. Which configure should I use? or I should wait you to update the build script.
    Tks!

    • October 26, 2011 at 1:16 pm

      Hi venusbai,

      Tesseract setup script (autogen.sh) and configure script (erhm… configure) have changed and actually got really better, so I could remove some workarounds. I’ve built tesseract 3.01 with leptonica 1.68 on Xcode 4.1 (Lion) and iOS SDK 4.3 with the following script:
      http://goo.gl/BZM8p

      If you’d like to use iOS SDK 5, try changing the IOS_BASE_SDK value and see if it works.

      And… yes, I’ve gotta stop saying I’ll post updates and actually write ‘em. Well, at least I provide some support!

      Regards,
      Suzuki

  24. October 27, 2011 at 2:36 am

    Do you have an Android version of the script?

    Or it will be the same process?

    Thanks.

    • October 27, 2011 at 9:27 am

      Unfortunately I don’t… But I believe you would have to go through the process of compiling for emulation and for devices (guess you’ll have to compile to multiple devices architectures as well).

      It seems to be a nice topic for a new post.

      Good luck with that, meanwhile.

  25. October 31, 2011 at 12:04 am

    @venusbai -> Hi can you share your version of the script? (and perhaps the console output) as well?

    I tried to change the properties : IOS_BASE_SDK=”5.0″ and IOS_DEPLOY_TGT=”5.0″ , but I did not work.

    The dirs leptonica outdir/arm6 , arm7 and i386 were all empty. and tesseract-3.01 did not have a outdir at all.

    I saw things in the console output like:
    cp: ./outdir/lib*.a: No such file or directory
    ./build_dependencies.sh: line 167: cd: /Users/pentateu/Developer/Tesseract-3.01/tesseract-3.01/outdir/i386: No such file or directory

    which look like problems for me.

    Having your console output would help me figure it out what is wrong with my environment.

    I’m using xcode 4.2 with iOS 5 btw.

    • 55 venusbai
      October 31, 2011 at 11:25 pm

      I think you can follow the 7 simple steps what I did:

      1: create an empty folder anywhere and name it whatever you like

      2: download tesseract3.01 source package and save it to the folder you created. and double click it to unpack.
      (http://code.google.com/p/tesseract-ocr/downloads/detail?name=tesseract-3.01.tar.gz&can=2&q=)

      3: download Leptonica 1.68 source package and save it to the floder you created. and double click it to unpack.
      (http://www.leptonica.org/source/leptonica-1.68.tar.gz)

      3: download Suzuki’s build script and save it to the folder you created.
      (http://goo.gl/BZM8p)

      4: check what version SDK of IOS you installed. open “/Developer/Platforms/iPhoneOS.platform/Developer/SDKs”, there is a file whose name is like iPhoneOSx.x.sdk. The x.x is the version number.

      5.if your SDK version number is 4.2 ,skip this step.If not,open the build_dependencies.sh and edit version number at line 9 (IOS_BASE_SDK=”4.2″).and save.

      6.run the build_dependencies.sh from terminal app.

      7.cross your finger.

  26. November 1, 2011 at 5:59 am

    Hi Suzuki,

    I’m using xcode 4.2 and iOS 5.

    I have set the properties IOS_BASE_SDK=”5.0″ and IOS_DEPLOY_TGT=”5.0″ , but it still not compiling properly.

    I had a look at the setenv_all() function in the script and the compiler path did not exist in my machine. I have changed it to be the following:

    #export CPP=”$DEVROOT/usr/bin/cpp-4.2″ //original value
    export CPP=”$DEVROOT/usr/llvm-gcc-4.2/bin/llvm-cpp-4.2″ //there was not a clear match like for the others..

    #export CXX=”$DEVROOT/usr/bin/g++-4.2″ //original value
    export CXX=”$DEVROOT/usr/bin/g++”

    #export CXXCPP=”$DEVROOT/usr/bin/cpp-4.2″ //original value
    export CXXCPP=”$DEVROOT/usr/llvm-gcc-4.2/bin/llvm-cpp-4.2″

    #export CC=”$DEVROOT/usr/bin/gcc-4.2″ //original value
    export CC=”$DEVROOT/usr/bin/gcc”

    The script output shows:
    configure: error: in `/Users/pentateu/Developer/Tesseract-3.01/leptonica-1.68′:
    configure: error: C preprocessor “/Developer/Platforms/iPhoneOS.platform/Developer/usr/llvm-gcc-4.2/bin/llvm-cpp-4.2″ fails sanity check
    See `config.log’ for more details.

    Which lead me to believe the replacement I have done for the /cpp-4.2 might not be right.

    Any ideas?

  27. November 3, 2011 at 3:09 pm

    nice mate.. First and foremost Great to share your knowledge with us.

    Require your suggestion to resolved this issue.

    “tesseract::TessBaseAPI::Init(char const*, char const*, tesseract::OcrEngineMode, char**, int, GenericVector const*, GenericVector const*, bool)”, referenced from:

    Thanks

  28. 61 Danny Van den Heuvel
    November 6, 2011 at 10:34 pm

    I want to port a osx libnodave.so library to ios, is this possible with your configuration

    Thanks in advance,
    Danny

  29. 63 David
    January 25, 2012 at 7:45 pm

    Thanks for writing this! I especially like that you added a lot of detail.

  30. 64 Heinz Peter Posch
    January 28, 2012 at 7:09 pm

    Very nice Project!!!
    But it did not work when i tried it.
    I used the same structure like you but i did not work.
    So would it be possible that you try to Compile the libnodave library?
    The library can be found here: http://sourceforge.net/projects/libnodave/
    It would be great if you could do this and send me the compiled Files.

    Thank you!!!

    • January 28, 2012 at 7:53 pm

      Try downloading the sample project, it contains the pre-compiled binaries.

      About libnodave, try reading its README about how to build and modifying the script I shared to make it work with it.

      Good luck!

      • 66 Heinz Peter Posch
        January 29, 2012 at 8:21 am

        I tried it with that script but it didn’t work..
        Could you send me the files that you compiled for arm7 and i386 ?!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.