Compiling external C++ library for use with iOS project

后端 未结 6 1581
滥情空心
滥情空心 2020-11-29 01:49

I\'m completely new to using C++ libraries, so appreciate this might be a bit specific for my case (let me know and I can provide more details).

I have an external

相关标签:
6条回答
  • 2020-11-29 02:02

    Set your architecture back to default then try the following. 1. In Build Phases->Link Binary With Libraries add libz.dylib and libxml2.dylib libraries to your project. 2. In BuildSettings->Search Paths set Always Search User Paths to Yes, and under Framework Search Paths add the correct path of your framework. Use terminal to get the right path of your framework. 3. Try setting your "Compiler Source As" to C++ or use hit and trial and check with all options. Complier Source As is also under BuildSettings. Use cmd+f to search it.

    Try these and let me know, also tell me about the framework or sdk that you are trying to use in your project.

    0 讨论(0)
  • 2020-11-29 02:06

    Considering that you are new with C++ libraries, I guess you will need to do a bit more research.

    However, I will try to outline some steps things you need to take into consideration :

    • you need to make sure you compile for the same architecture both the static library (.a) and the project
    • from your error , you need to compile your static library for i386 OR change your project to x86_64 ( the difference between these architectures is a bit more complex, but for now let's say that i386 means desktop 32 bit while x86_64 means desktop 64 bit)
    • arm architectures are for iPhone , not for your MacOS (that's why it fails to find libraries with arm architecture inside the MacOSX folder) !

    There are multiple ways to approach these issues .

    For the first one I would suggest to include into your workspace the static library, and add it as dependency to your build target . For this you need to understand XCode builds.

    I'm guessing that you actually are trying to make a phone application, so for the 3rd option you need to configure your g++ build to look into the iPhoneSDK from XCode when linking arm targets (look after iPhoneOS.platform) for this.

    Making an arm build will only work on iPhones . If you want it to work on simulator , you will need to link your static library to libraries inside the iPhoneSimulator.platform.

    If you want your static library to work for both iPhones and iPhone simulator, you will need to make a fat lib (basically a library containing symbols for both platforms)

    If you are missing these platforms, you can download them from XCode (but I believe they are there)

    As you can see, things are going to get more and more complex along the way, so I strongly recommend to use XCode for compiling the static library (it is still doable with g++ thou).

    I believe the following concepts you would be useful to research upon :

    • arm, x86 , x86_64
    • static library
    • static linkage
    • fat lib (universal library)
    • XCode workspace with multiple projects

    Hope this helps :).

    0 讨论(0)
  • 2020-11-29 02:08

    Here is what worked for me in Xcode 9 for iOS devices (iPhone X):
    1) Compile dylib with these flags set as the following:
    a) "Installation Directory": @executable_path/Frameworks b) "Runpath Search Path": @executable_path/Frameworks
    See the picture bellow:
    dylib settings in Xcode 9

    2) In the Xcode project where the dylib is used/linked:
    a) "Runpath Search Path":
    @executable_path/Frameworks
    b) In "Build Phase->Embed Libraries" make sure you select "Destination" as "Executables" and Subpath as "Frameworks", "Code sign on copy" checked:
    Setting the the linking iOS app

    This method is tested and used with Xcode 9.2 and iPhone X.

    David

    0 讨论(0)
  • 2020-11-29 02:10

    So I've used many a 3rd party C++ library in my iOS projects. There are different strategies people use for this. As some have already cited, you can include the code within the project directly, build the static lib with Xcode, or build it command line. In the case of cross platform C++ libs which use the GNU configure and build system, I prefer command line. You only need to build it once and you only have to revisit it if you need to update the version or add a new architecture slice.

    The generalized approach you want is:

    • Figure out the right configure arguments to use to build each slice. Typically, you only need to focus on getting one of the arm as well as i386 working. The rest are easy one you have this done. In some cases, you actually need to modify the configure file to add the host or make some other adjustments.

    • Once you can build all slices, you want to run lipo to build a fat binary.

    The best way then to deal with this is create a build script which will do all the work for you. This way, it's easier to redo. More importantly, you can reuse the script or permute it to build other external libs.

    There are many ways you can build the script. Here is one. I happen to have several variations of this type of script. This script was used to build cURL. It more or less worked for presage with very little mod (ie. change curl to presage). Note I didn't test it in Xcode (ie. linking it and running it). I did find that I had to disable sqlite, else it built tool items which don't build right. If you need it, you can figure that part out.

    There are many ways you could make it more slick. For example using an array to store all the architectures. This is just brute force.

    The key points of the script are:

    1. Getting the latest SDK
    2. Building each slice
    3. Then running lipo

    Note that it should work out of the box, however, YMMV. Be prepared to have to debug it if necessary. For example, I haven't confirmed the host type, but generally that is what I've always used. You want to put this at the directory for presage (same directory where configure). When it is done, all architectures are in the output directory. The universal lib is in the presage directory.

    Also remember it is your responsibility to properly link in the universal lib as well as have the header files search path defined properly.

    #!/bin/bash
    
    PLATFORMPATH="/Applications/Xcode.app/Contents/Developer/Platforms"
    TOOLSPATH="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin"
    export IPHONEOS_DEPLOYMENT_TARGET="8.0"
    pwd=`pwd`
    
    findLatestSDKVersion()
    {
        sdks=`ls $PLATFORMPATH/$1.platform/Developer/SDKs`
        arr=()
        for sdk in $sdks
        do
           arr[${#arr[@]}]=$sdk
        done
    
        # Last item will be the current SDK, since it is alpha ordered
        count=${#arr[@]}
        if [ $count -gt 0 ]; then
           sdk=${arr[$count-1]:${#1}}
           num=`expr ${#sdk}-4`
           SDKVERSION=${sdk:0:$num}
        else
           SDKVERSION="8.0"
        fi
    }
    
    buildit()
    {
        target=$1
        hosttarget=$1
        platform=$2
    
        if [[ $hosttarget == "x86_64" ]]; then
            hostarget="i386"
        elif [[ $hosttarget == "arm64" ]]; then
            hosttarget="arm"
        fi
    
        export CC="$(xcrun -sdk iphoneos -find clang)"
        export CPP="$CC -E"
        export CFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
        export AR=$(xcrun -sdk iphoneos -find ar)
        export RANLIB=$(xcrun -sdk iphoneos -find ranlib)
        export CPPFLAGS="-arch ${target}  -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk -miphoneos-version-min=$SDKVERSION"
        export LDFLAGS="-arch ${target} -isysroot $PLATFORMPATH/$platform.platform/Developer/SDKs/$platform$SDKVERSION.sdk"
    
        mkdir -p $pwd/output/$target
    
         ./configure --prefix="$pwd/output/$target" --disable-shared --disable-sqlite --host=$hosttarget-apple-darwin
    
        make clean
        make
        make install
    }
    
    findLatestSDKVersion iPhoneOS
    
    buildit armv7 iPhoneOS
    buildit armv7s iPhoneOS
    buildit arm64 iPhoneOS
    buildit i386 iPhoneSimulator
    buildit x86_64 iPhoneSimulator
    
    LIPO=$(xcrun -sdk iphoneos -find lipo)
    $LIPO -create $pwd/output/armv7/lib/libpresage.a  $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a
    
    0 讨论(0)
  • 2020-11-29 02:22

    The script by Mobile Ben is great, apart from the final line hardcodes a library filename into the script. The following is a replacement for the last lipo command and dynamically uses lipo merges each library file created after compilation.

    Change Mobile Ben's line:

    $LIPO -create $pwd/output/armv7/lib/libpresage.a  $pwd/output/armv7s/lib/libpresage.a $pwd/output/arm64/lib/libpresage.a $pwd/output/x86_64/lib/libpresage.a $pwd/output/i386/lib/libpresage.a -output libpresage.a
    

    to:

    for t in `ls $pwd/output/armv7/lib/*.a` ;
    do
            export LIB=`basename $t`
            export ARCHSTRING=""
            for a in `ls $pwd/output`
            do
                    export ARCSTRING="$ARCSTRING $pwd/output/$a/lib/$LIB "
            done
            $LIPO -create $ARCSTRING  -output $LIB
    done
    

    Note: I didn't want to edit Mobile Ben's answer with new code functionality, and adding this as a comment lost formatting.

    0 讨论(0)
  • 2020-11-29 02:25

    C++ Works on iOS, you can just add it in your project. Or if you really want to have your dynamic library, you can compile it with Xcode and specify your target architecture.

    0 讨论(0)
提交回复
热议问题