;; ;; bild - a simple build tool ;; ;;; Notice: ;; ;; This is under active development. For now this is just a convenience wrapper ;; around `nix build`. The below commentary describes how this tool *should* ;; work. ;; ;;; Commentary: ;; ;; Design constraints ;; ;; - only input is a namespace, no subcommands, no packages ;; - no need to write specific build rules ;; - one rule for hs, one for rs, one for scm, and so on ;; - no need to distinguish between exe and lib, just have a single output ;; - never concerned with deployment/packaging - leave that to another tool (scp? tar?)) ;; ;; Features ;; ;; - namespace maps to filesystem ;; - no need for `bild -l` for listing available targets. Use `ls` or `tree` ;; - you build namespaces, not files/modules/packages/etc ;; - namespace maps to language modules ;; - build settings can be set in the file comments ;; - pwd is always considered the the source directory, no `src` vs `doc` etc. ;; - build methods automaticatly detected with file extensions ;; - flags modify the way to interact with the build ;; - -s = jump into a shell and/or repl ;; - -p = turn on profiling ;; - -t = limit build by type ;; - -e = exclude some regex in the ns tree ;; - -o = optimize level ;; ;; Example Commands ;; ;; bild [-rpt] ;; ;; The general scheme is to build the things described by the targets. A target ;; is a namespace. You can list as many as you want, but you must list at least ;; one. It could just be `.` for the current directory. Build outputs will go ;; into the _bild directory in the root of the project. ;; ;; bild biz.web ;; ;; Or `bild biz/web`. This shows building a file at ./biz/web.hs, this will ;; translate to something like `ghc --make Biz.Web`. ;; ;; bild -r ;; ;; Starts a repl/shell for target. ;; - if target.hs, load ghci ;; - if target.scm, load scheme repl ;; - if target.clj, load a clojure repl ;; - if target.nix, load nix-shell ;; - and so on. ;; ;; bild -p ;; ;; build target with profiling (if available) ;; ;; bild -t nix target ;; ;; only build target.nix, not target.hs and so on (in the case of multiple ;; targets with the same name but different extension). ;; ;; Here is an example integration with GHC. Given the following command-line ;; invocation to compile the namespace 'com.simatime.bild' which depends on ;; 'com.simatime.lib': ;; ;; ghc com/simatime/bild.hs -i com/simatime/lib.hs -o _bild/bild -v \ ;; -main-is Com.Simatime.Bild.main ;; ;; The general template of which is: ;; ;; ghc -i -o -main-is .main ;; ;; Some definitions: ;; ;; - is some source file ;; - is the stack of dependencies ;; - is the target namespace, indicated by 'bild ' ;; ;; To fill out the build template, we can parse the file for known ;; namespaces. The general recipe is: ;; ;; 1. Create a list of namespaces in my git repo. This can be cached, or I can ;; integrate with git somehow. ;; 2. Read the file corresponding to ;; 3. Look for 'import ', where is a namespace in the ;; aforementioned cache. ;; 4. If found, then save current build as a continuation and compile ;; . Result gets put on the dependency stack ;; 5. When finished, return to building ;; ;; Once the build command template is filled out, we can create the nix expression. ;; ;; Questions ;; ;; - how to import (third-party) dependencies? ;; 1 just don't have them...? yeah right ;; 2 the target.nix could be the build description for target.hs ;; 3 just use a default.nix for the com.whatever ;; 4 have a deps.nix file ;; 5 list them in the file with other settings ;; - how to handle multiple output formats? ;; - e.g. that ghcjs and ghc take the same input files... ;; - say you have a .md file, you want to bild it to pdf, html, and more. What do? ;; - i guess the nix file could return a set of drvs instead of a single drv ;; ;; TODO ;; - stream output from 'nix build' subprocess ;; - get rid of guile notes during execution ;; - ns<->path macro ;; - support list (scheme namespace) in ns<->path fns ;; ;;; Code: (define-module (com simatime bild) #:use-module ((ice-9 popen) #:prefix popen/) #:use-module ((ice-9 format) #:select (format)) #:use-module ((ice-9 rdelim) #:prefix rdelim/) #:use-module ((com simatime shell) #:prefix sh/) #:use-module ((com simatime string) #:prefix string/) #:export (ns? ns->path path->ns main)) (define-syntax fmt (syntax-rules () ((fmt s args ...) (format #f s args ...)))) (define (main args) (let* ((root (sh/exec "git rev-parse --show-toplevel")) (target (cadr args)) (path (ns->path target))) (display (fmt ":: bild ~a...\r" target)) (sh/exec (fmt "nix build -f ~a/default.nix ~a" root target)) (display (fmt ":: bilt ~a" target)))) (define ns? symbol?) (define (ns->path ns) (let ((to-path (lambda (s) (string/replace s #\. #\/)))) (cond ((symbol? ns) (to-path (symbol->string ns))) ((string? ns) (to-path ns)) (else (error "ns should be a string or symbol"))))) (define (path->ns path) (let ((to-ns (lambda (s) (string/replace s #\/ #\.)))) (cond ((symbol? path) (to-ns (symbol->string path))) ((string? path) (to-ns path)) (else (error "path should be a string or symbol")))))