aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends.py1
-rw-r--r--compilers.py230
-rw-r--r--coredata.py1
-rw-r--r--interpreter.py20
-rwxr-xr-xmesonconf.py40
-rwxr-xr-xmesongui.py10
-rwxr-xr-xmesonintrospect.py17
-rw-r--r--mesonlib.py76
-rw-r--r--ninjabackend.py1
-rw-r--r--optinterpreter.py103
-rw-r--r--test cases/frameworks/1 boost/meson.build6
-rw-r--r--test cases/frameworks/4 qt5/meson.build4
-rw-r--r--test cases/frameworks/9 wxwidgets/meson.build2
13 files changed, 329 insertions, 182 deletions
diff --git a/backends.py b/backends.py
index f13b3c7..4acf71c 100644
--- a/backends.py
+++ b/backends.py
@@ -210,6 +210,7 @@ class Backend():
commands += compiler.get_always_args()
if self.environment.coredata.buildtype != 'plain':
commands += compiler.get_warn_args(self.environment.coredata.warning_level)
+ commands += compiler.get_option_compile_args(self.environment.coredata.compiler_options)
commands += self.build.get_global_args(compiler)
commands += self.environment.coredata.external_args[compiler.get_language()]
commands += target.get_extra_args(compiler.get_language())
diff --git a/compilers.py b/compilers.py
index f817161..bb32069 100644
--- a/compilers.py
+++ b/compilers.py
@@ -91,6 +91,13 @@ mono_buildtype_args = {'plain' : [],
'debugoptimized': ['-debug', '-optimize+'],
'release' : ['-optimize+']}
+gnu_winlibs = ['-lkernel32', '-luser32', '-lgdi32', '-lwinspool', '-lshell32',
+ '-lole32', '-loleaut32', '-luuid', '-lcomdlg32', '-ladvapi32']
+
+msvc_winlibs = ['kernel32.lib', 'user32.lib', 'gdi32.lib',
+ 'winspool.lib', 'shell32.lib', 'ole32.lib', 'oleaut32.lib',
+ 'uuid.lib', 'comdlg32.lib', 'advapi32.lib']
+
def build_unix_rpath_args(build_dir, rpath_paths, install_rpath):
if len(rpath_paths) == 0 and len(install_rpath) == 0:
return []
@@ -118,8 +125,8 @@ class RunResult():
self.stdout = stdout
self.stderr = stderr
-class CCompiler():
- def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+class Compiler():
+ def __init__(self, exelist, version):
if type(exelist) == type(''):
self.exelist = [exelist]
elif type(exelist) == type([]):
@@ -127,6 +134,25 @@ class CCompiler():
else:
raise TypeError('Unknown argument to CCompiler')
self.version = version
+
+ def get_always_args(self):
+ return []
+
+ def get_linker_always_args(self):
+ return []
+
+ def get_options(self):
+ return {} # build afresh every time
+
+ def get_option_compile_args(self, options):
+ return []
+
+ def get_option_link_args(self, options):
+ return []
+
+class CCompiler(Compiler):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+ super().__init__(exelist, version)
self.language = 'c'
self.default_suffix = 'c'
self.id = 'unknown'
@@ -142,9 +168,6 @@ class CCompiler():
def get_always_args(self):
return []
- def get_linker_always_args(self):
- return []
-
def get_warn_args(self, level):
return self.warn_args[level]
@@ -539,29 +562,17 @@ class ObjCPPCompiler(CPPCompiler):
if pe.returncode != 0:
raise EnvironmentException('Executables created by ObjC++ compiler %s are not runnable.' % self.name_string())
-class MonoCompiler():
+class MonoCompiler(Compiler):
def __init__(self, exelist, version):
- if type(exelist) == type(''):
- self.exelist = [exelist]
- elif type(exelist) == type([]):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Mono compiler')
- self.version = version
+ super().__init__(exelist, version)
self.language = 'cs'
self.default_suffix = 'cs'
self.id = 'mono'
self.monorunner = 'mono'
- def get_always_args(self):
- return []
-
def get_output_args(self, fname):
return ['-out:' + fname]
- def get_linker_always_args(self):
- return []
-
def get_link_args(self, fname):
return ['-r:' + fname]
@@ -679,26 +690,14 @@ class MonoCompiler():
def get_buildtype_args(self, buildtype):
return mono_buildtype_args[buildtype]
-class JavaCompiler():
+class JavaCompiler(Compiler):
def __init__(self, exelist, version):
- if type(exelist) == type(''):
- self.exelist = [exelist]
- elif type(exelist) == type([]):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to JavaCompiler')
- self.version = version
+ super().__init__(exelist, version)
self.language = 'java'
self.default_suffix = 'java'
self.id = 'unknown'
self.javarunner = 'java'
- def get_always_args(self):
- return []
-
- def get_linker_always_args(self):
- return []
-
def get_soname_args(self, shlib_name, path, soversion):
return []
@@ -819,14 +818,9 @@ class JavaCompiler():
def has_function(self, funcname, prefix, env):
raise EnvironmentException('Java does not support function checks.')
-class ValaCompiler():
+class ValaCompiler(Compiler):
def __init__(self, exelist, version):
- if isinstance(exelist, str):
- self.exelist = [exelist]
- elif type(exelist) == type([]):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Vala compiler')
+ super().__init__(exelist, version)
self.version = version
self.id = 'unknown'
self.language = 'vala'
@@ -863,15 +857,9 @@ class ValaCompiler():
suffix = filename.split('.')[-1]
return suffix in ('vala', 'vapi')
-class RustCompiler():
+class RustCompiler(Compiler):
def __init__(self, exelist, version):
- if isinstance(exelist, str):
- self.exelist = [exelist]
- elif type(exelist) == type([]):
- self.exelist = exelist
- else:
- raise TypeError('Unknown argument to Rust compiler')
- self.version = version
+ super().__init__(exelist, version)
self.id = 'unknown'
self.language = 'rust'
@@ -920,6 +908,7 @@ class VisualStudioCCompiler(CCompiler):
vs2010_always_args = ['/nologo', '/showIncludes']
vs2013_always_args = ['/nologo', '/showIncludes', '/FS']
+
def __init__(self, exelist, version, is_cross, exe_wrap):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
self.id = 'msvc'
@@ -1012,6 +1001,15 @@ class VisualStudioCCompiler(CCompiler):
def thread_link_flags(self):
return []
+ def get_options(self):
+ return {'c_winlibs' : mesonlib.UserStringArrayOption('c_winlibs',
+ 'Windows libs to link against.',
+ msvc_winlibs)
+ }
+
+ def get_option_link_args(self, options):
+ return options['c_winlibs'].value
+
class VisualStudioCPPCompiler(VisualStudioCCompiler):
def __init__(self, exelist, version, is_cross, exe_wrap):
VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap)
@@ -1042,6 +1040,26 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler):
if pe.returncode != 0:
raise EnvironmentException('Executables created by C++ compiler %s are not runnable.' % self.name_string())
+ def get_options(self):
+ return {'cpp_eh' : mesonlib.UserComboOption('cpp_eh',
+ 'C++ exception handling type.',
+ ['none', 'a', 's', 'sc'],
+ 'sc'),
+ 'cpp_winlibs' : mesonlib.UserStringArrayOption('cpp_winlibs',
+ 'Windows libs to link against.',
+ msvc_winlibs)
+ }
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['cpp_eh']
+ if std.value != 'none':
+ args.append('/EH' + std.value)
+ return args
+
+ def get_option_link_args(self, options):
+ return options['cpp_winlibs'].value
+
GCC_STANDARD = 0
GCC_OSX = 1
GCC_MINGW = 2
@@ -1059,6 +1077,7 @@ def get_gcc_soname_args(gcc_type, shlib_name, path, soversion):
else:
raise RuntimeError('Not implemented yet.')
+
class GnuCCompiler(CCompiler):
def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None):
CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
@@ -1094,6 +1113,29 @@ class GnuCCompiler(CCompiler):
def can_compile(self, filename):
return super().can_compile(filename) or filename.split('.')[-1].lower() == 's' # Gcc can do asm, too.
+ def get_options(self):
+ opts = {'c_std' : mesonlib.UserComboOption('c_std', 'C language standard to use',
+ ['none', 'c89', 'c99', 'c11', 'gnu89', 'gnu99', 'gnu11'],
+ 'c11')}
+ if self.gcc_type == GCC_MINGW:
+ opts.update({
+ 'c_winlibs': mesonlib.UserStringArrayOption('c_winlibs', 'Standard Win libraries to link against',
+ gnu_winlibs),
+ })
+ return opts
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['c_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
+ def get_option_link_args(self, options):
+ if self.gcc_type == GCC_MINGW:
+ return options['c_winlibs'].value
+ return []
+
class GnuObjCCompiler(ObjCCompiler):
std_opt_args = ['-O2']
@@ -1182,6 +1224,22 @@ class ClangCCompiler(CCompiler):
# so it might change semantics at any time.
return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))]
+ def get_options(self):
+ return {'c_std' : mesonlib.UserComboOption('c_std', 'C language standard to use',
+ ['none', 'c89', 'c99', 'c11'],
+ 'c11')}
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['c_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
+ def get_option_link_args(self, options):
+ if self.gcc_type == GCC_MINGW:
+ return options['c_winlibs'].value
+ return []
class GnuCPPCompiler(CPPCompiler):
# may need to separate the latter to extra_debug_args or something
@@ -1210,6 +1268,29 @@ class GnuCPPCompiler(CPPCompiler):
def get_soname_args(self, shlib_name, path, soversion):
return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion)
+ def get_options(self):
+ opts = {'cpp_std' : mesonlib.UserComboOption('cpp_std', 'C language standard to use',
+ ['none', 'c++03', 'c++11', 'c++1y'],
+ 'c++11')}
+ if self.gcc_type == GCC_MINGW:
+ opts.update({
+ 'cpp_winlibs': mesonlib.UserStringArrayOption('c_winlibs', 'Standard Win libraries to link against',
+ gnu_winlibs),
+ })
+ return opts
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['cpp_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
+ def get_option_link_args(self, options):
+ if self.gcc_type == GCC_MINGW:
+ return options['cpp_winlibs'].value
+ return []
+
class ClangCPPCompiler(CPPCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper)
@@ -1233,11 +1314,24 @@ class ClangCPPCompiler(CPPCompiler):
# so it might change semantics at any time.
return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))]
-class FortranCompiler():
- def __init__(self, exelist, version,is_cross, exe_wrapper=None):
- super().__init__()
- self.exelist = exelist
- self.version = version
+ def get_options(self):
+ return {'cpp_std' : mesonlib.UserComboOption('cpp_std', 'C++ language standard to use',
+ ['none', 'c++03', 'c++11', 'c++1y'],
+ 'c++11')}
+
+ def get_option_compile_args(self, options):
+ args = []
+ std = options['cpp_std']
+ if std.value != 'none':
+ args.append('-std=' + std.value)
+ return args
+
+ def get_option_link_args(self, options):
+ return []
+
+class FortranCompiler(Compiler):
+ def __init__(self, exelist, version, is_cross, exe_wrapper=None):
+ super().__init__(exelist, version)
self.is_cross = is_cross
self.exe_wrapper = exe_wrapper
self.language = 'fortran'
@@ -1293,12 +1387,6 @@ end program prog
if pe.returncode != 0:
raise EnvironmentException('Executables created by Fortran compiler %s are not runnable.' % self.name_string())
- def get_always_args(self):
- return ['-pipe']
-
- def get_linker_always_args(self):
- return []
-
def get_std_warn_args(self, level):
return FortranCompiler.std_warn_args
@@ -1368,6 +1456,9 @@ class GnuFortranCompiler(FortranCompiler):
self.gcc_type = gcc_type
self.id = 'gcc'
+ def get_always_args(self):
+ return ['-pipe']
+
class G95FortranCompiler(FortranCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
super().__init__(exelist, version, is_cross, exe_wrapper=None)
@@ -1376,6 +1467,9 @@ class G95FortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-fmod='+path]
+ def get_always_args(self):
+ return ['-pipe']
+
class SunFortranCompiler(FortranCompiler):
def __init__(self, exelist, version, is_cross, exe_wrapper=None):
super().__init__(exelist, version, is_cross, exe_wrapper=None)
@@ -1403,9 +1497,6 @@ class IntelFortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-module', path]
- def get_always_args(self):
- return []
-
def can_compile(self, src):
suffix = os.path.splitext(src)[1].lower()
if suffix == '.f' or suffix == '.f90':
@@ -1425,9 +1516,6 @@ class PathScaleFortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-module', path]
- def get_always_args(self):
- return []
-
def can_compile(self, src):
suffix = os.path.splitext(src)[1].lower()
if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
@@ -1447,9 +1535,6 @@ class PGIFortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-module', path]
- def get_always_args(self):
- return []
-
def can_compile(self, src):
suffix = os.path.splitext(src)[1].lower()
if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
@@ -1470,9 +1555,6 @@ class Open64FortranCompiler(FortranCompiler):
def get_module_outdir_args(self, path):
return ['-module', path]
- def get_always_args(self):
- return []
-
def can_compile(self, src):
suffix = os.path.splitext(src)[1].lower()
if suffix == '.f' or suffix == '.f90' or suffix == '.f95':
@@ -1537,6 +1619,9 @@ class VisualStudioLinker():
def thread_link_flags(self):
return []
+ def get_option_link_args(self, options):
+ return []
+
class ArLinker():
std_args = ['csr']
@@ -1570,3 +1655,6 @@ class ArLinker():
def thread_link_flags(self):
return []
+
+ def get_option_link_args(self, options):
+ return []
diff --git a/coredata.py b/coredata.py
index 793cd47..4c244c0 100644
--- a/coredata.py
+++ b/coredata.py
@@ -61,6 +61,7 @@ class CoreData():
self.werror = options.werror
self.layout = options.layout
self.user_options = {}
+ self.compiler_options = {}
self.external_args = {} # These are set from "the outside" with e.g. mesonconf
self.external_link_args = {}
if options.cross_file is not None:
diff --git a/interpreter.py b/interpreter.py
index 914caa1..7e67711 100644
--- a/interpreter.py
+++ b/interpreter.py
@@ -1239,15 +1239,20 @@ class Interpreter():
if len(args) != 1:
raise InterpreterException('Argument required for get_option.')
optname = args[0]
- if optname not in coredata.builtin_options and self.is_subproject():
- optname = self.subproject + ':' + optname
try:
return self.environment.get_coredata().get_builtin_option(optname)
except RuntimeError:
pass
- if optname not in self.environment.coredata.user_options:
+ try:
+ return self.environment.coredata.compiler_options[optname].value
+ except KeyError:
+ pass
+ if optname not in coredata.builtin_options and self.is_subproject():
+ optname = self.subproject + ':' + optname
+ try:
+ return self.environment.coredata.user_options[optname].value
+ except KeyError:
raise InterpreterException('Tried to access unknown option "%s".' % optname)
- return self.environment.coredata.user_options[optname].value
@noKwargs
def func_configuration_data(self, node, args, kwargs):
@@ -1365,6 +1370,13 @@ class Interpreter():
if cross_comp is not None:
cross_comp.sanity_check(self.environment.get_scratch_dir())
self.coredata.cross_compilers[lang] = cross_comp
+ new_options = comp.get_options()
+ optprefix = lang + '_'
+ for i in new_options:
+ if not i.startswith(optprefix):
+ raise InterpreterException('Internal error, %s has incorrect prefix.' % i)
+ new_options.update(self.coredata.compiler_options)
+ self.coredata.compiler_options = new_options
mlog.log('Native %s compiler: ' % lang, mlog.bold(' '.join(comp.get_exelist())), ' (%s %s)' % (comp.id, comp.version), sep='')
if not comp.get_language() in self.coredata.external_args:
(ext_compile_args, ext_link_args) = environment.get_args_from_envvars(comp.get_language())
diff --git a/mesonconf.py b/mesonconf.py
index db526b0..963585a 100755
--- a/mesonconf.py
+++ b/mesonconf.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Copyright 2014 The Meson development team
+# Copyright 2014-2015 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
import sys, os
import pickle
import argparse
-import coredata, optinterpreter
+import coredata, mesonlib
from meson import build_types, layouts, warning_levels
parser = argparse.ArgumentParser()
@@ -64,13 +64,6 @@ class Conf:
f = '%s%s %s%s' % (name, namepad, descr, descrpad)
print(f, value)
- def tobool(self, thing):
- if thing.lower() == 'true':
- return True
- if thing.lower() == 'false':
- return False
- raise ConfException('Value %s is not boolean (true or false).' % thing)
-
def set_options(self, options):
for o in options:
if '=' not in o:
@@ -127,18 +120,10 @@ class Conf:
self.coredata.localedir = v
elif k in self.coredata.user_options:
tgt = self.coredata.user_options[k]
- if isinstance(tgt, optinterpreter.UserBooleanOption):
- tgt.set_value(self.tobool(v))
- elif isinstance(tgt, optinterpreter.UserComboOption):
- try:
- tgt.set_value(v)
- except optinterpreter.OptionException:
- raise ConfException('Value of %s must be one of %s.' %
- (k, tgt.choices))
- elif isinstance(tgt, optinterpreter.UserStringOption):
- tgt.set_value(v)
- else:
- raise ConfException('Internal error, unknown option type.')
+ tgt.set_value(v)
+ elif k in self.coredata.compiler_options:
+ tgt = self.coredata.compiler_options[k]
+ tgt.set_value(v)
elif k.endswith('linkargs'):
lang = k[:-8]
if not lang in self.coredata.external_link_args:
@@ -181,6 +166,17 @@ class Conf:
for (lang, args) in self.coredata.external_link_args.items():
print(lang + 'linkargs', str(args))
print('')
+ okeys = sorted(self.coredata.compiler_options.keys())
+ if len(okeys) == 0:
+ print('No compiler options\n')
+ else:
+ print('Compiler options\n')
+ coarr = []
+ for k in okeys:
+ o = self.coredata.compiler_options[k]
+ coarr.append([k, o.description, o.value])
+ self.print_aligned(coarr)
+ print('')
print('Directories\n')
parr = []
parr.append(['prefix', 'Install prefix', self.coredata.prefix])
@@ -193,7 +189,7 @@ class Conf:
self.print_aligned(parr)
print('')
if len(self.coredata.user_options) == 0:
- print('This project does not have any options')
+ print('This project does not have user options')
else:
print('Project options\n')
options = self.coredata.user_options
diff --git a/mesongui.py b/mesongui.py
index 10a84f7..bdd44bb 100755
--- a/mesongui.py
+++ b/mesongui.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Copyright 2013 The Meson development team
+# Copyright 2013-2015 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
# limitations under the License.
import sys, os, pickle, time, shutil
-import build, coredata, environment, optinterpreter
+import build, coredata, environment, mesonlib
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow, QHeaderView
from PyQt5.QtWidgets import QComboBox, QCheckBox
@@ -272,14 +272,14 @@ class OptionForm:
self.opt_widgets = []
for key in keys:
opt = options[key]
- if isinstance(opt, optinterpreter.UserStringOption):
+ if isinstance(opt, mesonlib.UserStringOption):
w = PyQt5.QtWidgets.QLineEdit(opt.value)
w.textChanged.connect(self.user_option_changed)
- elif isinstance(opt, optinterpreter.UserBooleanOption):
+ elif isinstance(opt, mesonlib.UserBooleanOption):
w = QCheckBox('')
w.setChecked(opt.value)
w.stateChanged.connect(self.user_option_changed)
- elif isinstance(opt, optinterpreter.UserComboOption):
+ elif isinstance(opt, mesonlib.UserComboOption):
w = QComboBox()
for i in opt.choices:
w.addItem(i)
diff --git a/mesonintrospect.py b/mesonintrospect.py
index ffdd320..3ef2ab5 100755
--- a/mesonintrospect.py
+++ b/mesonintrospect.py
@@ -22,7 +22,7 @@ Currently only works for the Ninja backend. Others use generated
project files and don't need this info."""
import json, pickle
-import coredata, build, optinterpreter
+import coredata, build, mesonlib
import argparse
import sys, os
@@ -107,7 +107,11 @@ def list_buildoptions(coredata, builddata):
'description' : 'Unity build',
'name' : 'unity'}
optlist = [buildtype, strip, coverage, pch, unity]
- options = coredata.user_options
+ add_keys(optlist, coredata.user_options)
+ add_keys(optlist, coredata.compiler_options)
+ print(json.dumps(optlist))
+
+def add_keys(optlist, options):
keys = list(options.keys())
keys.sort()
for key in keys:
@@ -115,19 +119,20 @@ def list_buildoptions(coredata, builddata):
optdict = {}
optdict['name'] = key
optdict['value'] = opt.value
- if isinstance(opt, optinterpreter.UserStringOption):
+ if isinstance(opt, mesonlib.UserStringOption):
typestr = 'string'
- elif isinstance(opt, optinterpreter.UserBooleanOption):
+ elif isinstance(opt, mesonlib.UserBooleanOption):
typestr = 'boolean'
- elif isinstance(opt, optinterpreter.UserComboOption):
+ elif isinstance(opt, mesonlib.UserComboOption):
optdict['choices'] = opt.choices
typestr = 'combo'
+ elif isinstance(opt, mesonlib.UserStringArrayOption):
+ typestr = 'stringarray'
else:
raise RuntimeError("Unknown option type")
optdict['type'] = typestr
optdict['description'] = opt.description
optlist.append(optdict)
- print(json.dumps(optlist))
def list_buildsystem_files(coredata, builddata):
src_dir = builddata.environment.get_source_dir()
diff --git a/mesonlib.py b/mesonlib.py
index d7c40f4..0c7c308 100644
--- a/mesonlib.py
+++ b/mesonlib.py
@@ -255,3 +255,79 @@ def replace_if_different(dst, dst_tmp):
pass
os.replace(dst_tmp, dst)
+class UserOption:
+ def __init__(self, name, description):
+ super().__init__()
+ self.name = name
+ self.description = description
+
+ def parse_string(self, valuestring):
+ return valuestring
+
+class UserStringOption(UserOption):
+ def __init__(self, name, description, value):
+ super().__init__(name, description)
+ self.set_value(value)
+
+ def set_value(self, newvalue):
+ if not isinstance(newvalue, str):
+ raise MesonException('Value "%s" for string option "%s" is not a string.' % (str(newvalue), self.name))
+ self.value = newvalue
+
+class UserBooleanOption(UserOption):
+ def __init__(self, name, description, value):
+ super().__init__(name, description)
+ self.set_value(value)
+
+ def tobool(self, thing):
+ if isinstance(thing, bool):
+ return thing
+ if thing.lower() == 'true':
+ return True
+ if thing.lower() == 'false':
+ return False
+ raise MesonException('Value %s is not boolean (true or false).' % thing)
+
+ def set_value(self, newvalue):
+ self.value = self.tobool(newvalue)
+
+ def parse_string(self, valuestring):
+ if valuestring == 'false':
+ return False
+ if valuestring == 'true':
+ return True
+ raise MesonException('Value "%s" for boolean option "%s" is not a boolean.' % (valuestring, self.name))
+
+class UserComboOption(UserOption):
+ def __init__(self, name, description, choices, value):
+ super().__init__(name, description)
+ self.choices = choices
+ if not isinstance(self.choices, list):
+ raise MesonException('Combo choices must be an array.')
+ for i in self.choices:
+ if not isinstance(i, str):
+ raise MesonException('Combo choice elements must be strings.')
+ self.set_value(value)
+
+ def set_value(self, newvalue):
+ if newvalue not in self.choices:
+ optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices])
+ raise MesonException('Value "%s" for combo option "%s" is not one of the choices. Possible choices are: %s.' % (newvalue, self.name, optionsstring))
+ self.value = newvalue
+
+class UserStringArrayOption(UserOption):
+ def __init__(self, name, description, value):
+ super().__init__(name, description)
+ self.set_value(value)
+
+ def set_value(self, newvalue):
+ if isinstance(newvalue, str):
+ if not newvalue.startswith('['):
+ raise MesonException('Valuestring does not define an array: ' + newvalue)
+ newvalue = eval(newvalue, {}, {}) # Yes, it is unsafe.
+ if not isinstance(newvalue, list):
+ raise MesonException('String array value is not an array.')
+ for i in newvalue:
+ if not isinstance(i, str):
+ raise MesonException('String array element not a string.')
+ self.value = newvalue
diff --git a/ninjabackend.py b/ninjabackend.py
index ce78f67..bd074bf 100644
--- a/ninjabackend.py
+++ b/ninjabackend.py
@@ -1454,6 +1454,7 @@ rule FORTRAN_DEP_HACK
commands = []
commands += linker.get_linker_always_args()
commands += linker.get_buildtype_linker_args(self.environment.coredata.buildtype)
+ commands += linker.get_option_link_args(self.environment.coredata.compiler_options)
if not(isinstance(target, build.StaticLibrary)):
commands += self.environment.coredata.external_link_args[linker.get_language()]
if isinstance(target, build.Executable):
diff --git a/optinterpreter.py b/optinterpreter.py
index 6906d31..d66aa1f 100644
--- a/optinterpreter.py
+++ b/optinterpreter.py
@@ -1,4 +1,4 @@
-# Copyright 2013-2014 The Meson development team
+# Copyright 2013-2015 The Meson development team
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,74 +13,53 @@
# limitations under the License.
import mparser
-import coredata
+import coredata, mesonlib
import os, re
forbidden_option_names = coredata.builtin_options
+forbidden_prefixes = {'c_': True,
+ 'cpp_': True,
+ 'rust_': True,
+ 'fortran_': True,
+ 'objc_': True,
+ 'objcpp_': True,
+ 'vala_': True,
+ 'csharp_': True
+ }
+
+def is_invalid_name(name):
+ if name in forbidden_option_names:
+ return True
+ if name in forbidden_prefixes:
+ return True
+ return False
class OptionException(coredata.MesonException):
pass
optname_regex = re.compile('[^a-zA-Z0-9_-]')
-class UserOption:
- def __init__(self, name, kwargs):
- super().__init__()
- self.description = kwargs.get('description', '')
- self.name = name
-
- def parse_string(self, valuestring):
- return valuestring
-
-class UserStringOption(UserOption):
- def __init__(self, name, kwargs):
- super().__init__(name, kwargs)
- self.set_value(kwargs.get('value', ''))
-
- def set_value(self, newvalue):
- if not isinstance(newvalue, str):
- raise OptionException('Value "%s" for string option "%s" is not a string.' % (str(newvalue), self.name))
- self.value = newvalue
-
-class UserBooleanOption(UserOption):
- def __init__(self, name, kwargs):
- super().__init__(name, kwargs)
- self.set_value(kwargs.get('value', 'true'))
-
- def set_value(self, newvalue):
- if not isinstance(newvalue, bool):
- raise OptionException('Value "%s" for boolean option "%s" is not a boolean.' % (str(newvalue), self.name))
- self.value = newvalue
-
- def parse_string(self, valuestring):
- if valuestring == 'false':
- return False
- if valuestring == 'true':
- return True
- raise OptionException('Value "%s" for boolean option "%s" is not a boolean.' % (valuestring, self.name))
-
-class UserComboOption(UserOption):
- def __init__(self, name, kwargs):
- super().__init__(name, kwargs)
- if 'choices' not in kwargs:
- raise OptionException('Combo option missing "choices" keyword.')
- self.choices = kwargs['choices']
- if not isinstance(self.choices, list):
- raise OptionException('Combo choices must be an array.')
- for i in self.choices:
- if not isinstance(i, str):
- raise OptionException('Combo choice elements must be strings.')
- self.value = kwargs.get('value', self.choices[0])
-
- def set_value(self, newvalue):
- if newvalue not in self.choices:
- optionsstring = ', '.join(['"%s"' % (item,) for item in self.choices])
- raise OptionException('Value "%s" for combo option "%s" is not one of the choices. Possible choices are: %s.' % (newvalue, self.name, optionsstring))
- self.value = newvalue
-
-option_types = {'string' : UserStringOption,
- 'boolean' : UserBooleanOption,
- 'combo' : UserComboOption,
+def StringParser(name, description, kwargs):
+ return mesonlib.UserStringOption(name, description,
+ kwargs.get('value', ''))
+
+def BooleanParser(name, description, kwargs):
+ return mesonlib.UserBooleanOption(name, description, kwargs.get('value', True))
+
+def ComboParser(name, description, kwargs):
+ if 'choices' not in kwargs:
+ raise OptionException('Combo option missing "choices" keyword.')
+ choices = kwargs['choices']
+ if not isinstance(choices, list):
+ raise OptionException('Combo choices must be an array.')
+ for i in choices:
+ if not isinstance(i, str):
+ raise OptionException('Combo choice elements must be strings.')
+ return mesonlib.UserComboOption(name, description, choices, kwargs.get('value', choices[0]))
+
+option_types = {'string' : StringParser,
+ 'boolean' : BooleanParser,
+ 'combo' : ComboParser,
}
class OptionInterpreter:
@@ -157,11 +136,11 @@ class OptionInterpreter:
raise OptionException('Positional argument must be a string.')
if optname_regex.search(opt_name) is not None:
raise OptionException('Option names can only contain letters, numbers or dashes.')
- if opt_name in forbidden_option_names:
+ if is_invalid_name(opt_name):
raise OptionException('Option name %s is reserved.' % opt_name)
if self.subproject != '':
opt_name = self.subproject + ':' + opt_name
- opt = option_types[opt_type](opt_name, kwargs)
+ opt = option_types[opt_type](opt_name, kwargs.get('description', ''), kwargs)
if opt.description == '':
opt.description = opt_name
if opt_name in self.cmd_line_options:
diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build
index 327d36f..454c161 100644
--- a/test cases/frameworks/1 boost/meson.build
+++ b/test cases/frameworks/1 boost/meson.build
@@ -1,11 +1,5 @@
project('boosttest', 'cpp')
-if meson.get_compiler('cpp').get_id() != 'msvc'
- add_global_arguments('-std=c++11', language : 'cpp')
-else
- add_global_arguments('/EHsc', language : 'cpp')
-endif
-
# We want to have multiple separate configurations of Boost
# within one project. The need to be independent of each other.
# Use one without a library dependency and one with it.
diff --git a/test cases/frameworks/4 qt5/meson.build b/test cases/frameworks/4 qt5/meson.build
index 67761e9..bce9dbd 100644
--- a/test cases/frameworks/4 qt5/meson.build
+++ b/test cases/frameworks/4 qt5/meson.build
@@ -3,10 +3,6 @@ project('qt5 build test', 'cpp')
qt5 = import('qt5')
qt5dep = dependency('qt5', modules : ['Core', 'Gui', 'Widgets'])
-if meson.get_compiler('cpp').get_id() != 'msvc'
- add_global_arguments('-std=c++11', language : 'cpp')
-endif
-
prep = qt5.preprocess(
moc_headers : ['mainWindow.h'], # These need to be fed through the moc tool before use.
ui_files : 'mainWindow.ui', # XML files that need to be compiled with the uic tol.
diff --git a/test cases/frameworks/9 wxwidgets/meson.build b/test cases/frameworks/9 wxwidgets/meson.build
index ecf0b39..4f4d251 100644
--- a/test cases/frameworks/9 wxwidgets/meson.build
+++ b/test cases/frameworks/9 wxwidgets/meson.build
@@ -1,7 +1,5 @@
project('wxwidgets test', 'cpp')
-add_global_arguments('-std=c++11', language : 'cpp')
-
wxd = dependency('wxwidgets', version : '>=3.0.0')
wp = executable('wxprog', 'wxprog.cpp',