About
hs-wayland-scanner is an implementation of the Wayland Message
Definition
Language. It
will produce low-level Haskell bindings for Wayland client/server
protocols.
It will process multiple protocols in a single run, checking for
dependencies, in order to properly generate imports for all
modules. All depending protocols must be generated at once and
unresolved dependencies will produce an error.
The generated Haskell modules will also include the documentation that
can be processed with Haddock.
hs-wayland-scanner also exposes a library.
Quick Start
You can install hs-wayland-scanner from
Hackage:
cabal install hs-wayland-scanner
or locally:
tar xvfz hs-wayland-scanner-0.1.0.tar.gz
cd hs-wayland-scanner-0.1.0
cabal [run|build|install]
Building with MicroHs
This package relies on a very minimal set of dependencies, most of
which included in base, so it can be easily built with
MicroHs:
git clone https://github.com/augustss/MicroHs.git
cd MicroHs
make install
# add the `mhs` path to the environment (change accordingly):
export PATH=/home/username/.mcabal/bin:$PATH
There are few dependencies that must be installed for
hs-wayland-scanner: the major one, which requires some special
handling, is xml that must be
installed from https://github.com/konsumlamm/xml
mcabal install ghc-compat
mcabal install --git=https://github.com/konsumlamm/xml xml
Then:
mcabal -r install hs-wayland-scanner
Done!
Generated files and modules
In order to make it possible to generate both client and server
protocol bindings for the same project, each protocol will produce two
different modules:
Graphics.Wayland.Protocol.ProtocolName
Graphics.Wayland.(Client|Server).Protocol.ProtocolName
The first module will export the defined Enumerations, which are
shared by client and server protocols. A single module for both avoids
name clashes.
The default Graphics may be changed with the -n command line
option.
All bindings will be written in the generated/ directory, by
default, but that can be changed with the -p command line option.
The Haskell bindings will be located in the src/ sub-directory of
generated/. This location can be changed with the --src command
line option.
Additionally the bindings to the core wayland-client and/or
wayland-server will also be generated:
Graphics.Wayland.(Client|Server).Core
This module exports the bindings to
wayland-[client|server]-core.h. Not all foreign functions of those
libraries are presently implemented.
hws will report the generated modules to be included in the .cabal
file.
Additional C wrappers will be generated in the default cbits
directory: this can be changed with the "--cbits" command line option.
By default:
generated/cbits/wayland-[client|server]-protocols.c
This file must be included in the c-sources cabal field, together
with the dependency to libwayland:
c-sources: ./cbits/wayland-[client|server]-protocols.c
pkgconfig-depends: wayland-[client|server]
It is also possible to create a configuration file and run hws -c path/to/config. The included examples will ship a configuration file
that can be used as a template.
Command line options
Usage: hws [OPTIONS] [PROTOCOLS]
Options:
-h Print help
-p PATH Root directory for generated files (Default: "./generated")
-n STRING Namespace for generated modules (Default: "Graphics")
-r ROLE Generate Client or Server protocols (Default: "Client")
-c PATH Path to a configuration file
--cbits PATH Sub-directory for generated C files (Default: "cbits")
--src PATH Sub-directory for generated Haskell files (Default: "src")
[PROTOCOLS] The Wayland XML files to be processed
Examples
The source code comes with three examples: a simple-server and a
simple-client which may interact, and a hello-world example: a
standalone client that demonstrates XDG-shell handshaking and
renders a semi-transparent blue window using POSIX shared memory.
Each example comes with a hws configuration file and a .cabal file
to build them. Refer to their respective README for further
information.
Known issues and future improvements
Versioning
Protocol interfaces may add (but not remove) requests and events over
time. Because interface listeners are represented as Haskell records,
generating bindings against a newer version of a protocol may lead to
"missing field" warnings if your implementation doesn't account for
the newly added events and requests for the server side.
Protocols themselves do not have versions; only individual interfaces
do. Requests and events often include a "since" attribute in the XML,
which is preserved in the generated Haddock documentation for each
module.
hs-wayland-scanner is currently intended to be used as a
pre-processing tool rather than being invoked during every build. For
this reason, I have included the specific protocol XML files used for
the examples to ensure they always compile out of the box.
Bindings to core libraries (client and server)
I plan to expand the number of foreign imports for the core server and
client libraries. Note that Variadic Functions (like
wl_proxy_marshal_flags) cannot be implemented in Haskell via direct
foreign calls.
However, since this scanner generates specific, type-safe wrappers for
all protocol messages, these generic variadic dispatchers are
generally not needed by end-users. See the hello-world example for
an idiomatic approach using the generated wrappers and opaque
pointers. Ideas or suggestions for expanding the core bindings are
welcome.