From mboxrd@z Thu Jan 1 00:00:00 1970 From: Matthew Jordan Subject: Re: [Patch] go@1.4 Date: Sun, 29 May 2016 14:48:00 -0400 Message-ID: <87wpmcya3j.fsf@mailerver.i-did-not-set--mail-host-address--so-tickle-me> References: <8737p2ynsx.fsf@mailerver.i-did-not-set--mail-host-address--so-tickle-me> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:60707) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b75ly-0007hM-0x for guix-devel@gnu.org; Sun, 29 May 2016 14:49:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b75lt-00083O-Ql for guix-devel@gnu.org; Sun, 29 May 2016 14:49:12 -0400 Received: from forward14h.cmail.yandex.net ([87.250.230.156]:50473) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b75ls-00081T-Ad for guix-devel@gnu.org; Sun, 29 May 2016 14:49:09 -0400 In-reply-to: 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: Andy Wingo Cc: guix-devel Hi Andy, And thanks for code snippet, I'll look at and see how I can integrate it with the current patches. I'm new to both go and guile, so there is still much to learn. Thanks again! -- Matthew Jordan Sent with my mu4e Andy Wingo writes: > 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") "/lib")) > (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/zoneinfo")) > (output (assoc-ref outputs "out"))) > (substitute* "cmd/go/build.go" > (("cgoldflags := \\[\\]string\\{\\}") > (string-append "cgoldflags := []string{" > "\"-rpath=" gcclib "\"" > "}")) > (("ldflags := buildLdflags") > (string-append > "ldflags := buildLdflags\n" > "ldflags = append(ldflags, \"-r\")\n" > "ldflags = 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/protocols"))) > (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 := \\[\\]string\\{\\}") > (string-append "cgoldflags := []string{" > "\"-rpath=" gcclib "\"" > "}")) > (("ldflags = setextld\\(ldflags, compiler\\)") > (string-append > "ldflags = setextld(ldflags, compiler)\n" > "ldflags = append(ldflags, \"-r\")\n" > "ldflags = append(ldflags, \"" gcclib "\")\n")) > (("\"-lgcc_s\", ") > (string-append > "\"-Wl,-rpath=" gcclib "\", \"-lgcc_s\", "))) > > But then tests fail: > > ##### ../misc/cgo/testshared > --- FAIL: TestTrivialExecutable (0.07s) > shared_test.go:40: executing ./bin/trivial (trivial executable) failed exit status 127: > ./bin/trivial: error while loading shared libraries: libruntime,sync-atomic.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 status 127: > ./bin/execgo: error while loading shared libraries: libruntime,sync-atomic.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 library) failed exit status 127: > ./bin/exe: error while loading shared libraries: libruntime,sync-atomic.so: 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 library) 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 between the executable and libdep.so"; got output: > ./bin/exe: error while loading shared libraries: libruntime,sync-atomic.so: 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 => not found > libgcc_s.so.1 => /gnu/store/zzz0zjgyd7f515wmbnmb8i1kmrgwh7bq-gcc-4.9.3-lib/lib/libgcc_s.so.1 (0x00007f43898c3000) > libc.so.6 => /gnu/store/8m00x5x8ykmar27s9248cmhnkdb2n54a-glibc-2.22/lib/libc.so.6 (0x00007f438951e000) > /gnu/store/8m00x5x8ykmar27s9248cmhnkdb2n54a-glibc-2.22/lib/ld-linux-x86-64.so.2 (0x00007f4389ad9000) > > 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 := make(map[string]bool) > seenLibs := make(map[string]bool) > addshlib := func(path string) { > dir, base := filepath.Split(path) > if !seenDirs[dir] { > argv = append(argv, "-L"+dir) > if !rpath.set { > argv = append(argv, "-Wl,-rpath="+dir) > } > seenDirs[dir] = true > } > base = strings.TrimSuffix(base, ".so") > base = strings.TrimPrefix(base, "lib") > if !seenLibs[base] { > argv = append(argv, "-l"+base) > seenLibs[base] = true > } > } > > Note the "!rpath.set" condition. Grrrrrrr. > > Anyway good luck :) There's a better solution for go 1.4 at least! >