custom build
what are build commands?
flower allows you to write custom build commands that are integrated into the flower build process. for example, this gets you live-reload for the commands, automatic rebuild detection if part of your site depends on the command, and progress messages that are integrated with a normal build.
NOTE: build tasks are not general purpose task runners. ninja silences all output from tasks unless they fail, and builds all tasks by default.
background
Flower is a build system masquerading as a static site generator. The build process is encoded in the build.ninja file generated by flower configure, and flower watch is a fancy wrapper around running ninja in a loop. "Flower core" (the flower binary itself) is extremely simple: basically just a clojure interpreter, file watcher, and http server.
Almost all of flower is defined in expressions/default-build.clj. You can think of build.clj as introducing new concepts. Custom commands are a way to introduce new concepts to your site.
adding a custom command
jyn.dev is built using flower, and developed in tandem. It has a custom command to rebuild flower on changes that looks like so (simplified):
(require '[expressions.default-build :as builder])
(def plan
{:phony [{:name "flower" :depends "target/flower"}]
:rules
[{:name "flower-meta"
:command "cd .. && clojure -T:build native"
:description "rebuild flower itself"}]
:builds
[{:rule "flower-meta"
:outputs "target/flower"
:inputs (fs/glob "../flower" "**")}]})
(def default-plan (builder/default-build-plan))
(ninja/generate! (merge-deep default-plan plan))
The basic idea is that you get a "default build plan" shipped with flower, which is what is used if you don't add a custom build.clj. It is a normal clojure map, which you can modify as you like. ninja/generate! serializes it to a build.ninja file.
For the most part, this is a 1-1 mapping between ninja and a clojure map. Further docs are a WIP. See expressions/default-build.clj for examples and expressions/ninja.clj for the implementation.
constraints
note that we had to explicitly name all the inputs and outputs of the custom command. this is an intentional restriction:
- knowing all inputs allows flower to know when your files need to be rebuilt.
- knowing all outputs allows flower to pass a list of your files to your index pages.
TODO: document how to set up an existing site
you may not care about including your existing site in your index pages; for example if your index pages are generated by your existing site. in that case, you can opt-out by simply running your-build-command && flower build, i.e. move the work outside of flower. live-reload will still work (even for files not created by flower!), and flower will never delete any path it did not create itself. however, flower cannot know when a previous build command conflicts with its own output files, so you'll have to verify that yourself.