2012-07-20 126 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