aboutsummaryrefslogtreecommitdiff
path: root/meson
diff options
context:
space:
mode:
Diffstat (limited to 'meson')
-rw-r--r--meson/backends.py15
-rwxr-xr-xmeson/commandrunner.py55
-rwxr-xr-xmeson/delwithsuffix.py32
-rwxr-xr-xmeson/depfixer.py299
-rwxr-xr-xmeson/dirchanger.py26
-rw-r--r--meson/environment.py2
-rwxr-xr-xmeson/gtkdochelper.py118
-rwxr-xr-xmeson/meson_benchmark.py97
-rwxr-xr-xmeson/meson_install.py227
-rwxr-xr-xmeson/meson_test.py232
-rwxr-xr-xmeson/mesonconf.py205
-rwxr-xr-xmeson/mesongui.py561
-rwxr-xr-xmeson/mesonintrospect.py208
-rw-r--r--[-rwxr-xr-x]meson/mesonmain.py3
-rw-r--r--meson/ninjabackend.py2
-rwxr-xr-xmeson/regen_checker.py42
-rwxr-xr-xmeson/symbolextractor.py102
-rwxr-xr-xmeson/vcstagger.py33
-rw-r--r--meson/wrap.py30
-rwxr-xr-xmeson/wraptool.py233
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)
-