;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2015, 2016 Efraim Flashner ;;; Copyright © 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 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))) (define-public go-1.5 (package (inherit go-1.4) (name "go") (version "1.5.4") (source (origin (method url-fetch) (uri (string-append "https://storage.googleapis.com/golang/" name version ".src.tar.gz")) (sha256 (base32 "14xwn2pr3g4i1h8qpyrjjdmq1pgvzkagk4aqsp841hfxwyyclah0")))) (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* ((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.+") '("os/exec/exec_test.go" . ".+TestIgnorePipeErrorOnSuccess.+") '("syscall/syscall_unix_test.go" . ".+TestPassFD\\(.+") '("os/exec/exec_test.go" . ".+TestExtraFiles.+") '("net/listen_test.go" . ".+TestIPv4MulticastListener\\(.+") '("syscall/exec_linux_test.go" . ".+TestCloneNEWUSERAndRemapNoRootDisableSetgroups.+"))) (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* ((go (assoc-ref inputs "go")) (output (assoc-ref outputs "out"))) (setenv "CC" (which "gcc")) (setenv "GOOS" "linux") (setenv "GOROOT" (dirname (getcwd))) (setenv "GOROOT_BOOTSTRAP" go) (setenv "GOROOT_FINAL" output) (setenv "GOGC" "400") (setenv "LD_LIBRARY_PATH" (getenv "LIBRARY_PATH")) (setenv "CGO_ENABLED" "1") (zero? (system* "sh" "all.bash"))))) (replace 'install (lambda* (#:key inputs outputs #: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.md" "CONTRIBUTORS" "AUTHORS" "PATENTS" "LICENSE" "VERSION" "CONTRIBUTING.md" "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 `(,@(package-inputs go-1.4))) (native-inputs `(("go" ,go-1.4) ,@(alist-delete "gccgo" (package-native-inputs go-1.4)))) (propagated-inputs `(,@(package-propagated-inputs go-1.4))))) (define-public go-1.6 (package (inherit go-1.4) (name "go") (version "1.6.2") (source (origin (method url-fetch) (uri (string-append "https://storage.googleapis.com/golang/" name version ".src.tar.gz")) (sha256 (base32 "1k5wy5ijll5aacj1m6xxnjfjw6x9f255ml3f1jiicw031mshnyvq")))) (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* ((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"))) (for-each (lambda (srcfile) (let ((srcfile (string-append "net/" srcfile))) (if (file-exists? srcfile) (delete-file srcfile)))) '("listen_test.go" "parse_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.+") '("os/exec/exec_test.go" . ".+TestIgnorePipeErrorOnSuccess.+") '("syscall/syscall_unix_test.go" . ".+TestPassFD\\(.+") '("os/exec/exec_test.go" . ".+TestExtraFiles/areturn.+") '("cmd/go/go_test.go" . ".+TestCoverageWithCgo.+") '("os/exec/exec_test.go" . ".+TestOutputStderrCapture.+") '("os/exec/exec_test.go" . ".+TestExtraFiles.+") '("os/exec/exec_test.go" . ".+TestExtraFilesRace.+") '("net/lookup_test.go" . ".+TestLookupPort.+") '("syscall/exec_linux_test.go" . ".+TestCloneNEWUSERAndRemapNoRootDisableSetgroups.+"))) (substitute* "../misc/cgo/testsanitizers/test.bash" (("(CC=)cc" all var) (string-append var "gcc"))) ;; fix shebang for testar script (substitute* "../misc/cgo/testcarchive/test.bash" (("#!/usr/bin/env") (string-append "#!" (which "env")))) (substitute* "net/lookup_unix.go" (("/etc/protocols") (string-append net-base "/etc/protocols"))) (substitute* "net/port_unix.go" (("/etc/services") (string-append net-base "/etc/services"))) (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* ((go (assoc-ref inputs "go")) (output (assoc-ref outputs "out"))) (setenv "CC" "gcc") (setenv "GOOS" "linux") (setenv "GOROOT" (dirname (getcwd))) (setenv "GOROOT_BOOTSTRAP" go) (setenv "GOROOT_FINAL" output) (setenv "GOGC" "400") (setenv "LD_LIBRARY_PATH" (getenv "LIBRARY_PATH")) (setenv "PATH" (string-append (getenv "GOROOT_FINAL") "/bin:" (getenv "GOROOT") "/bin:" (getenv "PATH"))) (setenv "CGO_ENABLED" "1") (zero? (system* "sh" "make.bash"))))) (replace 'install (lambda* (#:key inputs outputs #: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.md" "CONTRIBUTORS" "AUTHORS" "PATENTS" "LICENSE" "VERSION" "CONTRIBUTING.md" "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 `(,@(package-inputs go-1.4))) (native-inputs `(("go" ,go-1.4) ,@(alist-delete "gccgo" (package-native-inputs go-1.4)))) (propagated-inputs `(,@(package-propagated-inputs go-1.4))))) (define-public go go-1.6)