diff options
-rw-r--r-- | doc/guix.texi | 35 | ||||
-rw-r--r-- | gnu/packages/ncdu.scm | 3 | ||||
-rw-r--r-- | gnu/packages/zig-xyz.scm | 7 | ||||
-rw-r--r-- | gnu/packages/zig.scm | 63 | ||||
-rw-r--r-- | guix/build-system/zig.scm | 12 | ||||
-rw-r--r-- | guix/build/zig-build-system.scm | 126 |
6 files changed, 197 insertions, 49 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index c58468b910..924f13f0f6 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -10190,17 +10190,30 @@ build system (@command{zig build} command). Selecting this build system adds @code{zig} to the package inputs, in addition to the packages of @code{gnu-build-system}. -There is no @code{configure} phase because Zig packages typically do not -need to be configured. The @code{#:zig-build-flags} parameter is a list of -flags that are passed to the @code{zig} command during the build. The -@code{#:zig-test-flags} parameter is a list of flags that are passed to the -@code{zig test} command during the @code{check} phase. The default compiler -package can be overridden with the @code{#:zig} argument. - -The optional @code{zig-release-type} parameter declares the type of release. -Possible values are: @code{safe}, @code{fast}, or @code{small}. The default -value is @code{#f}, which causes the release flag to be omitted from the -@code{zig} command. That results in a @code{debug} build. +This build system by default installs package source to output. This +behavior can be disabled by setting @code{#:install-source?} parameter +to @code{#f}. + +For packages that don't install anything and don't come with a test +suite (likely library packages to be used by other Zig packages), you +can set @code{#:skip-build?} parameter to @code{#t}, which skips +@code{build} and @code{check} phases. + +The @code{configure} phase sets up environment for @command{zig build}. +You need to add custom phases after it if you want to invoke +@command{zig}. + +The @code{#:zig-build-flags} parameter is a list of flags that are +passed to @command{zig build} in @code{build} phase. The +@code{#:zig-test-flags} parameter is a list of flags that are passed to +@command{zig build test} in @code{check} phase. The default compiler +package can be overridden with the @code{#:zig} parameter. + +The optional @code{#:zig-release-type} parameter declares the type of +release. Possible values are: @code{"safe"}, @code{"fast"}, or +@code{"small"}. The default value is @code{#f}, which causes the +release flag to be omitted from the @code{zig} command and results in a +@code{"debug"} build. @end defvar @defvar scons-build-system diff --git a/gnu/packages/ncdu.scm b/gnu/packages/ncdu.scm index ab88f41dad..c49fefc077 100644 --- a/gnu/packages/ncdu.scm +++ b/gnu/packages/ncdu.scm @@ -72,7 +72,8 @@ ncurses installed.") "01g5mpvsm78lkd0yin82gyancrl23npy69qcp3d60vmm72yiwirz")))) (build-system zig-build-system) (arguments - (list #:zig zig-0.12)) + (list #:zig zig-0.12 + #:install-source? #f)) (inputs (list ncurses `(,zstd "lib"))) (native-inputs (list pkg-config)) (properties `((tunable? . #t))))) diff --git a/gnu/packages/zig-xyz.scm b/gnu/packages/zig-xyz.scm index 0cd08b6ac6..9c86dde556 100644 --- a/gnu/packages/zig-xyz.scm +++ b/gnu/packages/zig-xyz.scm @@ -53,6 +53,7 @@ (build-system zig-build-system) (arguments (list + #:install-source? #f #:phases #~(modify-phases %standard-phases (add-after 'install 'install-wayland-session @@ -98,6 +99,7 @@ directly from a tty using KMS/DRM.") (arguments (list #:zig zig-0.9 + #:install-source? #f #:zig-release-type "safe")) (synopsis "Distributed financial accounting database") (description "TigerBeetle is a financial accounting database designed for @@ -122,8 +124,9 @@ mission-critical safety and performance for financial services.") (build-system zig-build-system) (inputs (list zig-0.10 python)) (arguments - ;; The tests fail with memory leaks. - (list #:tests? #f)) + (list #:install-source? #f + ;; The tests fail with memory leaks. + #:tests? #f)) (synopsis "Zig language server") (description "Zig Language Server is a language server implementing the @acronym{LSP, diff --git a/gnu/packages/zig.scm b/gnu/packages/zig.scm index 99335c5404..2644516e69 100644 --- a/gnu/packages/zig.scm +++ b/gnu/packages/zig.scm @@ -24,6 +24,7 @@ #:use-module (guix gexp) #:use-module (guix packages) #:use-module (guix platform) + #:use-module (guix search-paths) #:use-module (guix utils) #:use-module (guix download) #:use-module (guix git-download) @@ -33,7 +34,51 @@ #:use-module (gnu packages compression) #:use-module (gnu packages llvm) #:use-module (gnu packages llvm-meta) - #:use-module (gnu packages web)) + #:use-module (gnu packages web) + #:export (add-build.zig.zon + rename-zig-dependencies)) + +(define* (add-build.zig.zon name version dependencies #:optional (paths '(""))) + "Snippet to generate build.zig.zon of DEPENDENCIES for package NAME@VERSION." + `(let ((port (open-file "build.zig.zon" "w" #:encoding "utf8"))) + (format port "\ +.{ + .name = \"~a\", + .version = \"~a\", + .paths = .{ +~{\ + \"~a\", +~}\ + }, + .dependencies = .{ +~{\ + .@\"~a\" = .{ + .url = \"\", + }, +~}\ + }, +}~%" ,name ,version (quote ,paths) (quote ,dependencies)) + (close-port port))) + +(define* (rename-zig-dependencies mapping #:optional (directories '("."))) + "Snippet to rename Zig dependencies in build.zig and build.zig.zon." + `(begin + (use-modules (ice-9 match) + (guix build utils)) + (for-each + (lambda (directory) + (for-each + (match-lambda + ((old-name . new-name) + (with-directory-excursion directory + (substitute* "build.zig" + (((string-append "([Dd]ependency.\")" old-name) _ prefix) + (string-append prefix new-name))) + (substitute* "build.zig.zon" + (((format #f "\\.(@\")?~a\"?" old-name)) + (format #f ".@\"~a\"" new-name)))))) + (quote ,mapping))) + (quote ,directories)))) (define (zig-source version commit hash) (origin @@ -169,16 +214,12 @@ (list llvm-13 zig-0.9-glibc-abi-tool)) (native-search-paths - (list - (search-path-specification - (variable "C_INCLUDE_PATH") - (files '("include"))) - (search-path-specification - (variable "CPLUS_INCLUDE_PATH") - (files '("include/c++" "include"))) - (search-path-specification - (variable "LIBRARY_PATH") - (files '("lib" "lib64"))))) + (list $C_INCLUDE_PATH + $CPLUS_INCLUDE_PATH + $LIBRARY_PATH + (search-path-specification + (variable "GUIX_ZIG_PACKAGE_PATH") + (files '("src/zig"))))) (synopsis "General purpose programming language and toolchain") (description "Zig is a general-purpose programming language and toolchain. Among other features it provides diff --git a/guix/build-system/zig.scm b/guix/build-system/zig.scm index 82df75729c..6d16303794 100644 --- a/guix/build-system/zig.scm +++ b/guix/build-system/zig.scm @@ -48,6 +48,8 @@ source (tests? #t) (test-target #f) + (install-source? #t) + (skip-build? #f) (zig-build-flags ''()) (zig-test-flags ''()) (zig-release-type #f) @@ -68,13 +70,15 @@ #:source #+source #:system #$system #:test-target #$test-target + #:install-source? #$install-source? + #:skip-build? #$skip-build? #:zig-build-flags #$zig-build-flags ;; For reproducibility. #:zig-build-target #$(platform-target (lookup-platform-by-system system)) #:zig-test-flags #$zig-test-flags #:zig-release-type #$zig-release-type - #:tests? #$tests? + #:tests? #$(and tests? (not skip-build?)) #:phases #$phases #:outputs #$(outputs->gexp outputs) #:search-paths '#$(sexp->gexp @@ -98,6 +102,8 @@ (native-search-paths '()) (tests? #t) (test-target #f) + (install-source? #t) + (skip-build? #f) (zig-build-flags ''()) (zig-test-flags ''()) (zig-destdir "out") @@ -141,13 +147,15 @@ #:native-search-paths '#$(map search-path-specification->sexp native-search-paths) + #:install-source? #$install-source? + #:skip-build? #$skip-build? #:zig-build-flags #$zig-build-flags #:zig-build-target #$target #:zig-test-flags #$zig-test-flags #:zig-release-type #$zig-release-type #:zig-destdir #$zig-destdir #:zig-test-destdir #$zig-test-destdir - #:tests? #$tests? + #:tests? #$(and tests? (not skip-build?)) #:search-paths '#$(sexp->gexp (map search-path-specification->sexp search-paths)))))) diff --git a/guix/build/zig-build-system.scm b/guix/build/zig-build-system.scm index 75ebdb7ca9..f6928ad253 100644 --- a/guix/build/zig-build-system.scm +++ b/guix/build/zig-build-system.scm @@ -24,38 +24,113 @@ #:use-module (ice-9 popen) #:use-module (ice-9 rdelim) #:use-module (ice-9 ftw) - #:use-module (ice-9 format) #:use-module (ice-9 match) - #:use-module (rnrs io ports) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:export (%standard-phases - zig-build)) + zig-build + zig-source-install-path)) ;; Interesting guide here: ;; https://github.com/riverwm/river/blob/master/PACKAGING.md +(define (zig-source-install-path output) + (string-append output "/src/zig/" (strip-store-file-name output))) + +(define (zig-input-install-path input) + (zig-source-install-path + (dirname (dirname (dirname (canonicalize-path input)))))) + +;; Notes on Zig package manager (`build.zig.zon') +;; 1. Dependency definition (name -> URL + hash) +;; - Dependency names are not necessarily consistent across packages. +;; - `zig fetch <url> --name=<name>' fetches <url> to Zig cache, computes its +;; hash, then overwrites dependency <name> with <url> and the computed hash. +;; 2. Dependency lookup +;; Lookup hash in Zig cache, fetch URL when missing. +;; 3. Recursive dependency is possible +;; `build.zig.zon' -> dependency (`build.zig.zon' -> next dependency). +;; +;; With our naming convention and different expectation on package sources, +;; we'll need to change dependency names and hashes for nearly every Zig +;; package. +;; - `rename-zig-dependencies' in `(gnu packages zig)' takes care of names. +;; - `unpack-dependencies' below is for hashes. Ideally we can parse +;; `build.zig.zon' and only `zig fetch' required dependencies for current +;; package, this way recursive dependencies are resolved by fetching store paths +;; defined in dependency URLs. However Zig package manager currently doesn't +;; support file URLs[0] so we are instead fetching all dependencies needed for +;; the build process and all of them are added to involved `build.zig.zon' as a +;; side effect. +;; [0]: https://github.com/ziglang/zig/pull/21931 +(define (unpack-dependencies . _) + "Unpack Zig dependencies from GUIX_ZIG_PACKAGE_PATH." + (define zig-inputs + (append-map + (lambda (directory) + (map (lambda (input-name) + (cons input-name + (in-vicinity directory input-name))) + (scandir directory (negate (cut member <> '("." "..")))))) + (or (and=> (getenv "GUIX_ZIG_PACKAGE_PATH") + (cut string-split <> #\:)) + '()))) + (define (strip-version input) + (let* ((name+version (string-split input #\-)) + (penult (first (take-right name+version 2))) + (ultima (last name+version))) + (string-join + (drop-right name+version + (cond + ;; aaa-0.0.0 + ((= 3 (length (string-split ultima #\.))) + 1) + ;; bbb-0.0.0-0.0000000-output + ((and (= 2 (length (string-split penult #\.))) + (not (string-contains ultima "."))) + 3) + ;; ccc-0.0.0-output + ;; ddd-0.0.0-0.0000000 + (else 2))) + "-"))) + (for-each + (lambda (build.zig.zon) + (format #t "unpacking dependencies for ~s...~%" build.zig.zon) + (with-directory-excursion (dirname build.zig.zon) + (false-if-exception + (for-each + (match-lambda + ((input-name . input-path) + (let ((call `("zig" "fetch" + ,(zig-input-install-path input-path) + ,(string-append "--save=" (strip-version input-name))))) + (format #t "running: ~s~%" call) + (apply invoke call)))) + (reverse zig-inputs))))) + (find-files "." "^build\\.zig\\.zon$"))) + (define* (build #:key zig-build-flags zig-build-target - zig-release-type ;; "safe", "fast" or "small" empty for a - ;; debug build" + ;; "safe", "fast" or "small", empty for a "debug" build. + zig-release-type + skip-build? #:allow-other-keys) "Build a given Zig package." - - (setenv "DESTDIR" "out") - (let ((call `("zig" "build" - "--prefix" "" ;; Don't add /usr - "--prefix-lib-dir" "lib" - "--prefix-exe-dir" "bin" - "--prefix-include-dir" "include" - ,(string-append "-Dtarget=" (zig-target zig-build-target)) - ,@(if zig-release-type - (list (string-append "-Drelease-" zig-release-type)) - '()) - ,@zig-build-flags))) - (format #t "running: ~s~%" call) - (apply invoke call))) + (when (not skip-build?) + (setenv "DESTDIR" "out") + (let ((call `("zig" "build" + "--prefix" "" ;; Don't add /usr + "--prefix-lib-dir" "lib" + "--prefix-exe-dir" "bin" + "--prefix-include-dir" "include" + ,(string-append "-Dtarget=" (zig-target zig-build-target)) + ,@(if zig-release-type + (list (string-append "-Drelease-" zig-release-type)) + '()) + ,@zig-build-flags))) + (format #t "running: ~s~%" call) + (apply invoke call)))) (define* (check #:key tests? zig-test-flags @@ -73,15 +148,22 @@ (setenv "DESTDIR" old-destdir) (unsetenv "DESTDIR"))))) -(define* (install #:key inputs outputs #:allow-other-keys) +(define* (install #:key outputs install-source? #:allow-other-keys) "Install a given Zig package." - (let ((out (assoc-ref outputs "out"))) - (copy-recursively "out" out))) + (let* ((out (assoc-ref outputs "out")) + (source-install-path (zig-source-install-path out))) + (when (file-exists? "out") + (copy-recursively "out" out) + (delete-file-recursively "out")) + (when install-source? + (mkdir-p source-install-path) + (copy-recursively "." source-install-path)))) (define %standard-phases (modify-phases gnu:%standard-phases (delete 'bootstrap) (replace 'configure zig-configure) + (add-after 'configure 'unpack-dependencies unpack-dependencies) (replace 'build build) (replace 'check check) (replace 'install install))) |