diff --git a/cross/i686-w64-mingw32.txt b/cross/i686-w64-mingw32.txt new file mode 100644 index 000000000..a17c2f2a3 --- /dev/null +++ b/cross/i686-w64-mingw32.txt @@ -0,0 +1,10 @@ +[binaries] +c = '/usr/bin/i686-w64-mingw32-gcc' +strip = '/usr/bin/i686-w64-mingw32-strip' +pkgconfig = '/usr/bin/i686-w64-mingw32-pkg-config' + +[host_machine] +system = 'windows' +cpu_family = 'x86' +cpu = 'i686' +endian = 'little' diff --git a/cross/x86_64-w64-mingw32.txt b/cross/x86_64-w64-mingw32.txt new file mode 100644 index 000000000..7d7bd3ce8 --- /dev/null +++ b/cross/x86_64-w64-mingw32.txt @@ -0,0 +1,10 @@ +[binaries] +c = '/usr/bin/x86_64-w64-mingw32-gcc' +strip = '/usr/bin/x86_64-w64-mingw32-strip' +pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config' + +[host_machine] +system = 'windows' +cpu_family = 'x86' +cpu = 'x86_64' +endian = 'little' diff --git a/meson.build b/meson.build index ce21ab558..5f2e9bc25 100644 --- a/meson.build +++ b/meson.build @@ -22,17 +22,30 @@ endif glib = dependency('glib-2.0', version: '>=2.40') gobject = dependency('gobject-2.0', version: '>=2.40') gio = dependency('gio-2.0', version: '>=2.40') -gio_unix = dependency('gio-unix-2.0', version: '>=2.40') +gio_unix = dependency('gio-unix-2.0', version: '>=2.40', required: false) +gio_windows = dependency('gio-windows-2.0', version: '>=2.40', required: false) gmodule = dependency('gmodule-2.0', version: '>=2.40') soup = dependency('libsoup-2.4', version: '>=2.44') vala_defines = [] +if meson.get_compiler('c').has_function('fork') + vala_defines += '--define=HAVE_FORK' +endif + # provide 'OutputStream.write_all_async' if gio.version().version_compare('>=2.44') vala_defines += '--define=GIO_2_44' endif +if gio_unix.found() + vala_defines += '--define=GIO_UNIX' +endif + +if gio_windows.found() + vala_defines += '--define=GIO_WINDOWS' +endif + # new 'Soup.Server' API if soup.version().version_compare('>=2.48') vala_defines += '--define=SOUP_2_48' diff --git a/src/vsgi/meson.build b/src/vsgi/meson.build index 2ce4df252..5beb64c79 100644 --- a/src/vsgi/meson.build +++ b/src/vsgi/meson.build @@ -20,7 +20,7 @@ vsgi_sources = files( 'vsgi-socket-server.vala', 'vsgi-tee-output-stream.vala') vsgi_lib = library('vsgi-' + api_version, vsgi_sources, - dependencies: [glib, gobject, gio, gio_unix, gmodule, soup], + dependencies: [glib, gobject, gio, gio_unix, gio_windows, gmodule, soup], vala_args: ['--pkg=posix'] + vala_defines, link_args: '-Wl,-rpath,$$ORIGIN/servers', install: true, @@ -33,9 +33,19 @@ install_headers(meson.current_build_dir() + '/vsgi-@0@.h'.format(api_version), s install_data(meson.current_build_dir() + '/vsgi-@0@.vapi'.format(api_version), install_dir: 'share/vala/vapi') install_data('vsgi-@0@.deps'.format(api_version), install_dir: 'share/vala/vapi') +vsgi_requires_private = ['gmodule-2.0'] + +if gio_unix.found () + vsgi_requires_private += 'gio-unix-2.0' +endif + +if gio_windows.found() + vsgi_requires_private += 'gio-windows-2.0' +endif + pkgconfig = import('pkgconfig') pkgconfig.generate(requires: 'glib-2.0 gobject-2.0 gio-2.0 libsoup-2.4', - requires_private: 'gio-unix-2.0 gmodule-2.0', + requires_private: vsgi_requires_private, libraries: vsgi_lib, version: meson.project_version(), name: 'VSGI', diff --git a/src/vsgi/servers/meson.build b/src/vsgi/servers/meson.build index ba1a38762..f4eaafd13 100644 --- a/src/vsgi/servers/meson.build +++ b/src/vsgi/servers/meson.build @@ -5,7 +5,7 @@ shared_library('vsgi-http', ['vsgi-http.vala'], install_dir: '@0@/vsgi-@1@/servers'.format(get_option('libdir'), api_version)) shared_library('vsgi-cgi', 'vsgi-cgi.vala', - dependencies: [glib, gobject, gio, gio_unix, soup, vsgi], + dependencies: [glib, gobject, gio, gio_unix, gio_windows, soup, vsgi], vala_args: vala_defines, install: true, install_dir: '@0@/vsgi-@1@/servers'.format(get_option('libdir'), api_version)) @@ -13,7 +13,7 @@ shared_library('vsgi-cgi', 'vsgi-cgi.vala', fcgi = meson.get_compiler('c').find_library('fcgi', required: false) if fcgi.found() shared_library('vsgi-fastcgi', 'vsgi-fastcgi.vala', - dependencies: [glib, gobject, gio, gio_unix, soup, vsgi, fcgi], + dependencies: [glib, gobject, gio, gio_unix, gio_windows, soup, vsgi, fcgi], vala_args: ['--pkg=fcgi', '--vapidir=' + meson.current_source_dir()] + vala_defines, install: true, install_dir: '@0@/vsgi-@1@/servers'.format(get_option('libdir'), api_version)) diff --git a/src/vsgi/servers/vsgi-cgi.vala b/src/vsgi/servers/vsgi-cgi.vala index 5f2f65010..2416c8d84 100644 --- a/src/vsgi/servers/vsgi-cgi.vala +++ b/src/vsgi/servers/vsgi-cgi.vala @@ -70,9 +70,18 @@ namespace VSGI.CGI { } Idle.add (() => { +#if GIO_UNIX var connection = new Connection (this, new UnixInputStream (stdin.fileno (), true), new UnixOutputStream (stdout.fileno (), true)); +#elif GIO_WINDOWS + // TODO: obtain I/O handles + var connection = new Connection (this, + new Win32InputStream (null, true), + new Win32OutputStream (null, true)); +#else + // TODO: find an alternative +#endif var req = new Request (connection, Environ.@get ()); var res = new Response (req); diff --git a/src/vsgi/servers/vsgi-fastcgi.vala b/src/vsgi/servers/vsgi-fastcgi.vala index 425d9b7b3..fe831de54 100644 --- a/src/vsgi/servers/vsgi-fastcgi.vala +++ b/src/vsgi/servers/vsgi-fastcgi.vala @@ -55,13 +55,25 @@ namespace VSGI.FastCGI { return "Unknown error code '%d'".printf (error); } - private class StreamInputStream : UnixInputStream { + private class StreamInputStream : +#if GIO_UNIX + UnixInputStream +#else + InputStream +#endif + { public unowned global::FastCGI.Stream @in { construct; get; } +#if GIO_UNIX public StreamInputStream (int fd, global::FastCGI.Stream @in) { Object (fd: fd, close_fd: false, @in: @in); } +#else + public StreamInputStream (global::FastCGI.Stream @in) { + Object (@in: @in); + } +#endif public override ssize_t read (uint8[] buffer, Cancellable? cancellable = null) throws IOError { var read = this.in.read (buffer); @@ -84,15 +96,27 @@ namespace VSGI.FastCGI { } } - private class StreamOutputStream : UnixOutputStream { + private class StreamOutputStream : +#if GIO_UNIX + UnixOutputStream +#else + OutputStream +#endif + { public unowned global::FastCGI.Stream @out { construct; get; } public unowned global::FastCGI.Stream err { construct; get; } +#if GIO_UNIX public StreamOutputStream (int fd, global::FastCGI.Stream @out, global::FastCGI.Stream err) { Object (fd: fd, close_fd: false, @out: @out, err: err); } +#else + public StreamOutputStream (global::FastCGI.Stream @out, global::FastCGI.Stream err) { + Object (@out: @out, err: err); + } +#endif public override ssize_t write (uint8[] buffer, Cancellable? cancellable = null) throws IOError { var written = this.out.put_str (buffer); @@ -191,7 +215,10 @@ namespace VSGI.FastCGI { if (address == null) { fd = global::FastCGI.LISTENSOCK_FILENO; _uris.append (new Soup.URI ("fcgi+fd://%d/".printf (fd))); - } else if (address is UnixSocketAddress) { + } + +#if GIO_UNIX + else if (address is UnixSocketAddress) { var socket_address = address as UnixSocketAddress; fd = global::FastCGI.open_socket (socket_address.path, backlog); @@ -201,7 +228,10 @@ namespace VSGI.FastCGI { } _uris.append (new Soup.URI ("fcgi+unix://%s/".printf (socket_address.path))); - } else if (address is InetSocketAddress) { + } +#endif + + else if (address is InetSocketAddress) { var inet_address = address as InetSocketAddress; if (inet_address.get_family () == SocketFamily.IPV6) { @@ -311,8 +341,13 @@ namespace VSGI.FastCGI { yield; +#if GIO_UNIX this._input_stream = new StreamInputStream (fd, request.in); this._output_stream = new StreamOutputStream (fd, request.out, request.err); +#else + this._input_stream = new StreamInputStream (request.in); + this._output_stream = new StreamOutputStream (request.out, request.err); +#endif return true; } diff --git a/src/vsgi/vsgi-application.vala b/src/vsgi/vsgi-application.vala index 41ae1d4d1..870211675 100644 --- a/src/vsgi/vsgi-application.vala +++ b/src/vsgi/vsgi-application.vala @@ -147,7 +147,11 @@ public class VSGI.Application : GLib.Application { // socket path if (sockets != null) { foreach (var socket in sockets.get_bytestring_array ()) { +#if GIO_UNIX server.listen (new UnixSocketAddress (socket)); +#elif GIO_WINDOWS + // TODO: find an alternative +#endif } } @@ -205,12 +209,16 @@ public class VSGI.Application : GLib.Application { // keep the process (and workers) alive hold (); +#if GIO_UNIX // release on 'SIGTERM' Unix.signal_add (ProcessSignal.TERM, () => { release (); server.stop (); return false; }, Priority.LOW); +#elif GIO_WINDOWS + // TODO: find an alternative +#endif return 0; } diff --git a/src/vsgi/vsgi-server.vala b/src/vsgi/vsgi-server.vala index 161d79c5f..f33d08661 100644 --- a/src/vsgi/vsgi-server.vala +++ b/src/vsgi/vsgi-server.vala @@ -140,11 +140,15 @@ namespace VSGI { */ [Version (since = "0.3")] public virtual Pid fork () throws Error { +#if HAVE_FORK var pid = Posix.fork (); if (pid == -1) { throw new SpawnError.FORK (strerror (errno)); } return pid; +#else + return 0; +#endif } /** diff --git a/src/vsgi/vsgi-socket-server.vala b/src/vsgi/vsgi-socket-server.vala index bb5d983ee..2d2e77fe3 100644 --- a/src/vsgi/vsgi-socket-server.vala +++ b/src/vsgi/vsgi-socket-server.vala @@ -74,10 +74,14 @@ public abstract class VSGI.SocketServer : Server { effective_inet_address.get_address ().to_string (), effective_inet_address.get_port ()))); } - } else if (effective_address is UnixSocketAddress) { + } + +#if GIO_UNIX + else if (effective_address is UnixSocketAddress) { var effective_unix_address = effective_address as UnixSocketAddress; _uris.append (new Soup.URI ("%s+unix://%s/".printf (scheme, effective_unix_address.get_path ()))); } +#endif } } diff --git a/tests/socket-server-test.vala b/tests/socket-server-test.vala index e52c862f3..5dc7f9624 100644 --- a/tests/socket-server-test.vala +++ b/tests/socket-server-test.vala @@ -59,6 +59,7 @@ public int main (string[] args) { }); Test.add_func ("/socket_server/listen/unix_socket", () => { +#if GIO_UNIX var server = new MockedSocketServer (); try { @@ -70,9 +71,13 @@ public int main (string[] args) { } assert ("mock+unix://some-socket.sock/" == server.uris.data.to_string (false)); +#else + Test.skip ("This test require 'gio-unix-2.0' installed."); +#endif }); Test.add_func ("/socket_server/listen_socket", () => { +#if GIO_UNIX var server = new MockedSocketServer (); try { @@ -84,6 +89,9 @@ public int main (string[] args) { } finally { FileUtils.unlink ("some-socket.sock"); } +#else + Test.skip ("This test require 'gio-unix-2.0' installed."); +#endif }); return Test.run ();