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.
This commit is contained in:
Matthieu Gautier 2017-02-06 15:33:51 +01:00
parent 4adae738d5
commit 9f1942a0e1
4 changed files with 129 additions and 44 deletions

View File

@ -19,6 +19,33 @@ REMOTE_PREFIX = 'http://download.kiwix.org/dev/'
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) 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 = { PACKAGE_NAME_MAPPERS = {
'fedora_native_dyn': { 'fedora_native_dyn': {
@ -61,6 +88,13 @@ class Defaultdict(defaultdict):
def __getattr__(self, name): def __getattr__(self, name):
return 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): def remove_duplicates(iterable, key_function=None):
seen = set() seen = set()
if key_function is None: if key_function is None:
@ -176,57 +210,35 @@ class BuildEnv:
getattr(self, 'setup_{}'.format(self.build_target))() getattr(self, 'setup_{}'.format(self.build_target))()
def setup_native(self): def setup_native(self):
self.cross_env = {}
self.wrapper = None self.wrapper = None
self.cmake_command = "cmake"
self.configure_option = "" self.configure_option = ""
self.cmake_option = "" self.cmake_option = ""
self.cmake_crossfile = None
self.meson_crossfile = None self.meson_crossfile = None
def _get_rpm_mingw32(self, value): def _gen_crossfile(self, name):
command = "rpm --eval %{{mingw32_{}}}".format(value) crossfile = pj(self.build_dir, name)
output = subprocess.check_output(command, shell=True) template_file = pj(SCRIPT_DIR, 'templates', name)
return output[:-1].decode() with open(template_file, 'r') as f:
template = f.read()
def _gen_meson_crossfile(self): content = template.format(
self.meson_crossfile = pj(self.build_dir, 'cross_file.txt') which=Which(),
config = configparser.ConfigParser() root_path=self.cross_env['root_path']
config['binaries'] = { )
'c' : repr(self._get_rpm_mingw32('cc')), with open(crossfile, 'w') as outfile:
'cpp' : repr(self._get_rpm_mingw32('cxx')), outfile.write(content)
'ar' : repr(self._get_rpm_mingw32('ar')), return crossfile
'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 setup_win32(self): def setup_win32(self):
command = "rpm --eval %{mingw32_env}" self.cross_env = CROSS_ENV['win32']
self.wrapper = pj(self.build_dir, 'mingw32-wrapper.sh') self.wrapper = self._gen_crossfile('bash_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()
current_permissions = stat.S_IMODE(os.lstat(self.wrapper).st_mode) current_permissions = stat.S_IMODE(os.lstat(self.wrapper).st_mode)
os.chmod(self.wrapper, current_permissions | stat.S_IXUSR) os.chmod(self.wrapper, current_permissions | stat.S_IXUSR)
self.configure_option = "--host=i686-w64-mingw32" self.configure_option = "--host=i686-w64-mingw32"
self.cmake_command = "mingw32-cmake"
self.cmake_option = "" self.cmake_option = ""
self.cmake_crossfile = self._gen_crossfile('cmake_cross_file.txt')
self._gen_meson_crossfile() self.meson_crossfile = self._gen_crossfile('meson_cross_file.txt')
def __getattr__(self, name): def __getattr__(self, name):
return getattr(self.options, name) return getattr(self.options, name)
@ -278,6 +290,11 @@ class BuildEnv:
command = "{} {}".format(self.wrapper, command) command = "{} {}".format(self.wrapper, command)
if env is None: if env is None:
env = dict(os.environ) 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 log = None
try: try:
if not self.options.verbose: if not self.options.verbose:
@ -572,13 +589,18 @@ class MakeBuilder(Builder):
class CMakeBuilder(MakeBuilder): class CMakeBuilder(MakeBuilder):
def _configure(self, context): def _configure(self, context):
context.try_skip(self.build_path) 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 = command.format(
command = self.buildEnv.cmake_command,
configure_option = "{} {}".format(self.buildEnv.cmake_option, self.configure_option), configure_option = "{} {}".format(self.buildEnv.cmake_option, self.configure_option),
install_dir = self.buildEnv.install_dir, install_dir = self.buildEnv.install_dir,
libdir = self.buildEnv.libprefix, 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) env = Defaultdict(str, os.environ)
if self.buildEnv.build_static: if self.buildEnv.build_static:
@ -615,7 +637,13 @@ class MesonBuilder(Builder):
else: else:
library_type = 'shared' library_type = 'shared'
configure_option = self.configure_option.format(buildEnv=self.buildEnv) 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, command = self.buildEnv.meson_command,
library_type=library_type, library_type=library_type,
configure_option=configure_option, configure_option=configure_option,

21
templates/bash_wrapper.sh Normal file
View File

@ -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 "$@"

View File

@ -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)

View File

@ -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'