Open nirbheek opened 7 years ago
Another requirement is that some vapi
s actually require other vapi
s to be usable. For instance, libosinfo-1.0
needs gio-2.0
. So valac --pkg=libosinfo-1.0 test.vala
will fail. You need to run valac --pkg=gio-2.0 --pkg=libosinfo-1.0 test.vala
.
I think with all this combined, and looking at how this is done in Autotools, the best solution is something like this:
# Find all these pkg-config files or custom-type deps (like sdl2) at once
# returns a single ExternalDependency object
dependencies('uuid', 'glib-2.0', 'gio-2.0', 'libosinfo-1.0') # Implicitly method : 'auto'
# Find all these pkg-config files and corresponding vapi files
# returns a single ExternalDependency object
dependencies('glib-2.0', 'gio-2.0', 'libosinfo-1.0', method : ['vala', 'pkgconfig'])
# Find all these vapi files, returns a single ExternalDependency object
dependencies('glib-2.0', 'gio-2.0', 'libosinfo-1.0', method : 'vala')
If you are to use a pkg-config dependency in a Vala target that does not have its corresponding system-wide VAPI, it will very likely result in a local file shipped along the sources. I think it's well covered with add_project_arguments
now:
Maybe with add_project_include_directory
#1139 we could have a more elegant solution?
add_project_arguments('--vapidir=vapi, language: 'vala')
add_project_include_directory('vapi', language: 'vala') # alternative
uuid_dep = dependency('uuid')
If we don't need the dependency from Vala, it's okay to create a dummy VAPI and it's likely that you will put some definition in it eventually.
You will not find cases where the VAPI is named differently. Doing that is very unfriendly because it prevents valac from resolving flags.
Also, if you use a VAPI that is not available system-wide, it's typically better to not expose its APIs.
The case that tickles me is when you have to combine both find_library
from the C and Vala compilers (e.g. no pkg-config at all). I would love to see that combined in a single declare_dependency
line and the included into a target.
Thus I think that we should systematically use pkg-config with dependency
and extend the path for searching VAPI instead.
Oh, also, the advantage of extending the VAPI path is that it gives you the ability to override system-wide ones. I use this for https://github.com/rainwoodman/vast to have a decent gobject-introspection-1.0.vapi
.
If you are to use a pkg-config dependency in a Vala target that does not have its corresponding system-wide VAPI, it will very likely result in a local file shipped along the sources. I think it's well covered with add_project_arguments now
This is a workaround at best because it is not discoverable, the error message you get if you don't do this is arcane, it is inconsistent with how we handle vapis in other cases (such as generated vapis), and it also looks hacky (because it is).
The easiest way to use vapis available in the source tree is by just adding them to the list of sources for a target, and this already works just fine. What we want is for dependency
to not add --pkg=foo
without even checking if foo.vapi
exists in the system locations. We do this by adding the method
kwarg which will do a vapi search and will also solve #711 at the same time.
That would also solve the situation where you don't want to use the .vapi
available in the system: just don't use method : 'vala'
for that dependency.
But, while checking for vapis, you often need other vapis to be available at the same time, which is why I proposed dependencies
. It also has the advantage that can print all the needed dependencies if some of them are not found, which also solves #985.
I agree that we need a way to add a dependency to a target that does not imply a --pkg
flag. I would be more in favor of a language-specific option like has_vapi
:
uuid_dep = dependency('uuid', has_vapi: false)
For private bindings, it's effectively the best approach to add them directly to the sources, but for public ones, it's better to keep the in standard/extended paths as you would expect them to be. We could use the has_vapi
flag with a private binding shipped with the sources.
This is the error you get, which is not that cryptic:
error: Package `uuid' not found in specified Vala API directories or GObject-Introspection GIR directories
Compilation failed: 1 error(s), 0 warning(s)
Ideally we would be searching for all the VAPIs at configure-time, but that's a non-trivial task. The search path depends on the API version of the compiler, the *.deps
files found alongside and GIR packages are also supported. I think it's best to process them like we do for headers: use inclusion paths and explicit files directly on the target.
I've been working on a vala project that uses x as a dependency, and although the pc
file is called libgit2-glib-1.0.pc, the vapi
file has a different base name: ggit-1.0.vapi.
Due to this issue, meson (actually ninja) produces an error because it's not able to find the provided vapi
file.
@inigomartinez please see https://bugzilla.gnome.org/show_bug.cgi?id=787198 The VAPI should be renamed.
I've been working with gsettings-desktop-schemas
in gitg
which is written in vala
.
gitg
provides the vapi
file which is called gdesktop-enums-3.0.vapi and a metadata
file called GDesktopEnums-3.0.metadata. These names follow the name used for the GIR file GDesktopEnums-3.0.gir
, so they make sense. However the pc
file is called gsettings-desktop-schemas.pc
, which causes an error when the vapi
file is not found, which dependency is already added by using valac.find_library
.
I have my doubts about this situation. The package uses the pc
file to exporte the include dir for the only installed header. Should the pc
file be renamed, or maybe meson should provide a way to disable vala
following this approach?
@inigomartinez:
gitg provides the vapi file which is called gdesktop-enums-3.0.vapi and a metadata file called GDesktopEnums-3.0.metadata. These names follow the name used for the GIR file GDesktopEnums-3.0.gir, so they make sense. However the pc file is called gsettings-desktop-schemas.pc, which causes an error when the vapi file is not found
The .metadata
file has to follow the name of the GIR, but the VAPI generated can be called whatever you like. In this case it should be gsettings-desktop-schemas.vapi
. Here is an example using vapigen
for libvips:
vapigen \
--library vips \
--pkg gobject-2.0 \
--pkg glib-2.0 \
--pkg gmodule-2.0 \
--metadatadir . \
Vips-8.0-custom.vala \
/usr/share/gir-1.0/Vips-8.0.gir
This produces a VAPI called vips.vapi
. vapigen
uses the library name passed to it and adds the .vapi
extension.
Using gnome.generate_vapi()
in a meson.build
file would be something like (untested):
gnome.generate_vapi( 'vips',
packages: ['gobject-2.0', 'glib-2.0', 'gmodule-2.0'],
sources: ['Vips-8.0', 'Vips-8.0-custom.vala']
)
So you simply need to change gdesktop-enums-3.0.vapi
to gsettings-desktop-schemas.vapi
in your build.
I would question though why gitg
is carrying several third party VAPIs: https://git.gnome.org/browse/gitg/tree/vapi
I haven't checked all, but bindings like libsoup-2.4
are carried upstream and are likely to be removed from the Vala distribution itself shortly - see https://bugzilla.gnome.org/show_bug.cgi?id=773197
Having these VAPIs also distributed with gitg
doesn't make sense.
So for gdesktop-enums-3.0.vapi
you should ideally generate this as part of the gsettings-desktop-schemas project and rename the VAPI to gsettings-desktop-schemas.vapi
. So it is then distributed with the development files.
Your example is more to do with how the Vala community manage distribution of bindings than it is to do with Meson working around any problems. If you can't get this upstream then gnome.generate_vapi
should be enough to generate a correctly named VAPI.
Thank you @astavale!
I have just sent a patch to rename the vapi
file accordingly. Hope it gets merged so the "workaround" won't be necessary.
meson.get_compiler('vala').find_library('my_lib')
only checks for VAPIs in the default Vala search paths, and not any additional paths added using add_project_arguments
. It could help to use that function internally to check for a VAPI when dependency
is used.
No, find_library
doesn't use any additional search paths from add_project_arguments
. However, find_library
has a parameter called dirs
that can be used to add additional search paths.
gitg
uses this feature to include custom VAPI packages.
@inigomartinez Thanks. I'll have a go at updating Meson's Vala docs to show that is the current best way of doing this.
Could be useful to have the VAPI search path added to in one place. Maybe:
meson.get_compiler('vala').include_directories = join_paths(meson.current_source_dir(), 'vapi')
Although that idea didn't get very far in #906
The ability to customize what meson passes as the --pkg
flag for a dependency is important for one more reason: valac
can consume GIRs directly, without explicitly generating a vapi
. (How was this completely ignored by meson devs?) And gir files don't have pkgconfig-matching names, they have CamelCase names.
The ability to customize what meson passes as the
--pkg
flag for a dependency is important for one more reason:valac
can consume GIRs directly, without explicitly generating avapi
. (How was this completely ignored by meson devs?) And gir files don't have pkgconfig-matching names, they have CamelCase names.
The is what vapigen
is for and why VAPIs distributed with Vala are built that way - see how all the VAPIs are generated from GIRs in the Vala source tree. Consuming GIRs the way you suggest is slow and can also produce unexpected errors - that is what all the metadata is for.
If you really wish to consume a GObject Introspection Repository that way have you tried something like:
add_project_arguments(['--pkg', `NotSomethingIRecommendBinding'], language: 'vala')
I'm not the one writing Vala, I'm more on the side of the package being depended on :) Yes, a custom --pkg
arg is what I recommended, but that feels janky, it would be much better if the dependency(..)
object would still be used.
slow and can also produce unexpected errors
Not if the gir is like, 5 very simple functions in total.
I'm not the one writing Vala, I'm more on the side of the package being depended on :)
If it's any help, there is gnome.generate_vapi()
so a VAPI can be generated and distributed as part of the dependent package. Alternatively that Meson function can instead be used by the Vala application if upstream don't want to include a VAPI in their distributed package.
it would be much better if the dependency(..) object would still be used
And actually, it's required because meson does linking on its own (rather than via valac), and without the dependency it won't link the library..
it would be much better if the dependency(..) object would still be used
And actually, it's required because meson does linking on its own (rather than via valac), and without the dependency it won't link the library..
When I added a lot more details about using libraries with Vala in the Meson Vala documentation I found that dependency()
does a lot behind the scenes and it requires some conventions to be followed to allow the interface files, both VAPI and C headers, to be found. The main convention is to use the same filename for the VAPI file and pkg-config file, this is a convention for Vala, not just Meson.
The problem you have is the GIR is a different name, including a version number, so in complex cases I found that using each compiler's find_library()
method worked better. This is detailed in the documentation mentioned. So dependency()
gets split in to meson.get_compiler('vala').find_library()
and meson.get_compiler('c').find_library()
. I've not tested it with GIR files, but it does work for more complex configurations. I'm not sure how additional search paths and filename conversions can be built in to dependency()
to make it as simple as you suggest.
Currently, our vala pkg-config support works like this:
1) We use a simple pkg-config dependency check:
dependency('foo-2.4')
2) While compiling vala files for a target, we unconditionally add--pkg=foo-2.4
for each pkg-config dependency listed for that targetThis is correct about 80% of the time. It breaks in the following cases:
a) There's no
foo-2.4.vapi
file corresponding to thefoo-2.4.pc
file. This can happen because of one of two reasons:.vapi
file is shipped with any vala package for that library (e.g.: uuid.pc)b) We don't actually want to use that dependency in the Vala sources. It is only used in the C sources. This is harmless if a
vapi
file for that dep actually exists, but if it doesn't it will cause an unnecessary error. c) Thefoo-2.4.vapi
file corresponding to thefoo-2.4.pc
file is shipped with the source tree. (e.g.govirt-1.0.vapi
is shipped with the Boxes source tree. d) Nofoo-2.4.vapi
file is needed because the information contained in thevapi
file is embedded in the source (e.g. Boxes does this for libuuid).I haven't found any cases where the
vapi
file has a different basename than thepc
file.