开发者

How do I include libxslt in my iPhone app?

I've heard that including libxslt.dylib is grounds for getting your app rejected. I don't know how accurate that is.

Nevertheless, I would like to include the latest version of libxslt. I'开发者_开发问答d like to do the same thing with libxml2, as well as other libraries in the future.

What is the correct way to include a code library like this in my app?


My app was rejected with the following message from Apple.


XYZ app cannot be posted to the App Store because it is using private or undocumented APIs:

Private Symbol References xsltApplyStylesheet xsltCleanupGlobals xsltFreeStylesheet xsltInit xsltParseStylesheetFile xsltSaveResultToString

As you know, as outlined in the iPhone Developer Program License Agreement section 3.3.1, the use of non-public APIs is not permitted. Before your application can be reviewed by the App Review Team, please resolve this issue and upload a new binary to iTunes Connect.


It was my understanding that the libxslt and libxml2 libraries were in fact present on the device and are available via the pull down menu in Xcode. I dynamically link link with these two libraries and my app works beautifully on the device. Hence, the libraries must be on the device. Why would I need to build these libraries from scratch as static libraries and increase the size of my app?

I can't find any clear way to work around this, aside from not using xml and xslt. That makes no sense at all!

Hilton, have you succeeded in submitting an app to iTunes that uses xslt?


I finally got libxslt to build in Xcode, link to my app, and evade the app store rejectionbot.

Basically you have to build libxslt statically and change the symbol names so they don't match the ones that Apple looks for. All symbols xsltFoo() must be changed to zsltFoo(). Also the name of the library itself must be changed from libxslt.a to libzslt.a.

Here's a how to do it in 10 easy steps :)

  1. Create a libxslt subdirectory and put libxslt-1.1.26.tar.gz into it.
  2. Right click on Target -> YourApp and select Add -> New Build Phase -> New Run Script Build Phase
  3. Copy the build script below
  4. Rename the the build phase from "Run Script" to "Build libxslt" and make it first in the list
  5. Build your project, which will cause libxslt to be configured and built and installed in libxslt/dist
  6. Right click on Frameworks and select Add -> Existing Files... and then select libxslt/dist/lib/libzslt.a
  7. Go to Project -> Edit Project Settings -> Build
  8. Under Search Paths, edit Header Search Paths and add libxslt/dist/include
  9. Add #include <libxslt/whatever.h> to your code as needed normally
  10. Use zsltFoo instead of xsltFoo everywhere in your code

Here is the libxslt build script referenced in step #3:

#!/bin/sh

# Setup
LIBXSLT_VERSION="1.1.26"
LIBXSLT_SHA1_CHECKSUM="69f74df8228b504a87e2b257c2d5238281c65154"
GCC_VERSION="4.2.1"
ARCH="arm-apple-darwin10"

# Bail on any error
set -e

# Function that patches a file using sed(1).
# First argument is filename, subsequent arguments are passed to sed(1).
sed_patch_file()
{
    FILE="${1}"
    shift
    sed ${1+"$@"} < "${FILE}" > "${FILE}".new
    if ! diff -q "${FILE}" "${FILE}".new >/dev/null; then
        cat "${FILE}".new > "${FILE}"
    fi
    rm "${FILE}".new
}

# Function that displays the command and then executes it
show_cmd()
{
    echo ${1+"$@"}
    ${1+"$@"}
}

# Dump environment variables
#echo '***************************************************'
#env | sort
#echo '***************************************************'

# Files
SRCBALL="${SOURCE_ROOT}/libxslt/libxslt-${LIBXSLT_VERSION}.tar.gz"
SRCDIR="${SOURCE_ROOT}/libxslt/libxslt-${LIBXSLT_VERSION}"
DISTDIR="${SOURCE_ROOT}/libxslt/dist"

# Verify source is installed
if ! [ -f "${SRCBALL}" ]; then
    echo "ERROR: please download and install ${SRCBALL}" 2>&1
    echo "The SHA1 checksum should be: ${LIBXSLT_SHA1_CHECKSUM}" 2>&1
    exit 1
fi

# Unpack the archive if necessary
if ! [ -e "${SRCDIR}" ]; then

    # Unpack archive
    echo "*** Unpacking archive ${SRCBALL}"
    tar zxf "${SRCBALL}" -C libxslt

    # Rename all symbols xsltFoobar -> zsltFoobar to avoid broken app store link analyzer
    echo "*** Changing symbol names"
    find libxslt/libxslt-"${LIBXSLT_VERSION}" -name '*.[ch]' -print | while read FILE; do
        sed_patch_file "${FILE}" -E 's%([^[:alnum:]_/"]|^)xslt([A-Z])%\1zslt\2%g'
    done

    # Disable build of xsltproc which fails to link
    sed_patch_file libxslt/libxslt-"${LIBXSLT_VERSION}"/Makefile.in -E '/^[[:space:]]xsltproc \\$/d'
fi

# Build and install
if ! [ -e "${DISTDIR}" ]; then

    # Set up autoconf environment variables
    export CPP="${PLATFORM_DEVELOPER_BIN_DIR}/${ARCH}-gcc-${GCC_VERSION} -E"
    export  CC="${PLATFORM_DEVELOPER_BIN_DIR}/${ARCH}-gcc-${GCC_VERSION}"
    export CXX="${PLATFORM_DEVELOPER_BIN_DIR}/${ARCH}-g++-${GCC_VERSION}"
    export CPPFLAGS="-I${SDKROOT}/usr/lib/gcc/${ARCH}/${GCC_VERSION}/include -I${SDKROOT}/usr/include"
    export LDFLAGS="--sysroot=${SDKROOT}"
    export CFLAGS="-Os -pipe ${CPPFLAGS} ${LDFLAGS}"
    export CXXFLAGS="${CFLAGS}"
    export ARCH

    # Configure libxslt
    echo "*** Configuring libxslt-${LIBXSLT_VERSION}"
    ( cd "${SRCDIR}" && show_cmd ./configure \
      --prefix="${DISTDIR}" \
      --build=i386-apple-darwin10 \
      --host="${ARCH}" \
      --enable-static \
      --disable-shared \
      --with-libxml-include-prefix="${SDKROOT}"/usr/include \
      --with-libxml-libs-prefix="${SDKROOT}"/usr/lib \
      --without-python )

    # Build it
    echo "*** Building libxslt-${LIBXSLT_VERSION}"
    ( cd "${SRCDIR}" && show_cmd make )

    # Install it
    echo "*** Installing libxslt-${LIBXSLT_VERSION}"
    ( cd "${SRCDIR}" && show_cmd make install )

    # Change library name to avoid dynamic linking to the iPhone's shared libxslt library
    ln libxslt/dist/lib/lib{x,z}slt.a
fi


Hey Hilton, any chance you could let us know how you managed to statically link the LIBXSLT library into your app please?

I'm having exactly the same issue as quite a few others but at the moment at least, I have no idea how to go about turning the dynamic library into a static one.

Thanks.

EDIT: Check out this Version of XSLT in iPhone

My app was rejected for using LibXSLT so instead I manually added the source code and did it that way. My app was approved a few days ago.


You can only dynamically link to libraries that are already present on the device.

If you want to link to an external library that is not present on the device, you will have to compile it yourself to a static library and link that instead.


Based on Archie's answer, this script (with XCode 5 command line tools) generates a multi-architecture libzslt suitable for inclusion in a project, compatible with iOS 6 and iOS 7 projects (though I haven't included iOS 7 64 bit).

This solution assumes libxslt-1.1.28 is unpacked and in the same directory as the script.

The script creates a directory dependencies which contains the header and lib files. You can include them in an Xcode project by adjusting the header and linker search paths.



    #!/bin/sh
    # build.sh

    GLOBAL_OUTDIR="`pwd`/dependencies"
    LOCAL_OUTDIR="outdir"
    XSLT_LIB="`pwd`/libxslt-1.1.28"

    IOS_BASE_SDK="7.0"
    IOS_DEPLOY_TGT="6.0"

    sed_patch_file()
    {
        FILE="${1}"
        shift
        sed ${1+"$@"}  "${FILE}".new
        if ! diff -q "${FILE}" "${FILE}".new >/dev/null; then
            cat "${FILE}".new > "${FILE}"
        fi
        rm "${FILE}".new
    }

    patch_libxslt() {
        export LIBXSLT_VERSION=1.1.28
        echo "*** Changing symbol names"
        find libxslt-"${LIBXSLT_VERSION}" -name '*.[ch]' -print | while read FILE; do
                sed_patch_file "${FILE}" -E 's%([^[:alnum:]_/"]|^)xslt([A-Z])%\1zslt\2%g'
        done

            # Disable build of xsltproc which fails to link
        sed_patch_file libxslt-"${LIBXSLT_VERSION}"/Makefile.in -E '/^[[:space:]]xsltproc \\$/d'
    }

    setenv_all()
    {
        unset LIBRARIES
        export LIBRARIES=${SDKROOT}/usr/lib
        echo "*** LIBRARIES: ${LIBRARIES}"

        # Add internal libs
        export LDFLAGS="--sysroot=${SDKROOT} $LDFLAGS -L${LIBRARIES}"
        export CFLAGS="--sysroot=${SDKROOT} $CFLAGS -I${SDKROOT}/usr/lib/gcc/${ARCH}/${GCC_VERSION}/include -I${SDKROOT}/usr/include -arch ${ARCH} -Os -pipe ${CPPFLAGS}"

        export CXX="$PLATFORM_BIN_DIR/g++"
        export CC="$PLATFORM_BIN_DIR/gcc"

        export LD=$TOOLROOT/ld
        export AR=$TOOLROOT/ar
        export AS=$TOOLROOT/as
        export NM=$TOOLROOT/nm
        export RANLIB=$TOOLROOT/ranlib
        export CPPFLAGS=$CFLAGS
        export CXXFLAGS=$CFLAGS

        export CXXFLAGS="${CFLAGS}"
    }

    setenv_arm7()
    {
        unset LN DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS DYLD_LIBRARY_PATH ARCH PLATFORM_BIN_DIR TOOLROOT DISTDIR

        export ARCH=armv7
        export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk
        export PLATFORM_BIN_DIR=/Applications/Xcode.app/Contents/Developer/usr/bin
        export TOOLROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin    

        export DYLD_LIBRARY_PATH="$SDKROOT/usr/lib"

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

        setenv_all
    }

    setenv_arm7s()
    {
        unset LN DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS DYLD_LIBRARY_PATH ARCH PLATFORM_BIN_DIR TOOLROOT DISTDIR

        export ARCH=armv7s
        export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneOS$IOS_BASE_SDK.sdk
        export PLATFORM_BIN_DIR=/Applications/Xcode.app/Contents/Developer/usr/bin
        export TOOLROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin    

        export DYLD_LIBRARY_PATH="$SDKROOT/usr/lib"

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

        setenv_all
    }

    setenv_i386()
    {
        unset LN DEVROOT SDKROOT CFLAGS CC LD CPP CXX AR AS NM CXXCPP RANLIB LDFLAGS CPPFLAGS CXXFLAGS DYLD_LIBRARY_PATH ARCH PLATFORM_BIN_DIR TOOLROOT DISTDIR

        export ARCH=i386
        export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer
        export SDKROOT=$DEVROOT/SDKs/iPhoneSimulator$IOS_BASE_SDK.sdk
        export PLATFORM_BIN_DIR=$DEVROOT/usr/bin
        export TOOLROOT=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

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

        setenv_all
    }

    create_outdir_lipo()
    {
        for lib_i386 in `find $LOCAL_OUTDIR/i386 -name "lib*\.a"`; do
            lib_arm7=`echo $lib_i386 | sed "s/i386/arm7/g"`
            lib_arm7s=`echo $lib_i386 | sed "s/i386/arm7s/g"`
            lib=`echo $lib_i386 | sed "s/i386\///g"`
            mkdir -p $(dirname $lib)
            cmd="xcrun -sdk iphoneos lipo -arch armv7 $lib_arm7 -arch i386 $lib_i386 -arch armv7s $lib_arm7s -create -output $lib"
            echo $cmd
            $cmd
        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 -
    }

    #######################
    # libxslt
    #######################

    patch_libxslt

    cd $XSLT_LIB
    rm -rf $LOCAL_OUTDIR
    mkdir -p $LOCAL_OUTDIR/arm7 $LOCAL_OUTDIR/i386

    make clean 2> /dev/null
    setenv_i386

    export DISTDIR=`pwd`/$LOCAL_OUTDIR/i386

    ./configure --prefix="${DISTDIR}" \
    --enable-static \
    --disable-shared \
    --with-libxml-include-prefix="${SDKROOT}"/usr/include \
    --with-libxml-libs-prefix="${SDKROOT}"/usr/lib \
    --without-crypto \
    --without-python || exit
    make "CC=$CC" "CFLAGS=$CFLAGS" "AR=$AR"
    make install

    ln $LOCAL_OUTDIR/i386/lib/lib{x,z}slt.a 

    # find ./ -iname *.a | grep -v $LOCAL_OUTDIR | xargs -L 1 -I '{}' cp '{}' $LOCAL_OUTDIR/i386
    # cp -vf lib*.a $LOCAL_OUTDIR/i386

    make clean 2> /dev/null
    setenv_arm7

    export DISTDIR=`pwd`/$LOCAL_OUTDIR/arm7

    ./configure --prefix="${DISTDIR}" \
    --host=armv7-apple-darwin12.5.0 \
    --enable-static \
    --disable-shared \
    --with-libxml-include-prefix="${SDKROOT}"/usr/include \
    --with-libxml-libs-prefix="${SDKROOT}"/usr/lib \
    --without-crypto \
    --without-python || exit
    make -j4
    make install

    ln $LOCAL_OUTDIR/arm7/lib/lib{x,z}slt.a 

    # find ./ -iname *.a | grep -v $LOCAL_OUTDIR | xargs -L 1 -I '{}' cp '{}' $LOCAL_OUTDIR/arm7
    # cp -rvf lib*.a $LOCAL_OUTDIR/arm7

    make clean 2> /dev/null
    setenv_arm7s

    export DISTDIR=`pwd`/$LOCAL_OUTDIR/arm7s

    ./configure --prefix="${DISTDIR}" \
    --host=armv7s-apple-darwin12.5.0 \
    --enable-static \
    --disable-shared \
    --with-libxml-include-prefix="${SDKROOT}"/usr/include \
    --with-libxml-libs-prefix="${SDKROOT}"/usr/lib \
    --without-crypto \
    --without-python || exit
    make -j4
    make install

    ln $LOCAL_OUTDIR/arm7s/lib/lib{x,z}slt.a 

    # find ./ -iname *.a | grep -v $LOCAL_OUTDIR | xargs -L 1 -I '{}' cp '{}' $LOCAL_OUTDIR/arm7s
    # cp -rvf lib*.a $LOCAL_OUTDIR/arm7s

    create_outdir_lipo
    mkdir -p $GLOBAL_OUTDIR/lib && cp -rvf $LOCAL_OUTDIR/lib/lib*.a $GLOBAL_OUTDIR/lib
    mkdir -p $GLOBAL_OUTDIR/include && cp -rvf $LOCAL_OUTDIR/arm7/include/* $GLOBAL_OUTDIR/include

    cd ..

    echo "Finished!"

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜