[Libguestfs] [PATCH libnbd v2 2/3] Add outline framework for Go language bindings (golang).

Richard W.M. Jones rjones at redhat.com
Tue Mar 17 21:20:12 UTC 2020


This simply compiles, passes tests, but is only able open a handle.
This commit does not contain the full bindings.
---
 Makefile.am                                   |   2 +
 configure.ac                                  |  32 ++++
 generator/GoLang.ml                           | 150 ++++++++++++++++++
 generator/GoLang.mli                          |  19 +++
 generator/Makefile.am                         |   2 +
 generator/generator.ml                        |   3 +
 golang/Makefile.am                            |  58 +++++++
 golang/config-test.go                         |  34 ++++
 golang/examples/LICENSE-FOR-EXAMPLES          |  38 +++++
 golang/examples/Makefile.am                   |  21 +++
 golang/run-tests.sh                           |  24 +++
 golang/src/libguestfs.org/libnbd/.gitignore   |   1 +
 .../libnbd/libnbd_010_load_test.go            |  25 +++
 .../libnbd/libnbd_100_handle_test.go          |  29 ++++
 run.in                                        |  17 ++
 15 files changed, 455 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index bf2db68..a9f13ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,6 +43,8 @@ SUBDIRS = \
 	ocaml \
 	ocaml/examples \
 	ocaml/tests \
+	golang \
+	golang/examples \
 	interop \
 	fuzzing \
 	bash \
diff --git a/configure.ac b/configure.ac
index 9fd284b..36617fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -403,6 +403,34 @@ AS_IF([test "x$enable_python" != "xno"],[
 AM_CONDITIONAL([HAVE_PYTHON],
     [test "x$PYTHON" != "xno" && test "x$have_python_module" = "x1" ])
 
+dnl Golang.
+AC_ARG_ENABLE([golang],
+    AS_HELP_STRING([--disable-golang], [disable Go language bindings]),
+        [],
+        [enable_golang=yes])
+AS_IF([test "x$enable_golang" != "xno"],[
+    AC_CHECK_PROG([GOLANG],[go],[go],[no])
+    AS_IF([test "x$GOLANG" != "xno"],[
+        AC_MSG_CHECKING([if $GOLANG is usable])
+        AS_IF([$GOLANG run $srcdir/golang/config-test.go 2>&AS_MESSAGE_LOG_FD],[
+            AC_MSG_RESULT([yes])
+
+            # Substitute some golang environment.
+            GOOS=`$GOLANG env GOOS`
+            GOARCH=`$GOLANG env GOARCH`
+            GOROOT=`$GOLANG env GOROOT`
+            AC_SUBST([GOOS])
+            AC_SUBST([GOARCH])
+            AC_SUBST([GOROOT])
+        ],[
+            AC_MSG_RESULT([no])
+            AC_MSG_WARN([golang ($GOLANG) is installed but not usable])
+            GOLANG=no
+        ])
+    ])
+],[GOLANG=no])
+AM_CONDITIONAL([HAVE_GOLANG],[test "x$GOLANG" != "xno"])
+
 dnl Produce output files.
 AC_CONFIG_HEADERS([config.h])
 
@@ -423,6 +451,8 @@ AC_CONFIG_FILES([Makefile
                  fuse/Makefile
                  fuzzing/Makefile
                  generator/Makefile
+                 golang/Makefile
+                 golang/examples/Makefile
                  include/Makefile
                  interop/Makefile
                  lib/Makefile
@@ -472,6 +502,8 @@ feature "Bash tab completion .................... " \
 echo
 echo "Language bindings:"
 echo
+feature "Go ..................................... " \
+        test "x$HAVE_GOLANG_TRUE" = "x"
 feature "OCaml .................................. " \
         test "x$HAVE_OCAML_TRUE" = "x"
 feature "Python ................................. " \
diff --git a/generator/GoLang.ml b/generator/GoLang.ml
new file mode 100644
index 0000000..1b8f20b
--- /dev/null
+++ b/generator/GoLang.ml
@@ -0,0 +1,150 @@
+(* nbd client library in userspace: generator
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+(* Go language bindings. *)
+
+open Printf
+
+open API
+open Utils
+
+let generate_golang_libnbd_go () =
+  generate_header CStyle;
+
+  pr "\
+package libnbd
+
+/*
+#cgo CFLAGS:
+#cgo LDFLAGS: -lnbd
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include \"libnbd.h\"
+
+struct error {
+  char *error;
+  int errnum;
+};
+
+static void
+save_error (struct error *err)
+{
+  err->error = strdup (nbd_get_error ());
+  err->errnum = nbd_get_errno ();
+}
+
+static void
+free_error (struct error *err)
+{
+  free (err->error);
+}
+
+static struct nbd_handle *
+_nbd_create_wrapper (struct error *err)
+{
+  struct nbd_handle *r;
+
+  r = nbd_create ();
+  if (r == NULL)
+    save_error (err);
+  return r;
+}
+
+// There must be no blank line between end comment and import!
+// https://github.com/golang/go/issues/9733
+*/
+import \"C\"
+
+import (
+    \"fmt\"
+    \"runtime\"
+    \"syscall\"
+)
+
+/* Handle. */
+type Libnbd struct {
+    h *C.struct_nbd_handle
+}
+
+/* Convert handle to string (just for debugging). */
+func (h *Libnbd) String () string {
+    return \"&Libnbd{}\"
+}
+
+/* All functions (except Close) return ([result,] LibnbdError). */
+type LibnbdError struct {
+    Op string                // operation which failed
+    Errmsg string            // string (nbd_get_error)
+    Errno syscall.Errno      // errno (nbd_get_errno)
+}
+
+func (e *LibnbdError) String() string {
+    if e.Errno != 0 {
+        return fmt.Sprintf (\"%%s: %%s\", e.Op, e.Errmsg);
+    } else {
+        return fmt.Sprintf (\"%%s: %%s: %%s\", e.Op, e.Errmsg, e.Errno);
+    }
+}
+
+/* Implement the error interface */
+func (e *LibnbdError) Error() string {
+     return e.String()
+}
+
+func get_error (op string, c_err C.struct_error) *LibnbdError {
+    errmsg := C.GoString (c_err.error)
+    errno := syscall.Errno (c_err.errnum)
+    return &LibnbdError{ Op : op, Errmsg : errmsg, Errno : errno }
+}
+
+func closed_handle_error (op string) *LibnbdError {
+    return &LibnbdError{ Op : op, Errmsg : \"handle is closed\",
+                         Errno : syscall.Errno (0) }
+}
+
+/* Create a new handle. */
+func Create () (*Libnbd, error) {
+    c_err := C.struct_error{}
+    c_h := C._nbd_create_wrapper (&c_err)
+    if c_h == nil {
+        err := get_error (\"create\", c_err)
+        C.free_error (&c_err)
+        return nil, err
+    }
+    h := &Libnbd{h : c_h}
+    // Finalizers aren't guaranteed to run, but try having one anyway ...
+    runtime.SetFinalizer (h, (*Libnbd).Close)
+    return h, nil
+}
+
+/* Close the handle. */
+func (h *Libnbd) Close () *LibnbdError {
+    if h.h == nil {
+        return closed_handle_error (\"close\")
+    }
+    C.nbd_close (h.h)
+    h.h = nil
+    return nil
+}
+
+";
diff --git a/generator/GoLang.mli b/generator/GoLang.mli
new file mode 100644
index 0000000..b8ec1b5
--- /dev/null
+++ b/generator/GoLang.mli
@@ -0,0 +1,19 @@
+(* nbd client library in userspace: generator
+ * Copyright (C) 2013-2020 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *)
+
+val generate_golang_libnbd_go : unit -> unit
diff --git a/generator/Makefile.am b/generator/Makefile.am
index e499ca8..0389d70 100644
--- a/generator/Makefile.am
+++ b/generator/Makefile.am
@@ -57,6 +57,8 @@ sources = \
 	Python.ml \
 	OCaml.mli \
 	OCaml.ml \
+	GoLang.mli \
+	GoLang.ml \
 	generator.ml \
 	$(NULL)
 
diff --git a/generator/generator.ml b/generator/generator.ml
index 1c97492..817c032 100755
--- a/generator/generator.ml
+++ b/generator/generator.ml
@@ -55,3 +55,6 @@ let () =
   output_to "ocaml/NBD.mli" OCaml.generate_ocaml_nbd_mli;
   output_to "ocaml/NBD.ml" OCaml.generate_ocaml_nbd_ml;
   output_to "ocaml/nbd-c.c" OCaml.generate_ocaml_nbd_c;
+
+  output_to "golang/src/libguestfs.org/libnbd/libnbd.go"
+    GoLang.generate_golang_libnbd_go;
diff --git a/golang/Makefile.am b/golang/Makefile.am
new file mode 100644
index 0000000..47234ff
--- /dev/null
+++ b/golang/Makefile.am
@@ -0,0 +1,58 @@
+# nbd client library in userspace
+# Copyright (C) 2013-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; 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
+
+# http://golang.org/doc/code.html#Organization
+pkg = libguestfs.org/libnbd
+
+source_files = \
+	src/$(pkg)/libnbd.go \
+	src/$(pkg)/libnbd_*_test.go
+
+generator_built = \
+	$(source_files)
+
+EXTRA_DIST = \
+	src/$(pkg)/.gitignore \
+	$(generator_built) \
+	config-test.go \
+	run-tests.sh
+
+if HAVE_GOLANG
+
+golangpkgdir = $(GOROOT)/pkg/$(GOOS)_$(GOARCH)/$(pkg)
+golangsrcdir = $(GOROOT)/src/pkg/$(pkg)
+
+golangpkg_DATA = \
+	pkg/$(GOOS)_$(GOARCH)/$(pkg).a
+
+pkg/$(GOOS)_$(GOARCH)/$(pkg).a: src/$(pkg)/libnbd.go
+	$(top_builddir)/run $(GOLANG) install $(pkg)
+
+golangsrc_DATA = $(source_files)
+
+TESTS_ENVIRONMENT = pkg=$(pkg) LIBNBD_DEBUG=1
+LOG_COMPILER = $(top_builddir)/run
+TESTS = run-tests.sh
+
+endif
+
+CLEANFILES += src/$(pkg)/*~
+
+clean-local:
+	rm -rf pkg
diff --git a/golang/config-test.go b/golang/config-test.go
new file mode 100644
index 0000000..e104c71
--- /dev/null
+++ b/golang/config-test.go
@@ -0,0 +1,34 @@
+/* libnbd Go configuration test
+ * Copyright (C) 2013-2020 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
+ */
+
+/* This is called from ./configure to check that golang works
+ * and is above the minimum required version.
+ */
+
+package main
+
+func main() {
+	/* XXX Check for minimum runtime.Version() >= "go1.1.1"
+         * Unfortunately go version numbers are not easy to parse.
+         * They have the 3 formats "goX.Y.Z", "release.rN" or
+         * "weekly.YYYY-MM-DD".  The latter two formats are mostly
+         * useless, and the first one is hard to parse.  See also
+         * cmpGoVersion in
+         * http://web.archive.org/web/20130402235148/http://golang.org/src/cmd/go/get.go?m=text
+         */
+}
diff --git a/golang/examples/LICENSE-FOR-EXAMPLES b/golang/examples/LICENSE-FOR-EXAMPLES
new file mode 100644
index 0000000..4986466
--- /dev/null
+++ b/golang/examples/LICENSE-FOR-EXAMPLES
@@ -0,0 +1,38 @@
+The files in the golang/examples/ directory are licensed under this
+very permissive BSD license.  This means that you can copy, use, adapt
+and modify them without any significant restrictions.  You can also
+combine them with proprietary code or include them in code that is
+distributed under other open source licenses.
+
+----------------------------------------------------------------------
+
+libnbd examples
+Copyright (C) 2013-2020 Red Hat Inc.
+
+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.
diff --git a/golang/examples/Makefile.am b/golang/examples/Makefile.am
new file mode 100644
index 0000000..90498ab
--- /dev/null
+++ b/golang/examples/Makefile.am
@@ -0,0 +1,21 @@
+# nbd client library in userspace
+# Copyright (C) 2013-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; 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
+
+EXTRA_DIST = \
+	LICENSE-FOR-EXAMPLES
diff --git a/golang/run-tests.sh b/golang/run-tests.sh
new file mode 100755
index 0000000..a155819
--- /dev/null
+++ b/golang/run-tests.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -
+# nbd client library in userspace
+# Copyright (C) 2013-2020 Red Hat Inc.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+set -e
+
+# The -count=1 parameter is the "idiomatic way to bypass test caching".
+# https://golang.org/doc/go1.10#test
+# The -v option enables verbose output.
+$GOLANG test -count=1 -v $pkg
diff --git a/golang/src/libguestfs.org/libnbd/.gitignore b/golang/src/libguestfs.org/libnbd/.gitignore
new file mode 100644
index 0000000..a2ce7eb
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/.gitignore
@@ -0,0 +1 @@
+/libnbd.go
diff --git a/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go b/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go
new file mode 100644
index 0000000..24cfe66
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/libnbd_010_load_test.go
@@ -0,0 +1,25 @@
+/* libnbd golang tests
+ * Copyright (C) 2013-2020 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.
+ */
+
+package libnbd
+
+import "testing"
+
+func Test010Load (t *testing.T) {
+	/* Nothing - just test that the library can be linked to. */
+}
diff --git a/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go b/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go
new file mode 100644
index 0000000..a3d933d
--- /dev/null
+++ b/golang/src/libguestfs.org/libnbd/libnbd_100_handle_test.go
@@ -0,0 +1,29 @@
+/* libnbd golang tests
+ * Copyright (C) 2013-2020 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.
+ */
+
+package libnbd
+
+import "testing"
+
+func Test100Handle (t *testing.T) {
+	h, err := Create ()
+	if err != nil {
+		t.Errorf ("could not create handle: %s", err)
+	}
+	h.Close ()
+}
diff --git a/run.in b/run.in
index 0411c85..9ffece5 100755
--- a/run.in
+++ b/run.in
@@ -78,6 +78,23 @@ export PYTHONPATH
 prepend CAML_LD_LIBRARY_PATH "$b/ocaml"
 export CAML_LD_LIBRARY_PATH
 
+# For golang.
+export GOLANG="@GOLANG@"
+prepend GOPATH "$b/golang"
+export GOPATH
+if [ -z "$CGO_CFLAGS" ]; then
+    CGO_CFLAGS="-I$s/include -I$b"
+else
+    CGO_CFLAGS="$CGO_CFLAGS -I$s/include -I$b"
+fi
+export CGO_CFLAGS
+if [ -z "$CGO_LDFLAGS" ]; then
+    CGO_LDFLAGS="-L$b/lib/.libs"
+else
+    CGO_LDFLAGS="$CGO_LDFLAGS -L$b/lib/.libs"
+fi
+export CGO_LDFLAGS
+
 # This is a cheap way to find some use-after-free and uninitialized
 # read problems when using glibc.
 export MALLOC_CHECK_=1
-- 
2.25.0




More information about the Libguestfs mailing list