aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authors.txt1
-rw-r--r--backends.py2
-rw-r--r--compilers.py169
-rw-r--r--coredata.py5
-rw-r--r--cross/iphone.txt26
-rw-r--r--cross/ubuntu-armhf.txt8
-rw-r--r--dependencies.py80
-rw-r--r--environment.py16
-rw-r--r--interpreter.py9
-rw-r--r--man/meson.12
-rw-r--r--man/mesonconf.12
-rw-r--r--man/mesongui.12
-rw-r--r--man/mesonintrospect.12
-rw-r--r--man/wraptool.12
-rwxr-xr-xmeson.py11
-rwxr-xr-xmesonconf.py7
-rw-r--r--mesonlib.py13
-rw-r--r--ninjabackend.py112
-rw-r--r--test cases/common/58 run target/helloprinter.c10
-rw-r--r--test cases/common/58 run target/meson.build6
-rw-r--r--test cases/failing/19 target clash/clash.c6
-rw-r--r--test cases/failing/19 target clash/meson.build15
-rw-r--r--test cases/frameworks/1 boost/meson.build5
-rw-r--r--test cases/frameworks/1 boost/nomod.cpp18
-rwxr-xr-xtools/ac_converter.py217
-rwxr-xr-xtools/autotools2meson.py122
-rwxr-xr-xtools/cmake2meson.py2
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
diff --git a/meson.py b/meson.py
index 6ca59de..da7b12f 100755
--- a/meson.py
+++ b/meson.py
@@ -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