aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py2
-rw-r--r--mesonbuild/compilers.py133
-rw-r--r--mesonbuild/dependencies.py32
-rw-r--r--mesonbuild/interpreter.py14
-rw-r--r--test cases/vala/13 find library/meson.build9
-rw-r--r--test cases/vala/13 find library/test.vala6
-rw-r--r--test cases/vala/4 config/meson-something-else.vapi1
-rw-r--r--test cases/vala/4 config/meson.build8
-rw-r--r--test cases/vala/4 config/prog.vala1
9 files changed, 133 insertions, 73 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 76f47ab..bb681d7 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1045,6 +1045,8 @@ int dummy;
and d.version_requirement.startswith(('>=', '==')):
args += ['--target-glib', d.version_requirement[2:]]
args += ['--pkg', d.name]
+ elif isinstance(d, dependencies.ExternalLibrary):
+ args += d.get_lang_args('vala')
extra_args = []
for a in target.extra_args.get('vala', []):
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 9b76f29..1505807 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -430,6 +430,51 @@ class Compiler():
extra_flags += environment.cross_info.config['properties'].get(lang_link_args_key, [])
return extra_flags
+ @contextlib.contextmanager
+ def compile(self, code, extra_args=None):
+ if extra_args is None:
+ extra_args = []
+
+ try:
+ with tempfile.TemporaryDirectory() as tmpdirname:
+ if isinstance(code, str):
+ srcname = os.path.join(tmpdirname,
+ 'testfile.' + self.default_suffix)
+ with open(srcname, 'w') as ofile:
+ ofile.write(code)
+ elif isinstance(code, mesonlib.File):
+ srcname = code.fname
+
+ # Extension only matters if running results; '.exe' is
+ # guaranteed to be executable on every platform.
+ output = os.path.join(tmpdirname, 'output.exe')
+
+ commands = self.get_exelist()
+ commands.append(srcname)
+ commands += extra_args
+ commands += self.get_output_args(output)
+ mlog.debug('Running compile:')
+ mlog.debug('Working directory: ', tmpdirname)
+ mlog.debug('Command line: ', ' '.join(commands), '\n')
+ mlog.debug('Code:\n', code)
+ p = subprocess.Popen(commands, cwd=tmpdirname,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ (stde, stdo) = p.communicate()
+ stde = stde.decode()
+ stdo = stdo.decode()
+ mlog.debug('Compiler stdout:\n', stdo)
+ mlog.debug('Compiler stderr:\n', stde)
+
+ p.input_name = srcname
+ p.output_name = output
+ yield p
+ except (PermissionError, OSError):
+ # On Windows antivirus programs and the like hold on to files so
+ # they can't be deleted. There's not much to do in this case. Also,
+ # catch OSError because the directory is then no longer empty.
+ pass
+
def get_colorout_args(self, colortype):
return []
@@ -659,51 +704,6 @@ int main () {{
args = extra_args + self.get_compiler_check_args()
return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies)
- @contextlib.contextmanager
- def compile(self, code, extra_args=None):
- if extra_args is None:
- extra_args = []
-
- try:
- with tempfile.TemporaryDirectory() as tmpdirname:
- if isinstance(code, str):
- srcname = os.path.join(tmpdirname,
- 'testfile.' + self.default_suffix)
- with open(srcname, 'w') as ofile:
- ofile.write(code)
- elif isinstance(code, mesonlib.File):
- srcname = code.fname
-
- # Extension only matters if running results; '.exe' is
- # guaranteed to be executable on every platform.
- output = os.path.join(tmpdirname, 'output.exe')
-
- commands = self.get_exelist()
- commands.append(srcname)
- commands += extra_args
- commands += self.get_output_args(output)
- mlog.debug('Running compile:')
- mlog.debug('Working directory: ', tmpdirname)
- mlog.debug('Command line: ', ' '.join(commands), '\n')
- mlog.debug('Code:\n', code)
- p = subprocess.Popen(commands, cwd=tmpdirname,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- (stde, stdo) = p.communicate()
- stde = stde.decode()
- stdo = stdo.decode()
- mlog.debug('Compiler stdout:\n', stdo)
- mlog.debug('Compiler stderr:\n', stde)
-
- p.input_name = srcname
- p.output_name = output
- yield p
- except (PermissionError, OSError):
- # On Windows antivirus programs and the like hold on to files so
- # they can't be deleted. There's not much to do in this case. Also,
- # catch OSError because the directory is then no longer empty.
- pass
-
def compiles(self, code, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
@@ -1330,27 +1330,48 @@ class ValaCompiler(Compiler):
def needs_static_linker(self):
return False # Because compiles into C.
+ def get_output_args(self, target):
+ return ['-o', target]
+
def get_werror_args(self):
return ['--fatal-warnings']
def sanity_check(self, work_dir, environment):
- src = 'valatest.vala'
- source_name = os.path.join(work_dir, src)
- with open(source_name, 'w') as ofile:
- ofile.write('''class SanityCheck : Object {
-}
-''')
- extra_flags = self.get_cross_extra_flags(environment, compile=True, link=False)
- pc = subprocess.Popen(self.exelist + extra_flags + ['-C', '-c', src], cwd=work_dir)
- pc.wait()
- if pc.returncode != 0:
- raise EnvironmentException('Vala compiler %s can not compile programs.' % self.name_string())
+ code = 'class MesonSanityCheck : Object { }'
+ args = self.get_cross_extra_flags(environment, compile=True, link=False)
+ args += ['-C']
+ with self.compile(code, args) as p:
+ if p.returncode != 0:
+ msg = 'Vala compiler {!r} can not compile programs' \
+ ''.format(self.name_string())
+ raise EnvironmentException(msg)
def get_buildtype_args(self, buildtype):
if buildtype == 'debug' or buildtype == 'debugoptimized' or buildtype == 'minsize':
return ['--debug']
return []
+ def find_library(self, libname, env, extra_dirs):
+ if extra_dirs and isinstance(extra_dirs, str):
+ extra_dirs = [extra_dirs]
+ # Valac always looks in the default vapi dir, so only search there if
+ # no extra dirs are specified.
+ if len(extra_dirs) == 0:
+ code = 'class MesonFindLibrary : Object { }'
+ vapi_args = ['--pkg', libname]
+ args = self.get_cross_extra_flags(env, compile=True, link=False)
+ args += ['-C'] + vapi_args
+ with self.compile(code, args) as p:
+ if p.returncode == 0:
+ return vapi_args
+ # Not found? Try to find the vapi file itself.
+ for d in extra_dirs:
+ vapi = os.path.join(d, libname + '.vapi')
+ if os.path.isfile(vapi):
+ return vapi
+ mlog.debug('Searched {!r} and {!r} wasn\'t found'.format(extra_dirs, libname))
+ return None
+
class RustCompiler(Compiler):
def __init__(self, exelist, version):
self.language = 'rust'
diff --git a/mesonbuild/dependencies.py b/mesonbuild/dependencies.py
index 8a1ff16..d336c21 100644
--- a/mesonbuild/dependencies.py
+++ b/mesonbuild/dependencies.py
@@ -455,29 +455,37 @@ class ExternalProgram():
return self.name
class ExternalLibrary(Dependency):
- def __init__(self, name, link_args=None, silent=False):
+ # TODO: Add `lang` to the parent Dependency object so that dependencies can
+ # be expressed for languages other than C-like
+ def __init__(self, name, link_args=None, language=None, silent=False):
super().__init__('external')
self.name = name
- # Rename fullpath to link_args once standalone find_library() gets removed.
- if link_args is not None:
- if isinstance(link_args, list):
- self.link_args = link_args
+ self.is_found = False
+ self.link_args = []
+ self.lang_args = []
+ if link_args:
+ self.is_found = True
+ if not isinstance(link_args, list):
+ link_args = [link_args]
+ if language:
+ self.lang_args = {language: link_args}
else:
- self.link_args = [link_args]
- else:
- self.link_args = link_args
+ self.link_args = link_args
if not silent:
- if self.found():
+ if self.is_found:
mlog.log('Library', mlog.bold(name), 'found:', mlog.green('YES'))
else:
mlog.log('Library', mlog.bold(name), 'found:', mlog.red('NO'))
def found(self):
- return self.link_args is not None
+ return self.is_found
def get_link_args(self):
- if self.found():
- return self.link_args
+ return self.link_args
+
+ def get_lang_args(self, lang):
+ if lang in self.lang_args:
+ return self.lang_args[lang]
return []
class BoostDependency(Dependency):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 33587a4..f8af82e 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -944,9 +944,17 @@ class CompilerHolder(InterpreterObject):
if not os.path.isabs(i):
raise InvalidCode('Search directory %s is not an absolute path.' % i)
linkargs = self.compiler.find_library(libname, self.environment, search_dirs)
- if required and linkargs is None:
- raise InterpreterException('Library {} not found'.format(libname))
- lib = dependencies.ExternalLibrary(libname, linkargs)
+ if required and not linkargs:
+ l = self.compiler.language.capitalize()
+ raise InterpreterException('{} library {!r} not found'.format(l, libname))
+ # If this is set to None, the library and link arguments are for
+ # a C-like compiler. Otherwise, it's for some other language that has
+ # a find_library implementation. We do this because it's easier than
+ # maintaining a list of languages that can consume C libraries.
+ lang = None
+ if self.compiler.language == 'vala':
+ lang = 'vala'
+ lib = dependencies.ExternalLibrary(libname, linkargs, language=lang)
return ExternalLibraryHolder(lib)
def has_argument_method(self, args, kwargs):
diff --git a/test cases/vala/13 find library/meson.build b/test cases/vala/13 find library/meson.build
new file mode 100644
index 0000000..03054d2
--- /dev/null
+++ b/test cases/vala/13 find library/meson.build
@@ -0,0 +1,9 @@
+project('find vala library', 'vala', 'c')
+
+valac = meson.get_compiler('vala')
+
+gobject = dependency('gobject-2.0')
+zlib = valac.find_library('zlib')
+
+e = executable('zlibtest', 'test.vala', dependencies : [gobject, zlib])
+test('testzlib', e)
diff --git a/test cases/vala/13 find library/test.vala b/test cases/vala/13 find library/test.vala
new file mode 100644
index 0000000..b087cfb
--- /dev/null
+++ b/test cases/vala/13 find library/test.vala
@@ -0,0 +1,6 @@
+using ZLib;
+
+public static int main(string[] args) {
+ stdout.printf("ZLIB_VERSION is: %s\n", ZLib.VERSION.STRING);
+ return 0;
+}
diff --git a/test cases/vala/4 config/meson-something-else.vapi b/test cases/vala/4 config/meson-something-else.vapi
new file mode 100644
index 0000000..ce2b83a
--- /dev/null
+++ b/test cases/vala/4 config/meson-something-else.vapi
@@ -0,0 +1 @@
+public const string SOMETHING_ELSE;
diff --git a/test cases/vala/4 config/meson.build b/test cases/vala/4 config/meson.build
index 9436e41..7cb93cf 100644
--- a/test cases/vala/4 config/meson.build
+++ b/test cases/vala/4 config/meson.build
@@ -1,11 +1,15 @@
project('valatest', 'vala', 'c')
-valadeps = [dependency('glib-2.0'), dependency('gobject-2.0')]
+valac = meson.get_compiler('vala')
+# Try to find our library
+valadeps = [valac.find_library('meson-something-else', dirs : meson.current_source_dir())]
+valadeps += [dependency('glib-2.0'), dependency('gobject-2.0')]
e = executable(
'valaprog',
sources : ['config.vapi', 'prog.vala'],
dependencies : valadeps,
-c_args : '-DDATA_DIRECTORY="@0@"'.format(meson.current_source_dir())
+c_args : ['-DDATA_DIRECTORY="@0@"'.format(meson.current_source_dir()),
+ '-DSOMETHING_ELSE="Out of this world!"']
)
test('valatest', e)
diff --git a/test cases/vala/4 config/prog.vala b/test cases/vala/4 config/prog.vala
index 7ab600c..2b08dad 100644
--- a/test cases/vala/4 config/prog.vala
+++ b/test cases/vala/4 config/prog.vala
@@ -2,6 +2,7 @@ class MainProg : GLib.Object {
public static int main(string[] args) {
stdout.printf("DATA_DIRECTORY is: %s.\n", DATA_DIRECTORY);
+ stdout.printf("SOMETHING_ELSE is: %s.\n", SOMETHING_ELSE);
return 0;
}
}