From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andy Wingo Subject: Re: [Patch] go@1.4 Date: Sun, 29 May 2016 19:49:39 +0200 Message-ID: References: <8737p2ynsx.fsf@mailerver.i-did-not-set--mail-host-address--so-tickle-me> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:53002) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b74r9-0003xg-3m for guix-devel@gnu.org; Sun, 29 May 2016 13:50:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b74r4-0006tu-D2 for guix-devel@gnu.org; Sun, 29 May 2016 13:50:30 -0400 Received: from pb-sasl1.pobox.com ([64.147.108.66]:54594 helo=sasl.smtp.pobox.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b74r4-0006m2-7P for guix-devel@gnu.org; Sun, 29 May 2016 13:50:26 -0400 In-Reply-To: <8737p2ynsx.fsf@mailerver.i-did-not-set--mail-host-address--so-tickle-me> (Matthew Jordan's message of "Sat, 28 May 2016 15:39:42 -0400") List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" To: Matthew Jordan Cc: guix-devel Hi! I also took a look at this package over the weekend but was away from the internet. It turns out that what is needed is to add "-rpath" invocations to Go itself. The issue is that Go binaries are still dynamically linked to libgcc_s, but of course there is no useful default search path in which the run-time part of the dynamic linker will find libgcc_s.so.1. Here's a build phase that works for go-1.4: (arguments `(#:phases (modify-phases %standard-phases (delete 'configure) (add-after 'patch-generated-file-shebangs 'chdir (lambda _ (chdir "src"))) (add-before 'build 'prebuild (lambda* (#:key inputs outputs #:allow-other-keys) (define-syntax-rule (disable-go-tests ((file) test ...) ...) (begin (substitute* file (((string-append "Test" test)) (string-append "DisabledTest" test)) ...) ...)) (let* ((gccgo (assoc-ref inputs "gccgo")) (gcclib (string-append (assoc-ref inputs "gcc:lib") "/l= ib")) (ld (string-append (assoc-ref inputs "glibc") "/lib")) (loader (car (find-files ld "^ld-linux.+"))) (net-base (assoc-ref inputs "net-base")) (tzdata-path (string-append (assoc-ref inputs "tzdata") "/share/zon= einfo")) (output (assoc-ref outputs "out"))) (substitute* "cmd/go/build.go" (("cgoldflags :=3D \\[\\]string\\{\\}") (string-append "cgoldflags :=3D []string{" "\"-rpath=3D" gcclib "\"" "}")) (("ldflags :=3D buildLdflags") (string-append "ldflags :=3D buildLdflags\n" "ldflags =3D append(ldflags, \"-r\")\n" "ldflags =3D append(ldflags, \"" gcclib "\")\n"))) ;; Disabling net/ tests (delete-file "net/multicast_test.go") (delete-file "net/parse_test.go") (delete-file "net/port_test.go") (substitute* "os/os_test.go" (("/usr/bin") (getcwd)) (("/bin/pwd") (which "pwd"))) (disable-go-tests (("os/os_test.go") "Hostname") (("net/net_test.go") "ShutdownUnix") (("net/dial_test.go") "DialTimeout") (("time/format_test.go") "ParseInSydney") (("os/exec/exec_test.go") "Echo" "CommandRelativeName" "CatStdin" "CatGoodAndBadFile" "ExitStatus" "Pipes" "StdinClose" "ExtraFiles") (("syscall/syscall_unix_test.go") "PassFD")) (substitute* "net/lookup_unix.go" (("/etc/protocols") (string-append net-base "/etc/protocol= s"))) (substitute* "time/zoneinfo_unix.go" (("/usr/share/zoneinfo/") tzdata-path)) (substitute* (find-files "cmd" "asm.c") (("/lib/ld-linux.*\\.so\\.[0-9]") loader))))) (replace 'build (lambda* (#:key inputs outputs #:allow-other-keys) (let* ((gccgo (assoc-ref inputs "gccgo")) (output (assoc-ref outputs "out"))) (setenv "CC" (which "gcc")) (setenv "GOOS" "linux") (setenv "GOROOT" (getcwd)) (setenv "GOROOT_BOOTSTRAP" gccgo) (setenv "GOROOT_FINAL" output) (setenv "CGO_ENABLED" "1") (zero? (system* "sh" "all.bash"))))) (replace 'install (lambda* (#:key outputs #:allow-other-keys) (let* ((output (assoc-ref outputs "out")) (docs (assoc-ref outputs "doc")) (tests (assoc-ref outputs "tests"))) (copy-recursively "../test" tests) (delete-file-recursively "../test") (copy-recursively "../api" (string-append docs "/api")) (delete-file-recursively "../api") (copy-recursively "../doc" (string-append docs "/doc")) (delete-file-recursively "../doc") (copy-recursively "../" output))))) #:tests? #f)) Please feel free to take this as yours, if you like :) For go 1.5, it's more complicated because of the new ability in Go to make shared libraries. I use this substitute* line: (substitute* "cmd/go/build.go" (("cgoldflags :=3D \\[\\]string\\{\\}") (string-append "cgoldflags :=3D []string{" "\"-rpath=3D" gcclib "\"" "}")) (("ldflags =3D setextld\\(ldflags, compiler\\)") (string-append "ldflags =3D setextld(ldflags, compiler)\n" "ldflags =3D append(ldflags, \"-r\")\n" "ldflags =3D append(ldflags, \"" gcclib "\")\n")) (("\"-lgcc_s\", ") (string-append "\"-Wl,-rpath=3D" gcclib "\", \"-lgcc_s\", "))) But then tests fail: ##### ../misc/cgo/testshared --- FAIL: TestTrivialExecutable (0.07s) shared_test.go:40: executing ./bin/trivial (trivial executable) failed ex= it status 127: ./bin/trivial: error while loading shared libraries: libruntime,sync-atom= ic.so: cannot open shared object file: No such file or directory shared_test.go:305: ./bin/trivial does not have rpath /tmp/guix-build-go-= 1.5.4.drv-6/go/pkg/linux_amd64_5577006791947779410_dynlink --- FAIL: TestCgoExecutable (0.54s) shared_test.go:40: executing ./bin/execgo (cgo executable) failed exit st= atus 127: ./bin/execgo: error while loading shared libraries: libruntime,sync-atomi= c.so: cannot open shared object file: No such file or directory --- FAIL: TestGopathShlib (0.14s) shared_test.go:305: ./bin/exe does not have rpath /tmp/guix-build-go-1.5.= 4.drv-6/go/pkg/linux_amd64_5577006791947779410_dynlink shared_test.go:305: ./bin/exe does not have rpath /tmp/guix-build-go-1.5.= 4.drv-6/testshared201992860/pkg/linux_amd64_5577006791947779410_dynlink shared_test.go:40: executing ./bin/exe (executable linked to GOPATH libra= ry) failed exit status 127: ./bin/exe: error while loading shared libraries: libruntime,sync-atomic.s= o: cannot open shared object file: No such file or directory --- FAIL: TestTwoGopathShlibs (0.15s) shared_test.go:40: executing ./bin/exe2 (executable linked to GOPATH libr= ary) failed exit status 127: ./bin/exe2: error while loading shared libraries: libruntime,sync-atomic.= so: cannot open shared object file: No such file or directory --- FAIL: TestABIChecking (0.09s) shared_test.go:661: exe failed, but without line "abi mismatch detected b= etween the executable and libdep.so"; got output: ./bin/exe: error while loading shared libraries: libruntime,sync-atomic.s= o: cannot open shared object file: No such file or directory And indeed. I modified the test to not delete the build dir and I find that while the runtime has the correct -rpath (as you can tell via ldd), the built executable does not: $ ldd bin/trivial linux-vdso.so.1 (0x00007ffdd8bc4000) libruntime,sync-atomic.so =3D> not found libgcc_s.so.1 =3D> /gnu/store/zzz0zjgyd7f515wmbnmb8i1kmrgwh7bq-gcc-4.9.3-= lib/lib/libgcc_s.so.1 (0x00007f43898c3000) libc.so.6 =3D> /gnu/store/8m00x5x8ykmar27s9248cmhnkdb2n54a-glibc-2.22/lib= /libc.so.6 (0x00007f438951e000) /gnu/store/8m00x5x8ykmar27s9248cmhnkdb2n54a-glibc-2.22/lib/ld-linux-x86-6= 4.so.2 (0x00007f4389ad9000) =20=20 I actually had another modification locally to add a -rpath for libc too, in case you can't reproduce this. Not sure. Anyway I think what's going on is this, that in go's linker when you are doing a shared link, that it will set -rpath automatically so that the executable has the right rpath -- EXCEPT that if you specify the rpath manually on the command line, that it disables this behavior. Most of the rpath logic is in cmd/go/build.go, but this bit is in the lower-level tool cmd/link/internal/ld.go: if Linkshared { seenDirs :=3D make(map[string]bool) seenLibs :=3D make(map[string]bool) addshlib :=3D func(path string) { dir, base :=3D filepath.Split(path) if !seenDirs[dir] { argv =3D append(argv, "-L"+dir) if !rpath.set { argv =3D append(argv, "-Wl,-rpath=3D"+dir) } seenDirs[dir] =3D true } base =3D strings.TrimSuffix(base, ".so") base =3D strings.TrimPrefix(base, "lib") if !seenLibs[base] { argv =3D append(argv, "-l"+base) seenLibs[base] =3D true } } Note the "!rpath.set" condition. Grrrrrrr. Anyway good luck :) There's a better solution for go 1.4 at least! On Sat 28 May 2016 21:39, Matthew Jordan w= rites: > Good Day, > > As suggested by others I have looked into the following variables as an > alternative to LD_LIBRARY_PATH. But was unable to make the build work > with any of them. It also possbile I have to fully understand how they > are meant to be used, so if anyone has any useful info feel free to share. > > LD_RUN_PATH > DT_RUNPATH > DT_RPATH > RUNPATH > RPATH > > From a7c7589ff61a225ae661bd3e55535c8fec4bf9fc Mon Sep 17 00:00:00 2001 > From: Matthew Jordan > Date: Thu, 26 May 2016 08:57:16 -0400 > Subject: [PATCH 1/3] Add go@1.4 > > * gnu/local.mk: Modified file. > * gnu/packages/golang.scm: New file. > --- > gnu/local.mk | 1 + > gnu/packages/golang.scm | 185 ++++++++++++++++++++++++++++++++++++++++++= ++++++ > 2 files changed, 186 insertions(+) > create mode 100644 gnu/packages/golang.scm > > diff --git a/gnu/local.mk b/gnu/local.mk > index 86b56d4..95b5ec0 100644 > --- a/gnu/local.mk > +++ b/gnu/local.mk > @@ -147,6 +147,7 @@ GNU_SYSTEM_MODULES =3D \ > %D%/packages/gnustep.scm \ > %D%/packages/gnuzilla.scm \ > %D%/packages/gnu-pw-mgr.scm \ > + %D%/packages/golang.scm \ > %D%/packages/gperf.scm \ > %D%/packages/gprolog.scm \ > %D%/packages/gps.scm \ > diff --git a/gnu/packages/golang.scm b/gnu/packages/golang.scm > new file mode 100644 > index 0000000..77d4b0e > --- /dev/null > +++ b/gnu/packages/golang.scm > @@ -0,0 +1,185 @@ > +;;; GNU Guix --- Functional package management for GNU > +;;; Copyright =C2=A9 2015, 2016 Efraim Flashner > +;;; Copyright =C2=A9 2016 Matthew Jordan > +;;; > +;;; This file is an addendum GNU Guix. > +;;; > +;;; GNU Guix 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 3 of the License, or (at > +;;; your option) any later version. > +;;; > +;;; GNU Guix 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 GNU Guix. If not, see . > + > +(define-module (gnu packages golang) > + #:use-module ((guix licenses) #:prefix license:) > + #:use-module (guix utils) > + #:use-module (guix download) > + #:use-module (guix packages) > + #:use-module (guix build-system gnu) > + #:use-module (gnu packages admin) > + #:use-module (gnu packages rc) > + #:use-module (gnu packages gcc) > + #:use-module (gnu packages base) > + #:use-module (gnu packages perl) > + #:use-module (gnu packages pkg-config) > + #:use-module (gnu packages pcre) > + #:use-module (gnu packages bash) > + #:use-module (srfi srfi-1)) > + > +;; According to https://golang.org/doc/install/gccgo, gccgo-4.8.2 includ= es a > +;; complete go-1.1.2 implementation, gccgo-4.9 includes a complete go-1.2 > +;; implementation, and gccgo-5 a complete implementation of go-1.4. Ult= imately > +;; we hope to build go-1.5+ with a bootstrap process using gccgo-5. As = of > +;; go-1.5, go cannot be bootstrapped without go-1.4, so we need to use g= o-1.4 or > +;; gccgo-5. Mips is not officially supported, but it should work if it = is > +;; bootstrapped. > + > +(define-public go-1.4 > + (package > + (name "go") > + (version "1.4.3") > + (source > + (origin > + (method url-fetch) > + (uri (string-append "https://storage.googleapis.com/golang/" > + name version ".src.tar.gz")) > + (sha256 > + (base32 > + "0na9yqilzpvq0bjndbibfp07wr796gf252y471cip10bbdqgqiwr")))) > + (build-system gnu-build-system) > + (outputs '("out" > + "doc" > + "src")) > + (arguments > + `(#:phases > + (modify-phases %standard-phases > + (delete 'configure) > + (delete 'validate-runpath) > + (add-after 'patch-generated-file-shebangs 'chdir > + (lambda _ (chdir "src"))) > + (add-before 'build 'prebuild > + (lambda* (#:key inputs outputs #:allow-other-keys) > + (let* ((gccgo (assoc-ref inputs "gccgo")) > + (gcclib (string-append (assoc-ref inputs "gcc:lib") = "/lib")) > + (ld (string-append > + (assoc-ref inputs "glibc") "/lib")) > + (loader (car (find-files ld "^ld-linux.+"))) > + (libgcc (string-append (assoc-ref inputs "gcc:lib") = "/lib")) > + (net-base (assoc-ref inputs "net-base")) > + (tzdata-path > + (string-append (assoc-ref inputs "tzdata") "/share/= zoneinfo")) > + (output (assoc-ref outputs "out"))) > + ;; Removing net/ tests > + (for-each > + (lambda (srcfile) > + (let ((srcfile (string-append "net/" srcfile))) > + (if (file-exists? srcfile) > + (delete-file srcfile)))) > + '("multicast_test.go" "parse_test.go" "port_test.go")) > + (substitute* "os/os_test.go" > + (("/usr/bin") (getcwd)) > + (("/bin/pwd") (which "pwd"))) > + ;; Disable failing tests > + (for-each > + (lambda (srcfile) > + (substitute* (car srcfile) > + (((cdr srcfile) all) (string-append all "return\n"))= )) > + (list > + '("net/net_test.go" . ".+TestShutdownUnix.+") > + '("net/dial_test.go" . ".+TestDialTimeout.+") > + '("os/os_test.go" . ".+TestHostname.+") > + '("time/format_test.go" . ".+TestParseInSydney.+") > + '("os/exec/exec_test.go" . ".+TestEcho.+") > + '("os/exec/exec_test.go" . ".+TestCommandRelativeName.+= ") > + '("os/exec/exec_test.go" . ".+TestCatStdin.+") > + '("os/exec/exec_test.go" . ".+TestCatGoodAndBadFile.+") > + '("os/exec/exec_test.go" . ".+TestExitStatus.+") > + '("os/exec/exec_test.go" . ".+TestPipes.+") > + '("os/exec/exec_test.go" . ".+TestStdinClose.+") > + '("syscall/syscall_unix_test.go" . ".+TestPassFD\\(.+") > + '("os/exec/exec_test.go" . ".+TestExtraFiles.+"))) > + (substitute* "net/lookup_unix.go" > + (("/etc/protocols") (string-append net-base "/etc/proto= cols"))) > + (substitute* "time/zoneinfo_unix.go" > + (("/usr/share/zoneinfo/") tzdata-path)) > + (substitute* > + (find-files "cmd" "asm.c") > + (("/lib/ld-linux.*\\.so\\.[0-9]") loader))))) > + (replace 'build > + (lambda* (#:key inputs outputs #:allow-other-keys) > + (let* ((gccgo (assoc-ref inputs "gccgo")) > + (output (assoc-ref outputs "out"))) > + (setenv "CC" (which "gcc")) > + (setenv "GOOS" "linux") > + (setenv "GOROOT" (dirname (getcwd))) > + (setenv "GOROOT_BOOTSTRAP" gccgo) > + (setenv "GOROOT_FINAL" output) > + (setenv "LD_LIBRARY_PATH" (getenv "LIBRARY_PATH")) > + (setenv "CGO_ENABLED" "1") > + (zero? (system* "sh" "all.bash"))))) > + (replace 'install > + (lambda* (#:key outputs inputs #:allow-other-keys) > + (let* ((output (assoc-ref outputs "out")) > + (doc_out (assoc-ref outputs "doc")) > + (bash (string-append (assoc-ref inputs "bash") "bin/= bash")) > + (docs (string-append doc_out "/share/doc/" ,name "-"= ,version)) > + (src (string-append > + (assoc-ref outputs "src") "/share/" ,name "-= " ,version))) > + (mkdir-p src) > + (copy-recursively "../test" (string-append src "/test")) > + (delete-file-recursively "../test") > + (mkdir-p docs) > + (copy-recursively "../api" (string-append docs "/api")) > + (delete-file-recursively "../api") > + (copy-recursively "../doc" (string-append docs "/doc")) > + (delete-file-recursively "../doc") > + > + (for-each > + (lambda (file) > + (let* ((filein (string-append "../" file)) > + (fileout (string-append docs "/" file))) > + (copy-file filein fileout) > + (delete-file filein))) > + '("README" "CONTRIBUTORS" "AUTHORS" "PATENTS" > + "LICENSE" "VERSION" "robots.txt")) > + (rename-file "../bin/go" (string-append "../bin/go-" ,ver= sion)) > + > + ;; Create a wrapper script for go command > + (call-with-output-file (string-append "../bin/go") > + (lambda (port) > + (format port (string-append "#!" bash "\n")) > + (format port "\nexport LD_LIBRARY_PATH=3D$LIBRARY_PAT= H\n") > + (format port (string-append "go-" ,version " \"$@\"")) > + (chmod port #o555))) > + (copy-recursively "../" output))))) > + #:tests? #f)) > + (inputs > + `(("which" ,which) > + ("tzdata" ,tzdata) > + ("pkg-config" ,%pkg-config) > + ("pcre" ,pcre))) > + (native-inputs > + `(("gccgo" ,gccgo-4.9) > + ("gcc:out" ,gcc-4.9 "out") > + ("net-base" ,net-base) > + ("rc" ,rc) > + ("perl" ,perl))) > + (propagated-inputs > + `(("gcc:lib" ,gcc-4.9 "lib") > + ("bash" ,bash) > + ("glibc" ,glibc))) > + (home-page "https://golang.org/") > + (synopsis "Compiled, statically typed language developed by Google") > + (description "Go, also commonly referred to as golang, is a programm= ing > + language developed at Google. Designed primarily for systems programmi= ng, it > + is a compiled, statically typed language in the tradition of C and C++,= with > +garbage collection, various safety features and in the style of communic= ating > +sequential processes (CSP) concurrent programming features added.") > + (license license:bsd-3)))