Mac下编译libcurl静态库

mac开发 18-10-01 17:56 3158  

1.背景 因为项目原因,需要为ios版本提供一个sdk版本,而这个sdk库中使用到了curl,为了完成这个ios sdk,需要编译一个ios环境下的libcurl库。 因为libcurl库的问题,在mac下编译出来的32和64位版本有兼容性问题,头文件都有不一样的地方,导致使用报错。另外mac环境下的各个cpu架构的支持和真机/模拟器的区别也给sdk的工作增加了难度。 2.libcurl编译脚本 经过各方比较后,最后这里介绍的方法最有效,不过也有几个小问题,需要做几点修改。为了防止链接失效,将基于他修改的ios编译脚本如下: #!/bin/sh # Automatic build script for libcurl # for iPhoneOS and iPhoneSimulator # # Created by Rockee on 2012-7-26. # Copyright 2012 Rockee. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ########################################################################### # Change values here # # # VERSION="7.40.0" # SDKVERSION=`xcrun -sdk iphoneos --show-sdk-version` # DEVELOPER=`xcode-select -print-path` # ARCHS="i386 x86_64 armv7 armv7s arm64" # # # ########################################################################### # # # Don't change anything under this line! # # # ########################################################################### xcodebuild -version #developer root path xcode-select -print-path #developer sdk version xcrun -sdk iphoneos --show-sdk-version xcrun -sdk iphonesimulator --show-sdk-version #developer sdk path xcrun -sdk iphoneos --show-sdk-path xcrun -sdk iphonesimulator --show-sdk-path #developer cmd path xcrun --sdk iphoneos --find gcc xcrun --sdk iphoneos --find clang++ ########################################################################### # # # # # Build oppenSSL # # # echo "##################################################################" # echo "########################## Build openSSL #########################" # ./ios-build-libssl.sh # echo "########################## Build openSSL End!#####################" # echo "##################################################################" # # # # # ########################################################################### echo "##################################################################" echo "########################## Build libcurl #########################" CURRENTPATH=$(pwd) #获取当前目录绝对路径 echo "--OK!------ 当前目录:${CURRENTPATH}" SSLPATH="${CURRENTPATH}/OpenSSL" echo "--OK!------ 第三方库:${SSLPATH}" mkdir -p "Curl" cd "Curl" CURRENTPATH=$(pwd) #获取当前目录绝对路径 echo "--OK!------ 当前目录:${CURRENTPATH}" #判断是否安装Xcode.app if [ ! \( -d "$DEVELOPER" \) ] ; then echo "--ERR:------ 编译工具:The iPhone SDK could not be found.Folder: \"$DEVELOPER\" does not exist." exit 1 else echo "--OK!------ 编译工具:The iPhone SDK be found!!" fi set -e #判断当前目录下是否有curl-VERSION.tar.gz压缩包 if [ ! -e curl-${VERSION}.tar.gz ] ; then echo "--OK!------ 下载文件:curl-${VERSION}.tar.gz" curl -O https://curl.haxx.se/download/curl-${VERSION}.tar.gz else echo "--OK!------ 使用文件:curl-${VERSION}.tar.gz" fi mkdir -p "${CURRENTPATH}/src" mkdir -p "${CURRENTPATH}/bin" mkdir -p "${CURRENTPATH}/lib" echo "--OK!------ 创建目录:${CURRENTPATH}/src" echo "--OK!------ 创建目录:${CURRENTPATH}/bin" echo "--OK!------ 创建目录:${CURRENTPATH}/lib" tar zvxf curl-${VERSION}.tar.gz -C "${CURRENTPATH}/src" #将压缩包解压缩到src下 echo "--OK!------ 解压文件:curl-${VERSION}.tar.gz到${CURRENTPATH}/src" cd "${CURRENTPATH}/src/curl-${VERSION}" #进入到curl文件夹下 echo "--OK!------ 进入目录:${CURRENTPATH}/src/curl-${VERSION}" #获取当前目录绝对路径 BUILDPATH=$(pwd) echo "--OK!------ 当前目录:${BUILDPATH}" for ARCH in ${ARCHS} do echo "##################BUILDIT(${ARCH} , ${ARCH})##################" export IPHONEOS_DEPLOYMENT_TARGET="7.0" export CROSS_TOP="${DEVELOPER}/Platforms/${PLATFORM}.platform/Developer" export CROSS_SDK="${PLATFORM}${SDKVERSION}.sdk" export BUILD_TOOLS="${DEVELOPER}" if [[ "${ARCH}" == "i386" || "${ARCH}" == "x86_64" ]]; then echo "##################BUILDIT(${ARCH} , ${ARCH})##################" PLATFORM="iPhoneSimulator" SDKTYPE="iphonesimulator" export CC=$(xcrun --sdk $SDKTYPE --find gcc) export CXX=$(xcrun --sdk $SDKTYPE --find clang++) export CFLAGS="-arch ${ARCH} -pipe -Os -gdwarf-2 -isysroot $(xcrun --sdk $SDKTYPE --show-sdk-path) -mios-simulator-version-min=$IPHONEOS_DEPLOYMENT_TARGET" export LDFLAGS="-L${SSLPATH}/bin/${platform}${SDK}-${target}.sdk/lib" export PKG_CONFIG_PATH="${SSLPATH}/bin/${platform}${SDK}-${target}.sdk/lib/pkgconfig" mkdir -p "${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk" LOG="${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/build-curl-${VERSION}.log" ./configure --without-libidn --disable-shared --enable-static --host="${ARCH}-apple-darwin" --with-ssl=$SSLPATH --prefix="${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/" > "${LOG}" 2>&1 else PLATFORM="iPhoneOS" SDKTYPE="iphoneos" export CC=$(xcrun --sdk $SDKTYPE --find gcc) export CXX=$(xcrun --sdk $SDKTYPE --find clang++) export CFLAGS="-arch ${ARCH} -pipe -Os -gdwarf-2 -isysroot $(xcrun --sdk $SDKTYPE --show-sdk-path) -miphoneos-version-min=$IPHONEOS_DEPLOYMENT_TARGET" export LDFLAGS="-L${SSLPATH}/bin/${platform}${SDK}-${target}.sdk/lib" export PKG_CONFIG_PATH="${SSLPATH}/bin/${platform}${SDK}-${target}.sdk/lib/pkgconfig" mkdir -p "${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk" LOG="${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/build-curl-${VERSION}.log" if [[ "${ARCH}" = "arm64" ]]; then ./configure --without-libidn --disable-shared --enable-static --enable-threaded-resolver --host="aarch64-apple-darwin" --with-ssl=$SSLPATH --prefix="${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/" > "${LOG}" 2>&1 else ./configure --without-libidn --disable-shared --enable-static --enable-threaded-resolver --host="${ARCH}-apple-darwin" --with-ssl=$SSLPATH --prefix="${CURRENTPATH}/bin/${PLATFORM}${SDKVERSION}-${ARCH}.sdk/" > "${LOG}" 2>&1 fi fi make #make -j `sysctl -n hw.logicalcpu_max` cp lib/.libs/libcurl.a ../../bin/libcurl-${ARCH}.a make clean echo "--OK!------ Install bin/libcurl-${ARCH}.a OK!" echo "################BUILDIT(${target} , ${platform}) End!################" echo "#####################################################################" done echo "--OK!------ ############################################################" echo "--OK!------ Build library..." #归档公用库 #lipo -create ${CURRENTPATH}/bin/libcurl.armv7.a ${CURRENTPATH}/bin/libcurl.i386.a -output ${CURRENTPATH}/lib/libcurl.a LIBCURL_SRC="" for ARCH in ${ARCHS} do if [[ "${ARCH}" == "i386" || "${ARCH}" == "x86_64" ]]; then LIBCURL_SRC="${LIBCURL_SRC}${CURRENTPATH}/bin/libcurl-${ARCH}.a " else LIBCURL_SRC="${LIBCURL_SRC}${CURRENTPATH}/bin/libcurl-${ARCH}.a " fi done lipo -create ${LIBCURL_SRC} -output ${CURRENTPATH}/lib/libcurl.a mkdir -p ${CURRENTPATH}/include cp -R ${BUILDPATH}/include ${CURRENTPATH}/ echo "--OK!------ Building done." echo "--OK!------ Cleaning up..." rm -rf ${CURRENTPATH}/src/curl-${VERSION} echo "--OK!------ Done." echo "--OK!------ ############################################################" 修改处如下: find clang 修改成 find gcc,不然会报错 curl拉取官网curl源代码包的使用改用https协议 使用以上脚本,编译出来的libcurl是ios全平台包。 3. array with a negative size 问题解决 由于libcurl存在32和64位编译出来兼容性问题,交叉使用可能会导致如下报错: '__curl_rule_01__' declared as an array with a negative size 最后发现是需要一个整合的curlbuild.h文件才能兼容,可以直接采用这里的curlbuild.h替换本地的对应文件,不过注意我是用的curl7.40版本,没测试过其他版本是否有兼容性问题。 curlbuild.h内容如下: /* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ #ifndef __CURL_CURLBUILD_H #define __CURL_CURLBUILD_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://curl.haxx.se/docs/copyright.html. * * You may opt to use, copy, modify, merge, publish, distribute and/or sell * copies of the Software, and permit persons to whom the Software is * furnished to do so, under the terms of the COPYING file. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ***************************************************************************/ /* ================================================================ */ /* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ /* ================================================================ */ /* * NOTE 1: * ------- * * Nothing in this file is intended to be modified or adjusted by the * curl library user nor by the curl library builder. * * If you think that something actually needs to be changed, adjusted * or fixed in this file, then, report it on the libcurl development * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ * * This header file shall only export symbols which are 'curl' or 'CURL' * prefixed, otherwise public name space would be polluted. * * NOTE 2: * ------- * * Right now you might be staring at file include/curl/curlbuild.h.in or * at file include/curl/curlbuild.h, this is due to the following reason: * * On systems capable of running the configure script, the configure process * will overwrite the distributed include/curl/curlbuild.h file with one that * is suitable and specific to the library being configured and built, which * is generated from the include/curl/curlbuild.h.in template file. * */ /* ================================================================ */ /* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ /* ================================================================ */ #ifdef CURL_SIZEOF_LONG #error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined #endif #ifdef CURL_TYPEOF_CURL_SOCKLEN_T #error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined #endif #ifdef CURL_SIZEOF_CURL_SOCKLEN_T #error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined #endif #ifdef CURL_TYPEOF_CURL_OFF_T #error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined #endif #ifdef CURL_FORMAT_CURL_OFF_T #error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined #endif #ifdef CURL_FORMAT_CURL_OFF_TU #error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined #endif #ifdef CURL_FORMAT_OFF_T #error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined #endif #ifdef CURL_SIZEOF_CURL_OFF_T #error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined #endif #ifdef CURL_SUFFIX_CURL_OFF_T #error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined #endif #ifdef CURL_SUFFIX_CURL_OFF_TU #error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined #endif /* ================================================================ */ /* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ /* ================================================================ */ #ifdef __LP64__ /* Configure process defines this to 1 when it finds out that system */ /* header file ws2tcpip.h must be included by the external interface. */ /* #undef CURL_PULL_WS2TCPIP_H */ #ifdef CURL_PULL_WS2TCPIP_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif # include <windows.h> # include <winsock2.h> # include <ws2tcpip.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/types.h must be included by the external interface. */ #define CURL_PULL_SYS_TYPES_H 1 #ifdef CURL_PULL_SYS_TYPES_H # include <sys/types.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file stdint.h must be included by the external interface. */ /* #undef CURL_PULL_STDINT_H */ #ifdef CURL_PULL_STDINT_H # include <stdint.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file inttypes.h must be included by the external interface. */ /* #undef CURL_PULL_INTTYPES_H */ #ifdef CURL_PULL_INTTYPES_H # include <inttypes.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/socket.h must be included by the external interface. */ #define CURL_PULL_SYS_SOCKET_H 1 #ifdef CURL_PULL_SYS_SOCKET_H # include <sys/socket.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/poll.h must be included by the external interface. */ /* #undef CURL_PULL_SYS_POLL_H */ #ifdef CURL_PULL_SYS_POLL_H # include <sys/poll.h> #endif /* The size of `long', as computed by sizeof. */ #define CURL_SIZEOF_LONG 8 /* Integral data type used for curl_socklen_t. */ #define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t /* The size of `curl_socklen_t', as computed by sizeof. */ #define CURL_SIZEOF_CURL_SOCKLEN_T 4 /* Data type definition of curl_socklen_t. */ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; /* Signed integral data type used for curl_off_t. */ #define CURL_TYPEOF_CURL_OFF_T long /* Data type definition of curl_off_t. */ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; /* curl_off_t formatting string directive without "%" conversion specifier. */ #define CURL_FORMAT_CURL_OFF_T "ld" /* unsigned curl_off_t formatting string without "%" conversion specifier. */ #define CURL_FORMAT_CURL_OFF_TU "lu" /* curl_off_t formatting string directive with "%" conversion specifier. */ #define CURL_FORMAT_OFF_T "%ld" /* The size of `curl_off_t', as computed by sizeof. */ #define CURL_SIZEOF_CURL_OFF_T 8 /* curl_off_t constant suffix. */ #define CURL_SUFFIX_CURL_OFF_T L /* unsigned curl_off_t constant suffix. */ #define CURL_SUFFIX_CURL_OFF_TU UL #else /* __LP64__ */ /* Configure process defines this to 1 when it finds out that system */ /* header file ws2tcpip.h must be included by the external interface. */ /* #undef CURL_PULL_WS2TCPIP_H */ #ifdef CURL_PULL_WS2TCPIP_H # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif # include <windows.h> # include <winsock2.h> # include <ws2tcpip.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/types.h must be included by the external interface. */ #define CURL_PULL_SYS_TYPES_H 1 #ifdef CURL_PULL_SYS_TYPES_H # include <sys/types.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file stdint.h must be included by the external interface. */ #define CURL_PULL_STDINT_H 1 #ifdef CURL_PULL_STDINT_H # include <stdint.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file inttypes.h must be included by the external interface. */ #define CURL_PULL_INTTYPES_H 1 #ifdef CURL_PULL_INTTYPES_H # include <inttypes.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/socket.h must be included by the external interface. */ #define CURL_PULL_SYS_SOCKET_H 1 #ifdef CURL_PULL_SYS_SOCKET_H # include <sys/socket.h> #endif /* Configure process defines this to 1 when it finds out that system */ /* header file sys/poll.h must be included by the external interface. */ /* #undef CURL_PULL_SYS_POLL_H */ #ifdef CURL_PULL_SYS_POLL_H # include <sys/poll.h> #endif /* The size of `long', as computed by sizeof. */ #define CURL_SIZEOF_LONG 4 /* Integral data type used for curl_socklen_t. */ #define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t /* The size of `curl_socklen_t', as computed by sizeof. */ #define CURL_SIZEOF_CURL_SOCKLEN_T 4 /* Data type definition of curl_socklen_t. */ typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; /* Signed integral data type used for curl_off_t. */ #define CURL_TYPEOF_CURL_OFF_T int64_t /* Data type definition of curl_off_t. */ typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; /* curl_off_t formatting string directive without "%" conversion specifier. */ #define CURL_FORMAT_CURL_OFF_T "lld" /* unsigned curl_off_t formatting string without "%" conversion specifier. */ #define CURL_FORMAT_CURL_OFF_TU "llu" /* curl_off_t formatting string directive with "%" conversion specifier. */ #define CURL_FORMAT_OFF_T "%lld" /* The size of `curl_off_t', as computed by sizeof. */ #define CURL_SIZEOF_CURL_OFF_T 8 /* curl_off_t constant suffix. */ #define CURL_SUFFIX_CURL_OFF_T LL /* unsigned curl_off_t constant suffix. */ #define CURL_SUFFIX_CURL_OFF_TU ULL #endif /* __LP64__ */ #endif /* __CURL_CURLBUILD_H */ 如此编译好libcurl.a库文件, 且替换好curlbuild.h后,即可添加到自己的xcode工程中使用。 4.array with a negative size问题的另外一个解决尝试 另外 问题也可以采用如下方式尝试解决: 在curlbuild.h文件中,将以下代码: #define CURL_SIZEOF_LONG 4 替换成 #ifdef __arch64__ #define CURL_SIZEOF_LONG 8 #else #define CURL_SIZEOF_LONG 4 #endif 5.libcurl另外的编译脚本选择 有2个另外的编译脚本看起来靠谱,但是未测试过,如下: https://raw.githubusercontent.com/sinofool/build-libcurl-ios/master/build_libcurl_dist.sh https://raw.githubusercontent.com/fenglc/build-libcurl-for-ios/master/build.sh

2019-03-05 17:31

请教一下,按照您写的全部走下来,编译什么都没问题,您遇到过 iOS9.3 IPhone5s (目前测试iphone6 iOS12正常)一调用libcurl 就崩溃的情况么,谢谢您的回答!