Python的C扩展源码编译不太易
Python生态的优势之一*多,*分两类,一类是完全用Python本身写的,另一类是结合或者说使用了C/C++扩展的,由于Python的跨平台,前者安装无忧,后者如果能用到包管理自动搞定也无忧,但是如果没有包管理器,也找不到预编译好的版本,只有源码,那么就可能有点忧愁了,这种情况在Windows平台上比较常见,一些小众的包只有源码,没有预编译的程序。
忧愁一:32位还是64位
Python本身现在也有32位和64位之分,如果操作系统是32位,那就没问题了,因为Python肯定是32位,但如果操作系统是64位,那就要注意已有的Python是32位还是64位,32位的Python编译后的包自然是为32位使用,64位同理。
那么问题来了,构建的链接阶段引用的已有库也需要和编译的目标架构匹配,否则就可能出现Link错误。
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_set_data
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_destroy
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_symbol_get_data
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_create
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_scanner_set_config
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_scanner_create
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_scanner_destroy
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_symbol_next
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_set_format
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_symbol_get_data_length
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_set_size
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_image_first_symbol
_zbarlight.obj : error LNK2001: 无法解析的外部符号 zbar_scan_image
build\lib.win-amd64-3.7\zbarlight\_zbarlight.cp37-win_amd64.pyd : fatal error LNK1120: 13 个无法解析的外部命令
忧愁二: Windows下的编译
如果没有C/C++背景,那么需要从源码构建Python包是不太容易的,因为途中可能因为一个路径,或者因为一个编译器参数的设置,总之有很多“或者”让你中途卡住。
经典场景:
error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools":
Microsoft Visual C++ compiler
在Windows上这个问题更加突出,Windows默认没有安装构建工具,在类Unix系统上,构建工具在系统被安装的可能性较大,即使没有安装也可以通过包管理器方便快捷的安装,但在Windows上,构建工具的安装却不太容易,为了安装C/C++的构建工具,正规的套路是安装Visual Studio 开发环境,GB以上的体量着实有些门槛,当日也可以通过独立安装包或者安装器有选择安装。此外,版本也是有讲究的,CPython官方的安装包本身是通过不同Microsoft Visual C++ compiler编译的,不同的版本用的c++ 编译器版本不一定相同。使用Visual C++ compiler编译器也不一定就毫无问题,如果源码年久失修,在新版编译器面前依旧可能半路翻车,非要用那貌似可以选择把Python降级处理。
zbar-0.10\zbarmodule.h(148): error C2143: 语法错误: 缺少“{”(在“*”的前面)
zbarmodule.c(53): error C2143: 语法错误: 缺少“{”(在“*”的前面)
zbarmodule.c(56): error C2143: 语法错误: 缺少“{”(在“*”的前面)
zbarmodule.c(112): warning C4033: “initzbar”必须返回值
zbarmodule.c(115): error C2065: “PyInt_Type”: 未声明的标识符
zbarmodule.c(115): warning C4133: “=”: 从“int *”到“_typeobject *”的类型不兼容
zbarmodule.c(129): warning C4033: “initzbar”必须返回值
zbarmodule.c(137): warning C4033: “initzbar”必须返回值
zbarmodule.c(146): warning C4013: “Py_InitModule”未定义;假设外部返回 int
zbarmodule.c(148): warning C4033: “initzbar”必须返回值
zbarmodule.c(146): warning C4047: “初始化”:“PyObject *”与“int”的间接级别不同
error: command 'C:\\Program Files\\Microsoft Visual Studio\\BuildTools\\...\\cl.exe' failed with exit status 2
mingw与mingw-w64
存在一些GNU构建工具移植Windows的项目,比如mingw,以及支持64位编译的mingw-w64,这些工具比较轻量级,在老些的Python版本上兼容性也不错,可以兼容3.5以下的版本。
在Python安装目录\Lib\distutils 下创建配置文件distutils.cfg使用mingw。
[build]
compiler=mingw32
但是3.5开始,就可能出现不兼容导致不能完成编译构建的可能了。
File "c:\program files\python\python35\lib\distutils\cygwinccompiler.py", line 282, in __init__
CygwinCCompiler.__init__ (self, verbose, dry_run, force)
File "c:\program files\python\python35\lib\distutils\cygwinccompiler.py", line 126, in __init__
if self.ld_version >= "2.10.90":
TypeError: '>=' not supported between instances of 'NoneType' and 'str'
Cygwin
另一种方案是使用类似Cygwin的环境,完全在环境中使用Python和编译包,Python distutils工具对这类环境有一些支持,不过感觉实际体验也不是想象的那么美。
忧愁三:可能用不了PIP
因为源码编译的缘故,难免会有些编译选项需要配置,比如在setup.py中改改头文件的位置,版本原因需要改链接库的名字等,此时
pip install
就不行了,需要手工下载对应的包,修改相应的文件,最后手工安装,显得比较麻烦。
python setup.py install
总的来说,为了节约点时间,节省点光阴陪陪父母,爱人,朋友,去看看山川大海,还是尽量用包管理器一个命令搞定吧,实在不行找找wheel直接安装,源码安装,尤其是Windows下端源码安装还是能避免就避免吧。
上一篇: 易错题