2010-04-06 12 views
13

Sto provando a creare un'estensione Python su MacOSX 10.6 e collegarlo a più framework (solo i386). Ho creato un file setup.py, usando distutils e l'oggetto Extension.Costruire un modulo python e collegarlo a un framework MacOSX

ho per collegare contro i miei quadri, i miei LDFLAGS env var dovrebbe essere simile:

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

Come non ho trovato una qualsiasi parola chiave 'quadro' nella documentazione del modulo di estensione, ho usato la extra_link_args Parola chiave invece.

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

Tutto sta compilando e collegando bene. Se rimuovo la linea -framework da extra_link_args, il mio linker fallisce, come previsto. Ecco le ultime due righe prodotte da un accumulo 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 

Purtroppo, la .so che ho appena prodotto non è in grado di trovare diversi simboli forniti da questo quadro. Ho provato a controllare il framework collegato con otool. Nessuno di loro appare.

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

V'è l'uscita di corsa otool su un binario di prova, fatta con g ++ e ldd base alle LDFLAGS descritte nella parte superiore del post. In questo esempio, il -framework ha funzionato.

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

Questo problema può essere collegato al flag "-undefined dynamic_lookup" nel passaggio di collegamento? Sono un po 'confuso dalle poche righe di documentazione che trovo su Google.

Cheers,

risposta

6

Questo non ha nulla a che fare con la dynamic_lookup indefinita ma tutti con distutils. Aggiunge gli extra_link_flags ai flag di collegamento che sceglie per la costruzione di python. Invece dovrebbe anteporlo perché gli elenchi -framework devono venire prima degli oggetti che li usano sulla cmdline (AFAIK questo è dovuto al modo in cui gcc raccoglie i simboli per il collegamento). Una soluzione rapida che io personalmente uso sta costruendo con

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

o qualsiasi altra cosa quadri necessari. LDFLAGS è preposto a distutils own flags. Si noti che il pacchetto non sarà in grado di pip install. Una correzione corretta può venire solo da distutils - imho dovrebbero supportare frameworks come supportano libraries.

In alternativa, è anche possibile aggiungere

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

nel setup.py. Il pacchetto dovrebbe quindi essere in grado di pip install.

1

sembra che il mio quadro è compilato per PPC e i386, ma non 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 

ho rimosso la bandiera x86_64 -arch dalla mia linea di collegamento. La mia biblioteca è collegata contro i miei quadri:

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

Se qualcuno sa come forza il -arch da utilizzare in fase di compilazione e di collegamento con il tempo distutils di Python ... si prega di condividere i tuoi consigli.

3

Non sono sicuro di capire cosa stai cercando di fare e il tuo risultato desiderato ma forse questo sarà di aiuto. Poiché i moduli di estensione C vengono normalmente eseguiti all'interno del contesto di esecuzione dell'interprete Python, i moduli di estensione devono essere costruiti per essere compatibili con l'interprete. Su OS X, Python e distutils si preoccupano di assicurare che i moduli di estensione C siano costruiti con lo stesso valore SDK (-sysroot), MACOSX_DEPLOYMENT_TARGET e -arch poiché l'interprete Python stesso è stato originariamente creato. Quindi, se stai usando Python fornito da Apple su 10.6, distutils fornirà -arch i386 -arch ppc -arch x86_64, i tre arch con cui è stato costruito. Se si utilizza un programma di installazione corrente X python.org OS (il 10.6, 10.5 o 10.4), userà:

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

Dai frammenti che fornite, sto cercando di indovinare che si sta utilizzando un universale MacPorts-installato Python e, per impostazione predefinita, è costruito con e utilizza -arch x86_64 -arch i386 -isysroot / per costruire moduli di estensione.

In generale, per far funzionare tutto il necessario per garantire:

  1. c'è almeno un arch in comune tra l'interprete, tutti i moduli di estensione C , e tutti esterni quadri e/o condiviso librerie che collegano a

  2. l'interprete sta eseguendo in quella (o una di quelle) architetture comuni.

Su OS X 10.6, l'ultimo passaggio non è così semplice come dovrebbe essere a seconda di quale Python si sta utilizzando. Per esempio, l'Apple fornito Python 2.6 ha una modifica per forzare l'esecuzione a 32 bit (vedi Apple man python per i dettagli):

export VERSIONER_PYTHON_PREFER_32_BIT=yes 

Se si costruisce il proprio 32/64-bit Python universale, ci sono correzioni in 2.6.5 per consentire la selezione in fase di esecuzione. Sfortunatamente, il modo in cui MacPorts costruisce Python ignora queste correzioni, quindi non sembra esserci un modo semplice per forzare una build universale per MacPorts python2.6 32-/64-bit su 10.6 da eseguire in modalità a 32-bit. Per motivi complicati, preferirà sempre 64 bit, se disponibile, anche se si utilizza /usr/bin/arch -i386.

Quindi, a seconda di ciò che si sta cercando di fare, si può essere in grado di risolvere il problema (se ho capito bene) mediante:

  1. ricostruire i quadri di includere -arch x86_64
  2. uso Python fornita da Apple (/usr/bin/python) in modalità a 32 bit o il python.org 2.6.5
  3. reinstallare il pitone MacPorts in modalità a 32 bit-only (non testata!):

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

La ringrazio molto per la risposta. Sembra che il linker non farà riferimento i quadri nel prodotto .so file se almeno un arco non si trova nel quadro. Nel mio caso, il mio framework include le varianti ppc e i386. Tutto funziona correttamente con la distribuzione python di base inclusa in MacOSX se forzo manualmente i flag -arch al passaggio di collegamento su "i386". Potrei trovare i miei framework se eseguo otool sul file .so prodotto. Ma se io uso le impostazioni predefinite del sistema di i386 -arch -arch ppc -arch x86_64, il file .so non è collegata a nessuno dei miei quadri. – madflo

+0

L'opzione 1 è sfortunatamente non disponibile, in quanto i framework sono forniti in quanto privi di qualsiasi fonte. Sembra impossibile ottenere una versione più recente dai miei provider. Opzione 2 sta lavorando. Grazie, ho quasi dimenticato di avere un binario python in bundle con macosx ... L'opzione 3 è, molto stranamente, non funziona. L'unico arco che appare sul passo di collegamento del buildutils è i386, come previsto, ma il .so non è collegato a nessuno dei framework. Proverò a risolvere questo problema. – madflo

3

Anche se molto tempo dopo la polvere si è stabilito, avendo la stessa domanda che mi sono scavato intorno un po 'e trovato questo:

/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 

sto arrivando il problema da un altro punto di vista - su 10.6 distutils sta cercando di costruire estensioni C e come si lamenta perché non c'è parte PPC nel 10.6 SDK.

Tuttavia,

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

funzionato come un fascino.

+0

Credo che il problema PPC sia solo se hai il nuovo XCode. Cioè, quello che puoi pagare. Quello che viene fornito con 10.6 dischi OS dovrebbe andare bene. –

+0

Non ho ancora provato la risposta @synthesizerpatel, ma ho avuto il problema di ppc con il precedente XCode. Quello che esce gratis da MacOS X DVD. – madflo

0

Mi sono imbattuto in questo io stesso. Ho dovuto bypassare le distutils, perché sembrano codificare in modo hard-defined il dynamic_lookup. Ecco il Makefile che sto usando per emulare 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) *~ 

Sono sicuro che ci sia un modo per ottenere distutils a smettere di emettere tale argomento -undefined, ma quanto sopra ha lavorato per me su 10.7

Problemi correlati