15

我正在尝试在 MacOSX 10.6 上构建 Python 扩展并将其链接到多个框架(仅限 i386)。我使用 distutils 和 Extension 对象制作了一个 setup.py 文件。

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

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

由于我在扩展模块文档中没有找到任何“框架”关键字,因此我使用了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++' )

一切都在编译和链接正常。如果我从 extra_link_args 中删除 -framework 行,我的链接器会按预期失败。这是 python setup.py build 生成的最后两行:

/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

不幸的是,我刚刚生成的 .so 无法找到该框架提供的几个符号。我试图用 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 在测试二进制文件上运行的输出,由 g++ 和 ldd 使用我帖子顶部描述的 LDFLAGS 制作。在此示例中,-framework 确实有效。

$ 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)

可以将此问题链接到链接步骤上的“-undefined dynamic_lookup”标志吗?我对在 Google 上找到的几行文档感到有些困惑。

干杯,

4

5 回答 5

11

这与未定义的 dynamic_lookup 无关,而与 distutils 无关。它将 extra_link_flags 附加到它为 python 构建选择的链接标志上。相反,它应该预先添加它,因为 -framework 列表必须出现在 cmdline 上使用它们的对象之前(AFAIK 这是由于 gcc 如何收集符号以进行链接)。我个人使用的一个快速修复方法是使用

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

或您需要的任何框架。LDFLAGS 被添加到 distutils 自己的标志之前。请注意,您的包裹将无法使用pip install。正确的修复只能来自 distutils - 恕我直言,他们应该frameworks像他们支持的那样支持libraries

或者,您也可以添加

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

在你的 setup.py 中。然后你的包应该pip install可以了。

于 2012-01-03T21:46:56.343 回答
4

尽管尘埃落定很久之后,我自己也有同样的问题,但我挖了一点,发现了这个:

/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

像魅力一样工作。

于 2011-05-26T06:40:30.390 回答
3

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

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

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

通常,要使一切正常工作,您需要确保:

  1. 在解释器、所有 C 扩展模块以及它们链接到的所有外部框架和/或共享库之间至少有一个arch共同点

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

在 OS X 10.6 上,最后一步并不像应有的那么简单,具体取决于您使用的 Python。例如,Apple 提供的 Python 2.6 进行了修改以强制 32 位执行(man python有关详细信息,请参阅 Apple 的):

export VERSIONER_PYTHON_PREFER_32_BIT=yes

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

因此,根据您要执行的操作,您可以通过以下任一方式解决该问题(如果我理解正确的话):

  1. 重建你的框架以包括-arch x86_64
  2. /usr/bin/python在 32 位模式下使用 Apple 提供的 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
    
于 2010-04-06T22:54:35.887 回答
1

似乎我的框架是为 ppc 和 i386 而不是 x86_64 编译的:

$ file /Library/Frameworks/fwk1.framework/Versions/A/fwk1 
/Library/Frameworks/fwk1.framework/Versions/A/fwk1: Mach-O universal binary with 2 architectures
/Library/Frameworks/fwk1.framework/Versions/A/fwk1 (for architecture ppc):  Mach-O dynamically linked shared library ppc
/Library/Frameworks/fwk1.framework/Versions/A/fwk1 (for architecture i386): Mach-O dynamically linked shared library i386

我从链接行中删除了 -arch x86_64 标志。我的库与我的框架链接:

$ otool -L  test.so
test.so:
    /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)

如果有人知道如何强制在编译时使用 -arch 并与 Python 的 distutils 链接...请分享您的建议。

于 2010-04-06T12:47:20.137 回答
0

我自己也遇到了这个。我不得不绕过 distutils,因为它们似乎对 -undefined dynamic_lookup 进行了硬编码。这是我用来模拟 distutils 的 Makefile:

CC = gcc
CFLAGS = -pipe -std=c99 -fno-strict-aliasing -fno-common -dynamic -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Werror -pedantic -Wall -Wstrict-prototypes -Wshorten-64-to-32 -g -Os -arch i386 -arch x86_64 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
LD = gcc
LDFLAGS = -Wl,-F. -bundle -Wl,-F. -arch i386 -arch x86_64 -framework CoreFoundation -framework CoreMIDI -framework Python

project = <extension_name>
library = $(project).so
modules = <module_names>
sources = $(foreach module,$(modules),$(module).c)
objects = $(sources:.c=.o)

all: $(library)

$(library): $(objects)
    $(LD) $(LDFLAGS) $(objects) -o $@

%.o: %.c Makefile
    $(CC) $(CFLAGS) $< -c -o $@

install: $(library)
    cp $(library) /Library/Python/2.7/site-packages

clean:
        rm -f $(library) $(objects) *~

我确信有一种方法可以让 distutils 停止发出该 -undefined 参数,但以上在 10.7 上对我有用

于 2011-11-07T20:23:59.117 回答