aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2022-02-19 18:17:28 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2022-02-19 18:17:28 +0200
commit623e57d088e480164d3d4fdadf00ce007f7121f9 (patch)
treeacf88709f5b8a480a337eac234b8a966a658b287
parent9daaece7850cdd378163cd50bc524693f5294309 (diff)
downloadmeson-env2cross.zip
meson-env2cross.tar.gz
meson-env2cross.tar.bz2
Add new env2cross command.env2cross
-rw-r--r--docs/markdown/snippets/env2cross.md7
-rw-r--r--mesonbuild/mesonmain.py4
-rwxr-xr-xmesonbuild/scripts/env2cross.py182
3 files changed, 192 insertions, 1 deletions
diff --git a/docs/markdown/snippets/env2cross.md b/docs/markdown/snippets/env2cross.md
new file mode 100644
index 0000000..6ebbc15
--- /dev/null
+++ b/docs/markdown/snippets/env2cross.md
@@ -0,0 +1,7 @@
+## Command to convert environments to cross files
+
+Add proper documentation here once the API has been finalized
+
+ meson env2cross --debarch armhf -o debarmhf.cross
+
+Also update the main cross compilation markdown files.
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 7a4e421..b069e03 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -30,7 +30,7 @@ from . import mconf, mdist, minit, minstall, mintro, msetup, mtest, rewriter, ms
from .mesonlib import MesonException, MesonBugException
from .environment import detect_msys2_arch
from .wrap import wraptool
-
+from .scripts import env2cross
# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
@@ -70,6 +70,8 @@ class CommandLineParser:
help_msg='Build the project')
self.add_command('devenv', mdevenv.add_arguments, mdevenv.run,
help_msg='Run commands in developer environment')
+ self.add_command('env2cross', env2cross.add_arguments, env2cross.run,
+ help_msg='Convert current environment to a cross file')
# Hidden commands
self.add_command('runpython', self.add_runpython_arguments, self.run_runpython_command,
diff --git a/mesonbuild/scripts/env2cross.py b/mesonbuild/scripts/env2cross.py
new file mode 100755
index 0000000..570549e
--- /dev/null
+++ b/mesonbuild/scripts/env2cross.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+
+# Copyright 2017 Jussi Pakkanen
+
+# 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 sys, os, subprocess, shutil
+
+import argparse
+
+def add_arguments(parser: 'argparse.ArgumentParser') -> None:
+ parser.add_argument('--debarch', default=None,
+ help='The dpkg architecture to generate.')
+ parser.add_argument('--gccsuffix', default="",
+ help='A particular gcc version suffix if necessary.')
+ parser.add_argument('-o', required=True, dest='outfile',
+ help='The output file.')
+
+#parser = argparse.ArgumentParser(description='''Generate cross compilation definition file for the Meson build system.
+#
+#If you do not specify the --arch argument, Meson assumes that running
+#plain 'dpkg-architecture' will return correct information for the
+#host system.
+#
+#This script must be run in an environment where CPPFLAGS et al are set to the
+#same values used in the actual compilation.
+#'''
+#)
+
+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("%s not found on $PATH" % program)
+
+def write_args_line(ofile, name, args):
+ if len(args) == 0:
+ return
+ ostr = name + ' = ['
+ ostr += ', '.join("'" + i + "'" for i in args)
+ ostr += ']\n'
+ ofile.write(ostr)
+
+def write_args_from_envvars(ofile):
+ import shlex
+ 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)
+
+cpu_family_map = dict(mips64el="mips64",
+ i686='x86')
+cpu_map = dict(armhf="arm7hlf",
+ mips64el="mips64",)
+
+class CrossInfo:
+ def __init__(self):
+ self.compilers = {}
+ self.binaries = {}
+ self.properties = {}
+
+ self.system = None
+ self.cpu = None
+ self.cpu_family = None
+ self.endian = None
+
+def deb_compiler_lookup(infos, compilerstems, host_arch, gccsuffix):
+ for langname, stem in compilerstems:
+ compilername = f'{host_arch}-{stem}{gccsuffix}'
+ try:
+ p = locate_path(compilername)
+ infos.compilers[langname] = p
+ except ValueError:
+ pass
+
+def detect_debianlike(options):
+ if options.debarch is None:
+ cmd = ['dpkg-architecture']
+ else:
+ cmd = ['dpkg-architecture', '-a' + options.debarch]
+ output = subprocess.check_output(cmd, universal_newlines=True,
+ stderr=subprocess.DEVNULL)
+ data = {}
+ for line in output.split('\n'):
+ line = line.strip()
+ if line == '':
+ continue
+ k, v = line.split('=', 1)
+ data[k] = v
+ host_arch = data['DEB_HOST_GNU_TYPE']
+ host_os = data['DEB_HOST_ARCH_OS']
+ host_cpu_family = cpu_family_map.get(data['DEB_HOST_GNU_CPU'],
+ data['DEB_HOST_GNU_CPU'])
+ host_cpu = cpu_map.get(data['DEB_HOST_ARCH'],
+ data['DEB_HOST_ARCH'])
+ host_endian = data['DEB_HOST_ARCH_ENDIAN']
+
+ compilerstems = [('c', 'gcc'),
+ ('cpp', 'h++'),
+ ('objc', 'gobjc'),
+ ('objcpp', 'gobjc++')]
+ infos = CrossInfo()
+ deb_compiler_lookup(infos, compilerstems, host_arch, options.gccsuffix)
+ if len(infos.compilers) == 0:
+ print('Warning: no compilers were detected.')
+ infos.binaries['ar'] = locate_path("%s-ar" % host_arch)
+ infos.binaries['strip'] = locate_path("%s-strip" % host_arch)
+ infos.binaries['objcopy'] = locate_path("%s-objcopy" % host_arch)
+ infos.binaries['ld'] = locate_path("%s-ld" % host_arch)
+ try:
+ infos.binaries['pkgconfig'] = locate_path("%s-pkg-config" % host_arch)
+ except ValueError:
+ pass # pkg-config is optional
+ try:
+ infos.binaries['cups-config'] = locate_path("cups-config")
+ except ValueError:
+ pass
+ infos.system = host_os
+ infos.cpu_family = host_cpu_family
+ infos.cpu = host_cpu
+ infos.endian = host_endian
+
+ return infos
+
+def write_crossfile(infos, ofilename):
+ tmpfilename = ofilename + '~'
+ with open(tmpfilename, 'w') as ofile:
+ ofile.write('[binaries]\n')
+ ofile.write('# Compilers\n')
+ for langname in sorted(infos.compilers.keys()):
+ compiler = infos.compilers[langname]
+ ofile.write(f"{langname} = '{compiler}'\n")
+ ofile.write('\n')
+
+ ofile.write('# Other binaries\n')
+ for exename in sorted(infos.binaries.keys()):
+ exe = infos.binaries[exename]
+ ofile.write(f"{exename} = '{exe}'\n")
+ ofile.write('\n')
+
+ ofile.write('[host_machine]\n')
+ ofile.write(f"cpu = '{infos.cpu}'\n")
+ ofile.write(f"cpu_family = '{infos.cpu_family}'\n")
+ ofile.write(f"endian = '{infos.endian}'\n")
+ ofile.write(f"system = '{infos.system}'\n")
+ os.replace(tmpfilename, ofilename)
+
+def run(options):
+ if options.debarch:
+ print('Detecting cross environment via dpkg-reconfigure.')
+ infos = detect_debianlike(options)
+ else:
+ #print('Detecting cross environment via environment variables')
+ sys.exit('Can currently only detect debianlike. Patches welcome.')
+ write_crossfile(infos, options.outfile)
+
+if __name__ == '__main__':
+ options = parser.parse_args()
+ run(options)