【问题标题】:Using libcurl on iOS 5 as an alternative to NSURLConnection在 iOS 5 上使用 libcurl 作为 NSURLConnection 的替代品
【发布时间】:2012-02-20 19:28:53
【问题描述】:

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

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

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

此外,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

我正在使用 curl 7.21.4,从 Apple 的 open source site 下载。

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

【问题讨论】:

  • 获取最新最好的脚本here。使用 Darwin SSL 编译——没错,原生 iOS/OSX SSL!

标签: ios5 nsurlconnection libcurl


【解决方案1】:

这适用于我使用最新的 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

【讨论】:

  • ranlib 二进制文件有一个小错字(你有“ranib”),除此之外,这是完美的。谢谢!
  • 很好的答案!非常感谢您的回答
【解决方案2】:

重要更新: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

【讨论】:

    【解决方案3】:

    使用 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
    

    【讨论】:

      【解决方案4】:

      问题是:

      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
      

      【讨论】:

      • 感谢您的回答,但这是不行的;我尝试将llvm-gcc-4.2llvm-cpp-4.2 分别替换为arm-apple-darwin10-llvm-gcc-4.2arm-apple-darwin10-llvm-g++-4.2,但我仍然遇到同样的错误,“C 编译器无法创建可执行文件”:|
      • 好吧,如果它不起作用,你为什么指望我们盲目地知道呢?你最好发布configure.log
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        我已经设置了a project on GitHub,它在有和没有 SSL(GnuTLS 和 OpenSSL)的情况下构建 curl(仅适用于 HTTP)。保留了许多 cmets,因此任何人都应该很容易根据自己的特定需求进行修改。

        【讨论】:

          【解决方案7】:

          此脚本适用于 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
          

          【讨论】:

            猜你喜欢
            • 2011-07-07
            • 2018-06-27
            • 2013-05-21
            • 1970-01-01
            • 1970-01-01
            • 2012-02-15
            • 1970-01-01
            • 2016-02-17
            • 2018-03-19
            相关资源
            最近更新 更多