(zilch lang go): document

Change-Id: I6a6a6964558b4fe2f96d78120b2e899f91d48c22
This commit is contained in:
puck 2025-06-23 12:22:20 +00:00
parent f0ce185d5c
commit 18f2887eba
13 changed files with 457 additions and 96 deletions

View file

@ -1,3 +1,6 @@
;; Higher-level utilities to write Go compilation instructions inside of Zilch.
;; These act on a `<go-package>` record, which is generated by `go-package-compile`,
;; and the final program linked together by `go-package-link`.
(define-library (zilch lang go)
(import
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
@ -8,23 +11,24 @@
(chicken base) (chicken format) (chicken foreign)
(srfi-4)
(zilch lang go core))
(export
<go-package>
make-go-package go-package?
go-package-name go-package-import-path
go-package-api go-package-code go-package-dependencies
go-dependency-closure
go-package-compile go-package-link)
(begin
;; A go package consists of a few separate `++(zilch magic)++` store paths.
;; The `++name++` is the package name as compiled, and `++import-path++` is a nicer
;; package name for "main" packages. The `++go-package-api++` is a store path consisting
;; of a `++.a++` containing the output of the compiler's `++__.PKGDEF++` only, which
;; A go package consists of a few separate `(zilch magic)` store paths.
;; The `name` is the package name as compiled, and `import-path` is a nicer
;; package name for "main" packages. The `go-package-api` is a store path consisting
;; of a `.a` containing the output of the compiler's `__.PKGDEF` only, which
;; contains the exported types and functions, along with a slight amount of LTO and
;; inlining metadata. the `++go-package-code++` store path contains the actual assembly
;; inlining metadata. the `go-package-code` store path contains the actual assembly
;; of the package.
(define-record-type <go-package>
(make-go-package name import-path api code dependencies)
@ -34,7 +38,7 @@
(api go-package-api)
(code go-package-code)
(dependencies go-package-dependencies))
(define-record-printer (<go-package> pkg out)
(fprintf out "#<go-package ~A api: ~S code: ~S deps: ~S>"
(if (string=? (go-package-import-path pkg) (go-package-name pkg))
@ -43,8 +47,9 @@
(go-package-api pkg)
(go-package-code pkg)
(map go-package-name (go-package-dependencies pkg))))
;; Recursively walk over the dependencies of a `++go-package++`, prepending to the `++vals++` list.
;; Recursively walk over the dependencies of a `<go-package>`, prepending to the `vals` list,
;; and returning the resulting list.
(define (go-dependency-closure package vals)
(unless (member package vals)
(set! vals (cons package vals))
@ -54,9 +59,16 @@
(go-package-dependencies package)))
vals)
;; `(go-package-compile name deps source-files)`
;; or `(go-package-compile name path deps source-files assembly-files assembly-includes embed-filenames embed-patterns)`
;; Build a Zilch-defined Go package of one store path as source code, and a list of dependencies.
;;
;; - `name` is the full name of the package, or `main` if the package is the main package.
;; - `path` is the full name of the package (e.g. `example.com/foo/bar`).
;; - `deps` is a list of `<go-package>` dependencies.
;; - `source-files` is a (zexp) alist of file name to their location on disk (or store path).
;; - `assembly-files` is identical to `source-files`, but for `.s` files.
;; - `assembly-includes` is either a single on-disk path pointing to a directory, or an alist of file name to on-disk location for header files that should be in scope for `#include` in assembly files.
;; - `embed-patterns` is an alist of Go embed patterns to the filenames they contain;
;; - `embed-filenames` is an alist of filenames used in embed patterns to their on-disk location.
(define go-package-compile
(case-lambda
((name deps source-files) (go-package-compile name name deps source-files '() '() '() '()))
@ -69,9 +81,9 @@
(define symabis #f)
(unless assembly-files (set! assembly-files '()))
(define path-or-name (if (string=? name "main") name path))
(define assembly-includes-dir
(if (list? assembly-includes)
(zdir (map (lambda (pair) (cons (car pair) (zsymlink (cdr pair)))) assembly-includes))
@ -85,7 +97,7 @@
(define merged-asmhdr
(zdir "go_asm.h" (zsymlink (cdr (assoc "asmhdr" compiled-go)))))
;; ISSUE: this needs the source dir for assembly imports reasons (filter out .h files?)
(define compiled-assembly
(map
@ -99,26 +111,24 @@
; NOTE: .go has to be compiled in one go; but .s is compiled one file at a time.
(define all-code (cons (cdr (assoc "code" compiled-go)) compiled-assembly))
; (printf " -> (store-path-for-ca-drv* meow meow ~S ~S meow)\n" all-code (env-for-goarch))
; Use `go tool pack` to merge the code together.
(define merged-code
(if (length assembly-files)
(cdar (store-path-for-ca-drv*
(cdar (store-path-for-ca-drv
(string-append "go-" (rewrite-package-name path) "-code") "x86_64-linux"
#~(,(string-append #$go-toolchain "/bin/go") "tool" "pack" "c" ,(make-placeholder "code") . #$all-code)
(env-for-goarch)
'("code")))
(cdr (assoc "code" compiled-go))))
; (printf " -> (make-go-package ~S ~S ~S ~S ~S)\n" name path (cdr (assoc "api" compiled-go)) merged-code deps)
(make-go-package name path (cdr (assoc "api" compiled-go)) merged-code deps))))
;; Link a `++go-package++` into a binary that can be (statically) executed.
;; Link a `<go-package>` into a binary that can be executed.
(define (go-package-link pkg)
(define code-importcfg
(zfile #~,(build-importcfg #$(map (lambda (pkg) (cons (go-package-import-path pkg) (go-package-code pkg))) (go-dependency-closure pkg '())) '())))
(cdar (store-path-for-ca-drv* (rewrite-package-name (go-package-import-path pkg)) "x86_64-linux"
(cdar (store-path-for-ca-drv (rewrite-package-name (go-package-import-path pkg)) "x86_64-linux"
#~(,(string-append #$go-toolchain "/bin/go") "tool" "link" "-buildid" ,(string-append "zilch out=" (make-placeholder "out")) "-importcfg" #$code-importcfg "-o" ,(make-placeholder "out") #$(go-package-code pkg)) (env-for-goarch) '("out"))))))