准备工作
ActivePerl (5.26.0.2600 x64)
Nasm (2.13.02 x64)
OpenSSL (1.1.0g)
Curl (7.57.0)
https://curl.haxx.se/download.html
开始编译
使用vs的cmd工具,在开始菜单中可以找到,vs2017是图中这个。我们编译的是x86版,x64的自己换。vs的专用控制台带有编译环境变量,所以不能直接使用系统自带的cmd。对于旧版vs没有这个工具,他提供的是一个名叫vcvars32.bat的批处理,在系统cmd中运行下就好。
英文:x86 Native ToolsCommand Prompt for VS 2017
中文:适用于 VS 2017 的 x86 本机工具命令提示
我们首先编译OpenSSL,从控制台中进入到代码根目录,我的目录如图所示
perl E:\C++库\源码\openssl-3.0.0-alpha5\openssl-3.0.0-alpha5\Configure no-shared no-asm VC-WIN32 --debug --prefix=E:\C++库\编译\OpenSSL --openssldir=E:\C++库\编译\OpenSSL
64位编译 perl Configure no-shared no-asm VC-WIN64A --prefix=F:\compile\openssl-1.1.1o
如果出现问题:
1、NOTE: If in doubt, on Unix-ish systems use './config'. 出现这个错误是perl 命令中VC-WIN64A,记得64位必须要有A,32位的可以没有;
2、NASM 没有定义的错误就是你NASM,系统环境没有配好,记得再path中添加路径
nmake
nmake test 测试可以不用,EXE可以使用
nmake install
nmake clean
perl是配置用,设置各种编译参数的地方。
no-shared表示编译lib,去掉就是编译dll。上面准备工作处,如果你没有安装Nasm,则需要no-asm这个参数,同理安装了的请去掉该参数。VC-WIN32可切换成VC-WIN64A。--debug去掉则为默认--release。--prefix和--openssldir用于输出,强烈建议设置。还有一些其他参数请参考代码根目录下的INSTALL文件。
四条nmake都是编译相关
nmake 编译
nmake test 编译后可以进行测试,但我们现在编译的是lib,没法测试,你要是可执行文件可以测试
nmake install 编译结果生成,这是最后一步
nmake clean 清理工作,排除各种疑难杂症,可多尝试先清理再编译
编译通过如下图
编译不过,这里有坑:
1,我们这里注意下ActivePerl的安装路径,此工具请安装在英文目录下,检查下看。实际上对于OpenSSL项目编译本身,我都建议在英文目录下进行,预防万一嘛。
2,ActivePerl进行配置时提示错误:
It looks like you don't have either nmake.exe or dmake.exe on your PATH,
so you will not be able to execute the commands from a Makefile. You can
install dmake.exe with the Perl Package Manager by running:
ppm install dmake
提示说得很清楚,但我明明有nmake,我也有手工添加PATH,为什么说他就没找到呢?你问我,我也不知道。我只能另下一个dmake来解决。提示中表示命令行:ppm install dmake可以下载dmake
开始编译libcurl
1 编译libcurl静态库
确保C/C++页面下代码生成/运行库确保跟解决方案保持一致,确保常规下输出路径和目标文件名称(d)
2 C/C++属性页面中的预处理器属性页设置定义
_DEBUG
BUILDING_LIBCURL
DEBUGBUILD
CURL_STATICLIB
USE_WINDOWS_SSPI
USE_SCHANNEL
USE_WINDOWS_SSPI和USE_SCHANNEL两个预编译处理定义是用来定义HTTPS,为了使用https协议需要指定,切记!
注意:配置管理器中针对libcurl存在多个可以编译的版本,例如WINDOWS SSPI ,OPENSSL, WOLFSSL等好几个版本,定义了USE_WINDOWS_SSPI就不需要引入OpenSSL的头文件以及库文件
3 调用工程C/C++属性页面中的预处理器属性页设置定义
BUILDING_LIBCURL
CURL_STATICLIB
因为宏定义主要作用于curl/curl.h头文件,用于头文件的宏定义条件编译,必须定义这两个宏定义,否则编译出错,看出错分析
附件目录
2 链接错误分析
1)error LNK2019: 无法解析的外部符号 __imp__curl_easy_init,该符号在函数 _main 中被引用
分析:不定义CURL_STATICLIB 编译结果,因为CURL_EXTERN CURL *curl_easy_init(void);函数之前有CURL_EXTERN定义,而该定义在
#ifdef CURL_STATICLIB
# define CURL_EXTERN
#elif defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)
# if defined(BUILDING_LIBCURL)
# define CURL_EXTERN __declspec(dllexport)
# else
# define CURL_EXTERN __declspec(dllimport)
# endif
#elif defined(BUILDING_LIBCURL) && defined(CURL_HIDDEN_SYMBOLS)
# define CURL_EXTERN CURL_EXTERN_SYMBOL
#else
# define CURL_EXTERN
#endif
这里被定义,如果没有定义CURL_STATICLIB,将会导致CURL_EXTERN被替换成__declspec(dllexport)或者__declspec(dllimport),这两个声明只应用于动态链接,不能应用于静态链接
2)error LNK2019: 无法解析的外部符号 __imp__ldap_init,该符号在函数 __ldap_free_urldesc 中被引用
在引用项目的属性中添加额外的静态库Crypt32.lib,Wldap32.lib,否则出现如下的错误,因为用到https
3)C2371 “curl_share_init”: 重定义;不同的基类型 libcurl
查看源码,如果没有定义BUILDING_LIBCURL,将导致curl_share_init在声明和定义中出现返回类型不一致的问题
#if defined(BUILDING_LIBCURL) || defined(CURL_STRICTER)
typedef struct Curl_easy CURL;
typedef struct Curl_share CURLSH;
#else
typedef void CURL;
typedef void CURLSH;
#endif