diff options
-rw-r--r-- | authors.txt | 1 | ||||
-rw-r--r-- | backends.py | 2 | ||||
-rw-r--r-- | compilers.py | 169 | ||||
-rw-r--r-- | coredata.py | 5 | ||||
-rw-r--r-- | cross/iphone.txt | 26 | ||||
-rw-r--r-- | cross/ubuntu-armhf.txt | 8 | ||||
-rw-r--r-- | dependencies.py | 80 | ||||
-rw-r--r-- | environment.py | 16 | ||||
-rw-r--r-- | interpreter.py | 9 | ||||
-rw-r--r-- | man/meson.1 | 2 | ||||
-rw-r--r-- | man/mesonconf.1 | 2 | ||||
-rw-r--r-- | man/mesongui.1 | 2 | ||||
-rw-r--r-- | man/mesonintrospect.1 | 2 | ||||
-rw-r--r-- | man/wraptool.1 | 2 | ||||
-rwxr-xr-x | meson.py | 11 | ||||
-rwxr-xr-x | mesonconf.py | 7 | ||||
-rw-r--r-- | mesonlib.py | 13 | ||||
-rw-r--r-- | ninjabackend.py | 112 | ||||
-rw-r--r-- | test cases/common/58 run target/helloprinter.c | 10 | ||||
-rw-r--r-- | test cases/common/58 run target/meson.build | 6 | ||||
-rw-r--r-- | test cases/failing/19 target clash/clash.c | 6 | ||||
-rw-r--r-- | test cases/failing/19 target clash/meson.build | 15 | ||||
-rw-r--r-- | test cases/frameworks/1 boost/meson.build | 5 | ||||
-rw-r--r-- | test cases/frameworks/1 boost/nomod.cpp | 18 | ||||
-rwxr-xr-x | tools/ac_converter.py | 217 | ||||
-rwxr-xr-x | tools/autotools2meson.py | 122 | ||||
-rwxr-xr-x | tools/cmake2meson.py | 2 |
27 files changed, 611 insertions, 259 deletions
diff --git a/authors.txt b/authors.txt index 0db0c3d..88e8ba3 100644 --- a/authors.txt +++ b/authors.txt @@ -20,3 +20,4 @@ Mathieu Duponchelle Jouni Roivas Rafaël Kooi Marko Raatikainen +German Diago Gomez diff --git a/backends.py b/backends.py index b83ad2a..0fc8646 100644 --- a/backends.py +++ b/backends.py @@ -209,7 +209,7 @@ class Backend(): commands = [] commands += compiler.get_always_args() if self.environment.coredata.buildtype != 'plain': - commands += compiler.get_std_warn_args() + commands += compiler.get_warn_args(self.environment.coredata.warning_level) 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 407770f..df8fc2f 100644 --- a/compilers.py +++ b/compilers.py @@ -145,6 +145,9 @@ class CCompiler(): def get_linker_always_args(self): return [] + def get_warn_args(self, level): + return self.warn_args[level] + def get_soname_args(self, shlib_name, path, soversion): return [] @@ -260,8 +263,7 @@ int someSymbolHereJustForFun; ''' return self.compiles(templ % hname) - def compiles(self, code): - mlog.debug('Running compile test:\n\n', code) + def compiles(self, code, extra_args = []): suflen = len(self.default_suffix) (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) @@ -269,8 +271,12 @@ int someSymbolHereJustForFun; ofile.write(code) ofile.close() commands = self.get_exelist() + commands += extra_args commands += self.get_compile_only_args() commands.append(srcname) + mlog.debug('Running compile test.') + mlog.debug('Command line: ', ' '.join(commands)) + mlog.debug('Code:\n', code) p = subprocess.Popen(commands, cwd=os.path.split(srcname)[0], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stde, stdo) = p.communicate() stde = stde.decode() @@ -324,7 +330,24 @@ int someSymbolHereJustForFun; os.remove(exename) return RunResult(True, pe.returncode, so, se) + def cross_sizeof(self, element, prefix, env): + templ = '''%s +int temparray[%d-sizeof(%s)]; +''' + extra_args = [] + try: + extra_args = env.cross_info.config['properties'][self.language + '_args'] + except KeyError: + pass + for i in range(1, 1024): + code = templ % (prefix, i, element) + if self.compiles(code, extra_args): + return i + raise EnvironmentException('Cross checking sizeof overflowed.') + def sizeof(self, element, prefix, env): + if self.is_cross: + return self.cross_sizeof(element, prefix, env) templ = '''#include<stdio.h> %s @@ -333,30 +356,35 @@ int main(int argc, char **argv) { return 0; }; ''' - varname = 'sizeof ' + element - varname = varname.replace(' ', '_') - if self.is_cross: - val = env.cross_info.config['properties'][varname] - if val is not None: - if isinstance(val, int): - return val - raise EnvironmentException('Cross variable {0} is not an integer.'.format(varname)) - cross_failed = False - try: - res = self.run(templ % (prefix, element)) - except CrossNoRunException: - cross_failed = True - if cross_failed: - message = '''Can not determine size of {0} because cross compiled binaries are not runnable. -Please define the corresponding variable {1} in your cross compilation definition file.'''.format(element, varname) - raise EnvironmentException(message) + res = self.run(templ % (prefix, element)) if not res.compiled: raise EnvironmentException('Could not compile sizeof test.') if res.returncode != 0: raise EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) + def cross_alignment(self, typename, env): + templ = '''#include<stddef.h> +struct tmp { + char c; + %s target; +}; + +int testarray[%d-offsetof(struct tmp, target)]; +''' + try: + extra_args = env.cross_info.config['properties'][self.language + '_args'] + except KeyError: + pass + for i in range(1, 1024): + code = templ % (typename, i) + if self.compiles(code, extra_args): + return i + raise EnvironmentException('Cross checking offsetof overflowed.') + def alignment(self, typename, env): + if self.is_cross: + return self.cross_alignment(typename, env) templ = '''#include<stdio.h> #include<stddef.h> @@ -370,23 +398,7 @@ int main(int argc, char **argv) { return 0; } ''' - varname = 'alignment ' + typename - varname = varname.replace(' ', '_') - if self.is_cross: - val = env.cross_info.config['properties'][varname] - if val is not None: - if isinstance(val, int): - return val - raise EnvironmentException('Cross variable {0} is not an integer.'.format(varname)) - cross_failed = False - try: - res = self.run(templ % typename) - except CrossNoRunException: - cross_failed = True - if cross_failed: - message = '''Can not determine alignment of {0} because cross compiled binaries are not runnable. -Please define the corresponding variable {1} in your cross compilation definition file.'''.format(typename, varname) - raise EnvironmentException(message) + res = self.run(templ % typename) if not res.compiled: raise EnvironmentException('Could not compile alignment test.') if res.returncode != 0: @@ -413,7 +425,7 @@ int main(int argc, char **argv) { if val is not None: if isinstance(val, bool): return val - raise EnvironmentException('Cross variable {0} is not an boolean.'.format(varname)) + raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) return self.compiles(templ % (prefix, funcname)) def has_member(self, typename, membername, prefix): @@ -915,13 +927,13 @@ class VisualStudioCCompiler(CCompiler): self.always_args = VisualStudioCCompiler.vs2013_always_args else: self.always_args = VisualStudioCCompiler.vs2010_always_args + self.warn_args = {'1': ['/W2'], + '2': ['/W3'], + '3': ['/w4']} def get_always_args(self): return self.always_args - def get_std_warn_args(self): - return self.std_warn_args - def get_buildtype_args(self, buildtype): return msvc_buildtype_args[buildtype] @@ -1039,7 +1051,8 @@ def get_gcc_soname_args(gcc_type, shlib_name, path, soversion): sostr = '' else: sostr = '.' + soversion - if gcc_type == GCC_STANDARD: + if gcc_type == GCC_STANDARD or gcc_type == GCC_MINGW: + # Might not be correct for mingw but seems to work. return ['-Wl,-soname,lib%s.so%s' % (shlib_name, sostr)] elif gcc_type == GCC_OSX: return ['-install_name', os.path.join(path, 'lib' + shlib_name + '.dylib')] @@ -1047,17 +1060,13 @@ def get_gcc_soname_args(gcc_type, shlib_name, path, soversion): raise RuntimeError('Not implemented yet.') class GnuCCompiler(CCompiler): - old_warn = ['-Wall', '-pedantic', '-Winvalid-pch'] - new_warn = ['-Wall', '-Wpedantic', '-Winvalid-pch'] - def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) self.id = 'gcc' self.gcc_type = gcc_type - if mesonlib.version_compare(version, ">=4.9.0"): - self.warn_args= GnuCCompiler.new_warn - else: - self.warn_args = GnuCCompiler.old_warn + self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch'], + '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']} def get_pic_args(self): if self.gcc_type == GCC_MINGW: @@ -1067,9 +1076,6 @@ class GnuCCompiler(CCompiler): def get_always_args(self): return ['-pipe'] - def get_std_warn_args(self): - return self.warn_args - def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1089,7 +1095,7 @@ class GnuCCompiler(CCompiler): return super().can_compile(filename) or filename.split('.')[-1].lower() == 's' # Gcc can do asm, too. class GnuObjCCompiler(ObjCCompiler): - std_warn_args = ['-Wall', '-Wpedantic', '-Winvalid-pch'] + std_opt_args = ['-O2'] def __init__(self, exelist, version, is_cross, exe_wrapper=None): ObjCCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) @@ -1097,9 +1103,9 @@ class GnuObjCCompiler(ObjCCompiler): # Not really correct, but GNU objc is only used on non-OSX non-win. File a bug # if this breaks your use case. self.gcc_type = GCC_STANDARD - - def get_std_warn_args(self): - return GnuObjCCompiler.std_warn_args + self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch'], + '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch']} def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1114,7 +1120,6 @@ class GnuObjCCompiler(ObjCCompiler): return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion) class GnuObjCPPCompiler(ObjCPPCompiler): - std_warn_args = ['-Wall', '-Wpedantic', '-Winvalid-pch'] std_opt_args = ['-O2'] def __init__(self, exelist, version, is_cross, exe_wrapper=None): @@ -1123,9 +1128,9 @@ class GnuObjCPPCompiler(ObjCPPCompiler): # Not really correct, but GNU objc is only used on non-OSX non-win. File a bug # if this breaks your use case. self.gcc_type = GCC_STANDARD - - def get_std_warn_args(self): - return GnuObjCPPCompiler.std_warn_args + self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'], + '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1155,9 +1160,9 @@ class ClangCCompiler(CCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): CCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) self.id = 'clang' - - def get_std_warn_args(self): - return ClangCCompiler.std_warn_args + self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch'], + '3' : ['-Weverything']} def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1179,8 +1184,6 @@ class ClangCCompiler(CCompiler): class GnuCPPCompiler(CPPCompiler): - new_warn = ['-Wall', '-Wpedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'] - old_warn = ['-Wall', '-pedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'] # may need to separate the latter to extra_debug_args or something std_debug_args = ['-g'] @@ -1188,17 +1191,13 @@ class GnuCPPCompiler(CPPCompiler): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) self.id = 'gcc' self.gcc_type = gcc_type - if mesonlib.version_compare(version, ">=4.9.0"): - self.warn_args= GnuCPPCompiler.new_warn - else: - self.warn_args = GnuCPPCompiler.old_warn + self.warn_args = {'1': ['-Wall', '-Winvalid-pch'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'], + '3': ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} def get_always_args(self): return ['-pipe'] - def get_std_warn_args(self): - return self.warn_args - def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1212,14 +1211,12 @@ class GnuCPPCompiler(CPPCompiler): return get_gcc_soname_args(self.gcc_type, shlib_name, path, soversion) class ClangCPPCompiler(CPPCompiler): - std_warn_args = ['-Wall', '-Wpedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'] - def __init__(self, exelist, version, is_cross, exe_wrapper=None): CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrapper) self.id = 'clang' - - def get_std_warn_args(self): - return ClangCPPCompiler.std_warn_args + self.warn_args = {'1': ['-Wall', '-Winvalid-pch', '-Wnon-virtual-dtor'], + '2': ['-Wall', '-Wpedantic', '-Winvalid-pch', '-Wnon-virtual-dtor'], + '3': ['-Weverything']} def get_buildtype_args(self, buildtype): return gnulike_buildtype_args[buildtype] @@ -1237,8 +1234,6 @@ class ClangCPPCompiler(CPPCompiler): return ['-include-pch', os.path.join (pch_dir, self.get_pch_name (header))] class FortranCompiler(): - std_warn_args = ['-Wall'] - def __init__(self, exelist, version,is_cross, exe_wrapper=None): super().__init__() self.exelist = exelist @@ -1304,7 +1299,7 @@ end program prog def get_linker_always_args(self): return [] - def get_std_warn_args(self): + def get_std_warn_args(self, level): return FortranCompiler.std_warn_args def get_buildtype_args(self, buildtype): @@ -1363,6 +1358,10 @@ end program prog def module_name_to_filename(self, module_name): return module_name.lower() + '.mod' + def get_warn_args(self, level): + return ['-Wall'] + + class GnuFortranCompiler(FortranCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None): super().__init__(exelist, version, is_cross, exe_wrapper=None) @@ -1388,7 +1387,7 @@ class SunFortranCompiler(FortranCompiler): def get_always_args(self): return [] - def get_std_warn_args(self): + def get_warn_args(self): return [] def get_module_outdir_args(self, path): @@ -1413,7 +1412,7 @@ class IntelFortranCompiler(FortranCompiler): return True return False - def get_std_warn_args(self): + def get_warn_args(self, level): return IntelFortranCompiler.std_warn_args class PathScaleFortranCompiler(FortranCompiler): @@ -1435,7 +1434,7 @@ class PathScaleFortranCompiler(FortranCompiler): return True return False - def get_std_warn_args(self): + def get_std_warn_args(self, level): return PathScaleFortranCompiler.std_warn_args class PGIFortranCompiler(FortranCompiler): @@ -1457,7 +1456,7 @@ class PGIFortranCompiler(FortranCompiler): return True return False - def get_std_warn_args(self): + def get_warn_args(self, level): return PGIFortranCompiler.std_warn_args @@ -1480,7 +1479,7 @@ class Open64FortranCompiler(FortranCompiler): return True return False - def get_std_warn_args(self): + def get_warn_args(self, level): return Open64FortranCompiler.std_warn_args class NAGFortranCompiler(FortranCompiler): @@ -1502,7 +1501,7 @@ class NAGFortranCompiler(FortranCompiler): return True return False - def get_std_warn_args(self): + def get_warn_args(self, level): return NAGFortranCompiler.std_warn_args diff --git a/coredata.py b/coredata.py index 7837762..793cd47 100644 --- a/coredata.py +++ b/coredata.py @@ -14,7 +14,7 @@ import pickle, os, uuid -version = '0.26.0-research' +version = '0.27.0-research' builtin_options = {'buildtype': True, 'strip': True, @@ -29,8 +29,10 @@ builtin_options = {'buildtype': True, 'mandir' : True, 'localedir' : True, 'werror' : True, + 'warning_level': True, 'layout' : True, } + # This class contains all data that must persist over multiple # invocations of Meson. It is roughly the same thing as # cmakecache. @@ -55,6 +57,7 @@ class CoreData(): self.use_pch = options.use_pch self.unity = options.unity self.coverage = options.coverage + self.warning_level = options.warning_level self.werror = options.werror self.layout = options.layout self.user_options = {} diff --git a/cross/iphone.txt b/cross/iphone.txt new file mode 100644 index 0000000..de48551 --- /dev/null +++ b/cross/iphone.txt @@ -0,0 +1,26 @@ +# This is a cross compilation file from OSX Yosemite to iPhone +# Apple keeps changing the location and names of files so +# these might not work for you. Use the googels and xcrun. + +[binaries] +c = 'clang' +cpp = 'clang++' +ar = 'ar' +strip = 'strip' + +[properties] +root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer' + +c_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] +cpp_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] +c_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] +cpp_link_args = ['-arch', 'armv7', '-miphoneos-version-min=8.0', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.4.sdk'] + +has_function_printf = true +has_function_hfkerhisadf = false + +[host_machine] +system = 'ios' +cpu = 'armv7' +endian = 'little' + diff --git a/cross/ubuntu-armhf.txt b/cross/ubuntu-armhf.txt index 196f2bf..d15780e 100644 --- a/cross/ubuntu-armhf.txt +++ b/cross/ubuntu-armhf.txt @@ -10,14 +10,6 @@ pkgconfig = '/usr/bin/arm-linux-gnueabihf-pkg-config' [properties] root = '/usr/arm-linux-gnueabihf' -sizeof_int = 4 -sizeof_wchar_t = 4 -sizeof_void* = 4 - -alignment_char = 1 -alignment_void* = 4 -alignment_double = 4 # Don't know if this is correct... - has_function_printf = true has_function_hfkerhisadf = false diff --git a/dependencies.py b/dependencies.py index d47dac8..d3a82db 100644 --- a/dependencies.py +++ b/dependencies.py @@ -393,6 +393,7 @@ class BoostDependency(Dependency): def __init__(self, environment, kwargs): Dependency.__init__(self) self.name = 'boost' + self.libdir = '' try: self.boost_root = os.environ['BOOST_ROOT'] if not os.path.isabs(self.boost_root): @@ -400,9 +401,15 @@ class BoostDependency(Dependency): except KeyError: self.boost_root = None if self.boost_root is None: - self.incdir = '/usr/include/boost' + if mesonlib.is_windows(): + self.boost_root = self.detect_win_root() + self.incdir = self.boost_root + else: + self.incdir = '/usr/include' else: - self.incdir = os.path.join(self.boost_root, 'include/boost') + self.incdir = os.path.join(self.boost_root, 'include') + self.boost_inc_subdir = os.path.join(self.incdir, 'boost') + mlog.debug('Boost library root dir is', self.boost_root) self.src_modules = {} self.lib_modules = {} self.lib_modules_mt = {} @@ -422,17 +429,26 @@ class BoostDependency(Dependency): else: mlog.log("Dependency Boost (%s) found:" % module_str, mlog.red('NO')) + def detect_win_root(self): + globtext = 'c:\\local\\boost_*' + files = glob.glob(globtext) + if len(files) > 0: + return files[0] + return 'C:\\' + def get_compile_args(self): args = [] if self.boost_root is not None: - args.append('-I' + os.path.join(self.boost_root, 'include')) + if mesonlib.is_windows(): + args.append('-I' + self.boost_root) + else: + args.append('-I' + os.path.join(self.boost_root, 'include')) + else: + args.append('-I' + self.incdir) return args def get_requested(self, kwargs): - modules = 'modules' - if not modules in kwargs: - raise DependencyException('Boost dependency must specify "%s" keyword.' % modules) - candidates = kwargs[modules] + candidates = kwargs.get('modules', []) if isinstance(candidates, str): return [candidates] for c in candidates: @@ -453,7 +469,7 @@ class BoostDependency(Dependency): def detect_version(self): try: - ifile = open(os.path.join(self.incdir, 'version.hpp')) + ifile = open(os.path.join(self.boost_inc_subdir, 'version.hpp')) except FileNotFoundError: self.version = None return @@ -466,13 +482,41 @@ class BoostDependency(Dependency): self.version = None def detect_src_modules(self): - for entry in os.listdir(self.incdir): - entry = os.path.join(self.incdir, entry) + for entry in os.listdir(self.boost_inc_subdir): + entry = os.path.join(self.boost_inc_subdir, entry) if stat.S_ISDIR(os.stat(entry).st_mode): self.src_modules[os.path.split(entry)[-1]] = True def detect_lib_modules(self): - globber = 'libboost_*.so' # FIXME, make platform independent. + if mesonlib.is_windows(): + return self.detect_lib_modules_win() + return self.detect_lib_modules_nix() + + def detect_lib_modules_win(self): + if mesonlib.is_32bit(): + gl = 'lib32*' + else: + gl = 'lib64*' + libdir = glob.glob(os.path.join(self.boost_root, gl)) + if len(libdir) == 0: + return + libdir = libdir[0] + self.libdir = libdir + globber = 'boost_*-gd-*.lib' # FIXME + for entry in glob.glob(os.path.join(libdir, globber)): + (_, fname) = os.path.split(entry) + base = fname.split('_', 1)[1] + modname = base.split('-', 1)[0] + self.lib_modules_mt[modname] = fname + + def detect_lib_modules_nix(self): + libsuffix = None + if mesonlib.is_osx(): + libsuffix = 'dylib' + else: + libsuffix = 'so' + + globber = 'libboost_*.{}'.format(libsuffix) if self.boost_root is None: libdirs = mesonlib.get_library_dirs() else: @@ -488,12 +532,24 @@ class BoostDependency(Dependency): else: self.lib_modules[name] = True - def get_link_args(self): + def get_win_link_args(self): args = [] if self.boost_root: # FIXME, these are in gcc format, not msvc. # On the other hand, so are the args that # pkg-config returns. + args.append('/LIBPATH:' + self.libdir) + for module in self.requested_modules: + module = BoostDependency.name2lib.get(module, module) + if module in self.lib_modules_mt: + args.append(self.lib_modules_mt[module]) + return args + + def get_link_args(self): + if mesonlib.is_windows(): + return self.get_win_link_args() + args = [] + if self.boost_root: args.append('-L' + os.path.join(self.boost_root, 'lib')) for module in self.requested_modules: module = BoostDependency.name2lib.get(module, module) diff --git a/environment.py b/environment.py index 493ee2c..41520d1 100644 --- a/environment.py +++ b/environment.py @@ -189,7 +189,12 @@ class Environment(): return GnuCCompiler(ccache + [compiler], version, GCC_OSX, is_cross, exe_wrap) if (out.startswith('cc') or 'gcc' in out) and \ 'Free Software Foundation' in out: - return GnuCCompiler(ccache + [compiler], version, GCC_STANDARD, is_cross, exe_wrap) + lowerout = out.lower() + if 'mingw' in lowerout or 'msys' in lowerout or 'mingw' in compiler.lower(): + gtype = GCC_MINGW + else: + gtype = GCC_STANDARD + return GnuCCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap) if 'clang' in out: return ClangCCompiler(ccache + [compiler], version, is_cross, exe_wrap) if 'Microsoft' in out: @@ -308,7 +313,12 @@ class Environment(): return GnuCPPCompiler(ccache + [compiler], version, GCC_OSX, is_cross, exe_wrap) if (out.startswith('c++ ') or 'g++' in out or 'GCC' in out) and \ 'Free Software Foundation' in out: - return GnuCPPCompiler(ccache + [compiler], version, GCC_STANDARD, is_cross, exe_wrap) + lowerout = out.lower() + if 'mingw' in lowerout or 'msys' in lowerout or 'mingw' in compiler.lower(): + gtype = GCC_MINGW + else: + gtype = GCC_STANDARD + return GnuCPPCompiler(ccache + [compiler], version, gtype, is_cross, exe_wrap) if 'clang' in out: return ClangCPPCompiler(ccache + [compiler], version, is_cross, exe_wrap) if 'Microsoft' in out: @@ -622,7 +632,7 @@ class CrossBuildInfo(): for i in res: if not self.ok_type(i): raise EnvironmentException('Malformed value in cross file variable %s.' % varname) - self.items[varname] = res + self.config[s][entry] = res else: raise EnvironmentException('Malformed value in cross file variable %s.' % varname) diff --git a/interpreter.py b/interpreter.py index 264fcf6..5da6d8b 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1462,11 +1462,18 @@ class Interpreter(): self.add_target(name, tg.held_object) return tg - @stringArgs @noKwargs def func_run_target(self, node, args, kwargs): if len(args) < 2: raise InterpreterException('Incorrect number of arguments') + for i in args: + try: + i = i.held_object + except AttributeError: + pass + if not isinstance(i, (str, build.BuildTarget)): + mlog.debug('Wrong type:', str(i)) + raise InterpreterException('Invalid argument to run_target.') name = args[0] command = args[1] cmd_args = args[2:] diff --git a/man/meson.1 b/man/meson.1 index 3839709..0f326ff 100644 --- a/man/meson.1 +++ b/man/meson.1 @@ -1,4 +1,4 @@ -.TH MESON "1" "July 2015" "meson 0.25.0" "User Commands" +.TH MESON "1" "September 2015" "meson 0.26.0" "User Commands" .SH NAME meson - a high productivity build system .SH DESCRIPTION diff --git a/man/mesonconf.1 b/man/mesonconf.1 index 28cf3c2..ad5268f 100644 --- a/man/mesonconf.1 +++ b/man/mesonconf.1 @@ -1,4 +1,4 @@ -.TH MESONCONF "1" "July 2015" "mesonconf 0.25.0" "User Commands" +.TH MESONCONF "1" "September 2015" "mesonconf 0.26.0" "User Commands" .SH NAME mesonconf - a tool to configure Meson builds .SH DESCRIPTION diff --git a/man/mesongui.1 b/man/mesongui.1 index c233844..d0a17db 100644 --- a/man/mesongui.1 +++ b/man/mesongui.1 @@ -1,4 +1,4 @@ -.TH MESONGUI "1" "July 2015" "mesongui 0.25.0" "User Commands" +.TH MESONGUI "1" "September 2015" "mesongui 0.26.0" "User Commands" .SH NAME mesongui - a gui for the Meson build system .SH DESCRIPTION diff --git a/man/mesonintrospect.1 b/man/mesonintrospect.1 index 6b6b9d5..e3f0efb 100644 --- a/man/mesonintrospect.1 +++ b/man/mesonintrospect.1 @@ -1,4 +1,4 @@ -.TH MESONCONF "1" "July 2015" "mesonintrospect 0.25.0" "User Commands" +.TH MESONCONF "1" "September 2015" "mesonintrospect 0.26.0" "User Commands" .SH NAME mesonintrospect - a tool to extract information about a Meson build .SH DESCRIPTION diff --git a/man/wraptool.1 b/man/wraptool.1 index d9d2aba..48baa89 100644 --- a/man/wraptool.1 +++ b/man/wraptool.1 @@ -1,4 +1,4 @@ -.TH WRAPTOOL "1" "July 2015" "meson 0.25.0" "User Commands" +.TH WRAPTOOL "1" "September 2015" "meson 0.26.0" "User Commands" .SH NAME wraptool - source dependency downloader .SH DESCRIPTION @@ -29,6 +29,15 @@ parser = argparse.ArgumentParser() backendlist = ['ninja', 'vs2010', 'xcode'] build_types = ['plain', 'debug', 'debugoptimized', 'release'] layouts = ['mirror', 'flat'] +warning_levels = ['1', '2', '3'] + +default_warning = '1' +try: + warn_candidate = os.environ['MESON_WARN_LEVEL'] + if warn_candidate in warning_levels: + default_warning = warn_candidate +except KeyError: + pass if mesonlib.is_windows(): def_prefix = 'c:/' @@ -65,6 +74,8 @@ parser.add_argument('--werror', action='store_true', dest='werror', default=Fals help='Treat warnings as errors') parser.add_argument('--layout', choices=layouts, dest='layout', default='mirror',\ help='Build directory layout.') +parser.add_argument('--warnlevel', default=default_warning, dest='warning_level', choices=warning_levels,\ + help='Level of compiler warnings to use (larger is more, default is %(default)s)') parser.add_argument('--cross-file', default=None, dest='cross_file', help='file describing cross compilation environment') parser.add_argument('-D', action='append', dest='projectoptions', default=[], diff --git a/mesonconf.py b/mesonconf.py index adec6e2..db526b0 100755 --- a/mesonconf.py +++ b/mesonconf.py @@ -18,7 +18,7 @@ import sys, os import pickle import argparse import coredata, optinterpreter -from meson import build_types, layouts +from meson import build_types, layouts, warning_levels parser = argparse.ArgumentParser() @@ -84,6 +84,10 @@ class Conf: if v not in layouts: raise ConfException('Invalid layout type %s.' % v) self.coredata.layout = v + elif k == 'warnlevel': + if not v in warning_levels: + raise ConfException('Invalid warning level %s.' % v) + self.coredata.warning_level = v elif k == 'strip': self.coredata.strip = self.tobool(v) elif k == 'coverage': @@ -162,6 +166,7 @@ class Conf: print('Core options\n') carr = [] carr.append(['buildtype', 'Build type', self.coredata.buildtype]) + carr.append(['warnlevel', 'Warning level', self.coredata.warning_level]) carr.append(['strip', 'Strip on install', self.coredata.strip]) carr.append(['coverage', 'Coverage report', self.coredata.coverage]) carr.append(['pch', 'Precompiled headers', self.coredata.use_pch]) diff --git a/mesonlib.py b/mesonlib.py index 76fb792..d7c40f4 100644 --- a/mesonlib.py +++ b/mesonlib.py @@ -14,7 +14,7 @@ """A library of random helper functionality.""" -import platform, subprocess, operator, os, shutil, re +import platform, subprocess, operator, os, shutil, re, sys from glob import glob @@ -79,6 +79,9 @@ def is_windows(): platname = platform.system().lower() return platname == 'windows' or 'mingw' in platname +def is_32bit(): + return not(sys.maxsize > 2**32) + def is_debianlike(): try: open('/etc/debian_version', 'r') @@ -113,9 +116,13 @@ def detect_vcs(source_dir): return vcs return None +numpart = re.compile('[0-9.]+') + def version_compare(vstr1, vstr2): - if '-' in vstr1: - vstr1 = vstr1.split('-')[0] + match = numpart.match(vstr1.strip()) + if match is None: + raise MesonException('Unconparable version string %s.' % vstr1) + vstr1 = match.group(0) if vstr2.startswith('>='): cmpop = operator.ge vstr2 = vstr2[2:] diff --git a/ninjabackend.py b/ninjabackend.py index 2fa60df..01223ab 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -114,6 +114,13 @@ class NinjaBackend(backends.Backend): self.source_suffix_in_objs = True self.ninja_filename = 'build.ninja' self.fortran_deps = {} + self.all_outputs = {} + + def check_outputs(self, elem): + for n in elem.outfilenames: + if n in self.all_outputs: + raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n) + self.all_outputs[n] = True def generate(self, interp): self.interpreter = interp @@ -259,7 +266,8 @@ class NinjaBackend(backends.Backend): obj_list.append(self.generate_single_compile(target, outfile, src, True, unity_deps + header_deps)) linker = self.determine_linker(target, src_list) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects) - self.generate_shlib_aliases(target, self.get_target_dir(target), outfile, elem) + self.generate_shlib_aliases(target, self.get_target_dir(target)) + elem.write(outfile) self.processed_targets[name] = True def process_target_dependencies(self, target, outfile): @@ -326,17 +334,42 @@ class NinjaBackend(backends.Backend): elem.add_item('COMMAND', cmd) elem.add_item('description', 'Generating %s with a custom command.' % target.name) elem.write(outfile) + self.check_outputs(elem) self.processed_targets[target.name + target.type_suffix()] = True def generate_run_target(self, target, outfile): runnerscript = os.path.join(self.environment.get_script_dir(), 'commandrunner.py') - elem = NinjaBuildElement(target.name, 'CUSTOM_COMMAND', []) - cmd = [sys.executable, runnerscript, self.environment.get_source_dir(), self.environment.get_build_dir(), - target.subdir, target.command] + target.args + deps = [] + arg_strings = [] + for i in target.args: + if isinstance(i, str): + arg_strings.append(i) + elif isinstance(i, build.BuildTarget): + deps.append(self.get_target_filename(i)) + else: + raise MesonException('Unreachable code.') + elem = NinjaBuildElement(target.name, 'CUSTOM_COMMAND', deps) + cmd = [sys.executable, runnerscript, self.environment.get_source_dir(), self.environment.get_build_dir(), target.subdir] + texe = target.command + try: + texe = texe.held_object + except AttributeError: + pass + if isinstance(texe, build.Executable): + abs_exe = os.path.join(self.environment.get_build_dir(), self.get_target_filename(texe)) + deps.append(self.get_target_filename(texe)) + if self.environment.is_cross_build() \ + and self.environment.cross_info.config['binaries'].get('exe_wrapper', None) is not None: + cmd += [self.environment.cross_info.config['binaries']['exe_wrapper']] + cmd.append(abs_exe) + else: + cmd.append(target.command) + cmd += target.args elem.add_item('COMMAND', cmd) elem.add_item('description', 'Running external command %s.' % target.name) elem.add_item('pool', 'console') elem.write(outfile) + self.check_outputs(elem) self.processed_targets[target.name + target.type_suffix()] = True def generate_po(self, outfile): @@ -349,6 +382,7 @@ class NinjaBackend(backends.Backend): elem.add_item('FILELIST', os.path.join(self.environment.get_source_dir(), input_file)) elem.add_item('OUTDIR', os.path.join(self.environment.get_source_dir(), subdir)) elem.write(outfile) + self.check_outputs(elem) for l in languages: infile = os.path.join(self.environment.get_source_dir(), subdir, l + '.po') outfilename = os.path.join(subdir, l + '.gmo') @@ -356,6 +390,7 @@ class NinjaBackend(backends.Backend): lelem.add_item('INFILE', infile) lelem.add_item('OUTFILE', outfilename) lelem.write(outfile) + self.check_outputs(lelem) def generate_coverage_rules(self, outfile): (gcovr_exe, lcov_exe, genhtml_exe) = environment.find_coverage_tools() @@ -372,6 +407,7 @@ class NinjaBackend(backends.Backend): '-o', os.path.join(self.environment.get_log_dir(), 'coverage.txt')]) elem.add_item('DESC', 'Generating text coverage report.') elem.write(outfile) + self.check_outputs(elem) if lcov_exe and genhtml_exe: added_rule = True phony_elem = NinjaBuildElement('coverage-html', 'phony', 'coveragereport/index.html') @@ -385,6 +421,7 @@ class NinjaBackend(backends.Backend): '--legend', '--show-details', 'coverage.info'] elem.add_item('COMMAND', command) elem.add_item('DESC', 'Generating HTML coverage report.') + self.check_outputs(elem) elem.write(outfile) if not added_rule: mlog.log(mlog.red('Warning:'), 'coverage requested but neither gcovr nor lcov/genhtml found.') @@ -412,6 +449,7 @@ class NinjaBackend(backends.Backend): self.generate_custom_install_script(d) self.generate_subdir_install(d) elem.write(outfile) + self.check_outputs(elem) ofile = open(install_data_file, 'wb') pickle.dump(d, ofile) @@ -517,6 +555,7 @@ class NinjaBackend(backends.Backend): elem.add_item('DESC', 'Running test suite.') elem.add_item('pool', 'console') elem.write(outfile) + self.check_outputs(elem) if valgrind: velem = NinjaBuildElement('test-valgrind', 'CUSTOM_COMMAND', ['all', 'PHONY']) @@ -524,6 +563,7 @@ class NinjaBackend(backends.Backend): velem.add_item('DESC', 'Running test suite under Valgrind.') velem.add_item('pool', 'console') velem.write(outfile) + self.check_outputs(velem) def generate_rules(self, outfile): outfile.write('# Rules for compiling.\n\n') @@ -600,6 +640,7 @@ class NinjaBackend(backends.Backend): elem.add_dep([os.path.join(self.get_target_private_dir(target), i) for i in class_list]) elem.add_item('ARGS', commands) elem.write(outfile) + self.check_outputs(elem) def generate_cs_resource_tasks(self, target, outfile): args = [] @@ -615,6 +656,7 @@ class NinjaBackend(backends.Backend): elem.add_item('COMMAND', ['resgen', rel_sourcefile, ofilename]) elem.add_item('DESC', 'Compiling resource %s.' % rel_sourcefile) elem.write(outfile) + self.check_outputs(elem) deps.append(ofilename) a = '-resource:' + ofilename else: @@ -654,6 +696,7 @@ class NinjaBackend(backends.Backend): elem = NinjaBuildElement(outputs, 'cs_COMPILER', rel_srcs) elem.add_dep(deps) elem.add_item('ARGS', commands) + self.check_outputs(elem) elem.write(outfile) def generate_single_java_compile(self, src, target, compiler, outfile): @@ -666,6 +709,7 @@ class NinjaBackend(backends.Backend): element = NinjaBuildElement(rel_obj, compiler.get_language() + '_COMPILER', rel_src) element.add_item('ARGS', args) element.write(outfile) + self.check_outputs(element) return plain_class_path def generate_java_link(self, outfile): @@ -689,6 +733,7 @@ class NinjaBackend(backends.Backend): element = NinjaBuildElement(rel_vapi, valac.get_language() + '_COMPILER', rel_s) element.add_item('ARGS', args) element.write(outfile) + self.check_outputs(element) fastvapis[s] = (vapibase, rel_vapi) return fastvapis @@ -751,6 +796,7 @@ class NinjaBackend(backends.Backend): element.add_orderdep(vapi_order_deps) element.add_dep(extra_dep_files) element.write(outfile) + self.check_outputs(element) return generated_c def generate_rust_target(self, target, outfile): @@ -790,6 +836,7 @@ class NinjaBackend(backends.Backend): element.add_item('targetdep', depfile) element.add_item('cratetype', cratetype) element.write(outfile) + self.check_outputs(element) def generate_static_link_rules(self, is_cross, outfile): if self.build.has_language('java'): @@ -832,11 +879,17 @@ class NinjaBackend(backends.Backend): langname == 'rust' or langname == 'cs': continue crstr = '' + cross_args = [] if is_cross: crstr = '_CROSS' + try: + cross_args = self.environment.cross_info.config['properties'][langname + '_link_args'] + except KeyError: + pass rule = 'rule %s%s_LINKER\n' % (langname, crstr) - command = ' command = %s $ARGS %s $in $LINK_ARGS $aliasing\n' % \ + command = ' command = %s %s $ARGS %s $in $LINK_ARGS $aliasing\n' % \ (' '.join(compiler.get_linker_exelist()),\ + ' '.join(cross_args),\ ' '.join(compiler.get_linker_output_args('$out'))) description = ' description = Linking target $out' outfile.write(rule) @@ -957,8 +1010,15 @@ rule FORTRAN_DEP_HACK if d != '$out' and d != '$in': d = qstr % d quoted_depargs.append(d) - command = " command = %s $ARGS %s %s %s $in\n" % \ + cross_args = [] + if is_cross: + try: + cross_args = self.environment.cross_info.config['properties'][langname + '_args'] + except KeyError: + pass + command = " command = %s %s $ARGS %s %s %s $in\n" % \ (' '.join(compiler.get_exelist()),\ + ' '.join(cross_args), ' '.join(quoted_depargs),\ ' '.join(compiler.get_output_args('$out')),\ ' '.join(compiler.get_compile_only_args())) @@ -983,6 +1043,13 @@ rule FORTRAN_DEP_HACK crstr = '' rule = 'rule %s%s_PCH\n' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') + cross_args = [] + if is_cross: + try: + cross_args = self.environment.cross_info.config['properties'][langname + '_args'] + except KeyError: + pass + quoted_depargs = [] for d in depargs: if d != '$out' and d != '$in': @@ -992,8 +1059,9 @@ rule FORTRAN_DEP_HACK output = '' else: output = ' '.join(compiler.get_output_args('$out')) - command = " command = %s $ARGS %s %s %s $in\n" % \ + command = " command = %s %s $ARGS %s %s %s $in\n" % \ (' '.join(compiler.get_exelist()),\ + ' '.join(cross_args),\ ' '.join(quoted_depargs),\ output,\ ' '.join(compiler.get_compile_only_args())) @@ -1086,6 +1154,7 @@ rule FORTRAN_DEP_HACK elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmdlist) elem.write(outfile) + self.check_outputs(elem) def scan_fortran_module_outputs(self, target): compiler = None @@ -1233,6 +1302,7 @@ rule FORTRAN_DEP_HACK if srcfile == src: depelem = NinjaBuildElement(modfile, 'FORTRAN_DEP_HACK', rel_obj) depelem.write(outfile) + self.check_outputs(depelem) commands += compiler.get_module_outdir_args(self.get_target_private_dir_abs(target)) element = NinjaBuildElement(rel_obj, compiler_name, rel_src) @@ -1257,6 +1327,7 @@ rule FORTRAN_DEP_HACK element.add_item('DEPFILE', dep_file) element.add_item('ARGS', commands) element.write(outfile) + self.check_outputs(element) return rel_obj # Fortran is a bit weird (again). When you link against a library, just compiling a source file @@ -1322,6 +1393,7 @@ rule FORTRAN_DEP_HACK elem.add_item('ARGS', commands) elem.add_item('DEPFILE', dep) elem.write(outfile) + self.check_outputs(elem) return pch_objects def generate_shsym(self, outfile, target): @@ -1332,6 +1404,7 @@ rule FORTRAN_DEP_HACK if self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler(): elem.add_item('CROSS', '--cross-host=' + self.environment.cross_info.config['host_machine']['system']) elem.write(outfile) + self.check_outputs(elem) def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): if isinstance(target, build.StaticLibrary): @@ -1395,6 +1468,7 @@ rule FORTRAN_DEP_HACK elem = NinjaBuildElement(outname, linker_rule, obj_list) elem.add_dep(dep_targets) elem.add_item('LINK_ARGS', commands) + self.check_outputs(elem) return elem def determine_rpath_dirs(self, target): @@ -1411,19 +1485,19 @@ rule FORTRAN_DEP_HACK return os.path.join(self.get_target_private_dir_abs(t), self.get_target_filename(t) + '.symbols') return self.get_target_filename(t) - def generate_shlib_aliases(self, target, outdir, outfile, elem): + def generate_shlib_aliases(self, target, outdir): basename = target.get_filename() aliases = target.get_aliaslist() - aliascmd = [] - if shutil.which('ln'): + if not mesonlib.is_windows(): for alias in aliases: - aliasfile = os.path.join(outdir, alias) - cmd = ["&&", 'ln', '-s', '-f', basename, aliasfile] - aliascmd += cmd + aliasfile = os.path.join(self.environment.get_build_dir(), outdir, alias) + try: + os.remove(aliasfile) + except Exception: + pass + os.symlink(basename, aliasfile) else: - mlog.log("Library versioning disabled because host does not support symlinks.") - elem.add_item('aliasing', aliascmd) - elem.write(outfile) + mlog.debug("Library versioning disabled because host does not support symlinks.") def generate_gcov_clean(self, outfile): gcno_elem = NinjaBuildElement('clean-gcno', 'CUSTOM_COMMAND', 'PHONY') @@ -1432,6 +1506,7 @@ rule FORTRAN_DEP_HACK gcno_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files') gcno_elem.write(outfile) + self.check_outputs(gcno_elem, gcno_elem) gcda_elem = NinjaBuildElement('clean-gcda', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() @@ -1439,6 +1514,7 @@ rule FORTRAN_DEP_HACK gcda_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcda']) gcda_elem.add_item('description', 'Deleting gcda files') gcda_elem.write(outfile) + self.check_outputs(gcda_elem) def is_compilable_file(self, filename): if filename.endswith('.cpp') or\ @@ -1464,6 +1540,7 @@ rule FORTRAN_DEP_HACK infilename = os.path.join(self.build_to_src, target.get_source_subdir(), src) elem = NinjaBuildElement(outfilename, rule.name, infilename) elem.write(outfile) + self.check_outputs(elem) if self.is_compilable_file(outfilename): src_deps.append(outfilename) else: @@ -1476,6 +1553,7 @@ rule FORTRAN_DEP_HACK elem = NinjaBuildElement('all', 'phony', targetlist) elem.write(outfile) + self.check_outputs(elem) default = 'default all\n\n' outfile.write(default) @@ -1491,6 +1569,7 @@ rule FORTRAN_DEP_HACK elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') elem.write(outfile) + self.check_outputs(elem) deps = [os.path.join(self.build_to_src, df) \ for df in self.interpreter.get_build_def_files()] @@ -1510,3 +1589,4 @@ rule FORTRAN_DEP_HACK elem = NinjaBuildElement(deps, 'phony', '') elem.write(outfile) + self.check_outputs(elem) diff --git a/test cases/common/58 run target/helloprinter.c b/test cases/common/58 run target/helloprinter.c new file mode 100644 index 0000000..7f94b19 --- /dev/null +++ b/test cases/common/58 run target/helloprinter.c @@ -0,0 +1,10 @@ +#include<stdio.h> + +int main(int argc, char **argv) { + if(argc != 2) { + printf("I can not haz argument.\n"); + } else { + printf("I can haz argument: %s\n", argv[1]); + } + return 0; +} diff --git a/test cases/common/58 run target/meson.build b/test cases/common/58 run target/meson.build index 3ae80d2..519adf5 100644 --- a/test cases/common/58 run target/meson.build +++ b/test cases/common/58 run target/meson.build @@ -1,3 +1,9 @@ project('run target', 'c') run_target('mycommand', 'scripts/script.sh') + +# Make it possible to run built programs. +# In cross builds exe_wrapper should be added if it exists. + +exe = executable('helloprinter', 'helloprinter.c') +run_target('runhello', exe, 'argument') diff --git a/test cases/failing/19 target clash/clash.c b/test cases/failing/19 target clash/clash.c new file mode 100644 index 0000000..2daa06c --- /dev/null +++ b/test cases/failing/19 target clash/clash.c @@ -0,0 +1,6 @@ +#include<stdio.h> + +int main(int argc, char **argv) { + printf("Clash 2.\n"); + return 0; +} diff --git a/test cases/failing/19 target clash/meson.build b/test cases/failing/19 target clash/meson.build new file mode 100644 index 0000000..070631b --- /dev/null +++ b/test cases/failing/19 target clash/meson.build @@ -0,0 +1,15 @@ +project('clash', 'c') + +# This setup causes a namespace clash when two Meson targets would +# produce a Ninja targets with the same name. It only works on +# unix, because on Windows the target has a '.exe' suffix. +# +# This test might fail to work on different backends or when +# output location is redirected. + +if host_machine.system() == 'windows' + error('This is expected.') +endif + +executable('clash', 'clash.c') +run_target('clash', 'echo', 'clash 1') diff --git a/test cases/frameworks/1 boost/meson.build b/test cases/frameworks/1 boost/meson.build index f1a7d0e..327d36f 100644 --- a/test cases/frameworks/1 boost/meson.build +++ b/test cases/frameworks/1 boost/meson.build @@ -2,6 +2,8 @@ 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 @@ -11,11 +13,14 @@ endif nolinkdep = dependency('boost', modules: 'utility') linkdep = dependency('boost', modules : ['thread', 'system']) testdep = dependency('boost', modules : 'test') +nomoddep = dependency('boost') nolinkexe = executable('nolinkedexe', 'nolinkexe.cc', dependencies : nolinkdep) linkexe = executable('linkedexe', 'linkexe.cc', dependencies : linkdep) unitexe = executable('utf', 'unit_test.cpp', dependencies: testdep) +nomodexe = executable('nomod', 'nomod.cpp', dependencies : nomoddep) test('Boost nolinktext', nolinkexe) test('Boost linktext', linkexe) test('Boost UTF test', unitexe) +test('Boost nomod', nomodexe) diff --git a/test cases/frameworks/1 boost/nomod.cpp b/test cases/frameworks/1 boost/nomod.cpp new file mode 100644 index 0000000..7b16881 --- /dev/null +++ b/test cases/frameworks/1 boost/nomod.cpp @@ -0,0 +1,18 @@ +#include<boost/any.hpp> +#include<iostream> + +boost::any get_any() { + boost::any foobar = 3; + return foobar; +} + +int main(int argc, char **argv) { + boost::any result = get_any(); + if(boost::any_cast<int>(result) == 3) { + std::cout << "Everything is fine in the worls.\n"; + return 0; + } else { + std::cout << "Mathematics stopped working.\n"; + return 1; + } +} diff --git a/tools/ac_converter.py b/tools/ac_converter.py new file mode 100755 index 0000000..150edb5 --- /dev/null +++ b/tools/ac_converter.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 + +# Copyright 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. +# 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. + +"""This script reads config.h.meson, looks for header +checks and writes the corresponding meson declaration. + +Copy config.h.in to config.h.meson, replace #undef +with #mesondefine and run this. We can't do this automatically +because some configure scripts have #undef statements +that are unrelated to configure checks. +""" + +import sys + +print('''cc = meson.get_compiler('c') +cdata = configuration_data()''') + +print('check_headers = [') + +for line in open(sys.argv[1]): + line = line.strip() + if line.startswith('#mesondefine') and \ + line.endswith('_H'): + token = line.split()[1] + tarr = token.split('_')[1:-1] + tarr = [x.lower() for x in tarr] + hname = '/'.join(tarr) + '.h' + print(" ['%s', '%s']," % (token, hname)) +print(']\n') + +print('''foreach h : check_headers + if cc.has_header(h.get(1)) + cdata.set(h.get(0), 1) + endif +endforeach +''') + +# Add stuff here as it is encountered. +function_data = \ + {'HAVE_FEENABLEEXCEPT' : ('feenableexcept', 'fenv.h'), + 'HAVE_FECLEAREXCEPT' : ('feclearexcept', 'fenv.h'), + 'HAVE_FEDISABLEEXCEPT' : ('fedisableexcept', 'fenv.h'), + 'HAVE_MMAP' : ('mmap', 'sys/mman.h'), + 'HAVE_GETPAGESIZE' : ('getpagesize', 'unistd.h'), + 'HAVE_GETISAX' : ('getisax', 'sys/auxv.h'), + 'HAVE_GETTIMEOFDAY' : ('gettimeofday', 'sys/time.h'), + 'HAVE_MPROTECT' : ('mprotect', 'sys/mman.h'), + 'HAVE_POSIX_MEMALIGN' : ('posix_memalign', 'stdlib.h'), + 'HAVE_SIGACTION' : ('sigaction', 'signal.h'), + 'HAVE_ALARM' : ('alarm', 'unistd.h'), + 'HAVE_CLOCK_GETTIME' : ('clock_gettime', 'time.h'), + 'HAVE_CTIME_R' : ('ctime_r', 'time.h'), + 'HAVE_DRAND48' : ('drand48', 'stdlib.h'), + 'HAVE_FLOCKFILE' : ('flockfile', 'stdio.h'), + 'HAVE_FORK' : ('fork', 'unistd.h'), + 'HAVE_FUNLOCKFILE' : ('funlockfile', 'stdio.h'), + 'HAVE_GETLINE' : ('getline', 'stdio.h'), + 'HAVE_LINK' : ('link', 'unistd.h'), + 'HAVE_RAISE' : ('raise', 'signal.h'), + 'HAVE_STRNDUP' : ('strndup', 'string.h'), + 'HAVE_SCHED_GETAFFINITY' : ('sched_getaffinity', 'sched.h'), + 'HAVE_WAITPID' : ('waitpid', 'sys/wait.h'), + 'HAVE_XRENDERCREATECONICALGRADIENT' : ('XRenderCreateConicalGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATELINEARGRADIENT' : ('XRenderCreateLinearGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATERADIALGRADIENT' : ('XRenderCreateRadialGradient', 'xcb/render.h'), + 'HAVE_XRENDERCREATESOLIDFILL' : ('XRenderCreateSolidFill', 'xcb/render.h'), + 'HAVE_DCGETTEXT': ('dcgettext', 'libintl.h'), + 'HAVE_ENDMNTENT': ('endmntent', 'mntent.h'), + 'HAVE_ENDSERVENT' : ('endservent', 'netdb.h'), + 'HAVE_EVENTFD': ('eventfd', 'sys/eventfd.h'), + 'HAVE_FALLOCATE': ('fallocate', 'fcntl.h'), + 'HAVE_FCHMOD': ('fchmod', 'sys/stat.h'), + 'HAVE_FCHOWN': ('fchown', 'unistd.h'), + 'HAVE_FDWALK': ('fdwalk', 'stdlib.h'), + 'HAVE_FSYNC': ('fsync', 'unistd.h'), + 'HAVE_GETC_UNLOCKED': ('getc_unlocked', 'stdio.h'), + 'HAVE_GETFSSTAT': ('getfsstat', 'sys/mount.h'), + 'HAVE_GETMNTENT_R': ('getmntent_r', 'mntent.h'), + 'HAVE_GETPROTOBYNAME_R': ('getprotobyname_r', 'netdb.h'), + 'HAVE_GETRESUID' : ('getresuid', 'unistd.h'), + 'HAVE_GETVFSSTAT' : ('getvfsstat', 'sys/statvfs.h'), + 'HAVE_GMTIME_R' : ('gmtime_r', 'time.h'), + 'HAVE_HASMNTOPT': ('hasmntopt', 'mntent.h'), + 'HAVE_IF_INDEXTONAME': ('if_indextoname', 'net/if.h'), + 'HAVE_IF_NAMETOINDEX': ('if_nametoindex', 'net/if.h'), + 'HAVE_INOTIFY_INIT1': ('inotify_init1', 'sys/inotify.h'), + 'HAVE_ISSETUGID': ('issetugid', 'unistd.h'), + 'HAVE_KEVENT': ('kevent', 'sys/event.h'), + 'HAVE_KQUEUE': ('kqueue', 'sys/event.h'), + 'HAVE_LCHMOD': ('lchmod', 'sys/stat.h'), + 'HAVE_LCHOWN': ('lchown', 'unistd.h'), + 'HAVE_LSTAT': ('lstat', 'sys/stat.h'), + 'HAVE_MEMCPY': ('memcpy', 'string.h'), + 'HAVE_MEMALIGN': ('memalign', 'stdlib.h'), + 'HAVE_MEMMEM': ('memmem', 'string.h'), + 'HAVE_NEWLOCALE': ('newlocale', 'locale.h'), + 'HAVE_PIPE2': ('pipe2', 'fcntl.h'), + 'HAVE_POLL': ('poll', 'poll.h'), + 'HAVE_PRLIMIT': ('prlimit', 'sys/resource.h'), + 'HAVE_PTHREAD_ATTR_SETSTACKSIZE': ('pthread_attr_setstacksize', 'pthread.h'), + 'HAVE_PTHREAD_CONDATTR_SETCLOCK': ('pthread_condattr_setclock', 'pthread.h'), + 'HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP': ('pthread_cond_timedwait_relative_np', 'pthread.h'), + 'HAVE_READLINK': ('readlink', 'unistd.h'), + 'HAVE_RES_INIT': ('res_init', 'resolv.h'), + 'HAVE_SENDMMSG': ('sendmmsg', 'sys/socket.h'), + 'HAVE_SETENV': ('setenv', 'stdlib.h'), + 'HAVE_SETMNTENT': ('setmntent', 'mntent.h'), + 'HAVE_SNPRINTF': ('snprintf', 'stdio.h'), + 'HAVE_SPLICE': ('splice', 'fcntl.h'), + 'HAVE_STATFS': ('statfs', 'mount.h'), + 'HAVE_STATVFS': ('statvfs', 'sys/statvfs.h'), + 'HAVE_STPCOPY': ('stpcopy', 'string.h'), + 'HAVE_STRCASECMP': ('strcasecmp', 'strings.h'), + 'HAVE_STRLCPY': ('strlcpy', 'string.h'), + 'HAVE_STRNCASECMP': ('strncasecmp', 'strings.h'), + 'HAVE_STRSIGNAL': ('strsignal', 'signal.h'), + 'HAVE_STRTOD_L': ('strtod_l', 'stdlib.h'), + 'HAVE_STRTOLL_L': ('strtoll_l', 'stdlib.h'), + 'HAVE_STRTOULL_L': ('strtoull_l', 'stdlib.h'), + 'HAVE_SYMLINK': ('symlink', 'unistd.h'), + 'HAVE_SYSCTLBYNAME': ('sysctlbyname', 'sys/sysctl.h'), + 'HAVE_TIMEGM': ('timegm', 'time.h'), + 'HAVE_UNSETENV': ('unsetenv', 'stdlib.h'), + 'HAVE_USELOCALE': ('uselocale', 'xlocale.h'), + 'HAVE_UTIMES': ('utimes', 'sys/time.h'), + 'HAVE_VALLOC': ('valloc', 'stdlib.h'), + 'HAVE_VASPRINTF': ('vasprintf', 'stdio.h'), + 'HAVE_VSNPRINTF': ('vsnprintf', 'stdio.h'), + 'HAVE_BCOPY': ('bcopy', 'strings.h'), + 'HAVE_STRERROR': ('strerror', 'string.h'), + 'HAVE_MEMMOVE': ('memmove', 'string.h'), + 'HAVE_STRTOIMAX': ('strtoimax', 'inttypes.h'), + 'HAVE_STRTOLL': ('strtoll', 'stdlib.h'), + 'HAVE_STRTOQ': ('strtoq', 'stdlib.h'), + 'HAVE_ACCEPT4': ('accept4', 'sys/socket.h'), + 'HAVE_CHMOD': ('chmod', 'sys/stat.h'), + 'HAVE_CHOWN': ('chown', 'unistd.h'), + 'HAVE_FSTAT': ('fstat', 'sys/stat.h'), + 'HAVE_GETADDRINFO': ('getaddrinfo', 'netdb.h'), + 'HAVE_GETGRGID_R': ('getgrgid_r', 'grp.h'), + 'HAVE_GETGRNAM_R': ('getgrnam_r', 'grp.h'), + 'HAVE_GETGROUPS': ('getgroups', 'grp.h'), + 'HAVE_GETOPT_LONG': ('getopt_long', 'getopt.h'), + 'HAVE_GETPWNAM_R': ('getpwnam', 'pwd.h'), + 'HAVE_GETPWUID_R': ('getpwuid_r', 'pwd.h'), + 'HAVE_GETUID': ('getuid', 'unistd.h'), + 'HAVE_LRINTF': ('lrintf', 'math.h'), + 'HAVE_MKFIFO': ('mkfifo', 'sys/stat.h'), + 'HAVE_MLOCK': ('mlock', 'sys/mman.h'), + 'HAVE_NANOSLEEP': ('nanosleep', 'time.h'), + 'HAVE_PIPE': ('pipe', 'unistd.h'), + 'HAVE_PPOLL': ('ppoll', 'poll.h'), + 'HAVE_REGEXEC': ('regexec', 'regex.h'), + 'HAVE_SETEGID': ('setegid', 'unistd.h'), + 'HAVE_SETEUID': ('seteuid', 'unistd.h'), + 'HAVE_SETPGID': ('setpgid', 'unistd.h'), + 'HAVE_SETREGID': ('setregid', 'unistd.h'), + 'HAVE_SETRESGID': ('setresgid', 'unistd.h'), + 'HAVE_SETRESUID': ('setresuid', 'unistd.h'), + 'HAVE_SHM_OPEN': ('shm_open', 'fcntl.h'), + 'HAVE_SLEEP': ('sleep', 'unistd.h'), + 'HAVE_STRERROR_R': ('strerror_r', 'string.h'), + 'HAVE_STRTOF': ('strtof', 'stdlib.h'), + 'HAVE_SYSCONF': ('sysconf', 'unistd.h'), + 'HAVE_USLEEP': ('usleep', 'unistd.h'), + 'HAVE_VFORK': ('vfork', 'unistd.h'), + } + +print('check_functions = [') + +for line in open(sys.argv[1]): + try: + token = line.split()[1] + if token in function_data: + fdata = function_data[token] + print(" ['%s', '%s', '#include<%s>']," % (token, fdata[0], fdata[1])) + elif token.startswith('HAVE_') and not token.endswith('_H'): + print('# check token', token) + except Exception: + pass +print(']\n') + +print('''foreach f : check_functions + if cc.has_function(f.get(1), prefix : f.get(2)) + cdata.set(f.get(0), 1) + endif +endforeach +''') + +# Convert sizeof checks. + +for line in open(sys.argv[1]): + arr = line.strip().split() + if len(arr) != 2: + continue + elem = arr[1] + if elem.startswith('SIZEOF_'): + typename = elem.split('_', 1)[1].replace('_P', '*').replace('_', ' ').lower().replace('size t', 'size_t') + print("cdata.set('%s', cc.sizeof('%s'))" % (elem, typename)) + +print(''' +configure_file(input : 'config.h.in', + output : 'config.h', + configuration : cdata)''') diff --git a/tools/autotools2meson.py b/tools/autotools2meson.py deleted file mode 100755 index 1ec1348..0000000 --- a/tools/autotools2meson.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/python3 - -# Copyright 2014 Jussi Pakkanen - -# 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, re - -class Converter(): - def __init__(self, root): - self.project_root = root - - def readlines(self, file, continuator): - line = file.readline() - while line != '': - line = line.rstrip() - while line.endswith(continuator): - line = line[:-1] + file.readline().rstrip() - yield line - line = file.readline() - - def convert(self, subdir=None): - if subdir is None: - subdir = self.project_root - try: - ifile = open(os.path.join(subdir, 'Makefile.am')) - except FileNotFoundError: - print('Makefile.am not found in subdir', subdir) - return - ofile = open(os.path.join(subdir, 'meson.build'), 'w') - if subdir == self.project_root: - self.process_autoconf(ofile, subdir) - for line in self.readlines(ifile, '\\'): - items = line.strip().split() - if len(items) == 0: - ofile.write('\n') - continue - if items[0] == 'SUBDIRS': - for i in items[2:]: - if i != '.': - ofile.write("subdir('%s')\n" % i) - self.convert(os.path.join(subdir, i)) - elif items[0].endswith('_SOURCES'): - self.convert_target(ofile, items) - else: - ofile.write("# %s\n" % line) - - def convert_target(self, ofile, items): - if items[0].endswith('la_SOURCES'): - func = 'shared_library' - tname = "'%s'" % items[0][:-11] - elif items[0].endswith('a_SOURCES'): - func = 'static_library' - tname = "'%s'" % items[0][:-10] - else: - func = 'executable' - tname = "'%s'" % items[0][:-8] - sources = [tname] - for s in items[2:]: - if s.startswith('$(') and s.endswith(')'): - s = s[2:-1] - else: - s = "'%s'" % s - sources.append(s) - ofile.write('%s(%s)\n' % (func, ',\n'.join(sources))) - - def process_autoconf(self, ofile, subdir): - ifile = open(os.path.join(subdir, 'configure.ac')) - languages = [] - name = 'undetected' - outlines = [] - for line in self.readlines(ifile, ','): - line = line.strip() - if line == 'AC_PROG_CC': - languages.append("'c'") - elif line == 'AC_PROG_CXX': - languages.append("'cpp'") - elif line.startswith('AC_INIT'): - line = line[8:] - if line[0] == '[': - name = line.split(']')[0][1:] - else: - name = line.split()[0] - elif line.startswith('#'): - outlines.append(line + '\n') - elif line.startswith('PKG_CHECK_MODULES'): - rest = line.split('(', 1)[-1].strip() - pkgstanza = rest.split()[1:] - for i in pkgstanza: - i = i.strip() - dep = None - if '=' in i: - continue - if i.startswith('['): - dep = i[1:] - elif re.match('[a-zA-Z]', i): - dep = i - if dep is not None: - outlines.append("%s_dep = dependency('%s')\n" % (dep, dep)) - else: - outlines.append('# %s\n' % line) - ofile.write("project(%s)\n" % ', '.join(["'%s'" % name] + languages)) - ofile.writelines(outlines) - - -if __name__ == '__main__': - if len(sys.argv) != 2: - print(sys.argv[0], '<Autotools project root>') - sys.exit(1) - c = Converter(sys.argv[1]) - c.convert() diff --git a/tools/cmake2meson.py b/tools/cmake2meson.py index f1720a8..098a6e0 100755 --- a/tools/cmake2meson.py +++ b/tools/cmake2meson.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 # Copyright 2014 Jussi Pakkanen |