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

About these ads

89 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!

      • 3 Shweta
        June 12, 2013 at 11:02 am

        hi suzuki,

        Can you please tell me how to build third party static library for simulator.
        Thanks in advance.

  2. 4 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. 5 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. 7 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.

      • 9 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.

      • 11 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?

      • 12 Benjamin Ng
        November 28, 2012 at 4:00 am

        I figured out how to fix this. When compiling the library or linking it in as a subproject you need to change the header files from private to public to allow the linker the find in the files correctly.

    • 13 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. 14 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. 16 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.

    • April 26, 2013 at 11:17 am

      Hi Max,

      I really appreciate if you could share the steps how did you build leptonica with jpeg ? I tried to build jpeg lib and removed the –without-libjpeg from leptonica configure command line and it didn’t work: when I build my app it complains about undefined symbols (the JPEG ones)

      Also, I take my hat off for Suzuki for his great post !

      Thanks

      Noomen

  7. 19 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. 20 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. 22 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

      • 24 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. 26 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. 28 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

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

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

      • 30 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. 32 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. 36 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. 38 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. 40 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. 42 GVH
    October 1, 2011 at 3:25 am

    Awesome stuff! Thanks.

  18. 43 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. 46 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. 52 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.

    • 58 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. 64 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. 66 David
    January 25, 2012 at 7:45 pm

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

  30. 67 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!

      • 69 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 ?!

  31. 70 John
    April 13, 2012 at 1:01 am

    i can’t for the life of me make this thing compile in xcode 4.3. I’ve installed command line tools in xcode, and changed the devroot path to Applications/Xcode.app/Contents or whatever, but it dies. has anyone had any success compiling for xcode 4.3 or above? if so, please share any changes you made to the build script. Thank you suzuki for your brilliant work! it worked for xcode 4.2, but not anymore. John

    • April 16, 2012 at 10:31 pm

      Make sure you change:

      IOS_BASE_SDK=”5.1″

      and in the appropriate 3 spots of setenv_arm6(), setenv_arm7() and setenv_i386() set the following in their respective places:

      for setenv_arm6() and setenv_arm7():
      export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer

      for setenv_i386():
      export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer

      XCode4.3 only ships with iOS5.1 so the following lines won’t be pointing to valid paths if IOS_BASE_SDK is still set to “5.0”:
      export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk
      export SDKROOT=$DEVROOT/SDKs/iPhoneSimulator$IOS_BASE_SDK.sdk

  32. 73 Dac
    May 10, 2012 at 10:30 am

    Hello,

    First of all: Nice post.

    Please give some hints in order to compile the
    libpcap/tcpdump libraries for iOS.

    I have tried to change your script: “build_dependencies.sh” to
    cross-compile these libraries for iOS, but i did not manage to
    generate the needed library.

    Thanks in advance.

  33. 74 hasan
    July 10, 2012 at 6:31 am

    Hi Suzuki,

    I checked your two posts related to the subject and you were so helpful. Thank you very much.

    I downloaded the opencv header and library files you provided in this post. but it doesn’t work for armv7.

    I believe that you managed to make it work.

    Can you please provide me with the opencv 1.0 header and library files that work for armv7.

    plz plz plz ;)

  34. August 2, 2012 at 6:03 pm

    Hi Suzuki,

    I am just compiling Leptonica.

    I followed this tutorial and the comments on this thread and I was able to compile Leptonica in iOS. I was able to call the getLeptonicaVersion() function and get back the result.

    However when I call pixRead on an image file. I am expect to have a pix returned but I am seeing:

    Error in pixReadStreamPng: function not present
    Error in pixReadStream: png: no pix returned
    Error in pixRead: pix not read

    I am running 1.69 Leptonica in Lion. Any suggestions on this?

  35. September 29, 2012 at 7:55 am

    Hi this is very detailed and well explained post this help me very much.

    I use xcode 4.5 with ios6 sdk And when I try to use the script and compile the libs I get one error like below

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

    And the code is use is at here https://github.com/AalokParikh/Pocket-OCR

    Please help me out

  36. October 1, 2012 at 5:48 am

    Hi your post is great and very helpful.
    But I got one problem with it how I am able to generate lib files compatible with arch armv7s which is the new architecture for ios6?

    So Please help me out :)

  37. 79 Hieu
    April 26, 2013 at 4:25 am

    Hi Suzuki,

    Is there any way to build leptonica to support png or tiff format?

    for example, in your script :

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

    we always build without png or tiff format.

    I change the environ.h and change –with-libpng but it still not work.

    Thanks,
    Hieu

    • June 11, 2013 at 5:43 am

      Know the answer, If we need Leptonica support png, jpeg etc.. for iOS we have to get the source code of the png .. then build for iOS CPU architecture armv6, armv7 or armv7s. that’s it!!

  38. 81 Mike
    April 28, 2013 at 8:48 pm

    Do I copy your configure file into the directory before or after the autogen.sh is ran? I’m finding it’s overriding yours and leaving the check for leptonica?

    Thanks for the help.

    Mike.

    • June 14, 2013 at 12:31 am

      No Need, Mike. The configure is auto generated, if you want to change something you should change in configure.ac. The .ac file is used to generate the configure script file. When we run the build script, it checks and generates the configure script if need.

      If you follow the script of Suzuki, No need to change anything in code. something you should do is update some other versions of Libs or SDK or CPU Architecture.

  39. June 18, 2013 at 12:10 pm

    Thanks Suzuki, you have given me hope. I will try your approach right away tomorrow. And if it works I will link it here.
    http://stackoverflow.com/questions/17169300/how-do-i-make-libtiff-for-an-xcode-project-and-an-ios-application

  40. 84 phiphu
    June 25, 2013 at 12:36 am

    I follow this instruction, and has sucessfully porting Apache Subversion to iphone.

    This is my progress, but in vietnamesse: https://groups.google.com/forum/#!topic/isvnstat/mtfW5XL5zUM


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 )

Google+ photo

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

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: