2012-07-20 66 views
1

在我的Linux x86_64主機上,我想爲我的PowerPC目標交叉編譯一些額外的Python模塊,具體來說就是greenlet,gevent,gevent-websockets。目前,我只是試圖交叉構建greenlet模塊。Python的greenlet和gevent在Linux x86_64上對於PowerPC的交叉編譯

使用信息從這個站點:使用此設置爲我的編譯環境

# Undo variables for cross-compile environment 
unset ROOT 
unset SDKDIR 
unset KLIBDIR 
unset NFSDIR 
unset CONFIG 
unset CONFIGURED 
unset ARCH 
unset OS 
unset TOOLCHAIN_BASE 
unset TOOLCHAIN_BIN 
unset CROSS_COMPILE 
unset c 
unset KERNEL_DIR 
unset AS 
unset LD 
unset CC 
unset AR 
unset STRIP 
unset SSTRIP 
unset OBJCOPY 
unset OBJDUMP 
unset MAKE 
unset CFLAGS 

# Set cross-compile variables: 
export TOOLCHAIN=/opt/freescale/usr/local/gcc-4.3.74-eglibc-2.8.74-dp-2/powerpc-none-linux-gnuspe/bin/powerpc-none-linux-gnuspe- 
export CC=${TOOLCHAIN}gcc 
export CXX=${TOOLCHAIN}g++ 
export AR=${TOOLCHAIN}ar 
export RANLIB=${TOOLCHAIN}ranlib 
export BLDSHARED="${TOOLCHAIN}gcc -shared" 
export LDSHARED="${TOOLCHAIN}gcc -shared" 
export RFS="../../ltib/rootfs" 
export CFLAGS="-save-temps -Wall -I${RFS}/usr/include -I${RFS}/include/python2.7 -L${RFS}/usr/lib -L${RFS}/lib" 
export LDFLAGS="-I${RFS}/usr/include -I${RFS}/include/python2.7 -L${RFS}/usr/lib -L${RFS}/lib" 
export CROSS_COMPILE=ppc-linux 
export CROSS_COMPILE_TARGET=yes 
export HOSTARCH=ppc-linux 
export BUILDARCH=x86_64-linux-gnu 

http://randomsplat.com/id5-cross-compiling-python-for-embedded-linux.html

我能交叉編譯的Python 2.7.2與上面的配置我的環境腳本,然後嘗試構建greenlet模塊產量:

$ python ./setup.py build 
running build 
running build_ext 
building 'greenlet' extension 
creating build 
creating build/temp.linux-x86_64-2.7 
/opt/freescale/usr/local/gcc-4.3.74-eglibc-2.8.74-dp-2/powerpc-none-linux-gnuspe/bin/powerpc-none-linux-gnuspe-gcc -I../../../ltib/rootfs/usr/include -L../../../ltib/rootfs/usr/lib -L../../../ltib/rootfs/lib -fPIC -I/usr/include/python2.7 -c greenlet.c -o build/temp.linux-x86_64-2.7/greenlet.o 
In file included from /usr/include/python2.7/Python.h:58, 
       from greenlet.h:8, 
       from greenlet.c:5: 
/usr/include/python2.7/pyport.h:849:2: error: #error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)." 
error: command '/opt/freescale/usr/local/gcc-4.3.74-eglibc-2.8.74-dp-2/powerpc-none-linux-gnuspe/bin/powerpc-none-linux-gnuspe-gcc' failed with exit status 1 

爲什麼setup.py從我的主機系統上的/usr/include/python2.7中提取?我無法在我的目標上找到那個目標。我如何爲我的目標創建它?

有什麼建議嗎?

謝謝!

特雷弗

更新#1:

我對目標的根文件系統的我的主機的複製相對引用是不正確的。糾正它並重新運行良率:

$ python ./setup.py build 
running build 
running build_ext 
building 'greenlet' extension 
creating build 
creating build/temp.linux-x86_64-2.7 
/opt/freescale/usr/local/gcc-4.3.74-eglibc-2.8.74-dp-2/powerpc-none-linux-gnuspe/bin/powerpc-none-linux-gnuspe-gcc -save-temps -Wall -I../../ltib/rootfs/usr/include -I../../ltib/rootfs/include/python2.7 -L../../ltib/rootfs/usr/lib -L../../ltib/rootfs/lib -fPIC -I/usr/include/python2.7 -c greenlet.c -o build/temp.linux-x86_64-2.7/greenlet.o 
greenlet.s: Assembler messages: 
greenlet.s:832: Error: syntax error; found `(' but expected `,' 
greenlet.s:832: Error: junk at end of line: `(31),1' 
error: command '/opt/freescale/usr/local/gcc-4.3.74-eglibc-2.8.74-dp-2/powerpc-none-linux-gnuspe/bin/powerpc-none-linux-gnuspe-gcc' failed with exit status 1 

至少它是找到更多我的目標的包含庫,但現在我真的難倒了! :(

任何建議

感謝

更新#2:?!

通過添加-save-temps標誌編譯器(上更新錯誤),我才得以保全,並檢查中間的彙編代碼在上面的錯誤信息中提到,虛線包括:

#APP 
# 52 "platform/switch_ppc_linux.h" 1 
    mr 8(31), 1 
# 0 "" 2 

MR(移動寄存器)op是公平的簡單,只接受2個參數(mr to-reg, from-reg)。我不知道如何添加附加寄存器編號的括號。 FWIW,這裏是上述頭文件中引用的宏:

#define STACK_REFPLUS 1 

#ifdef SLP_EVAL 

#define STACK_MAGIC 3 

/* !!!!WARNING!!!! need to add "r31" in the next line if this header file 
* is meant to be compiled non-dynamically! 
*/ 
#define REGS_TO_SAVE "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", \ 
     "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", \ 
     "cr2", "cr3", "cr4" 
static int 
slp_switch(void) 
{ 
    register int *stackref, stsizediff; 
    __asm__ volatile ("" : : : REGS_TO_SAVE); 
    __asm__ ("mr %0, 1" : "=g" (stackref) :); 
    { 
     SLP_SAVE_STATE(stackref, stsizediff); 
     __asm__ volatile (
      "mr 11, %0\n" 
      "add 1, 1, 11\n" 
      "add 30, 30, 11\n" 
      : /* no outputs */ 
      : "g" (stsizediff) 
      : "11" 
      ); 
     SLP_RESTORE_STATE(); 
    } 
    __asm__ volatile ("" : : : REGS_TO_SAVE); 
    return 0; 
} 

#endif 

我開始懷疑,如果這是在編譯器中的錯誤,因爲宏似乎很簡單!有什麼建議麼? ... 謝謝!

+0

鑑於該博客文章的評論似乎意味着人們甚至沒有獲得目標Python來導入標準庫模塊,指令不適用於第三方模塊也不足爲奇...... – abarnert 2012-07-20 22:26:17

+1

這不是問題所在(標題問題?),我可能會遺漏一些東西,但是您沒有指定PPC而不是ARM工具鏈? – 2012-07-20 22:27:03

+0

@TiloWiklund:很好。他從中複製的博客是關於ARM和PPC的交叉編譯,他似乎抄襲了錯誤的博客。這實際上並不能解釋他的問題,因爲如果他使用了ARM工具鏈,情況會完全相同。但這意味着他在嘗試爲它構建擴展之前,還沒有嘗試過對其構建的Python進行最低限度的測試。 – abarnert 2012-07-20 22:30:29

回答

2

也許你應該問一個新問題,因爲這裏確實存在(至少)兩個完全獨立的問題。但是,看看你的第二個問題:

__asm__ ("mr %0, 1" : "=g" (stackref) :); 

這是錯誤的。我會解釋爲什麼下面,但首先,以下變化可能會解決這個問題:

__asm__ ("mr %0, 1" : "=r" (stackref) :); 

您可能還需要以下"g" (stsizediff)改爲"r" (stsizediff)

那麼,現有版本有什麼問題?首先,看一下如何stackref定義:

register int *stackref, stsizediff; 

register是一個提示編譯器,說你認爲如果它分配一個寄存器stackref而不是使用堆棧單元的它可能使事情更快,更好,不要求。如果stackref以R12結尾,那麼很好;如果它結束了8個字節到堆棧幀,那也沒關係。要麼是完全合法的,只要它不違反任何限制。

那麼,stackref有什麼限制?唯一一個在上面引用的asm塊中。你有"=g" (stackref)作爲輸出操作數。 =表示它是隻寫約束,而g表示它必須位於寄存器,內存位置或立即值中。

所以編譯器沒有做錯任何事情。它分配stackref 8個字節從堆棧,其約束(這是一個內存位置)相匹配,那麼它則替換爲"%0"該值,你會得到:

mr 8(31), 1 

沒有錯,直到您嘗試彙編它,並且彙編程序注意到您正嘗試將8(31)與僅使用寄存器的操作碼結合使用。但問題不在於編譯器或彙編器,而在於代碼。你要求它使用stackref作爲mr的操作數,並沒有強制stackref成爲註冊表,所以你得到了你所要求的。

無論如何,將"=g"更改爲"=r"會將約束從「任何寄存器,內存位置或直接值」更改爲「任何通用寄存器」。這意味着編譯器必須將stackref放在通用寄存器中。或者,如果因爲某種原因不能這樣做,它會失敗並告訴你爲什麼,而不是生成不會組裝的組件。

那麼,爲什麼這對原作者有效?那麼,他可能很幸運,並且stackref被分配到了比如說R12,而不是8個字節的堆棧幀,所以他最終以mr 12, 1,這組裝好了。

或者,還有一種可能性。看看git樹,看起來代碼是在Mac OS X上開發的,然後十年前移植到AIX(由主要是Mac開發人員的人員),然後逐字從AIX複製到Linux(甚至將描述「Port for AIX on PowerPC「),並且自從那以後沒有被大幅度觸及。當時OS X和AIX都只有gcc 3。所以,也許這就是當時爲大家工作的原因,並且不適合你。也許只是得到一箇舊的交叉編譯器將解決你的問題。但我會嘗試先修復代碼。

+0

謝謝!這是問題所在。順便說一句,如果我強制執行'-O2'編譯器優化,編譯器會正確組裝。 FWIW,我從模塊的作者那裏收到了類似的支持信息:[link](https://github.com/python-greenlet/greenlet/issues/16)...感謝您的專家,詳細和清晰的解釋。我知道這花了一些時間,我非常感謝。 :) – Trevor 2012-07-27 18:05:03

+0

我可以相信-O2使它在一個寄存器中分配stackref,而-O0將它留在堆棧上。但它不是一個真正的修復,只是因爲它恰好在你的機器上工作,而不是原來的代碼是正確的,因爲它碰巧在原來的編碼器的機器上工作......無論如何,希望你可以讓他們接受= r修正上游(並得到它的測試,當然,而不是通過我對gcc內聯彙編的回憶......)。 – abarnert 2012-07-27 21:20:07

1

Why is setup.py pulling from /usr/include/python2.7 on my host system?

不是這樣。 /usr/include/python2.7/pyport.h:849指的是用於構建您的主機Python的源代碼,它可能實際上可能不在您的系統中。

I can't find that dir on my target. How can I create it for my target?

我不確定你想要。我想你是在一個紅鯡魚。

這裏的關鍵是你的問題:您正在使用您的主機的本地Python來建立一個擴展

$ python ./setup.py build 

,而你沒有做任何事情來告訴它你想擴展交叉編譯。因此,就其所知,您正在嘗試爲其構建greenlet,而不是其他Python。因此,像這樣的事情:

creating build/temp.linux-x86_64-2.7

但是,當然,你給它的ARM交叉編譯器,它不會是能夠編譯擴展您的x86_64的主機蟒蛇,因此這樣的:

/usr/include/python2.7/pyport.h:849:2: error: #error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."

您的主機Python是使用LONG_BIT爲64位LP系統構建的,但它試圖用32位系統的編譯器構建代碼。

博客文章http://kynesim.blogspot.co.uk/2012/06/cross-compiling-python-for-arm-with.html(鏈接自您引用的文章)展示瞭如何構建第三方C擴展模塊。正如你所看到的那樣,這不是微不足道的,可能需要一些實驗才能使它起作用,但看起來它是可行的。

+0

我該如何告訴我的dev-host的python,我正在構建一個交叉編譯的模塊,超出了我已經設置的env-vars? – Trevor 2012-07-20 22:44:56

+0

@barnert:感謝您的更新和鏈接,但是在學習完該博客之後,我想我已經更接近我的上述更新的解決方案,更不用說需要從該配方中解開混雜的環境。任何其他想法? ... 謝謝! – Trevor 2012-07-21 18:52:04