#!/bin/sh #_( exec "$(dirname "$0")/bb" "$0" "$@" ) ;; Generate buck2 http_archive data from the DotSlash files beside this script. ;; ;; DotSlash is where a tool's version, URL and digest are written down. buck ;; needs the same three facts to fetch that tool itself — it cannot use the ;; shim, which resolves on the machine at run time and so is neither an action ;; input nor anything a remote worker could be given. Rather than write them ;; twice and let them drift, this reads the manifests and emits the table buck ;; reads. ;; ;; just sync-dist # after editing any scripts/*.dotslash ;; ;; The DotSlash format is JSON with a `//` shebang line on top: one entry per ;; platform, each with a url, a size, a digest and the path of the binary ;; inside the archive. Only the archive itself is wanted here; the path inside ;; it is the shim's business, and the toolchain rules name what they need. (require '[babashka.fs :as fs] '[cheshire.core :as json] '[clojure.string :as str]) (def here (fs/parent (fs/canonicalize *file*))) (def out-file (fs/path (fs/parent here) "toolchains" "dist" "generated.bzl")) ;; The tools buck fetches for itself. buck2 is not among them: it is the thing ;; doing the fetching. jolt is not either — it is fetched by DotSlash on the ;; machine that runs the boot image compile, which may not be this one. (def tools [;; DotSlash itself, so an action can fetch what it needs where it runs ;; rather than being handed it from here. See android/BUCK. "dotslash" ;; jolt-native's release, so the APK's UI half and the Jolt side of the ;; tree ABI are fetched rather than built out of a second checkout. "libvidya-android" "glimmer-vidya" "android-glue"]) (defn load-manifest [stem] (let [candidate (->> [(fs/path here (str stem ".dotslash")) (fs/path here stem)] (filter fs/exists?) first)] (when-not candidate (binding [*out* *err*] (println (str "no DotSlash manifest for " stem))) (System/exit 1)) (let [text (slurp (str candidate))] (json/parse-string (subs text (str/index-of text "{")))))) (defn platform-entry [entry] (let [;; The path of the binary inside the archive starts with the directory ;; the tarball unpacks into, which is what to strip. A flat archive — ;; one binary, no directory around it — has nothing to strip, and ;; naming the binary would strip the whole payload. [head rest] (str/split (get entry "path") #"/" 2)] (array-map "url" (get-in entry ["providers" 0 "url"]) "sha256" (get entry "digest") "strip_prefix" (if rest head "") "type" (get entry "format")))) (def dist (into (array-map) (for [stem (sort tools)] [stem (into (array-map) (for [[platform entry] (sort-by key (get (load-manifest stem) "platforms")) ;; http_archive takes sha256 and nothing else. :when (= "sha256" (get entry "hash"))] [platform (platform-entry entry)]))]))) ;; Four-space indentation, like the Starlark around it: this file is read by ;; people as often as by buck. (def pretty (json/create-pretty-printer (assoc json/default-pretty-print-options :indentation " " :object-field-value-separator ": "))) (fs/create-dirs (fs/parent out-file)) (spit (str out-file) (str/join "\n" ["# @generated by scripts/dotslash-to-buck — do not edit." "#" "# The same archives scripts/*.dotslash pins, as facts buck can act on." "# Bump the DotSlash file and run `just sync-dist`." "" (str "DIST = " (json/generate-string dist {:pretty pretty})) ""])) (println (str "wrote " (fs/relativize (fs/parent here) out-file)))