From 9f1942a0e12039f1d0f38c254eb7cdc398362644 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Mon, 6 Feb 2017 15:33:51 +0100 Subject: [PATCH] Do not depends on custom fedora tools for cross-compile. Fedora provides a set of (powerfull) tools to correctly pass the right options to compilation tools (configure, cmake, ...) This is great but we must not use them as we want to cross-compile from other distribution (ubuntu). Now, we do not use those tools and we can easily port cross-compilation to ubuntu. --- kiwix-build.py | 116 ++++++++++++++++++++------------- templates/bash_wrapper.sh | 21 ++++++ templates/cmake_cross_file.txt | 19 ++++++ templates/meson_cross_file.txt | 17 +++++ 4 files changed, 129 insertions(+), 44 deletions(-) create mode 100644 templates/bash_wrapper.sh create mode 100644 templates/cmake_cross_file.txt create mode 100644 templates/meson_cross_file.txt diff --git a/kiwix-build.py b/kiwix-build.py index c264ab0..f1b7e97 100755 --- a/kiwix-build.py +++ b/kiwix-build.py @@ -19,6 +19,33 @@ REMOTE_PREFIX = 'http://download.kiwix.org/dev/' SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +CROSS_ENV = { + 'win32' : { + 'root_path' : '/usr/i686-w64-mingw32/sys-root/mingw', + 'binaries' : { + 'c' : 'i686-w64-mingw32-gcc', + 'cpp' : 'i686-w64-mingw32-g++', + 'ar' : 'i686-w64-mingw32-ar', + 'strip' : 'i686-w64-mingw32-strip', + 'pkgconfig' : 'i686-w64-mingw32-pkg-config', + 'exe_wrapper' : 'wine' + }, + 'properties' : { + 'c_link_args': ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'], + 'cpp_link_args': ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'] + }, + 'host_machine' : { + 'system' : 'windows', + 'cpu_family' : 'x86', + 'cpu' : 'i686', + 'endian' : 'little' + }, + 'env': { + '_format_PKG_CONFIG_LIBDIR' : '{root_path}/lib/pkgconfig' + } + } +} + PACKAGE_NAME_MAPPERS = { 'fedora_native_dyn': { @@ -61,6 +88,13 @@ class Defaultdict(defaultdict): def __getattr__(self, name): return self[name] + +class Which(): + def __getattr__(self, name): + command = "which {}".format(name) + output = subprocess.check_output(command, shell=True) + return output[:-1].decode() + def remove_duplicates(iterable, key_function=None): seen = set() if key_function is None: @@ -176,57 +210,35 @@ class BuildEnv: getattr(self, 'setup_{}'.format(self.build_target))() def setup_native(self): + self.cross_env = {} self.wrapper = None - self.cmake_command = "cmake" self.configure_option = "" self.cmake_option = "" + self.cmake_crossfile = None self.meson_crossfile = None - def _get_rpm_mingw32(self, value): - command = "rpm --eval %{{mingw32_{}}}".format(value) - output = subprocess.check_output(command, shell=True) - return output[:-1].decode() - - def _gen_meson_crossfile(self): - self.meson_crossfile = pj(self.build_dir, 'cross_file.txt') - config = configparser.ConfigParser() - config['binaries'] = { - 'c' : repr(self._get_rpm_mingw32('cc')), - 'cpp' : repr(self._get_rpm_mingw32('cxx')), - 'ar' : repr(self._get_rpm_mingw32('ar')), - 'strip' : repr(self._get_rpm_mingw32('strip')), - 'pkgconfig' : repr(self._get_rpm_mingw32('pkg_config')), - 'exe_wrapper' : repr('wine') # A command used to run generated executables. - } - config['properties'] = { - 'c_link_args': ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'], - 'cpp_link_args': ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'] - } - config['host_machine'] = { - 'system' : repr('windows'), - 'cpu_family' : repr('x86'), - 'cpu' : repr('i586'), - 'endian' : repr('little') - } - with open(self.meson_crossfile, 'w') as configfile: - config.write(configfile) + def _gen_crossfile(self, name): + crossfile = pj(self.build_dir, name) + template_file = pj(SCRIPT_DIR, 'templates', name) + with open(template_file, 'r') as f: + template = f.read() + content = template.format( + which=Which(), + root_path=self.cross_env['root_path'] + ) + with open(crossfile, 'w') as outfile: + outfile.write(content) + return crossfile def setup_win32(self): - command = "rpm --eval %{mingw32_env}" - self.wrapper = pj(self.build_dir, 'mingw32-wrapper.sh') - with open(self.wrapper, 'w') as output: - output.write("#!/usr/bin/sh\n\n") - output.flush() - output.write(self._get_rpm_mingw32('env')) - output.write('\n\nexec "$@"\n') - output.flush() + self.cross_env = CROSS_ENV['win32'] + self.wrapper = self._gen_crossfile('bash_wrapper.sh') current_permissions = stat.S_IMODE(os.lstat(self.wrapper).st_mode) os.chmod(self.wrapper, current_permissions | stat.S_IXUSR) self.configure_option = "--host=i686-w64-mingw32" - self.cmake_command = "mingw32-cmake" self.cmake_option = "" - - self._gen_meson_crossfile() + self.cmake_crossfile = self._gen_crossfile('cmake_cross_file.txt') + self.meson_crossfile = self._gen_crossfile('meson_cross_file.txt') def __getattr__(self, name): return getattr(self.options, name) @@ -278,6 +290,11 @@ class BuildEnv: command = "{} {}".format(self.wrapper, command) if env is None: env = dict(os.environ) + for k, v in self.cross_env.get('env', {}).items(): + if k.startswith('_format_'): + v = v.format(**self.cross_env) + k = k[8:] + env[k] = v log = None try: if not self.options.verbose: @@ -572,13 +589,18 @@ class MakeBuilder(Builder): class CMakeBuilder(MakeBuilder): def _configure(self, context): context.try_skip(self.build_path) - command = "{command} {configure_option} -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DCMAKE_INSTALL_PREFIX={install_dir} -DCMAKE_INSTALL_LIBDIR={libdir} {source_path}" + command = ("cmake {configure_option}" + " -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON" + " -DCMAKE_INSTALL_PREFIX={install_dir}" + " -DCMAKE_INSTALL_LIBDIR={libdir}" + " {source_path}" + " {cross_option}") command = command.format( - command = self.buildEnv.cmake_command, configure_option = "{} {}".format(self.buildEnv.cmake_option, self.configure_option), install_dir = self.buildEnv.install_dir, libdir = self.buildEnv.libprefix, - source_path = self.source_path + source_path = self.source_path, + cross_option = "-DCMAKE_TOOLCHAIN_FILE={}".format(self.buildEnv.cmake_crossfile) if self.buildEnv.cmake_crossfile else "" ) env = Defaultdict(str, os.environ) if self.buildEnv.build_static: @@ -615,7 +637,13 @@ class MesonBuilder(Builder): else: library_type = 'shared' configure_option = self.configure_option.format(buildEnv=self.buildEnv) - command = "{command} --default-library={library_type} {configure_option} . {build_path} --prefix={buildEnv.install_dir} --libdir={buildEnv.libprefix} {cross_option}".format( + command = ("{command} . {build_path}" + " --default-library={library_type}" + " {configure_option}" + " --prefix={buildEnv.install_dir}" + " --libdir={buildEnv.libprefix}" + " {cross_option}") + command = command.format( command = self.buildEnv.meson_command, library_type=library_type, configure_option=configure_option, diff --git a/templates/bash_wrapper.sh b/templates/bash_wrapper.sh new file mode 100644 index 0000000..258c657 --- /dev/null +++ b/templates/bash_wrapper.sh @@ -0,0 +1,21 @@ +#!/usr/bin/sh + + +if test -z "$PATH_ORIG" ; then + PATH_ORIG="$PATH"; export PATH_ORIG; +fi; + +PATH="{root_path}/bin:$PATH_ORIG"; export PATH; + +HOST_CC=gcc; export HOST_CC; +unset PKG_CONFIG_PATH; + +CC={which.i686-w64-mingw32-gcc}; export CC +AR={which.i686-w64-mingw32-ar}; export AR +CXX={which.i686-w64-mingw32-g++}; export CXX +STRIP={which.i686-w64-mingw32-strip}; export STRIP +CFLAGS=" -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4"; export CFLAGS; +CXXFLAGS=" -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions --param=ssp-buffer-size=4"; export CXXFLAGS; + + +exec "$@" diff --git a/templates/cmake_cross_file.txt b/templates/cmake_cross_file.txt new file mode 100644 index 0000000..4a1ceb2 --- /dev/null +++ b/templates/cmake_cross_file.txt @@ -0,0 +1,19 @@ +SET(CMAKE_SYSTEM_NAME Windows) +SET(CMAKE_SYSTEM_PROCESSOR x86) + +# specify the cross compiler +SET(CMAKE_C_COMPILER {which.i686-w64-mingw32-gcc}) +SET(CMAKE_CXX_COMPILER {which.i686-w64-mingw32-g++}) +SET(CMAKE_RC_COMPILER {which.i686-w64-mingw32-windres}) +SET(CMAKE_AR:FILEPATH {which.i686-w64-mingw32-ar}) +SET(CMAKE_RANLIB:FILEPATH {which.i686-w64-mingw32-ranlib}) + +# where is the target environment +SET(CMAKE_FIND_ROOT_PATH {root_path}) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + diff --git a/templates/meson_cross_file.txt b/templates/meson_cross_file.txt new file mode 100644 index 0000000..786b685 --- /dev/null +++ b/templates/meson_cross_file.txt @@ -0,0 +1,17 @@ +[binaries] +pkgconfig = 'pkg-config' +c = '{which.i686-w64-mingw32-gcc}' +ar = '{which.i686-w64-mingw32-ar}' +cpp = '{which.i686-w64-mingw32-g++}' +strip = '{which.i686-w64-mingw32-strip}' +exe_wrapper = 'wine' + +[properties] +c_link_args = ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'] +cpp_link_args = ['-lwinmm', '-lws2_32', '-lshlwapi', '-lrpcrt4'] + +[host_machine] +cpu_family = 'x86' +cpu = 'i586' +system = 'windows' +endian = 'little'