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/compilers.py15
-rw-r--r--mesonbuild/coredata.py3
-rw-r--r--mesonbuild/environment.py8
-rw-r--r--mesonbuild/interpreter.py28
-rw-r--r--mesonbuild/mesonlib.py21
-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/modules/qt5.py7
-rw-r--r--mesonbuild/scripts/meson_install.py47
-rwxr-xr-xmesongui.py20
-rwxr-xr-xrun_tests.py3
-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
28 files changed, 187 insertions, 1053 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/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 287d29a..5f00ac3 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -70,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)
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 8d260f0..ba943e3 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'):
@@ -1883,13 +1887,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.')
@@ -1899,16 +1901,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 fe831bd..584b3b2 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.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/modules/qt5.py b/mesonbuild/modules/qt5.py
index e12d5ea..4f19b78 100644
--- a/mesonbuild/modules/qt5.py
+++ b/mesonbuild/modules/qt5.py
@@ -123,17 +123,16 @@ class Qt5Module():
srctmp = [srctmp]
sources = args[1:] + srctmp
if len(rcc_files) > 0:
- rcc_kwargs = {'output' : '@BASENAME@.cpp',
- 'arguments' : ['@INPUT@', '-o', '@OUTPUT@']}
qrc_deps = []
for i in rcc_files:
qrc_deps += self.parse_qrc(state, i)
+ basename = os.path.split(rcc_files[0])[1]
rcc_kwargs = {'input' : rcc_files,
- 'output' : rcc_files[0] + '.cpp',
+ 'output' : basename + '.cpp',
'command' : [self.rcc, '-o', '@OUTPUT@', '@INPUT@'],
'depend_files' : qrc_deps,
}
- res_target = build.CustomTarget(rcc_files[0].replace('.', '_'),
+ res_target = build.CustomTarget(basename.replace('.', '_'),
state.subdir,
rcc_kwargs)
sources.append(res_target)
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 abff831..1c6ae11 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -431,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