在iOS 5上使用libcurl作为NSURLConnection的替代方案

时间:2012-01-27 20:21:16

标签: ios5 nsurlconnection libcurl

更新:NSURLConnection现在似乎正确支持100-Continue。在任何情况下,this answer都包含指向用于为iOS / OSX构建libcurl的脚本的链接。

我在使用NSURLConnection时遇到了一些困难,因为它不支持RFC 2616(HTTP / 1.1)的Section 8.2.3

基本上,客户端需要能够支持发送标头Expect: 100-Continue;发送请求标头后,必须在发送100 / POST正文之前等待来自状态码为PUT的服务器的响应。

此外,NSURLConnection(以及因此构建在其上的所有库)在上传所有数据之前不会从服务器返回任何响应 - 这很痛苦,因为服务器可能会立即拒绝上传(凭证无效,没有空格,文件太大等)。 虽然它对小文件“工作”(内容完全上传,并且调用了带响应的委托方法),但是在大文件上而不是从服务器获取错误响应(我肯定确定) ),我刚刚收到“连接失败”错误。

我知道libcurl正确支持100-Continue规范,所以我需要一些帮助来编译它并在iOS 5项目上运行它。

我从this post开始(滚动到底部),但我无法走远......

做出这些改变......

export CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2
export CFLAGS="-arch armv7 --sysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
export CPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-cpp-4.2
export AR=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar
./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --without-ldap --disable-ldap --host=arm-apple-darwin10 --build=arm-apple-darwin10
make clean
make
ar rv libcurl.armv7.a lib/*.o

...但编译失败并带有消息

(...)
checking for arm-apple-darwin10-gcc... /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2
checking whether the C compiler works... no
configure: error: in `/Users/bruno/Downloads/curl-7.21.4':
configure: error: C compiler cannot create executables

我正在使用从Apple的open source site下载的卷曲7.21.4。

那么,我如何编译curl并在iOS 5项目中使用它,最好是支持SSL?

7 个答案:

答案 0 :(得分:15)

这对我来说最新的SDK:

#!/bin/sh 
export SDK=5.0

buildit()
{
    target=$1
    platform=$2

    export CC=/Developer/Platforms/${platform}.platform/Developer/usr/bin/gcc
    export CFLAGS="-arch ${target} -isysroot /Developer/Platforms/${platform}.platform/Developer/SDKs/${platform}${SDK}.sdk"
    export CPP="/Developer/Platforms/${platform}.platform/Developer/usr/bin/llvm-cpp-4.2"
    export AR=/Developer/Platforms/${platform}.platform/Developer/usr/bin/ar
    export RANLIB=/Developer/Platforms/${platform}.platform/Developer/usr/bin/ranlib

    ./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --without-ldap --disable-ldap \
            --host=${target}-apple-darwin10

    make clean
    make
    $AR rv libcurl.${target}.a lib/*.o
}

buildit armv6 iPhoneOS
buildit armv7 iPhoneOS
buildit i386 iPhoneSimulator

lipo -create libcurl.armv7.a libcurl.armv6.a libcurl.i386.a -output libcurl.a

答案 1 :(得分:9)

获得者的重要更新:C compiler cannot create executables
确保安装命令行XCode工具...

从XCode菜单中选择:Preferences --> downloads --> Command Line Tools

...如果没有安装,请点击“安装”。

上述脚本的问题在于它适用于旧版本的XCode。如果安装了最新的XCode,则所有编译器工具的位置都会不同。我已经更改了脚本以支持旧的和新的XCode版本,并且内置了一些错误检查。这有帮助吗?

下面 - 我假设SDK版本5.1 - 您可能需要修改...

#!/bin/bash

set -e

export SDK=5.1

checkExists() {

    if [ ! -e $1 ]
    then
        echo "Didn't find: $1 -- try to locate parts of this to see how to fix the path"
        exit 1
    else 
        echo "using $1"
    fi

}

buildit() {

    target=$1
    platform=$2

    root="/Applications/Xcode.app/Contents/Developer/Platforms/${platform}.platform/Developer"
    oldRoot="/Developer/Platforms/${platform}.platform/Developer"

    if [ ! -d "${root}" ]
    then
        root="${oldRoot}"
    fi

    if [ ! -d "${root}" ]
    then
        echo " "
        echo "Oopsie.  You don't have an iOS SDK root in either of these locations: "
        echo "   ${root} "
        echo "   ${oldRoot}"
        echo " "
        echo "If you have 'locate' enabled, you might find where you have it installed with:"
        echo "   locate iPhoneOS.platform | grep -v 'iPhoneOS.platform/'"
        echo " "
        echo "and alter the 'root' variable in the script -- or install XCode if you can't find it... "
        echo " "
        exit 1
    fi

    export CC="${root}/usr/bin/gcc"
    export CFLAGS="-arch ${target} -isysroot ${root}/SDKs/${platform}${SDK}.sdk"
    export CPP="${root}/usr/bin/llvm-cpp-4.2"
    export AR="${root}/usr/bin/ar"
    export RANLIB="${root}/usr/bin/ranlib"

    checkExists ${CC}
    checkExists ${root}/SDKs/${platform}${SDK}.sdk
    checkExists ${CPP}
    checkExists ${AR}
    checkExists ${RANLIB}

    ./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --without-ldap --disable-ldap --host=${target}-apple-darwin10

    make clean
    make
    $AR rv libcurl.${target}.a lib/*.o
}

buildit armv6 iPhoneOS
buildit armv7 iPhoneOS
buildit i386 iPhoneSimulator

lipo -create libcurl.armv7.a libcurl.armv6.a libcurl.i386.a -output libcurl.a

答案 2 :(得分:1)

使用sudo执行脚本:

$ sudo library.sh 

我的剧本:

#!/bin/sh 
export SDK=5.0

buildit()
{
    target=$1
    platform=$2

    export CC=/Developer/Platforms/${platform}.platform/Developer/usr/bin/gcc
    export CFLAGS="-arch ${target} -isysroot /Developer/Platforms/${platform}.platform/Developer/SDKs/${platform}${SDK}.sdk"
    export CPP="/Developer/Platforms/${platform}.platform/Developer/usr/bin/llvm-cpp-4.2"
    export AR=/Developer/Platforms/${platform}.platform/Developer/usr/bin/ar
    export RANLIB=/Developer/Platforms/${platform}.platform/Developer/usr/bin/ranlib

    sudo ./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --    without-ldap --disable-ldap \ --host=${target}-apple-darwin10

    make clean
    make
    $AR rv libcurl.${target}.a lib/*.o
}

buildit armv6 iPhoneOS
buildit armv7 iPhoneOS
buildit i386 iPhoneSimulator

lipo -create libcurl.armv7.a libcurl.armv6.a libcurl.i386.a -output libcurl.a

答案 3 :(得分:0)

问题是:

C compiler cannot create executables

原因:

你的iOS C编译器arm-apple-darwin9-gcc是一个交叉编译器:它在PC上运行,但为iDevices生成代码。因此,它无法使用计算机的本机编程资源(库,头文件)。你必须告诉它在哪里可以找到iOS自己的头文件和库。您可以通过传递-isysroot=/path/to/iOS_SDK/选项来完成此操作。例如,以下内容无法开箱即用:

/path/to/arm-apple-darwin10-gcc hello.c -o hello

但以下是:

/path/to/arm-apple-darwin10-gcc -isysroot /Developer/Platforms/iPhoneOS.platform/SDKs/iPhoneOS5.0.1.sdk hello.c -o hello

我不使用Xcode,也没有Mac,所以我不知道iOS工具链sysroot的确切位置,但它可能与上面命令中的类似。

如何在配置中使用所有这些?那么,你有3个编译阶段:预处理,编译和链接。所以你必须告诉预处理器和编译器它在哪里可以找到头,以及链接器在哪里可以找到库。 (特别是,你必须忘记告诉预处理器你的sysroot在哪里)。所以做这样的事情:

export CC=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-gcc-4.2
export CFLAGS="-arch armv7 -isysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
export CPPFLAGS="-isysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
export LDFLAGS="-arch armv7 -isysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk"
export CPP=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/llvm-cpp-4.2
export AR=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ar
./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --without-ldap --disable-ldap --host=arm-apple-darwin10 --build=arm-apple-darwin10
make
sudo make install

答案 4 :(得分:0)

“我仍然得到同样的错误,”C编译器无法创建可执行文件“:|”只需以root身份运行./configure(sudo ./configure ....)

答案 5 :(得分:0)

我已设置a project on GitHub,使用和不使用SSL(GnuTLS和OpenSSL)构建curl(仅限HTTP)。留下了许多评论,所以应该很容易让任何人根据他的特殊需要进行修改。

答案 6 :(得分:0)

这个脚本适用于Xcode 4.4.1环境(请原谅我几乎不存在的sh技能):

#!/bin/sh

#run with sudo

export OSSDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/"
export SIMSDK="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/"
export SDKROOT=$OSSDK
export VER=5.1

buildit()
{
    target=$1
    platform=$2

    export CC="${root}/usr/bin/llvm-gcc-4.2"
    export CFLAGS="-arch ${target} -isysroot=${PLATFORM}/${SDKROOT}/${PLATFORM}${SDK}.sdk"
    export CPPFLAGS="-isysroot=${SDKROOT}/${platform}${SDK}.sdk"
    export LDFLAGS="-arch ${target} -isysroot=${SDKROOT}/${platform}${SDK}.sdk"
    export CPP="${root}/usr/bin/llvm-cpp-4.2"
    export AR="${root}/usr/bin/ar"    
    export RANLIB="${root}/usr/bin/ranlib"

    sudo ./configure --disable-shared --without-ssl --without-libssh2 --without-ca-bundle --without-ldap --disable-ldap --host=arm-apple-darwin10 --build=arm-apple-darwin10

    sudo make clean
    sudo make
    sudo $AR rv libcurl.${target}.a lib/*.o
}

# Run once for armv6 & armv7, then for i386. Comment lines alternatively, as explained below.

# Run for armv6 & armv7 by changing line 6 to "export SDKROOT=$OSSDK". Comment line with "buildit i386..."
#buildit armv6 iPhoneOS
#buildit armv7 iPhoneOS

# Run for i386 by changing line 6 to "export SDKROOT=$SIMSDK". Comment line with buildit "armv6..." and "buildit armv7..."
buildit i386 iPhoneSimulator

sudo lipo -create libcurl.armv7.a libcurl.armv6.a libcurl.i386.a -output libcurl.a