diff options
Diffstat (limited to 'meson')
-rw-r--r-- | meson/backends.py | 15 | ||||
-rwxr-xr-x | meson/commandrunner.py | 55 | ||||
-rwxr-xr-x | meson/delwithsuffix.py | 32 | ||||
-rwxr-xr-x | meson/depfixer.py | 299 | ||||
-rwxr-xr-x | meson/dirchanger.py | 26 | ||||
-rw-r--r-- | meson/environment.py | 2 | ||||
-rwxr-xr-x | meson/gtkdochelper.py | 118 | ||||
-rwxr-xr-x | meson/meson_benchmark.py | 97 | ||||
-rwxr-xr-x | meson/meson_install.py | 227 | ||||
-rwxr-xr-x | meson/meson_test.py | 232 | ||||
-rwxr-xr-x | meson/mesonconf.py | 205 | ||||
-rwxr-xr-x | meson/mesongui.py | 561 | ||||
-rwxr-xr-x | meson/mesonintrospect.py | 208 | ||||
-rw-r--r--[-rwxr-xr-x] | meson/mesonmain.py | 3 | ||||
-rw-r--r-- | meson/ninjabackend.py | 2 | ||||
-rwxr-xr-x | meson/regen_checker.py | 42 | ||||
-rwxr-xr-x | meson/symbolextractor.py | 102 | ||||
-rwxr-xr-x | meson/vcstagger.py | 33 | ||||
-rw-r--r-- | meson/wrap.py | 30 | ||||
-rwxr-xr-x | meson/wraptool.py | 233 |
20 files changed, 45 insertions, 2477 deletions
diff --git a/meson/backends.py b/meson/backends.py index 2706368..c583a7b 100644 --- a/meson/backends.py +++ b/meson/backends.py @@ -19,6 +19,21 @@ from . import mesonlib import json from .coredata import MesonException +class InstallData(): + def __init__(self, source_dir, build_dir, prefix, depfixer): + self.source_dir = source_dir + self.build_dir= build_dir + self.prefix = prefix + self.targets = [] + self.depfixer = depfixer + self.headers = [] + self.man = [] + self.data = [] + self.po_package_name = '' + self.po = [] + self.install_scripts = [] + self.install_subdirs = [] + class TestSerialisation: def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env, should_fail, valgrind_args, timeout, workdir, extra_paths): diff --git a/meson/commandrunner.py b/meson/commandrunner.py deleted file mode 100755 index 0dad585..0000000 --- a/meson/commandrunner.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2014 The Meson development 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. - -"""This program is a wrapper to run external commands. It determines -what to run, sets up the environment and executes the command.""" - -import sys, os, subprocess, shutil - -def run_command(source_dir, build_dir, subdir, command, arguments): - env = {'MESON_SOURCE_ROOT' : source_dir, - 'MESON_BUILD_ROOT' : build_dir, - 'MESON_SUBDIR' : subdir - } - cwd = os.path.join(source_dir, subdir) - child_env = os.environ.copy() - child_env.update(env) - - # Is the command an executable in path? - exe = shutil.which(command) - if exe is not None: - command_array = [exe] + arguments - return subprocess.Popen(command_array, env=child_env, cwd=cwd) - # No? Maybe it is a script in the source tree. - fullpath = os.path.join(source_dir, subdir, command) - command_array = [fullpath] + arguments - try: - return subprocess.Popen(command_array,env=child_env, cwd=cwd) - except FileNotFoundError: - print('Could not execute command "%s".' % command) - sys.exit(1) - -if __name__ == '__main__': - if len(sys.argv) < 5: - print(sys.argv[0], '<source dir> <build dir> <subdir> <command> [arguments]') - src_dir = sys.argv[1] - build_dir = sys.argv[2] - subdir = sys.argv[3] - command = sys.argv[4] - arguments = sys.argv[5:] - pc = run_command(src_dir, build_dir, subdir, command, arguments) - pc.wait() - sys.exit(pc.returncode) diff --git a/meson/delwithsuffix.py b/meson/delwithsuffix.py deleted file mode 100755 index 4b8a60d..0000000 --- a/meson/delwithsuffix.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013 The Meson development 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 os, sys - -if len(sys.argv) != 3: - print('%s <root of subdir to process> <suffix to delete>' % sys.argv[0]) - sys.exit(1) - -topdir = sys.argv[1] -suffix = sys.argv[2] -if suffix[0] != '.': - suffix = '.' + suffix - -for (root, dirs, files) in os.walk(topdir): - for f in files: - if f.endswith(suffix): - fullname = os.path.join(root, f) - os.unlink(fullname) diff --git a/meson/depfixer.py b/meson/depfixer.py deleted file mode 100755 index 4f7ce3d..0000000 --- a/meson/depfixer.py +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013-2014 The Meson development 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 sys, struct - -SHT_STRTAB = 3 -DT_NEEDED = 1 -DT_RPATH = 15 -DT_STRTAB = 5 -DT_SONAME = 14 - -class DataSizes(): - def __init__(self, ptrsize, is_le): - if is_le: - p = '<' - else: - p = '>' - self.Half = p+'h' - self.HalfSize = 2 - self.Word = p+'I' - self.WordSize = 4 - self.Sword = p+'i' - self.SwordSize = 4 - if ptrsize == 64: - self.Addr = p+'Q' - self.AddrSize = 8 - self.Off = p+'Q' - self.OffSize = 8 - self.XWord = p+'Q' - self.XWordSize = 8 - self.Sxword = p+'q' - self.SxwordSize = 8 - else: - self.Addr = p+'I' - self.AddrSize = 4 - self.Off = p+'I' - self.OffSize = 4 - -class DynamicEntry(DataSizes): - def __init__(self, ifile, ptrsize, is_le): - super().__init__(ptrsize, is_le) - self.ptrsize = ptrsize - if ptrsize == 64: - self.d_tag = struct.unpack(self.Sxword, ifile.read(self.SxwordSize))[0]; - self.val = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0]; - else: - self.d_tag = struct.unpack(self.Sword, ifile.read(self.SwordSize))[0] - self.val = struct.unpack(self.Word, ifile.read(self.WordSize))[0] - - def write(self, ofile): - if self.ptrsize == 64: - ofile.write(struct.pack(self.Sxword, self.d_tag)) - ofile.write(struct.pack(self.XWord, self.val)) - else: - ofile.write(struct.pack(self.Sword, self.d_tag)) - ofile.write(struct.pack(self.Word, self.val)) - -class SectionHeader(DataSizes): - def __init__(self, ifile, ptrsize, is_le): - super().__init__(ptrsize, is_le) - if ptrsize == 64: - is_64 = True - else: - is_64 = False -#Elf64_Word - self.sh_name = struct.unpack(self.Word, ifile.read(self.WordSize))[0]; -#Elf64_Word - self.sh_type = struct.unpack(self.Word, ifile.read(self.WordSize))[0] -#Elf64_Xword - if is_64: - self.sh_flags = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] - else: - self.sh_flags = struct.unpack(self.Word, ifile.read(self.WordSize))[0] -#Elf64_Addr - self.sh_addr = struct.unpack(self.Addr, ifile.read(self.AddrSize))[0]; -#Elf64_Off - self.sh_offset = struct.unpack(self.Off, ifile.read(self.OffSize))[0] -#Elf64_Xword - if is_64: - self.sh_size = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] - else: - self.sh_size = struct.unpack(self.Word, ifile.read(self.WordSize))[0] -#Elf64_Word - self.sh_link = struct.unpack(self.Word, ifile.read(self.WordSize))[0]; -#Elf64_Word - self.sh_info = struct.unpack(self.Word, ifile.read(self.WordSize))[0]; -#Elf64_Xword - if is_64: - self.sh_addralign = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] - else: - self.sh_addralign = struct.unpack(self.Word, ifile.read(self.WordSize))[0] -#Elf64_Xword - if is_64: - self.sh_entsize = struct.unpack(self.XWord, ifile.read(self.XWordSize))[0] - else: - self.sh_entsize = struct.unpack(self.Word, ifile.read(self.WordSize))[0] - -class Elf(DataSizes): - def __init__(self, bfile): - self.bfile = bfile - self.bf = open(bfile, 'r+b') - (self.ptrsize, self.is_le) = self.detect_elf_type() - super().__init__(self.ptrsize, self.is_le) - self.parse_header() - self.parse_sections() - self.parse_dynamic() - - def detect_elf_type(self): - data = self.bf.read(6) - if data[1:4] != b'ELF': - # This script gets called to non-elf targets too - # so just ignore them. - print('File "%s" is not an ELF file.' % self.bfile) - sys.exit(0) - if data[4] == 1: - ptrsize = 32 - elif data[4] == 2: - ptrsize = 64 - else: - print('File "%s" has unknown ELF class.' % self.bfile) - sys.exit(1) - if data[5] == 1: - is_le = True - elif data[5] == 2: - is_le = False - else: - print('File "%s" has unknown ELF endianness.' % self.bfile) - sys.exit(1) - return (ptrsize, is_le) - - def parse_header(self): - self.bf.seek(0) - self.e_ident = struct.unpack('16s', self.bf.read(16))[0] - self.e_type = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_machine = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_version = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] - self.e_entry = struct.unpack(self.Addr, self.bf.read(self.AddrSize))[0] - self.e_phoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] - self.e_shoff = struct.unpack(self.Off, self.bf.read(self.OffSize))[0] - self.e_flags = struct.unpack(self.Word, self.bf.read(self.WordSize))[0] - self.e_ehsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_phentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_phnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_shentsize = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_shnum = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - self.e_shstrndx = struct.unpack(self.Half, self.bf.read(self.HalfSize))[0] - - def parse_sections(self): - self.bf.seek(self.e_shoff) - self.sections = [] - for i in range(self.e_shnum): - self.sections.append(SectionHeader(self.bf, self.ptrsize, self.is_le)) - - def read_str(self): - arr = [] - x = self.bf.read(1) - while x != b'\0': - arr.append(x) - x = self.bf.read(1) - if x == b'': - raise RuntimeError('Tried to read past the end of the file') - return b''.join(arr) - - def find_section(self, target_name): - section_names = self.sections[self.e_shstrndx] - for i in self.sections: - self.bf.seek(section_names.sh_offset + i.sh_name) - name = self.read_str() - if name == target_name: - return i - - def parse_dynamic(self): - sec = self.find_section(b'.dynamic') - self.dynamic = [] - self.bf.seek(sec.sh_offset) - while True: - e = DynamicEntry(self.bf, self.ptrsize, self.is_le) - self.dynamic.append(e) - if e.d_tag == 0: - break - - def print_section_names(self): - section_names = self.sections[self.e_shstrndx] - for i in self.sections: - self.bf.seek(section_names.sh_offset + i.sh_name) - name = self.read_str() - print(name.decode()) - - def print_soname(self): - soname = None - strtab = None - for i in self.dynamic: - if i.d_tag == DT_SONAME: - soname = i - if i.d_tag == DT_STRTAB: - strtab = i - self.bf.seek(strtab.val + soname.val) - print(self.read_str()) - - def get_rpath_offset(self): - sec = self.find_section(b'.dynstr') - for i in self.dynamic: - if i.d_tag == DT_RPATH: - return sec.sh_offset + i.val - return None - - def print_rpath(self): - offset = self.get_rpath_offset() - if offset is None: - print("This file does not have an rpath.") - else: - self.bf.seek(offset) - print(self.read_str()) - - def print_deps(self): - sec = self.find_section(b'.dynstr') - deps = [] - for i in self.dynamic: - if i.d_tag == DT_NEEDED: - deps.append(i) - for i in deps: - offset = sec.sh_offset + i.val - self.bf.seek(offset) - name = self.read_str() - print(name) - - def fix_deps(self, prefix): - sec = self.find_section(b'.dynstr') - deps = [] - for i in self.dynamic: - if i.d_tag == DT_NEEDED: - deps.append(i) - for i in deps: - offset = sec.sh_offset + i.val - self.bf.seek(offset) - name = self.read_str() - if name.startswith(prefix): - basename = name.split(b'/')[-1] - padding = b'\0'*(len(name) - len(basename)) - newname = basename + padding - assert(len(newname) == len(name)) - self.bf.seek(offset) - self.bf.write(newname) - - def fix_rpath(self, new_rpath): - rp_off = self.get_rpath_offset() - if rp_off is None: - print('File does not have rpath. It should be a fully static executable.') - return - self.bf.seek(rp_off) - old_rpath = self.read_str() - if len(old_rpath) < len(new_rpath): - print("New rpath must not be longer than the old one.") - self.bf.seek(rp_off) - self.bf.write(new_rpath) - self.bf.write(b'\0'*(len(old_rpath) - len(new_rpath) + 1)) - if len(new_rpath) == 0: - self.remove_rpath_entry() - - def remove_rpath_entry(self): - sec = self.find_section(b'.dynamic') - for (i, entry) in enumerate(self.dynamic): - if entry.d_tag == DT_RPATH: - rpentry = self.dynamic[i] - rpentry.d_tag = 0 - self.dynamic = self.dynamic[:i] + self.dynamic[i+1:] + [rpentry] - break; - self.bf.seek(sec.sh_offset) - for entry in self.dynamic: - entry.write(self.bf) - return None - -if __name__ == '__main__': - if len(sys.argv) < 2 or len(sys.argv) > 3: - print('This application resets target rpath.') - print('Don\'t run this unless you know what you are doing.') - print('%s: <binary file> <prefix>' % sys.argv[0]) - exit(1) - e = Elf(sys.argv[1]) - if len(sys.argv) == 2: - e.print_rpath() - else: - new_rpath = sys.argv[2] - e.fix_rpath(new_rpath.encode('utf8')) - #e.fix_deps(prefix.encode()) diff --git a/meson/dirchanger.py b/meson/dirchanger.py deleted file mode 100755 index fd3dc23..0000000 --- a/meson/dirchanger.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2015-2016 The Meson development 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. - -'''CD into dir given as first argument and execute -the command given in the rest of the arguments.''' - -import os, subprocess, sys - -dirname = sys.argv[1] -command = sys.argv[2:] - -os.chdir(dirname) -sys.exit(subprocess.call(command)) diff --git a/meson/environment.py b/meson/environment.py index 3e10bd4..a99cb30 100644 --- a/meson/environment.py +++ b/meson/environment.py @@ -125,7 +125,7 @@ class Environment(): coredata.save(self.coredata, cdf) def get_script_dir(self): - return os.path.dirname(self.meson_script_file) + return os.path.join(os.path.dirname(self.meson_script_file), '../scripts') def get_log_dir(self): return self.log_dir diff --git a/meson/gtkdochelper.py b/meson/gtkdochelper.py deleted file mode 100755 index 7e476b8..0000000 --- a/meson/gtkdochelper.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2015 The Meson development 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 sys, os -import subprocess -import shutil -import argparse - -parser = argparse.ArgumentParser() - -parser.add_argument('--sourcedir', dest='sourcedir') -parser.add_argument('--builddir', dest='builddir') -parser.add_argument('--subdir', dest='subdir') -parser.add_argument('--headerdir', dest='headerdir') -parser.add_argument('--mainfile', dest='mainfile') -parser.add_argument('--modulename', dest='modulename') -parser.add_argument('--htmlargs', dest='htmlargs', default='') -parser.add_argument('--scanargs', dest='scanargs', default='') - -def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir, - main_file, module, html_args, scan_args): - abs_src = os.path.join(source_root, src_subdir) - abs_out = os.path.join(build_root, doc_subdir) - htmldir = os.path.join(abs_out, 'html') - scan_cmd = ['gtkdoc-scan', - '--module=' + module, - '--source-dir=' + abs_src] + scan_args -# print(scan_cmd) -# sys.exit(1) - subprocess.check_call(scan_cmd, - cwd=abs_out) - if main_file.endswith('sgml'): - modeflag = '--sgml-mode' - else: - modeflag = '--xml-mode' - mkdb_cmd = ['gtkdoc-mkdb', - '--module=' + module, - '--output-format=xml', - modeflag, - '--source-dir=' + abs_src] - main_abs = os.path.join(source_root, doc_subdir, main_file) - if len(main_file) > 0: - # Yes, this is the flag even if the file is in xml. - mkdb_cmd.append('--main-sgml-file=' + main_file) -# print(mkdb_cmd) -# sys.exit(1) - subprocess.check_call(mkdb_cmd, cwd=abs_out) - shutil.rmtree(htmldir, ignore_errors=True) - try: - os.mkdir(htmldir) - except Exception: - pass - mkhtml_cmd = ['gtkdoc-mkhtml', - '--path=' + abs_src, - module, - ] + html_args - if len(main_file) > 0: - mkhtml_cmd.append('../' + main_file) - else: - mkhtml_cmd.append('%s-docs.xml' % module) - # html gen must be run in the HTML dir -# print(mkhtml_cmd) -# sys.exit(1) - subprocess.check_call(mkhtml_cmd, cwd=os.path.join(abs_out, 'html'), shell=False) - fixref_cmd = ['gtkdoc-fixxref', - '--module=' + module, - '--module-dir=html'] -# print(fixref_cmd) -# sys.exit(1) - subprocess.check_call(fixref_cmd, cwd=abs_out) - -def install_gtkdoc(build_root, doc_subdir, install_prefix, datadir, module): - source = os.path.join(build_root, doc_subdir, 'html') - final_destination = os.path.join(install_prefix, datadir, module) - shutil.rmtree(final_destination, ignore_errors=True) - shutil.copytree(source, final_destination) - -if __name__ == '__main__': - options = parser.parse_args(sys.argv[1:]) - if len(options.htmlargs) > 0: - htmlargs = options.htmlargs.split('@@') - else: - htmlargs = [] - if len(options.scanargs) > 0: - scanargs = options.scanargs.split('@@') - else: - scanargs = [] - build_gtkdoc(options.sourcedir, - options.builddir, - options.subdir, - options.headerdir, - options.mainfile, - options.modulename, - htmlargs, - scanargs) - - if 'MESON_INSTALL_PREFIX' in os.environ: - if 'DESTDIR' in os.environ: - installdir = os.environ['DESTDIR'] + os.environ['MESON_INSTALL_PREFIX'] - else: - installdir = os.environ['MESON_INSTALL_PREFIX'] - install_gtkdoc(options.builddir, - options.subdir, - installdir, - 'share/gtk-doc/html', - options.modulename) diff --git a/meson/meson_benchmark.py b/meson/meson_benchmark.py deleted file mode 100755 index 26f1f95..0000000 --- a/meson/meson_benchmark.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2015 The Meson development 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 subprocess, sys, os, argparse -import pickle, statistics, json -from . import meson_test - -parser = argparse.ArgumentParser() -parser.add_argument('--wd', default=None, dest='wd', - help='directory to cd into before running') -parser.add_argument('args', nargs='+') - -def print_stats(numlen, num_tests, name, res, i, duration, stdev): - startpad = ' '*(numlen - len('%d' % (i+1))) - num = '%s%d/%d' % (startpad, i+1, num_tests) - padding1 = ' '*(38-len(name)) - padding2 = ' '*(8-len(res)) - result_str = '%s %s %s%s%s%5.5f s +- %5.5f s' % \ - (num, name, padding1, res, padding2, duration, stdev) - print(result_str) -# write_json_log(jsonlogfile, name, result) - -def print_json_log(jsonlogfile, rawruns, test_name, i): - jsonobj = {'name' : test_name} - runs = [] - for r in rawruns: - runobj = {'duration': r.duration, - 'stdout': r.stdo, - 'stderr': r.stde, - 'returncode' : r.returncode, - 'duration' : r.duration} - runs.append(runobj) - jsonobj['runs'] = runs - jsonlogfile.write(json.dumps(jsonobj) + '\n') - jsonlogfile.flush() - -def run_benchmarks(options, datafile): - failed_tests = 0 - logfile_base = 'meson-logs/benchmarklog' - jsonlogfilename = logfile_base+ '.json' - jsonlogfile = open(jsonlogfilename, 'w') - tests = pickle.load(open(datafile, 'rb')) - num_tests = len(tests) - if num_tests == 0: - print('No benchmarks defined.') - return 0 - iteration_count = 5 - wrap = [] # Benchmarks on cross builds are pointless so don't support them. - for i, test in enumerate(tests): - runs = [] - durations = [] - failed = False - for _ in range(iteration_count): - res = meson_test.run_single_test(wrap, test) - runs.append(res) - durations.append(res.duration) - if res.returncode != 0: - failed = True - mean = statistics.mean(durations) - stddev = statistics.stdev(durations) - if failed: - resultstr = 'FAIL' - failed_tests += 1 - else: - resultstr = 'OK' - print_stats(3, num_tests, test.name, resultstr, i, mean, stddev) - print_json_log(jsonlogfile, runs, test.name, i) - print('\nFull log written to meson-logs/benchmarklog.json.') - return failed_tests - -def run(args): - global failed_tests - options = parser.parse_args(args) - if len(options.args) != 1: - print('Benchmark runner for Meson. Do not run on your own, mmm\'kay?') - print('%s [data file]' % sys.argv[0]) - if options.wd is not None: - os.chdir(options.wd) - datafile = options.args[0] - returncode = run_benchmarks(options, datafile) - return returncode - -if __name__ == '__main__': - sys.exit(run(sys.argv[1:])) diff --git a/meson/meson_install.py b/meson/meson_install.py deleted file mode 100755 index c5c17ba..0000000 --- a/meson/meson_install.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013-2014 The Meson development 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 sys, pickle, os, shutil, subprocess, gzip, platform -from glob import glob - -class InstallData(): - def __init__(self, source_dir, build_dir, prefix, depfixer): - self.source_dir = source_dir - self.build_dir= build_dir - self.prefix = prefix - self.targets = [] - self.depfixer = depfixer - self.headers = [] - self.man = [] - self.data = [] - self.po_package_name = '' - self.po = [] - self.install_scripts = [] - self.install_subdirs = [] - -def do_install(datafilename): - ifile = open(datafilename, 'rb') - d = pickle.load(ifile) - destdir_var = 'DESTDIR' - if destdir_var in os.environ: - d.destdir = os.environ[destdir_var] - else: - d.destdir = '' - d.fullprefix = d.destdir + d.prefix - - install_subdirs(d) # Must be first, because it needs to delete the old subtree. - install_targets(d) - install_headers(d) - install_man(d) - install_data(d) - install_po(d) - run_install_script(d) - -def install_subdirs(d): - for (src_dir, dst_dir) in d.install_subdirs: - if os.path.isabs(dst_dir): - dst_dir = d.destdir + dst_dir - else: - dst_dir = d.fullprefix + dst_dir - # Python's copytree works in strange ways. - last_level = os.path.split(src_dir)[-1] - final_dst = os.path.join(dst_dir, last_level) -# Don't do rmtree because final_dst might point to e.g. /var/www -# We might need to revert to walking the directory tree by hand. -# shutil.rmtree(final_dst, ignore_errors=True) - shutil.copytree(src_dir, final_dst, symlinks=True) - print('Installing subdir %s to %s.' % (src_dir, dst_dir)) - -def install_po(d): - packagename = d.po_package_name - for f in d.po: - srcfile = f[0] - localedir = f[1] - languagename = f[2] - outfile = os.path.join(d.fullprefix, localedir, languagename, 'LC_MESSAGES', - packagename + '.mo') - os.makedirs(os.path.split(outfile)[0], exist_ok=True) - shutil.copyfile(srcfile, outfile) - shutil.copystat(srcfile, outfile) - print('Installing %s to %s.' % (srcfile, outfile)) - -def install_data(d): - for i in d.data: - fullfilename = i[0] - outfilename = i[1] - if os.path.isabs(outfilename): - outdir = d.destdir + os.path.split(outfilename)[0] - outfilename = d.destdir + outfilename - else: - outdir = os.path.join(d.fullprefix, os.path.split(outfilename)[0]) - outfilename = os.path.join(outdir, os.path.split(outfilename)[1]) - os.makedirs(outdir, exist_ok=True) - print('Installing %s to %s.' % (fullfilename, outdir)) - shutil.copyfile(fullfilename, outfilename) - shutil.copystat(fullfilename, outfilename) - -def install_man(d): - for m in d.man: - outfileroot = m[1] - outfilename = os.path.join(d.fullprefix, outfileroot) - full_source_filename = m[0] - outdir = os.path.split(outfilename)[0] - os.makedirs(outdir, exist_ok=True) - print('Installing %s to %s.' % (full_source_filename, outdir)) - if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'): - open(outfilename, 'wb').write(gzip.compress(open(full_source_filename, 'rb').read())) - else: - shutil.copyfile(full_source_filename, outfilename) - shutil.copystat(full_source_filename, outfilename) - -def install_headers(d): - for t in d.headers: - fullfilename = t[0] - outdir = os.path.join(d.fullprefix, t[1]) - fname = os.path.split(fullfilename)[1] - outfilename = os.path.join(outdir, fname) - print('Installing %s to %s' % (fname, outdir)) - os.makedirs(outdir, exist_ok=True) - shutil.copyfile(fullfilename, outfilename) - shutil.copystat(fullfilename, outfilename) - -def run_install_script(d): - env = {'MESON_SOURCE_ROOT' : d.source_dir, - 'MESON_BUILD_ROOT' : d.build_dir, - 'MESON_INSTALL_PREFIX' : d.prefix - } - child_env = os.environ.copy() - child_env.update(env) - - for i in d.install_scripts: - script = i.cmd_arr[0] - print('Running custom install script %s' % script) - suffix = os.path.splitext(script)[1].lower() - if platform.system().lower() == 'windows' and suffix != '.bat': - first_line = open(script).readline().strip() - if first_line.startswith('#!'): - commands = first_line[2:].split('#')[0].strip().split() - commands[0] = shutil.which(commands[0].split('/')[-1]) - if commands[0] is None: - raise RuntimeError("Don't know how to run script %s." % script) - final_command = commands + [script] + i.cmd_arr[1:] - else: - final_command = i.cmd_arr - subprocess.check_call(final_command, env=child_env) - -def is_elf_platform(): - platname = platform.system().lower() - if platname == 'darwin' or platname == 'windows': - return False - return True - -def check_for_stampfile(fname): - '''Some languages e.g. Rust have output files - whose names are not known at configure time. - Check if this is the case and return the real - file instead.''' - if fname.endswith('.so') or fname.endswith('.dll'): - if os.stat(fname).st_size == 0: - (base, suffix) = os.path.splitext(fname) - files = glob(base + '-*' + suffix) - if len(files) > 1: - print("Stale dynamic library files in build dir. Can't install.") - sys.exit(1) - if len(files) == 1: - return files[0] - elif fname.endswith('.a') or fname.endswith('.lib'): - if os.stat(fname).st_size == 0: - (base, suffix) = os.path.splitext(fname) - files = glob(base + '-*' + '.rlib') - if len(files) > 1: - print("Stale static library files in build dir. Can't install.") - sys.exit(1) - if len(files) == 1: - return files[0] - return fname - -def install_targets(d): - for t in d.targets: - fname = check_for_stampfile(t[0]) - outdir = os.path.join(d.fullprefix, t[1]) - aliases = t[2] - outname = os.path.join(outdir, os.path.split(fname)[-1]) - should_strip = t[3] - install_rpath = t[4] - print('Installing %s to %s' % (fname, outname)) - os.makedirs(outdir, exist_ok=True) - shutil.copyfile(fname, outname) - shutil.copystat(fname, outname) - if should_strip: - print('Stripping target') - ps = subprocess.Popen(['strip', outname], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - (stdo, stde) = ps.communicate() - if ps.returncode != 0: - print('Could not strip file.\n') - print('Stdout:\n%s\n' % stdo.decode()) - print('Stderr:\n%s\n' % stde.decode()) - sys.exit(1) - printed_symlink_error = False - for alias in aliases: - try: - symlinkfilename = os.path.join(outdir, alias) - try: - os.unlink(symlinkfilename) - except FileNotFoundError: - pass - os.symlink(os.path.split(fname)[-1], symlinkfilename) - except NotImplementedError: - if not printed_symlink_error: - print("Symlink creation does not work on this platform.") - printed_symlink_error = True - if is_elf_platform(): - p = subprocess.Popen([d.depfixer, outname, install_rpath], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (stdo, stde) = p.communicate() - if p.returncode != 0: - print('Could not fix dependency info.\n') - print('Stdout:\n%s\n' % stdo.decode()) - print('Stderr:\n%s\n' % stde.decode()) - sys.exit(1) - -if __name__ == '__main__': - if len(sys.argv) != 2: - print('Installer script for Meson. Do not run on your own, mmm\'kay?') - print('%s [install info file]' % sys.argv[0]) - datafilename = sys.argv[1] - do_install(datafilename) - diff --git a/meson/meson_test.py b/meson/meson_test.py deleted file mode 100755 index d9b4993..0000000 --- a/meson/meson_test.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013-2015 The Meson development 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 sys, os, subprocess, time, datetime, pickle, multiprocessing, json -import concurrent.futures as conc -import argparse -import platform - -def is_windows(): - platname = platform.system().lower() - return platname == 'windows' or 'mingw' in platname - -tests_failed = [] - -parser = argparse.ArgumentParser() -parser.add_argument('--wrapper', default=None, dest='wrapper', - help='wrapper to run tests with (e.g. valgrind)') -parser.add_argument('--wd', default=None, dest='wd', - help='directory to cd into before running') -parser.add_argument('--suite', default=None, dest='suite', - help='Only run tests belonging to this suite.') -parser.add_argument('args', nargs='+') - - -class TestRun(): - def __init__(self, res, returncode, duration, stdo, stde, cmd): - self.res = res - self.returncode = returncode - self.duration = duration - self.stdo = stdo - self.stde = stde - self.cmd = cmd - -def decode(stream): - try: - return stream.decode('utf-8') - except UnicodeDecodeError: - return stream.decode('iso-8859-1', errors='ignore') - -def write_log(logfile, test_name, result_str, result): - logfile.write(result_str + '\n\n') - logfile.write('--- command ---\n') - if result.cmd is None: - logfile.write('NONE') - else: - logfile.write(' '.join(result.cmd)) - logfile.write('\n--- "%s" stdout ---\n' % test_name) - logfile.write(result.stdo) - logfile.write('\n--- "%s" stderr ---\n' % test_name) - logfile.write(result.stde) - logfile.write('\n-------\n\n') - -def write_json_log(jsonlogfile, test_name, result): - result = {'name' : test_name, - 'stdout' : result.stdo, - 'stderr' : result.stde, - 'result' : result.res, - 'duration' : result.duration, - 'returncode' : result.returncode, - 'command' : result.cmd} - jsonlogfile.write(json.dumps(result) + '\n') - -def run_with_mono(fname): - if fname.endswith('.exe') and not is_windows(): - return True - return False - -def run_single_test(wrap, test): - global tests_failed - if test.fname[0].endswith('.jar'): - cmd = ['java', '-jar'] + test.fname - elif not test.is_cross and run_with_mono(test.fname[0]): - cmd = ['mono'] + test.fname - else: - if test.is_cross: - if test.exe_runner is None: - # Can not run test on cross compiled executable - # because there is no execute wrapper. - cmd = None - else: - cmd = [test.exe_runner] + test.fname - else: - cmd = test.fname - if len(wrap) > 0 and 'valgrind' in wrap[0]: - wrap += test.valgrind_args - if cmd is None: - res = 'SKIP' - duration = 0.0 - stdo = 'Not run because can not execute cross compiled binaries.' - stde = '' - returncode = -1 - else: - cmd = wrap + cmd + test.cmd_args - starttime = time.time() - child_env = os.environ.copy() - child_env.update(test.env) - if len(test.extra_paths) > 0: - child_env['PATH'] = child_env['PATH'] + ';'.join([''] + test.extra_paths) - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env=child_env, cwd=test.workdir) - timed_out = False - try: - (stdo, stde) = p.communicate(timeout=test.timeout) - except subprocess.TimeoutExpired: - timed_out = True - p.kill() - (stdo, stde) = p.communicate() - endtime = time.time() - duration = endtime - starttime - stdo = decode(stdo) - stde = decode(stde) - if timed_out: - res = 'TIMEOUT' - tests_failed.append((test.name, stdo, stde)) - elif (not test.should_fail and p.returncode == 0) or \ - (test.should_fail and p.returncode != 0): - res = 'OK' - else: - res = 'FAIL' - tests_failed.append((test.name, stdo, stde)) - returncode = p.returncode - return TestRun(res, returncode, duration, stdo, stde, cmd) - -def print_stats(numlen, tests, name, result, i, logfile, jsonlogfile): - startpad = ' '*(numlen - len('%d' % (i+1))) - num = '%s%d/%d' % (startpad, i+1, len(tests)) - padding1 = ' '*(38-len(name)) - padding2 = ' '*(8-len(result.res)) - result_str = '%s %s %s%s%s%5.2f s' % \ - (num, name, padding1, result.res, padding2, result.duration) - print(result_str) - write_log(logfile, name, result_str, result) - write_json_log(jsonlogfile, name, result) - -def drain_futures(futures): - for i in futures: - (result, numlen, tests, name, i, logfile, jsonlogfile) = i - print_stats(numlen, tests, name, result.result(), i, logfile, jsonlogfile) - -def filter_tests(suite, tests): - if suite is None: - return tests - return [x for x in tests if suite in x.suite] - -def run_tests(options, datafilename): - logfile_base = 'meson-logs/testlog' - if options.wrapper is None: - wrap = [] - logfilename = logfile_base + '.txt' - jsonlogfilename = logfile_base+ '.json' - else: - wrap = [options.wrapper] - logfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.txt' - jsonlogfilename = logfile_base + '-' + options.wrapper.replace(' ', '_') + '.json' - logfile = open(logfilename, 'w') - jsonlogfile = open(jsonlogfilename, 'w') - logfile.write('Log of Meson test suite run on %s.\n\n' % datetime.datetime.now().isoformat()) - tests = pickle.load(open(datafilename, 'rb')) - if len(tests) == 0: - print('No tests defined.') - return - numlen = len('%d' % len(tests)) - varname = 'MESON_TESTTHREADS' - if varname in os.environ: - try: - num_workers = int(os.environ[varname]) - except ValueError: - print('Invalid value in %s, using 1 thread.' % varname) - num_workers = 1 - else: - num_workers = multiprocessing.cpu_count() - executor = conc.ThreadPoolExecutor(max_workers=num_workers) - futures = [] - filtered_tests = filter_tests(options.suite, tests) - for i, test in enumerate(filtered_tests): - if test.suite[0] == '': - visible_name = test.name - else: - if options.suite is not None: - visible_name = options.suite + ' / ' + test.name - else: - visible_name = test.suite[0] + ' / ' + test.name - - if not test.is_parallel: - drain_futures(futures) - futures = [] - res = run_single_test(wrap, test) - print_stats(numlen, filtered_tests, visible_name, res, i, logfile, jsonlogfile) - else: - f = executor.submit(run_single_test, wrap, test) - futures.append((f, numlen, filtered_tests, visible_name, i, logfile, jsonlogfile)) - drain_futures(futures) - return logfilename - -def run(args): - global tests_failed - options = parser.parse_args(args) - if len(options.args) != 1: - print('Test runner for Meson. Do not run on your own, mmm\'kay?') - print('%s [data file]' % sys.argv[0]) - if options.wd is not None: - os.chdir(options.wd) - datafile = options.args[0] - logfilename = run_tests(options, datafile) - returncode = 0 - if len(tests_failed) > 0: - print('\nOutput of failed tests (max 10):') - for (name, stdo, stde) in tests_failed[:10]: - print("{} stdout:\n".format(name)) - print(stdo) - print('\n{} stderr:\n'.format(name)) - print(stde) - print('\n') - returncode = 1 - print('\nFull log written to %s.' % logfilename) - return returncode - -if __name__ == '__main__': - sys.exit(run(sys.argv[1:])) diff --git a/meson/mesonconf.py b/meson/mesonconf.py deleted file mode 100755 index e53875f..0000000 --- a/meson/mesonconf.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2014-2015 The Meson development 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 sys, os -import pickle -import argparse -import coredata, mesonlib -from coredata import build_types, layouts, warning_levels, libtypelist - -parser = argparse.ArgumentParser() - -parser.add_argument('-D', action='append', default=[], dest='sets', - help='Set an option to the given value.') -parser.add_argument('directory', nargs='*') - -class ConfException(coredata.MesonException): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - -class Conf: - def __init__(self, build_dir): - self.build_dir = build_dir - self.coredata_file = os.path.join(build_dir, 'meson-private/coredata.dat') - self.build_file = os.path.join(build_dir, 'meson-private/build.dat') - if not os.path.isfile(self.coredata_file) or not os.path.isfile(self.build_file): - raise ConfException('Directory %s does not seem to be a Meson build directory.' % build_dir) - self.coredata = pickle.load(open(self.coredata_file, 'rb')) - self.build = pickle.load(open(self.build_file, 'rb')) - if self.coredata.version != coredata.version: - raise ConfException('Version mismatch (%s vs %s)' % - (coredata.version, self.coredata.version)) - - def save(self): - # Only called if something has changed so overwrite unconditionally. - pickle.dump(self.coredata, open(self.coredata_file, 'wb')) - # We don't write the build file because any changes to it - # are erased when Meson is executed the nex time, i.e. the next - # time Ninja is run. - - def print_aligned(self, arr): - if len(arr) == 0: - return - titles = ['Option', 'Description', 'Current Value', ''] - longest_name = len(titles[0]) - longest_descr = len(titles[1]) - longest_value = len(titles[2]) - longest_possible_value = len(titles[3]) - for x in arr: - longest_name = max(longest_name, len(x[0])) - longest_descr = max(longest_descr, len(x[1])) - longest_value = max(longest_value, len(str(x[2]))) - longest_possible_value = max(longest_possible_value, len(x[3])) - - if longest_possible_value > 0: - titles[3] = 'Possible Values' - print(' %s%s %s%s %s%s %s' % (titles[0], ' '*(longest_name - len(titles[0])), titles[1], ' '*(longest_descr - len(titles[1])), titles[2], ' '*(longest_value - len(titles[2])), titles[3])) - print(' %s%s %s%s %s%s %s' % ('-'*len(titles[0]), ' '*(longest_name - len(titles[0])), '-'*len(titles[1]), ' '*(longest_descr - len(titles[1])), '-'*len(titles[2]), ' '*(longest_value - len(titles[2])), '-'*len(titles[3]))) - for i in arr: - name = i[0] - descr = i[1] - value = i[2] - if isinstance(value, bool): - value = 'true' if value else 'false' - possible_values = i[3] - namepad = ' '*(longest_name - len(name)) - descrpad = ' '*(longest_descr - len(descr)) - valuepad = ' '*(longest_value - len(str(value))) - f = ' %s%s %s%s %s%s %s' % (name, namepad, descr, descrpad, value, valuepad, possible_values) - print(f) - - def set_options(self, options): - for o in options: - if '=' not in o: - raise ConfException('Value "%s" not of type "a=b".' % o) - (k, v) = o.split('=', 1) - if self.coredata.is_builtin_option(k): - self.coredata.set_builtin_option(k, v) - elif k in self.coredata.user_options: - tgt = self.coredata.user_options[k] - tgt.set_value(v) - elif k in self.coredata.compiler_options: - tgt = self.coredata.compiler_options[k] - tgt.set_value(v) - elif k.endswith('linkargs'): - lang = k[:-8] - if not lang in self.coredata.external_link_args: - raise ConfException('Unknown language %s in linkargs.' % lang) - # TODO, currently split on spaces, make it so that user - # can pass in an array string. - newvalue = v.split() - self.coredata.external_link_args[lang] = newvalue - elif k.endswith('args'): - lang = k[:-4] - if not lang in self.coredata.external_args: - raise ConfException('Unknown language %s in compile args' % lang) - # TODO same fix as above - newvalue = v.split() - self.coredata.external_args[lang] = newvalue - else: - raise ConfException('Unknown option %s.' % k) - - - def print_conf(self): - print('Core properties:') - print(' Source dir', self.build.environment.source_dir) - print(' Build dir ', self.build.environment.build_dir) - print('') - print('Core options:') - carr = [] - booleans = '[true, false]' - carr.append(['buildtype', 'Build type', self.coredata.get_builtin_option('buildtype'), build_types]) - carr.append(['warning_level', 'Warning level', self.coredata.get_builtin_option('warning_level'), warning_levels]) - carr.append(['strip', 'Strip on install', self.coredata.get_builtin_option('strip'), booleans]) - carr.append(['coverage', 'Coverage report', self.coredata.get_builtin_option('coverage'), booleans]) - carr.append(['use_pch', 'Precompiled headers', self.coredata.get_builtin_option('use_pch'), booleans]) - carr.append(['unity', 'Unity build', self.coredata.get_builtin_option('unity'), booleans]) - carr.append(['default_library', 'Default library type', self.coredata.get_builtin_option('default_library'), libtypelist]) - self.print_aligned(carr) - print('') - print('Compiler arguments:') - for (lang, args) in self.coredata.external_args.items(): - print(' ' + lang + 'args', str(args)) - print('') - print('Linker args:') - for (lang, args) in self.coredata.external_link_args.items(): - print(' ' + lang + 'linkargs', str(args)) - print('') - print('Compiler options:') - okeys = sorted(self.coredata.compiler_options.keys()) - if len(okeys) == 0: - print(' No compiler options\n') - else: - coarr = [] - for k in okeys: - o = self.coredata.compiler_options[k] - coarr.append([k, o.description, o.value, '']) - self.print_aligned(coarr) - print('') - print('Directories:') - parr = [] - parr.append(['prefix', 'Install prefix', self.coredata.get_builtin_option('prefix'), '']) - parr.append(['libdir', 'Library directory', self.coredata.get_builtin_option('libdir'), '']) - parr.append(['bindir', 'Binary directory', self.coredata.get_builtin_option('bindir'), '']) - parr.append(['includedir', 'Header directory', self.coredata.get_builtin_option('includedir'), '']) - parr.append(['datadir', 'Data directory', self.coredata.get_builtin_option('datadir'), '']) - parr.append(['mandir', 'Man page directory', self.coredata.get_builtin_option('mandir'), '']) - parr.append(['localedir', 'Locale file directory', self.coredata.get_builtin_option('localedir'), '']) - self.print_aligned(parr) - print('') - print('Project options:') - if len(self.coredata.user_options) == 0: - print(' This project does not have any options') - else: - options = self.coredata.user_options - keys = list(options.keys()) - keys.sort() - optarr = [] - for key in keys: - opt = options[key] - if (opt.choices is None) or (len(opt.choices) == 0): - # Zero length list or string - choices = ''; - else: - # A non zero length list or string, convert to string - choices = str(opt.choices); - optarr.append([key, opt.description, opt.value, choices]) - self.print_aligned(optarr) - -if __name__ == '__main__': - args = mesonlib.expand_arguments(sys.argv[:]) - if not args: - sys.exit(1) - options = parser.parse_args(args[1:]) - if len(options.directory) > 1: - print('%s <build directory>' % sys.argv[0]) - print('If you omit the build directory, the current directory is substituted.') - sys.exit(1) - if len(options.directory) == 0: - builddir = os.getcwd() - else: - builddir = options.directory[0] - try: - c = Conf(builddir) - if len(options.sets) > 0: - c.set_options(options.sets) - c.save() - else: - c.print_conf() - except ConfException as e: - print('Meson configurator encountered an error:\n') - print(e) - diff --git a/meson/mesongui.py b/meson/mesongui.py deleted file mode 100755 index bdd44bb..0000000 --- a/meson/mesongui.py +++ /dev/null @@ -1,561 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013-2015 The Meson development 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 sys, os, pickle, time, shutil -import build, coredata, environment, mesonlib -from PyQt5 import uic -from PyQt5.QtWidgets import QApplication, QMainWindow, QHeaderView -from PyQt5.QtWidgets import QComboBox, QCheckBox -from PyQt5.QtCore import QAbstractItemModel, QModelIndex, QVariant, QTimer -import PyQt5.QtCore -import PyQt5.QtWidgets - -priv_dir = os.path.split(os.path.abspath(os.path.realpath(__file__)))[0] - -class PathModel(QAbstractItemModel): - def __init__(self, coredata): - super().__init__() - self.coredata = coredata - self.names = ['Prefix', 'Library dir', 'Binary dir', 'Include dir', 'Data dir',\ - 'Man dir', 'Locale dir'] - self.attr_name = ['prefix', 'libdir', 'bindir', 'includedir', 'datadir', \ - 'mandir', 'localedir'] - - def args(self, index): - if index.column() == 1: - editable = PyQt5.QtCore.Qt.ItemIsEditable - else: - editable= 0 - return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled | editable - - def rowCount(self, index): - if index.isValid(): - return 0 - return len(self.names) - - def columnCount(self, index): - return 2 - - def headerData(self, section, orientation, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - if section == 1: - return QVariant('Path') - return QVariant('Type') - - def index(self, row, column, parent): - return self.createIndex(row, column) - - def data(self, index, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - row = index.row() - column = index.column() - if column == 0: - return self.names[row] - return getattr(self.coredata, self.attr_name[row]) - - def parent(self, index): - return QModelIndex() - - def setData(self, index, value, role): - if role != PyQt5.QtCore.Qt.EditRole: - return False - row = index.row() - column = index.column() - s = str(value) - setattr(self.coredata, self.attr_name[row], s) - self.dataChanged.emit(self.createIndex(row, column), self.createIndex(row, column)) - return True - -class TargetModel(QAbstractItemModel): - def __init__(self, builddata): - super().__init__() - self.targets = [] - for target in builddata.get_targets().values(): - name = target.get_basename() - num_sources = len(target.get_sources()) + len(target.get_generated_sources()) - if isinstance(target, build.Executable): - typename = 'executable' - elif isinstance(target, build.SharedLibrary): - typename = 'shared library' - elif isinstance(target, build.StaticLibrary): - typename = 'static library' - elif isinstance(target, build.CustomTarget): - typename = 'custom' - else: - typename = 'unknown' - if target.should_install(): - installed = 'Yes' - else: - installed = 'No' - self.targets.append((name, typename, installed, num_sources)) - - def args(self, index): - return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled - - def rowCount(self, index): - if index.isValid(): - return 0 - return len(self.targets) - - def columnCount(self, index): - return 4 - - def headerData(self, section, orientation, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - if section == 3: - return QVariant('Source files') - if section == 2: - return QVariant('Installed') - if section == 1: - return QVariant('Type') - return QVariant('Name') - - def data(self, index, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - row = index.row() - column = index.column() - return self.targets[row][column] - - def index(self, row, column, parent): - return self.createIndex(row, column) - - def parent(self, index): - return QModelIndex() - -class DependencyModel(QAbstractItemModel): - def __init__(self, coredata): - super().__init__() - self.deps = [] - for k in coredata.deps.keys(): - bd = coredata.deps[k] - name = k - found = bd.found() - if found: - cflags = str(bd.get_compile_args()) - libs = str(bd.get_link_args()) - found = 'yes' - else: - cflags = '' - libs = '' - found = 'no' - self.deps.append((name, found, cflags, libs)) - - def args(self, index): - return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled - - def rowCount(self, index): - if index.isValid(): - return 0 - return len(self.deps) - - def columnCount(self, index): - return 4 - - def headerData(self, section, orientation, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - if section == 3: - return QVariant('Link args') - if section == 2: - return QVariant('Compile args') - if section == 1: - return QVariant('Found') - return QVariant('Name') - - def data(self, index, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - row = index.row() - column = index.column() - return self.deps[row][column] - - def index(self, row, column, parent): - return self.createIndex(row, column) - - def parent(self, index): - return QModelIndex() - -class CoreModel(QAbstractItemModel): - def __init__(self, core_data): - super().__init__() - self.elems = [] - for langname, comp in core_data.compilers.items(): - self.elems.append((langname + ' compiler', str(comp.get_exelist()))) - for langname, comp in core_data.cross_compilers.items(): - self.elems.append((langname + ' cross compiler', str(comp.get_exelist()))) - - def args(self, index): - return PyQt5.QtCore.Qt.ItemIsSelectable | PyQt5.QtCore.Qt.ItemIsEnabled - - def rowCount(self, index): - if index.isValid(): - return 0 - return len(self.elems) - - def columnCount(self, index): - return 2 - - def headerData(self, section, orientation, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - if section == 1: - return QVariant('Value') - return QVariant('Name') - - def data(self, index, role): - if role != PyQt5.QtCore.Qt.DisplayRole: - return QVariant() - row = index.row() - column = index.column() - return self.elems[row][column] - - def index(self, row, column, parent): - return self.createIndex(row, column) - - def parent(self, index): - return QModelIndex() - -class OptionForm: - def __init__(self, coredata, form): - self.coredata = coredata - self.form = form - form.addRow(PyQt5.QtWidgets.QLabel("Meson options")) - combo = QComboBox() - combo.addItem('plain') - combo.addItem('debug') - combo.addItem('debugoptimized') - combo.addItem('release') - combo.setCurrentText(self.coredata.buildtype) - combo.currentTextChanged.connect(self.build_type_changed) - self.form.addRow('Build type', combo) - strip = QCheckBox("") - strip.setChecked(self.coredata.strip) - strip.stateChanged.connect(self.strip_changed) - self.form.addRow('Strip on install', strip) - coverage = QCheckBox("") - coverage.setChecked(self.coredata.coverage) - coverage.stateChanged.connect(self.coverage_changed) - self.form.addRow('Enable coverage', coverage) - pch = QCheckBox("") - pch.setChecked(self.coredata.use_pch) - pch.stateChanged.connect(self.pch_changed) - self.form.addRow('Enable pch', pch) - unity = QCheckBox("") - unity.setChecked(self.coredata.unity) - unity.stateChanged.connect(self.unity_changed) - self.form.addRow('Unity build', unity) - form.addRow(PyQt5.QtWidgets.QLabel("Project options")) - self.set_user_options() - - def set_user_options(self): - options = self.coredata.user_options - keys = list(options.keys()) - keys.sort() - self.opt_keys = keys - self.opt_widgets = [] - for key in keys: - opt = options[key] - if isinstance(opt, mesonlib.UserStringOption): - w = PyQt5.QtWidgets.QLineEdit(opt.value) - w.textChanged.connect(self.user_option_changed) - elif isinstance(opt, mesonlib.UserBooleanOption): - w = QCheckBox('') - w.setChecked(opt.value) - w.stateChanged.connect(self.user_option_changed) - elif isinstance(opt, mesonlib.UserComboOption): - w = QComboBox() - for i in opt.choices: - w.addItem(i) - w.setCurrentText(opt.value) - w.currentTextChanged.connect(self.user_option_changed) - else: - raise RuntimeError("Unknown option type") - self.opt_widgets.append(w) - self.form.addRow(opt.description, w) - - def user_option_changed(self, dummy=None): - for i in range(len(self.opt_keys)): - key = self.opt_keys[i] - w = self.opt_widgets[i] - if isinstance(w, PyQt5.QtWidgets.QLineEdit): - newval = w.text() - elif isinstance(w, QComboBox): - newval = w.currentText() - elif isinstance(w, QCheckBox): - if w.checkState() == 0: - newval = False - else: - newval = True - else: - raise RuntimeError('Unknown widget type') - self.coredata.user_options[key].set_value(newval) - - def build_type_changed(self, newtype): - self.coredata.buildtype = newtype - - def strip_changed(self, newState): - if newState == 0: - ns = False - else: - ns = True - self.coredata.strip = ns - - def coverage_changed(self, newState): - if newState == 0: - ns = False - else: - ns = True - self.coredata.coverage = ns - - def pch_changed(self, newState): - if newState == 0: - ns = False - else: - ns = True - self.coredata.use_pch = ns - - def unity_changed(self, newState): - if newState == 0: - ns = False - else: - ns = True - self.coredata.unity = ns - -class ProcessRunner(): - def __init__(self, rundir, cmdlist): - self.cmdlist = cmdlist - self.ui = uic.loadUi(os.path.join(priv_dir, 'mesonrunner.ui')) - self.timer = QTimer(self.ui) - self.timer.setInterval(1000) - self.timer.timeout.connect(self.timeout) - self.process = PyQt5.QtCore.QProcess() - self.process.setProcessChannelMode(PyQt5.QtCore.QProcess.MergedChannels) - self.process.setWorkingDirectory(rundir) - self.process.readyRead.connect(self.read_data) - self.process.finished.connect(self.finished) - self.ui.termbutton.clicked.connect(self.terminated) - self.return_value = 100 - - def run(self): - self.process.start(self.cmdlist[0], self.cmdlist[1:]) - self.timer.start() - self.start_time = time.time() - return self.ui.exec() - - def read_data(self): - while(self.process.canReadLine()): - txt = bytes(self.process.readLine()).decode('utf8') - self.ui.console.append(txt) - - def finished(self): - self.read_data() - self.ui.termbutton.setText('Done') - self.timer.stop() - self.return_value = self.process.exitCode() - - def terminated(self, foo): - self.process.kill() - self.timer.stop() - self.ui.done(self.return_value) - - def timeout(self): - now = time.time() - duration = int(now - self.start_time) - msg = 'Elapsed time: %d:%d' % (duration // 60, duration % 60) - self.ui.timelabel.setText(msg) - -class MesonGui(): - def __init__(self, respawner, build_dir): - self.respawner = respawner - uifile = os.path.join(priv_dir, 'mesonmain.ui') - self.ui = uic.loadUi(uifile) - self.coredata_file = os.path.join(build_dir, 'meson-private/coredata.dat') - self.build_file = os.path.join(build_dir, 'meson-private/build.dat') - if not os.path.exists(self.coredata_file): - print("Argument is not build directory.") - sys.exit(1) - self.coredata = pickle.load(open(self.coredata_file, 'rb')) - self.build = pickle.load(open(self.build_file, 'rb')) - self.build_dir = self.build.environment.build_dir - self.src_dir = self.build.environment.source_dir - self.build_models() - self.options = OptionForm(self.coredata, self.ui.option_form) - self.ui.show() - - def hide(self): - self.ui.hide() - - def geometry(self): - return self.ui.geometry() - - def move(self, x, y): - return self.ui.move(x, y) - - def size(self): - return self.ui.size() - - def resize(self, s): - return self.ui.resize(s) - - def build_models(self): - self.path_model = PathModel(self.coredata) - self.target_model = TargetModel(self.build) - self.dep_model = DependencyModel(self.coredata) - self.core_model = CoreModel(self.coredata) - self.fill_data() - self.ui.core_view.setModel(self.core_model) - hv = QHeaderView(1) - hv.setModel(self.core_model) - self.ui.core_view.setHeader(hv) - self.ui.path_view.setModel(self.path_model) - hv = QHeaderView(1) - hv.setModel(self.path_model) - self.ui.path_view.setHeader(hv) - self.ui.target_view.setModel(self.target_model) - hv = QHeaderView(1) - hv.setModel(self.target_model) - self.ui.target_view.setHeader(hv) - self.ui.dep_view.setModel(self.dep_model) - hv = QHeaderView(1) - hv.setModel(self.dep_model) - self.ui.dep_view.setHeader(hv) - self.ui.compile_button.clicked.connect(self.compile) - self.ui.test_button.clicked.connect(self.run_tests) - self.ui.install_button.clicked.connect(self.install) - self.ui.clean_button.clicked.connect(self.clean) - self.ui.save_button.clicked.connect(self.save) - - def fill_data(self): - self.ui.project_label.setText(self.build.projects['']) - self.ui.srcdir_label.setText(self.src_dir) - self.ui.builddir_label.setText(self.build_dir) - if self.coredata.cross_file is None: - btype = 'Native build' - else: - btype = 'Cross build' - self.ui.buildtype_label.setText(btype) - - def run_process(self, cmdlist): - cmdlist = [shutil.which(environment.detect_ninja())] + cmdlist - dialog = ProcessRunner(self.build.environment.build_dir, cmdlist) - dialog.run() - # All processes (at the moment) may change cache state - # so reload. - self.respawner.respawn() - - def compile(self, foo): - self.run_process([]) - - def run_tests(self, foo): - self.run_process(['test']) - - def install(self, foo): - self.run_process(['install']) - - def clean(self, foo): - self.run_process(['clean']) - - def save(self, foo): - pickle.dump(self.coredata, open(self.coredata_file, 'wb')) - -class Starter(): - def __init__(self, sdir): - uifile = os.path.join(priv_dir, 'mesonstart.ui') - self.ui = uic.loadUi(uifile) - self.ui.source_entry.setText(sdir) - self.dialog = PyQt5.QtWidgets.QFileDialog() - if len(sdir) == 0: - self.dialog.setDirectory(os.getcwd()) - else: - self.dialog.setDirectory(sdir) - self.ui.source_browse_button.clicked.connect(self.src_browse_clicked) - self.ui.build_browse_button.clicked.connect(self.build_browse_clicked) - self.ui.cross_browse_button.clicked.connect(self.cross_browse_clicked) - self.ui.source_entry.textChanged.connect(self.update_button) - self.ui.build_entry.textChanged.connect(self.update_button) - self.ui.generate_button.clicked.connect(self.generate) - self.update_button() - self.ui.show() - - def generate(self): - srcdir = self.ui.source_entry.text() - builddir = self.ui.build_entry.text() - cross = self.ui.cross_entry.text() - cmdlist = [os.path.join(os.path.split(__file__)[0], 'meson.py'), srcdir, builddir] - if cross != '': - cmdlist += ['--cross', cross] - pr = ProcessRunner(os.getcwd(), cmdlist) - rvalue = pr.run() - if rvalue == 0: - os.execl(__file__, 'dummy', builddir) - - def update_button(self): - if self.ui.source_entry.text() == '' or self.ui.build_entry.text() == '': - self.ui.generate_button.setEnabled(False) - else: - self.ui.generate_button.setEnabled(True) - - def src_browse_clicked(self): - self.dialog.setFileMode(2) - if self.dialog.exec(): - self.ui.source_entry.setText(self.dialog.selectedFiles()[0]) - - def build_browse_clicked(self): - self.dialog.setFileMode(2) - if self.dialog.exec(): - self.ui.build_entry.setText(self.dialog.selectedFiles()[0]) - - def cross_browse_clicked(self): - self.dialog.setFileMode(1) - if self.dialog.exec(): - self.ui.cross_entry.setText(self.dialog.selectedFiles()[0]) - -# Rather than rewrite all classes and arrays to be -# updateable, just rebuild the entire GUI from -# scratch whenever data on disk changes. - -class MesonGuiRespawner(): - def __init__(self, arg): - self.arg = arg - self.gui = MesonGui(self, self.arg) - - def respawn(self): - geo = self.gui.geometry() - s = self.gui.size() - self.gui.hide() - self.gui = MesonGui(self, self.arg) - self.gui.move(geo.x(), geo.y()) - self.gui.resize(s) - # Garbage collection takes care of the old gui widget - -if __name__ == '__main__': - app = QApplication(sys.argv) - if len(sys.argv) == 1: - arg = "" - elif len(sys.argv) == 2: - arg = sys.argv[1] - else: - print(sys.argv[0], "<build or source dir>") - sys.exit(1) - if os.path.exists(os.path.join(arg, 'meson-private/coredata.dat')): - guirespawner = MesonGuiRespawner(arg) - else: - runner = Starter(arg) - sys.exit(app.exec_()) diff --git a/meson/mesonintrospect.py b/meson/mesonintrospect.py deleted file mode 100755 index 9fcd4db..0000000 --- a/meson/mesonintrospect.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2014-2015 The Meson development 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. - -"""This is a helper script for IDE developers. It allows you to -extract information such as list of targets, files, compiler flags, -tests and so on. All output is in JSON for simple parsing. - -Currently only works for the Ninja backend. Others use generated -project files and don't need this info.""" - -import json, pickle -import coredata, build, mesonlib -import argparse -import sys, os - -parser = argparse.ArgumentParser() -parser.add_argument('--targets', action='store_true', dest='list_targets', default=False, - help='List top level targets.') -parser.add_argument('--target-files', action='store', dest='target_files', default=None, - help='List source files for a given target.') -parser.add_argument('--buildsystem-files', action='store_true', dest='buildsystem_files', default=False, - help='List files that make up the build system.') -parser.add_argument('--buildoptions', action='store_true', dest='buildoptions', default=False, - help='List all build options.') -parser.add_argument('--tests', action='store_true', dest='tests', default=False, - help='List all unit tests.') -parser.add_argument('--benchmarks', action='store_true', dest='benchmarks', default=False, - help='List all benchmarks.') -parser.add_argument('--dependencies', action='store_true', dest='dependencies', default=False, - help='list external dependencies.') -parser.add_argument('args', nargs='+') - -def list_targets(coredata, builddata): - tlist = [] - for (idname, target) in builddata.get_targets().items(): - t = {} - t['name'] = target.get_basename() - t['id'] = idname - fname = target.get_filename() - if isinstance(fname, list): - fname = [os.path.join(target.subdir, x) for x in fname] - else: - fname = os.path.join(target.subdir, fname) - t['filename'] = fname - if isinstance(target, build.Executable): - typename = 'executable' - elif isinstance(target, build.SharedLibrary): - typename = 'shared library' - elif isinstance(target, build.StaticLibrary): - typename = 'static library' - elif isinstance(target, build.CustomTarget): - typename = 'custom' - elif isinstance(target, build.RunTarget): - typename = 'run' - else: - typename = 'unknown' - t['type'] = typename - if target.should_install(): - t['installed'] = True - else: - t['installed'] = False - tlist.append(t) - print(json.dumps(tlist)) - -def list_target_files(target_name, coredata, builddata): - try: - t = builddata.targets[target_name] - sources = t.sources + t.extra_files - subdir = t.subdir - except KeyError: - print("Unknown target %s." % target_name) - sys.exit(1) - sources = [os.path.join(i.subdir, i.fname) for i in sources] - print(json.dumps(sources)) - -def list_buildoptions(coredata, builddata): - buildtype= {'choices': ['plain', 'debug', 'debugoptimized', 'release'], - 'type' : 'combo', - 'value' : coredata.buildtype, - 'description' : 'Build type', - 'name' : 'type'} - strip = {'value' : coredata.strip, - 'type' : 'boolean', - 'description' : 'Strip on install', - 'name' : 'strip'} - coverage = {'value': coredata.coverage, - 'type' : 'boolean', - 'description' : 'Enable coverage', - 'name' : 'coverage'} - pch = {'value' : coredata.use_pch, - 'type' : 'boolean', - 'description' : 'Use precompiled headers', - 'name' : 'pch'} - unity = {'value' : coredata.unity, - 'type' : 'boolean', - 'description' : 'Unity build', - 'name' : 'unity'} - optlist = [buildtype, strip, coverage, pch, unity] - add_keys(optlist, coredata.user_options) - add_keys(optlist, coredata.compiler_options) - print(json.dumps(optlist)) - -def add_keys(optlist, options): - keys = list(options.keys()) - keys.sort() - for key in keys: - opt = options[key] - optdict = {} - optdict['name'] = key - optdict['value'] = opt.value - if isinstance(opt, mesonlib.UserStringOption): - typestr = 'string' - elif isinstance(opt, mesonlib.UserBooleanOption): - typestr = 'boolean' - elif isinstance(opt, mesonlib.UserComboOption): - optdict['choices'] = opt.choices - typestr = 'combo' - elif isinstance(opt, mesonlib.UserStringArrayOption): - typestr = 'stringarray' - else: - raise RuntimeError("Unknown option type") - optdict['type'] = typestr - optdict['description'] = opt.description - optlist.append(optdict) - -def list_buildsystem_files(coredata, builddata): - src_dir = builddata.environment.get_source_dir() - # I feel dirty about this. But only slightly. - filelist = [] - for root, _, files in os.walk(src_dir): - for f in files: - if f == 'meson.build' or f == 'meson_options.txt': - filelist.append(os.path.relpath(os.path.join(root, f), src_dir)) - print(json.dumps(filelist)) - -def list_deps(coredata): - result = {} - for d in coredata.deps.values(): - if d.found(): - args = {'compile_args': d.get_compile_args(), - 'link_args': d.get_link_args()} - result[d.name] = args - print(json.dumps(result)) - -def list_tests(testdata): - result = [] - for t in testdata: - to = {} - if isinstance(t.fname, str): - fname = [t.fname] - else: - fname = t.fname - to['cmd'] = fname + t.cmd_args - to['env'] = t.env - to['name'] = t.name - to['workdir'] = t.workdir - to['timeout'] = t.timeout - to['suite'] = t.suite - result.append(to) - print(json.dumps(result)) - -if __name__ == '__main__': - options = parser.parse_args() - if len(options.args) > 1: - print('Too many arguments') - sys.exit(1) - elif len(options.args) == 1: - bdir = options.args[0] - else: - bdir = '' - corefile = os.path.join(bdir, 'meson-private/coredata.dat') - buildfile = os.path.join(bdir, 'meson-private/build.dat') - testfile = os.path.join(bdir, 'meson-private/meson_test_setup.dat') - benchmarkfile = os.path.join(bdir, 'meson-private/meson_benchmark_setup.dat') - coredata = pickle.load(open(corefile, 'rb')) - builddata = pickle.load(open(buildfile, 'rb')) - testdata = pickle.load(open(testfile, 'rb')) - benchmarkdata = pickle.load(open(benchmarkfile, 'rb')) - if options.list_targets: - list_targets(coredata, builddata) - elif options.target_files is not None: - list_target_files(options.target_files, coredata, builddata) - elif options.buildsystem_files: - list_buildsystem_files(coredata, builddata) - elif options.buildoptions: - list_buildoptions(coredata, builddata) - elif options.tests: - list_tests(testdata) - elif options.benchmarks: - list_tests(benchmarkdata) - elif options.dependencies: - list_deps(coredata) - else: - print('No command specified') - sys.exit(1) diff --git a/meson/mesonmain.py b/meson/mesonmain.py index c4a9ada..0bf123c 100755..100644 --- a/meson/mesonmain.py +++ b/meson/mesonmain.py @@ -220,6 +220,3 @@ def run(args): traceback.print_exc() return 1 return 0 - -if __name__ == '__main__': - sys.exit(run(sys.argv[:])) diff --git a/meson/ninjabackend.py b/meson/ninjabackend.py index 53b59a1..d21cea0 100644 --- a/meson/ninjabackend.py +++ b/meson/ninjabackend.py @@ -18,7 +18,7 @@ from . import build from . import mlog from . import dependencies from .mesonlib import File -from .meson_install import InstallData +from .backends import InstallData from .build import InvalidArguments from .coredata import MesonException import os, sys, pickle, re diff --git a/meson/regen_checker.py b/meson/regen_checker.py deleted file mode 100755 index a0fe028..0000000 --- a/meson/regen_checker.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2015 The Meson development 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 sys, os -import pickle, subprocess - -# This could also be used for XCode. - -def need_regen(regeninfo): - sln_time = os.stat(os.path.join(regeninfo.build_dir, regeninfo.solutionfile)).st_mtime - for i in regeninfo.depfiles: - curfile = os.path.join(regeninfo.build_dir, i) - curtime = os.stat(curfile).st_mtime - if curtime > sln_time: - return True - return False - -def regen(regeninfo): - scriptdir = os.path.split(__file__)[0] - mesonscript = os.path.join(scriptdir, 'meson.py') - cmd = [sys.executable, mesonscript, regeninfo.build_dir, regeninfo.source_dir, - '--backend=vs2010', 'secret-handshake'] - subprocess.check_call(cmd) - -if __name__ == '__main__': - regeninfo = pickle.load(open(os.path.join(sys.argv[1], 'regeninfo.dump'), 'rb')) - if need_regen(regeninfo): - regen(regeninfo) - sys.exit(0) diff --git a/meson/symbolextractor.py b/meson/symbolextractor.py deleted file mode 100755 index f2c709d..0000000 --- a/meson/symbolextractor.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2013-2015 The Meson development 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. - -# This script extracts the symbols of a given shared library -# into a file. If the symbols have not changed, the file is not -# touched. This information is used to skip link steps if the -# ABI has not changed. - -# This file is basically a reimplementation of -# http://cgit.freedesktop.org/libreoffice/core/commit/?id=3213cd54b76bc80a6f0516aac75a48ff3b2ad67c - -import sys, subprocess -import mesonlib -import argparse - -parser = argparse.ArgumentParser() - -parser.add_argument('--cross-host', default=None, dest='cross_host', - help='cross compilation host platform') -parser.add_argument('args', nargs='+') - -def dummy_syms(outfilename): - """Just touch it so relinking happens always.""" - open(outfilename, 'w').close() - -def write_if_changed(text, outfilename): - try: - oldtext = open(outfilename, 'r').read() - if text == oldtext: - return - except FileNotFoundError: - pass - open(outfilename, 'w').write(text) - -def linux_syms(libfilename, outfilename): - pe = subprocess.Popen(['readelf', '-d', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output = pe.communicate()[0].decode() - if pe.returncode != 0: - raise RuntimeError('Readelf does not work') - result = [x for x in output.split('\n') if 'SONAME' in x] - assert(len(result) <= 1) - pnm = subprocess.Popen(['nm', '--dynamic', '--extern-only', '--defined-only', '--format=posix', libfilename], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output = pnm.communicate()[0].decode() - if pnm.returncode != 0: - raise RuntimeError('nm does not work.') - result += [' '.join(x.split()[0:2]) for x in output.split('\n') if len(x) > 0] - write_if_changed('\n'.join(result) + '\n', outfilename) - -def osx_syms(libfilename, outfilename): - pe = subprocess.Popen(['otool', '-l', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output = pe.communicate()[0].decode() - if pe.returncode != 0: - raise RuntimeError('Otool does not work.') - arr = output.split('\n') - for (i, val) in enumerate(arr): - if 'LC_ID_DYLIB' in val: - match = i - break - result = [arr[match+2], arr[match+5]] # Libreoffice stores all 5 lines but the others seem irrelevant. - pnm = subprocess.Popen(['nm', '-g', '-P', libfilename], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output = pnm.communicate()[0].decode() - if pnm.returncode != 0: - raise RuntimeError('nm does not work.') - result += [' '.join(x.split()[0:2]) for x in output.split('\n') if len(x) > 0 and not x.endswith('U')] - write_if_changed('\n'.join(result) + '\n', outfilename) - -def gen_symbols(libfilename, outfilename, cross_host): - if cross_host is not None: - # In case of cross builds just always relink. - # In theory we could determine the correct - # toolset but there are more important things - # to do. - dummy_syms(outfilename) - elif mesonlib.is_linux(): - linux_syms(libfilename, outfilename) - elif mesonlib.is_osx(): - osx_syms(libfilename, outfilename) - else: - dummy_syms(outfilename) - -if __name__ == '__main__': - options = parser.parse_args() - if len(options.args) != 2: - print(sys.argv[0], '<shared library file> <output file>') - sys.exit(1) - libfile = options.args[0] - outfile = options.args[1] - gen_symbols(libfile, outfile, options.cross_host) diff --git a/meson/vcstagger.py b/meson/vcstagger.py deleted file mode 100755 index ccc584e..0000000 --- a/meson/vcstagger.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2015 The Meson development 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 sys, os, subprocess, re - -def config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, cmd): - try: - output = subprocess.check_output(cmd, cwd=source_dir) - new_string = re.search(regex_selector, output.decode()).group(1).strip() - except Exception: - new_string = fallback - - new_data = open(infile).read().replace(replace_string, new_string) - if (not os.path.exists(outfile)) or (open(outfile).read() != new_data): - open(outfile, 'w').write(new_data) - -if __name__ == '__main__': - infile, outfile, fallback, source_dir, replace_string, regex_selector = sys.argv[1:7] - command = sys.argv[7:] - config_vcs_tag(infile, outfile, fallback, source_dir, replace_string, regex_selector, command) diff --git a/meson/wrap.py b/meson/wrap.py index e55d3db..ac9c9ce 100644 --- a/meson/wrap.py +++ b/meson/wrap.py @@ -17,7 +17,33 @@ import urllib.request, os, hashlib, shutil import subprocess import sys -from . import wraptool +try: + import ssl + has_ssl = True + API_ROOT = 'https://wrapdb.mesonbuild.com/v1/' +except ImportError: + has_ssl = False + API_ROOT = 'http://wrapdb.mesonbuild.com/v1/' + +def open_wrapdburl(urlstring): + global ssl_warning_printed + if has_ssl: + try: + return urllib.request.urlopen(urlstring)#, context=build_ssl_context()) + except urllib.error.URLError: + if not ssl_warning_printed: + print('SSL connection failed. Falling back to unencrypted connections.') + ssl_warning_printed = True + if not ssl_warning_printed: + print('Warning: SSL not available, traffic not authenticated.', + file=sys.stderr) + ssl_warning_printed = True + # Trying to open SSL connection to wrapdb fails because the + # certificate is not known. + if urlstring.startswith('https'): + urlstring = 'http' + urlstring[5:] + return urllib.request.urlopen(urlstring) + class PackageDefinition: def __init__(self, fname): @@ -94,7 +120,7 @@ class Resolver: def get_data(self, url): blocksize = 10*1024 if url.startswith('https://wrapdb.mesonbuild.com'): - resp = wraptool.open_wrapdburl(url) + resp = open_wrapdburl(url) else: resp = urllib.request.urlopen(url) dlsize = int(resp.info()['Content-Length']) diff --git a/meson/wraptool.py b/meson/wraptool.py deleted file mode 100755 index 2366b78..0000000 --- a/meson/wraptool.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2015 The Meson development 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 urllib.request, json -import sys, os -import configparser -import shutil -import platform -try: - import ssl - has_ssl = True - API_ROOT = 'https://wrapdb.mesonbuild.com/v1/' -except ImportError: - has_ssl = False - API_ROOT = 'http://wrapdb.mesonbuild.com/v1/' - - -ssl_warning_printed = False - -from glob import glob - -help_templ = '''This program allows you to manage your Wrap dependencies -using the online wrap database http://wrapdb.mesonbuild.com. - -Run this command in your top level source directory. - -Usage: - -%s <command> [options] - -Commands: - - list - show all available projects - search - search the db by name - install - install the specified project - update - update the project to its newest available release - info - show available versions of a project - status - show installed and available versions of your projects - -''' - - -def print_help(): - print(help_templ % sys.argv[0]) - -def build_ssl_context(): - ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ctx.options |= ssl.OP_NO_SSLv2 - ctx.options |= ssl.OP_NO_SSLv3 - ctx.verify_mode = ssl.CERT_REQUIRED - ctx.load_default_certs() - return ctx - -def open_wrapdburl(urlstring): - global ssl_warning_printed - if has_ssl: - try: - return urllib.request.urlopen(urlstring)#, context=build_ssl_context()) - except urllib.error.URLError: - if not ssl_warning_printed: - print('SSL connection failed. Falling back to unencrypted connections.') - ssl_warning_printed = True - if not ssl_warning_printed: - print('Warning: SSL not available, traffic not authenticated.', - file=sys.stderr) - ssl_warning_printed = True - # Trying to open SSL connection to wrapdb fails because the - # certificate is not known. - if urlstring.startswith('https'): - urlstring = 'http' + urlstring[5:] - return urllib.request.urlopen(urlstring) - -def get_result(urlstring): - u = open_wrapdburl(urlstring) - data = u.read().decode('utf-8') - jd = json.loads(data) - if jd['output'] != 'ok': - print('Got bad output from server.') - print(data) - sys.exit(1) - return jd - -def get_projectlist(): - jd = get_result(API_ROOT + 'projects') - projects = jd['projects'] - return projects - -def list_projects(): - projects = get_projectlist() - for p in projects: - print(p) - -def search(name): - jd = get_result(API_ROOT + 'query/byname/' + name) - for p in jd['projects']: - print(p) - -def get_latest_version(name): - jd = get_result(API_ROOT + 'query/get_latest/' + name) - branch = jd['branch'] - revision = jd['revision'] - return (branch, revision) - -def install(name): - if not os.path.isdir('subprojects'): - print('Subprojects dir not found. Run this script in your source root directory.') - sys.exit(1) - if os.path.isdir(os.path.join('subprojects', name)): - print('Subproject directory for this project already exists.') - sys.exit(1) - wrapfile = os.path.join('subprojects', name + '.wrap') - if os.path.exists(wrapfile): - print('Wrap file already exists.') - sys.exit(1) - (branch, revision) = get_latest_version(name) - u = open_wrapdburl(API_ROOT + 'projects/%s/%s/%s/get_wrap' % (name, branch, revision)) - data = u.read() - open(wrapfile, 'wb').write(data) - print('Installed', name, 'branch', branch, 'revision', revision) - -def get_current_version(wrapfile): - cp = configparser.ConfigParser() - cp.read(wrapfile) - cp = cp['wrap-file'] - patch_url = cp['patch_url'] - arr = patch_url.split('/') - branch = arr[-3] - revision = int(arr[-2]) - return (branch, revision, cp['directory'], cp['source_filename'], cp['patch_filename']) - -def update(name): - if not os.path.isdir('subprojects'): - print('Subprojects dir not found. Run this command in your source root directory.') - sys.exit(1) - wrapfile = os.path.join('subprojects', name + '.wrap') - if not os.path.exists(wrapfile): - print('Project', name, 'is not in use.') - sys.exit(1) - (branch, revision, subdir, src_file, patch_file) = get_current_version(wrapfile) - (new_branch, new_revision) = get_latest_version(name) - if new_branch == branch and new_revision == revision: - print('Project', name, 'is already up to date.') - sys.exit(0) - u = open_wrapdburl(API_ROOT + 'projects/%s/%s/%d/get_wrap' % (name, new_branch, new_revision)) - data = u.read() - shutil.rmtree(os.path.join('subprojects', subdir), ignore_errors=True) - try: - os.unlink(os.path.join('subprojects/packagecache', src_file)) - except FileNotFoundError: - pass - try: - os.unlink(os.path.join('subprojects/packagecache', patch_file)) - except FileNotFoundError: - pass - open(wrapfile, 'wb').write(data) - print('Updated', name, 'to branch', new_branch, 'revision', new_revision) - -def info(name): - jd = get_result(API_ROOT + 'projects/' + name) - versions = jd['versions'] - if len(versions) == 0: - print('No available versions of', name) - sys.exit(0) - print('Available versions of %s:' % name) - for v in versions: - print(' ', v['branch'], v['revision']) - -def status(): - print('Subproject status') - for w in glob('subprojects/*.wrap'): - name = os.path.split(w)[1][:-5] - try: - (latest_branch, latest_revision) = get_latest_version(name) - except Exception: - print('', name, 'not available in wrapdb.') - continue - try: - (current_branch, current_revision, _, _, _) = get_current_version(w) - except Exception: - print('Wrap file not from wrapdb.') - continue - if current_branch == latest_branch and current_revision == latest_revision: - print('', name, 'up to date. Branch %s, revision %d.' % (current_branch, current_revision)) - else: - print('', name, 'not up to date. Have %s %d, but %s %d is available.' % (current_branch, current_revision, latest_branch, latest_revision)) - -if __name__ == '__main__': - if len(sys.argv) < 2 or sys.argv[1] == '-h' or sys.argv[1] == '--help': - print_help() - sys.exit(0) - command = sys.argv[1] - args = sys.argv[2:] - if command == 'list': - list_projects() - elif command == 'search': - if len(args) != 1: - print('Search requires exactly one argument.') - sys.exit(1) - search(args[0]) - elif command == 'install': - if len(args) != 1: - print('Install requires exactly one argument.') - sys.exit(1) - install(args[0]) - elif command == 'update': - if len(args) != 1: - print('update requires exactly one argument.') - sys.exit(1) - update(args[0]) - elif command == 'info': - if len(args) != 1: - print('info requires exactly one argument.') - sys.exit(1) - info(args[0]) - elif command == 'status': - status() - else: - print('Unknown command', command) - sys.exit(1) - |