On Tue, Mar 17, 2020 at 09:20:12PM +0000, Richard W.M. Jones wrote:
+ +/* +#cgo CFLAGS: +#cgo LDFLAGS: -lnbd
I assume you support pkg-config for libnbd, and thus you should just do #cgo pkg-config: libnbd
+ +#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.g... + */
I believe you can just achieve the version check using a build tag comment at the top of the source file eg to mandate go 1.10 or later: // +build go1.10 See build constraints here: https://golang.org/pkg/go/build/ Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|