▄▄· ▄▄▄▄▄      
   ▪     ▐█ ▌▪•██  ▪     
    ▄█▀▄ ██ ▄▄ ▐█.▪ ▄█▀▄ 
   ▐█▌.▐▌▐███▌ ▐█▌·▐█▌.▐▌
    ▀█▄▀▪·▀▀▀  ▀▀▀  ▀█▄▀▪
        build system
         Qix ~ 2014


Octo is a build system built on top of Node.JS that allows advanced configurations of files to be operated on in a modular fashion.

Where most automated build systems currently require listing files manually or using globbing that can easily become hairy, Octo makes use of .octo files placed throughout the project tree in order to define file classes, which are then described and operated upon in the Octo makefile (located at the project root).

The Octo task API (the commands that operate on classes) can be extended, wrapped, and hacked on prior to defining tasks to specifically tailor each task to its particular need.

Simple Project

Given the following file tree:


we can place .octo files in coffee/ and typescript/ in order to define globbing patterns that collect files as a particular type:





Every .octo file specifies at least one class and pattern. Classes are denoted with a colon at the end (i.e. coffee-files above) and patterns follow. Both classes and patterns can be indented with arbitrary whitespace. # at the beginning of a line denotes a comment. Patterns are relative to the location of the .octo file, and can exclude files by including a ! at the beginning of the pattern.

NOTE: An .octo file can apply to subdirectories if the pattern specifies; the above could be adjusted to **/*.coffee and **/*.ts to include subdirectories. For more information on globbing patterns, refer to the Minimatch or Glob libraries Octo utilizes.

and then define our compilation steps for these classes in our OctoMake file (located in the project root):


// Compile our coffeescript files
task.coffee = octo.task("coffee-files")
    .compile['coffee']()     ///< Compile the CoffeeScript to Javascript
    .out("bin", "js");       ///< Output the compiled files to 'bin/*.js'

// Compile our typescript files
task.typescript = octo.task("typescript-files")
    .compile['typescript']() ///< Compile the TypeScript to Javascript
    .out("bin", "js");       ///< Output the compiled files to 'bin/*.js'

A task is specified by assigning it to a task name (task.name = ...) and passing one or more classes (specified in .octo files), ultimately pushing in globbed files and running them through the task. For instance, the above task coffee pushes in files collected as coffee-files in the .octo file described above, compiles them, and then moves them to their final location with a new extension.

and finally run Octo from the command line (from our project root):

octo coffee typescript

By default, tasks are 'disabled' and don't pull in files unless specified so, either on the command line or by assigning them as an array to task.main. If the command line doesn't include any tasks, Octo looks specifically for task(s) specified in task.main and fails if none are found.

which generates the following file tree: