From eb306ccbc64736fa7ea64fd25e7b71e33f3deb76 Mon Sep 17 00:00:00 2001 From: Le Philousophe Date: Sun, 17 Oct 2021 09:48:07 +0000 Subject: [PATCH] ALL: Add meson support --- toolchains/common/Dockerfile | 2 +- toolchains/common/functions.sh | 7 +- toolchains/common/meson-crossgen | 173 +++++++++++++++++++++++++++++++ toolchains/common/prepare.sh | 1 + toolchains/m4/paths.m4 | 3 + 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100755 toolchains/common/meson-crossgen diff --git a/toolchains/common/Dockerfile b/toolchains/common/Dockerfile index 0a23c1c..c92c388 100644 --- a/toolchains/common/Dockerfile +++ b/toolchains/common/Dockerfile @@ -1,4 +1,4 @@ FROM scratch -COPY prepare.sh functions.sh /lib-helpers/ +COPY prepare.sh functions.sh meson-crossgen /lib-helpers/ COPY packages /lib-helpers/packages/ diff --git a/toolchains/common/functions.sh b/toolchains/common/functions.sh index 3416689..fbb1159 100755 --- a/toolchains/common/functions.sh +++ b/toolchains/common/functions.sh @@ -111,6 +111,11 @@ __do_cmake () { -DBUILD_SHARED_LIBS=no "$@" .. } +__do_meson () { + meson --prefix=$PREFIX --cross-file cross.ini --buildtype release --default-library static "$@" _build + cd _build +} + __do_make () { local num_cpus num_cpus=$(nproc || grep -c ^processor /proc/cpuinfo || echo 1) @@ -130,7 +135,7 @@ __error () { # but still use base function (Poor man's inheritance) # Aliases are expanded at definition time so that's not the good way for f in do_make_bdir do_clean_bdir do_patch do_pkg_fetch do_http_fetch \ - do_git_fetch do_configure do_cmake do_make log error; do + do_git_fetch do_configure do_cmake do_meson do_make log error; do eval "$f () { __$f \"\$@\"; }" done diff --git a/toolchains/common/meson-crossgen b/toolchains/common/meson-crossgen new file mode 100755 index 0000000..3f85fef --- /dev/null +++ b/toolchains/common/meson-crossgen @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 + +# Copyright 2017 Jussi Pakkanen +# Copyright 2021 ScummVM team + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +import re +import shlex +import sys + +parser = argparse.ArgumentParser(description='''Generate cross compilation definition file for the Meson build system. + +This script must be run in an environment where CC, CXX, LD, CPPFLAGS, CFLAGS et al are set to the +same values used in the actual compilation. +''' +) + +parser.add_argument('--system', required=True, + help='The system to use.') +parser.add_argument('--cpu', required=True, + help='The cpu to generate.') +parser.add_argument('--sysroot', default=None, + help='The sysroot location.') +parser.add_argument('-o', required=True, dest='outfile', + help='The output file.') + +def locate_path(program): + if os.path.isabs(program): + return program + for d in os.get_exec_path(): + f = os.path.join(d, program) + if os.access(f, os.X_OK): + return f + raise ValueError("{0} not found on $PATH".format(program)) + +def get_value(v, context): + if callable(v): + return v(context) + return v + +def write_args_line(ofile, name, args): + if len(args) == 0: + return + ostr = '{0} = [{1}]\n'.format(name, + ', '.join("'{0}'".format(i) for i in args)) + ofile.write(ostr) + +BINARIES = { + 'AR': ('ar', None), + 'C': ('c', None), + 'CXX': ('cpp', None), + 'OBJCOPY': ('objcopy', None), + 'LD': ('ld', None), + 'PKG_CONFIG': ('pkgconfig', 'pkg-config'), + 'STRIP': ('strip', None), + 'WINDRES': ('windres', None), +} + +def write_binaries(ofile): + for envvar, (confvar, default) in BINARIES.items(): + binary = os.environ.get(envvar, default) + if binary: + ofile.write("{0} = '{1}'\n".format( + confvar, + locate_path(binary))) + +def write_args_from_envvars(ofile): + cppflags = shlex.split(os.environ.get('CPPFLAGS', '')) + cflags = shlex.split(os.environ.get('CFLAGS', '')) + cxxflags = shlex.split(os.environ.get('CXXFLAGS', '')) + ldflags = shlex.split(os.environ.get('LDFLAGS', '')) + + c_args = cppflags + cflags + cpp_args = cppflags + cxxflags + c_link_args = cflags + ldflags + cpp_link_args = cxxflags + ldflags + + write_args_line(ofile, 'c_args', c_args) + write_args_line(ofile, 'cpp_args', cpp_args) + write_args_line(ofile, 'c_link_args', c_link_args) + write_args_line(ofile, 'cpp_link_args', cpp_link_args) + +def write_properties(ofile, sysroot): + if not sysroot: + sysroot = os.environ.get('PKG_CONFIG_SYSROOT_DIR', None) + if sysroot: + ofile.write("sys_root = '{0}'\n".format(sysroot)) + + pkg_config_libdir = os.environ.get('PKG_CONFIG_LIBDIR', None) + if pkg_config_libdir: + ofile.write("pkg_config_libdir = '{0}'\n".format(pkg_config_libdir)) + +# Order in this list is important: most specific match first +CPUS = [ + {'key': r'(i[34567]86|pentium)', 'family': 'x86', 'bigendian': False }, + {'key': r'(x86_64|amd64)', 'family': 'x86_64', 'bigendian': False }, + {'key': r'alpha.*', 'family': 'alpha', 'bigendian': False }, + {'key': r'(arm64|aarch64).*', 'family': 'aarch64', 'bigendian': False, 'cpu': 'aarch64' }, + {'key': r'(arm.*)b', 'family': 'arm', 'bigendian': True, 'cpu': lambda m: m.group(1) }, + {'key': r'arm.*', 'family': 'arm', 'bigendian': False }, + {'key': r'avr32', 'family': 'avr', 'bigendian': True }, + {'key': r'ia64', 'family': 'ia64', 'bigendian': False }, + {'key': r'm32r', 'family': 'm32r', 'bigendian': True }, + {'key': r'm68k', 'family': 'm68k', 'bigendian': True }, + {'key': r'mips(32)?(eb)?', 'family': 'mips', 'bigendian': True, 'cpu': 'mips' }, + {'key': r'mips(32)?el', 'family': 'mips', 'bigendian': False, 'cpu': 'mips' }, + {'key': r'mips64', 'family': 'mips64', 'bigendian': True }, + {'key': r'mips64el', 'family': 'mips64', 'bigendian': False, 'cpu': 'mips64' }, + {'key': r'hppa.*', 'family': 'parisc', 'bigendian': True }, + {'key': r'(powerpc|ppc)', 'family': 'ppc', 'bigendian': True }, + {'key': r'powerpcle', 'family': 'ppc', 'bigendian': False, 'cpu': 'powerpc' }, + {'key': r'(powerpc|ppc)64', 'family': 'ppc64', 'bigendian': True }, + {'key': r'powerpc64le', 'family': 'ppc64', 'bigendian': False, 'cpu': 'powerpc64' }, + {'key': r'riscv64', 'family': 'riscv64', 'bigendian': False }, + {'key': r's390', 'family': 's390', 'bigendian': True }, + {'key': r's390x', 'family': 's390x', 'bigendian': True }, + {'key': r'sh4', 'family': 'sh4', 'bigendian': False }, + {'key': r'sh4eb', 'family': 'sh4', 'bigendian': True, 'cpu': 'sh4' }, + {'key': r'sparc', 'family': 'sparc', 'bigendian': True }, + {'key': r'sparc64', 'family': 'sparc64', 'bigendian': True }, +] +for cpu in CPUS: + cpu['key'] = re.compile(cpu['key']) + +def find_cpu(cpu_name): + for cpu in CPUS: + mtch = cpu['key'].match(cpu_name) + if mtch is None: + continue + + family = get_value(cpu['family'], mtch) + endian = 'big' if get_value(cpu['bigendian'], mtch) else 'little' + cpu_name = get_value(cpu.get('cpu', cpu_name), mtch) + + return { + 'cpu_family': family, + 'endian': endian, + 'cpu': cpu_name, + } + + raise LookupError("Can't find cpu {0}".format(cpu_name)) + +def run(options): + cpu = find_cpu(options.cpu) + os.makedirs(os.path.dirname(options.outfile), exist_ok=True) + with open(options.outfile, "w") as ofile: + ofile.write('[host_machine]\n') + ofile.write("system = '{0}'\n".format(options.system)) + for k, v in cpu.items(): + ofile.write("{0} = '{1}'\n".format(k, v)) + ofile.write('\n[binaries]\n') + write_binaries(ofile) + ofile.write('\n[built-in options]\n') + write_args_from_envvars(ofile) + ofile.write('\n[properties]\n') + write_properties(ofile, options.sysroot) + +if __name__ == '__main__': + options = parser.parse_args() + run(options) diff --git a/toolchains/common/prepare.sh b/toolchains/common/prepare.sh index bd0d705..5ae0925 100755 --- a/toolchains/common/prepare.sh +++ b/toolchains/common/prepare.sh @@ -17,6 +17,7 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ gnupg \ libtool \ make \ + meson \ pkg-config \ quilt \ unzip \ diff --git a/toolchains/m4/paths.m4 b/toolchains/m4/paths.m4 index 95423fd..6e2aaff 100644 --- a/toolchains/m4/paths.m4 +++ b/toolchains/m4/paths.m4 @@ -5,4 +5,7 @@ m4_define(`def_binaries', `m4_foreachq(`binary', `$2',`environmentalize(binary)= m4_define(`def_aclocal', `ACLOCAL_PATH=`$1'/share/aclocal') m4_define(`def_pkg_config', `PKG_CONFIG_LIBDIR=`$1'/lib/pkgconfig') +m4_define(`crossgen', ``COPY --from=helpers /lib-helpers/meson-crossgen lib-helpers/meson-crossgen'' +RUN $4 ``lib-helpers/meson-crossgen'' -o /usr/local/share/meson/cross/cross.ini --system=$1 --cpu=$2 $3) + m4_divert`'m4_dnl