diff --git a/config.h.meson b/config.h.meson
new file mode 100644
index 0000000..d6c879f
--- /dev/null
+++ b/config.h.meson
@@ -0,0 +1,77 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `accept4' function. */
+#mesondefine HAVE_ACCEPT4
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#mesondefine HAVE_DLFCN_H
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#mesondefine HAVE_EXECINFO_H
+
+/* Define to 1 if you have the <expat.h> header file. */
+#mesondefine HAVE_EXPAT_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#mesondefine HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#mesondefine HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mkostemp' function. */
+#mesondefine HAVE_MKOSTEMP
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#mesondefine HAVE_POSIX_FALLOCATE
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#mesondefine HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#mesondefine HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#mesondefine HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#mesondefine HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#mesondefine HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#mesondefine HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#mesondefine HAVE_UNISTD_H
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#mesondefine LT_OBJDIR
+
+/* Name of package */
+#mesondefine PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#mesondefine PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#mesondefine PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#mesondefine PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#mesondefine PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#mesondefine PACKAGE_URL
+
+/* Define to the version of this package. */
+#mesondefine PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#mesondefine STDC_HEADERS
+
+/* Version number of package */
+#mesondefine VERSION
diff --git a/cursor/meson.build b/cursor/meson.build
new file mode 100644
index 0000000..b2996ca
--- /dev/null
+++ b/cursor/meson.build
@@ -0,0 +1,6 @@
+install_headers('wayland-cursor.h')
+
+configure_file(input : 'wayland-cursor.pc.in',
+output : 'wayland-cursor.pc',
+configuration : subst_conf,
+install_dir : get_option('libdir') + '/pkgconfig')
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..bfe05ab
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,138 @@
+project('wayland', 'c', 'cpp')
+
+version_major = 1
+version_minor = 7
+version_micro = 90
+version_str = '@0@.@1@.@2@'.format(version_major, version_minor, version_micro)
+pkgver_str = version_str
+
+subst_conf = configuration_data()
+
+subst_conf.set('WAYLAND_VERSION_MAJOR', version_major)
+subst_conf.set('WAYLAND_VERSION_MINOR', version_minor)
+subst_conf.set('WAYLAND_VERSION_MICRO', version_micro)
+subst_conf.set('WAYLAND_VERSION', version_str)
+subst_conf.set('PACKAGE_VERSION', pkgver_str)
+subst_conf.set('prefix', get_option('prefix'))
+subst_conf.set('includedir', get_option('prefix') + '/' + get_option('includedir'))
+subst_conf.set('libdir', get_option('prefix') + '/' + get_option('libdir'))
+
+ffidep = dependency('libffi')
+expatdep = dependency('expat')
+
+inc = [include_directories('.'),
+include_directories('src')]
+
+cc = meson.get_compiler('c')
+conf_data = configuration_data()
+
+if cc.get_id() != 'msvc'
+  add_global_arguments('-Wextra', '-Wno-unused-parameter', '-Wstrict-prototypes', language : 'c')
+  add_global_arguments('-Wextra', '-Wno-unused-parameter', '-Wstrict-prototypes', language : 'cpp')
+endif
+
+if not cc.has_header('sys/signalfd.h')
+  error('Signalfd.h is needed to compile Wayland.')
+endif
+
+if not cc.has_header('sys/timerfd.h')
+  error('Timerfd.h is needed to compile Wayland.')
+endif
+
+monocode = '''#include<time.h>
+void func() {
+  clockid_t clocktype = CLOCK_MONOTONIC;
+}
+'''
+
+if not cc.compiles(monocode, name : 'clock_monotonic')
+  error('CLOCK_MONOTONIC is needed to compile Wayland.')
+endif
+
+conf_data.set('HAVE_EXPAT_H', cc.has_header('expat.h'))
+conf_data.set('HAVE_EXECINFO_H', cc.has_header('execinfo.h'))
+conf_data.set('HAVE_INTTYPES_H', cc.has_header('inttypes.h'))
+conf_data.set('HAVE_MEMORY_H', cc.has_header('memory.h'))
+conf_data.set('HAVE_STDINT_H', cc.has_header('stdint.h'))
+conf_data.set('HAVE_STDLIB_H', cc.has_header('stdlib.h'))
+conf_data.set('HAVE_STRINGS_H', cc.has_header('strings.h'))
+conf_data.set('HAVE_STRING_H', cc.has_header('string.h'))
+conf_data.set('HAVE_SYS_STAT_H', cc.has_header('sys/stat.h'))
+conf_data.set('HAVE_SYS_TYPES_H', cc.has_header('sys/types.h'))
+conf_data.set('HAVE_UNISTD_H', cc.has_header('unistd.h'))
+
+configure_file(input : 'config.h.meson',
+output : 'config.h',
+configuration : conf_data)
+
+libutil = static_library('wayland-util',
+'src/connection.c',
+'src/wayland-util.c',
+'src/wayland-os.c',
+c_args : '-fPIC',
+dependencies : ffidep
+)
+
+scanner = executable('wayland-scanner',
+'src/scanner.c',
+dependencies : expatdep,
+link_with : libutil,
+install : true)
+
+server_h = custom_target('server-header',
+input : 'protocol/wayland.xml',
+output : 'wayland-server-protocol.h',
+command : [scanner , 'server-header', '@INPUT@', '@OUTPUT@'],
+install : true,
+install_dir : 'include')
+
+client_h = custom_target('client-header',
+input : 'protocol/wayland.xml',
+output : 'wayland-client-protocol.h',
+command : [scanner , 'client-header', '@INPUT@', '@OUTPUT@'],
+install : true,
+install_dir : 'include')
+
+protocol_c = custom_target('protocol-code',
+input : 'protocol/wayland.xml',
+output : 'wayland-protocol.c',
+command : [scanner , 'code', '@INPUT@', '@OUTPUT@'])
+
+libserver = shared_library('wayland-server',
+'src/wayland-server.c',
+'src/wayland-shm.c',
+'src/event-loop.c',
+server_h,
+protocol_c,
+include_directories : inc,
+c_args : '-pthread',
+link_args : ['-pthread', '-lrt', '-lm'],
+link_with : libutil,
+install : true,
+version : '0.1.0',
+soversion : '0')
+
+libclient = shared_library('wayland-client',
+'src/wayland-client.c',
+client_h,
+protocol_c,
+c_args : '-pthread',
+link_args : ['-pthread', '-lrt', '-lm'],
+link_with : libutil,
+install : true,
+version : '0.3.0',
+soversion : '0')
+
+libcursor = shared_library('wayland-cursor',
+'cursor/wayland-cursor.c',
+'cursor/os-compatibility.c',
+'cursor/xcursor.c',
+link_with : libutil,
+include_directories : inc,
+install : true,
+version : '0.0.0',
+soversion : '0')
+
+subdir('cursor')
+subdir('src')
+subdir('tests')
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..6f1f752
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,25 @@
+configure_file(input : 'wayland-version.h.in',
+output : 'wayland-version.h',
+configuration : subst_conf,
+install_dir : 'include')
+
+configure_file(input : 'wayland-client.pc.in',
+output : 'wayland-client.pc',
+configuration : subst_conf,
+install_dir : get_option('libdir') + '/pkgconfig')
+
+configure_file(input : 'wayland-scanner.pc.in',
+output : 'wayland-scanner.pc',
+configuration : subst_conf,
+install_dir : get_option('libdir') + '/pkgconfig')
+
+configure_file(input : 'wayland-server.pc.in',
+output : 'wayland-server.pc',
+configuration : subst_conf,
+install_dir : get_option('libdir') + '/pkgconfig')
+
+
+install_headers('wayland-client.h',
+'wayland-egl.h',
+'wayland-server.h',
+'wayland-util.h')
diff --git a/src/scanner.c b/src/scanner.c
index 1f1e59a..e036e0f 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -28,6 +28,8 @@
 #include <errno.h>
 #include <ctype.h>
 #include <expat.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include "wayland-util.h"
 
@@ -1252,6 +1254,7 @@ int main(int argc, char *argv[])
 {
 	struct parse_context ctx;
 	struct protocol protocol;
+	FILE *input = stdin;
 	int len;
 	void *buf;
 	enum {
@@ -1260,7 +1263,7 @@ int main(int argc, char *argv[])
 		CODE,
 	} mode;
 
-	if (argc != 2)
+	if (argc < 2 || argc > 4)
 		usage(EXIT_FAILURE);
 	else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0)
 		usage(EXIT_SUCCESS);
@@ -1273,6 +1276,16 @@ int main(int argc, char *argv[])
 	else
 		usage(EXIT_FAILURE);
 
+	if(argc > 2) {
+		input = fopen(argv[2], "r");
+	}
+	if(argc > 3) {
+		int outfd = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC,
+			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+			S_IROTH | S_IWOTH);
+		dup2(outfd, STDOUT_FILENO);
+	}
+
 	wl_list_init(&protocol.interface_list);
 	protocol.type_index = 0;
 	protocol.null_run_length = 0;
@@ -1293,7 +1306,7 @@ int main(int argc, char *argv[])
 
 	do {
 		buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
-		len = fread(buf, 1, XML_BUFFER_SIZE, stdin);
+		len = fread(buf, 1, XML_BUFFER_SIZE, input);
 		if (len < 0) {
 			fprintf(stderr, "fread: %m\n");
 			exit(EXIT_FAILURE);
@@ -1324,3 +1337,4 @@ int main(int argc, char *argv[])
 
 	return 0;
 }
+
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..f4250a4
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,33 @@
+libtestrunner = static_library('test_runner',
+'test-runner.c',
+'test-helpers.c',
+'test-compositor.c',
+link_with : [libserver, libclient, libutil],
+dependencies : ffidep,
+include_directories : inc)
+
+tests = [['array-test', 'array-test.c'],
+['client-test', 'client-test.c'],
+['display-test', 'display-test.c'],
+['connection-test', 'connection-test.c'],
+['event-loop-test', 'event-loop-test.c'],
+['fixed-test', 'fixed-test.c'],
+['list-test', 'list-test.c'],
+['map-test', 'map-test.c'],
+['os-wrappers-test', 'os-wrappers-test.c'],
+['sanity-test', 'sanity-test.c'],
+['socket-test', 'socket-test.c'],
+['queue-test', 'queue-test.c'],
+['signal-test', 'signal-test.c'],
+['resources-test', 'resources-test.c'],
+['message-test', 'message-test.c'],
+['cpp-compile-test', 'cpp-compile-test.cpp']
+]
+
+foreach t : tests
+  exe = executable(t.get(0), t.get(1),
+      include_directories : inc,
+      link_args : ['-lrt', '-ldl', '-pthread'],
+      link_with : [libtestrunner])
+  test(t.get(0), exe)
+endforeach
