2

Linux x86_64 ホストで、PowerPC ターゲット用にいくつかの追加の Python モジュール、具体的にはgreenletgevent、およびgevent-websocketsをクロスコンパイルしようとしています。現在、greenlet モジュールをクロスビルドしようとして立ち往生しています。

このサイトの情報を使用する:

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

ビルド環境でこのセットアップを使用して、Python 2.7.2 をクロスコンパイルできました。

# 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

上記のスクリプトを使用して環境を構成し、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:

ターゲットの rootfs のホストのコピーへの相対参照が正しくありませんでした。それを修正して再実行すると、次のようになります。

$ 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

マクロが単純に見えるので、これはコンパイラのバグではないかと思い始めています! 助言がありますか?... ありがとう!

4

3 に答える 3

3

ここには (少なくとも) 2 つの完全に独立した問題があるため、新しい質問をする必要があるかもしれません。しかし、あなたの2番目の問題を見てください:

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

これは間違っています。以下で理由を説明しますが、最初に、次の変更で問題が解決する可能性があります。

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

"g" (stsizediff)以下をに変更する必要がある場合もあります"r" (stsizediff)

では、既存のバージョンの何が問題になっているのでしょうか。まず、stackref がどのように定義されているかを見てください。

register int *stackref, stsizediff;

これはコンパイラへのヒントであり、要件ではなく、スタックの場所を使用する代わりにregisterレジスタを割り当てた場合に、処理が高速化または改善される可能性があると考えていることを示しています。R12 で終わるstackref場合は、素晴らしいです。stackrefスタック フレームに 8 バイト入っていれば、それも問題ありません。制約に違反しない限り、どちらも完全に合法です。

では、どのような制約がありstackrefますか? 唯一のものは、上で引用した asm ブロックにあります。"=g" (stackref)出力オペランドとして持っています。は=書き込み専用の制約であるgことを意味し、レジスタ、メモリ位置、または即値にある必要があることを意味します。

したがって、コンパイラは何も悪いことをしていません。スタックから 8 バイトを割り当てstackrefます。これは制約 (メモリの場所) に一致し、その値を に代入すると、次の"%0"ようになります。

mr 8(31), 1

アセンブルしようとすると、アセンブラーが、レジスターのみを使用するオペコードで 8(31) を使用しようとしていることに気付くまでは、何も問題はありません。しかし、問題はコンパイラやアセンブラではなく、コードです。stackrefのオペランドとして使用するように要求し、強制的にレジスタにすることはmrしなかったので、要求したものが得られました。stackref

とにかく、をに変更する"=g""=r"、制約が「任意のレジスタ、メモリ位置、または即値」から「任意の汎用レジスタ」に変更されます。つまり、コンパイラはstackref汎用レジスタを配置する必要があります。または、何らかの理由でできない場合は、アセンブルしないアセンブリを生成する代わりに、失敗してその理由を教えてくれます。

では、なぜこれが原作者にとってうまくいったのでしょうか。まあ、彼はおそらく幸運にstackref恵まれ、スタック フレームに 8 バイトではなく、たとえば R12 に割り当てられたので、最終的には になりましたmr 12, 1。これは問題なくアセンブルされます。

または、もう1つの可能性。git ツリーを見ると、コードは Mac OS X で開発され、10 年前に (主に Mac 開発者によって) AIX に移植され、AIX から Linux にそのままコピーされたように見えます (「Port for PowerPC 上の AIX") であり、それ以来あまり触れられていません。OS X も AIX も当時は gcc 3 しかありませんでした。だから、それが当時誰にとってもうまくいった理由で、あなたにはうまくいかなかったのかもしれません. そして、古いクロスコンパイラを入手するだけで問題が解決するかもしれません。しかし、最初にコードを修正してみます。

于 2012-07-27T17:15:30.660 に答える
1

setup.pyがホストシステムの/usr/include/python2.7からプルするのはなぜですか?

そうではありません。は/usr/include/python2.7/pyport.h:849、ホストPythonの構築に使用されるソースを指します。これは、実際にシステム上にある場合とない場合があります。

ターゲットにそのdirが見つかりません。ターゲット用に作成するにはどうすればよいですか?

あなたがしたいかどうかわかりません。私はあなたが赤いニシンに乗っていると思います。

問題の鍵は次のとおりです。

$ python ./setup.py build

ホストのネイティブPythonを使用して拡張機能を構築しており、拡張機能をクロスコンパイルするように指示することは何もしていません。したがって、それが知る限り、あなたは他のPythonではなく、そのためのグリーンレットを構築しようとしています。したがって、次のようなものです。

build/temp.linux-x86_64-2.7の作成

しかしもちろん、ARMクロスコンパイラーを提供しているので、x86_64ホストPythonの拡張機能をコンパイルすることはできません。したがって、次のようになります。

/usr/include/python2.7/pyport.h:849:2:エラー:#error「プラットフォームのLONG_BIT定義が間違っているようです(gcc / glibc構成が正しくありませんか?)」

ホストPythonは64ビットLPシステム用にLONG_BITを設定してビルドされましたが、32ビットシステム用のコンパイラーを使用してコードをビルドしようとしています。

ブログ投稿http://kynesim.blogspot.co.uk/2012/06/cross-compiling-python-for-arm-with.html(引用したものからリンクされています)は、サードパーティのC拡張モジュールを構築する方法を示しています。ご覧のとおり、これは完全に些細なことではなく、機能させるには少し実験が必要な場合がありますが、実行可能のようです。

于 2012-07-20T22:24:35.857 に答える