环境
- 下载安装Visual Studio 2019
安装时在【工作负载】必须勾选【使用C++的桌面开发】 - 下载
cyrus-sasl
源码
从Github上clone
或者下载zip包,我本来是需要2.1.26,但是从从https://www.cyrusimap.org/releases/下载对应版本的源码包编译都有问题,因此直接从Github下载2.1分支的包,解压到C:\
,并重命名C:\cyrus-sasl-2.1
- Python3.7环境(可选)
我编译sasl
是因为在windows使用python的sasl
模块时有问题,因此通过python的sasl
模块来调试生成的lib
和dll
是否可用(当然也可以直接通过sasl
自带的client
和server
或者其他调用软件进行调试)。从官网下载安装python3.7即可。
编译
- 打开编译控制台
编译32位的,因此在开始菜单的Visual Studio 2019目录下选择【x86 Native Tools Command Prompt for VS 2019】;编译64位的就选择【x64 Native Tools Command Prompt for VS 2019】。下面先编译32位的,再编译64位的
- 编译32位
直接进入源码的lib
目录
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl STATIC=no
...
windlopen.obj : error LNK2001: 无法解析的外部符号 _anonymous_server_plug_init
...
查看是否执行成功,如果编译报以上错误,是静态链接插件的库不存在,可以选择需要修改win32/include/config.h
注释所有静态插件,那么插件都通过动态链接库的形式提供;也可以选择将插件的文件从plugins
拷贝到lib
目录,并修改所有插件文件中的***_server_plug_init
和***_client_plug_init
方法,在方法前面增加LIBSASL_API
作为导出函数,并在lib\NTMakefile
中添加对应的模块,具体查看https://jira.mongodb.org/browse/CXX-645#。我需要使用动态加载插件,因此直接修改config.h
// #define STATIC_ANONYMOUS 1
// #define STATIC_DIGESTMD5 1
// #define STATIC_NTLM 1
// #define STATIC_PLAIN 1
// #define STATIC_SCRAM 1
重新编译和安装,并拷贝lib\libsasl.lib
命名为lib\sasl2.lib
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl STATIC=no
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl STATIC=no install
C:\cyrus-sasl-2.1\lib>copy /Y C:\sasl\lib\libsasl.lib C:\sasl\lib\sasl2.lib
接下来进入include
目录安装头文件
C:\cyrus-sasl-2.1\include>nmake /f ntmakefile prefix=c:\sasl STATIC=no install
安装完成在prefix
指定的目录C:\sasl
会有如下
C:\SASL
├─bin
│ libsasl.dll
│ libsasl.pdb
├─include
│ └─sasl
│ *.h
└─lib
libsasl.lib
sasl2.lib
- 编译64位
打开x64 Native Tools Command Prompt for VS 2019
的控制台,直接进入源码的lib
目录,先清理之前32位的编译,同时修改prefix
为C:\sasl64
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl64 STATIC=no clean
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl64 STATIC=no
C:\cyrus-sasl-2.1\lib>nmake /f ntmakefile prefix=C:\sasl64 STATIC=no install
C:\cyrus-sasl-2.1\lib>copy /Y C:\sasl64\lib\libsasl.lib C:\sasl64\lib\sasl2.lib
C:\cyrus-sasl-2.1\lib>cd ..\include
C:\cyrus-sasl-2.1\include>nmake /f ntmakefile prefix=C:\sasl64 STATIC=no install
两个版本顺利安装完成
调试python的sasl
安装好python3.7和pip之后,直接安装sasl
,32位的Python需要使用C:\sasl\
,64位的Python需要使用C:\sasl64\
。
C:\>pip install sasl --global-option=build_ext --global-option=-IC:\\sasl64\\include --global-option=-LC:\\sasl64\\lib
...
...\sasl\saslwrapper.h(26): fatal error C1083: 无法打开包括文件: “unistd.h”: No such file or directory
...
unistd.h
是Linux下的头文件,增加一个头文件放在INCLUDE
路径所在的目录,我把它放在C:\sasl\include\
和C:\sasl64\include\
中
#ifndef _UNISTD_H
#define _UNISTD_H 1
#define R_OK 4
#define W_OK 2
#define F_OK 0
#define access _access
#define dup2 _dup2
#define execve _execve
#define ftruncate _chsize
#define unlink _unlink
#define fileno _fileno
#define getcwd _getcwd
#define chdir _chdir
#define isatty _isatty
#define lseek _lseek
#define size_t unsigned int
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
char *getpass(const char *prompt)
{
return "no pass";
}
#endif /* unistd.h */
重新编译,查看是否会报以下错误
C:\>pip install sasl --global-option=build_ext --global-option=-IC:\\sasl64\\include --global-option=-LC:\\sasl64\\lib
...
LINK : fatal error LNK1181: 无法打开输入文件“sasl2.lib”
...
报以上错误是因为默认编译sasl
生成的库是libsasl.lib
,需要拷贝重命名为sasl2.dll
C:\>copy C:\sasl64\lib\libsasl.lib C:\sasl64\lib\sasl2.lib
如果报以下错误,那么可能是python
的版本和sasl
的版本不一致(32
位还是64
位必须一致)
C:\>pip install sasl --global-option=build_ext --global-option=-IC:\\sasl64\\include --global-option=-LC:\\sasl64\\lib
...
saslwrapper.obj : error LNK2001: 无法解析的外部符号 sasl_decode
...
检查确定sasl
编译的时候使用了正确的版本。
一切顺利编译完成,还需要最后一步就是拷贝libsasl.dll
到安装目录
C:\>FOR /F "usebackq delims=" %A IN (`python -c "from importlib import util;import os;print(os.path.dirname(util.find_spec('sasl').origin))"`) DO copy C:\sasl64\bin\libsasl.dll %A
拷贝完成之后就可以在python中使用sasl
>>> import sasl
>>> client = sasl.Client()
注意python在单独使用sasl
库的时候必须在init()
方法之前初始化socket
,否则会报初始化失败,具体原因查看[解决方案] Windows pyhive Could not start SASL分析