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

91 thoughts on “How To: Cross compiling libraries for iOS (armv6/armv7/i386)

  1. 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.

    1. 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!

      1. hi suzuki,

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

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

    1. 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.

      1. 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?

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

      3. 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?

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

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

    1. Hi Max, thanks for the compliments and… I’m a Brazilian of Japanese descent 😛

      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. Man, thanks for the tip, but after reading your first paragraph i must state openly that you are a freaking TWAT

    1. 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.

    2. 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. 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. 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!

    1. 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

      1. 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.

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

  10. 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

      1. 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!

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

  11. 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”

  12. 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???

    1. 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!

  13. 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 ^.^

    1. 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

  14. 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

    1. Try running lipo to check you library. Example:
      lipo -i /usr/lib/libstdc++.dylib
      Architectures in the fat file: /usr/lib/libstdc++.dylib are: x86_64 i386

  15. 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

  16. 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

  17. 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.

  18. 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

  19. 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!

    1. 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

    1. 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.

  20. @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.

    1. 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.

  21. 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?

    1. @Rafael,
      see my comment above on how to set the CPP variable, I ran into a similar problem cross compiling for iOS5. The solution is to use GCC + the argument which makes it stop after preprocessing (-E)

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

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

    Thanks in advance,
    Danny

  24. 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!!!

    1. 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!

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

  25. 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

    1. 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

  26. 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.

  27. 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 😉

  28. 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?

  29. 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

  30. 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 🙂

  31. 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

    1. 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!!

  32. 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.

    1. 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.

Leave a reply to Suzuki Cancel reply