构建python模块并将其链接到MacOSX fram

2024-05-14 08:49:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在MacOSX 10.6上构建一个Python扩展,并将其链接到几个框架(仅i386)。我用distutils和Extension对象创建了一个setup.py文件。

为了链接到我的框架,我的LDFLAGSenv var应该如下所示:

LDFLAGS = -lc -arch i386 -framework fwk1 -framework fwk2

由于在扩展模块文档中没有找到任何“framework”关键字,因此我改用了extra_link_args关键字。

Extension('test',
define_macros = [('MAJOR_VERSION', '1'), ,('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include', 'include/', 'include/vitale'],
extra_link_args = ['-arch i386',
                   '-framework fwk1',
                   '-framework fwk2'],
sources = "testmodule.cpp",
language = 'c++' )

一切都在编译和链接。如果我从额外的链接参数中删除-framework行,我的链接器将按预期失败。下面是python setup.py生成的最后两行:

/usr/bin/g++-4.2 -arch x86_64 -arch i386 -isysroot /
-L/opt/local/lib -arch x86_64 -arch i386 -bundle
-undefined dynamic_lookup build/temp.macosx-10.6-intel-2.6/testmodule.o
-o build/lib.macosx-10.6-intel-2.6/test.so
-arch i386 -framework fwk1 -framework fwk2

不幸的是,我刚刚制作的.所以找不到这个框架提供的几个符号。我试着用otool检查链接的框架。他们都没出现。

$ otool -L test.so
test.so:
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.0.1)

有一个测试二进制文件的otool run输出,它是用g++和ldd生成的,使用的LDFLAGS在我文章的顶部描述。在这个例子中,-框架确实有效。

$ otool -L vitaosx 
vitaosx:
    /Library/Frameworks/fwk1.framework/Versions/A/fwk1 (compatibility version 1.0.0, current version 1.0.0)
    /Library/Frameworks/fwk2.framework/Versions/A/fwk2 (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.0.1)

此问题是否可以链接到链接步骤上的“-未定义的动态查找”标志?在Google上找到的几行文档让我有点困惑。

干杯


Tags: test框架include链接versionlibusrframework
3条回答

虽然尘埃落定很久之后,我自己也有同样的问题,但我在周围摸索了一下,发现:

/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/distutils/sysconfig.py

   if 'ARCHFLAGS' in os.environ:
                archflags = os.environ['ARCHFLAGS']
            else:
                archflags = '-arch i386 -arch ppc -arch x86_64'
            _config_vars['ARCHFLAGS'] = archflags
            if archflags.strip() != '':
                _config_vars['CFLAGS'] = _config_vars['CFLAGS'] + ' ' + archflags
                _config_vars['LDFLAGS'] = _config_vars['LDFLAGS'] + ' ' + archflags

我从另一个角度来讨论这个问题——10.6版本的distutils正在尝试构建C扩展,但由于10.6版本的SDK中没有PPC部分,因此我对此表示不满。

然而

 export ARCHFLAGS="-arch i386 -arch x86_64"
 python setup.py build

工作起来很有魅力。

我不确定我是否理解你在做什么和你想要的结果,但也许这会有帮助。由于C扩展模块通常在Python解释器的执行上下文中运行,因此必须构建与解释器兼容的扩展模块。在OS X上,Python和distutils在确保C扩展模块使用与Python解释器本身最初构建时相同的SDK(-sysroot)、MACOSX_DEPLOYMENT_TARGET值和-arch值时会遇到一些麻烦。因此,如果您在10.6上使用Apple提供的Python,distutils将提供-arch i386 -arch ppc -arch x86_64,这是用它构建的三个arch。如果使用当前的python.org OS X安装程序(在10.6、10.5或10.4上),它将使用:

gcc-4.0 -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk

从您提供的代码片段来看,我猜您使用的是安装了通用Python的MacPorts,默认情况下,它是使用-arch x86_64 -arch i386 -isysroot /构建扩展模块的。

一般来说,要使一切正常工作,您需要确保:

  1. 中至少有一个arch 在口译员中很常见 扩展模块和所有外部 框架和/或共享库 它们链接到

  2. 解释器在那个(或其中一个)公共体系结构中执行。

在OSX10.6上,最后一步并不那么简单,这取决于您使用的是哪种Python。例如,Apple提供的Python2.6修改了强制32位执行(有关详细信息,请参见Apple的man python):

export VERSIONER_PYTHON_PREFER_32_BIT=yes

如果您构建自己的32/64位通用Python,那么2.6.5中有一些修正,允许在运行时进行选择。不幸的是,MacPorts构建Python的方法绕过了这些修复,因此似乎没有任何简单的方法强制MacPorts python2.6在10.6上运行32位/64位通用构建,使其以32位模式运行。由于复杂的原因,即使您使用/usr/bin/arch -i386,它也总是喜欢64位(如果可用)。

因此,取决于你想做什么,你可以通过以下任一方法来解决这个问题(如果我理解正确的话):

  1. 重新构建框架以包含-arch x86_64
  2. 在32位模式下使用Apple提供的Python(/usr/bin/python)或Python.org 2.6.5
  3. 以32位模式重新安装MacPorts python(未测试!)以下内容:

    sudo port selfupdate
    sudo port clean python26
    sudo port install python26 +universal universal_archs=i386
    

这与未定义的动态查找无关,而是与distutils有关。它将额外的链接标志附加到它为python构建选择的链接标志。相反,它应该放在前面,因为-framework列表必须在命令行上使用它们的对象之前(AFAIK这是因为gcc如何收集用于链接的符号)。我个人使用的一个快速修复方法是

    LDFLAGS="-framework Carbon" python setup.py build_ext --inplace

或者你需要的任何框架。LDFLAGS前面是distutils own flags。请注意,您的包将不能pip install。正确的修复只能来自distutils-imho,它们应该支持frameworks,就像它们支持libraries

或者,也可以添加

import os
os.environ['LDFLAGS'] = '-framework Carbon'

在你的setup.py中。然后,您的包应该能够pip install

相关问题 更多 >

    热门问题