|
|
|
---
|
|
|
|
title: Vala
|
|
|
|
short-description: Compiling Vala and Genie programs
|
|
|
|
...
|
|
|
|
|
|
|
|
# Compiling Vala applications and libraries
|
|
|
|
Meson supports compiling applications and libraries written in
|
|
|
|
[Vala](https://vala-project.org/) and
|
|
|
|
[Genie](https://wiki.gnome.org/Projects/Genie) . A skeleton `meson.build` file:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
You must always specify the `glib-2.0` and `gobject-2.0` libraries as
|
|
|
|
dependencies, because all current Vala applications use them.
|
|
|
|
[GLib](https://developer.gnome.org/glib/stable/) is used for basic data types
|
|
|
|
and [GObject](https://developer.gnome.org/gobject/stable/) is used for the
|
|
|
|
runtime type system.
|
|
|
|
|
|
|
|
|
|
|
|
## Using libraries
|
|
|
|
Meson uses the [`dependency()`](Reference-manual.md#dependency) function to find
|
|
|
|
the relevant VAPI, C headers and linker flags when it encounters a Vala source
|
|
|
|
file in a build target. Vala needs a VAPI file and a C header or headers to use
|
|
|
|
a library. The VAPI file helps map Vala code to the library's C programming
|
|
|
|
interface. It is the
|
|
|
|
[`pkg-config`](https://www.freedesktop.org/wiki/Software/pkg-config/) tool that
|
|
|
|
makes finding these installed files all work seamlessly behind the scenes. When
|
|
|
|
a `pkg-config` file doesn't exist for the library then the
|
|
|
|
[`find_library()`](Reference-manual.md#find_library) method of the [compiler
|
|
|
|
object](Reference-manual.md#compiler-object) needs to be used. Examples are
|
|
|
|
given later.
|
|
|
|
|
|
|
|
Note Vala uses libraries that follow the C Application Binary Interface (C ABI).
|
|
|
|
The library, however, could be written in C, Vala, Rust, Go, C++ or any other
|
|
|
|
language that can generate a binary compatible with the C ABI and so provides C
|
|
|
|
headers.
|
|
|
|
|
|
|
|
|
|
|
|
### The simplest case
|
|
|
|
This first example is a simple addition to the `meson.build` file because:
|
|
|
|
|
|
|
|
* the library has a `pkg-config` file, `gtk+-3.0.pc`
|
|
|
|
* the VAPI is distributed with Vala and so installed with the Vala compiler
|
|
|
|
* the VAPI is installed in Vala's standard search path
|
|
|
|
* the VAPI, `gtk+-3.0.vapi`, has the same name as the `pkg-config` file
|
|
|
|
|
|
|
|
Everything works seamlessly in the background and only a single extra line is
|
|
|
|
needed:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
dependency('gtk+-3.0'),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
GTK+ is the graphical toolkit used by GNOME, elementary OS and other desktop
|
|
|
|
environments. The binding to the library, the VAPI file, is distributed with
|
|
|
|
Vala.
|
|
|
|
|
|
|
|
Other libraries may have a VAPI that is distributed with the library itself.
|
|
|
|
Such libraries will have their VAPI file installed along with their other
|
|
|
|
development files. The VAPI is installed in Vala's standard search path and so
|
|
|
|
works just as seamlessly using the `dependency()` function.
|
|
|
|
|
|
|
|
|
|
|
|
### Targetting a version of GLib
|
|
|
|
Meson's [`dependency()`](Reference-manual.md#dependency) function allows a
|
|
|
|
version check of a library. This is often used to check a minimum version is
|
|
|
|
installed. When setting a minimum version of GLib, Meson will also pass this to
|
|
|
|
the Vala compiler using the `--target-glib` option.
|
|
|
|
|
|
|
|
This is needed when using GTK+'s user interface definition files with Vala's
|
|
|
|
`[GtkTemplate]`, `[GtkChild]` and `[GtkCallback]` annotations. This requires
|
|
|
|
`--target-glib 2.38`, or a newer version, to be passed to Vala. With Meson this
|
|
|
|
is simply done with:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0', version: '>=2.38'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
dependency('gtk+-3.0'),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
Using `[GtkTemplate]` also requires the GTK+ user interface definition files to
|
|
|
|
be built in to the binary as GResources. For completeness, the next example
|
|
|
|
shows this:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0', version: '>=2.38'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
dependency('gtk+-3.0'),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
sources += import( 'gnome' ).compile_resources(
|
|
|
|
'project-resources',
|
|
|
|
'src/resources/resources.gresource.xml',
|
|
|
|
source_dir: 'src/resources',
|
|
|
|
)
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Adding to Vala's search path
|
|
|
|
So far we have covered the cases where the VAPI file is either distributed with
|
|
|
|
Vala or the library. A VAPI can also be included in the source files of your
|
|
|
|
project. The convention is to put it in the `vapi` directory of your project.
|
|
|
|
|
|
|
|
This is needed when a library does not have a VAPI or your project needs to link
|
|
|
|
to another component in the project that uses the C ABI. For example if part of
|
|
|
|
the project is written in C.
|
|
|
|
|
|
|
|
The Vala compiler's `--vapidir` option is used to add the project directory to
|
|
|
|
the VAPI search path. In Meson this is done with the `add_project_arguments()`
|
|
|
|
function:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
vapi_dir = join_paths(meson.current_source_dir(), 'vapi')
|
|
|
|
|
|
|
|
add_project_arguments(['--vapidir', vapi_dir], language: 'vala')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
dependency('foo'), # 'foo.vapi' will be resolved as './vapi/foo.vapi'
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
If the VAPI is for an external library then make sure that the VAPI name
|
|
|
|
corresponds to the pkg-config file name.
|
|
|
|
|
|
|
|
The [`vala-extra-vapis` repository](https://github.com/nemequ/vala-extra-vapis)
|
|
|
|
is a community maintained repository of VAPIs that are not distributed.
|
|
|
|
Developers use the repository to share early work on new bindings and
|
|
|
|
improvements to existing bindings. So the VAPIs can frequently change. It is
|
|
|
|
recommended VAPIs from this repository are copied in to your project's source
|
|
|
|
files.
|
|
|
|
|
|
|
|
This also works well for starting to write new bindings before they are shared
|
|
|
|
with the `vala-extra-vapis` repository.
|
|
|
|
|
|
|
|
|
|
|
|
### Libraries without pkg-config files
|
|
|
|
A library that does not have a corresponding pkg-config file may mean
|
|
|
|
`dependency()` is unsuitable for finding the C and Vala interface files. In this
|
|
|
|
case it is necessary to use the `find_library()` method of the compiler object.
|
|
|
|
|
|
|
|
The first example uses Vala's POSIX binding. There is no pkg-config file because
|
|
|
|
POSIX includes the standard C library on Unix systems. All that is needed is the
|
|
|
|
VAPI file, `posix.vapi`. This is included with Vala and installed in Vala's
|
|
|
|
standard search path. Meson just needs to be told to only find the library for
|
|
|
|
the Vala compiler:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
meson.get_compiler('vala').find_library('posix'),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
|
|
|
|
The next example shows how to link with a C library where no additional VAPI is
|
|
|
|
needed. The standard maths functions are already bound in `glib-2.0.vapi`, but
|
|
|
|
the GNU C library requires linking to the maths library separately. In this
|
|
|
|
example Meson is told to find the library only for the C compiler:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
meson.get_compiler('c').find_library('m', required: false),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
The `required: false` means the build will continue when using another C library
|
|
|
|
that does not separate the maths library. See [Add math library (-lm)
|
|
|
|
portably](howtox.md#add-math-library-lm-portably).
|
|
|
|
|
|
|
|
The final example shows how to use a library that does not have a pkg-config
|
|
|
|
file and the VAPI is in the `vapi` directory of your project source files:
|
|
|
|
```meson
|
|
|
|
project('vala app', 'vala', 'c')
|
|
|
|
|
|
|
|
vapi_dir = join_paths(meson.current_source_dir(), 'vapi')
|
|
|
|
|
|
|
|
add_project_arguments(['--vapidir', vapi_dir], language: 'vala')
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
dependency('glib-2.0'),
|
|
|
|
dependency('gobject-2.0'),
|
|
|
|
meson.get_compiler('c').find_library('foo'),
|
|
|
|
meson.get_compiler('vala').find_library('foo', dir: vapi_dir),
|
|
|
|
]
|
|
|
|
|
|
|
|
sources = files('app.vala')
|
|
|
|
|
|
|
|
executable('app_name', sources, dependencies: dependencies)
|
|
|
|
```
|
|
|
|
The `find_library()` method of the C compiler object will try to find the C
|
|
|
|
header files and the library to link with.
|
|
|
|
|
|
|
|
The `find_library()` method of the Vala compiler object needs to have the `dir`
|
|
|
|
keyword added to include the project VAPI directory. This is not added
|
|
|
|
automatically by `add_project_arguments()`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Building libraries
|
|
|
|
|
|
|
|
|
|
|
|
### Changing C header and VAPI names
|
|
|
|
Meson's [`library`](Reference-manual.md#library) target automatically outputs
|
|
|
|
the C header and the VAPI. They can be renamed by setting the `vala_header` and
|
|
|
|
`vala_vapi` arguments respectively:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
foo_lib = shared_library('foo', 'foo.vala',
|
|
|
|
vala_header: 'foo.h',
|
|
|
|
vala_vapi: 'foo-1.0.vapi',
|
|
|
|
dependencies: [glib_dep, gobject_dep],
|
|
|
|
install: true,
|
|
|
|
install_dir: [true, true, true])
|
|
|
|
```
|
|
|
|
In this example, the second and third elements of the `install_dir` array
|
|
|
|
indicate the destination with `true` to use default directories (i.e. `include`
|
|
|
|
and `share/vala/vapi`).
|
|
|
|
|
|
|
|
|
|
|
|
### GObject Introspection and language bindings
|
|
|
|
A 'binding' allows another programming language to use a library written in
|
|
|
|
Vala. Because Vala uses the GObject type system as its runtime type system it is
|
|
|
|
very easy to use introspection to generate a binding. A Meson build of a Vala
|
|
|
|
library can generate the GObject introspection metadata. The metadata is then
|
|
|
|
used in separate projects with [language specific
|
|
|
|
tools](https://wiki.gnome.org/Projects/Vala/LibraryWritingBindings) to generate
|
|
|
|
a binding.
|
|
|
|
|
|
|
|
The main form of metadata is a GObject Introspection Repository (GIR) XML file.
|
|
|
|
GIRs are mostly used by languages that generate bindings at compile time.
|
|
|
|
Languages that generate bindings at runtime mostly use a typelib file, which is
|
|
|
|
generated from the GIR.
|
|
|
|
|
|
|
|
Meson can generate a GIR as part of the build. For a Vala library the
|
|
|
|
`vala_gir` option has to be set for the `library`:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
foo_lib = shared_library('foo', 'foo.vala',
|
|
|
|
vala_gir: 'Foo-1.0.gir',
|
|
|
|
dependencies: [glib_dep, gobject_dep],
|
|
|
|
install: true,
|
|
|
|
install_dir: [true, true, true, true])
|
|
|
|
```
|
|
|
|
|
|
|
|
The `true` value in `install_dir` tells Meson to use the default directory (i.e.
|
|
|
|
`share/gir-1.0` for GIRs). The fourth element in the `install_dir` array
|
|
|
|
indicates where the GIR file will be installed.
|
|
|
|
|
|
|
|
To then generate a typelib file use a custom target with the `g-ir-compiler`
|
|
|
|
program and a dependency on the library:
|
|
|
|
|
|
|
|
```meson
|
|
|
|
g_ir_compiler = find_program('g-ir-compiler')
|
|
|
|
custom_target('foo typelib', command: [g_ir_compiler, '--output', '@OUTPUT@', '@INPUT@'],
|
|
|
|
input: join_paths(meson.current_build_dir(), 'Foo-1.0.gir'),
|
|
|
|
output: 'Foo-1.0.typelib',
|
|
|
|
depends: foo_lib,
|
|
|
|
install: true,
|
|
|
|
install_dir: join_paths(get_option('libdir'), 'girepository-1.0'))
|
|
|
|
```
|