Richard W.M. Jones
2019-Feb-08 11:55 UTC
[Libguestfs] [PATCH nbdkit] Add support for writing plugins in Rust.
This adds very rough support for writing nbdkit plugins in Rust. This is not very idiomatic -- essentially we're handling the direct C calls from nbdkit in Rust. We have to use ‘unsafe’ in a few places because there's no way to tell the Rust code that nbdkit satisfies guarantees (eg. around thread safety, always returning leaked pointers back to the close function, always doing bounds checking). See the TODO file changes for the mising bits. TBH there's not much to review here. Rich.
Richard W.M. Jones
2019-Feb-08 11:55 UTC
[Libguestfs] [PATCH nbdkit] Add support for writing plugins in Rust.
--- .gitignore | 3 + README | 4 +- TODO | 13 +++ configure.ac | 12 +++ docs/nbdkit-plugin.pod | 6 +- docs/nbdkit.pod | 1 + plugins/rust/Cargo.toml.in | 14 +++ plugins/rust/Makefile.am | 65 ++++++++++++ plugins/rust/examples/ramdisk.rs | 119 +++++++++++++++++++++ plugins/rust/nbdkit-rust-plugin.pod | 99 ++++++++++++++++++ plugins/rust/src/lib.rs | 155 ++++++++++++++++++++++++++++ 11 files changed, 487 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 91229c6..e1c767c 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,9 @@ Makefile.in /missing /nbdkit /plugins/example4/nbdkit-example4-plugin +/plugins/rust/Cargo.lock +/plugins/rust/Cargo.toml +/plugins/rust/target /plugins/tar/nbdkit-tar-plugin /podwrapper.pl /server/nbdkit diff --git a/README b/README index 5e6c886..4a5ef4b 100644 --- a/README +++ b/README @@ -15,8 +15,8 @@ The key features are: * Well-documented, simple plugin API with a stable ABI guarantee. Lets you export “unconventional” block devices easily. - * You can write plugins in C, Lua, Perl, Python, OCaml, Ruby, shell - script or Tcl. + * You can write plugins in C, Lua, Perl, Python, OCaml, Ruby, Rust, + shell script or Tcl. * Filters can be stacked in front of plugins to transform the output. diff --git a/TODO b/TODO index 48c43a3..81c8ca9 100644 --- a/TODO +++ b/TODO @@ -164,3 +164,16 @@ Build-related not play nicely with --prefix builds for a non-root user. * Port to Windows. + +Rust plugins +------------ + +* Consider supporting a more idiomatic style for writing Rust plugins. + +* Better documentation. + +* Add tests. + +* There is no attempt to ‘make install’ or otherwise package the + crate. Since it looks as if Rust code is normally distributed as + source it's not clear what that would even mean. diff --git a/configure.ac b/configure.ac index d87abd4..a0ed770 100644 --- a/configure.ac +++ b/configure.ac @@ -545,6 +545,15 @@ AS_IF([test "x$OCAMLOPT" != "xno" && test "x$enable_ocaml" != "xno"],[ AM_CONDITIONAL([HAVE_OCAML],[test "x$OCAMLOPT" != "xno" && test "x$ocaml_link_shared" = "xyes"]) +dnl For developing plugins in Rust, optional. +AC_CHECK_PROG([CARGO],[cargo],[cargo],[no]) +AC_ARG_ENABLE([rust], + [AS_HELP_STRING([--disable-rust], [disable Rust plugin])], + [], + [enable_rust=yes]) +AM_CONDITIONAL([HAVE_RUST], + [test "x$CARGO" != "xno" && test "x$enable_ruby" != "xno"]) + dnl Check for Ruby, for embedding in the Ruby plugin. AC_CHECK_PROG([RUBY],[ruby],[ruby],[no]) AC_ARG_ENABLE([ruby], @@ -765,6 +774,7 @@ lang_plugins="\ perl \ python \ ruby \ + rust \ sh \ tcl \ " @@ -854,6 +864,8 @@ AC_CONFIG_FILES([Makefile plugins/python/Makefile plugins/random/Makefile plugins/ruby/Makefile + plugins/rust/Cargo.toml + plugins/rust/Makefile plugins/sh/Makefile plugins/split/Makefile plugins/streaming/Makefile diff --git a/docs/nbdkit-plugin.pod b/docs/nbdkit-plugin.pod index 72f6d40..a7a6a15 100644 --- a/docs/nbdkit-plugin.pod +++ b/docs/nbdkit-plugin.pod @@ -66,6 +66,7 @@ L<nbdkit-ocaml-plugin(3)>, L<nbdkit-perl-plugin(3)>, L<nbdkit-python-plugin(3)>, L<nbdkit-ruby-plugin(3)>, +L<nbdkit-rust-plugin(3)>, L<nbdkit-sh-plugin(3)>, L<nbdkit-tcl-plugin(3)>. @@ -950,8 +951,8 @@ which defines C<$(NBDKIT_PLUGINDIR)> in automake-generated Makefiles. =head1 WRITING PLUGINS IN OTHER PROGRAMMING LANGUAGES You can also write nbdkit plugins in Lua, OCaml, Perl, Python, Ruby, -shell script or Tcl. Other programming languages may be offered in -future. +Rust, shell script or Tcl. Other programming languages may be offered +in future. For more information see: L<nbdkit-lua-plugin(3)>, @@ -959,6 +960,7 @@ L<nbdkit-ocaml-plugin(3)>, L<nbdkit-perl-plugin(3)>, L<nbdkit-python-plugin(3)>, L<nbdkit-ruby-plugin(3)>, +L<nbdkit-rust-plugin(3)>, L<nbdkit-sh-plugin(3)>, L<nbdkit-tcl-plugin(3)>. diff --git a/docs/nbdkit.pod b/docs/nbdkit.pod index 1100b97..a9c64c7 100644 --- a/docs/nbdkit.pod +++ b/docs/nbdkit.pod @@ -517,6 +517,7 @@ L<nbdkit-ocaml-plugin(3)>, L<nbdkit-perl-plugin(3)>, L<nbdkit-python-plugin(3)>, L<nbdkit-ruby-plugin(3)>, +L<nbdkit-rust-plugin(3)>, L<nbdkit-sh-plugin(3)>, L<nbdkit-tcl-plugin(3)>. diff --git a/plugins/rust/Cargo.toml.in b/plugins/rust/Cargo.toml.in new file mode 100644 index 0000000..f7a9f41 --- /dev/null +++ b/plugins/rust/Cargo.toml.in @@ -0,0 +1,14 @@ +[package] +name = "nbdkit" +version = "@VERSION@" +authors = ["Richard W.M. Jones <rjones@redhat.com>"] +edition = "2018" + +[dependencies] +libc = "0.2" +# lazy_static is used by the example. +lazy_static = "1.2.0" + +[[example]] +name = "ramdisk" +crate-type = ["cdylib"] diff --git a/plugins/rust/Makefile.am b/plugins/rust/Makefile.am new file mode 100644 index 0000000..ccdb000 --- /dev/null +++ b/plugins/rust/Makefile.am @@ -0,0 +1,65 @@ +# nbdkit +# Copyright (C) 2019 Red Hat Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Red Hat nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +include $(top_srcdir)/common-rules.mk + +EXTRA_DIST = \ + Cargo.toml.in \ + examples/ramdisk.rs \ + nbdkit-rust-plugin.pod \ + src/lib.rs + +if HAVE_RUST + +noinst_SCRIPTS = \ + target/release/libnbdkit.rlib \ + target/release/examples/libramdisk.so + +target/release/libnbdkit.rlib: Cargo.toml src/lib.rs + cargo build --release + +target/release/examples/libramdisk.so: Cargo.toml examples/ramdisk.rs + cargo build --release --example ramdisk + +if HAVE_POD + +man_MANS = nbdkit-rust-plugin.3 +CLEANFILES += $(man_MANS) + +nbdkit-rust-plugin.3: nbdkit-rust-plugin.pod + $(PODWRAPPER) --section=3 --man $@ \ + --html $(top_builddir)/html/$@.html \ + $< + +endif HAVE_POD + +endif diff --git a/plugins/rust/examples/ramdisk.rs b/plugins/rust/examples/ramdisk.rs new file mode 100644 index 0000000..b03a50c --- /dev/null +++ b/plugins/rust/examples/ramdisk.rs @@ -0,0 +1,119 @@ +// nbdkit +// Copyright (C) 2019 Red Hat Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Red Hat nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. + +extern crate nbdkit; + +#[macro_use] +extern crate lazy_static; + +use libc::*; +use std::ptr; +use std::os::raw::c_int; +use std::sync::Mutex; + +use nbdkit::*; +use nbdkit::ThreadModel::*; + +// The RAM disk. +lazy_static! { + static ref DISK: Mutex<Vec<u8>> = Mutex::new (vec![0; 100 * 1024 * 1024]); +} + +struct Handle { + // Box::new doesn't allocate anything unless we put some dummy + // fields here. In a real implementation you would put per-handle + // data here as required. + _not_used: i32, +} + +extern fn ramdisk_open (_readonly: c_int) -> *mut c_void { + let h = Handle {_not_used: 0}; + let h = Box::new(h); + return Box::into_raw(h) as *mut c_void; +} + +extern fn ramdisk_close (h: *mut c_void) { + let h = unsafe { Box::from_raw(h as *mut Handle) }; + drop (h); +} + +extern fn ramdisk_get_size (_h: *mut c_void) -> int64_t { + return DISK.lock().unwrap().capacity() as int64_t; +} + +extern fn ramdisk_pread (_h: *mut c_void, buf: *mut c_char, count: uint32_t, + offset: uint64_t, _flags: uint32_t) -> c_int { + let offset = offset as usize; + let count = count as usize; + let disk = DISK.lock().unwrap(); + unsafe { + ptr::copy_nonoverlapping (&disk[offset], buf as *mut u8, count); + } + return 0; +} + +extern fn ramdisk_pwrite (_h: *mut c_void, buf: *const c_char, count: uint32_t, + offset: uint64_t, _flags: uint32_t) -> c_int { + let offset = offset as usize; + let count = count as usize; + let mut disk = DISK.lock().unwrap(); + unsafe { + ptr::copy_nonoverlapping (buf as *const u8, &mut disk[offset], count); + } + return 0; +} + +// Every plugin must define a public, C-compatible plugin_init +// function which returns a pointer to an Plugin struct. +#[no_mangle] +pub extern fn plugin_init () -> *const Plugin { + // Plugin name. + // https://github.com/rust-lang/rfcs/issues/400 + let name = "ramdisk\0" as *const str as *const [c_char] as *const c_char; + + // Create a mutable plugin, setting the 5 required fields. + let mut plugin = Plugin::new ( + Parallel, + name, + ramdisk_open, + ramdisk_get_size, + ramdisk_pread + ); + // Update any other fields as required. + plugin.close = Some (ramdisk_close); + plugin.pwrite = Some (ramdisk_pwrite); + + // Return the pointer. + let plugin = Box::new(plugin); + // XXX Memory leak. + return Box::into_raw(plugin); +} diff --git a/plugins/rust/nbdkit-rust-plugin.pod b/plugins/rust/nbdkit-rust-plugin.pod new file mode 100644 index 0000000..d158762 --- /dev/null +++ b/plugins/rust/nbdkit-rust-plugin.pod @@ -0,0 +1,99 @@ +=head1 NAME + +nbdkit-rust-plugin - writing nbdkit plugins in Rust + +=head1 SYNOPSIS + + nbdkit /path/to/libplugin.so [arguments...] + +=head1 DESCRIPTION + +This manual page describes how to write nbdkit plugins in compiled +Rust code. Rust plugins are compiled to F<*.so> files (the same as +plugins written in C) and are used in the same way. + +=head1 WRITING A RUST NBDKIT PLUGIN + +Broadly speaking, Rust nbdkit plugins work like C ones, so you should +read L<nbdkit-plugin(3)> first. + +You should also look at C<plugins/rust/src/lib.rs> and +C<plugins/rust/examples/ramdisk.rs> in the nbdkit source tree, which +describe the plugin interface for Rust plugins and provides an +example. + +We may change how Rust plugins are written in future to make them more +idiomatic. At the moment each callback corresponds directly to a C +callback - in fact each is called directly from the server. + +Your Rust code should define a public C<plugin_init> function which +returns a pointer to a C<Plugin> struct. This struct is exactly +compatible with the C struct used by C plugins. + + #[no_mangle] + pub extern fn plugin_init () -> *const Plugin { + // Plugin name. + let name = "myplugin\0" + as *const str as *const [c_char] as *const c_char; + + // Create a mutable plugin, setting the 5 required fields. + let mut plugin = Plugin::new ( + Serialize_All_Requests, + name, + myplugin_open, + myplugin_get_size, + myplugin_pread + ); + // Update any other fields as required. + plugin.close = Some (myplugin_close); + plugin.pwrite = Some (myplugin_pwrite); + + // Return the pointer. + let plugin = Box::new(plugin); + return Box::into_raw(plugin); +} + +=head2 Compiling a Rust nbdkit plugin + +Because you are building a C-compatible shared library, the crate type +must be set to: + + crate-type = ["cdylib"] + +After compiling using C<cargo build> you can then use +C<libmyplugin.so> as an nbdkit plugin (see L<nbdkit(1)>, +L<nbdkit-plugin(3)>): + + nbdkit ./libmyplugin.so [args ...] + +=head2 Threads + +The first parameter of C<Plugin::new> is the thread model, which can +be one of the values in the table below. For more information on +thread models, see L<nbdkit-plugin(3)/THREADS>. + +=over 4 + +=item C<Serialize_Connections> + +=item C<Serialize_All_Requests> + +=item C<Serialize_Requests> + +=item C<Parallel> + +=back + +=head1 SEE ALSO + +L<nbdkit(1)>, +L<nbdkit-plugin(3)>, +L<cargo(1)>. + +=head1 AUTHORS + +Richard W.M. Jones + +=head1 COPYRIGHT + +Copyright (C) 2019 Red Hat Inc. diff --git a/plugins/rust/src/lib.rs b/plugins/rust/src/lib.rs new file mode 100644 index 0000000..23aa204 --- /dev/null +++ b/plugins/rust/src/lib.rs @@ -0,0 +1,155 @@ +// nbdkit +// Copyright (C) 2019 Red Hat Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Red Hat nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. + +extern crate libc; + +use libc::*; +use std::os::raw::c_int; +use std::mem; + +// This struct describes the plugin ABI which your plugin_init() +// function must return. +#[repr(C)] +pub struct Plugin { + _struct_size: uint64_t, + _api_version: c_int, + _thread_model: c_int, + + pub name: *const c_char, + pub longname: *const c_char, + pub version: *const c_char, + pub description: *const c_char, + + pub load: Option<extern fn ()>, + pub unload: Option<extern fn ()>, + + pub config: Option<extern fn (*const c_char, *const c_char)>, + pub config_complete: Option<extern fn () -> c_int>, + pub config_help: *const c_char, + + pub open: extern fn (c_int) -> *mut c_void, + pub close: Option<extern fn (*mut c_void)>, + + pub get_size: extern fn (*mut c_void) -> int64_t, + + pub can_write: Option<extern fn (*mut c_void) -> c_int>, + pub can_flush: Option<extern fn (*mut c_void) -> c_int>, + pub is_rotational: Option<extern fn (*mut c_void) -> c_int>, + pub can_trim: Option<extern fn (*mut c_void) -> c_int>, + + // Slots for old v1 API functions. + _pread_old: Option<extern fn ()>, + _pwrite_old: Option<extern fn ()>, + _flush_old: Option<extern fn ()>, + _trim_old: Option<extern fn ()>, + _zero_old: Option<extern fn ()>, + + errno_is_preserved: c_int, + + pub dump_plugin: Option<extern fn ()>, + + pub can_zero: Option<extern fn (*mut c_void) -> c_int>, + pub can_fua: Option<extern fn (*mut c_void) -> c_int>, + + pub pread: extern fn (h: *mut c_void, buf: *mut c_char, count: uint32_t, + offset: uint64_t, + flags: uint32_t) -> c_int, + pub pwrite: Option<extern fn (h: *mut c_void, buf: *const c_char, + count: uint32_t, offset: uint64_t, + flags: uint32_t) -> c_int>, + pub flush: Option<extern fn (h: *mut c_void, flags: uint32_t) -> c_int>, + pub trim: Option<extern fn (h: *mut c_void, + count: uint32_t, offset: uint64_t, + flags: uint32_t) -> c_int>, + pub zero: Option<extern fn (h: *mut c_void, + count: uint32_t, offset: uint64_t, + flags: uint32_t) -> c_int>, + + pub magic_config_key: *const c_char, + + pub can_multi_conn: Option<extern fn (h: *mut c_void) -> c_int>, +} + +pub enum ThreadModel { + SerializeConnections = 0, + SerializeAllRequests = 1, + SerializeRequests = 2, + Parallel = 3, +} + +impl Plugin { + pub fn new (thread_model: ThreadModel, + name: *const c_char, + open: extern fn (c_int) -> *mut c_void, + get_size: extern fn (*mut c_void) -> int64_t, + pread: extern fn (h: *mut c_void, buf: *mut c_char, + count: uint32_t, offset: uint64_t, + flags: uint32_t) -> c_int) -> Plugin { + Plugin { + _struct_size: mem::size_of::<Plugin>() as uint64_t, + _api_version: 2, + _thread_model: thread_model as c_int, + name: name, + longname: std::ptr::null(), + version: std::ptr::null(), + description: std::ptr::null(), + load: None, + unload: None, + config: None, + config_complete: None, + config_help: std::ptr::null(), + open: open, + close: None, + get_size: get_size, + can_write: None, + can_flush: None, + is_rotational: None, + can_trim: None, + _pread_old: None, + _pwrite_old: None, + _flush_old: None, + _trim_old: None, + _zero_old: None, + errno_is_preserved: 0, + dump_plugin: None, + can_zero: None, + can_fua: None, + pread: pread, + pwrite: None, + flush: None, + trim: None, + zero: None, + magic_config_key: std::ptr::null(), + can_multi_conn: None, + } + } +} -- 2.20.1
Eric Blake
2019-Feb-08 14:53 UTC
Re: [Libguestfs] [PATCH nbdkit] Add support for writing plugins in Rust.
On 2/8/19 5:55 AM, Richard W.M. Jones wrote:> ---> +* Consider supporting a more idiomatic style for writing Rust plugins. > +Considering I've written nothing in Rust, I'm no good at deciding what forms idiomatic Rust plugins.> +++ b/configure.ac > @@ -545,6 +545,15 @@ AS_IF([test "x$OCAMLOPT" != "xno" && test "x$enable_ocaml" != "xno"],[ > AM_CONDITIONAL([HAVE_OCAML],[test "x$OCAMLOPT" != "xno" && > test "x$ocaml_link_shared" = "xyes"]) > > +dnl For developing plugins in Rust, optional. > +AC_CHECK_PROG([CARGO],[cargo],[cargo],[no]) > +AC_ARG_ENABLE([rust], > + [AS_HELP_STRING([--disable-rust], [disable Rust plugin])], > + [], > + [enable_rust=yes]) > +AM_CONDITIONAL([HAVE_RUST], > + [test "x$CARGO" != "xno" && test "x$enable_ruby" != "xno"])Copy-and-paste bug: s/ruby/rust/> @@ -950,8 +951,8 @@ which defines C<$(NBDKIT_PLUGINDIR)> in automake-generated Makefiles. > =head1 WRITING PLUGINS IN OTHER PROGRAMMING LANGUAGES > > You can also write nbdkit plugins in Lua, OCaml, Perl, Python, Ruby, > -shell script or Tcl. Other programming languages may be offered in > -future. > +Rust, shell script or Tcl. Other programming languages may be offered > +in future.Pre-existing, s/in/in the/> +++ b/plugins/rust/Cargo.toml.in > @@ -0,0 +1,14 @@ > +[package] > +name = "nbdkit" > +version = "@VERSION@" > +authors = ["Richard W.M. Jones <rjones@redhat.com>"] > +edition = "2018"2019? Some form of @YEAR@ to make it auto-update from configure results?> +++ b/plugins/rust/examples/ramdisk.rs> + > +// Every plugin must define a public, C-compatible plugin_init > +// function which returns a pointer to an Plugin struct.s/an Plugin/a Plugin/ Otherwise, it seems to work (given my lack of Rust knowledge) -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org
Eric Blake
2019-Apr-24 13:53 UTC
Re: [Libguestfs] [PATCH nbdkit] Add support for writing plugins in Rust.
On 2/8/19 5:55 AM, Richard W.M. Jones wrote:> --- > .gitignore | 3 + > README | 4 +- > TODO | 13 +++ > configure.ac | 12 +++ > docs/nbdkit-plugin.pod | 6 +- > docs/nbdkit.pod | 1 + > plugins/rust/Cargo.toml.in | 14 +++ > plugins/rust/Makefile.am | 65 ++++++++++++ > plugins/rust/examples/ramdisk.rs | 119 +++++++++++++++++++++ > plugins/rust/nbdkit-rust-plugin.pod | 99 ++++++++++++++++++ > plugins/rust/src/lib.rs | 155 ++++++++++++++++++++++++++++ > 11 files changed, 487 insertions(+), 4 deletions(-)I'm just now noticing, but this may need further changes to be VPATH-friendly. 'make distcheck' fails with: make[4]: Entering directory '/home/eblake/nbdkit/nbdkit-1.13.1/_build/sub/plugins/rust' cargo build --release error: failed to parse manifest at `/home/eblake/nbdkit/nbdkit-1.13.1/_build/sub/plugins/rust/Cargo.toml` Caused by: no targets specified in the manifest either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present make[4]: *** [Makefile:682: target/release/libnbdkit.rlib] Error 101 make[4]: Leaving directory '/home/eblake/nbdkit/nbdkit-1.13.1/_build/sub/plugins/rust' [Note that make distcheck fails for other reasons as well, such as the fact that pkg-config gives results for bash-completion that tries to install into the live system rather than honoring --prefix. I've had threads on that in the past; those other failures later in the 'make distcheck' sequence mean we can't completely rely on it to ensure our package is self-contained and VPATH friendly, but it does help in catching some obvious problems even with those known failures] -- Eric Blake, Principal Software Engineer Red Hat, Inc. +1-919-301-3226 Virtualization: qemu.org | libvirt.org