diff mbox

go@1.4

Message ID 8737p2ynsx.fsf@mailerver.i-did-not-set--mail-host-address--so-tickle-me
State New
Headers show

Commit Message

Matthew Jordan May 28, 2016, 7:39 p.m. UTC
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
Note that there will be two more patches  to follow, which are dependant
on this one.

Sincerely,

--
Matthew Jordan
Sent with my mu4e

Comments

Andy Wingo May 29, 2016, 5:49 p.m. UTC | #1
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!

On Sat 28 May 2016 21:39, Matthew Jordan <matthewjordandevops@yandex.com> writes:

> 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 <matthewjordandevops@yandex.com>
> 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 =				\
>    %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 © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
> +;;; Copyright © 2016 Matthew Jordan <matthewjordandevops@yandex.com>
> +;;;
> +;;; 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 <http://www.gnu.org/licenses/>.
> +
> +(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 includes 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.  Ultimately
> +;; 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 go-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/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" (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-" ,version))
> +
> +               ;; 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=$LIBRARY_PATH\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 programming
> + language developed at Google.  Designed primarily for systems programming, 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 communicating
> +sequential processes (CSP) concurrent programming features added.")
> +    (license license:bsd-3)))
Matthew Jordan May 29, 2016, 6:48 p.m. UTC | #2
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!
Andy Wingo June 2, 2016, 7:54 a.m. UTC | #3
Hi,

How goes the patching?

FWIW for Go 1.5 and 1.6, if I remove this test in the linker then I can
build without the LD_LIBRARY_PATH hacks and the tests work for me:

On Sun 29 May 2016 19:49, Andy Wingo <wingo@igalia.com> writes:

> 	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)
> 				}

This one.  I do a substitute* of !rpath.set to "true" :)

I am not sure whether this is the right fix -- I guess it seems that the
intention of this code in the linker is that whatever calls the linker,
if it passes the "-r" argument (yes, "-r" not "-rpath" because this is
the Go internal linker that has different kinds of arguments; grrr; and
yet, when linking a shared library it still shells out to the system
ld), then it means that the caller is omniscient and knows the entire
rpath to set.  Otherwise the linker is doing magic by adding its own
rpath incantations.  But, that seems to me to be a bad design.  I can't
see why passing -r should turn off the "automatic" rpath stuff where Go
adds -rpaths appropriate the -l libraries that it is linking, unless in
some really strange deployment scenarios.

Anyway.  I think it is a sufficiently innocuous of a fix that it will
allow us to merge Go.  Let us call this yak shaved and get Go in.  WDYT?

Andy
Matthew Jordan June 2, 2016, 4:29 p.m. UTC | #4
Hey Andy and everyone,

Just a quick update, will send more details, or some patches later.

Just finished up building go@1.5.4, thanks to last bit you sent. The
runpath now validates in both go@1.4.3 and go@1.5.4.  All enabled test
now pass.

>> 	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)
>> 				}
>
> This one.  I do a substitute* of !rpath.set to "true" :)

Personally I have no problem with it, already added some code for it.

> Anyway.  I think it is a sufficiently innocuous of a fix that it will
> allow us to merge Go.  Let us call this yak shaved and get Go in.  WDYT?

I'm game for anything practical, but we'll see what the reviewers have
to say when I submit the updated patches.

Also do you mind if I add you name and email an Co-author of these three
packages?

Sincerely,

--
Matthew Jordan
Sent with my mu4e
Andy Wingo June 3, 2016, 8:13 a.m. UTC | #5
Hi,

Sounds great :)

On Thu 02 Jun 2016 18:29, Matthew Jordan <matthewjordandevops@yandex.com> writes:

> Also do you mind if I add you name and email an Co-author of these three
> packages?

Sure, sounds fine.

Cheers,

Andy
diff mbox

Patch

From a7c7589ff61a225ae661bd3e55535c8fec4bf9fc Mon Sep 17 00:00:00 2001
From: Matthew Jordan <matthewjordandevops@yandex.com>
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 =				\
   %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 © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Matthew Jordan <matthewjordandevops@yandex.com>
+;;;
+;;; 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 <http://www.gnu.org/licenses/>.
+
+(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 includes 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.  Ultimately
+;; 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 go-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/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" (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-" ,version))
+
+               ;; 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=$LIBRARY_PATH\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 programming
+ language developed at Google.  Designed primarily for systems programming, 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 communicating
+sequential processes (CSP) concurrent programming features added.")
+    (license license:bsd-3)))
-- 
2.8.3