安装/编译pylzma(lzma Python绑定)
我之前在作者的网站上发过这个问题,但我想在这里也问一下。
我一直在尝试用以下配置安装pylzma:
- Windows 7 x64
- Python 2.6.6 x64
- 来自Windows Server 2003 SDK的amd64编译器
- 克隆了git仓库 git://github.com/fancycode/pylzma.git
我用简单的命令easy_install pylzma
得到了以下结果:
cl : 命令行警告 D9025 : 用'/MT'覆盖'/MD' pylzma.c src/pylzma/pylzma.c(85) : 警告 C4244: '=' : 从 'Py_ssize_t' 转换到 'int',可能会丢失数据
src/pylzma/pylzma.c(102) : 错误 C2275: 'CSha256' : 该类型作为表达式的非法使用 c:\users\xavier.lapointe\appdata\local\temp\easy_install-2mfkqu\pylzma-0.4.3\src\pylzma../7zip/C/Sha256.h(18) : 查看 'CSha256' 的声明
src/pylzma/pylzma.c(102) : 错误 C2146: 语法错误 : 在标识符 'sha' 前缺少 ';'
src/pylzma/pylzma.c(102) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(103) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(103) : 警告 C4133: 'function' : 不兼容的类型 - 从 'int *' 到 'CSha256 *'
src/pylzma/pylzma.c(104) : 错误 C2143: 语法错误 : 在 'type' 前缺少 ';'
src/pylzma/pylzma.c(105) : 错误 C2143: 语法错误 : 在 'type' 前缺少 ';'
src/pylzma/pylzma.c(106) : 错误 C2143: 语法错误 : 在 'type' 前缺少 ';'
src/pylzma/pylzma.c(107) : 错误 C2143: 语法错误 : 在 'type' 前缺少 ';'
src/pylzma/pylzma.c(108) : 错误 C2065: 'round' : 未声明的标识符
src/pylzma/pylzma.c(108) : 错误 C2065: 'round' : 未声明的标识符
src/pylzma/pylzma.c(108) : 错误 C2065: 'rounds' : 未声明的标识符
src/pylzma/pylzma.c(108) : 错误 C2065: 'round' : 未声明的标识符
src/pylzma/pylzma.c(109) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(109) : 警告 C4133: 'function' : 不兼容的类型 - 从 'int *' 到 'CSha256 *'
src/pylzma/pylzma.c(110) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(110) : 警告 C4133: 'function' : 不兼容的类型 - 从 'int *' 到 'CSha256 *'
src/pylzma/pylzma.c(111) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(111) : 警告 C4133: 'function' : 不兼容的类型 - 从 'int *' 到 'CSha256 *'
src/pylzma/pylzma.c(111) : 错误 C2065: 'temp' : 未声明的标识符
src/pylzma/pylzma.c(112) : 错误 C2065: 'i' : 未声明的标识符
src/pylzma/pylzma.c(112) : 错误 C2065: 'i' : 未声明的标识符
src/pylzma/pylzma.c(112) : 错误 C2065: 'i' : 未声明的标识符
src/pylzma/pylzma.c(113) : 错误 C2065: 'temp' : 未声明的标识符
src/pylzma/pylzma.c(113) : 错误 C2065: 'i' : 未声明的标识符
src/pylzma/pylzma.c(113) : 错误 C2109: 下标需要数组或指针类型
src/pylzma/pylzma.c(116) : 错误 C2065: 'sha' : 未声明的标识符
src/pylzma/pylzma.c(116) : 警告 C4133: 'function' : 不兼容的类型 - 从 'int *' 到 'CSha256 *'
错误: 设置脚本以错误退出: 命令 '"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\cl.exe"' 失败,退出状态为 2
然后我在网上搜索后发现这和编译器有关(c90与c99),有些人建议把.c扩展名改成.cpp。所以我这样做了,并相应地修改了setup.py(主要是文件名)。
然后成功了,经过一些调整在CpuArch.c(pp)和另一个有语法错误的文件后,它编译通过了。
现在的问题是链接器出错:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:C:\dev\pylzma\build\temp.win-amd64-2.6\Release\src\pylzma /LIBPATH:C:\Python26\libs /LIBPATH:C:\Python26\PCbuild\amd64 user32.lib oleaut32.lib /EXPORT:initpylzma build\temp.win-amd64-2.6\Release\src/pylzma/pylzma.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_decompressobj.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_compressfile.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_decompress.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_compress.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_streams.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_aes.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_decompress_compat.obj build\temp.win-amd64-2.6\Release\src/pylzma/pylzma_decompressobj_compat.obj build\temp.win-amd64-2.6\Release\src\sdk\LzFind.obj build\temp.win-amd64-2.6\Release\src\sdk\LzmaDec.obj build\temp.win-amd64-2.6\Release\src\sdk\LzmaEnc.obj build\temp.win-amd64-2.6\Release\src\7zip\C\CpuArch.obj build\temp.win-amd64-2.6\Release\src\7zip\C\Aes.obj build\temp.win-amd64-2.6\Release\src\7zip\C\AesOpt.obj build\temp.win-amd64-2.6\Release\src\7zip\C\Sha256.obj build\temp.win-amd64-2.6\Release\src\compat\LzmaCompatDecode.obj build\temp.win-amd64-2.6\Release\src/sdk/LzFindMt.obj build\temp.win-amd64-2.6\Release\src/sdk/Threads.obj /OUT:build\lib.win-amd64-2.6\pylzma.pyd /IMPLIB:build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.lib /MANIFESTFILE:build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.pyd.manifest
pylzma.obj : 警告 LNK4197: 导出 'initpylzma' 被多次指定; 使用第一个规格 创建 库 build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.lib 和对象 build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.exp
pylzma.obj : 错误 LNK2001: 未解决的 外部符号 "char const * const doc_decompress" (?doc_decompress@@3QBDB)
pylzma.obj : 错误 LNK2001: 未解决的 外部符号 "struct _object * __cdecl pylzma_decompress(struct _object *,struct _object *)" (?pylzma_decompress@@YAPEAU_object@@PEAU1@0@Z)
pylzma.obj : 错误 LNK2001: 未解决的 外部符号 "char const * const doc_compress" (?doc_compress@@3QBDB)
Aes.obj : 错误 LNK2019: 未解决的 外部符号 "void __cdecl AesCtr_Code_Intel(unsigned int *,unsigned char *,unsigned __int64)" (?AesCtr_Code_Intel@@YAXPEAIPEAE_K@Z) 在函数 AesGenTables 中引用
Aes.obj : 错误 LNK2019: 未解决的 外部符号 "void __cdecl AesCbc_Decode_Intel(unsigned int *,unsigned char *,unsigned __int64)" (?AesCbc_Decode_Intel@@YAXPEAIPEAE_K@Z) 在函数 AesGenTables 中引用
Aes.obj : 错误 LNK2019: 未解决的 外部符号 "void __cdecl AesCbc_Encode_Intel(unsigned int *,unsigned char *,unsigned __int64)" (?AesCbc_Encode_Intel@@YAXPEAIPEAE_K@Z) 在函数 AesGenTables 中引用
AesOpt.obj : 错误 LNK2019: 未解决的 外部符号 _mm_aesenclast_si128 在函数 "void __cdecl AesCbc_Encode_Intel(union __m128i *,union __m128i *,unsigned __int64)" (?AesCbc_Encode_Intel@@YAXPEAT__m128i@@0_K@Z) 中引用
AesOpt.obj : 错误 LNK2019: 未解决的 外部符号 _mm_aesenc_si128 在函数 "void __cdecl AesCbc_Encode_Intel(union __m128i *,union __m128i *,unsigned __int64)" (?AesCbc_Encode_Intel@@YAXPEAT__m128i@@0_K@Z) 中引用
AesOpt.obj : 错误 LNK2019: 未解决的 外部符号 _mm_aesdeclast_si128 在函数 "void __cdecl AesCbc_Decode_Intel(union __m128i *,union __m128i *,unsigned __int64)" (?AesCbc_Decode_Intel@@YAXPEAT__m128i@@0_K@Z) 中引用
AesOpt.obj : 错误 LNK2019: 未解决的 外部符号 _mm_aesdec_si128 在函数 "void __cdecl AesCbc_Decode_Intel(union __m128i *,union __m128i *,unsigned __int64)" (?AesCbc_Decode_Intel@@YAXPEAT__m128i@@0_K@Z) 中引用
build\lib.win-amd64-2.6\pylzma.pyd : 致命错误 LNK1120: 10 个未解决的外部符号
错误: 命令 '"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\BIN\amd64\link.exe"' 失败,退出状态 1120
现在我很难理解这些链接器的问题,即使参考了MSDN文档(关于链接器错误)。这可能是因为我对C/C++的知识不足。
所以基本上我的问题是:
- 有没有办法解决这些链接器问题?
- 我把那些文件从.c改成.cpp是错的吗?如果是的话,能否用msvc amd64编译器编译.c文件?
编辑 没有得到太多回答,所以我想再加一些问题:
当遇到链接错误时,你的处理方法是什么?
有没有什么逻辑可以帮助我在网上找到答案(结合这个MSDN链接错误)?
因为我看到很多人成功地为32位系统编译,那么在64位系统上编译成功,但在链接时由于架构类型失败的可能性大吗?
我更希望得到一些提示,而不是一个完全可行的答案。
非常感谢你的帮助(:
1 个回答
我安装了pylzma来自己试试看。对于Python 2.6,使用mingw编译没有问题,但用msvc编译器在Python 2.4到2.7之间就出错了。我们先看看错误信息:
src/pylzma/pylzma.c(102) : 错误 C2275: 'CSha256' : 这种类型作为表达式的使用不合法 c:\users\xavier.lapointe\appdata\local\temp\easy_install-2mfkqu\pylzma-0.4.3\src\pylzma../7zip/C/Sha256.h(18) : 请查看 'CSha256' 的声明
出问题的代码是:
} else {
Py_BEGIN_ALLOW_THREADS
Sha256_Init(&sha);
CSha256 sha;
long round;
int i;
long rounds = (long) 1 << cycles;
unsigned char temp[8] = { 0,0,0,0,0,0,0,0 };
for (round = 0; round < rounds; round++) {
这段代码明显是无效的C代码,因为在代码后面声明变量是不允许的。当你把.c文件改成.cpp时,就避免了这个错误,因为C++允许这样做(而且mingw似乎也支持这种写法)。但是切换到C++后又出现了名称混淆和链接错误。要解决这些问题,你可以在所有代码周围加上extern "C" { ... }
。
不过,最好还是修复src/pylzma/pylzma.c,修复方法很简单——把Py_BEGIN_ALLOW_THREADS和Sha256_Init(&sha);移动到变量声明之后:
} else {
CSha256 sha;
long round;
int i;
long rounds = (long) 1 << cycles;
unsigned char temp[8] = { 0,0,0,0,0,0,0,0 };
Py_BEGIN_ALLOW_THREADS
Sha256_Init(&sha);
for (round = 0; round < rounds; round++) {
现在pylzma可以正常编译,但在链接后运行清单工具时失败了:
创建库 build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.lib 和对象 build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.exp C:\Program Files\Microsoft SDKs\Windows\v7.0\bin\x64\mt.exe -nologo -manifest bu ild\temp.win-amd64-2.6\Release\src/pylzma\pylzma.pyd.manifest -outputresource:bu ild\lib.win-amd64-2.6\pylzma.pyd;2
build\temp.win-amd64-2.6\Release\src/pylzma\pylzma.pyd.manifest : 一般错误 c1010070: 无法 加载和解析清单。系统找不到指定的文件。错误: 命令 'mt.exe' 失败,退出状态为31
查看构建目录发现那里没有pylzma.pyd.manifest文件,尽管输出中显示link.exe有/MANIFEST:...的开关。快速在网上搜索“link没有创建清单”发现了一个链接 http://bugs.python.org/issue4431,里面解释了使用/MT开关时不会创建清单,解决方法是给链接器标志添加/MANIFEST。好吧,我们来编辑pylzma的setup.py,为MSVC编译器添加这个链接器标志:
if isinstance(self.compiler, MSVCCompiler):
# set flags only available when using MSVC
ext.extra_link_args.append('/MANIFEST') # force linker to create manifest
if COMPILE_DEBUG:
ext.extra_compile_args.append('/Zi')
ext.extra_compile_args.append('/MTd')
ext.extra_link_args.append('/DEBUG')
else:
ext.extra_compile_args.append('/MT')
好了,现在pylzma可以用MSVC正常构建了。我测试了在Python 2.4到2.7的32位和2.6到2.7的64位下构建:
08.02.2011 10:08 71 844 pylzma-0.4.3dev-py2.4-win32.egg
08.02.2011 10:09 71 480 pylzma-0.4.3dev-py2.5-win32.egg
08.02.2011 10:07 79 358 pylzma-0.4.3dev-py2.6-win-amd64.egg
08.02.2011 10:09 75 637 pylzma-0.4.3dev-py2.6-win32.egg
08.02.2011 10:08 79 259 pylzma-0.4.3dev-py2.7-win-amd64.egg
08.02.2011 10:09 75 540 pylzma-0.4.3dev-py2.7-win32.egg
6 File(s) 453 118 bytes
至于处理任何错误的总体方法——这可能需要一些知识和经验才能理解它们背后的原因。