
简介libcurl 作为应用广泛的跨平台网络传输库支持 HTTP、FTP、SMTP 等协议常被用于 iOS、Android、Windows、Linux 等平台的客户端开发。这份资源面向需要在多端集成 libcurl 的开发者提供了 curl-7.74.0 原生源码包、面向 iOS 的构建脚本 build_libcurl_ios.sh以及配套的 README.md 说明帮助理解 configure/CMake 配置、交叉编译及静态库/动态库生成流程。资源共 3 个文件以 md 文档、gz 源码压缩包、sh 脚本为主压缩包整体仅 3.82MB轻量但覆盖了跨平台编译的典型环节。已有 408 人学习适合希望快速搭建 libcurl 编译环境、或需要在移动端集成 curl 能力的开发者参考。借助源码包与脚本读者可以梳理不同平台的编译选项、SSL/TLS 后端选择以及产物集成方式减少从零摸索的成本。 前阵子帮同事排查一台Windows测试机的问题curl访问内网某个接口始终报curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN。网上方案试了一圈改注册表、刷新系统证书、换代理全都没用。最后一怒之下自己下载libcurl源码换掉schannel后端重新编译了一个curl.exe问题当场消失。那次经历让我意识到一件事对大量开发和运维同学来说curl是每天都在用的工具但libcurl跨平台编译这件事本身还是有点门槛的。尤其是当你需要自定义协议支持、需要静态编译、需要换TLS后端、甚至需要在Linux上交叉编译出Windows版curl时光靠官网下载的安装包是解决不了的。这篇文章把我自己从源码编译libcurl并打包成curl.zip的完整思路、命令和踩坑记录整理出来覆盖Windows原生编译、Linux交叉编译、常见报错排查希望能帮你少走点弯路。1. 为什么放着官方安装包不用非要自己编译1.1 curl、libcurl与编译到底指什么先说清楚一个容易混淆的概念。curl是一个命令行工具我们平时在终端里敲的curl -I https://example.com调用的就是它。而libcurl是curl背后的核心库所有HTTP、FTP、SMTP等协议的解析、传输、TLS握手逻辑都封装在这个库里。curl命令本身只是libcurl的一层薄壳把命令行参数转换成libcurl API调用再把结果打印到终端。所以当你决定从源码编译curl时实际上是在做两件事编译出libcurl库以及编译出依赖libcurl的curl可执行文件。大多数正式项目里这两者是一起构建的但你也可以选择只编译libcurl然后把它链接到你自己的应用程序里。理解了这层关系后面看各种编译参数就不会懵了。1.2 我见过最典型的三个自编译需求官方其实提供了Windows安装包为什么还要自己编译根据我接触过的实际场景核心需求基本集中在三方面。第一需要静态编译。官方Windows版curl默认依赖schannel和系统运行时换了机器可能缺DLL跑不起来。而很多运维同学希望拿到一个独立的curl.exe扔到任何一台Windows Server上都能直接用这就要求把所有依赖都静态编进exe里一个文件搞定一切。第二需要定制功能和协议。默认curl的编译配置是全都要但你生产的瘦身需求可能是只要HTTPS和FTP。反过来如果你需要HTTP/2、brotli压缩、IDN域名支持官方安装包又不一定全带。自己编译可以精确控制功能开关。第三需要换TLS后端。官方Windows版curl走的是schannelWindows自带的TLS实现。schannel本身没问题但遇到某些网关、代理或特殊证书链时确实会出现我开头说的那种TLS协商失败。换用OpenSSL后端重新编译往往是一个绕过问题的有效手段。顺带提一句如果你在Linux上遇到依赖于 curl;然而:未安装软件包 curl这类报错那是系统包管理器缺包apt install curl或者yum install curl就能解决跟你自己编译curl是两码事。自己编译解决的是定制需求不是替代包管理器。2. 编译前先定三件事SSL后端、依赖库、运行时联动2.1 选OpenSSL还是schannel直接决定后续排错难度TLS后端是编译curl时最重要的一个决策点没有之一。Windows平台上有两个主流的TLS后端schannel和OpenSSL。schannel是操作系统自带的最大的好处是编译时不需要额外引入任何第三方库curl.exe拿到就能跑证书的信任链也直接复用Windows系统证书库。但它有两个短板一是TLS行为受系统配置影响大出问题时的排查路径比较黑盒二是它对TLS扩展、会话恢复等细节的控制能力没有OpenSSL那么细。OpenSSL是跨平台的事实标准Linux、macOS、Windows上都长一个样。用OpenSSL作为后端证书管理走自己的证书文件不依赖系统库行为高度可控。代价是编译前必须先编译好OpenSSL并且把生成的DLL或者静态库一起打包分发。我的建议很简单如果只是Windows本地临时用追求零依赖直接用schannel编译省事如果你的curl要部署到生产环境、要长期维护、或者已经遇到了schannel的TLS协商报错果断上OpenSSL后端排查问题的成本会低很多。2.2 依赖库取舍表协议和功能从哪来curl的很多功能不是你编译一下就会有的而是需要提前编译对应依赖库再在编译curl时加上对应的开关。下面这个表我每次搭构建环境都会看一眼依赖库提供能力curl编译选项依赖来源OpenSSLHTTPS、TLSCURL_USE_OPENSSLON / --with-openssl自己编译或vcpkgzlibHTTP压缩传输、文件压缩CURL_ZLIBON / --with-zlib几乎必装nghttp2HTTP/2支持USE_NGHTTP2ON / --with-nghttp2按需brotlibr压缩算法CURL_BROTLION按需c-ares异步DNS解析CARESON / --enable-ares高并发时推荐libssh2SFTP/SCP支持CURL_USE_LIBSSH2ON / --with-libssh2按需我个人建议最基础的组合是OpenSSL zlib。其他库等有明确需求再加不要一上来全开不然光是打通依赖关系就能耗掉一整天。2.3 静态编译是一个exe走天下的前提这里说的静态有两个层面经常被混在一起。第一个层面是libcurl本身静态还是动态。静态时libcurl的代码直接编进curl.exe里动态时curl.exe依赖libcurl.dll。第二个层面是C运行时CRT静态还是动态。MSVC环境下动态CRT编译出的exe在目标机器上需要VC运行库比如vcruntime140.dll、msvcp140.dll老的Windows Server上没有就得现装。要做好一个exe走天下两个层面都得静态BUILD_SHARED_LIBSOFF加上CMAKE_MSVC_RUNTIME_LIBRARYMultiThreaded。如果只把libcurl编成静态CRT还是动态的换台干净机器照样报错。这个坑我最早踩过curl.exe从自己开发机拷到服务器直接提示无法启动因为找不到VCRUNTIME140.dll后来重新用全静态参数编了一版才消停。3. Windows本地编译CMake与winbuild两条路3.1 推荐路线VS CMake依赖少、参数透明现在的curl版本对CMake支持非常成熟这也是我最推荐的Windows本地编译方式。前提是你装了Visual Studio 2019或2022并且勾选了C桌面开发组件CMake工具会自动带上。从源码编译的完整流程是这样git clone https://github.com/curl/curl.git cd curl git checkout curl-8_10_1 cmake -B build -DCMAKE_BUILD_TYPERelease -DCURL_USE_OPENSSLON -DCURL_ZLIBON -DBUILD_SHARED_LIBSOFF -DCURL_DISABLE_LDAPON cmake --build build --config Release逐个解释一下参数。CURL_USE_OPENSSLON指定TLS后端为OpenSSL。CURL_ZLIBON打开zlib压缩支持。BUILD_SHARED_LIBSOFF关键让curl和libcurl都走静态编译。CURL_DISABLE_LDAPON是经验之谈Windows下LDAP支持偶尔会引入依赖问题不太用LDAP协议的可以直接关掉省去不少麻烦。这里的隐形成本是OpenSSL从哪来。如果没有现成的OpenSSL库CURL_USE_OPENSSLON编译到最后会报找不到头文件。两个解决办法要么先编译安装OpenSSL并把路径通过OPENSSL_ROOT_DIR指给CMake要么用vcpkg统一管理依赖vcpkg install openssl:x64-windows-static装好后再编译CMake会自动识别。如果你不想折腾OpenSSL就想先跑通一个能用的curl.exe把上面命令里的-DCURL_USE_OPENSSLON换成-DCURL_USE_SCHANNELON就行不需要任何外部依赖编出来就能用。3.2 传统路线winbuild nmake老派做法是走源码自带的winbuild目录用nmake编译。这个方法不需要CMake只要在Visual Studio的开发者命令提示符里执行cd winbuild nmake /f Makefile.vc modestatic MACHINEx64 WITH_SSLstatic WITH_ZLIBstatic ENABLE_IDNyesmodestatic决定编译出静态版MACHINEx64表示64位WITH_SSLstatic和WITH_ZLIBstatic表示静态链接OpenSSL和zlib。这里的前提同样是你机器上有可用的OpenSSL和zlib库winbuild并不会自动下载依赖。winbuild的好处是命令短、参数也不算复杂CI脚本里写起来方便。缺点是它没有CMake那种灵活的依赖检测机制遇到问题时的报错信息也比较粗糙。我现在的习惯是快速验证用winbuild正式构建走CMake。两条路产出的文件路径略有不同winbuild默认在builds目录下按配置生成子目录CMake则在build/src/Release和build/lib/Release下找的时候稍微留意一下。3.3 编译产物与自检命令编译完成后第一件事是检查版本和功能开关curl.exe --version输出大概长这样curl 8.10.1 (x86_64-pc-win32) release-Debug Release-Date: 2024-09-18 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ws wss Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe TLS-SRP UnixSocketsProtocols列表里有你关心的http、https、ftp就算基本成功。再验证一下TLS功能是否正常随便打一个HTTPS的HEAD请求curl.exe -I https://curl.se如果能正常返回响应头说明TLS链路通了。若报证书错误多半是缺CA证书文件后面的章节会专门讲。4. Linux交叉编译Windows版curl省一台Windows机器的玩法4.1 为什么交叉编译是一套干净的构建方式很多团队的实际状况是开发、CI全在Linux上Windows只是作为最终部署目标。为了一次编译就出一版Windows的curl.exe没必要专门搭一台Windows构建机用MinGW-w64工具链在Linux上交叉编译即可。我对交叉编译的评价是门槛稍高但构建环境非常干净。它不依赖Windows上的任何SDK和IDE所有工具链都是Linux软件包适合放进CI流水线跑一次出一版。另外交叉编译天然强迫你把依赖库也按Windows目标编译一遍这反而促使你理清楚整个依赖链路。4.2 交叉编译的具体操作与依赖坑Debian/Ubuntu系装工具链sudo apt update sudo apt install gcc-mingw-w64-x86-64接着下载curl源码解压后执行configurewget https://curl.se/download/curl-8.10.1.tar.gz tar xzf curl-8.10.1.tar.gz cd curl-8.10.1 ./configure --hostx86_64-w64-mingw32 --buildx86_64-linux-gnu --disable-shared --enable-static --without-ssl make参数的含义--host指定目标运行平台是64位Windows--build指定当前构建平台是Linux。这两个参数缺一不可configure脚本要靠它们判断用什么编译器和生成什么格式的产物。--without-ssl是这里的关键取舍交叉编译时如果带上OpenSSL你必须先把OpenSSL也交叉编译成Windows版本然后把路径传给configure这通常是最折腾的部分。初次尝试建议先不加SSL把基本流程跑通再回头补OpenSSL。依赖库交叉编译的原则只有一句话所有依赖库的目标平台必须和curl一致。你在Linux本机apt装一个OpenSSL那是给Linux用的链接进Windows的curl.exe里只会得到一堆格式错误。要么用MinGW的交叉编译工具链重新编这些库要么用已有的Windows预编译库。4.3 在Linux上快速验证Windows版curl交叉编译出来的exe没法直接执行但可以用wine在Linux上跑起来wine src/curl.exe --versionwine的兼容性对这种轻量命令行程序一般都没问题。如果没有装wine也可以通过file命令确认产物格式file src/curl.exe看到输出里带PE32 executable (console) x86-64就说明确实是Windows的64位程序。至于功能层面的验证建议还是把exe拷到真正的Windows机器上跑一轮wine环境毕竟不能100%模拟Windows系统行为尤其是TLS证书这类和系统环境强相关的功能。5. 编译完之后必查的报错坑DLL缺失、schannel证书、DNS、连接重置5.1 动态编译的经典遗留问题DLL缺失自己编译curl后最常见的第一个问题不是编译报错而是编译成功了但运行时起不来。症状是双击或调用curl.exe时弹出找不到libcurl.dll或者VCRUNTIME140.dll缺失。根因基本就是选择了动态编译或者动态CRT。检查方法很简单用Dependency Walker或者Process Explorer看curl.exe的DLL依赖会发现libcurl.dll、libssl-3-x64.dll这类文件不在exe所在目录也不在系统搜索路径里。解决办法有两个方向如果你明确要做单exe分发按上一章说的全静态参数重新编一版如果只是本地开发环境用把对应的DLL拷到curl.exe旁边即可OpenSSL 3.x对应的是libssl-3-x64.dll和libcrypto-3-x64.dll。5.2 (35)开头的SSL报错换个后端经常直接解决排错过程中SSL/TLS层的报错最让人头疼因为信息量少、变数多。整理一下我实际遇到和见过的几类报错信息常见场景排查方向curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKENschannel后端访问特定服务器/网关尝试OpenSSL后端编译更新系统TLS配置curl: (35) TCP connection reset by peerTLS握手阶段连接被重置检查中间设备/防火墙尝试降低TLS版本curl: (35) recv failure: connection reset by peer下载传输中被断开网络链路问题代理干扰换HTTP/1.1重试curl: (60) SSL certificate problem证书链不受信任更新CA证书或指定 --cacert注意到没有(35)这个错误码横跨了schannel的TLS协商失败和TCP层重置两者的本质完全不同。schannel的SEC_E_INVALID_TOKEN我开头说过了用OpenSSL后端通常能绕开。而TCP connection reset by peer往往和TLS后端无关是TCP层就被重置了多半是网络设备或者代理的问题这时候与其换编译参数不如先用--http1.1、--tlsv1.2这类参数改变握手行为或者检查目标地址是否可达。5.3 DNS解析失败与c-ares的关系curl: (6) couldnt resolve host name这条报错热词里频繁出现典型的例子就是访问https://mirrors.almalinux.org时解析不了域名。很多人以为是编译问题其实大部分时候是DNS配置问题。先确认两点系统能不能ping通这个域名对应的IPnslookup返回的DNS服务器是否正常。如果系统本身就解析不了curl怎么编译都没用。但有一个例外值得了解如果你在高并发场景下频繁进行短连接请求同步DNS解析会成为瓶颈。此时可以在编译curl时启用c-ares异步DNS库让DNS解析不阻塞主流程。开启方式是-DCARESONCMake或--enable-aresconfigure。编出来后curl --version的Features里会多出AsynchDNS一项这种优化不是解决解析不了的问题而是解决解析太慢的问题别搞混了。6. 打包curl.zip的个人习惯哪些文件必须带6.1 一个干净的curl.zip里应该有什么把curl.exe编出来只是第一步真正要交付给团队的通常是一个压缩包比如curl.zip。我见过不少人费劲编好了exe结果拷给别人用的时候当场报错其实就是打包时漏了东西。我自己的打包清单分两种情况。如果你编译的是全静态版那很简单一个curl.exe就够了最多加一个README说明版本和编译参数。如果你编译的是动态版按我的OpenSSL zlib组合至少得包含curl.exelibcurl.dll或libcurl-x64.dll取决于构建系统命名libssl-3-x64.dlllibcrypto-3-x64.dllzlib1.dll如果还启用了nghttp2或brotli对应DLL也一并带上。整理好之后用PowerShell压缩Compress-Archive -Path curl.exe, libcurl.dll, libssl-3-x64.dll, libcrypto-3-x64.dll, zlib1.dll, ca-bundle.crt -DestinationPath curl.zip6.2 证书文件ca-bundle.crt别漏掉这是OpenSSL后端最容易踩的坑。用schannel的curl不需要额外的证书文件因为它直接读Windows系统证书库。换成OpenSSL后程序不会自动读取系统证书库而是需要你提供一个CA根证书集合文件通常叫ca-bundle.crt。如果不提供访问HTTPS网站时会直接报curl: (60) SSL certificate problem: unable to get local issuer certificate。解决方式有两种。一是从curl官网的CA证书页面下载现成的ca-bundle.crt放到curl.exe同级的目录二是如果你能确定所在组织的内部CA也可以把内部根证书追加进这个文件中。总之OpenSSL后端把证书管理和程序分离了这个文件的发放要纳入你的分发流程。6.3 几个值得长期保留的构建经验最后分享几个在这件事上反复验证过的个人习惯。第一把你的构建命令写成脚本保存下来。CMake参数一多过两个月真的会忘。我在项目里维护了一个build-curl-win.bat每次更新版本只需要改版本号然后双击执行生成的zip包统一带上版本号命名。第二在源码目录里保留一个编译记录文件记录当时的工具链版本、依赖库版本、编译参数。这样引入到新环境时可以复现完全一致的构建。看似麻烦但排查线上问题时会谢天谢地。第三如果条件允许同时维护 schannel 和 OpenSSL 两个版本的构建。schannel版作为默认快速分发版OpenSSL版专门应对TLS兼容性疑难杂症。实际维护成本也就多跑一遍脚本但你在现场排查问题时手里有两个不同TLS后端的版本进退余地会大很多。根据我个人的经验libcurl跨平台编译这件事最难的不是编译本身而是搞清楚自己到底需要什么要静态还是动态、要哪个TLS后端、要哪些协议支持。把这些决策在动手前定清楚后面的命令执行其实都很快。希望这篇整理能让你少踩几个我已经踩过的坑。本文还有配套的精品资源点击获取