aboutsummaryrefslogtreecommitdiff
path: root/docs/build-manual.tex
blob: ca2f004e4d236eb14d9292f70ea0d42073e7dbae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
\documentclass[letterpaper]{book}
\usepackage{listings}
\begin{document}

\title{Xagasoft Build Manual}
\author{Mike Buland}
\date{November 2012}
\maketitle

\tableofcontents

\chapter{Introduction}
Build is a self-contained, sophisticated tool for performing multi-step
processes. The primary goal is to be able to replace the standard
configure/make or cmake/make systems that have become quite popular.

By default Build will work much as one would expect for compiling software, it
uses file existence and timestamps to determine what to build, and every file
has a list of dependent files and input files.

However, this is only the default configuration, you can use anything as the
condition for determining what to build or rebuild, and targets do not have to
be files.

Build boasts a sophisticated system for chaining rules together to take files
through as many steps as necessary to get them in the desirable format for input
to the final step.  This may sound a little vague and confusing, but what it
means in the end is that you can list, say, a bison file as on input to an
executable target that requires object (.o) files.  In this case build will
automatically figure out that it can get a .c file from the .y input file, and
a .o file from the .c file.  It will auto generate these targets for you and
save a lot of time and effort on your part.

\chapter{Structure of a Build File}
Build files contain build script along with four major types of declarations.
These are the major types that can be declared:

\begin{description}
    \item[Targets] \hfill \\
    Explicit targets can be defined that represent units of work with a definite
    goal and possibly inputs that can be other targets.
    \item[Actions] \hfill \\
    Actions are triggered from the command line and determine what targets to
    build and how.
    \item[Rules] \hfill \\
    Rules determine both how to build explicit targets to make life easier as
    well as how to auto-generate implicit targets.  An explicitly defined target
    does not need to use a rule, but it can make everything easier.
    \item[Functions] \hfill \\
    Functions can be defined like in most programming languages, and called
    anywhere in the script.  Functions can also be used in several key places in
    targets to extend the functionality of build.
\end{description}

Build script also allows you to declare and use variables like many other
scripting languages, which can be integers, floats, booleans, strings, lists,
the special value null, and file handles.

\section{A Quick Example}
Let's start with a very basic example.  This example is capable of building an
executable from any number of cpp source files:

\begin{lstlisting}
target "myprogram"
{
    rule "exe";
    input files("src/*.cpp");
}
\end{lstlisting}

This example doesn't set any special compilation or linking flags, but it is a
complete and valid build file.  It will find all cpp files in src, generate an
implicit target for each file to compile it into an object (.o) file, and then
use those files as the input to the myprogram target in the end.

\section{Targets}
A target represents a unit of work.  This is usually a file in a compilation
process, e.g. an object file, an executable, a library, et cetera.  Targets
come in two major flavors: explicit and implicit.  Explicit targets are any
targets that you define in a build script with the "target" keyword.  Targets
can also be auto-generated by rules when needed, these are known as implicit
targets.

If a target is declared more than once the two targets are merged.  You can
think of this as a newer target overriding \emph{parts} of an older target.  It
does not replace the previous target.

Targets can be declared inside of any linguistic construct, including if blocks
and loops, this gives you a lot of flexibility, but in addition, you can
specify a list of strings instead of a single string for the name of a target,
this creates a target with the same specs for each name in the list.

Targets can contain the following special keywords:

\begin{description}
    \item[input] \hfill \\
    You can specify any expression that results in a string or list of strings.
    These strings will be added to the list of inputs to this target, and if
    they are targets they will be added as dependencies.  If you have a rule
    specified then the list of inputs will be used to generate implicit targets
    to satisfy dependencies.
    \item[requires] \hfill \\
    Requires works just like input, except that the items here will not be added
    to the list of inputs.  They will be added as dependencies to figure out
    when this target needs to be rebuilt, but will not be listed as inputs.
    This is handy for things like libraries, data files, et cetera.
    \item[rule] \hfill \\
    You can optionally specify a single rule name by string.  This rule will be
    applied to this target before processing and used to provide the display,
    profiles, and potentially additionally inputs and requirements.  Rules can
    also add additional tags.
    \item[tag] \hfill \\
    You can specify any number of tags.  These can be used to group targets
    together to find them easily for use in actions and other places.  You can
    use the handy targets() function to find all targets that match a given tag.
    \item[display] \hfill \\
    You can optionally specify a string that will be displayed while this
    action is being processed.  If this action has a rule set or was implicitly
    generated then the display name is set from the rule name.  If a target is
    explicit and does not have a rule then the default is an empty string.
    \item[profile] \hfill \\
    Profiles are in actuality scripts that handle the real work of processing
    a target.  Each target can have multiple profiles, and they can have any
    name but the names "build" and "clean" have special meaning and life is
    much easier if you use them.  You can specify any number of profiles with
    any name, another common name is  "install".
\end{description}

\subsection{Explicit Target Example With Rule}
\begin{lstlisting}
target "program"
{
    input ["input1.cpp", "input2.cpp", "input3.cpp"];
    rule "exe";
    tag "programs";
    display "awesome exe";
    requires "library.a";
}
\end{lstlisting}
This example shows every option listed above except for profile.

\subsection{Profiles}
Each profile is basically just a script that is run when the target is
processed.  Unlike other build systems this is not a shell script, but build
script.  You can use any variables, functions, or constructs that you can use
anywhere else.  Very often these will use the execute() function to run
commands.

There is an extra property that can be set in any profile, and that's condition.
Specifying a condition will allow you to change how build decides when it's
appropriate to process that target in that profile.  There are four built-in
conditions: always, never, fileTime, and fileExists.  In the future it may also
be possible to use a user-defined function as a condition.


\subsection{Explicit Target Example Without Rule}
\begin{lstlisting}
target "datafile.zip"
{
    input files("data/*");
    tag "datafile";
    display "zip";
    profile "build"
    {
        condition filetime;
        execute("zip -u ${OUTPUT} ${INPUT}");
    }
    profile "clean"
    {
        condition fileexists;
        unlink( OUTPUT );
    }
}
\end{lstlisting}

This example shows you how to build and clean a target that is a zipfile from
it's component pieces.

\section{Actions}
Actions are the primary interface to build scripts from the command line, when
calling build you specify an action to run.  If no action is specified on the
command line the action "default" is run.  If the build script doesn't specify
a default action, one is generated for it that will attempt to build all
explicit targets.

Actions can contain almost any build script, plus an extra syntax that allows
you to process a list of targets in a given profile (see the targets section
for details). Basically this means that you have a lot of flexibility
controlling how your targets are processed.

Let's start with an example:

\begin{lstlisting}
action "default"
{
    build: "myprogram";
}
\end{lstlisting}

This is as basic as it gets, this example will cause build to process the
target "myprogram" using the profile "build".



\end{document}