From d622a15d0889c18bdfd32b569479001f53567177 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Wed, 18 Dec 2019 16:06:14 +0100 Subject: Move the "binary" build system from the Gaming Channels to Nonguix. * nonguix/build-system/binary.scm: New file. * nonguix/build/binary-build-system.scm: New file. * nonguix/build/utils.scm: New file. * nonguix/utils.scm: New file. --- nonguix/build/utils.scm | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 nonguix/build/utils.scm (limited to 'nonguix/build/utils.scm') diff --git a/nonguix/build/utils.scm b/nonguix/build/utils.scm new file mode 100644 index 0000000..b520769 --- /dev/null +++ b/nonguix/build/utils.scm @@ -0,0 +1,185 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2019 Pierre Neidhardt +;;; +;;; This file is not 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 . + +(define-module (nonguix build utils) + #:use-module (ice-9 match) + #:use-module (ice-9 binary-ports) + #:use-module (guix build utils) + #:export (64-bit? + make-desktop-entry-file + make-wrapper)) + +(define (64-bit? file) + "Return true if ELF file is in 64-bit format, false otherwise. +See https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header." + (with-input-from-file file + (lambda () + (= 2 + (array-ref (get-bytevector-n (current-input-port) 5) 4))) + #:binary #t)) + +(define* (make-desktop-entry-file destination #:key + (type "Application") ; One of "Application", "Link" or "Directory". + (version "1.1") + name + (generic-name name) + (no-display #f) + comment + icon + (hidden #f) + only-show-in + not-show-in + (d-bus-activatable #f) + try-exec + exec + path + (terminal #f) + actions + mime-type + (categories "Application") + implements + keywords + (startup-notify #t) + startup-w-m-class + #:rest all-args) + "Create a desktop entry file at DESTINATION. +You must specify NAME. + +Values can be booleans, numbers, strings or list of strings. + +Additionally, locales can be specified with an alist where the key is the +locale. The #f key specifies the default. Example: + + #:name '((#f \"I love Guix\") (\"fr\" \"J'aime Guix\")) + +produces + + Name=I love Guix + Name[fr]=J'aime Guix + +For a complete description of the format, see the specifications at +https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html." + (define (escape-semicolon s) + (string-join (string-split s #\;) "\\;")) + (define* (parse key value #:optional locale) + (set! value (match value + (#t "true") + (#f "false") + ((? number? n) n) + ((? string? s) (escape-semicolon s)) + ((? list? value) + (catch 'wrong-type-arg + (lambda () (string-join (map escape-semicolon value) ";")) + (lambda args (error "List arguments can only contain strings: ~a" args)))) + (_ (error "Value must be a boolean, number, string or list of strings")))) + (format #t "~a=~a~%" + (if locale + (format #f "~a[~a]" key locale) + key) + value)) + + (define key-error-message "This procedure only takes key arguments beside DESTINATION") + + (unless name + (error "Missing NAME key argument")) + (unless (member #:type all-args) + (set! all-args (append (list #:type type) all-args))) + (mkdir-p (dirname destination)) + + (with-output-to-file destination + (lambda () + (format #t "[Desktop Entry]~%") + (let loop ((args all-args)) + (match args + (() #t) + ((_) (error key-error-message)) + ((key value . ...) + (unless (keyword? key) + (error key-error-message)) + (set! key + (string-join (map string-titlecase + (string-split (symbol->string + (keyword->symbol key)) + #\-)) + "")) + (match value + (((_ . _) . _) + (for-each (lambda (locale-subvalue) + (parse key + (if (and (list? (cdr locale-subvalue)) + (= 1 (length (cdr locale-subvalue)))) + ;; Support both proper and improper lists for convenience. + (cadr locale-subvalue) + (cdr locale-subvalue)) + (car locale-subvalue))) + value)) + (_ + (parse key value))) + (loop (cddr args)))))))) + +(define* (make-wrapper wrapper real-file #:rest vars) + "Like `wrap-program' but create WRAPPER around REAL-FILE. +The wrapper automatically changes directory to that of REAL-FILE. + +Example: + + (make-wrapper \"bin/foo\" \"sub-dir/original-foo\" + '(\"PATH\" \":\" = (\"/gnu/.../bar/bin\")) + '(\"CERT_PATH\" suffix (\"/gnu/.../baz/certs\" + \"/qux/certs\"))) + +will create 'bin/foo' with the following +contents: + + #!location/of/bin/bash + export PATH=\"/gnu/.../bar/bin\" + export CERT_PATH=\"$CERT_PATH${CERT_PATH:+:}/gnu/.../baz/certs:/qux/certs\" + cd sub-dir + exec -a $0 sub-dir/original-foo \"$@\"." + (define (export-variable lst) + ;; Return a string that exports an environment variable. + (match lst + ((var sep '= rest) + (format #f "export ~a=\"~a\"" + var (string-join rest sep))) + ((var sep 'prefix rest) + (format #f "export ~a=\"~a${~a:+~a}$~a\"" + var (string-join rest sep) var sep var)) + ((var sep 'suffix rest) + (format #f "export ~a=\"$~a${~a+~a}~a\"" + var var var sep (string-join rest sep))) + ((var '= rest) + (format #f "export ~a=\"~a\"" + var (string-join rest ":"))) + ((var 'prefix rest) + (format #f "export ~a=\"~a${~a:+:}$~a\"" + var (string-join rest ":") var var)) + ((var 'suffix rest) + (format #f "export ~a=\"$~a${~a:+:}~a\"" + var var var (string-join rest ":"))))) + + (mkdir-p (dirname wrapper)) + (call-with-output-file wrapper + (lambda (port) + (format port + "#!~a~%~a~%cd \"~a\"~%exec -a \"$0\" \"~a\" \"$@\"~%" + (which "bash") + (string-join (map export-variable vars) "\n") + (dirname real-file) + (canonicalize-path real-file)))) + (chmod wrapper #o755)) -- cgit v1.2.3