From 4cbbf2325b33b2d0002019d0cdb8982760582567 Mon Sep 17 00:00:00 2001 From: cm8 Date: Sat, 23 Jun 2018 11:18:08 +0200 Subject: [PATCH] cleanup mips32r2.py and use python class inheritance for flavors added mips32r2_uclibc_gclibcxx_dyn, (preferred atm, tested on prod hw) mips32r2_uclibc_gclibcxx_static targets (shared) and renamed previous uclibc ones to mips32r2_uclibc_uclibcxx_dyn, mips32r2_uclibc_uclibcxx_static for clarity (i.e. non-shared, pure ones) reworked builder classes to use inheritance of properties and methods (instead of copying boiler plate code) mips32r2_uclibc_gclibcxx_dyn target compiles and tested to run on production targets such as avm routers modified with a freetz env. See cm8/freetz@41d97c378987786111ef78c30aa8de597e53f7e2 for one of many possible projects to build a working toolchain with. In short - git clone - umask 0022 - make menuconfig (choose expert, disable toolchain download and let the toolchain/make scripts built a gcc-5.x one, do not forget to set FREETZ_LIB_libuClibc__WITH_WCHAR=y) - read the commit message for further info on long double math peculiarities - tested here with 0.9.33.2 Remember that swap will need to be running on the box, or else kiwix-serve is likely to quit with "invalid lzma stream in cluster" errors (if memory is too low). If the box lacks library support such as libstdc++.so*, you can copy them from the target toolchain libdir over to BUILD_mips32r2_uclibc_gclibcxx_dyn/INSTALL/lib if there are unsatisfied dependencies at runtime. (Which libraries need to be supplemented this way depends on your firmware and/or freetz configuration). Another issue is the execution in non-standard installation directories. LD_LIBRARY_PATH env needs to point to "our" lib directory. If you tar INSTALL/ dir, transport the result to an embedded device, untar and wan't to run from there, it is best to wrap all the elf binaries with a shell script that correctly sets LD_LIBRARY_PATH. This step has been automated, but needs testing, see kiwixbuild/patches/fixenv-run-in-nonstd-installdir.sh for details. This fixenv script is copied to INSTALL/bin during the build and it should be run on the box, if kiwix-tools is to reside in nonstd location (i.e. if files are not installed or installable to /bin, /lib or their usr/ pendants). Feel free to improve on automation of the necessary setup steps to make mips port build and deployment easier. --- .../fixenv-run-in-nonstd-installdir.sh | 39 +++++ kiwixbuild/platforms/mips32r2.py | 150 ++++++++---------- 2 files changed, 106 insertions(+), 83 deletions(-) create mode 100644 kiwixbuild/patches/fixenv-run-in-nonstd-installdir.sh diff --git a/kiwixbuild/patches/fixenv-run-in-nonstd-installdir.sh b/kiwixbuild/patches/fixenv-run-in-nonstd-installdir.sh new file mode 100644 index 0000000..ebd97f5 --- /dev/null +++ b/kiwixbuild/patches/fixenv-run-in-nonstd-installdir.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +if ! test -f kiwix-serve +then + echo Needs to run in the same directory that hosts kiwix-serve binary. + exit 1 +fi + +find -type f | \ +while read +do + if hexdump -C $REPLY | head -1 | grep -q ELF + then + mv -iv "$REPLY" "$REPLY.real" + ln -s run-nonroot "$REPLY" + fi +done + +cat < run-nonroot +#!/bin/sh + +BASENAME=`basename $0` +SCRIPT=`realpath $0` +SCRIPTPATH=`dirname $SCRIPT` + +if test x"$BASENAME" != xrun-nonroot +then + for fullarch in "" mips-linux-gnu + do for libdir in usr/lib lib + do LD_LIBRARY_PATH="${SCRIPTPATH%/bin}/$libdir/$fullarch:$LD_LIBRARY_PATH" + done + done + + export LD_LIBRARY_PATH + exec ${SCRIPTPATH}/$BASENAME.real "$@" +fi +EOF + +chmod +x run-nonroot diff --git a/kiwixbuild/platforms/mips32r2.py b/kiwixbuild/platforms/mips32r2.py index 05e50cd..b99c849 100644 --- a/kiwixbuild/platforms/mips32r2.py +++ b/kiwixbuild/platforms/mips32r2.py @@ -2,10 +2,13 @@ from .base import PlatformInfo from kiwixbuild.utils import pj from kiwixbuild._global import get_target_step +from os import makedirs, chmod +from shutil import copy +from .base import _SCRIPT_DIR class MIPS32R2PlatformInfo(PlatformInfo): - build = 'mips32r2' + build = 'mips32r2_glibc_glibcxx' arch_full = 'mips-linux-gnu' compatible_hosts = ['fedora', 'debian'] @@ -28,11 +31,24 @@ class MIPS32R2PlatformInfo(PlatformInfo): @property def root_path(self): + # apt-get'able debian/ubuntu hard-float glibc glibcxx toolchain return '/usr/mips-linux-gnu' + @property + def tcbindir(self): + return pj(self.root_path, 'bin') + + @property + def tcbinprefix(self): + return '../../bin/' + self.arch_full + '-' + + @property + def tclibdir(self): + return pj(self.root_path, 'lib') + @property def binaries(self): - binaries = ((k,'{}-{}'.format(self.arch_full, v)) + binaries = ((k,'{}{}'.format(self.tcbinprefix, v)) for k, v in (('CC', 'gcc'), ('CXX', 'g++'), ('AR', 'ar'), @@ -41,7 +57,7 @@ class MIPS32R2PlatformInfo(PlatformInfo): ('RANLIB', 'ranlib'), ('LD', 'ld')) ) - return {k:pj('/usr', 'bin', v) + return {k:pj(self.tcbindir, v) for k,v in binaries} @property @@ -57,23 +73,14 @@ class MIPS32R2PlatformInfo(PlatformInfo): def configure_option(self): return '--host={}'.format(self.arch_full) - def get_bin_dir(self): - return [pj(self.root_path, 'bin')] - def set_env(self, env): - env['PKG_CONFIG_LIBDIR'] = pj(self.root_path, 'lib', 'pkgconfig') - # soft float is another abi and thus unsupported by current maintained (apt-get'able) debian/ubuntu tcs, - # additionally these are (gnu) libc only; if uclibc is needed, see https://buildroot.org/downloads/ and - # make a toolchain and rootfs, then checkout and use kiwixbuild --target_platform native_* within chroot env - # (it needs qemu-mips-static from host copied to rootfs/usr/bin, in order to chroot into using a non-mips-host) - #env['CFLAGS'] = " -march=mips32r2 -mtune=24kc -msoft-float "+env['CFLAGS'] - #env['CXXFLAGS'] = " -march=mips32r2 -mtune=24kc -msoft-float "+env['CXXFLAGS'] - env['CFLAGS'] = " -march=mips32r2 -mtune=24kc "+env['CFLAGS'] + env['PKG_CONFIG_LIBDIR'] = pj(self.tclibdir, 'pkgconfig') + env['CFLAGS'] = " -march=mips32r2 -mtune=24kc "+env['CFLAGS'] env['CXXFLAGS'] = " -march=mips32r2 -mtune=24kc "+env['CXXFLAGS'] env['QEMU_LD_PREFIX'] = pj(self.root_path) env['QEMU_SET_ENV'] = "LD_LIBRARY_PATH={}".format( ':'.join([ - pj(self.root_path, "lib"), + pj(self.tclibdir), env['LD_LIBRARY_PATH'] ])) @@ -97,88 +104,65 @@ class MIPS32R2Static(MIPS32R2PlatformInfo): -class MIPS32R2_UCLIBCPlatformInfo(PlatformInfo): - build = 'mips32r2_uclibc' +class MIPS32R2_UC_GCXXPlatformInfo(MIPS32R2PlatformInfo): + build = 'mips32r2_uclibc_gclibcxx' # "shared, heterogenous" (gnu c++ lib "on top of" uClibc) arch_full = 'mips-linux-uclibc' - compatible_hosts = ['fedora', 'debian'] - - def get_cross_config(self): - return { - 'binaries': self.binaries, - 'exec_wrapper_def': '', - 'root_path': self.root_path, - 'extra_libs': [ '-lm' ], - 'extra_cflags': [], - 'host_machine': { - 'system': 'linux', - 'lsystem': 'linux', - 'cpu_family': 'mips32r2', - 'cpu': '24kc', - 'endian': 'big', - 'abi': '' - } - } @property def root_path(self): return '/dev/shm/freetz/toolchain/build/mips_gcc-5.5.0_uClibc-0.9.33.2-nptl/mips-linux-uclibc' @property - def binaries(self): - binaries = ((k,'{}-{}'.format(self.arch_full, v)) - for k, v in (('CC', 'gcc'), - ('CXX', 'g++-uc'), - ('AR', 'ar'), - ('STRIP', 'strip'), - ('WINDRES', 'windres'), - ('RANLIB', 'ranlib'), - ('LD', 'ld')) - ) - return {k:pj(self.root_path, 'usr', 'bin', v) - for k,v in binaries} - - @property - def exec_wrapper_def(self): - try: - which('qemu-mips-static') - except subprocess.CalledProcessError: - return "" - else: - return "exec_wrapper = 'qemu-mips-static'" - - @property - def configure_option(self): - return '--host={}'.format(self.arch_full) - - def get_bin_dir(self): - return [pj(self.root_path, 'bin')] + def tcbinprefix(self): + return self.arch_full + '-' def set_env(self, env): - # altering PATH for mips-linux-uclibc-g++-uc wrapper to find real binary - env['PATH'] = ':'.join([pj(self.root_path, 'usr', 'bin'), env['PATH']]) - env['PKG_CONFIG_LIBDIR'] = pj(self.root_path, 'lib', 'pkgconfig') - env['CFLAGS'] = " -march=mips32r2 -mtune=24kc -msoft-float -Os -pipe -Wa,--trap "+env['CFLAGS'] - env['CXXFLAGS'] = " -march=mips32r2 -mtune=24kc -msoft-float -Os -pipe -Wa,--trap "+env['CXXFLAGS'] - env['QEMU_LD_PREFIX'] = pj(self.root_path) - env['QEMU_SET_ENV'] = "LD_LIBRARY_PATH={}".format( - ':'.join([ - pj(self.root_path, "lib"), - env['LD_LIBRARY_PATH'] - ])) + super().set_env(env) + env['CFLAGS'] = " -msoft-float -Os -pipe -Wa,--trap "+env['CFLAGS'] + env['CXXFLAGS'] = " -msoft-float -Os -pipe -Wa,--trap "+env['CXXFLAGS'] - def set_compiler(self, env): - env['CC'] = self.binaries['CC'] - env['CXX'] = self.binaries['CXX'] +class MIPS32R2_UC_GCXXDyn(MIPS32R2_UC_GCXXPlatformInfo): + name = 'mips32r2_uclibc_gclibcxx_dyn' + static = False def finalize_setup(self): super().finalize_setup() - self.buildEnv.cmake_crossfile = self._gen_crossfile('cmake_cross_file.txt') - self.buildEnv.meson_crossfile = self._gen_crossfile('meson_cross_file.txt') + dest = pj(_SCRIPT_DIR, '..', '..', 'BUILD_'+self.name, 'INSTALL', 'bin') + makedirs(dest, mode=0o755, exist_ok=True) + dest = pj(dest, 'fixenv-run-in-nonstd-installdir.sh') + copy(pj(_SCRIPT_DIR, '..', 'patches', 'fixenv-run-in-nonstd-installdir.sh'), dest) + chmod(dest, 0o755) -class MIPS32R2_UCLIBCDyn(MIPS32R2_UCLIBCPlatformInfo): - name = 'mips32r2_uclibc_dyn' +class MIPS32R2_UC_GCXXStatic(MIPS32R2_UC_GCXXPlatformInfo): + name = 'mips32r2_uclibc_gclibcxx_static' + static = True + + + + +class MIPS32R2_UC_UCXXPlatformInfo(MIPS32R2_UC_GCXXPlatformInfo): + build = 'mips32r2_uclibc_uclibcxx' # "pure, homogenous" + + def get_cross_config(self): + conf = super().get_cross_config() + conf['extra_libs'] += [ '-lm' ] + return conf + + @property + def binaries(self): + bins = super().binaries + bins['CXX'] += '-uc' + return bins + + def set_env(self, env): + super().set_env(env) + # for mips-linux-uclibc-g++-uc wrapper to find real binary + env['PATH'] = ':'.join([pj(self.tcbindir), env['PATH']]) + +class MIPS32R2_UC_UCXXDyn(MIPS32R2_UC_UCXXPlatformInfo): + name = 'mips32r2_uclibc_uclibcxx_dyn' static = False -class MIPS32R2_UCLIBCStatic(MIPS32R2_UCLIBCPlatformInfo): - name = 'mips32r2_uclibc_static' +class MIPS32R2_UC_UCXXStatic(MIPS32R2_UC_UCXXPlatformInfo): + name = 'mips32r2_uclibc_uclibcxx_static' static = True