diff options
Diffstat (limited to 'guix')
| -rw-r--r-- | guix/build-system/rebar.scm | 143 | ||||
| -rw-r--r-- | guix/build/rebar-build-system.scm | 147 | 
2 files changed, 290 insertions, 0 deletions
| diff --git a/guix/build-system/rebar.scm b/guix/build-system/rebar.scm new file mode 100644 index 0000000000..8a8fb7708c --- /dev/null +++ b/guix/build-system/rebar.scm @@ -0,0 +1,143 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2020 Hartmut Goebel <h.goebel@crazy-compilers.com> +;;; +;;; This file is part of 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 (guix build-system rebar) +  #:use-module (guix store) +  #:use-module (guix utils) +  #:use-module (guix gexp) +  #:use-module (guix packages) +  #:use-module (guix monads) +  #:use-module (guix search-paths) +  #:use-module (guix build-system) +  #:use-module (guix build-system gnu) +  #:use-module ((guix hexpm-download) #:select (hexpm-uri) #:prefix dl:) +  #:use-module (ice-9 match) +  #:use-module (srfi srfi-26) +  #:export (hexpm-uri +            %rebar-build-system-modules +            rebar-build +            rebar-build-system)) + +;; +;; Standard build procedure for Erlang packages using Rebar. +;; + +(define hexpm-uri dl:hexpm-uri) + +(define %rebar-build-system-modules +  ;; Build-side modules imported by default. +  `((guix build rebar-build-system) +    ,@%gnu-build-system-modules)) + +(define (default-rebar3) +  "Return the default Rebar3 package." +  ;; Lazily resolve the binding to avoid a circular dependency. +  (let ((erlang-mod (resolve-interface '(gnu packages erlang)))) +    (module-ref erlang-mod 'rebar3))) + +(define (default-erlang) +  "Return the default Erlang package." +  ;; Lazily resolve the binding to avoid a circular dependency. +  (let ((erlang-mod (resolve-interface '(gnu packages erlang)))) +    (module-ref erlang-mod 'erlang))) + +(define* (lower name +                #:key source inputs native-inputs outputs system target +                (rebar (default-rebar3)) +                (erlang (default-erlang)) +                #:allow-other-keys +                #:rest arguments) +  "Return a bag for NAME from the given arguments." +  (define private-keywords +    '(#:target #:rebar #:erlang #:inputs #:native-inputs)) + +  (and (not target)                               ;XXX: no cross-compilation +       (bag +         (name name) +         (system system) +         (host-inputs `(,@(if source +                              `(("source" ,source)) +                              '()) +                        ,@inputs)) +         (build-inputs `(("rebar" ,rebar) +                         ("erlang" ,erlang) ;; for escriptize +                         ,@native-inputs +                         ;; Keep the standard inputs of 'gnu-build-system'. +                         ,@(standard-packages))) +         (outputs outputs) +         (build rebar-build) +         (arguments (strip-keyword-arguments private-keywords arguments))))) + +(define* (rebar-build name inputs +                       #:key +                       guile source +                       (rebar-flags ''("skip_deps=true" "-vv")) +                       (tests? #t) +                       (test-target "eunit") +                       ;; TODO: install-name  ; default: based on guix package name +                       (install-profile "default") +                       (phases '(@ (guix build rebar-build-system) +                                   %standard-phases)) +                       (outputs '("out")) +                       (search-paths '()) +                       (native-search-paths '()) +                       (system (%current-system)) +                       (imported-modules %rebar-build-system-modules) +                       (modules '((guix build rebar-build-system) +                                  (guix build utils)))) +  "Build SOURCE with INPUTS." + +  (define builder +    (with-imported-modules imported-modules +      #~(begin +          (use-modules #$@(sexp->gexp modules)) + +          #$(with-build-variables inputs outputs +              #~(rebar-build #:source #+source +                      #:system #$system +                      #:name #$name +                      #:rebar-flags #$rebar-flags +                      #:tests? #$tests? +                      #:test-target #$test-target +                      ;; TODO: #:install-name #$install-name +                      #:install-profile #$install-profile +                      #:phases #$(if (pair? phases) +                                     (sexp->gexp phases) +                                     phases) +                      #:outputs %outputs +                      #:search-paths '#$(sexp->gexp +                                         (map search-path-specification->sexp +                                              search-paths)) +                      #:inputs %build-inputs))))) + +  (mlet %store-monad ((guile (package->derivation (or guile (default-guile)) +                                                  system #:graft? #f))) +    ;; Note: Always pass #:graft? #f.  Without it, ALLOWED-REFERENCES & +    ;; co. would be interpreted as referring to grafted packages. +    (gexp->derivation name builder +                      #:system system +                      #:target #f +                      #:graft? #f +                      #:guile-for-build guile))) + +(define rebar-build-system +  (build-system +    (name 'rebar) +    (description "The standard Rebar build system") +    (lower lower))) diff --git a/guix/build/rebar-build-system.scm b/guix/build/rebar-build-system.scm new file mode 100644 index 0000000000..fb66422877 --- /dev/null +++ b/guix/build/rebar-build-system.scm @@ -0,0 +1,147 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2016, 2018 Ricardo Wurmus <rekado@elephly.net> +;;; Copyright © 2019 Björn Höfling <bjoern.hoefling@bjoernhoefling.de> +;;; Copyright © 2020, 2022 Hartmut Goebel <h.goebel@crazy-compilers.com> +;;; +;;; This file is part of 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 (guix build rebar-build-system) +  #:use-module ((guix build gnu-build-system) #:prefix gnu:) +  #:use-module ((guix build utils) #:hide (delete)) +  #:use-module (ice-9 match) +  #:use-module (ice-9 ftw) +  #:use-module (srfi srfi-1) +  #:use-module (srfi srfi-26) +  #:export (rebar-build +            %standard-phases)) + +;; +;; Builder-side code of the standard build procedure for Erlang packages using +;; rebar3. +;; +;; TODO: Think about whether bindir ("ebin"), libdir ("priv") and includedir +;; "(include") need to be configurable + +(define %erlang-libdir "/lib/erlang/lib") + +(define* (erlang-depends #:key inputs #:allow-other-keys) +  (define input-directories +    (match inputs +      (((_ . dir) ...) +       dir))) +  (mkdir-p "_checkouts") + +  (for-each +   (lambda (input-dir) +     (let ((elibdir (string-append input-dir %erlang-libdir))) +       (when (directory-exists? elibdir) +         (for-each +          (lambda (dirname) +            (let ((dest (string-append elibdir "/" dirname)) +                  (link (string-append "_checkouts/" dirname))) +              (when (not (file-exists? link)) +                ;; RETHINK: Maybe better copy and make writable to avoid some +                ;; error messages e.g. when using with rebar3-git-vsn. +                (symlink dest link)))) +          (list-directories elibdir))))) +   input-directories)) + +(define* (unpack #:key source #:allow-other-keys) +  "Unpack SOURCE in the working directory, and change directory within the +source.  When SOURCE is a directory, copy it in a sub-directory of the current +working directory." +  (let ((gnu-unpack (assoc-ref gnu:%standard-phases 'unpack))) +    (gnu-unpack #:source source) +    ;; Packages from hex.pm typically have a contents.tar.gz containing the +    ;; actual source. If this tar file exists, extract it. +    (when (file-exists? "contents.tar.gz") +      (invoke "tar" "xvf" "contents.tar.gz")))) + +(define* (build #:key (rebar-flags '()) #:allow-other-keys) +  (apply invoke `("rebar3" "compile" ,@rebar-flags))) + +(define* (check #:key target (rebar-flags '()) (tests? (not target)) +                (test-target "eunit") +                #:allow-other-keys) +  (if tests? +      (apply invoke `("rebar3" ,test-target ,@rebar-flags)) +      (format #t "test suite not run~%"))) + +(define (erlang-package? name) +  "Check if NAME correspond to the name of an Erlang package." +  (string-prefix? "erlang-" name)) + +(define (package-name-version->erlang-name name+ver) +  "Convert the Guix package NAME-VER to the corresponding Erlang name-version +format.  Essentially drop the prefix used in Guix and replace dashes by +underscores." +  (let* ((name- (package-name->name+version name+ver))) +    (string-join +     (string-split +      (if (erlang-package? name-)  ; checks for "erlang-" prefix +          (string-drop name- (string-length "erlang-")) +          name-) +      #\-) +     "_"))) + +(define (list-directories directory) +  "Return file names of the sub-directory of DIRECTORY." +  (scandir directory +           (lambda (file) +             (and (not (member file '("." ".."))) +                  (file-is-directory? (string-append directory "/" file)))))) + +(define* (install #:key name outputs +                  (install-name (package-name-version->erlang-name name)) +                  (install-profile "default") ; build profile outputs to install +                  #:allow-other-keys) +  (let* ((out (assoc-ref outputs "out")) +         (pkg-dir (string-append out %erlang-libdir "/" install-name))) +    (let ((bin-dir (string-append "_build/" install-profile "/bin")) +          (lib-dir (string-append "_build/" install-profile "/lib"))) +      ;; install _build/PROFILE/bin +      (when (file-exists? bin-dir) +        (copy-recursively bin-dir out #:follow-symlinks? #t)) +      ;; install _build/PROFILE/lib/*/{ebin,include,priv} +      (for-each +       (lambda (*) +         (for-each +          (lambda (dirname) +            (let ((src-dir (string-append lib-dir "/" * "/" dirname)) +                  (dst-dir (string-append pkg-dir "/" dirname))) +              (when (file-exists? src-dir) +                (copy-recursively src-dir dst-dir #:follow-symlinks? #t)) +              (false-if-exception +               (delete-file (string-append dst-dir "/.gitignore"))))) +          '("ebin" "include" "priv"))) +       (list-directories lib-dir)) +      (false-if-exception +       (delete-file (string-append pkg-dir "/priv/Run-eunit-loop.expect")))))) + +(define %standard-phases +  (modify-phases gnu:%standard-phases +    (replace 'unpack unpack) +    (delete 'bootstrap) +    (delete 'configure) +    (add-before 'build 'erlang-depends erlang-depends) +    (replace 'build build) +    (replace 'check check) +    (replace 'install install))) + +(define* (rebar-build #:key inputs (phases %standard-phases) +                      #:allow-other-keys #:rest args) +  "Build the given Erlang package, applying all of PHASES in order." +  (apply gnu:gnu-build #:inputs inputs #:phases phases args)) | 
