Использование libcurl на iOS 5 в качестве альтернативы NSURLConnection

Обновление: теперь NSURLConnection корректно поддерживает 100-Continue. В любом случае этот ответ содержит ссылку на script для сборки libcurl для iOS/OSX.

Мне немного сложно с NSURLConnection, учитывая, что он не поддерживает раздел 8.2.3 RFC 2616 (HTTP/1.1).

В основном клиент должен иметь возможность поддерживать отправку заголовка Expect: 100-Continue; после отправки заголовков запроса он должен дождаться ответа от сервера с кодом состояния 100 перед отправкой телу POST/PUT.

Кроме того, NSURLConnection (и, следовательно, все libs, которые строятся поверх него) не возвратит никакого ответа с сервера до тех пор, пока не будут загружены все данные - это боль, поскольку сервер может сразу же отказаться от загрузки (недействителен учетные данные, отсутствие места, файл слишком большой и т.д.). Хотя он "работает" для небольших файлов (контент полностью загружен и вызывается метод делегата с ответом), на большие файлы вместо получения ответа об ошибке с сервера (который я уверенно уверен,)), Я просто получаю сообщение "Ошибка подключения".

Я знаю, что libcurl правильно поддерживает спецификацию 100-Continue, поэтому мне нужна помощь в ее компиляции и ее запуске и запуске в проекте iOS 5.

Я начал с этот пост (прокрутите вниз), но я не мог далеко продвинуться...

Сделал эти изменения...

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 сайт с открытым исходным кодом.

Итак, как я могу скомпилировать curl и использовать его в проекте iOS 5, желательно с поддержкой SSL?

Ответ 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

Ответ 2

Важное обновление для людей, получающих: C compiler cannot create executables
Убедитесь, что вы установили инструменты командной строки XCode...

В меню XCode выберите: Preferences --> downloads --> Command Line Tools

... и нажмите "Установить", если он не установлен.

Проблема с приведенным выше script заключается в том, что он работает со старыми версиями XCode. Если вы установили последний XCode, расположение всех инструментов компилятора будет иным. Я изменил script, чтобы поддерживать как старые, так и новые версии 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

Выполните script с помощью sudo:

$ sudo library.sh 

my script:

#!/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

Причина:

Ваш компилятор C для iOS, arm-apple-darwin9-gcc, является кросс-компилятором: он работает на ПК, но генерирует код для 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 toolchain 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

Ответ 5

"Я все еще получаю ту же ошибку," компилятор C не может создавать исполняемые файлы ": |" Просто запустите. /configure как root (sudo./configure....)

Ответ 6

Я создал проект на GitHub, который строит curl (только для HTTP) с SSL и без него (GnuTLS и OpenSSL). Осталось много комментариев на месте, поэтому должно быть достаточно легко, чтобы кто-либо мог изменить его в соответствии с его конкретными потребностями.

Ответ 7

Этот script работал у меня со средой 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