From d76e89f78044698a31ee422601206eef131f010c Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 4 Oct 2015 02:57:07 +0300 Subject: Extracted common functionality to base class. --- compilers.py | 100 +++++++++++++++++------------------------------------------ 1 file changed, 29 insertions(+), 71 deletions(-) (limited to 'compilers.py') diff --git a/compilers.py b/compilers.py index f81716184..9c78932db 100644 --- a/compilers.py +++ b/compilers.py @@ -118,8 +118,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 +127,16 @@ 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 [] + +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 +152,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 +546,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 +674,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 +802,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 +841,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' @@ -1233,11 +1205,9 @@ 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 +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 +1263,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 +1332,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 +1343,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 +1373,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 +1392,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 +1411,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 +1431,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': -- cgit v1.2.3 From 50663144c37af5e0f411902eb3b799641daffa45 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 4 Oct 2015 03:41:38 +0300 Subject: Can set compiler options, added language versions for Gnu and Clang. --- backends.py | 1 + compilers.py | 74 +++++++++++++++++++++++++++ coredata.py | 1 + interpreter.py | 7 +++ ninjabackend.py | 1 + test cases/frameworks/1 boost/meson.build | 4 +- test cases/frameworks/4 qt5/meson.build | 4 -- test cases/frameworks/9 wxwidgets/meson.build | 2 - 8 files changed, 85 insertions(+), 9 deletions(-) (limited to 'compilers.py') diff --git a/backends.py b/backends.py index f13b3c75f..4acf71c81 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 9c78932db..7a4394e62 100644 --- a/compilers.py +++ b/compilers.py @@ -134,6 +134,15 @@ class Compiler(): 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) @@ -1066,6 +1075,21 @@ 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): + return {'c_std' : mesonlib.UserComboOption('c_std', 'C language standard to use', + ['none', 'c89', 'c99', 'c11', 'gnu89', 'gnu99', 'gnu11'], + '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): + return [] + class GnuObjCCompiler(ObjCCompiler): std_opt_args = ['-O2'] @@ -1154,6 +1178,20 @@ 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): + return [] class GnuCPPCompiler(CPPCompiler): # may need to separate the latter to extra_debug_args or something @@ -1182,6 +1220,21 @@ 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): + 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 ClangCPPCompiler(CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) @@ -1205,6 +1258,21 @@ class ClangCPPCompiler(CPPCompiler): # 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('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) @@ -1495,6 +1563,9 @@ class VisualStudioLinker(): def thread_link_flags(self): return [] + def get_option_link_args(self, options): + return [] + class ArLinker(): std_args = ['csr'] @@ -1528,3 +1599,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 793cd4702..4c244c063 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 edfe59b86..472a10c9d 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1330,6 +1330,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/ninjabackend.py b/ninjabackend.py index 2f611a121..e6cb6a547 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -1452,6 +1452,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/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index 327d36ff5..afdfe0f9b 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -1,8 +1,6 @@ project('boosttest', 'cpp') -if meson.get_compiler('cpp').get_id() != 'msvc' - add_global_arguments('-std=c++11', language : 'cpp') -else +if meson.get_compiler('cpp').get_id() == 'msvc' add_global_arguments('/EHsc', language : 'cpp') endif diff --git a/test cases/frameworks/4 qt5/meson.build b/test cases/frameworks/4 qt5/meson.build index 67761e93c..bce9dbd8a 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 ecf0b39c8..4f4d251da 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', -- cgit v1.2.3 From 9a4016d37accbba852117e66790ad2144ad27210 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 5 Oct 2015 21:35:15 +0300 Subject: Added option for VS exception type. --- compilers.py | 18 +++++++++++++++++- test cases/frameworks/1 boost/meson.build | 4 ---- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'compilers.py') diff --git a/compilers.py b/compilers.py index 7a4394e62..10579eada 100644 --- a/compilers.py +++ b/compilers.py @@ -1023,6 +1023,22 @@ 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')} + + 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 [] + GCC_STANDARD = 0 GCC_OSX = 1 GCC_MINGW = 2 @@ -1259,7 +1275,7 @@ class ClangCPPCompiler(CPPCompiler): return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))] def get_options(self): - return {'c_std' : mesonlib.UserComboOption('cpp_std', 'C++ language standard to use', + return {'cpp_std' : mesonlib.UserComboOption('cpp_std', 'C++ language standard to use', ['none', 'c++03', 'c++11', 'c++1y'], 'c++11')} diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index afdfe0f9b..454c161af 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -1,9 +1,5 @@ project('boosttest', 'cpp') -if meson.get_compiler('cpp').get_id() == 'msvc' - 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. -- cgit v1.2.3 From 0d56955e9cda7993ef07894fb58bb90ba5b463e6 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Mon, 12 Oct 2015 22:22:13 +0300 Subject: Created a stringarray option type and added Windows system libs option that uses it. --- compilers.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ mesonintrospect.py | 2 ++ mesonlib.py | 17 +++++++++++++++++ 3 files changed, 65 insertions(+), 6 deletions(-) (limited to 'compilers.py') diff --git a/compilers.py b/compilers.py index 10579eada..bb32069e3 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 [] @@ -901,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' @@ -993,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) @@ -1027,7 +1044,11 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler): return {'cpp_eh' : mesonlib.UserComboOption('cpp_eh', 'C++ exception handling type.', ['none', 'a', 's', 'sc'], - 'sc')} + 'sc'), + 'cpp_winlibs' : mesonlib.UserStringArrayOption('cpp_winlibs', + 'Windows libs to link against.', + msvc_winlibs) + } def get_option_compile_args(self, options): args = [] @@ -1037,7 +1058,7 @@ class VisualStudioCPPCompiler(VisualStudioCCompiler): return args def get_option_link_args(self, options): - return [] + return options['cpp_winlibs'].value GCC_STANDARD = 0 GCC_OSX = 1 @@ -1056,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) @@ -1092,9 +1114,15 @@ class GnuCCompiler(CCompiler): return super().can_compile(filename) or filename.split('.')[-1].lower() == 's' # Gcc can do asm, too. def get_options(self): - return {'c_std' : mesonlib.UserComboOption('c_std', 'C language standard to use', + 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 = [] @@ -1104,6 +1132,8 @@ class GnuCCompiler(CCompiler): return args def get_option_link_args(self, options): + if self.gcc_type == GCC_MINGW: + return options['c_winlibs'].value return [] class GnuObjCCompiler(ObjCCompiler): @@ -1207,6 +1237,8 @@ class ClangCCompiler(CCompiler): return args def get_option_link_args(self, options): + if self.gcc_type == GCC_MINGW: + return options['c_winlibs'].value return [] class GnuCPPCompiler(CPPCompiler): @@ -1237,9 +1269,15 @@ class GnuCPPCompiler(CPPCompiler): return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion) 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')} + 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 = [] @@ -1249,6 +1287,8 @@ class GnuCPPCompiler(CPPCompiler): return args def get_option_link_args(self, options): + if self.gcc_type == GCC_MINGW: + return options['cpp_winlibs'].value return [] class ClangCPPCompiler(CPPCompiler): diff --git a/mesonintrospect.py b/mesonintrospect.py index 238d1528d..3ef2ab586 100755 --- a/mesonintrospect.py +++ b/mesonintrospect.py @@ -126,6 +126,8 @@ def add_keys(optlist, options): 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 diff --git a/mesonlib.py b/mesonlib.py index 0e31ef118..0c7c3080d 100644 --- a/mesonlib.py +++ b/mesonlib.py @@ -314,3 +314,20 @@ class UserComboOption(UserOption): 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 -- cgit v1.2.3