parent
fcca265035
commit
5a4177523e
18 changed files with 283 additions and 5 deletions
@ -0,0 +1,64 @@ |
||||
# Unstable Wayland Module |
||||
|
||||
This module is available since version 0.62.0. |
||||
|
||||
This module provides helper functions to find wayland protocol |
||||
xmls and to generate .c and .h files using wayland-scanner |
||||
|
||||
**Note**: this module is unstable. It is only provided as a technology |
||||
preview. Its API may change in arbitrary ways between releases or it |
||||
might be removed from Meson altogether. |
||||
|
||||
## Quick Usage |
||||
|
||||
```meson |
||||
project('hello-wayland', 'c') |
||||
|
||||
wl_dep = dependency('wayland-client') |
||||
wl_mod = import('unstable-wayland') |
||||
|
||||
xml = wl_mod.find_protocol('xdg-shell') |
||||
xdg_shell = wl_mod.scan_xml(xml) |
||||
|
||||
executable('hw', 'main.c', xdg_shell, dependencies : wl_dep) |
||||
``` |
||||
|
||||
## Methods |
||||
|
||||
### find_protocol |
||||
|
||||
```meson |
||||
xml = wl_mod.find_protocol( |
||||
'xdg-decoration', |
||||
state : 'unstable', |
||||
version : 1, |
||||
) |
||||
``` |
||||
This function requires one positional argument: the protocol base name. |
||||
- `state` Optional arg that specifies the current state of the protocol. |
||||
Either stable, staging, or unstable. |
||||
The default is stable. |
||||
- `version` The backwards incompatible version number. |
||||
Required for staging or unstable. An error is raised for stable. |
||||
|
||||
### scan_xml |
||||
```meson |
||||
generated = wl_mod.scan_xml( |
||||
'my-protocol.xml', |
||||
side : 'client', |
||||
scope : 'private', |
||||
) |
||||
``` |
||||
This function accepts one or more arguments of either string or file type. |
||||
|
||||
- `side` Optional arg that specifies if client or server side code is generated. |
||||
The default is client side. |
||||
- `scope` Optional arg that specifies the scope of the generated code. |
||||
Either public or private. |
||||
The default is private. |
||||
|
||||
|
||||
## Links |
||||
- [Official Wayland Documentation](https://wayland.freedesktop.org/docs/html/) |
||||
- [Wayland GitLab](https://gitlab.freedesktop.org/wayland) |
||||
- [Wayland Book](https://wayland-book.com/) |
@ -0,0 +1,4 @@ |
||||
## New unstable wayland module |
||||
|
||||
This module can search for protocol xml files from the wayland-protocols |
||||
package, and generate .c and .h files using wayland-scanner. |
@ -0,0 +1,120 @@ |
||||
# Copyright 2022 Mark Bolhuis <mark@bolhuis.dev> |
||||
|
||||
# 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 os |
||||
|
||||
from . import ExtensionModule, ModuleReturnValue |
||||
from ..build import CustomTarget |
||||
from ..interpreter.type_checking import NoneType, in_set_validator |
||||
from ..interpreterbase import FeatureNew, typed_pos_args, typed_kwargs, KwargInfo |
||||
from ..mesonlib import File, MesonException, MachineChoice |
||||
|
||||
|
||||
class WaylandModule(ExtensionModule): |
||||
|
||||
@FeatureNew('wayland module', '0.62.0') |
||||
def __init__(self, interpreter): |
||||
super().__init__(interpreter) |
||||
|
||||
self.protocols_dep = None |
||||
self.pkgdatadir = None |
||||
self.scanner_bin = None |
||||
|
||||
self.methods.update({ |
||||
'scan_xml': self.scan_xml, |
||||
'find_protocol': self.find_protocol, |
||||
}) |
||||
|
||||
@typed_pos_args('wayland.scan_xml', varargs=(str, File), min_varargs=1) |
||||
@typed_kwargs( |
||||
'wayland.scan_xml', |
||||
KwargInfo('side', str, default='client', validator=in_set_validator({'client', 'server'})), |
||||
KwargInfo('scope', str, default='private', validator=in_set_validator({'private', 'public'})), |
||||
) |
||||
def scan_xml(self, state, args, kwargs): |
||||
if self.scanner_bin is None: |
||||
self.scanner_bin = state.find_program('wayland-scanner', for_machine=MachineChoice.BUILD) |
||||
|
||||
scope = kwargs['scope'] |
||||
side = kwargs['side'] |
||||
|
||||
xml_files = self.interpreter.source_strings_to_files(args[0]) |
||||
targets = [] |
||||
for xml_file in xml_files: |
||||
name = os.path.splitext(os.path.basename(xml_file.fname))[0] |
||||
|
||||
code = CustomTarget( |
||||
f'{name}-protocol', |
||||
state.subdir, |
||||
state.subproject, |
||||
[self.scanner_bin, f'{scope}-code', '@INPUT@', '@OUTPUT@'], |
||||
[xml_file], |
||||
[f'{name}-protocol.c'], |
||||
backend=state.backend, |
||||
) |
||||
targets.append(code) |
||||
|
||||
header = CustomTarget( |
||||
f'{name}-{side}-protocol', |
||||
state.subdir, |
||||
state.subproject, |
||||
[self.scanner_bin, f'{side}-header', '@INPUT@', '@OUTPUT@'], |
||||
[xml_file], |
||||
[f'{name}-{side}-protocol.h'], |
||||
backend=state.backend, |
||||
) |
||||
targets.append(header) |
||||
|
||||
return ModuleReturnValue(targets, targets) |
||||
|
||||
@typed_pos_args('wayland.find_protocol', str) |
||||
@typed_kwargs( |
||||
'wayland.find_protocol', |
||||
KwargInfo('state', str, default='stable', validator=in_set_validator({'stable', 'staging', 'unstable'})), |
||||
KwargInfo('version', (int, NoneType)), |
||||
) |
||||
def find_protocol(self, state, args, kwargs): |
||||
base_name = args[0] |
||||
xml_state = kwargs['state'] |
||||
version = kwargs['version'] |
||||
|
||||
if xml_state != 'stable' and version is None: |
||||
raise MesonException(f'{xml_state} protocols require a version number.') |
||||
|
||||
if xml_state == 'stable' and version is not None: |
||||
raise MesonException('stable protocols do not require a version number.') |
||||
|
||||
if self.protocols_dep is None: |
||||
self.protocols_dep = self.interpreter.func_dependency(state.current_node, ['wayland-protocols'], {}) |
||||
|
||||
if self.pkgdatadir is None: |
||||
self.pkgdatadir = self.protocols_dep.get_variable(pkgconfig='pkgdatadir', internal='pkgdatadir') |
||||
|
||||
if xml_state == 'stable': |
||||
xml_name = f'{base_name}.xml' |
||||
elif xml_state == 'staging': |
||||
xml_name = f'{base_name}-v{version}.xml' |
||||
else: |
||||
xml_name = f'{base_name}-unstable-v{version}.xml' |
||||
|
||||
path = os.path.join(self.pkgdatadir, xml_state, base_name, xml_name) |
||||
|
||||
if not os.path.exists(path): |
||||
raise MesonException(f'The file {path} does not exist.') |
||||
|
||||
return File.from_absolute_file(path) |
||||
|
||||
|
||||
def initialize(interpreter): |
||||
return WaylandModule(interpreter) |
@ -0,0 +1,9 @@ |
||||
#include "xdg-shell-client-protocol.h" |
||||
|
||||
int main() { |
||||
#ifdef XDG_SHELL_CLIENT_PROTOCOL_H |
||||
return 0; |
||||
#else |
||||
return 1; |
||||
#endif |
||||
} |
@ -0,0 +1,16 @@ |
||||
project('wayland-test-client', 'c') |
||||
|
||||
wl_protocols_dep = dependency('wayland-protocols', required : false) |
||||
if not wl_protocols_dep.found() |
||||
error('MESON_SKIP_TEST: wayland-protocols not installed') |
||||
endif |
||||
|
||||
wl_dep = dependency('wayland-client') |
||||
wl_mod = import('unstable-wayland') |
||||
|
||||
xdg_shell_xml = wl_mod.find_protocol('xdg-shell') |
||||
xdg_shell = wl_mod.scan_xml(xdg_shell_xml) |
||||
|
||||
exe = executable('client', 'main.c', xdg_shell, dependencies : wl_dep) |
||||
|
||||
test('client', exe) |
@ -0,0 +1,9 @@ |
||||
#include "xdg-shell-server-protocol.h" |
||||
|
||||
int main() { |
||||
#ifdef XDG_SHELL_SERVER_PROTOCOL_H |
||||
return 0; |
||||
#else |
||||
return 1; |
||||
#endif |
||||
} |
@ -0,0 +1,16 @@ |
||||
project('wayland-test-server', 'c') |
||||
|
||||
wl_protocols_dep = dependency('wayland-protocols', required : false) |
||||
if not wl_protocols_dep.found() |
||||
error('MESON_SKIP_TEST: wayland-protocols not installed') |
||||
endif |
||||
|
||||
wl_dep = dependency('wayland-server') |
||||
wl_mod = import('unstable-wayland') |
||||
|
||||
xdg_shell_xml = wl_mod.find_protocol('xdg-shell') |
||||
xdg_shell = wl_mod.scan_xml(xdg_shell_xml, side : 'server') |
||||
|
||||
exe = executable('server', 'main.c', xdg_shell, dependencies : wl_dep) |
||||
|
||||
test('client', exe) |
@ -0,0 +1,9 @@ |
||||
#include "test-client-protocol.h" |
||||
|
||||
int main() { |
||||
#ifdef TEST_CLIENT_PROTOCOL_H |
||||
return 0; |
||||
#else |
||||
return 1; |
||||
#endif |
||||
} |
@ -0,0 +1,11 @@ |
||||
project('wayland-test-local', 'c') |
||||
|
||||
wl_dep = dependency('wayland-client') |
||||
wl_mod = import('unstable-wayland') |
||||
|
||||
xmls = files('test.xml') |
||||
gen = wl_mod.scan_xml(xmls) |
||||
|
||||
exe = executable('local', 'main.c', gen, dependencies : wl_dep) |
||||
|
||||
test('local', exe) |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<protocol name="test"> |
||||
<interface name="ext_test" version="1"> |
||||
<request name="destroy" type="destructor"/> |
||||
</interface> |
||||
</protocol> |
Loading…
Reference in new issue