summaryrefslogtreecommitdiff
path: root/Biz/Bild.scm
diff options
context:
space:
mode:
Diffstat (limited to 'Biz/Bild.scm')
-rwxr-xr-xBiz/Bild.scm158
1 files changed, 158 insertions, 0 deletions
diff --git a/Biz/Bild.scm b/Biz/Bild.scm
new file mode 100755
index 0000000..4e1d490
--- /dev/null
+++ b/Biz/Bild.scm
@@ -0,0 +1,158 @@
+;;
+;; 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] <target..>
+;;
+;; 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 <target>
+;;
+;; 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 <target>
+;;
+;; 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 Biz.Bild.main
+;;
+;; The general template of which is:
+;;
+;; ghc <source> -i <deps..> -o <target> -main-is <target>.main
+;;
+;; Some definitions:
+;;
+;; - <source> is some source file
+;; - <deps..> is the stack of dependencies
+;; - <target> is the target namespace, indicated by 'bild <target>'
+;;
+;; 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 <source> file corresponding to <target>
+;; 3. Look for 'import <namespace>', where <namespace> is a namespace in the
+;; aforementioned cache.
+;; 4. If found, then save current build as a continuation and compile
+;; <namespace>. Result gets put on the dependency stack
+;; 5. When finished, return to building <target>
+;;
+;; 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. Starting with Haskell,
+;; have comments like `{-: PACKAGE base <5.0.0.0 :-}' or `-- : PACKAGE base <5.0.0.0'.
+;; Other languages could use `#:` for the special prefix, basically just
+;; a comment plus colon.
+;; - 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 (Biz Bild)
+ #:use-module ((ice-9 popen) #:prefix popen/)
+ #:use-module ((ice-9 format) #:select (format))
+ #:use-module ((ice-9 rdelim) #:prefix rdelim/)
+ #:use-module ((Alpha Core) #:select (fmt))
+ #:use-module ((Alpha Shell) #:prefix sh/)
+ #:use-module ((Alpha String) #:prefix string/)
+ #:export (ns?
+ ns->path
+ path->ns
+ main))
+
+(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")))))