>From 0d20c4cd49f0f884020a4b41651241449896cd6d Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 21 Oct 2015 13:48:39 +0100 Subject: [PATCH] Add Rust (language) bindings. On Fedora you will need to install the Rust copr from: https://copr.fedoraproject.org/coprs/fabiand/rust-binary/ until the package is added to Fedora: https://bugzilla.redhat.com/show_bug.cgi?id=915043 --- .gitignore | 5 ++ Makefile.am | 3 ++ README | 2 + configure.ac | 17 ++++++ generator/Makefile.am | 2 + generator/main.ml | 3 ++ generator/rust.ml | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++ rust/Cargo.toml.in | 9 ++++ rust/Makefile.am | 30 +++++++++++ rust/src/.gitignore | 0 src/guestfs.pod | 2 + 11 files changed, 220 insertions(+) create mode 100644 generator/rust.ml create mode 100644 rust/Cargo.toml.in create mode 100644 rust/Makefile.am create mode 100644 rust/src/.gitignore diff --git a/.gitignore b/.gitignore index d5c5d1e..dcf9d63 100644 --- a/.gitignore +++ b/.gitignore @@ -468,6 +468,11 @@ Makefile.in /ruby/ext/guestfs/mkmf.log /ruby/Rakefile /ruby/stamp-rdoc +/rust/Cargo.lock +/rust/Cargo.toml +/rust/src/ffi.rs +/rust/src/lib.rs +/rust/target /run /sparsify/.depend /sparsify/stamp-virt-sparsify.pod diff --git a/Makefile.am b/Makefile.am index 713df42..aa96fc3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -123,6 +123,9 @@ endif if HAVE_GOLANG SUBDIRS += golang golang/examples endif +if HAVE_RUST +SUBDIRS += rust +endif # Unconditional because nothing is built yet. SUBDIRS += csharp diff --git a/README b/README index 19a1fb2..0669806 100644 --- a/README +++ b/README @@ -223,6 +223,8 @@ The full requirements are described below. +--------------+-------------+---+-----------------------------------------+ | golang | 1.1.1 | O | For the Go bindings. | +--------------+-------------+---+-----------------------------------------+ +| rustc | 1.0 | O | For the Rust bindings. | ++--------------+-------------+---+-----------------------------------------+ | valgrind | | O | For testing for memory problems. | +--------------+-------------+---+-----------------------------------------+ | Sys::Virt | | O | Perl bindings for libvirt. | diff --git a/configure.ac b/configure.ac index 4f6650e..e5b8ade 100644 --- a/configure.ac +++ b/configure.ac @@ -1578,6 +1578,21 @@ AS_IF([test "x$enable_golang" != "xno"],[ ],[GOLANG=no]) AM_CONDITIONAL([HAVE_GOLANG],[test "x$GOLANG" != "xno"]) +dnl Rust compiler. +AC_ARG_ENABLE([rust], + AS_HELP_STRING([--disable-rust], [disable Rust language bindings]), + [], + [enable_rust=yes]) +AS_IF([test "x$enable_rust" != "xno"],[ + AC_CHECK_PROG([RUSTC],[rustc],[rustc],[no]) + AC_CHECK_PROG([CARGO],[cargo],[cargo],[no]) +],[ + RUSTC=no + CARGO=no +]) +AM_CONDITIONAL([HAVE_RUST], + [test "x$RUSTC" != "xno" && test "x$CARGO" != "xno"]) + dnl Check for Perl modules needed by Perl virt tools (virt-df, etc.) AS_IF([test "x$PERL" != "xno"],[ missing_perl_modules=no @@ -1791,6 +1806,8 @@ AC_CONFIG_FILES([Makefile ruby/Rakefile ruby/examples/Makefile ruby/ext/guestfs/extconf.rb + rust/Cargo.toml + rust/Makefile sparsify/Makefile src/Makefile src/libguestfs.pc diff --git a/generator/Makefile.am b/generator/Makefile.am index a3fe50d..34ac5c5 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -48,6 +48,7 @@ sources = \ prepopts.mli \ python.ml \ ruby.ml \ + rust.ml \ structs.ml \ structs.mli \ tests_c_api.ml \ @@ -85,6 +86,7 @@ objects = \ lua.cmo \ gobject.cmo \ golang.cmo \ + rust.cmo \ bindtests.cmo \ errnostring.cmo \ customize.cmo \ diff --git a/generator/main.ml b/generator/main.ml index 1e0e7d6..d56f028 100644 --- a/generator/main.ml +++ b/generator/main.ml @@ -43,6 +43,7 @@ open Erlang open Lua open Gobject open Golang +open Rust open Bindtests open Errnostring open Customize @@ -165,6 +166,8 @@ Run it from the top source directory using the command output_to "lua/bindtests.lua" generate_lua_bindtests; output_to "golang/src/libguestfs.org/guestfs/guestfs.go" generate_golang_go; output_to "golang/bindtests.go" generate_golang_bindtests; + output_to "rust/src/ffi.rs" generate_rust_ffi_rs; + output_to "rust/src/lib.rs" generate_rust_lib_rs; output_to "gobject/bindtests.js" generate_gobject_js_bindtests; output_to "gobject/Makefile.inc" generate_gobject_makefile; diff --git a/generator/rust.ml b/generator/rust.ml new file mode 100644 index 0000000..8678e91 --- /dev/null +++ b/generator/rust.ml @@ -0,0 +1,147 @@ +(* libguestfs + * Copyright (C) 2015 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *) + +(* Please read generator/README first. *) + +open Printf + +open Types +open Utils +open Pr +open Docstrings +open Optgroups +open Actions +open Structs +open C +open Events + +(* Generate rust bindings. *) + +let generate_rust_ffi_rs () = + generate_header CPlusPlusStyle LGPLv2plus; + + pr "\ +use libc::{c_char, c_uint, int64_t}; + +// Represents the opaque handle (guestfs_h). +#[allow(non_camel_case_types)] +pub enum guestfs_h {} + +// XXX generate +#[repr(C)] +struct _version { + pub _major: int64_t, + pub _minor: int64_t, + pub _release: int64_t, + pub _extra: *const c_char, +} + +#[link (name = \"guestfs\")] +extern { + pub fn guestfs_create () -> *mut guestfs_h; + pub fn guestfs_create_flags (flags: c_uint, ...) -> *mut guestfs_h; + pub fn guestfs_close (g: *mut guestfs_h); + + pub fn guestfs_last_error (g: *mut guestfs_h) -> *const c_char; + + // XXX generate these + pub fn guestfs_version (g: *mut guestfs_h) -> *mut _version; + pub fn guestfs_free_version (version: *mut _version); +} + +" + +let generate_rust_lib_rs () = + generate_header CPlusPlusStyle LGPLv2plus; + + pr "\ +extern crate libc; + +use std::ffi::CStr; +use std::str; +use std::sync::Arc; + +// Temporarily allow dead_code in the ffi submodule. Eventually +// we can remove this once every ffi function has a safe wrapper. XXX +#[allow(dead_code)] +mod ffi; + +struct GuestfsHandleInternal { + g: *mut ffi::guestfs_h, +} + +impl Drop for GuestfsHandleInternal { + fn drop (&mut self) { + unsafe { ffi::guestfs_close (self.g); } + } +} + +pub struct GuestfsHandle { + rc : Arc, +} + +// XXX generate +pub struct Version { + pub major: i64, + pub minor: i64, + pub release: i64, + pub extra: String, +} + +fn get_last_error (g: *mut ffi::guestfs_h) -> String { + let error_cstr = unsafe { ffi::guestfs_last_error (g) }; + let error_buf = unsafe { CStr::from_ptr (error_cstr).to_bytes() }; + let error = str::from_utf8 (error_buf).unwrap().to_owned(); + return error; +} + +impl GuestfsHandle { + pub fn create () -> Result { + let g = unsafe { ffi::guestfs_create () }; + if g.is_null() { + //let errno = Error::last_os_error().raw_os_error(); + // XXX convert errno to a string + return Err (\"XXX\".to_string()); + } + + let rc = Arc::new (GuestfsHandleInternal { g: g }); + Ok (GuestfsHandle { rc: rc }) + } + + // XXX generate these + pub fn version (&mut self) -> Result { + let v = unsafe { ffi::guestfs_version (self.rc.g) }; + if v.is_null() { + return Err (get_last_error (self.rc.g)); + } + let major = unsafe { (*v)._major }; + let minor = unsafe { (*v)._minor }; + let release = unsafe { (*v)._release }; + let extra_cstr = unsafe { (*v)._extra }; + let extra_buf = unsafe { CStr::from_ptr (extra_cstr).to_bytes() }; + let extra = str::from_utf8 (extra_buf).unwrap().to_owned(); + unsafe { ffi::guestfs_free_version (v) }; + Ok (Version { + major: major, + minor: minor, + release: release, + extra: extra, + }) + } +} +" diff --git a/rust/Cargo.toml.in b/rust/Cargo.toml.in new file mode 100644 index 0000000..11d113e --- /dev/null +++ b/rust/Cargo.toml.in @@ -0,0 +1,9 @@ +[package] +name = "guestfs" +version = "@PACKAGE_VERSION@" +authors = ["libguestfs authors "] +description = "Library for accessing and modifying virtual machine images" +repository = "https://github.com/libguestfs/libguestfs" + +[dependencies] +libc = "*" diff --git a/rust/Makefile.am b/rust/Makefile.am new file mode 100644 index 0000000..5c363f4 --- /dev/null +++ b/rust/Makefile.am @@ -0,0 +1,30 @@ +# libguestfs Rust bindings +# Copyright (C) 2015 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +include $(top_srcdir)/subdir-rules.mk + +generator_built = \ + src/ffi.rs \ + src/lib.rs + +EXTRA_DIST = \ + $(generator_built) + +if HAVE_RUST + + +endif diff --git a/rust/src/.gitignore b/rust/src/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/src/guestfs.pod b/src/guestfs.pod index f8d7e2c..31b0ddf 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -4606,6 +4606,8 @@ L command and documentation. =item F +=item F + Language bindings. =back -- 2.5.0