2010-04-06 8 views
13

Estoy intentando construir una extensión Python en MacOSX 10.6 y vincularla con varios frameworks (solo i386). Hice un archivo setup.py, usando distutils y el objeto Extension.Creando un módulo python y vinculándolo con un framework MacOSX

I para ligar en contra de mis marcos, mis LDFLAGS env var debe verse como:

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

Como no he encontrado ninguna palabra clave 'marco' en la documentación del módulo de extensión, he utilizado la extra_link_args palabra clave en su lugar.

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++') 

Todo está compilando y enlazando bien. Si elimino la línea -framework de extra_link_args, mi enlazador falla, como se esperaba. Aquí están las dos últimas líneas producidas por una acumulación de pitón 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 

Por desgracia, la .so que acaba de producir no es capaz de encontrar varios símbolos proporcionados por este marco. Traté de verificar el marco vinculado con otool. Ninguno de ellos está apareciendo.

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

No es la salida de Ejecución otool en un binario de prueba, hecha con g ++ y ldd utilizando los LDFLAGS descritos en la parte superior de mi puesto. En este ejemplo, el marco trabajó.

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

¿Puede este problema estar relacionado con el indicador "-dinámico definido indefinido" en el paso de enlace? Estoy un poco confundido por las pocas líneas de documentación que encuentro en Google.

Saludos,

Respuesta

6

Esto no tiene nada que ver con el dynamic_lookup indefinido, pero todo con distutils. Añade los marcadores extra_link_flags a los enlaces que elige para la creación de python. En su lugar, debe anteponerlo porque los listados de marcos deben venir antes que los objetos que los utilizan en la línea de cm (AFAIK esto es debido a cómo gcc reúne símbolos para vincular). Una solución rápida que yo personalmente uso está construyendo con

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

o cualquiera que sea el marco que necesite. LDFLAGS se antepone a los propios indicadores de distutils. Tenga en cuenta que su paquete no será pip install capaz. Una solución adecuada solo puede provenir de distutils: en caso de que sean compatibles con frameworks, es compatible con libraries.

Como alternativa, también se puede añadir

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

en su setup.py. Su paquete debe ser pip install capaz.

1

parece que mi marco está compilado para ppc y i386 pero no 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 

me retiran la bandera x86_64 -arch de mi línea de enlace. Mi biblioteca está enlazado con mis marcos:

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

Si alguien sabe cómo fuerza la -arch para ser usado en tiempo de compilación y enlace con el tiempo distutils de Python ... Por favor comparta su consejo.

3

No estoy seguro de entender lo que está tratando de hacer y su resultado deseado, pero quizás esto ayude. Como los módulos de extensión C normalmente se ejecutan dentro del contexto de ejecución del intérprete de Python, los módulos de extensión deben construirse para que sean compatibles con el intérprete. En OS X, Python y distutils causan problemas para garantizar que los módulos de extensión C se generen con los mismos valores de SDK (-sysroot), MACOSX_DEPLOYMENT_TARGET y -arch que el intérprete de Python en sí. Por lo tanto, si está utilizando el Python suministrado por Apple en 10.6, distutils suministrará -arch i386 -arch ppc -arch x86_64, los tres arcos con los que fue construido. Si se utiliza un instalador actual X OS python.org (de 10,6, 10,5, 10,4), utilizará:

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

A partir de los fragmentos que la oferta, supongo que está utilizando universal instalado de MacPorts Python y, por defecto, está construido con y usa -arch x86_64 -arch i386 -isysroot / para construir módulos de extensión.

En general, para que todo funcione es necesario asegurar:

  1. hay al menos un arch en común entre el intérprete, todos los módulos de extensión C , y todos externa marcos y/o compartida bibliotecas que enlazan a

  2. el intérprete se está ejecutando en esa (o una de esas) arquitectura (s) común (es).

En OS X 10.6, el último paso no es tan fácil como debería ser en función de la cual Python que está utilizando. Por ejemplo, el pitón suministrado por Apple 2.6 tiene una modificación a forzar la ejecución de 32 bits (véase Apple man python para más detalles):

export VERSIONER_PYTHON_PREFER_32_BIT=yes 

Si usted construye su propio Python universal de 32-/64-bits, hay correcciones en 2.6.5 para permitir la selección en tiempo de ejecución. Desafortunadamente, la forma en que MacPorts construye Python pasa por alto esas correcciones, por lo que no parece haber una manera simple de forzar una compilación universal MacPorts python2.6 de 32/64 bits en 10.6 para que se ejecute en modo de 32 bits. Por razones complicadas, siempre preferirá 64 bits, si está disponible, incluso si usa /usr/bin/arch -i386.

Por lo tanto, dependiendo de lo que está tratando de hacer, puede ser capaz de evitar el problema (si he entendido bien) ya sea:

  1. reconstruir sus marcos para incluir -arch x86_64
  2. uso el pitón suministrado por Apple (/usr/bin/python) en el modo de 32 bits o la python.org 2.6.5
  3. reinstalar el pitón DarwinPorts en modo de sólo 32 bits (no probado!):

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

Muchas gracias por su respuesta. Parece que el vinculador no hará referencia a los marcos en el archivo .so producido si al menos un arco no se encuentra en el marco. En mi caso, mi marco incluye las variantes ppc e i386. Todo está funcionando bien con la distribución básica de python incluida en MacOSX si forzo manualmente los indicadores de búsqueda en el paso de vinculación a "i386". Es posible que encuentre mis marcos si ejecuto la copia de sonido en el archivo .so producido. Pero si uso los valores predeterminados del sistema de -arch i386 -arch ppc -arch x86_64, el archivo .so no está vinculado a ninguno de mis marcos. – madflo

+0

La opción 1 desafortunadamente no está disponible, ya que los marcos se proporcionan sin ningún origen. Parece imposible obtener una versión más nueva de mis proveedores. La opción 2 está funcionando. Gracias, casi olvidé que tenía un paquete binario de pitón con macosx ... La opción 3 es, muy extrañamente, que no funciona. El único arco que aparece en el paso de enlace de buildutils es i386, como se esperaba, pero .so no está vinculado a ninguno de los marcos. Intentaré aclarar este problema. – madflo

3

Aunque mucho después de que el polvo se ha asentado, que tiene la misma pregunta a mí mismo Cavé alrededor de un poco y encontré esto:

/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 

estoy viniendo el problema desde un ángulo diferente - en 10,6 distutils está tratando de construir extensiones C y que se queja porque no hay parte de PPC en el 10,6 SDK.

Sin embargo,

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

funcionó de maravilla.

+0

Creo que el problema de PPC es solo si tienes el XCode más nuevo. Es decir, el que puede pagar. El que viene con 10.6 discos de sistema operativo debería estar bien. –

+0

No he intentado responder @synthesizerpatel todavía, pero tuve el problema de ppc con el XCode anterior. El que saldrá libre de MacOS X DVD. – madflo

0

Me encontré con esto yo mismo. Tuve que omitir distutils, ya que parecen codificar el dinámico_indefinido indefinido. Aquí está el Makefile que estoy usando para emular distutils:

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 [email protected] 

%.o: %.c Makefile 
    $(CC) $(CFLAGS) $< -c -o [email protected] 

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

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

Estoy seguro de que es una manera de conseguir distutils a dejar de emitir ese argumento -undefined, pero lo anterior trabajó para mí en 10.7

Cuestiones relacionadas