前段时间移植一个python项目到OpenWrt,踩了不少坑,总结一下希望帮到有需要的人,来看打包问题:
0x01
在OpenWrt 使用pip直接安装了pyinstaller,打包过程中出现文件缺失、文件错误的问题:
从githut/pyinstaller得知linux环境下使用pyinstaller需要ldd、objcopy、objdump支持,openwrt安装gcc即可自动安装binutils:
opkg update
opkg install gcc
github 传送门:https://github.com/pyinstaller/pyinstaller
0x02
继续打包,继续报错,错误信息如下:
root@mux:~/daemon# pyinstaller daemon.py
2230 INFO: PyInstaller: 3.2.1
2232 INFO: Python: 2.7.9
2240 INFO: Platform: Linux-3.18.29-mips-with-glibc2.0
2244 INFO: wrote /root/daemon/daemon.spec
2278 INFO: UPX is not available.
2294 INFO: Extending PYTHONPATH with paths
['/root/daemon', '/root/daemon']
2296 INFO: checking Analysis
2454 INFO: checking PYZ
2542 INFO: checking PKG
2556 INFO: Building because toc changed
2558 INFO: Building PKG (CArchive) out00-PKG.pkg
ldd: can't open cache '/etc/ld.so.cache'
2713 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
2785 INFO: Bootloader /usr/lib/python2.7/site-packages/PyInstaller/bootloader/Linux-32bit/run
2788 INFO: checking EXE
2790 INFO: Building EXE because out00-EXE.toc is non existent
2791 INFO: Building EXE from out00-EXE.toc
2795 INFO: Appending archive to ELF section in EXE /root/daemon/build/daemon/daemon
Traceback (most recent call last):
File "/usr/bin/pyinstaller", line 9, in <module>
load_entry_point('PyInstaller==3.2.1', 'console_scripts', 'pyinstaller')()
File "/usr/lib/python2.7/site-packages/PyInstaller/__main__.py", line 90, in run
run_build(pyi_config, spec_file, **vars(args))
File "/usr/lib/python2.7/site-packages/PyInstaller/__main__.py", line 46, in run_build
PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
File "/usr/lib/python2.7/site-packages/PyInstaller/building/build_main.py", line 788, in main
build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
File "/usr/lib/python2.7/site-packages/PyInstaller/building/build_main.py", line 734, in build
exec(text, spec_namespace)
File "<string>", line 26, in <module>
File "/usr/lib/python2.7/site-packages/PyInstaller/building/api.py", line 411, in __init__
self.__postinit__()
File "/usr/lib/python2.7/site-packages/PyInstaller/building/datastruct.py", line 161, in __postinit__
self.assemble()
File "/usr/lib/python2.7/site-packages/PyInstaller/building/api.py", line 563, in assemble
self.name)
File "/usr/lib/python2.7/site-packages/PyInstaller/compat.py", line 486, in exec_command_all
stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1335, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
继续填坑,根据github用户提示,打包出错原因是:使用pip安装的pyinstaller,已经预编译过bootloader。需要在Openwrt平台手动重新编译,再手动安装:
git clone https://github.com/pyinstaller/pyinstaller.git
cd pyinstaller && git checkout v3.1
cd bootloader
python ./waf distclean all --no-lsb
python waf configure --no-lsb build install
见 https://github.com/pyinstaller/pyinstaller/issues/2050#issuecomment-248525988
0x03
以为柳暗花明,猝不及防又一坑:
重编译bootloader过程中出现:无法识别gcc -m32
在源码wscript文件找到这个-m32,看注释描述:
# This ensures proper compilation with 64bit gcc and 32bit Python
# or vice versa or with manually choosen --target-arch.
# Option -m32/-m64 has to be passed to cflags and linkflages.
elif ctx.env.PYI_ARCH == '32bit':
# It was reported that flag '-m32' does not work with gcc
# on 32-bit arm Linux. So skip the -m32 flag.
if not (machine() == 'arm' and is_linux):
ctx.check_cc(ccflags='-m32', msg='Checking for flags -m32')
ctx.env.append_value('CFLAGS', '-m32')
ctx.env.append_value('LINKFLAGS', '-m32')
# Set LARGE_ADDRESS_AWARE_FLAG to True.
# On Windows this allows 32bit apps to use 4GB of memory and
# not only 2GB.
# TODO verify if this option being as default might cause any side effects.
if is_win:
ctx.env.append_value('LINKFLAGS', '-Wl,--large-address-aware')
elif ctx.env.PYI_ARCH == '64bit':
ctx.check_cc(ccflags='-m64', msg='Checking for flags -m64')
ctx.env.append_value('CFLAGS', '-m64')
ctx.env.append_value('LINKFLAGS', '-m64')
elif ctx.env.PYI_ARCH == '32bit':
pass掉就好了:
# This ensures proper compilation with 64bit gcc and 32bit Python
# or vice versa or with manually choosen --target-arch.
# Option -m32/-m64 has to be passed to cflags and linkflages.
elif ctx.env.PYI_ARCH == '32bit':
pass
# It was reported that flag '-m32' does not work with gcc
# on 32-bit arm Linux. So skip the -m32 flag.
# if not (machine() == None and machine() == 'arm' and is_linux):
# ctx.check_cc(ccflags='-m32', msg='Checking for flags -m32')
# ctx.env.append_value('CFLAGS', '-m32')
# ctx.env.append_value('LINKFLAGS', '-m32')
# Set LARGE_ADDRESS_AWARE_FLAG to True.
# On Windows this allows 32bit apps to use 4GB of memory and
# not only 2GB.
# TODO verify if this option being as default might cause any side effects.
# if is_win:
# ctx.env.append_value('LINKFLAGS', '-Wl,--large-address-aware')
elif ctx.env.PYI_ARCH == '64bit':
ctx.check_cc(ccflags='-m64', msg='Checking for flags -m64')
ctx.env.append_value('CFLAGS', '-m64')
ctx.env.append_value('LINKFLAGS', '-m64')
修改完毕,继续编译bootloader,根据提示增加需要的头文件,即可通过编译
0x04
最后一步,回到顶层目录,手动安装pyinstaller:
python setup.py install
搞定,附上一个打包成功的截图:
总结:安装gcc-->修改bootloader的wscript文件-->编译-->安装
第一次写博客,希望能帮助到有需要的童鞋 :)