aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml22
-rw-r--r--man/mesongui.124
-rw-r--r--mesonbuild/backend/ninjabackend.py16
-rw-r--r--mesonbuild/backend/vs2010backend.py27
-rw-r--r--mesonbuild/backend/vs2015backend.py34
-rw-r--r--mesonbuild/compilers.py15
-rw-r--r--mesonbuild/coredata.py6
-rw-r--r--mesonbuild/environment.py8
-rw-r--r--mesonbuild/interpreter.py28
-rw-r--r--mesonbuild/mesonlib.py21
-rw-r--r--mesonbuild/mesonmain.py4
-rw-r--r--mesonbuild/mesonmain.ui248
-rw-r--r--mesonbuild/mesonrunner.ui52
-rw-r--r--mesonbuild/mesonstart.ui119
-rw-r--r--mesonbuild/mgui.py543
-rw-r--r--mesonbuild/scripts/meson_install.py47
-rwxr-xr-xmesongui.py20
-rwxr-xr-xrun_tests.py10
-rw-r--r--setup.py3
-rw-r--r--test cases/common/10 man install/installed_files.txt1
-rw-r--r--test cases/common/10 man install/meson.build1
-rw-r--r--test cases/common/10 man install/vanishing/vanishing.21
-rw-r--r--test cases/common/16 configure file/dumpprog.c33
-rw-r--r--test cases/common/16 configure file/meson.build15
-rw-r--r--test cases/common/49 subproject/meson.build2
-rw-r--r--test cases/common/49 subproject/subprojects/sublib/meson.build2
-rw-r--r--test cases/common/66 install subdir/installed_files.txt2
-rw-r--r--test cases/common/66 install subdir/meson.build2
-rw-r--r--test cases/common/66 install subdir/sub/sub1/third.dat1
-rw-r--r--test cases/common/66 install subdir/sub1/second.dat1
30 files changed, 253 insertions, 1055 deletions
diff --git a/.travis.yml b/.travis.yml
index 8b13401..2564742 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,18 +1,26 @@
sudo: required
-language: c
+os:
+ - linux
+ - osx
+
+language:
+ - cpp
services:
- docker
before_install:
- - docker pull jpakkane/mesonci:xenial
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull jpakkane/mesonci:xenial; fi
-# We need to copy the current checkout inside the container,
+# We need to copy the current checkout inside the Docker container,
# because it has the MR id to be tested checked out.
script:
- - echo FROM jpakkane/mesonci:xenial > Dockerfile
- - echo ADD . /root >> Dockerfile
- - docker build -t withgit .
- - docker run withgit /bin/sh -c "cd /root && ./run_tests.py"
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:xenial > Dockerfile; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi
+ - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && ./run_tests.py"; fi
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./run_tests.py --backend=ninja ; fi
diff --git a/man/mesongui.1 b/man/mesongui.1
deleted file mode 100644
index 976c3f7..0000000
--- a/man/mesongui.1
+++ /dev/null
@@ -1,24 +0,0 @@
-.TH MESONGUI "1" "April 2016" "mesongui 0.31.0" "User Commands"
-.SH NAME
-mesongui - a gui for the Meson build system
-.SH DESCRIPTION
-
-Mesongui provides a graphical user interface to the Meson
-build system. It can be used for two main purposes: configuring
-an existing build or creating a new build for the given source.
-
-.B mesongui [
-.I source or build directory
-.B ]
-
-If the argument is a directory with a Meson project, the
-Gui will allow you to configure and generate a build tree
-for it.
-
-If the argument is an existing build directory, Mesongui will
-start a gui that will show all your configuration
-options and allows you to change them as desired. The
-gui can also be used to build and install the project.
-
-.SH SEE ALSO
-http://mesonbuild.com/
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 3bec19d..077254d 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -459,8 +459,6 @@ int dummy;
mlog.log(mlog.red('Warning:'), 'coverage requested but neither gcovr nor lcov/genhtml found.')
def generate_install(self, outfile):
- script_root = self.environment.get_script_dir()
- install_script = os.path.join(script_root, 'meson_install.py')
install_data_file = os.path.join(self.environment.get_scratch_dir(), 'install.dat')
d = InstallData(self.environment.get_source_dir(),
self.environment.get_build_dir(),
@@ -525,7 +523,7 @@ int dummy;
if subdir is None:
subdir = os.path.join(manroot, 'man' + num)
srcabs = os.path.join(self.environment.get_source_dir(), m.get_source_subdir(), f)
- dstabs = os.path.join(subdir, f + '.gz')
+ dstabs = os.path.join(subdir, os.path.split(f)[1] + '.gz')
i = [srcabs, dstabs]
d.man.append(i)
@@ -547,9 +545,17 @@ int dummy;
def generate_subdir_install(self, d):
for sd in self.build.get_install_subdirs():
- src_dir = os.path.join(self.environment.get_source_dir(), sd.source_subdir, sd.installable_subdir)
+ inst_subdir = sd.installable_subdir.rstrip('/')
+ idir_parts = inst_subdir.split('/')
+ if len(idir_parts) > 1:
+ subdir = os.path.join(sd.source_subdir, '/'.join(idir_parts[:-1]))
+ inst_dir = idir_parts[-1]
+ else:
+ subdir = sd.source_subdir
+ inst_dir = sd.installable_subdir
+ src_dir = os.path.join(self.environment.get_source_dir(), subdir)
dst_dir = os.path.join(self.environment.get_prefix(), sd.install_dir)
- d.install_subdirs.append([src_dir, dst_dir])
+ d.install_subdirs.append([src_dir, inst_dir, dst_dir])
def write_test_suite_targets(self, cmd, outfile):
suites = {}
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index 355798d..540dd04 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -39,6 +39,7 @@ class Vs2010Backend(backends.Backend):
super().__init__(build)
self.project_file_version = '10.0.30319.1'
self.sources_conflicts = {}
+ self.platform_toolset = None
def object_filename_from_source(self, target, source):
basename = os.path.basename(source.fname)
@@ -309,6 +310,8 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(type_config, 'ConfigurationType')
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
ET.SubElement(type_config, 'UseOfMfc').text = 'false'
+ if self.platform_toolset:
+ ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
direlem = ET.SubElement(root, 'PropertyGroup')
fver = ET.SubElement(direlem, '_ProjectFileVersion')
@@ -385,6 +388,18 @@ class Vs2010Backend(backends.Backend):
lang = Vs2010Backend.lang_from_source_file(source_file)
ET.SubElement(parent_node, "AdditionalOptions").text = ' '.join(extra_args[lang]) + ' %(AdditionalOptions)'
+ @staticmethod
+ def has_objects(objects, additional_objects, generated_objects):
+ # Ignore generated objects, those are automatically used by MSBuild for VS2010, because they are part of
+ # the CustomBuildStep Outputs.
+ return len(objects) + len(additional_objects) > 0
+
+ @staticmethod
+ def add_generated_objects(node, generated_objects):
+ # Do not add generated objects to project file. Those are automatically used by MSBuild for VS2010, because
+ # they are part of the CustomBuildStep Outputs.
+ return
+
@classmethod
def quote_define_cmdline(cls, arg):
return re.sub(r'^([-/])D(.*?)="(.*)"$', r'\1D\2=\"\3\"', arg)
@@ -441,6 +456,8 @@ class Vs2010Backend(backends.Backend):
type_config = ET.SubElement(root, 'PropertyGroup', Label='Configuration')
ET.SubElement(type_config, 'ConfigurationType').text = conftype
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
+ if self.platform_toolset:
+ ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset
ET.SubElement(type_config, 'WholeProgramOptimization').text = 'false'
ET.SubElement(type_config, 'UseDebugLibraries').text = 'true'
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
@@ -641,15 +658,15 @@ class Vs2010Backend(backends.Backend):
pch_file.text = os.path.split(header)[1]
self.add_additional_options(impl, inc_cl, extra_args, additional_options_set)
- if len(objects) + len(additional_objects) > 0:
- # Do not add gen_objs to project file. Those are automatically used by MSBuild, because they are part of
- # the CustomBuildStep Outputs.
+ if self.has_objects(objects, additional_objects, gen_objs):
inc_objs = ET.SubElement(root, 'ItemGroup')
for s in objects:
relpath = s.rel_to_builddir(proj_to_src_root)
ET.SubElement(inc_objs, 'Object', Include=relpath)
for s in additional_objects:
ET.SubElement(inc_objs, 'Object', Include=s)
+ self.add_generated_objects(inc_objs, gen_objs)
+
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
# Reference the regen target.
ig = ET.SubElement(root, 'ItemGroup')
@@ -691,6 +708,8 @@ class Vs2010Backend(backends.Backend):
ET.SubElement(type_config, 'ConfigurationType').text = "Utility"
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
ET.SubElement(type_config, 'UseOfMfc').text = 'false'
+ if self.platform_toolset:
+ ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
direlem = ET.SubElement(root, 'PropertyGroup')
fver = ET.SubElement(direlem, '_ProjectFileVersion')
@@ -768,6 +787,8 @@ if %%errorlevel%% neq 0 goto :VCEnd'''
ET.SubElement(type_config, 'ConfigurationType')
ET.SubElement(type_config, 'CharacterSet').text = 'MultiByte'
ET.SubElement(type_config, 'UseOfMfc').text = 'false'
+ if self.platform_toolset:
+ ET.SubElement(type_config, 'PlatformToolset').text = self.platform_toolset
ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.props')
direlem = ET.SubElement(root, 'PropertyGroup')
fver = ET.SubElement(direlem, '_ProjectFileVersion')
diff --git a/mesonbuild/backend/vs2015backend.py b/mesonbuild/backend/vs2015backend.py
new file mode 100644
index 0000000..c138cb5
--- /dev/null
+++ b/mesonbuild/backend/vs2015backend.py
@@ -0,0 +1,34 @@
+# Copyright 2014-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.
+
+from xml.etree import ElementTree as ET
+from .vs2010backend import Vs2010Backend
+
+
+class Vs2015Backend(Vs2010Backend):
+ def __init__(self, build):
+ super().__init__(build)
+ self.platform_toolset = 'v140'
+
+ @staticmethod
+ def has_objects(objects, additional_objects, generated_objects):
+ # VS2015 requires generated objects to be added explicitly to the project file.
+ return len(objects) + len(additional_objects) + len(generated_objects) > 0
+
+ @staticmethod
+ def add_generated_objects(node, generated_objects):
+ # VS2015 requires generated objects to be added explicitly to the project file.
+ for s in generated_objects:
+ ET.SubElement(node, 'Object', Include=s)
+ return
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 1fc936a..03ef9f9 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -116,7 +116,7 @@ msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
base_options = {
- 'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', False),
+ 'b_pch': coredata.UserBooleanOption('b_pch', 'Use precompiled headers', True),
'b_lto': coredata.UserBooleanOption('b_lto', 'Use link time optimization', False),
'b_sanitize': coredata.UserComboOption('b_sanitize',
'Code sanitizer to use',
@@ -533,7 +533,12 @@ int main () {{ {1}; }}'''
ofile = open(srcname, 'w')
ofile.write(code)
ofile.close()
- extra_args = self.unix_link_flags_to_native(extra_args) + \
+ # Need to add buildtype args to select the CRT to use with MSVC
+ # This is needed especially while trying to link with static libraries
+ # since MSVC won't auto-select a CRT for us in that case and will error
+ # out asking us to select one.
+ extra_args = self.get_buildtype_args('debug') + \
+ self.unix_link_flags_to_native(extra_args) + \
self.get_output_args(dstname)
p = self.compile(code, srcname, extra_args)
try:
@@ -553,6 +558,8 @@ int main () {{ {1}; }}'''
ofile.close()
exename = srcname + '.exe' # Is guaranteed to be executable on every platform.
commands = self.get_exelist()
+ # Same reasoning as self.links() above
+ commands += self.get_buildtype_args('debug')
commands += self.unix_link_flags_to_native(extra_args)
commands.append(srcname)
commands += self.get_output_args(exename)
@@ -1688,7 +1695,7 @@ class GnuCPPCompiler(CPPCompiler):
def get_options(self):
opts = {'cpp_std' : coredata.UserComboOption('cpp_std', 'C++ language standard to use',
- ['none', 'c++03', 'c++11', 'c++14'],
+ ['none', 'c++03', 'c++11', 'c++14', 'c++1z'],
'none'),
'cpp_debugstl': coredata.UserBooleanOption('cpp_debugstl',
'STL debug mode',
@@ -1743,7 +1750,7 @@ class ClangCPPCompiler(CPPCompiler):
def get_options(self):
return {'cpp_std' : coredata.UserComboOption('cpp_std', 'C++ language standard to use',
- ['none', 'c++03', 'c++11', 'c++14'],
+ ['none', 'c++03', 'c++11', 'c++14', 'c++1z'],
'none')}
def get_option_compile_args(self, options):
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 8227340..5f00ac3 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -16,6 +16,7 @@ import pickle, os, uuid
from .mesonlib import MesonException, default_libdir, default_libexecdir, default_prefix
version = '0.32.0.dev1'
+backendlist = ['ninja', 'vs2010', 'vs2015', 'xcode']
class UserOption:
def __init__(self, name, description, choices):
@@ -69,6 +70,9 @@ class UserBooleanOption(UserOption):
return True
raise MesonException('Value "%s" for boolean option "%s" is not a boolean.' % (valuestring, self.name))
+ def __bool__(self):
+ return self.value
+
class UserComboOption(UserOption):
def __init__(self, name, description, choices, value):
super().__init__(name, description, choices)
@@ -209,7 +213,7 @@ builtin_options = {
'warning_level' : [ UserComboOption, 'Compiler warning level to use.', [ '1', '2', '3' ], '1'],
'layout' : [ UserComboOption, 'Build directory layout.', ['mirror', 'flat' ], 'mirror' ],
'default_library' : [ UserComboOption, 'Default library type.', [ 'shared', 'static' ], 'shared' ],
- 'backend' : [ UserComboOption, 'Backend to use.', [ 'ninja', 'vs2010', 'xcode' ], 'ninja' ],
+ 'backend' : [ UserComboOption, 'Backend to use.', backendlist, 'ninja' ],
'stdsplit' : [ UserBooleanOption, 'Split stdout and stderr in test logs.', True ],
'errorlogs' : [ UserBooleanOption, "Whether to print the logs from failing tests.", False ],
}
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 5096320..fcd4bdb 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -309,7 +309,13 @@ class Environment():
version = vmatch.group(0)
if 'GNU Fortran' in out:
- return GnuFortranCompiler([compiler], version, GCC_STANDARD, is_cross, exe_wrap)
+ if mesonlib.is_osx():
+ gcctype = GCC_OSX
+ elif mesonlib.is_windows():
+ gcctype = GCC_MINGW
+ else:
+ gcctype = GCC_STANDARD
+ return GnuFortranCompiler([compiler], version, gcctype, is_cross, exe_wrap)
if 'G95' in out:
return G95FortranCompiler([compiler], version, is_cross, exe_wrap)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index f0d22c5..47ed61c 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -837,6 +837,7 @@ class MesonMain(InterpreterObject):
'add_postconf_script' : self.add_postconf_script_method,
'install_dependency_manifest': self.install_dependency_manifest_method,
'project_version': self.project_version_method,
+ 'project_name' : self.project_name_method,
})
def add_install_script_method(self, args, kwargs):
@@ -933,6 +934,9 @@ class MesonMain(InterpreterObject):
def project_version_method(self, args, kwargs):
return self.build.dep_manifest[self.interpreter.active_projectname]['version']
+ def project_name_method(self, args, kwargs):
+ return self.interpreter.active_projectname
+
class Interpreter():
def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects'):
@@ -1903,13 +1907,11 @@ class Interpreter():
def func_configure_file(self, node, args, kwargs):
if len(args) > 0:
raise InterpreterException("configure_file takes only keyword arguments.")
- if not 'input' in kwargs:
- raise InterpreterException('Required keyword argument "input" not defined.')
if not 'output' in kwargs:
raise InterpreterException('Required keyword argument "output" not defined.')
- inputfile = kwargs['input']
+ inputfile = kwargs.get('input', None)
output = kwargs['output']
- if not isinstance(inputfile, str):
+ if not isinstance(inputfile, (str, type(None))):
raise InterpreterException('Input must be a string.')
if not isinstance(output, str):
raise InterpreterException('Output must be a string.')
@@ -1919,16 +1921,20 @@ class Interpreter():
conf = kwargs['configuration']
if not isinstance(conf, ConfigurationDataHolder):
raise InterpreterException('Argument "configuration" is not of type configuration_data')
-
- conffile = os.path.join(self.subdir, inputfile)
- if conffile not in self.build_def_files:
- self.build_def_files.append(conffile)
- os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
- ifile_abs = os.path.join(self.environment.source_dir, self.subdir, inputfile)
ofile_abs = os.path.join(self.environment.build_dir, self.subdir, output)
- mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object)
+ if inputfile is not None:
+ conffile = os.path.join(self.subdir, inputfile)
+ if conffile not in self.build_def_files:
+ self.build_def_files.append(conffile)
+ os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
+ ifile_abs = os.path.join(self.environment.source_dir, self.subdir, inputfile)
+ mesonlib.do_conf_file(ifile_abs, ofile_abs, conf.held_object)
+ else:
+ mesonlib.dump_conf_header(ofile_abs, conf.held_object)
conf.mark_used()
elif 'command' in kwargs:
+ if 'input' not in kwargs:
+ raise InterpreterException('Required keyword input missing.')
res = self.func_run_command(node, kwargs['command'], {})
if res.returncode != 0:
raise InterpreterException('Running configure command failed.\n%s\n%s' %
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index c4fdead..837f78a 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -267,6 +267,27 @@ def do_conf_file(src, dst, confdata):
shutil.copymode(src, dst_tmp)
replace_if_different(dst, dst_tmp)
+def dump_conf_header(ofilename, cdata):
+ with open(ofilename, 'w') as ofile:
+ ofile.write('''/*
+ * Autogenerated by the Meson build system.
+ * Do not edit, your changes will be lost.
+ */
+
+#pragma once
+
+''')
+ for k in sorted(cdata.keys()):
+ v = cdata.get(k)
+ if isinstance(v, bool):
+ if v:
+ ofile.write('#define %s\n\n' % k)
+ else:
+ ofile.write('#undef %s\n\n' % k)
+ elif isinstance(v, (int, str)):
+ ofile.write('#define %s %s\n\n' % (k, v))
+ else:
+ raise MesonException('Unknown data type in configuration file entry: ' + k)
def replace_if_different(dst, dst_tmp):
# If contents are identical, don't touch the file to prevent
diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py
index 4f8314c..3f5612b 100644
--- a/mesonbuild/mesonmain.py
+++ b/mesonbuild/mesonmain.py
@@ -23,7 +23,6 @@ import platform
from . import mlog, coredata
from .mesonlib import MesonException
-backendlist = ['ninja', 'vs2010', 'xcode']
parser = argparse.ArgumentParser()
@@ -139,6 +138,9 @@ itself as required.'''
elif self.options.backend == 'vs2010':
from .backend import vs2010backend
g = vs2010backend.Vs2010Backend(b)
+ elif self.options.backend == 'vs2015':
+ from .backend import vs2015backend
+ g = vs2015backend.Vs2015Backend(b)
elif self.options.backend == 'xcode':
from .backend import xcodebackend
g = xcodebackend.XCodeBackend(b)
diff --git a/mesonbuild/mesonmain.ui b/mesonbuild/mesonmain.ui
deleted file mode 100644
index 209584b..0000000
--- a/mesonbuild/mesonmain.ui
+++ /dev/null
@@ -1,248 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>740</width>
- <height>613</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Meson</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Project</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLabel" name="project_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Source directory</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLabel" name="srcdir_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_5">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Build directory</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="builddir_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>Build type</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLabel" name="buildtype_label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TextLabel</string>
- </property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Backend</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLabel" name="backend_label">
- <property name="text">
- <string>Ninja</string>
- </property>
- </widget>
- </item>
- <item row="5" column="0" colspan="2">
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>2</number>
- </property>
- <widget class="QWidget" name="core_tab">
- <attribute name="title">
- <string>Core data</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_6">
- <item row="0" column="0">
- <widget class="QTreeView" name="core_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="path_tab">
- <attribute name="title">
- <string>Paths</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="0">
- <widget class="QTreeView" name="path_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="option_tab">
- <attribute name="title">
- <string>Options</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_4">
- <item row="0" column="0">
- <layout class="QFormLayout" name="option_form"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="dependency_tab">
- <attribute name="title">
- <string>Dependencies</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_5">
- <item row="0" column="0">
- <widget class="QTreeView" name="dep_view"/>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="target_tab">
- <attribute name="title">
- <string>Build targets</string>
- </attribute>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <widget class="QTreeView" name="target_view"/>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item row="6" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QPushButton" name="save_button">
- <property name="text">
- <string>Save</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="compile_button">
- <property name="text">
- <string>Compile</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="test_button">
- <property name="text">
- <string>Run tests</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="install_button">
- <property name="text">
- <string>Install</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="clean_button">
- <property name="text">
- <string>Clean</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>740</width>
- <height>25</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuFile">
- <property name="title">
- <string>File</string>
- </property>
- <addaction name="actionSave"/>
- <addaction name="actionQuit"/>
- </widget>
- <addaction name="menuFile"/>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- <action name="actionSave">
- <property name="text">
- <string>&amp;Save</string>
- </property>
- </action>
- <action name="actionQuit">
- <property name="text">
- <string>&amp;Quit</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/mesonbuild/mesonrunner.ui b/mesonbuild/mesonrunner.ui
deleted file mode 100644
index 942c6bd..0000000
--- a/mesonbuild/mesonrunner.ui
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>rundialog</class>
- <widget class="QDialog" name="rundialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>581</width>
- <height>368</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>External process output</string>
- </property>
- <property name="modal">
- <bool>true</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="1" column="0">
- <widget class="QLabel" name="timelabel">
- <property name="text">
- <string>Compile time: 0:0</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="termbutton">
- <property name="text">
- <string>Terminate</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0" colspan="2">
- <widget class="QTextEdit" name="console">
- <property name="readOnly">
- <bool>true</bool>
- </property>
- <property name="html">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/mesonbuild/mesonstart.ui b/mesonbuild/mesonstart.ui
deleted file mode 100644
index c6c5f96..0000000
--- a/mesonbuild/mesonstart.ui
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>644</width>
- <height>192</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Meson</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Source directory</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="source_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QPushButton" name="source_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Build directory</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="build_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="build_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Cross file</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="cross_entry">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="cross_browse_button">
- <property name="text">
- <string>Browse</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QPushButton" name="generate_button">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Generate</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>644</width>
- <height>25</height>
- </rect>
- </property>
- </widget>
- <widget class="QStatusBar" name="statusbar"/>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/mesonbuild/mgui.py b/mesonbuild/mgui.py
deleted file mode 100644
index ffd1800..0000000
--- a/mesonbuild/mgui.py
+++ /dev/null
@@ -1,543 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2013-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.
-
-import sys, os, pickle, time, shutil
-from . 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.get_builtin_option('buildtype'))
- combo.currentTextChanged.connect(self.build_type_changed)
- self.form.addRow('Build type', combo)
- strip = QCheckBox("")
- strip.setChecked(self.coredata.get_builtin_option('strip'))
- strip.stateChanged.connect(self.strip_changed)
- self.form.addRow('Strip on install', strip)
- unity = QCheckBox("")
- unity.setChecked(self.coredata.get_builtin_option('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 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
-
-
-def run(args): # SPECIAL, Qt wants all args, including command name.
- app = QApplication(sys.argv)
- if len(args) == 1:
- arg = ""
- elif len(args) == 2:
- arg = sys.argv[1]
- else:
- print(sys.argv[0], "<build or source dir>")
- return 1
- if os.path.exists(os.path.join(arg, 'meson-private/coredata.dat')):
- guirespawner = MesonGuiRespawner(arg)
- else:
- runner = Starter(arg)
- return app.exec_()
-
-if __name__ == '__main__':
- sys.exit(run(sys.argv))
diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py
index 085dd69..0af7c24 100644
--- a/mesonbuild/scripts/meson_install.py
+++ b/mesonbuild/scripts/meson_install.py
@@ -42,20 +42,43 @@ def do_install(datafilename):
install_data(d)
run_install_script(d)
-def install_subdirs(d):
- for (src_dir, dst_dir) in d.install_subdirs:
+def install_subdirs(data):
+ for (src_dir, inst_dir, dst_dir) in data.install_subdirs:
+ if src_dir.endswith('/'):
+ src_dir = src_dir[:-1]
+ src_prefix = os.path.join(src_dir, inst_dir)
+ print('Installing subdir %s to %s.' % (src_prefix, dst_dir))
if os.path.isabs(dst_dir):
- dst_dir = destdir_join(d.destdir, dst_dir)
+ dst_dir = destdir_join(data.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))
+ dst_dir = data.fullprefix + dst_dir
+ if not os.path.exists(dst_dir):
+ os.makedirs(dst_dir)
+ for root, dirs, files in os.walk(src_prefix):
+ for d in dirs:
+ abs_src = os.path.join(src_dir, root, d)
+ filepart = abs_src[len(src_dir)+1:]
+ abs_dst = os.path.join(dst_dir, filepart)
+ if os.path.isdir(abs_dst):
+ continue
+ if os.path.exists(abs_dst):
+ print('Tried to copy directory %s but a file of that name already exists.' % abs_dst)
+ sys.exit(1)
+ os.makedirs(abs_dst)
+ shutil.copystat(abs_src, abs_dst)
+ for f in files:
+ abs_src = os.path.join(src_dir, root, f)
+ filepart = abs_src[len(src_dir)+1:]
+ abs_dst = os.path.join(dst_dir, filepart)
+ if os.path.isdir(abs_dst):
+ print('Tried to copy file %s but a directory of that name already exists.' % abs_dst)
+ if os.path.exists(abs_dst):
+ os.unlink(abs_dst)
+ parent_dir = os.path.split(abs_dst)[0]
+ if not os.path.isdir(parent_dir):
+ os.mkdir(parent_dir)
+ shutil.copystat(os.path.split(abs_src)[0], parent_dir)
+ shutil.copy2(abs_src, abs_dst, follow_symlinks=False)
def install_data(d):
for i in d.data:
diff --git a/mesongui.py b/mesongui.py
deleted file mode 100755
index 9e16b00..0000000
--- a/mesongui.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 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.
-
-from mesonbuild import mgui
-import sys
-
-sys.exit(mgui.run(sys.argv))
diff --git a/run_tests.py b/run_tests.py
index 1317380..1c6ae11 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -31,7 +31,7 @@ import time
import multiprocessing
import concurrent.futures as conc
-from mesonbuild.mesonmain import backendlist
+from mesonbuild.coredata import backendlist
class TestResult:
def __init__(self, msg, stdo, stde, conftime=0, buildtime=0, testtime=0):
@@ -100,6 +100,11 @@ def setup_commands(backend):
compile_commands = ['msbuild']
test_commands = ['msbuild', 'RUN_TESTS.vcxproj']
install_commands = []
+ elif backend == 'vs2015':
+ backend_flags = ['--backend=vs2015']
+ compile_commands = ['msbuild']
+ test_commands = ['msbuild', 'RUN_TESTS.vcxproj']
+ install_commands = []
elif backend == 'xcode' or (backend is None and mesonlib.is_osx()):
backend_flags = ['--backend=xcode']
compile_commands = ['xcodebuild']
@@ -426,5 +431,8 @@ if __name__ == '__main__':
print('\nTotal passed tests:', passing_tests)
print('Total failed tests:', failing_tests)
print('Total skipped tests:', skipped_tests)
+ if failing_tests > 0 and 'TRAVIS' in os.environ:
+ # Cat because it can have stuff of unknown encodings mixed.
+ subprocess.call(['cat', 'meson-test-run.txt'])
sys.exit(failing_tests)
diff --git a/setup.py b/setup.py
index 1c96435..d5b79ae 100644
--- a/setup.py
+++ b/setup.py
@@ -42,15 +42,12 @@ setup(name='meson',
'mesonbuild.scripts',
'mesonbuild.backend',
'mesonbuild.wrap'],
- package_data={'mesonbuild': ['*.ui']},
scripts=['meson.py',
'mesonconf.py',
- 'mesongui.py',
'mesonintrospect.py',
'wraptool.py'],
data_files=[('share/man/man1', ['man/meson.1',
'man/mesonconf.1',
- 'man/mesongui.1',
'man/mesonintrospect.1',
'man/wraptool.1'])],
classifiers=['Development Status :: 5 - Production/Stable',
diff --git a/test cases/common/10 man install/installed_files.txt b/test cases/common/10 man install/installed_files.txt
index 29331e4..7b19616 100644
--- a/test cases/common/10 man install/installed_files.txt
+++ b/test cases/common/10 man install/installed_files.txt
@@ -1,3 +1,4 @@
usr/share/man/man1/foo.1.gz
usr/share/man/man2/bar.2.gz
usr/share/man/man1/vanishing.1.gz
+usr/share/man/man2/vanishing.2.gz
diff --git a/test cases/common/10 man install/meson.build b/test cases/common/10 man install/meson.build
index 1c93036..8436fa5 100644
--- a/test cases/common/10 man install/meson.build
+++ b/test cases/common/10 man install/meson.build
@@ -1,4 +1,5 @@
project('man install', 'c')
m1 = install_man('foo.1')
m2 = install_man('bar.2')
+install_man('vanishing/vanishing.2')
subdir('vanishing')
diff --git a/test cases/common/10 man install/vanishing/vanishing.2 b/test cases/common/10 man install/vanishing/vanishing.2
new file mode 100644
index 0000000..d12f76a
--- /dev/null
+++ b/test cases/common/10 man install/vanishing/vanishing.2
@@ -0,0 +1 @@
+This is a second man page of the vanishing subdirectory.
diff --git a/test cases/common/16 configure file/dumpprog.c b/test cases/common/16 configure file/dumpprog.c
new file mode 100644
index 0000000..e0c9868
--- /dev/null
+++ b/test cases/common/16 configure file/dumpprog.c
@@ -0,0 +1,33 @@
+#define SHOULD_BE_UNDEFINED 1
+
+#include"config3.h"
+#include<string.h>
+#include<stdio.h>
+
+#ifdef SHOULD_BE_UNDEFINED
+#error Token did not get undefined.
+#endif
+
+#ifndef SHOULD_BE_DEFINED
+#error Token did not get defined
+#endif
+
+int main(int argc, char **argv) {
+ if(strcmp(SHOULD_BE_STRING, "string") != 0) {
+ printf("String token defined wrong.\n");
+ return 1;
+ }
+ if(SHOULD_BE_ONE != 1) {
+ printf("One defined incorrectly.\n");
+ return 1;
+ }
+ if(SHOULD_BE_ZERO != 0) {
+ printf("Zero defined incorrectly.\n");
+ return 1;
+ }
+ if(strcmp(SHOULD_BE_QUOTED_ONE, "1") != 0) {
+ printf("Quoted number defined incorrectly.\n");
+ return 1;
+ }
+ SHOULD_BE_RETURN 0;
+}
diff --git a/test cases/common/16 configure file/meson.build b/test cases/common/16 configure file/meson.build
index 8dec8fe..e1bdff3 100644
--- a/test cases/common/16 configure file/meson.build
+++ b/test cases/common/16 configure file/meson.build
@@ -30,3 +30,18 @@ command : [genprog, scriptfile, ifile, ofile],
install_dir : 'share/appdir')
test('inctest2', executable('prog2', 'prog2.c'))
+
+# Generate a conf file without an input file.
+
+dump = configuration_data()
+dump.set('SHOULD_BE_STRING', '"string"')
+dump.set('SHOULD_BE_RETURN', 'return')
+dump.set('SHOULD_BE_DEFINED', true)
+dump.set('SHOULD_BE_UNDEFINED', false)
+dump.set('SHOULD_BE_ONE', 1)
+dump.set('SHOULD_BE_ZERO', 0)
+dump.set('SHOULD_BE_QUOTED_ONE', '"1"')
+configure_file(output : 'config3.h',
+ configuration : dump)
+
+test('Configless.', executable('dumpprog', 'dumpprog.c'))
diff --git a/test cases/common/49 subproject/meson.build b/test cases/common/49 subproject/meson.build
index 1e05ddf..c6ec116 100644
--- a/test cases/common/49 subproject/meson.build
+++ b/test cases/common/49 subproject/meson.build
@@ -2,6 +2,8 @@ project('subproj user', 'c',
version : '2.3.4',
license : 'mylicense')
+assert(meson.project_name() == 'subproj user', 'Incorrect project name')
+
sub = subproject('sublib', version : '1.0.0')
if meson.project_version() != '2.3.4'
diff --git a/test cases/common/49 subproject/subprojects/sublib/meson.build b/test cases/common/49 subproject/subprojects/sublib/meson.build
index 3da031b..269f815 100644
--- a/test cases/common/49 subproject/subprojects/sublib/meson.build
+++ b/test cases/common/49 subproject/subprojects/sublib/meson.build
@@ -6,6 +6,8 @@ if not meson.is_subproject()
error('Claimed to be master project even though we are a subproject.')
endif
+assert(meson.project_name() == 'subproject', 'Incorrect subproject name')
+
if meson.project_version() != '1.0.0'
error('Incorrect version string in subproject.')
endif
diff --git a/test cases/common/66 install subdir/installed_files.txt b/test cases/common/66 install subdir/installed_files.txt
index 93ee283..a610c51 100644
--- a/test cases/common/66 install subdir/installed_files.txt
+++ b/test cases/common/66 install subdir/installed_files.txt
@@ -1,2 +1,4 @@
usr/share/sub1/data1.dat
+usr/share/sub1/second.dat
+usr/share/sub1/third.dat
usr/share/sub1/sub2/data2.dat
diff --git a/test cases/common/66 install subdir/meson.build b/test cases/common/66 install subdir/meson.build
index 16062b0..669cf09 100644
--- a/test cases/common/66 install subdir/meson.build
+++ b/test cases/common/66 install subdir/meson.build
@@ -1,3 +1,5 @@
project('install a whole subdir', 'c')
subdir('subdir')
+install_subdir('sub1', install_dir : 'share')
+install_subdir('sub/sub1', install_dir : 'share')
diff --git a/test cases/common/66 install subdir/sub/sub1/third.dat b/test cases/common/66 install subdir/sub/sub1/third.dat
new file mode 100644
index 0000000..5ccbc43
--- /dev/null
+++ b/test cases/common/66 install subdir/sub/sub1/third.dat
@@ -0,0 +1 @@
+This is a third data file for sub1 dir.
diff --git a/test cases/common/66 install subdir/sub1/second.dat b/test cases/common/66 install subdir/sub1/second.dat
new file mode 100644
index 0000000..48857a8
--- /dev/null
+++ b/test cases/common/66 install subdir/sub1/second.dat
@@ -0,0 +1 @@
+Test that multiple install_subdirs meld their results. \ No newline at end of file