diff options
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>&Save</string> - </property> - </action> - <action name="actionQuit"> - <property name="text"> - <string>&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><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></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) @@ -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 |