Python交叉编译和移植

参考:http://blog.csdn.net/AIXT2006/article/details/4229779

1、交叉编译之前要确定PC上安装对应版本的python

2、下载python http://www.python.org/ftp/python/2.7/Python-2.7.tar.bz2
3、解压 tar xjvf Python-2.7.tar.bz2
4、由于在编译python的时候,需要先编译一个叫pgen的程序出来,用于生成语法解析器,所以要先生成一个pc版本的pgen,而且还需要编译一个完整PC版本的python:
mkdir build.pc
cd build.pc
../configure
make 

然后ls Parser一下,应该就能看到有pgen了,而且在当前目录生成了python。

cd .. 准备编译;

5、配置:

./configure --prefix=/home/pub/johnny/xbmc/python_install --host=mips-linux-gnu "CC=mips-linux-gnu-gcc -EL" "CFLAGS=-EL" "LDFLAGS=-EL" --enable-shared --disable-ipv6 --with-libc="-L/opt/ali_sdk/staging/lib -lc" "LIBS=-L/opt/ali_sdk/staging/lib"

6、修改setup.py
detect_modules函数:
函数的前两行是把/usr/local加到搜索目录中,我们的cross compiler一般不会直接安装在 /usr/local里面的,所以这两行去掉:
        add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
        add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')

7、之后就要对Makefile做一些修改:
(1)把
# OPT=            -DNDEBUG -g -O3 -Wall -Wstrict-prototypes
OPT=        -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes
一行中,去掉-g,我们不要debug python,-O3改为-O2,空间紧张O2就可以了。
(2)在:
PGEN=           Parser/pgen$(EXE)
一行的下面加上:
PGEN_HOST=      build.pc/Parser/pgen$(EXE)
表明我们在HOST上运行的pgen。
(3)在要使用PGEN的地方改为PGEN_HOST:
$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT)
                -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C)
改为:
$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT)
                -$(PGEN_HOST) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C)

(4)修改所有使用新生成的python的地方。

在BUILDPYTHON变量下面定义一个变量:PYTHON_HOST=build.pc/python$(EXE),然后将所有./$(BUILDPYTHON)的地方都换成./$(PYTHON_HOST),如果你使用vi,可以直接这么替换:%s/.\/$(BUILDPYTHON)/.\/$(PYTHON_HOST)/g


8、make 出现错误:
Include/pyport.h:243: error: #error "This platform's pyconfig.h needs to define PY_FORMAT_LONG_LONG"
修改pyconfig.h: 找到#undef PY_FORMAT_LONG_LONG 处加:#define PY_FORMAT_LONG_LONG "ll"
9、make,make test ,make install;

10、make test时发现有些模块test不通过;

319 tests OK.
23 tests failed:
    test___all__ test_codecmaps_cn test_codecmaps_hk test_codecmaps_jp
    test_codecmaps_kr test_codecmaps_tw test_cookielib test_distutils
    test_hashlib test_hmac test_md5 test_multiprocessing
    test_normalization test_pep247 test_sha test_smtplib test_sundry
    test_tarfile test_unicodedata test_urllib2 test_urllib2_localnet
    test_urllib2net test_uuid
42 tests skipped:
    test_aepack test_al test_applesingle test_bsddb test_bsddb185
    test_bsddb3 test_bz2 test_cd test_cl test_crypt test_curses
    test_dbm test_dl test_gdbm test_gl test_gzip test_imageop
    test_imgfile test_kqueue test_linuxaudiodev test_macos
    test_macostools test_nis test_ossaudiodev test_readline
    test_scriptpackages test_smtpnet test_socketserver test_sqlite
    test_ssl test_startfile test_sunaudiodev test_tcl test_timeout
    test_tk test_ttk_guionly test_ttk_textonly test_urllibnet
    test_winreg test_winsound test_zipfile64 test_zlib


11、在开发板上通过nfs进入到当前路径执行./python,成功;
12、编译测试程序:
mips-linux-gnu-gcc -EL test.c -L. -lpython2.7

#include "./Include/Python.h"
int main()
{
    printf("1111\n");
    Py_Initialize();                             
    PyRun_SimpleString("print 'hi,python!'");       
    Py_Finalize();                               
    return 0;
}

13、执行测试程序

14、如果我们测试 import urllib,会有如下错误:

ImportError: No module named _socket

如果我们print sys.path,结果如下:

['', '/home/pub/johnny/xbmc/test/test2/install/lib/python27.zip', '/root/xbmc/test/test2/Python-2.7/Lib', '/root/xbmc/test/test2/Python-2.7/Lib/plat-linux3', '/root/xbmc/test/test2/Python-2.7/Lib/lib-tk', '/root/xbmc/test/test2/Python-2.7/Lib/lib-old', '/root/xbmc/test/test2/Python-2.7/build/lib.linux-mips-2.7']

我们发现在build下面并没有lib.linux-mips-2.7,而只有lib.linux-x86_64-2.7 目录,而且下面有_socket_failed.so;

那么就把lib.linux-x86_64-2.7 复制成lib.linux-mips-2.7,并把_socket_failed.so以及其他一些需要的so的_failed去掉,批量更改的方法:rename 's/_failed//' *.so;即改成_socket.so等,发现import urllib成功了!

如果把所有的so的_failed去掉,继续make test时发现缺少_sha256等模块,仍然过不了;

http://mail.python.org/pipermail/spambayes/2004-April/012138.html

按照http://blog.sina.com.cn/s/blog_3c8ced580100zxq9.html来修改Module/Setup文件仍然不行;

15、后来在setup.py中搜索_sha256,发现如下程序:

        if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
            # OpenSSL doesn't do these until 0.9.8 so we'll bring our own hash
            exts.append( Extension('_sha256', ['sha256module.c']) )
            exts.append( Extension('_sha512', ['sha512module.c']) )

是不是这个if条件不成立所以没有编译呢?把
if COMPILED_WITH_PYDEBUG or openssl_ver < min_sha2_openssl_ver:
改成if 1:

就生成了_sha512_failed.so和_sha256_failed.so,改成_sha256.so和_sha512.so刚才的import urllib2也成功了!

16、如果在py文件中import gzip,会发现找不到zlib模块;
通过在setup.py中的zlib编译出添加打印信息发现:在if (self.compiler.find_library_file(lib_dirs, 'z')):条件不成立,没有执行的到exts.append,而是执行到了 missing.append('zlib');
if (self.compiler.find_library_file(lib_dirs, 'z')):处添加(self.compiler.find_library_file(lib_dirs+['/usr/lib32'], 'z')):,将zlib模块添加到编译列表中(不同的编译环境此处可能不一样);
仍然不能编译出zlib.so,通过make过程中的log发现,链接时ld不到libz,就在detect_modules中通过add_dir_to_list(self.compiler.library_dirs, './'),然后将交叉编译环境下的libz.so复制到当前目录下;

还需要修改Modules/binascii.c和Modules/zlibmodule.c的路径,为#include "zlib/zlib.h",否则会出现 fatal error: zlib.h: No such file or directory的错误;

再次make,发现生成了zlib.so,此时import gzip也成功了;

17、在开发板上执行时,如果出现如下错误:

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
ImportError: No module named site

需要在当前环境变量中或者在/etc/profile中添加:

export PYTHONHOME=/root/xbmc/python_install-test
export PYTHONPATH=$PYTHONHOME:$PYTHONHOME/lib/python2.7:$PYTHONHOME/lib:$PYTHONHOME/lib/python2.7/site-packages
export PATH=$PATH:$PYTHONHOME:$PYTHONPATH

即可;

你可能感兴趣的:(Python交叉编译和移植)