diff options
21 files changed, 224 insertions, 13 deletions
diff --git a/docs/markdown/Vala.md b/docs/markdown/Vala.md index 259ebd1..7674cf3 100644 --- a/docs/markdown/Vala.md +++ b/docs/markdown/Vala.md @@ -36,9 +36,31 @@ foo_dep = dependency('foo') # 'foo.vapi' will be resolved in './vapi/foo.vapi' executable('app', 'app.vala', dependencies: [glib_dep, gobject_dep, foo_dep]) ``` +In this case, make sure that the VAPI name corresponds to the pkg-config file. + +If no pkg-config file is provided, you must use `find_library`. Using`declare_dependency` is cleaner because it does not require passing both dependency objects to the target. + +```meson +foo_lib = meson.get_compiler('c').find_library('foo') # assuming libfoo.so is installed +foo_vapi = meson.get_compiler('vala').find_library('foo', dirs: join_paths(meson.current_source_dir(), 'vapi') +foo_dep = declare_dependency(dependencies: [foo_lib, foo_vapi]) + +executable('app', 'app.vala', dependencies: [glib_dep, gobject_dep, foo_dep]) +``` + +## VAPI without pkg-config file + +Some Vala bindings do not need a corresponding pkg-config file and `dependency` is unsuitable for resolving them. It's necessary to use `find_library` in this case. + +```meson +posix_dep = meson.get_compiler('vala').find_library('posix') + +executable('app', 'app.vala', dependencies: [glib_dep, gobject_dep, posix_dep]) +``` + ## Custom output names -If a library target is used, Meson automatically output the C header and the VAPI. They can be renamed by setting the `vala_header` and `vala_vapi` arguments respectively. In this case, the second and third elements of the `install_dir` array indicate the destination with `true` to indicate default directories. +If a library target is used, Meson automatically outputs the C header and the VAPI. They can be renamed by setting the `vala_header` and `vala_vapi` arguments respectively. In this case, the second and third elements of the `install_dir` array indicate the destination with `true` to indicate default directories (i.e. `include` and `share/vala/vapi`). ```meson foo_lib = library('foo', 'foo.vala', diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 5727248..de03db4 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -20,7 +20,7 @@ from .. import mlog from .. import dependencies from .. import compilers from ..compilers import CompilerArgs -from ..mesonlib import File, MesonException +from ..mesonlib import File, MesonException, OrderedSet from ..mesonlib import get_meson_script, get_compiler_for_source, Popen_safe from .backends import CleanTrees, InstallData from ..build import InvalidArguments @@ -233,6 +233,9 @@ int dummy; for src in genlist.get_outputs(): if self.environment.is_header(src): header_deps.append(self.get_target_generated_dir(target, genlist, src)) + if 'vala' in target.compilers and not isinstance(target, build.Executable): + vala_header = File.from_built_file(self.get_target_dir(target), target.vala_header) + header_deps.append(vala_header) # Recurse and find generated headers for dep in target.link_targets: if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): @@ -985,7 +988,7 @@ int dummy; the same name as the BuildTarget and return the path to it relative to the build directory. """ - result = [] + result = OrderedSet() for dep in target.link_targets: for i in dep.sources: if hasattr(i, 'fname'): @@ -993,9 +996,9 @@ int dummy; if i.endswith('vala'): vapiname = dep.name + '.vapi' fullname = os.path.join(self.get_target_dir(dep), vapiname) - result.append(fullname) + result.add(fullname) break - return result + return list(result) def split_vala_sources(self, t): """ @@ -1093,7 +1096,7 @@ int dummy; args += ['--library=' + target.name] # Outputted header hname = os.path.join(self.get_target_dir(target), target.vala_header) - args += ['-H', hname] + args += ['-H', hname, '--use-header'] valac_outputs.append(hname) # Outputted vapi file vapiname = os.path.join(self.get_target_dir(target), target.vala_vapi) @@ -1707,12 +1710,13 @@ rule FORTRAN_DEP_HACK modre = re.compile(r"\s*module\s+(\w+)", re.IGNORECASE) module_files = {} for s in target.get_sources(): - # FIXME, does not work for generated Fortran sources, - # but those are really rare. I hope. + # FIXME, does not work for Fortran sources generated by + # custom_target() and generator() as those are run after + # the configuration (configure_file() is OK) if not compiler.can_compile(s): continue - filename = os.path.join(self.environment.get_source_dir(), - s.subdir, s.fname) + filename = s.absolute_path(self.environment.get_source_dir(), + self.environment.get_build_dir()) with open(filename) as f: for line in f: modmatch = modre.match(line) @@ -2182,6 +2186,9 @@ rule FORTRAN_DEP_HACK if isinstance(target, build.Executable): # Currently only used with the Swift compiler to add '-emit-executable' commands += linker.get_std_exe_link_args() + # If gui_app, and that's significant on this platform + if target.gui_app and hasattr(linker, 'get_gui_app_args'): + commands += linker.get_gui_app_args() elif isinstance(target, build.SharedLibrary): if isinstance(target, build.SharedModule): commands += linker.get_std_shared_module_link_args() diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 199bbab..fa06ae9 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -2461,6 +2461,10 @@ class GnuCompiler: # For other targets, discard the .def file. return [] + def get_gui_app_args(self): + if self.gcc_type in (GCC_CYGWIN, GCC_MINGW): + return ['-mwindows'] + return [] class GnuCCompiler(GnuCompiler, CCompiler): def __init__(self, exelist, version, gcc_type, is_cross, exe_wrapper=None, defines=None): diff --git a/run_project_tests.py b/run_project_tests.py index b8ef0e9..ab8e3ae 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -34,6 +34,7 @@ import time import multiprocessing import concurrent.futures as conc import re +from run_unittests import get_fake_options from run_tests import get_backend_commands, get_backend_args_for_dir, Backend from run_tests import ensure_backend_detects_changes @@ -416,6 +417,25 @@ def have_d_compiler(): return True return False +def have_objc_compiler(): + with AutoDeletedDir(tempfile.mkdtemp(prefix='b ', dir='.')) as build_dir: + env = environment.Environment(None, build_dir, None, get_fake_options('/'), []) + objc_comp = env.detect_objc_compiler(False) + if not objc_comp: + return False + try: + objc_comp.sanity_check(env.get_scratch_dir(), env) + except: + return False + objcpp_comp = env.detect_objc_compiler(False) + if not objcpp_comp: + return False + try: + objcpp_comp.sanity_check(env.get_scratch_dir(), env) + except: + return False + return True + def have_java(): if shutil.which('javac') and shutil.which('java'): return True @@ -440,7 +460,7 @@ def detect_tests_to_run(): ('vala', 'vala', backend is not Backend.ninja or not shutil.which('valac')), ('rust', 'rust', backend is not Backend.ninja or not shutil.which('rustc')), ('d', 'd', backend is not Backend.ninja or not have_d_compiler()), - ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows()), + ('objective c', 'objc', backend not in (Backend.ninja, Backend.xcode) or mesonlib.is_windows() or not have_objc_compiler()), ('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')), ('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')), ('python3', 'python3', backend is not Backend.ninja or not shutil.which('python3')), diff --git a/test cases/fortran/5 static/meson.build b/test cases/fortran/5 static/meson.build index bd74a29..ab9d3c4 100644 --- a/test cases/fortran/5 static/meson.build +++ b/test cases/fortran/5 static/meson.build @@ -2,4 +2,5 @@ project('try-static-library', 'fortran') static_hello = static_library('static_hello', 'static_hello.f90') -executable('test_exe', 'main.f90', link_with : static_hello) +exe = executable('test_exe', 'main.f90', link_with : static_hello) +test('static-fortran', exe) diff --git a/test cases/fortran/6 dynamic/meson.build b/test cases/fortran/6 dynamic/meson.build index c791dac..e5e259f 100644 --- a/test cases/fortran/6 dynamic/meson.build +++ b/test cases/fortran/6 dynamic/meson.build @@ -1,4 +1,5 @@ project('dynamic_fortran', 'fortran') dynamic = shared_library('dynamic', 'dynamic.f90') -executable('test_exe', 'main.f90', link_with : dynamic) +exe = executable('test_exe', 'main.f90', link_with : dynamic) +test('dynamic-fortran', exe) diff --git a/test cases/fortran/7 generated/meson.build b/test cases/fortran/7 generated/meson.build new file mode 100644 index 0000000..c2efe34 --- /dev/null +++ b/test cases/fortran/7 generated/meson.build @@ -0,0 +1,22 @@ +# Tests whether fortran sources files created during configuration are properly +# scanned for dependency information + +project('generated', 'fortran') + +conf_data = configuration_data() +conf_data.set('ONE', 1) +conf_data.set('TWO', 2) + +templates_basenames = ['mod2', 'mod1'] +generated_sources = [] +foreach template_basename : templates_basenames + infilename = '@0@.fpp'.format(template_basename) + outfilename = '@0@.f90'.format(template_basename) + outfile = configure_file( + input : infilename, output : outfilename, configuration : conf_data) + generated_sources += [outfile] +endforeach + +sources = ['prog.f90'] + generated_sources +exe = executable('generated', sources) +test('generated', exe) diff --git a/test cases/fortran/7 generated/mod1.fpp b/test cases/fortran/7 generated/mod1.fpp new file mode 100644 index 0000000..42d1fde --- /dev/null +++ b/test cases/fortran/7 generated/mod1.fpp @@ -0,0 +1,6 @@ +module mod1 + implicit none + + integer, parameter :: modval1 = @ONE@ + +end module mod1 diff --git a/test cases/fortran/7 generated/mod2.fpp b/test cases/fortran/7 generated/mod2.fpp new file mode 100644 index 0000000..594e9df --- /dev/null +++ b/test cases/fortran/7 generated/mod2.fpp @@ -0,0 +1,7 @@ +module mod2 + use mod1 + implicit none + + integer, parameter :: modval2 = @TWO@ + +end module mod2 diff --git a/test cases/fortran/7 generated/prog.f90 b/test cases/fortran/7 generated/prog.f90 new file mode 100644 index 0000000..c476e9c --- /dev/null +++ b/test cases/fortran/7 generated/prog.f90 @@ -0,0 +1,9 @@ +program prog + use mod2 + implicit none + + if (modval1 + modval2 /= 3) then + stop 1 + end if + +end program prog diff --git a/test cases/vala/16 mixed dependence/app.vala b/test cases/vala/16 mixed dependence/app.vala new file mode 100644 index 0000000..5b54543 --- /dev/null +++ b/test cases/vala/16 mixed dependence/app.vala @@ -0,0 +1,7 @@ +namespace App { + public static int main(string[] args) { + var mixer = new Mixer(); + print("Current volume is %u\n", mixer.get_volume()); + return 0; + } +} diff --git a/test cases/vala/16 mixed dependence/meson.build b/test cases/vala/16 mixed dependence/meson.build new file mode 100644 index 0000000..e6967be --- /dev/null +++ b/test cases/vala/16 mixed dependence/meson.build @@ -0,0 +1,12 @@ +project('mixed dependence', 'vala', 'c') + +deps = [dependency('glib-2.0'), dependency('gobject-2.0')] + +mixer = static_library('mixer', 'mixer.vala', 'mixer-glue.c', + dependencies : deps) + +app = executable('app', 'app.vala', + link_with : mixer, + dependencies : deps) + +test('valamixeddependencetest', app) diff --git a/test cases/vala/16 mixed dependence/mixer-glue.c b/test cases/vala/16 mixed dependence/mixer-glue.c new file mode 100644 index 0000000..d6c0c37 --- /dev/null +++ b/test cases/vala/16 mixed dependence/mixer-glue.c @@ -0,0 +1,5 @@ +#include "mixer.h" + +guint mixer_get_volume(Mixer *mixer) { + return 11; +} diff --git a/test cases/vala/16 mixed dependence/mixer.vala b/test cases/vala/16 mixed dependence/mixer.vala new file mode 100644 index 0000000..f207132 --- /dev/null +++ b/test cases/vala/16 mixed dependence/mixer.vala @@ -0,0 +1,3 @@ +public class Mixer : Object { + public extern uint get_volume(); +} diff --git a/test cases/vala/17 plain consumer/app.c b/test cases/vala/17 plain consumer/app.c new file mode 100644 index 0000000..c8d0010 --- /dev/null +++ b/test cases/vala/17 plain consumer/app.c @@ -0,0 +1,11 @@ +#include "badger.h" + +int main(int argc, char *argv[]) { + Badger *badger; + + badger = g_object_new(TYPE_BADGER, NULL); + g_print("Badger whose name is '%s'\n", badger_get_name(badger)); + g_object_unref(badger); + + return 0; +} diff --git a/test cases/vala/17 plain consumer/badger.vala b/test cases/vala/17 plain consumer/badger.vala new file mode 100644 index 0000000..1aaeda6 --- /dev/null +++ b/test cases/vala/17 plain consumer/badger.vala @@ -0,0 +1,10 @@ +public class Badger : Object { + public string name { + get; + construct; + } + + Badger() { + Object(name: "Joe"); + } +} diff --git a/test cases/vala/17 plain consumer/meson.build b/test cases/vala/17 plain consumer/meson.build new file mode 100644 index 0000000..e98bca1 --- /dev/null +++ b/test cases/vala/17 plain consumer/meson.build @@ -0,0 +1,12 @@ +project('plain consumer', 'vala', 'c') + +deps = [dependency('glib-2.0'), dependency('gobject-2.0')] + +badger = static_library('badger', 'badger.vala', + dependencies : deps) + +app = executable('app', 'app.c', + link_with : badger, + dependencies : deps) + +test('valaplainconsumertest', app) diff --git a/test cases/vala/18 vapi consumed twice/app.vala b/test cases/vala/18 vapi consumed twice/app.vala new file mode 100644 index 0000000..cd94a42 --- /dev/null +++ b/test cases/vala/18 vapi consumed twice/app.vala @@ -0,0 +1,11 @@ +namespace App { + public static int main(string[] args) { + var person = new Person(); + print("Favorite beer of \"%s\" is %s\n", person.name, person.favorite_beer.flavor); + + var beer = new Beer("tasty"); + print("This beer is %s\n", beer.flavor); + + return 0; + } +} diff --git a/test cases/vala/18 vapi consumed twice/beer.vala b/test cases/vala/18 vapi consumed twice/beer.vala new file mode 100644 index 0000000..cee38ad --- /dev/null +++ b/test cases/vala/18 vapi consumed twice/beer.vala @@ -0,0 +1,10 @@ +public class Beer : Object { + public string flavor { + get; + construct; + } + + public Beer(string flavor) { + Object(flavor: flavor); + } +} diff --git a/test cases/vala/18 vapi consumed twice/meson.build b/test cases/vala/18 vapi consumed twice/meson.build new file mode 100644 index 0000000..6a7f5eb --- /dev/null +++ b/test cases/vala/18 vapi consumed twice/meson.build @@ -0,0 +1,15 @@ +project('vapi consumed twice', 'vala', 'c') + +base_deps = [dependency('glib-2.0'), dependency('gobject-2.0')] + +beer = library('beer', 'beer.vala', dependencies : base_deps) +beer_dep = declare_dependency(link_with : beer) + +person = library('person', 'person.vala', link_with : beer, + dependencies : base_deps) +person_dep = declare_dependency(link_with : person, dependencies : [beer_dep]) + +app = executable('app', 'app.vala', + dependencies : base_deps + [person_dep, beer_dep]) + +test('valavapiconsumedtwicetest', app) diff --git a/test cases/vala/18 vapi consumed twice/person.vala b/test cases/vala/18 vapi consumed twice/person.vala new file mode 100644 index 0000000..36b0025 --- /dev/null +++ b/test cases/vala/18 vapi consumed twice/person.vala @@ -0,0 +1,16 @@ +public class Person : Object { + public string name { + get { + return "Joe Badger"; + } + } + + public Beer favorite_beer { + get; + construct; + } + + public Person() { + Object(favorite_beer: new Beer("smooth")); + } +} |