- 作者:
- 分类:知识&开发->语言->Python
- 阅读:2242
- 点赞:4
- 版权:CC BY-SA 4.0
- 创建:2023-09-05
- 更新:2023-09-06
原文链接(持续更新):https://neucrack.com/p/504
下载源码
https://www.python.org/downloads/source/
编译给 HOST(PC)用的 python
cd Python-3.6.9/./configure --prefix=$PWD/../_install_host --enable-sharedmake -j`nproc`make install
配置参数
https://docs.python.org/3/using/configure.html#configure-options
export PATH=_install_host的bin 路径export LD_LIBRARY_PATH=_install_host的lib路径python3 --version
编译 target
清除之前的
make distclean
这里是 armA7 为例
./configure --host=arm-openwrt-linux --build=armv7l --prefix=`pwd`/../python_target --enable-shared --with-build-python --enable-ipv6 ac_cv_file__dev_ptmx="yes" ac_cv_file__dev_ptc="no"make -j`nproc`make install
如果最后遇到了subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1.
用 root 用户编辑 /usr/bin/lsb_release, #!/usr/bin/python3 改为 python3 即可,这是因为 python3 命令才能调用到我们编译出来的 python3。
交叉编译遇到 The necessary bits to build these optional modules were not found
Python build finished successfully!The necessary bits to build these optional modules were not found:_bz2 _curses _curses_panel_dbm _gdbm _hashlib_lzma _sqlite3 _ssl_tkinter nis readlinezlibTo find the necessary bits, look in setup.py in detect_modules() for the module's name.The following modules found by detect_modules() in setup.py, have beenbuilt by the Makefile instead, as configured by the Setup files:_abc atexit pwdtimeFailed to build these modules:_ctypes _uuidCould not build the ssl module!Python requires an OpenSSL 1.0.2 or 1.1 compatible libssl with X509_VERIFY_PARAM_set1_host().LibreSSL 2.6.4 and earlier do not provide the necessary APIs, https://github.com/libressl-portable/portable/issues/381
编译好了使用python3 -m ensurepip 来安装 pip,也会出现找不到zlib模块的问题。
如果是本机编译比较好解决,比如Ubuntu直接apt安装对应的包就好了。
交叉编译则比较麻烦:
在Python 源码 setup.py 中有detect_modules函数来找依赖的源码,其中detect_compress_exts函数就是找zlib,可以看到它去zlib_inc = find_file('zlib.h', [], self.inc_dirs) include的路径找zlib.h头文件了,以及self.lib_dirs找库文件,所以理论上我们交叉编译好 zlib,并且编译 Python 时往./configure命令传入CFLAGS="-I***/include CPPFLAGS="-I***/include" LDFLAGS="-L***/lib环境变量就好了,其它模块同理去看对应的detect_*****()函数里面在检测什么变量,编译时传入环境变量即可。
可以参考这里: https://gist.github.com/j-c-cook/2a291dc0bfaa2f6639272e344ff66e62
$ tar -xvf v1.2.11.tar.gz && cd cd zlib-1.2.11/$ CHOST="${cross}" CC="${cross}-gcc" CXX="${cross}-g++" AR="${cross}-ar" LD="${cross}-ld" RANLIB="${cross}-ranlib"$ ./configure --prefix=$HOME/zlibArm$ make -j`nproc`$ make install
pip 也需要 ssl, openssl 有专门的参数--with-openssl=DIR, 设置了这个参数,configure 会自动去这个目录下找include``lib,所以不用我们自己设置变量了。这个 DIR 就是交叉编译后的 openssl install 路径
$ tar -xvf OpenSSL_1_1_1o.tar.gz && cd openssl-OpenSSL_1_1_1o$ ./Configure linux-generic32 shared -DL_ENDIAN --prefix=$HOME/opensslArm --openssldir=$HOME/opensslArm$ make CC="${cross}"-gcc RANLIB="${cross}"-ranlib LD="${cross}"-ld MAKEDEPPROG="${cross}"-gcc PROCESSOR=ARM$ make install
$ cd cpython-3.7.13/$ CHOST="${cross}" CC="${cross}"-gcc CXX="${cross}"-g++ AR="${cross}"-ar LD="${cross}"-ld RANLIB="${cross}"-ranlib CFLAGS="-I$HOME/zlibArm/include -I$HOME/sqliteArm/include -I$HOME/libffiArm/include" LDFLAGS="-L$HOME/zlibArm/lib -L$HOME/sqliteArm/lib -L$HOME/libffiArm/lib" CPPFLAGS="-I$HOME/zlibArm/include -I$HOME/sqliteArm/include -I$HOME/libffiArm/include" ./configure --prefix=$HOME/pythonArm --host="${cross}" --target=arm --build=x86_64-linux-gnu --with-openssl="$HOME/opensslArm" --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no --with-ensurepip=install --enable-loadable-sqlite-extensions --enable-optimizations$ make -j 8
