#build #build-tool #command-line #cc #rules #file #source-file

build ruler

A straight-forward, general-purpose build tool

7 releases

0.1.6 Mar 1, 2021
0.1.5 Jan 23, 2021
0.1.4 Oct 12, 2020
0.1.2 Sep 21, 2020
0.1.0 Jul 5, 2020

#329 in Build Utils

MIT license

305KB
8K SLoC

Ruler

Ruler is a tool for managing a dependence graph of files. It fits any situation where a commandline executable takes files as input (sources) and generates files as output (targets). A large-scale C/C++ project is a good example. C/C++ projects are usually subdivided into libraries and object files. With the right dependence graph, Ruler can help speed up incremental builds by only re-building when necessary. C/C++ is not the only use-case, however. Many problems can be solved by dependence management.

Dependencies are encoded in a .rules file. A .rules file contains newline-separated blocks called rules. Each rule consists of three sections: targets, sources and command. Targets and sources are newline-separated lists of file paths. Command is a command-line invocation that presumably takes the sources as input and updates the targets. Each section ends with a single ":" alone on a line. For example, a .rules might contain this single rule:

build/game
:
src/game.h
src/game.cpp
:
c++
src/game.cpp
--std=c++17
-o build/game
:

That rule declares that the executable build/game depends on three source files, and builds by this line:

c++ game.cpp --std=c++17 -o build/game

(Note: Ruler uses slightly unconventional syntax for the commandline so that one invocation can span multiple lines without the need for backslashes. To get a multi-line invocation, separate by a ";" alone on a line.)

With the above.rules file, if we type this:

ruler build

Ruler checks whether the target file build/game is up-to-date with its source files:

src/game.h
src/game.cpp

If it is not up-to-date, Ruler runs the command:

c++ game.cpp --std=c++17 -o build/game

In general, a .rules file can contain lots of rules, each separated from the next by a single empty line, like this:

build/game
:
src/include/math.h
src/include/physics.h
build/math.o
build/physics.o
src/game.cpp
:
c++
build/math.o
build/physics.o
src/game.cpp
--std=c++17
-o
build/game
:

build/math.o
:
src/include/math.h
src/math.cpp
:
c++
--std=c++17
-c
src/math.cpp
-o
build/math.o
:

build/physics.o
:
src/include/math.h
src/physics.cpp
:
c++
--std=c++17
-c
src/physics.cpp
-o
build/physics.o
:

With that .rules file, if we type...

ruler build

... Ruler will execute the commands to build the intermeidate targets: build/math.o and build/physics.o before finally building build/game. What's more, Ruler will only execute the command to build a target that is out-of-date, so if build/math.o and build/physics.o have already been built, Ruler will not bother building them again.

This line:

ruler clean

removes all files listed as targets in the .rules file. Actually, that is only partly true. Rather than delete the files, it relocates them to a cache. If a build is invoked and Ruler determines that some files already reside in the cache, Ruler recovers them, rather than rebuilding.

The cache also gets populated when intermediate build results are replaced. So, if you edit a source file, type ruler build, then undo the edit and ruler build again, Ruler appeals to the cache and recovers the target instead of rebuilding it.

Dependencies

~6.5MB
~108K SLoC