From patchwork Sun Feb 27 02:34:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Philip McGrath X-Patchwork-Id: 37498 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 4746127BBE9; Sun, 27 Feb 2022 02:39:19 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,FROM_FMBLA_NEWDOM,MAILING_LIST_MULTI,RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL,SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id F35F127BBEC for ; Sun, 27 Feb 2022 02:39:14 +0000 (GMT) Received: from localhost ([::1]:39328 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nO9Ss-0006q5-4n for patchwork@mira.cbaines.net; Sat, 26 Feb 2022 21:39:14 -0500 Received: from eggs.gnu.org ([209.51.188.92]:42650) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nO9Sh-0006om-U1 for guix-patches@gnu.org; Sat, 26 Feb 2022 21:39:03 -0500 Received: from debbugs.gnu.org ([209.51.188.43]:34464) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nO9Sh-0006U4-LR for guix-patches@gnu.org; Sat, 26 Feb 2022 21:39:03 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nO9Sh-0004IX-H6 for guix-patches@gnu.org; Sat, 26 Feb 2022 21:39:03 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#53878] [PATCH v6 10/24] gnu: racket-minimal: Separate from the Racket VM. Resent-From: Philip McGrath Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Sun, 27 Feb 2022 02:39:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 53878 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 53878@debbugs.gnu.org, Liliana Marie Prikler , zimoun Cc: Philip McGrath , Ludovic =?utf-8?q?Court=C3=A8?= =?utf-8?q?s?= , Maxime Devos , raingloom , Liliana Marie Prikler , Attila Lendvai , Malte Gerdes Received: via spool by 53878-submit@debbugs.gnu.org id=B53878.164592949216320 (code B ref 53878); Sun, 27 Feb 2022 02:39:03 +0000 Received: (at 53878) by debbugs.gnu.org; 27 Feb 2022 02:38:12 +0000 Received: from localhost ([127.0.0.1]:56559 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nO9Rr-0004F8-AW for submit@debbugs.gnu.org; Sat, 26 Feb 2022 21:38:12 -0500 Received: from mail-qt1-f179.google.com ([209.85.160.179]:36577) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nO9Rm-0004Dl-LM for 53878@debbugs.gnu.org; Sat, 26 Feb 2022 21:38:08 -0500 Received: by mail-qt1-f179.google.com with SMTP id f18so6101464qtb.3 for <53878@debbugs.gnu.org>; Sat, 26 Feb 2022 18:38:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philipmcgrath.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MyqBuKQrh0l2BfKrMcE8f1kV4NNl5lRbW0Psl3d3OiQ=; b=FvZGiDbkVstrWdAEyNk4LEuduQ98RCT60uqNcLZYtV1bL9qc9rUxMJyQsxacx492EF 3YQLJ2HaekqE5ofL17VDfQQ/JFVuCjCIyDNU20LsJeLH0wWFK4VHPmi7A/3Gyu0+9gln 47rc9ARUoOsAAMhjb0KQWKQoJe+i+QQ223Vms4K8Ie175X1M6xDFDufQbCz/fajXqitF fkrZk+bersI9vBZLwgr490IMgOGYa+Ahhi59Kjw3SIgbO7MmGejEm0P8uDOsU8Xs6MbZ osPPL0DCZRsx6UsEXF3KjPzZ/jF/xCdyfyYAW4+SCpLxqXIPcVLpcwK0OZrEXC02jJbn tP8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MyqBuKQrh0l2BfKrMcE8f1kV4NNl5lRbW0Psl3d3OiQ=; b=S/kbKTU6rAXKNrb6FDVCkY4gkuJAvJ9O2D0sEdbotekROR56fbydiswFZYVrmDLy/f lahwXt2KWdV2tU0qvO+QxW6pu1YxYZZOuRT4DI+Ng21qQHPmDG2DOihljVzqDr47dejV DZ4lTnBLaLKZ0RYYAPeNx8OL4l7tAf/H+/iBuBYXcZUnjl3OBU2KAVqezsTtPMsjvtcb YDVqG9bKQC8IjgzIoKXuQG4Wbaj40pXdCmAdwdzkGWDRs4CKksixGZT3wpHlJIHA0NLr DYu8NPNTgzMLtLSKjs+wWMsQIfiaS/3ZIoJ02N7QSrCdaSMUaOT4L2nckKfeiOH3ES1O Xs6w== X-Gm-Message-State: AOAM530rwAmcn9QzBOO7BeYJl3M861RNmrh9bYkbTaJBe4Slk+lAQhy9 gspvObdAb+KPEaddJZ+/J9AMTati/SL3bEZ/utA= X-Google-Smtp-Source: ABdhPJwoWF0tZtaa+FUGbyvkM9J1w/kYkOh7gb00OeR+tjbbkH0OjtZLw/uL0kUx0bsiFnMDs329Xg== X-Received: by 2002:a05:622a:1113:b0:2dd:5385:36c3 with SMTP id e19-20020a05622a111300b002dd538536c3mr12209617qty.262.1645929480317; Sat, 26 Feb 2022 18:38:00 -0800 (PST) Received: from localhost (c-73-125-98-51.hsd1.fl.comcast.net. [73.125.98.51]) by smtp.gmail.com with UTF8SMTPSA id t2-20020a05622a01c200b002de5098fbaesm4330154qtw.26.2022.02.26.18.37.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 26 Feb 2022 18:37:59 -0800 (PST) From: Philip McGrath Date: Sat, 26 Feb 2022 21:34:36 -0500 Message-Id: <20220227023450.1877215-11-philip@philipmcgrath.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20220227023450.1877215-1-philip@philipmcgrath.com> References: <20220220060610.178131-1-philip@philipmcgrath.com> <20220227023450.1877215-1-philip@philipmcgrath.com> MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: "Guix-patches" X-getmail-retrieved-from-mailbox: Patches For consistency with other Racket distributions, 'racket-minimal' should have the "racket-lib" Racket package installed: see . Happily, this gives us a clean boundary between the core Racket VM and compiler, with all of the bootstrapping involved, and building Racket packages and installation layers, which can be handled in a nice, uniform way and eventually turned into a 'racket-build-system'. Building the VM layer as an "in-place" installation should help us use it with other Racket tools. * gnu/packages/racket.scm (racket-vm-common-configure-flags): Add "--enable-origtree". Adapt "--enable-racket=" for "opt/racket-vm/" prefix. (racket-minimal-bc-cgc): Rename to ... (racket-vm-cgc): ... this new variable. [inputs]: Move 'openssl' and 'sqlite' to new 'racket-minimal'. [arguments]<#:strip-directories>: Use "opt/racket-vm/" prefix. <#:phases>: Wrap 'configure', 'patch-shebangs', 'validate-runpath', 'make-dynamic-linker-cache', and 'patch-dot-desktop-files' to use "opt/racket-vm/" prefix. Adapt 'initialize-config.rktd' for removal of 'openssl' and 'sqlite'. [description]: Tweak. (racket-minimal-bc-3m): Rename to ... (racket-vm-bc): ... this new variable. [synopsis, description]: Tweak. (racket-vm-cs): New variable, adapted from the old 'racket-minimal'. (chez-scheme-for-racket-bootstrap-bootfiles)[arguments]<#:phhases>: Adapt to the "opt/racket-vm/" prefix. (racket-minimal): Rewrite like 'racket' using 'racket-vm-cs'. (racket): Inherit from 'racket-minimal'. [inputs]: Add 'racket-vm-cs'. Move "racket-lib" and "base" to 'racket-minimal'. [arguments]<#:make-flags, #:configure-flags>: Override from 'racket-minimal'. (configure-layer.rkt): Adapt to support in-place VM build with possible intermediate layer. --- gnu/packages/racket.scm | 597 ++++++++++++++++++++++++++-------------- 1 file changed, 385 insertions(+), 212 deletions(-) diff --git a/gnu/packages/racket.scm b/gnu/packages/racket.scm index 4f5f0c1df2..3271e78d45 100644 --- a/gnu/packages/racket.scm +++ b/gnu/packages/racket.scm @@ -54,7 +54,91 @@ (define-module (gnu packages racket) ;; Commentary: ;; -;; Here's how bootstrapping minimal Racket works: +;; Anatomy of Racket: +;; ------------------ +;; +;; The main Racket Git repository () is +;; organized broadly like this: +;; +;; . +;; ├── Makefile +;; ├── pkgs/ +;; └── racket/ +;; ├── collects/ +;; └── src/ +;; ├── configure +;; ├── Makefile.in +;; ├── bc/ +;; ├── cs/ +;; ├── ChezScheme/ +;; └── ... +;; +;; The 'racket/src/' directory contains the source of the runtime system, core +;; compiler, and primitives for the major Racket implementations: this layer +;; is called the ``Racket VM''. It is basically a normal autotools +;; project. (Even when Racket VM implementations use components implemented in +;; Racket, they are compiled in special modes to produce VM primitives.) +;; (There are or have been experimental Racket VM implementations elsewhere, +;; e.g. .) +;; +;; The 'racket/collects/' directory contains ``built in'' Racket libraries +;; that are not part of any package, including the implementation of +;; 'racket/base': in particular, it must contain enough to implement `raco pkg +;; install'. It is theoretically possible to use the Racket VM layer without +;; the main collections, but it is not stable or useful. +;; +;; The 'pkgs/' directory contains Racket packages that are especially closely +;; tied to the implementation of the Racket VM, including 'compiler-lib', +;; 'racket-doc', and 'racket-test'. Some of these packages depend on Racket +;; packages that are developed in other Git repositories, predominantly but +;; not exclusively under the 'racket' GitHub organization. Conversely, not all +;; of the packages developed in the main Git repository are part of the main +;; Racket distribution. (Additionally, components of the Racket VM that are +;; implemented in Racket can be installed as packages, mostly for ease of +;; development.) +;; +;; The top-level 'Makefile' is more like a directory of scripts: it has +;; convienience targets for developing Racket, and it cooperates with the +;; 'distro-build' package to assemble custom Racket distributions. It is not +;; part of Racket source distributions: the root of a source distribution is +;; basically 'racket/src' with some extra package sources and configuration +;; added. +;; +;; A ''minimal Racket'' installation includes two packages: 'base', which is a +;; sort of bridge between the current ``built-in'' collections and the package +;; system's model of dependencies, and 'racket-lib', which, for installations +;; that can not rely on a system package manager, pulls in the SQLite and +;; OpenSSL shared libraries as platform-specific dependencies for use by the +;; ``built-in'' collections. +;; +;; The main Racket distribution consists of installing the 'main-distribution' +;; package and all of its dependencies. +;; +;; The default mode when building Racket (or installing it with the released +;; installers) is an ``in-place build'', which produces a self-contained, +;; relocatable, roughly FHS-like directory. (Racket also supports +;; ``Unix-style'' installations, which rearrange the parts of an in-place +;; build into Racket-specific subdirectories and generally tries to work for +;; installation into an FHS-based system.) Certain tools, e.g. 'distro-build' +;; and 'raco cross', are able to work with an in-place Racket build. +;; +;; This file defines the packages 'racket-vm-cgc', 'racket-vm-bc', and +;; 'racket-vm-cs'. All three are in-place builds of 'racket/src/' and +;; 'racket/collects/' and are installed to 'opt/racket-vm/' in the store +;; output. The function 'racket-vm-for-system' returns the recomended Racket +;; VM package for a given system. +;; +;; The file 'racket.scm' builds on these packages to define 'racket-minimal' +;; and 'racket' packages. These use Racket's support for ``layered +;; installations'', which allow an immutable base layer to be extended with +;; additional packages. They use the layer configuration directly provide +;; ready-to-install FHS-like trees, rather than relying on the built in +;; ``Unix-style install'' mechanism. +;; +;; Bootstrapping Racket: +;; --------------------- +;; +;; Here's how bootstrapping Racket works: ;; ;; - Racket BC [CGC] can be built with only a C compiler (except for ;; one caveat discussed below). @@ -72,6 +156,10 @@ (define-module (gnu packages racket) ;; ;; So, we build CGC to build 3M to build bootfiles and CS. ;; +;; (Note: since the CGC variant is basically only for bootstrapping, we +;; often use "BC" to mean "3M", consistent with `(banner)` and the +;; suffixes used on executables when more than one variant co-exists.) +;; ;; One remaining bootstrapping limitation is that Racket's reader, module ;; system, and macro expander are implemented in Racket. For Racket CS, ;; they are compiled to R6RS libraries as discussed above. This note from the @@ -145,14 +233,15 @@ (define (racket-vm-common-configure-flags) '())) ,@(cond ((false-if-exception - (search-input-file %build-inputs "/bin/racket")) + (search-input-file %build-inputs "/opt/racket-vm/bin/racket")) => (lambda (racket) (list (string-append "--enable-racket=" racket)))) (else '())) ,(string-append "CPPFLAGS=-DGUIX_RKTIO_PATCH_BIN_SH=" #$(file-append bash-minimal "/bin/sh")) - "--disable-strip")) + "--disable-strip" + "--enable-origtree")) (define (make-unpack-nanopass+stex) ;; Adapted from chez-scheme. @@ -173,31 +262,25 @@ (define (make-unpack-nanopass+stex) (display "# to placate ../configure"))))) -(define-public racket-minimal-bc-cgc +(define-public racket-vm-cgc ;; Eventually, it may make sense for some vm packages to not be hidden, ;; but this one is especially likely to remain hidden. (hidden-package (package - (name "racket-minimal-bc-cgc") + (name "racket-vm-cgc") (version %racket-version) (source %racket-origin) - (inputs - (list - ;; common to all racket-minimal variants: - openssl - sqlite - bash-minimal ;; <- for `system` - ncurses ;; <- for #%terminal - ;; only for BC variants: - libffi)) + (inputs (list ncurses ;; <- common to all variants (for #%terminal) + bash-minimal ;; <- common to all variants (for `system`) + libffi)) ;; <- only for BC variants (native-inputs (list libtool)) ;; <- only for BC variants (outputs '("out" "debug")) (build-system gnu-build-system) (arguments (list #:configure-flags - #~(cons* "--enable-cgcdefault" - #$(racket-vm-common-configure-flags)) + #~(cons "--enable-cgcdefault" + #$(racket-vm-common-configure-flags)) ;; Tests are in packages like racket-test-core and ;; main-distribution-test that aren't part of the main ;; distribution. @@ -208,51 +291,72 @@ (define-public racket-minimal-bc-cgc (ice-9 regex) (guix build gnu-build-system) (guix build utils)) + #:strip-directories #~'("opt/racket-vm/bin" + "opt/racket-vm/lib") #:phases - #~(modify-phases %standard-phases - (add-before 'configure 'initialize-config.rktd - (lambda* (#:key inputs #:allow-other-keys) - (define (write-racket-hash alist) - ;; inside must use dotted pair notation - (display "#hash(") - (for-each (match-lambda - ((k . v) - (format #t "(~s . ~s)" k v))) - alist) - (display ")\n")) - (define maybe-release-catalog - (let ((v #$(package-version this-package))) - (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" - v) - `(,(string-append - "https://download.racket-lang.org/releases/" - v - "/catalog/")) - '()))) - (mkdir-p "racket/etc") - (with-output-to-file "racket/etc/config.rktd" - (lambda () - (write-racket-hash - `((lib-search-dirs - . (#f #$(file-append (this-package-input "openssl") "/lib") - #$(file-append (this-package-input "sqlite") "/lib"))) - (build-stamp . "") - (catalogs ,@maybe-release-catalog - #f))))))) - (add-before 'configure 'chdir - (lambda _ - (chdir "racket/src"))) - (add-after 'install 'remove-pkgs-directory - ;; If the configured pkgs-dir exists, "pkgs.rktd" does not - ;; exist, and a lock file does not exist, commands like - ;; `raco pkg show` will try to create a lock file and fail - ;; due to the read-only store. - ;; Arguably this may be a bug in `pkg/private/lock`: - ;; see . - ;; As a workaround, remove the directory. - (lambda args - ;; rmdir because we want an error if it isn't empty - (rmdir (string-append #$output "/share/racket/pkgs"))))))) + #~(let () + (define* ((wrap-racket-vm-outputs phase) . args) + (apply + phase + (let loop ((args args)) + (match args + ((#:outputs outputs . args) + `(#:outputs + ,(let loop ((outputs outputs)) + (match outputs + ((("out" . out) . outputs) + `(("out" . ,(string-append out "/opt/racket-vm/")) + ,@outputs)) + ((other . outputs) + (cons other (loop outputs))))) + ,@args)) + ((arg . args) + (cons arg (loop args))))))) + (modify-phases %standard-phases + (add-before 'configure 'initialize-config.rktd + (lambda* (#:key inputs #:allow-other-keys) + (define (write-racket-hash alist) + ;; inside must use dotted pair notation + (display "#hash(") + (for-each (match-lambda + ((k . v) + (format #t "(~s . ~s)" k v))) + alist) + (display ")\n")) + (define maybe-release-catalog + (let ((v #$(package-version this-package))) + (if (string-match "^[0-9]+\\.[0-9]+($|\\.[0-8][0-9]*$)" + v) + `(,(string-append + "https://download.racket-lang.org/releases/" + v + "/catalog/")) + '()))) + (mkdir-p "racket/etc") + (with-output-to-file "racket/etc/config.rktd" + (lambda () + (write-racket-hash + `((build-stamp . "") + (catalogs ,@maybe-release-catalog + #f))))))) + (add-before 'configure 'chdir + (lambda _ + (chdir "racket/src"))) + (replace 'configure + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'configure))) + (replace 'patch-shebangs + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-shebangs))) + (replace 'validate-runpath + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'validate-runpath))) + (replace 'make-dynamic-linker-cache + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'make-dynamic-linker-cache))) + (replace 'patch-dot-desktop-files + (wrap-racket-vm-outputs + (assoc-ref %standard-phases 'patch-dot-desktop-files))))))) (home-page "https://racket-lang.org") (synopsis "Old Racket implementation used for bootstrapping") (description "This variant of the Racket BC (``before Chez'' or @@ -262,32 +366,33 @@ (define maybe-release-catalog scheme) by the 3M variant, which in turn was succeeded in version 8.0 by the Racket CS implementation. -Racket BC [CGC] is primarily used for bootstrapping Racket BC [3M]. It may +Racket CGC is primarily used for bootstrapping Racket BC [3M]. It may also be used for embedding applications without the annotations needed in C code to use the 3M garbage collector.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat))))) -(define-public racket-minimal-bc-3m +(define-public racket-vm-bc (package - (inherit racket-minimal-bc-cgc) - (name "racket-minimal-bc-3m") + (inherit racket-vm-cgc) + (name "racket-vm-bc") (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) - (prepend racket-minimal-bc-cgc))) + (modify-inputs (package-native-inputs racket-vm-cgc) + (prepend racket-vm-cgc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-cgc) + (substitute-keyword-arguments (package-arguments racket-vm-cgc) ((#:configure-flags _ '()) #~(cons "--enable-bconly" #$(racket-vm-common-configure-flags))))) - (synopsis "Minimal Racket with the BC [3M] runtime system") + (synopsis "Racket BC [3M] implementation") (description "The Racket BC (``before Chez'' or ``bytecode'') implementation was the default before Racket 8.0. It uses a compiler written in C targeting architecture-independent bytecode, plus a JIT compiler on most platforms. Racket BC has a different C API and supports a slightly different set of architectures than the current default runtime system, Racket CS (based -on ``Chez Scheme''). +on ``Chez Scheme''). It is the recommended implementation for architectures +that Racket CS doesn't support. This package is the normal implementation of Racket BC with a precise garbage collector, 3M (``Moving Memory Manager'').") @@ -295,23 +400,23 @@ (define-public racket-minimal-bc-3m ;; The LGPL components are only used by Racket BC. (license (list license:lgpl3+ license:asl2.0 license:expat)))) -(define-public racket-minimal +(define-public racket-vm-cs (package - (inherit racket-minimal-bc-3m) - (name "racket-minimal") + (inherit racket-vm-bc) + (name "racket-vm-cs") (inputs - (modify-inputs (package-inputs racket-minimal-bc-cgc) + (modify-inputs (package-inputs racket-vm-cgc) (prepend zlib lz4) (delete "libffi"))) (native-inputs - (modify-inputs (package-native-inputs racket-minimal-bc-cgc) + (modify-inputs (package-native-inputs racket-vm-cgc) (delete "libtool") (prepend chez-scheme-for-racket-bootstrap-bootfiles - racket-minimal-bc-3m))) + racket-vm-bc))) (arguments - (substitute-keyword-arguments (package-arguments racket-minimal-bc-3m) - ((#:phases bc-phases) - #~(modify-phases #$bc-phases + (substitute-keyword-arguments (package-arguments racket-vm-cgc) + ((#:phases those-phases #~%standard-phases) + #~(modify-phases #$those-phases (add-after 'unpack 'unpack-nanopass+stex (lambda args (with-directory-excursion "racket/src/ChezScheme" @@ -328,17 +433,14 @@ (define-public racket-minimal "--enable-libz" "--enable-lz4" #$(racket-vm-common-configure-flags))))) - (synopsis "Racket without bundled packages such as DrRacket") - (description - "Racket is a general-purpose programming language in the Scheme family, -with a large set of libraries and a compiler based on Chez Scheme. Racket is -also a platform for language-oriented programming, from small domain-specific -languages to complete language implementations. + (synopsis "Racket CS implementation") + (description "The Racket CS implementation, which uses ``Chez Scheme'' as +its core compiler and runtime system, has been the default Racket VM +implemetation since Racket 8.0. It performs better than the Racket BC +implementation for most programs. -The ``minimal Racket'' distribution includes just enough of Racket for you to -use @command{raco pkg} to install more. Bundled packages, such as the -DrRacket IDE, are not included.") - (properties `()) +Using the Racket VM packages directly is not recommended: instead, install the +@code{racket-minimal} or @code{racket} packages.") ;; https://download.racket-lang.org/license.html ;; The LGPL components are only used by Racket BC. (license (list license:asl2.0 license:expat)))) @@ -353,7 +455,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles ;; When updating, remember to also update %racket-version in racket.scm. (source %racket-origin) (inputs `()) - (native-inputs (list racket-minimal-bc-3m)) + (native-inputs (list racket-vm-bc)) (build-system copy-build-system) ;; TODO: cross compilation (arguments @@ -371,7 +473,7 @@ (define-public chez-scheme-for-racket-bootstrap-bootfiles (add-before 'install 'build (lambda* (#:key native-inputs inputs #:allow-other-keys) (invoke (search-input-file (or native-inputs inputs) - "/bin/racket") + "/opt/racket-vm/bin/racket") "rktboot/main.rkt")))))) (home-page "https://github.com/racket/ChezScheme") ;; ^ This is downstream of https://github.com/racket/racket, @@ -452,10 +554,116 @@ (define (simple-racket-origin repo hash spec0 . spec*) spec0 spec*)) +(define-public racket-minimal + (package + (name "racket-minimal") + (version %racket-version) + (source #f) + ;; For cross-compilation, Matthew Flatt recommends reusing + ;; as much of `raco cross` as possible. So, put that off until + ;; we have a build system for Racket packages. + (inputs + (list openssl + sqlite + racket-vm-cs ;; TODO (racket-vm-for-system) + (racket-packages-origin + "base" %racket-origin + '("base" "pkgs/base") + '("racket-lib" "pkgs/racket-lib")))) + (build-system gnu-build-system) + (arguments + ;; Here and for the `racket` package, we're using #:configure-flags + ;; to pass flags for `configure-layer.rkt` and #:make-flags + ;; to pass arguments for `raco pkg install`. + (list + #:configure-flags + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format + #f "~s" + (list #$(file-append (this-package-input "openssl") "/lib") + #$(file-append (this-package-input "sqlite") "/lib")))) + #:make-flags #~`("racket-lib") + #:tests? #f ;; packaged separately + #:modules '((guix build gnu-build-system) + (guix build utils) + (guix build union) + (ice-9 match)) + #:imported-modules `((guix build union) + ,@%gnu-build-system-modules) + #:phases + #~(modify-phases %standard-phases + (delete 'unpack) + (replace 'configure + (lambda* (#:key inputs configure-flags #:allow-other-keys) + (let* ((vm-dir (search-input-directory inputs "opt/racket-vm")) + (racket (string-append vm-dir "/bin/racket"))) + (apply invoke + racket + #$configure-layer.rkt + `(,@(cond + ((false-if-exception + (search-input-file + inputs "etc/racket/config.rktd")) + => (lambda (file) + `("--parent" + ,(dirname (dirname (dirname file)))))) + (else + '())) + ,@configure-flags + ,vm-dir + ,#$output)) + (invoke racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" "setup" + "--no-user")))) + (replace 'build + (lambda* (#:key inputs #:allow-other-keys) + ;; We use "share/racket/pkgs" for sources to distinguish them + ;; from the "lib/racket/pkgs" of a potential parent layer. + (union-build (string-append #$output "/lib/racket/pkgs") + (search-path-as-list '("share/racket/pkgs") + (map cdr inputs)) + #:create-all-directories? #t))) + (replace 'install + (lambda* (#:key inputs make-flags #:allow-other-keys) + (let ((racket + (search-input-file inputs "/opt/racket-vm/bin/racket"))) + (unless (null? make-flags) + (invoke racket + "-l-" + "pkg/dirs-catalog" + "--link" + "local-catalog" + (string-append #$output "/lib/racket/pkgs")) + (apply invoke + racket + "--config" (string-append #$output "/etc/racket") + "-l" "raco" + "pkg" "install" + "--installation" + "--auto" + "--catalog" "local-catalog" + make-flags)))))))) + (home-page "https://racket-lang.org") + (synopsis "Racket without bundled packages such as DrRacket") + (description + "Racket is a general-purpose programming language in the Scheme family, +with a large set of libraries and a compiler based on Chez Scheme. Racket is +also a platform for language-oriented programming, from small domain-specific +languages to complete language implementations. + +The ``minimal Racket'' distribution includes just enough of Racket for you to +use @command{raco pkg} to install more. Bundled packages, such as the +DrRacket IDE, are not included.") + ;; https://download.racket-lang.org/license.html + ;; The LGPL components are only used by Racket BC. + (license (list license:asl2.0 license:expat)))) + (define-public racket (package + (inherit racket-minimal) (name "racket") - (version %racket-version) (source #f) (inputs (list @@ -474,6 +682,7 @@ (define-public racket unixodbc libedit ;; TODO reconsider in light of expeditor and readline-gpl racket-minimal ;; <-- TODO non-tethered layer + racket-vm-cs ;; TODO (racket-vm-for-system) (simple-racket-origin "2d" (base32 "1zzcz5qyjv7syi41vb8jkxjp1rqgj61zbsdrg0nlc4qy9qsafzgr") "2d" "2d-doc" "2d-lib") @@ -482,8 +691,6 @@ (define-public racket '("algol60" ".")) (racket-packages-origin "racket" %racket-origin - '("base" "pkgs/base") ;; FIXME belongs in racket-minimal - '("racket-lib" "pkgs/racket-lib") ;; FIXME belongs in racket-minimal '("at-exp-lib" "pkgs/at-exp-lib") '("compiler" "pkgs/compiler") '("compiler-lib" "pkgs/compiler-lib") @@ -808,91 +1015,39 @@ (define-public racket "xrepl" "xrepl-doc" "xrepl-lib"))) (build-system gnu-build-system) (arguments - ;; We're using #:configure-flags to pass flags for - ;; `configure-layer.rkt` and #:make-flags to pass arguments for - ;; `raco pkg install`. - (list - #:configure-flags - #~`("--extra-foreign-lib-search-dirs" - ,(format #f "~s" - '(#$@(map (lambda (name) - (cond - ((this-package-input name) - => (cut file-append <> "/lib")) - (else - (raise-exception - (make-exception - (make-assertion-failure) - (make-exception-with-message - "missing input to the 'racket' package") - (make-exception-with-irritants - (list name))))))) - '("cairo" - "fontconfig-minimal" ;; aka fontconfig - "glib" - "glu" - "gmp" - "gtk+" - "libjpeg-turbo" - "libpng" - "libx11" - "mesa" - "mpfr" - "pango" - "unixodbc" - "libedit"))))) - #:make-flags #~`("main-distribution") - #:tests? #f ;; packaged separately - #:modules '((guix build gnu-build-system) - (guix build utils) - (guix build union) - (ice-9 match)) - #:imported-modules `((guix build union) - ,@%gnu-build-system-modules) - #:phases - #~(modify-phases %standard-phases - (delete 'unpack) - (replace 'configure - (lambda* (#:key inputs configure-flags #:allow-other-keys) - (let* ((racket (search-input-file inputs "bin/racket"))) - (apply invoke - racket - #$configure-layer.rkt - `(,@configure-flags - ,(dirname (dirname racket)) - ,#$output)) - (invoke racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" "setup" - "--no-user")))) - (replace 'build - (lambda* (#:key inputs #:allow-other-keys) - ;; We use "share/racket/pkgs" for sources to distinguish them - ;; from the "lib/racket/pkgs" of a potential parent layer. - (union-build (string-append #$output "/lib/racket/pkgs") - (search-path-as-list '("share/racket/pkgs") - (map cdr inputs)) - #:create-all-directories? #t))) - (replace 'install - (lambda* (#:key inputs make-flags #:allow-other-keys) - (let ((racket (search-input-file inputs "/bin/racket"))) - (unless (null? make-flags) - (invoke racket - "-l-" - "pkg/dirs-catalog" - "--link" - "local-catalog" - (string-append #$output "/lib/racket/pkgs")) - (apply invoke - racket - "--config" (string-append #$output "/etc/racket") - "-l" "raco" - "pkg" "install" - "--installation" - "--auto" - "--catalog" "local-catalog" - make-flags)))))))) - (home-page "https://racket-lang.org") + (substitute-keyword-arguments (package-arguments racket-minimal) + ((#:make-flags _ '()) + #~`("main-distribution")) + ((#:configure-flags _ '()) + #~`("--tethered" + "--extra-foreign-lib-search-dirs" + ,(format #f "~s" + '(#$@(map (lambda (name) + (cond + ((this-package-input name) + => (cut file-append <> "/lib")) + (else + (raise-exception + (make-exception + (make-assertion-failure) + (make-exception-with-message + "missing input to the 'racket' package") + (make-exception-with-irritants + (list name))))))) + '("cairo" + "fontconfig-minimal" ;; aka fontconfig + "glib" + "glu" + "gmp" + "gtk+" + "libjpeg-turbo" + "libpng" + "libx11" + "mesa" + "mpfr" + "pango" + "unixodbc" + "libedit")))))))) (synopsis "Programmable programming language in the Scheme family") (description "Racket is a general-purpose programming language in the Scheme family, @@ -902,10 +1057,7 @@ (define-public racket The main Racket distribution comes with many bundled packages, including the DrRacket IDE, libraries for GUI and web programming, and implementations of -languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog.") - ;; https://download.racket-lang.org/license.html - ;; The LGPL components are only used by Racket BC. - (license (list license:asl2.0 license:expat)))) +languages such as Typed Racket, R5RS and R6RS Scheme, Algol 60, and Datalog."))) (define configure-layer.rkt (scheme-file @@ -918,41 +1070,53 @@ (define configure-layer.rkt racket/port racket/list racket/pretty) - (define config-file-pth - "etc/racket/config.rktd") (define (build-path-string . args) (path->string (apply build-path args))) (define rx:racket ;; Guile's reader doesn't support #rx"racket" (regexp "racket")) + (define tethered? #f) + (define parent #f) (define extra-foreign-lib-search-dirs '()) - (define-values [parent-layer prefix] + (define-values [vm-dir prefix] (command-line #:once-each + [("--tethered") "create a tethered layer" + (set! tethered? #t)] + [("--parent") dir "path of parent layer, if any" + (set! parent dir)] [("--extra-foreign-lib-search-dirs") dir-list "foreign library directories, as a list of strings in `read` syntax" (set! extra-foreign-lib-search-dirs (call-with-input-string dir-list read))] - #:args (parent-layer prefix) - (values parent-layer prefix))) + #:args (vm-dir prefix) + (values vm-dir prefix))) (let* ([config (for/fold - ([config (file->value (build-path parent-layer - config-file-pth))]) - ([spec (in-list - '((lib-dir lib-search-dirs "lib/racket") - (share-dir share-search-dirs "share/racket") - (links-file - links-search-files - "share/racket/links.rktd") - (pkgs-dir pkgs-search-dirs "share/racket/pkgs") - (bin-dir bin-search-dirs "bin") - (man-dir man-search-dirs "share/man") - (doc-dir doc-search-dirs "share/doc/racket") - (include-dir - include-search-dirs - "include/racket")))]) - (match-define (list main-key search-key pth) spec) + ([config (file->value + (if parent + (build-path parent "etc/racket/config.rktd") + (build-path vm-dir "etc/config.rktd")))]) + ([spec + (in-list + '((lib-dir lib-search-dirs "lib/racket" "lib") + (share-dir share-search-dirs "share/racket" "share") + (links-file links-search-files + "lib/racket/links.rktd" + "share/links.rktd") + (pkgs-dir pkgs-search-dirs "lib/racket/pkgs" "share/pkgs") + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(bin-dir bin-search-dirs "bin" "bin") + (bin-dir bin-search-dirs + "lib/racket/bogus-untethered-bin" + "bin") + (man-dir man-search-dirs "share/man" "share/man") + (doc-dir doc-search-dirs "share/doc/racket" "doc") + (include-dir include-search-dirs + "include/racket" + "include")))]) + (match-define (list main-key search-key pth vm-pth) spec) (hash-set* config main-key @@ -961,7 +1125,10 @@ (define-values [parent-layer prefix] (list* #f (hash-ref config main-key - (build-path-string parent-layer pth)) + (lambda () + (if parent + (build-path-string parent pth) + (build-path-string vm-dir vm-pth)))) (filter values (hash-ref config search-key null)))))] [config (hash-update config @@ -995,15 +1162,21 @@ (define-values [rkt old-foreign-dirs] ;; workaround Guile reader/printer: ['|3m| "-bc"] [_ ""])))] - [bin-dir - (hash-ref config 'bin-dir)] [config - (hash-set* config - 'config-tethered-apps-dir (hash-ref config 'apps-dir) - 'config-tethered-console-bin-dir bin-dir - 'config-tethered-gui-bin-dir bin-dir)] - [new-config-pth - (build-path prefix config-file-pth)]) + (cond + [tethered? + ;; Partial workaround for: + ;; https://github.com/racket/racket/issues/4133 + #;(define bin-dir (hash-ref config 'bin-dir)) + (define bin-dir (build-path-string prefix "bin")) + (hash-set* config + 'config-tethered-apps-dir (hash-ref config 'apps-dir) + 'config-tethered-console-bin-dir bin-dir + 'config-tethered-gui-bin-dir bin-dir)] + [else + config])]) + (define new-config-pth + (build-path prefix "etc/racket/config.rktd")) (make-parent-directory* new-config-pth) (call-with-output-file* new-config-pth