\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}