unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: Julien Lepiller <julien@lepiller.eu>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: 42338@debbugs.gnu.org
Subject: [bug#42338] [PATCH 03/34] guix: Add composer-build-system.
Date: Tue, 29 Sep 2020 16:49:20 +0200	[thread overview]
Message-ID: <20200929164920.0684be42@tachikoma.lepiller.eu> (raw)
In-Reply-To: <87eemq16y3.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 562 bytes --]

Le Fri, 25 Sep 2020 12:33:56 +0200,
Ludovic Courtès <ludo@gnu.org> a écrit :

> Hi,
> 
> As for Guile-JSON: perhaps you can post a draft that we can play with
> to see if there’s anything wrong, but off the top of my head I don’t
> see why it wouldn’t work.
> 
> Thanks,
> Ludo’.

Here's a new version, hopefully this addresses all your remarks. I'm
still not sure how (json) is pulled in to the build side though... How
does guix know it needs to use guile-json-3 instead of guile-json-1 for
instance? How does it work with inferiors?

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-guix-Add-composer-build-system.patch --]
[-- Type: text/x-patch, Size: 26503 bytes --]

From 432f57aeeb3b2e48591288e6491d66ab299661f0 Mon Sep 17 00:00:00 2001
From: Julien Lepiller <julien@lepiller.eu>
Date: Tue, 29 Oct 2019 20:58:51 +0100
Subject: [PATCH 03/34] guix: Add composer-build-system.

* guix/build-system/composer.scm: New file.
* guix/build/composer-build-system.scm: New file.
* gnu/packages/aux-files/findclass.php: New file.
* Makefile.am: Add them.
* doc/guix.texi (Build Systems): Document it.
---
 Makefile.am                          |   5 +-
 doc/guix.texi                        |  14 ++
 gnu/packages/aux-files/findclass.php | 125 ++++++++++++++
 guix/build-system/composer.scm       | 173 +++++++++++++++++++
 guix/build/composer-build-system.scm | 241 +++++++++++++++++++++++++++
 5 files changed, 557 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/aux-files/findclass.php
 create mode 100644 guix/build-system/composer.scm
 create mode 100644 guix/build/composer-build-system.scm

diff --git a/Makefile.am b/Makefile.am
index 6ce1430ea6..5af964b0e9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -115,6 +115,7 @@ MODULES =					\
   guix/build-system/cargo.scm			\
   guix/build-system/clojure.scm			\
   guix/build-system/cmake.scm			\
+  guix/build-system/composer.scm		\
   guix/build-system/dub.scm			\
   guix/build-system/dune.scm			\
   guix/build-system/emacs.scm			\
@@ -163,6 +164,7 @@ MODULES =					\
   guix/build/cargo-build-system.scm		\
   guix/build/cargo-utils.scm			\
   guix/build/cmake-build-system.scm		\
+  guix/build/composer-build-system.scm		\
   guix/build/dub-build-system.scm		\
   guix/build/dune-build-system.scm		\
   guix/build/emacs-build-system.scm		\
@@ -354,7 +356,8 @@ AUX_FILES =						\
   gnu/packages/aux-files/linux-libre/4.4-i686.conf	\
   gnu/packages/aux-files/linux-libre/4.4-x86_64.conf	\
   gnu/packages/aux-files/pack-audit.c			\
-  gnu/packages/aux-files/run-in-namespace.c
+  gnu/packages/aux-files/run-in-namespace.c		\
+  gnu/packages/aux-files/findclass.php
 
 # Templates, examples.
 EXAMPLES =					\
diff --git a/doc/guix.texi b/doc/guix.texi
index 626915fd39..6870163c23 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6941,6 +6941,20 @@ debugging information''), which roughly means that code is compiled with
 @code{-O2 -g}, as is the case for Autoconf-based packages by default.
 @end defvr
 
+@defvr {Scheme Variable} composer-build-system
+This variable is exported by @code{(guix build-system composer)}.  It
+implements the build procedure for packages using
+@url{https://getcomposer.org/, Composer}, the PHP package manager.
+
+It automatically adds the @code{php} package to the set of inputs.  Which
+package is used can be specified with the @code{#:php} parameter.
+
+The @code{#:test-target} parameter is used to control which script is run
+for the tests.  By default, the @code{test} script is run if it exists.  If
+the script does not exist, the build system will run @code{phpunit} from the
+source directory, assuming there is a @file{phpunit.xml} file.
+@end defvr
+
 @defvr {Scheme Variable} dune-build-system
 This variable is exported by @code{(guix build-system dune)}.  It
 supports builds of packages using @uref{https://dune.build/, Dune}, a build
diff --git a/gnu/packages/aux-files/findclass.php b/gnu/packages/aux-files/findclass.php
new file mode 100644
index 0000000000..d0b250c8e1
--- /dev/null
+++ b/gnu/packages/aux-files/findclass.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * The content of this file is copied from composer's src/Composer/Autoload/ClassMapGenerator.php
+ * the findClasses method was extracted, to prevent using any dependency.
+ *
+ * Composer (and thus this file) is distributed under the expat license, and
+ * ClassMapGenerator.php also contains this notice:
+ *
+ *   This file is part of Composer.
+ *
+ *   (c) Nils Adermann <naderman@naderman.de>
+ *       Jordi Boggiano <j.boggiano@seld.be>
+ *
+ *   For the full copyright and license information, please view the LICENSE
+ *   file that was distributed with this source code.
+ *
+ *   This file is copied from the Symfony package.
+ *
+ *   (c) Fabien Potencier <fabien@symfony.com>
+ * 
+ * To the extent to wich it makes sense, as the author of the extract:
+ * Copyright © 2020 Julien Lepiller <julien@lepiller.eu>
+ */
+
+/**
+ * Extract the classes in the given file
+ *
+ * @param  string            $path The file to check
+ * @throws \RuntimeException
+ * @return array             The found classes
+ */
+function findClasses($path)
+{
+    $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
+    if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
+        $extraTypes .= '|enum';
+    }
+    // Use @ here instead of Silencer to actively suppress 'unhelpful' output
+    // @link https://github.com/composer/composer/pull/4886
+    $contents = @php_strip_whitespace($path);
+    if (!$contents) {
+        if (!file_exists($path)) {
+            $message = 'File at "%s" does not exist, check your classmap definitions';
+        } elseif (!is_readable($path)) {
+            $message = 'File at "%s" is not readable, check its permissions';
+        } elseif ('' === trim(file_get_contents($path))) {
+            // The input file was really empty and thus contains no classes
+            return array();
+        } else {
+            $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
+        }
+        $error = error_get_last();
+        if (isset($error['message'])) {
+            $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
+        }
+        throw new \RuntimeException(sprintf($message, $path));
+    }
+    // return early if there is no chance of matching anything in this file
+    if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
+        return array();
+    }
+    // strip heredocs/nowdocs
+    $contents = preg_replace('{<<<[ \t]*([\'"]?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)(?:\s*)\\2(?=\s+|[;,.)])}s', 'null', $contents);
+    // strip strings
+    $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
+    // strip leading non-php code if needed
+    if (substr($contents, 0, 2) !== '<?') {
+        $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
+        if ($replacements === 0) {
+            return array();
+        }
+    }
+    // strip non-php blocks in the file
+    $contents = preg_replace('{\?>(?:[^<]++|<(?!\?))*+<\?}s', '?><?', $contents);
+    // strip trailing non-php code if needed
+    $pos = strrpos($contents, '?>');
+    if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
+        $contents = substr($contents, 0, $pos);
+    }
+    // strip comments if short open tags are in the file
+    if (preg_match('{(<\?)(?!(php|hh))}i', $contents)) {
+        $contents = preg_replace('{//.* | /\*(?:[^*]++|\*(?!/))*\*/}x', '', $contents);
+    }
+    preg_match_all('{
+        (?:
+             \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
+           | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;]
+        )
+    }ix', $contents, $matches);
+    $classes = array();
+    $namespace = '';
+    for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
+        if (!empty($matches['ns'][$i])) {
+            $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
+        } else {
+            $name = $matches['name'][$i];
+            // skip anon classes extending/implementing
+            if ($name === 'extends' || $name === 'implements') {
+                continue;
+            }
+            if ($name[0] === ':') {
+                // This is an XHP class, https://github.com/facebook/xhp
+                $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
+            } elseif ($matches['type'][$i] === 'enum') {
+                // In Hack, something like:
+                //   enum Foo: int { HERP = '123'; }
+                // The regex above captures the colon, which isn't part of
+                // the class name.
+                $name = rtrim($name, ':');
+            }
+            $classes[] = ltrim($namespace . $name, '\\');
+        }
+    }
+    return $classes;
+}
+
+$options = getopt('i:f:', []);
+$file = $options["f"];
+$input = $options["i"];
+
+$classes = findClasses($file);
+foreach($classes as $class) {
+  echo '$classmap[\''.$class.'\'] = \''.$input.'/'.$file.'\';';
+  echo "\n";
+}
diff --git a/guix/build-system/composer.scm b/guix/build-system/composer.scm
new file mode 100644
index 0000000000..0299f11906
--- /dev/null
+++ b/guix/build-system/composer.scm
@@ -0,0 +1,173 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 composer)
+  #:use-module (guix store)
+  #:use-module (guix utils)
+  #:use-module (guix derivations)
+  #:use-module (guix search-paths)
+  #:use-module (guix build-system)
+  #:use-module (guix build-system gnu)
+  #:use-module (guix gexp)
+  #:use-module (guix packages)
+  #:use-module (gnu packages)
+  #:use-module (ice-9 match)
+  #:use-module (srfi srfi-1)
+  #:export (%composer-build-system-modules
+            lower
+            composer-build
+            composer-build-system))
+
+;; Commentary:
+;;
+;; Standard build procedure for PHP packages using Composer. This is implemented
+;; as an extension of `gnu-build-system'.
+;;
+;; Code:
+
+(define (default-php)
+  "Return the default PHP package."
+
+  ;; Do not use `@' to avoid introducing circular dependencies.
+  (let ((module (resolve-interface '(gnu packages php))))
+    (module-ref module 'php)))
+
+(define (default-findclass)
+  "Return the default findclass script."
+  (search-auxiliary-file "findclass.php"))
+
+(define (default-composer-classloader)
+  "Return the default composer-classloader package."
+
+  ;; Do not use `@' to avoid introducing circular dependencies.
+  (let ((module (resolve-interface '(gnu packages php-xyz))))
+    (module-ref module 'composer-classloader)))
+
+(define %composer-build-system-modules
+  ;; Build-side modules imported by default.
+  `((guix build composer-build-system)
+    (guix build union)
+    (json)
+    (json builder)
+    (json parser)
+    (json record)
+    ,@%gnu-build-system-modules))
+
+(define* (lower name
+                #:key source inputs native-inputs outputs system target
+                (php (default-php))
+                (composer-classloader (default-composer-classloader))
+                (findclass (default-findclass))
+                #:allow-other-keys
+                #:rest arguments)
+  "Return a bag for NAME."
+  (define private-keywords
+    '(#:source #:target #:php #:composer-classloader #:findclass #:inputs #:native-inputs))
+
+  (and (not target)                               ;XXX: no cross-compilation
+       (bag
+         (name name)
+         (system system)
+         (host-inputs `(,@(if source
+                              `(("source" ,source))
+                              '())
+                        ,@inputs
+
+                        ;; Keep the standard inputs of 'gnu-build-system'.
+                        ,@(standard-packages)))
+         (build-inputs `(("php" ,php)
+                         ("findclass.php" ,findclass)
+			 ("composer-classloader" ,composer-classloader)
+                         ,@native-inputs))
+         (outputs outputs)
+         (build composer-build)
+         (arguments (strip-keyword-arguments private-keywords arguments)))))
+
+(define* (composer-build store name inputs
+                         #:key (guile #f)
+                         (outputs '("out")) (configure-flags ''())
+                         (search-paths '())
+                         (out-of-source? #t)
+                         (composer-file "composer.json")
+                         (tests? #t)
+                         (test-target "test")
+                         (install-target "install")
+                         (validate-runpath? #t)
+                         (patch-shebangs? #t)
+                         (strip-binaries? #t)
+                         (strip-flags ''("--strip-debug"))
+                         (strip-directories ''("lib" "lib64" "libexec"
+                                               "bin" "sbin"))
+                         (phases '(@ (guix build composer-build-system)
+                                     %standard-phases))
+                         (system (%current-system))
+                         (imported-modules %composer-build-system-modules)
+                         (modules '((guix build composer-build-system)
+                                    (guix build utils)
+                                    (json))))
+  "Build SOURCE using PHP, and with INPUTS. This assumes that SOURCE provides
+a 'composer.json' file as its build system."
+  (define builder
+    `(begin
+       (use-modules ,@modules)
+       (composer-build #:source ,(match (assoc-ref inputs "source")
+                                   (((? derivation? source))
+                                    (derivation->output-path source))
+                                   ((source)
+                                    source)
+                                   (source
+                                    source))
+                       #:system ,system
+                       #:outputs %outputs
+                       #:inputs %build-inputs
+                       #:search-paths ',(map search-path-specification->sexp
+                                             search-paths)
+                       #:phases ,phases
+                       #:out-of-source? ,out-of-source?
+                       #:composer-file ,composer-file
+                       #:tests? ,tests?
+                       #:test-target ,test-target
+                       #:install-target ,install-target
+                       #:validate-runpath? ,validate-runpath?
+                       #:patch-shebangs? ,patch-shebangs?
+                       #:strip-binaries? ,strip-binaries?
+                       #:strip-flags ,strip-flags
+                       #:strip-directories ,strip-directories)))
+
+  (define guile-for-build
+    (match guile
+      ((? package?)
+       (package-derivation store guile system #:graft? #f))
+      (#f                                         ; the default
+       (let* ((distro (resolve-interface '(gnu packages commencement)))
+              (guile  (module-ref distro 'guile-final)))
+         (package-derivation store guile system #:graft? #f)))))
+
+  (build-expression->derivation store name builder
+                                #:system system
+                                #:inputs inputs
+                                #:modules imported-modules
+                                #:outputs outputs
+                                #:guile-for-build guile-for-build))
+
+(define composer-build-system
+  (build-system
+    (name 'composer)
+    (description "The standard Composer build system")
+    (lower lower)))
+
+;;; composer.scm ends here
diff --git a/guix/build/composer-build-system.scm b/guix/build/composer-build-system.scm
new file mode 100644
index 0000000000..1af5e59b81
--- /dev/null
+++ b/guix/build/composer-build-system.scm
@@ -0,0 +1,241 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
+;;;
+;;; 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 composer-build-system)
+  #:use-module ((guix build gnu-build-system) #:prefix gnu:)
+  #:use-module (guix build utils)
+  #:use-module (ice-9 match)
+  #:use-module (json)
+  #:use-module (srfi srfi-26)
+  #:export (%standard-phases
+            composer-build))
+
+;; Commentary:
+;;
+;; Builder-side code of the standard composer build procedure.
+;;
+;; Code:
+
+(define (json->require dict)
+  (if dict
+      (let loop ((result '()) (require dict))
+        (match require
+          (() result)
+          ((((? (cut string-contains <> "/") name) . _)
+             require ...)
+           (loop (cons name result) require))
+          ((_ require ...) (loop result require))))
+      '()))
+
+(define-json-mapping <composer-autoload> make-composer-autoload composer-autoload?
+  json->composer-autoload
+  (psr-4 composer-autoload-psr-4 "psr-4"
+                (match-lambda
+                  (#f '())
+                  (psr-4 psr-4)))
+  (classmap composer-autoload-classmap "classmap"
+            (match-lambda
+              (#f '())
+              (#(lst ...) lst))))
+
+(define-json-mapping <composer-package> make-composer-package composer-package?
+  json->composer-package
+  (name         composer-package-name)
+  (autoload     composer-package-autoload "autoload" json->composer-autoload)
+  (autoload-dev composer-package-autoload-dev "autoload-dev" json->composer-autoload)
+  (require      composer-package-require "require" json->require)
+  (dev-require  composer-package-dev-require "require-dev" json->require)
+  (scripts      composer-package-scripts "scripts"
+                (match-lambda
+                  (#f '())
+                  ((scripts ...) scripts)))
+  (binaries     composer-package-binaries "bin"
+                (match-lambda
+                  (#f '())
+                  (#(lst ...) lst))))
+
+(define* (read-package-data #:key (filename "composer.json"))
+  (call-with-input-file filename
+    (lambda (port)
+      (json->composer-package (json->scm port)))))
+
+(define* (check #:key composer-file inputs outputs tests? test-target #:allow-other-keys)
+  "Install the given package."
+  (when tests?
+    (mkdir-p "vendor")
+    (create-autoload (string-append (getcwd) "/vendor") composer-file
+                     (append inputs outputs) #:dev-dependencies? #t)
+    (let* ((package-data (read-package-data #:filename composer-file))
+           (scripts (composer-package-scripts package-data))
+           (test-script (assoc-ref scripts test-target))
+           (dependencies (composer-package-require package-data))
+           (dependencies-dev (composer-package-dev-require package-data))
+           (name (composer-package-name package-data)))
+      (for-each
+        (match-lambda
+          ((_ . input)
+           (let ((bin (find-php-bin input)))
+             (when bin
+               (copy-recursively bin "vendor/bin")))))
+        inputs)
+      (match test-script
+        ((? string? command)
+         (unless (zero? (system command))
+           (throw 'failed-command command)))
+        (('@ (? string? command) ...)
+         (for-each
+           (lambda (c)
+             (unless (zero? (system c))
+               (throw 'failed-command c)))
+           command))
+        (#f (invoke "vendor/bin/phpunit")))))
+  #t)
+
+(define (find-php-bin input)
+  (let* ((web-dir (string-append input "/share/web"))
+         (vendors (if (file-exists? web-dir)
+                      (find-files web-dir "^vendor$" #:directories? #t)
+                      #f)))
+    (match vendors
+      ((vendor)
+       (let ((bin (string-append vendor "/bin")))
+         (and (file-exists? bin) bin)))
+      (_ #f))))
+
+(define (find-php-dep inputs dependency)
+  (let loop ((inputs inputs))
+    (match inputs
+      (() (throw 'unsatisfied-dependency "Unsatisfied dependency: required "
+                 dependency))
+      (((_ . input) inputs ...)
+       (let ((autoload (string-append input "/share/web/" dependency
+                                      "/vendor/autoload_conf.php")))
+          (if (file-exists? autoload)
+              autoload
+              (loop inputs)))))))
+
+(define* (create-autoload vendor composer-file inputs #:key dev-dependencies?)
+  "creates an autoload.php file that sets up the class locations for this package,
+so it can be autoloaded by PHP when the package classes are required."
+  (with-output-to-file (string-append vendor "/autoload.php")
+    (lambda _
+      (display (string-append
+                 "<?php
+// autoload.php @generated by Guix
+$map = $psr4map = $classmap = array();
+require_once '" vendor "/autoload_conf.php'
+require_once '" (assoc-ref inputs "composer-classloader") "/share/web/composer/ClassLoader.php'
+$loader = new \\Composer\\Autoload\\ClassLoader();
+foreach ($map as $namespace => $path) {
+  $loader->set($namespace, $path);
+}
+foreach ($psr4map as $namespace => $path) {
+  $loader->setPsr4($namespace, $path);
+}
+$loader->addClassMap($classmap);
+$loader->register();
+"))))
+  ;; Now, create autoload_conf.php that contains the actual data, as a set
+  ;; of arrays
+  (let* ((package-data (read-package-data #:filename composer-file))
+         (autoload (composer-package-autoload package-data))
+         (autoload-dev (composer-package-autoload-dev package-data))
+         (dependencies (composer-package-require package-data))
+         (dependencies-dev (composer-package-dev-require package-data)))
+    (with-output-to-file (string-append vendor "/autoload_conf.php")
+      (lambda _
+        (format #t "<?php~%")
+        (format #t "// autoload_conf.php @generated by Guix~%")
+        (force-output)
+        (for-each
+          (lambda (psr4)
+            (match psr4
+              ((key . value)
+               (format #t "$psr4map['~a'] = '~a/../~a';~%"
+                       (string-join (string-split key #\\) "\\\\")
+                       vendor value))))
+          (append
+            (composer-autoload-psr-4 autoload)
+            (if dev-dependencies?
+                (composer-autoload-psr-4 autoload-dev)
+                '())))
+        (for-each
+          (lambda (classmap)
+            (for-each
+              (lambda (file)
+                (invoke "php" (assoc-ref inputs "findclass.php")
+                        "-i" (string-append vendor "/..") "-f" file))
+              (find-files classmap ".(php|hh|inc)$")))
+          (append
+            (composer-autoload-classmap autoload)
+            (if dev-dependencies?
+                (composer-autoload-classmap autoload-dev)
+                '())))
+        (for-each
+          (lambda (dep)
+            (format #t "require_once '~a';~%" (find-php-dep inputs dep)))
+          (append
+            dependencies
+            (if dev-dependencies?
+                dependencies-dev
+                '())))))))
+
+(define* (install #:key inputs outputs composer-file #:allow-other-keys)
+  "Install the given package."
+  (let* ((out (assoc-ref outputs "out"))
+         (package-data (read-package-data #:filename composer-file))
+         (name (composer-package-name package-data))
+         (php-dir (string-append out "/share/web/" name))
+         (bin-dir (string-append php-dir "/vendor/bin"))
+         (bin (string-append out "/bin"))
+         (binaries (composer-package-binaries package-data)))
+      (mkdir-p php-dir)
+      (copy-recursively "." php-dir)
+      (mkdir-p (string-append php-dir "/vendor"))
+      (when binaries
+        (mkdir-p bin-dir)
+        (mkdir-p bin)
+        (for-each
+          (lambda (file)
+            (let ((installed-file (string-append bin-dir "/" (basename file)))
+                  (bin-file (string-append bin "/" (basename file)))
+                  (original-file (string-append php-dir "/" file)))
+              (symlink original-file installed-file)
+              (symlink original-file bin-file)))
+          binaries))
+      (create-autoload (string-append php-dir "/vendor")
+                       composer-file inputs))
+  #t)
+
+(define %standard-phases
+  ;; Everything is as with the GNU Build System except for the `configure'
+  ;; , `build', `check' and `install' phases.
+  (modify-phases gnu:%standard-phases
+    (delete 'bootstrap)
+    (delete 'configure)
+    (delete 'build)
+    (delete 'check)
+    (replace 'install install)
+    (add-after 'install 'check check)))
+
+(define* (composer-build #:key inputs (phases %standard-phases)
+                         #:allow-other-keys #:rest args)
+  "Build the given package, applying all of PHASES in order."
+  (apply gnu:gnu-build #:inputs inputs #:phases phases args))
+
+;;; composer-build-system.scm ends here
-- 
2.28.0


  reply	other threads:[~2020-09-29 14:50 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-12 22:20 [bug#42338] [PATCH] Add composer build system (PHP) Julien Lepiller
2020-07-12 22:25 ` [bug#42338] [PATCH 01/34] guix: import: Add composer importer Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 02/34] gnu: Add composer-classloader Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 03/34] guix: Add composer-build-system Julien Lepiller
2020-09-07 14:09     ` Ludovic Courtès
2020-09-17 22:44       ` Julien Lepiller
2020-09-18  8:45         ` Ludovic Courtès
2020-09-18 23:24           ` Julien Lepiller
2020-09-25 10:33             ` Ludovic Courtès
2020-09-29 14:49               ` Julien Lepiller [this message]
2020-09-30  9:24                 ` Ludovic Courtès
2020-12-18 23:43                   ` Julien Lepiller
2020-12-21 14:51                     ` Ludovic Courtès
2020-07-12 22:25   ` [bug#42338] [PATCH 04/34] gnu: Add php-doctrine-instantiator Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 05/34] gnu: Add php-sebastian-recursion-context Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 06/34] gnu: Add php-sebastian-exporter Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 07/34] gnu: Add php-myclabs-deep-copy Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 08/34] gnu: Add php-phar-io-version Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 09/34] gnu: Add php-phar-io-manifest Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 10/34] gnu: Add php-symfony-polyfill-ctype Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 11/34] gnu: Add php-webmozart-assert Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 12/34] gnu: Add php-phpdocumentor-reflection-common Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 13/34] gnu: Add php-phpdocumentor-type-resolver Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 14/34] gnu: Add php-phpdocumentor-reflection-docblock Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 15/34] gnu: Add php-theseer-tokenizer Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 16/34] gnu: Add php-sebastian-code-unit-reverse-lookup Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 17/34] gnu: Add php-phpunit-php-token-stream Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 18/34] gnu: Add php-sebastian-version Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 19/34] gnu: Add php-phpunit-php-file-iterator Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 20/34] gnu: Add php-phpunit-php-text-template Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 21/34] gnu: Add php-sebastian-diff Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 22/34] gnu: Add php-sebastian-comparator Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 23/34] gnu: Add php-sebastian-environment Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 24/34] gnu: Add php-phpspec-prophecy Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 25/34] gnu: Add php-sebastian-object-reflector Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 26/34] gnu: Add php-sebastian-global-state Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 27/34] gnu: Add php-sebastian-object-enumerator Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 28/34] gnu: Add php-sebastian-resource-operations Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 29/34] gnu: Add php-sebastian-type Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 30/34] gnu: Add php-phpunit-php-code-coverage Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 31/34] gnu: Add php-phpunit-php-timer Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 32/34] gnu: Add php-phpunit-php-invoker Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 33/34] gnu: Add php-sebastian-code-unit Julien Lepiller
2020-07-12 22:25   ` [bug#42338] [PATCH 34/34] gnu: Add phpunit Julien Lepiller
2020-09-07 14:06   ` [bug#42338] [PATCH 01/34] guix: import: Add composer importer Ludovic Courtès
2020-09-17 22:43     ` Julien Lepiller
2020-09-18  8:31       ` Ludovic Courtès
2020-09-18 23:20         ` Julien Lepiller
2020-09-25 10:27           ` Ludovic Courtès
2021-10-16  4:15             ` [bug#42338] [PATCH] Add composer build system (PHP) Maxim Cournoyer
2021-08-23  9:46 ` [bug#42338] db
2022-08-13 20:30 ` [bug#42338] Ping about php composer guix-patches--- via
2022-08-13 20:38   ` Julien Lepiller
2022-10-06 16:27 ` [bug#42338] [PATCH] Add composer build system (PHP) Maxime Devos
2022-10-11 18:07   ` guix-patches--- via
2023-04-21  0:23 ` Adam Faiz via Guix-patches via
2023-09-26 10:31 ` [bug#42338] [PATCH v3 1/7] guix: import: Add composer importer Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 2/7] gnu: Add composer-classloader Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 3/7] guix: Add composer-build-system Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 4/7] guix: import: composer: Use memoization Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 5/7] guix: import: composer: Fix json->require Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 6/7] guix: import: composer: More robust string->license Nicolas Graves via Guix-patches via
2023-09-26 10:31   ` [bug#42338] [PATCH v3 7/7] guix: import: composer: Modern inputs formatting Nicolas Graves via Guix-patches via
2023-09-26 10:43   ` [bug#42338] [PATCH v3 1/7] guix: import: Add composer importer Nicolas Graves via Guix-patches via
2023-10-14 15:48   ` Ludovic Courtès
2023-09-26 11:25 ` [bug#42338] [PATCH v3] guix: import: composer: Fix match-lambda with a default fallback Nicolas Graves via Guix-patches via
2023-09-26 11:27   ` Nicolas Graves via Guix-patches via
2023-09-26 11:29 ` [bug#42338] [PATCH v4] guix: composer-build-system: Fix match-lambda with a fallback Nicolas Graves via Guix-patches via
2023-11-02 15:04 ` [bug#42338] [PATCH 0/9] Composer build system Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 1/9] guix: import: Add composer importer Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 2/9] gnu: Add composer-classloader Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 3/9] guix: Add composer-build-system Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 4/9] guix: import: composer: Use memoization Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 5/9] guix: import: composer: Fix json->require Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 6/9] guix: import: composer: More robust string->license Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 7/9] guix: import: composer: Modern inputs formatting Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 8/9] guix: import: composer: Full rewrite composer-fetch Nicolas Graves via Guix-patches via
2023-11-02 15:04   ` [bug#42338] [PATCH 9/9] gnu: composer-build-system: Full check phase rewrite Nicolas Graves via Guix-patches via
2023-11-02 15:16 ` [bug#42338] [PATCH v5 0/9] Composer build-system Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 1/9] guix: import: Add composer importer Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 2/9] gnu: Add composer-classloader Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 3/9] guix: Add composer-build-system Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 4/9] guix: import: composer: Use memoization Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 5/9] guix: import: composer: Fix json->require Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 6/9] guix: import: composer: More robust string->license Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 7/9] guix: import: composer: Modern inputs formatting Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 8/9] guix: import: composer: Full rewrite composer-fetch Nicolas Graves via Guix-patches via
2023-11-02 15:16   ` [bug#42338] [PATCH v5 9/9] gnu: composer-build-system: Full check phase rewrite Nicolas Graves via Guix-patches via
     [not found]   ` <87ttq3u8m4.fsf@ngraves.fr>
2023-12-07 12:36     ` [bug#42338] [Nicolas Graves via Guix-patches via] [bug#42338] [PATCH v5 0/9] Composer build-system Nicolas Graves via Guix-patches via
2023-12-18 22:33   ` Ludovic Courtès
2023-12-19  7:43     ` Nicolas Graves via Guix-patches via
2023-12-09 22:00 ` [bug#42338] [PATCH] Add composer build system (PHP) Charlie McMackin
2023-12-20 10:41 ` Wilko Meyer
2023-12-20 11:31   ` Julien Lepiller
2023-12-20 11:40     ` Wilko Meyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200929164920.0684be42@tachikoma.lepiller.eu \
    --to=julien@lepiller.eu \
    --cc=42338@debbugs.gnu.org \
    --cc=ludo@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).