安装/编译pylzma(lzma Python绑定)

2 投票
1 回答
4959 浏览
提问于 2025-04-16 10:24

我之前在作者的网站上发过这个问题,但我想在这里也问一下。

我一直在尝试用以下配置安装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 个回答

2

我安装了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

至于处理任何错误的总体方法——这可能需要一些知识和经验才能理解它们背后的原因。

撰写回答