(zilch lang go): document
Change-Id: I6a6a6964558b4fe2f96d78120b2e899f91d48c22
This commit is contained in:
parent
f0ce185d5c
commit
18f2887eba
13 changed files with 457 additions and 96 deletions
|
|
@ -1,6 +1,6 @@
|
|||
;; Defines the baseline definitions needed to compile Go code using Zilch.
|
||||
;; Defines the functions needed to compile Go code using Zilch.
|
||||
;;
|
||||
;; To make incremental builds work, this library uses up to four distinct
|
||||
;; To make incremental builds possible, this library uses up to four distinct
|
||||
;; outputs:
|
||||
;;
|
||||
;; - `api` is any `.a` file needed for compiling any other Go code that depends
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
json
|
||||
(chicken foreign)
|
||||
(srfi 4))
|
||||
|
||||
|
||||
(export
|
||||
build-importcfg
|
||||
build-embedcfg
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
go-compile-assembly
|
||||
|
||||
go-toolchain)
|
||||
|
||||
|
||||
|
||||
(begin
|
||||
;; The architecture to target the Go code at.
|
||||
|
|
@ -42,14 +42,15 @@
|
|||
(define %goarch (make-parameter "amd64"))
|
||||
|
||||
;; The Go toolchain to use to compile this all.
|
||||
(define go-toolchain (cdr (assoc "out" (nixpkgs "go_1_23"))))
|
||||
|
||||
(define go-toolchain (cdr (assoc "out" (nixpkgs "go_latest"))))
|
||||
|
||||
;; Builds an importcfg file. This file describes the mapping of both
|
||||
;; packages to their api, and the mapping of package name as used in `import`
|
||||
;; to the actual package names (e.g in case of `replace`.)
|
||||
;;
|
||||
;; - `++packagefiles++` is a alist of package name to .a file.
|
||||
;; - `++importmap++` is an alist of package name to actual package name.
|
||||
;; - `++packagefiles++` is an alist mapping a package name to .a file.
|
||||
;; - `++importmap++` is an alist mapping a package name to actual package name.
|
||||
;; This is primarily used by Go's standard library to vendor external packages.
|
||||
(define (build-importcfg packagefiles importmap)
|
||||
(call-with-port (open-output-string)
|
||||
(lambda (outstr)
|
||||
|
|
@ -72,11 +73,12 @@
|
|||
importmap)
|
||||
(get-output-string outstr))))
|
||||
|
||||
;; Builds an embedcfg file, which maps from the pattern used in `go:embed`
|
||||
;; to a list of files, as well as a filename to on-disk file mapping.
|
||||
;; Builds an `embedcfg` file, which maps the pattern used in `//go:embed` directives
|
||||
;; to a list of files that need to be embedded, and a mapping of filename to on-disk
|
||||
;; file path.
|
||||
;;
|
||||
;; - `++patterns++` is an alist of the pattern used to match files (e.g. `++foo/++`, or `++a.*++`) to a list of filenames.
|
||||
;; - `++files++` is an alist of file name to actual path.
|
||||
;; - `patterns` is an alist of the pattern used to match files (e.g. `foo/`, or `a.*`) to a list of filenames.
|
||||
;; - `files` is an alist mapping the file name in `patterns` to an on-disk path.
|
||||
(define (build-embedcfg patterns files)
|
||||
(call-with-port (open-output-string)
|
||||
(lambda (outstr)
|
||||
|
|
@ -88,6 +90,7 @@
|
|||
(get-output-string outstr))))
|
||||
|
||||
;; Clean up the package name to use in drv names.
|
||||
;; Replaces special characters seen in package names to underscores.
|
||||
(define (rewrite-package-name name)
|
||||
(set! name (string-copy name))
|
||||
(do ((x 0 (+ x 1)))
|
||||
|
|
@ -99,23 +102,29 @@
|
|||
|
||||
;; An empty go_asm.h file used when generating symabis.
|
||||
(define empty-asmhdr (zdir `(("go_asm.h" . ,(zfile "")))))
|
||||
|
||||
;; The environment to append to the build environment for Go.
|
||||
|
||||
;; The environment to append to the build environment for any Go derivation.
|
||||
(define (env-for-goarch)
|
||||
`(("GOARCH" . ,(%goarch))))
|
||||
|
||||
;; Extra defines to add to `++go tool asm++` uses.
|
||||
|
||||
;; Extra arguments to add to uses of `++go tool asm++`, to set the expected preprocessor
|
||||
;; variables.
|
||||
(define (defines-for-goarch)
|
||||
`(
|
||||
"-D" "GOOS_linux"
|
||||
"-D" ,(string-append "GOARCH_" (%goarch))
|
||||
,@(if (string=? (%goarch) "amd64") '("-D" "GOAMD64_v1") '())))
|
||||
|
||||
;; Returns an alist of three store paths.
|
||||
;; Calls `go tool compile` with the provided arguments.
|
||||
;;
|
||||
;; - `std` must be `#t` when compiling the standard library, and `#f` otherwise.
|
||||
;; - `package-name` is the (zexp) string with the name of the package.
|
||||
;; - `importcfg` must be set, and is a zexp path to a file containing the import map.
|
||||
;; - `symabis` and `embeds` (optionally) point to a file containing their respective configuration.
|
||||
;; - `files` is an alist of all files to compile, mapping filename to on-disk path.
|
||||
;; The filenames are used in `-trimpath`, providing for better runtime traces and error messages.
|
||||
;;
|
||||
;; - `++api++` containing the compiler's output, used when compiling
|
||||
;; - `++code++` contains the compiled code, used during linking only.
|
||||
;; - `++asmhdr++` contains the headers needed for any assembly code inside this package.
|
||||
;; Returns an alist containing store paths for `api`, `code`, and `asmhdr` outputs.
|
||||
(define (go-compile std package-name importcfg symabis embeds files)
|
||||
(define args
|
||||
#~(
|
||||
|
|
@ -133,13 +142,14 @@
|
|||
"-trimpath" ,(apply string-append (map (lambda (f) (string-append (cdr f) "=>" package-name "/" (car f) ";")) #$files))
|
||||
. ,(map cdr #$files)))
|
||||
|
||||
(store-path-for-ca-drv*
|
||||
(store-path-for-ca-drv
|
||||
(string-append (rewrite-package-name package-name) "-src")
|
||||
"x86_64-linux"
|
||||
#~(,(string-append #$go-toolchain "/bin/go") "tool" "compile" . #$args)
|
||||
(env-for-goarch) '("api" "code" "asmhdr")))
|
||||
|
||||
;; Returns a store path containing the symabi for the assembly files provided.
|
||||
|
||||
;; Calls `go tool asm -gensymabis`, returning a store path containing the symabi for the assembly files provided.
|
||||
;; `include-path` can be set to add a single path to the include path.
|
||||
(define (go-generate-symabi package-name include-path files)
|
||||
(define args
|
||||
#~(
|
||||
|
|
@ -152,15 +162,17 @@
|
|||
,@(if include-path (list "-I" #$include-path) '())
|
||||
. #$files))
|
||||
|
||||
(cdar (store-path-for-ca-drv*
|
||||
(cdar (store-path-for-ca-drv
|
||||
(string-append (rewrite-package-name package-name) "-asm-symabis")
|
||||
"x86_64-linux"
|
||||
#~(,(string-append #$go-toolchain "/bin/go") "tool" "asm" . #$args)
|
||||
(env-for-goarch) '("symabi"))))
|
||||
|
||||
;; Returns a store path containing the `++code++` of the provided assembly
|
||||
;; files. Assembly files have no `api`, and cannot be directly interacted
|
||||
;; with from other packages.
|
||||
;; Returns a store path containing the `code` of the provided assembly
|
||||
;; files. Assembly files have no `api`, and are used inside the package they're defined in.
|
||||
;;
|
||||
;; - `include-path` and `include-path2` are both added to `-I` arguments if set.
|
||||
;; - `files`, as with `go-compile`, is an alist of file name to on-disk path.
|
||||
(define (go-compile-assembly package-name include-path include-path2 files)
|
||||
(define args
|
||||
#~(
|
||||
|
|
@ -173,7 +185,7 @@
|
|||
"-trimpath" ,(apply string-append (map (lambda (f) (string-append (cdr f) "=>" package-name "/" (car f) ";")) #$files))
|
||||
. ,(map cdr #$files)))
|
||||
|
||||
(cdar (store-path-for-ca-drv*
|
||||
(cdar (store-path-for-ca-drv
|
||||
(string-append (rewrite-package-name package-name) "-asm")
|
||||
"x86_64-linux"
|
||||
#~(,(string-append #$go-toolchain "/bin/go") "tool" "asm" . #$args)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
;; Helpers for fetching files from the Go module proxy, slightly impurely.
|
||||
;; Helpers for fetching files from the Go module and checksum proxy.
|
||||
(define-library (zilch lang go fetch)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme read) (scheme file) (scheme char)
|
||||
(zilch magic) (zilch zexpr)
|
||||
(zilch nixpkgs)
|
||||
(chicken process-context) (chicken format) (chicken file))
|
||||
|
||||
|
||||
(export
|
||||
fetch-with-known-url rewrite-module-name-for-url)
|
||||
|
||||
(begin
|
||||
(define fetch-cache-file (string-append (get-environment-variable "HOME") "/.cache/zilch-fetch.scm"))
|
||||
(define fetch-cache (if (file-exists? fetch-cache-file) (call-with-input-file fetch-cache-file read) '()))
|
||||
|
||||
;; Creates a store path that runs `builtin:fetchurl` with specified `name` and `url`.
|
||||
;; If the hash isn't known in the user-wide cache at `~/.cache/zilch-fetch.scm`, shells
|
||||
;; out to `nix-prefetch-url` to fetch the path and calculate its hash.
|
||||
(define (fetch-with-known-url name url)
|
||||
(define cache-entry (assoc url fetch-cache))
|
||||
(define hash (if cache-entry
|
||||
|
|
|
|||
|
|
@ -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"))))))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
;; Processes go module files.
|
||||
;; Resolves dependencies for Go modules and processes them into `<go-package>` files
|
||||
;; that can then be used to compile existing Go modules with Zilch.
|
||||
(define-library (zilch lang go mod)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme read) (scheme file) (scheme process-context) (scheme lazy) (scheme case-lambda)
|
||||
|
|
@ -13,7 +14,7 @@
|
|||
(zilch lang go) (zilch lang go core) (zilch lang go stdlib) (zilch lang go vfs) (zilch lang go sum) (zilch lang go fetch) (zilch lang go package)
|
||||
(zilch lang go version)
|
||||
(chicken foreign))
|
||||
|
||||
|
||||
(export
|
||||
collect-requirements-for-module collect-packages-from-requires)
|
||||
|
||||
|
|
@ -33,15 +34,16 @@
|
|||
(define (read-go-mod mod-file)
|
||||
(call-with-port
|
||||
;; TODO(puck): don't use /bin/sh here.
|
||||
(store-path-open (cdar (store-path-for-ca-drv* "go.mod.json" "x86_64-linux" #~("/bin/sh" "-c" ,(string-append #$go-toolchain "/bin/go mod edit -json " #$mod-file " > $out")) '() '("out"))))
|
||||
(store-path-open (cdar (store-path-for-ca-drv "go.mod.json" "x86_64-linux" #~("/bin/sh" "-c" ,(string-append #$go-toolchain "/bin/go mod edit -json " #$mod-file " > $out")) '() '("out"))))
|
||||
(lambda (p) (json-read p))))
|
||||
|
||||
|
||||
(define (vector-get-kv-value key vec)
|
||||
(vector-any (lambda (v) (and (string=? (car v) key) (cdr v))) vec))
|
||||
|
||||
;; Reads in the module rooted by the vfs, and resolves its requirements list.
|
||||
|
||||
;; Reads in the module rooted by the vfs in `vfs`, and finds all its requirements.
|
||||
;; This returns two values: the name of the root module, and a mapping of
|
||||
;; module name to a pair of its version and the vfs.
|
||||
;; `replaces` is a list of ``<vfs>``es containing modules that should be prioritized as dependencies.
|
||||
(define (collect-requirements-for-module vfs replaces)
|
||||
(define sum-lines '())
|
||||
(define (parse-sumfile go-sum)
|
||||
|
|
@ -97,7 +99,7 @@
|
|||
(define path-name (handle-vfs vfs))
|
||||
(set! collected-requires (mapping-set! collected-requires path-name (cons #f vfs))))
|
||||
replaces)
|
||||
|
||||
|
||||
; we have the right module versions and their files now. Iterate over the packages we have,
|
||||
; until we have none left that need iterating. Once that's done, iterate all the packages and fetch the go.sum for them.
|
||||
(define (tick)
|
||||
|
|
@ -132,14 +134,14 @@
|
|||
(call-with-port (store-path-open file) (lambda (port) (read-line port) (parse-sumfile (vector (parse-go-sum-line (read-line port)) (parse-go-sum-line (read-line port))))))))
|
||||
found-missing)
|
||||
(tick))))
|
||||
|
||||
|
||||
(set! root-path-name (handle-vfs vfs))
|
||||
(set! collected-requires (mapping-set! collected-requires root-path-name (cons #f vfs)))
|
||||
(tick)
|
||||
(values root-path-name collected-requires))
|
||||
|
||||
|
||||
;; Processes a mapping of module name to a pair of version and vfs, and
|
||||
;; returns a procedure that takes a package name and returns its go-package.
|
||||
;; returns a procedure that takes a package name and returns a `<go-package>` representing it.
|
||||
(define (collect-packages-from-requires collected-requires)
|
||||
(define (process-package vfs last-part full-path pairs headers)
|
||||
(define name (cdr (assoc "name" pairs)))
|
||||
|
|
@ -172,7 +174,7 @@
|
|||
(collected-imports (map (lambda (name) (if (is-builtin name) (go-stdlib-ref name) (find-package name)))
|
||||
(filter (lambda (name) (not (member name '("builtin" "unsafe")))) imports))))
|
||||
(go-package-compile name full-path collected-imports collected-files collected-assembly-files collected-assembly-includes embed-filenames embed-patterns)))
|
||||
|
||||
|
||||
(define packages (mapping (make-default-comparator)))
|
||||
|
||||
(define (process-packages-for-module root-path vfs)
|
||||
|
|
@ -200,7 +202,7 @@
|
|||
(define pairs (vector->list (cdr pair)))
|
||||
(set! packages (mapping-set! packages full-path (delay (process-package vfs (car pair) full-path pairs headers)))))
|
||||
module-packages))
|
||||
|
||||
|
||||
(define (find-longest-prefix name)
|
||||
(define prefixes (mapping-entries (mapping-filter (lambda (key value) (string-prefix? key name)) collected-requires)))
|
||||
(unless (eq? prefixes '())
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
;; Routines to locate Go packages in a `<vfs>`.
|
||||
(define-library (zilch lang go package)
|
||||
(import
|
||||
(scheme base)
|
||||
|
|
@ -18,9 +19,9 @@
|
|||
(map go-stdlib-ref '("encoding/json" "fmt" "go/build" "io" "io/fs" "os" "path" "path/filepath" "sort" "strings" "time"))
|
||||
(list (cons "main.go" (zfile (foreign-value "parser_source" nonnull-c-string)))))))
|
||||
|
||||
;; Uses IFD to find each Go package defined inside this virtual filesystem,
|
||||
;; returning a vector containing pairs, mapping each directory to the
|
||||
;; package defined within.
|
||||
;; Finds each Go package defined inside this virtual filesystem,
|
||||
;; and returns a vector containing pairs, mapping the name of each directory to the
|
||||
;; a vector-based structure describing the package defined in said directory.
|
||||
(define (find-packages-inside-vfs vfs)
|
||||
(define input
|
||||
#~,(call-with-port
|
||||
|
|
@ -29,6 +30,6 @@
|
|||
(json-write (vector (cons "GOARCH" (%goarch)) (cons "GOOS" "linux") (cons "files" #$(vfs-to-json (vfs-filter-for-go-package vfs)))) bv)
|
||||
(get-output-bytevector bv))))
|
||||
(define input-file (zfile input))
|
||||
(define store-path (cdar (store-path-for-ca-drv* "find-packages" "x86_64-linux" #~(#$go-import-parser #$input-file) '() '("out"))))
|
||||
(define store-path (cdar (store-path-for-ca-drv "find-packages" "x86_64-linux" #~(#$go-import-parser #$input-file) '() '("out"))))
|
||||
(call-with-port (store-path-open store-path)
|
||||
(lambda (p) (json-read p))))))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
;; Handles the Go standard library.
|
||||
(define-library (zilch lang go stdlib)
|
||||
(import
|
||||
(scheme base) (scheme file) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -9,7 +10,7 @@
|
|||
(srfi-4)
|
||||
(zilch lang go core)
|
||||
(zilch lang go))
|
||||
|
||||
|
||||
(export
|
||||
go-stdlib-ref)
|
||||
|
||||
|
|
@ -20,12 +21,12 @@
|
|||
out
|
||||
(read-all-objects port (cons (json-read port) out))))
|
||||
|
||||
;; Runs `++go list++` (thru `++/bin/sh++`) and reads (IFD) the output to fetch the metadata of the Go standard library and commands.
|
||||
;; Runs `go list` (thru `/bin/sh`) and reads the output to fetch the metadata of the Go standard library and commands.
|
||||
(define stdlib-objects
|
||||
(map vector->list
|
||||
(call-with-port
|
||||
(store-path-open
|
||||
(cdar (store-path-for-ca-drv*
|
||||
(cdar (store-path-for-ca-drv
|
||||
"stdenv"
|
||||
"x86_64-linux"
|
||||
#~("/bin/sh" "-c" ,(string-append "GOCACHE=$TMPDIR/go-cache " #$go-toolchain "/bin/go list -json -deps std cmd > $out"))
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
(if res (cdr res) '()))
|
||||
|
||||
;; Extract everything until the first space.
|
||||
;; Space characters are illegal in Go package names, and `++go list -json std++`
|
||||
;; Space characters are illegal in Go package names, and `go list -json std`
|
||||
;; uses it to disambiguate multiple versions of some internal packages.
|
||||
(define (strip-space-bits name)
|
||||
(do
|
||||
|
|
@ -48,9 +49,9 @@
|
|||
(if (>= x (string-length name))
|
||||
name
|
||||
(substring name 0 x)))))
|
||||
|
||||
|
||||
;; Tail-recursively remove any packages that, if ignoring the postfixed origin
|
||||
;; (e.g. `++unsafe [cmd/compile]++`), match either `++unsafe++` or `++builtin++`;
|
||||
;; (e.g. `unsafe [cmd/compile]`), match either `unsafe` or `builtin`;
|
||||
;; these have no source code and are compiler-internal.
|
||||
(define (remove-builtin-packages pkgs)
|
||||
(if (eq? pkgs '())
|
||||
|
|
@ -59,21 +60,23 @@
|
|||
(if (or (string=? stripped "unsafe") (string=? stripped "builtin"))
|
||||
(remove-builtin-packages (cdr pkgs))
|
||||
(cons (car pkgs) (remove-builtin-packages (cdr pkgs)))))))
|
||||
|
||||
|
||||
(define (starts-with left right)
|
||||
(and
|
||||
(>= (string-length right) (string-length left))
|
||||
(string=? left (string-copy right 0 (string-length left)))))
|
||||
|
||||
|
||||
(define (filter condition lst)
|
||||
(if (eq? lst '())
|
||||
'()
|
||||
(if (condition (car lst))
|
||||
(cons (car lst) (filter condition (cdr lst)))
|
||||
(filter condition (cdr lst)))))
|
||||
|
||||
;; Helper that parses the JSON returned by `++go list -json -deps++` and builds a `++go-package++` record.
|
||||
;; This is distinct from `go-package-compile` because of format differences,
|
||||
|
||||
;; Helper that parses the JSON returned by `go list -json -deps` and builds a `go-package` record.
|
||||
;; This is distinct from `go-package-compile` because of format differences.
|
||||
;;
|
||||
;; TODO(puck): Is this still the case?
|
||||
(define (make-stdlib-inner meta)
|
||||
(define files (assoc-or-empty "GoFiles" meta)) ; .go files
|
||||
(define sfiles (assoc-or-empty "SFiles" meta)) ; .s files
|
||||
|
|
@ -89,7 +92,7 @@
|
|||
(when (string=? package-name "main")
|
||||
(set! name package-name))
|
||||
(define dir (cdr (assoc "Dir" meta)))
|
||||
|
||||
|
||||
; Fetch dependencies from the rest of the stdlib data.
|
||||
; We only need the `++api++` at this point.
|
||||
(define resolved-imports (map (lambda (v) (cons (strip-space-bits v) (go-package-api (go-stdlib-ref v)))) (remove-builtin-packages imports)))
|
||||
|
|
@ -140,7 +143,7 @@
|
|||
; Use `go tool pack` to merge the code together.
|
||||
(define merged-code
|
||||
(cdar
|
||||
(store-path-for-ca-drv*
|
||||
(store-path-for-ca-drv
|
||||
(string-append "go-" (rewrite-package-name name) "-code") "x86_64-linux"
|
||||
#~(,(string-append #$go-toolchain "/bin/go") "tool" "pack" "c" ,(make-placeholder "code") . #$all-code)
|
||||
(env-for-goarch)
|
||||
|
|
@ -148,11 +151,11 @@
|
|||
|
||||
(make-go-package name import-path go-api merged-code (map go-stdlib-ref (remove-builtin-packages imports))))
|
||||
|
||||
; Each entry is a list (name metadata (api code)).
|
||||
; Use `++delay++` to resolve the DAG lazily on use.
|
||||
; Each entry is a list of (name metadata (api code)).
|
||||
; Use `delay` to resolve the DAG lazily on use.
|
||||
(define stdlib-data (map (lambda (v) (list (cdr (assoc "ImportPath" v)) v (delay (make-stdlib-inner v)))) stdlib-objects))
|
||||
|
||||
;; Finds any package contained within Go's standard library.
|
||||
|
||||
;; Finds any package contained within Go's standard library, and returns a `<go-package>` for the package.
|
||||
(define (go-stdlib-ref name)
|
||||
(define entry (assoc name stdlib-data))
|
||||
(unless entry (error (string-append "Could not find package " name " in stdlib")))
|
||||
|
|
|
|||
|
|
@ -10,12 +10,16 @@
|
|||
(scheme char)
|
||||
(srfi 4) (srfi 128) (srfi 146) (srfi 207)
|
||||
(chicken foreign))
|
||||
|
||||
|
||||
(export
|
||||
parse-go-sum-line parse-go-sum-file go-sum-line? go-sum-module go-sum-version go-sum-path go-sum-hash)
|
||||
<go-sum-line> go-sum-line?
|
||||
go-sum-module go-sum-version go-sum-path go-sum-hash
|
||||
|
||||
parse-go-sum-line parse-go-sum-file)
|
||||
|
||||
(begin
|
||||
;; Contains the values from a single line from a `go.sum` file.
|
||||
;; `go-sum-hash` is a bytevector containing the base64-decoded hash.
|
||||
(define-record-type <go-sum-line>
|
||||
(make-go-sum-line module version path hash)
|
||||
go-sum-line?
|
||||
|
|
@ -30,7 +34,7 @@
|
|||
(go-sum-version sum)
|
||||
(if (go-sum-path sum) (go-sum-path sum) "")
|
||||
(bytevector->base64 (go-sum-hash sum))))
|
||||
|
||||
|
||||
(define (string-find str index char)
|
||||
(cond
|
||||
((= index (string-length str)) #f)
|
||||
|
|
@ -55,7 +59,7 @@
|
|||
(set! version (string-copy version 0 path-index)))
|
||||
(make-go-sum-line module-path version path (base64->bytevector (string-copy hash 3))))
|
||||
|
||||
;; Parses all the `go.sum` lines from `port`.
|
||||
;; Returns a list of all ``<go-sum-line>``s read from `port`.
|
||||
(define (parse-go-sum-file port)
|
||||
(do ((parsed '())
|
||||
(line "" (read-line port)))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
;; Procedures to deal with Go's semantic versions.
|
||||
;; Procedures to deal with Go's format of semantic versions.
|
||||
(define-library (zilch lang go version)
|
||||
(import
|
||||
(scheme base) (srfi 152))
|
||||
|
|
|
|||
|
|
@ -44,9 +44,8 @@
|
|||
(if (char-upper-case? ch) (set! out (string-append out (string #\! (char-downcase ch)))) (set! out (string-append out (string ch))))) name)
|
||||
out)
|
||||
|
||||
;; Reads a dirhash from a `go.sum` line. This prefetches the module from
|
||||
;; the go module proxy, and then generates the dirhash without unpacking
|
||||
;; said module file.
|
||||
;; Uses the hash in a `<go-sum-line>` to return a store path containing a list of the hashes of each file,
|
||||
;; following the https://pkg.go.dev/golang.org/x/mod/sumdb/dirhash[`dirhash`] format used by the `go.sum` files.
|
||||
(define (fetch-dirhash-for-sum sum-line)
|
||||
(when (go-sum-path sum-line) (error "go.sum line is invalid for fetch-dirhash-for-sum" sum-line))
|
||||
(define url (string-append "https://proxy.golang.org/" (rewrite-go-package-name-for-url (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
|
||||
|
|
@ -54,7 +53,8 @@
|
|||
(store-path-for-fod "module" "x86_64-linux" #~(#$(force dirhash-generator)) #~(("src" . #$known)) "sha256" (go-sum-hash sum-line) #f))
|
||||
|
||||
;; Generates a full VFS structure from a module as described by a `go.sum`
|
||||
;; line.
|
||||
;; line. Uses `fetch-dirhash-for-sum` to generate the dirhash, then creates FODs
|
||||
;; for each file based on said hash; this is then returned as a `<vfs>` structure.
|
||||
(define (vfs-from-dirhash sum-line)
|
||||
(define dirhash-file (fetch-dirhash-for-sum sum-line))
|
||||
(define url (string-append "https://proxy.golang.org/" (rewrite-go-package-name-for-url (go-sum-module sum-line)) "/@v/" (go-sum-version sum-line) ".zip"))
|
||||
|
|
@ -106,14 +106,17 @@
|
|||
((= i 0) #f)
|
||||
(else (extract-extension name (- i 1)))))
|
||||
|
||||
;; Returns a VFS, filtered down to only contain the contents of files that
|
||||
;; will be read during the processing of Go packages.
|
||||
;; Returns a subset of `vfs`, filtered down to only contain the contents of files that
|
||||
;; Go cares about.
|
||||
(define (vfs-filter-for-go-package vfs)
|
||||
(vfs-dir-filter vfs
|
||||
(lambda (dir fname contents)
|
||||
(define extension (extract-extension fname (- (string-length fname) 1)))
|
||||
(member extension good-extensions))))
|
||||
|
||||
;; Generates a representation of the `vfs`, processed to be turned into JSON.
|
||||
;; Primarily used by `(zilch lang go package)` to allow extracting the necessary
|
||||
;; information of each package from a module's vfs.
|
||||
(define (vfs-to-json vfs)
|
||||
(mapping-map->list
|
||||
(lambda (k v) (list (car k) (cdr k) (if (eq? v 'directory) "" v)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue