Build Rule
A build rule is a procedure for producing output files from a set of input files in the context of a specified build configuration. Build rules are specified in build files—typically named BUCK.
Note: A build rule must explicitly specify, in its arguments, all of its required inputs in order for Buck to be able to build the rule's output in a way that is deterministic and reproducible.
Buck's collection of build rules
Buck comes with a collection of built-in build rules for many common build procedures. For example, compiling Java code against the Android SDK is a common procedure, so Buck provides the build rule android_library
to do that. Similarly, the final product of most Android development is an APK, so you can use the build rule android_binary
to create an APK.
This documentation organizes Buck's build rules by development language and by target platform. Examples are: C++, Java, Python (development languages) and Android, iOS, .NET (target platforms). Consult the table of contents to locate the build rules that are appropriate for your development project.
You can view a list of Buck's build rules from the command line with the command:
buck audit ruletypes
You can view the arguments supported by a particular rule with the command:
buck audit ruletype <rule>
Note that the first of these commands uses the plural ruletypes
, and the second uses the singular ruletype
. For more information, see the buck audit
documentation.
Source files as inputs to build rules
Most build rules specify source files as inputs. For example, a cxx_library
rule would specify .cpp
files as inputs. To support specifying these files, a cxx_library
rule provides the srcs
argument. Some languages, such as C++, use header files as well. To specify these, cxx_library
provides a headers
argument.
In addition to srcs
and headers
, some rules provide variants of these arguments, such as platform_srcs
and platform_headers
. These arguments support groups of source files that should be used as inputs only when building for specific platforms. For more information, see the descriptions for platform_srcs
and platform_headers
in, for example, the cxx_library
topic.
Package boundaries and access to source files
In Buck, a BUCK file defines a package, which corresponds roughly to the directory that contains the BUCK file and those subdirectories that do not themselves contain BUCK files. (To learn more, see the Key Concepts topic.)
A rule in a BUCK file cannot specify a source file as an input unless that source file is in that BUCK file's package. An exception to this restriction exists for header files, but only if a rule in the package that contains the header file exports that header file using the exported_headers
argument. For more details, see the description for exported_headers
in, for example, the cxx_library
topic.
More commonly though, the package for a BUCK file contains all the source files required for the rules defined in that BUCK file. Functionality in source files from other packages is made available through the artifacts produced by the rules in the BUCK files for those packages. For example, a cxx_binary
might use the functionality in a cxx_library
that is defined in another package. To access that functionality, the cxx_binary
would take that cxx_library
as a dependency.
Symlinks: Use with caution if at all
We recommend that you do not use symlinks—either absolute or relative—to specify input files to build rules. Although using symlinks in this context does sometimes work, it can lead to unexpected behavior and errors.
Dependencies: Output from one rule as input to another rule
A build rule can use the output from another build rule as one of its inputs by specifying that rule as a dependency. Typically, a build rule specifies its dependencies as a list of build targets in its deps
argument. However, the rule can also specify dependencies—as build targets—in other arguments, such as srcs
.
Example: The output of a java_library
rule is a JAR file. If a java_library
rule specifies another java_library
rule as a dependency, the JAR file produced by the specified rule is added to the classpath for the java_library
that depends on it.
Example: If a java_binary
rule specifies a java_library
rule as a dependency, the JAR file for the specified java_library
is available on the classpath for the java_binary
. In addition, in the case of java_binary
, the JAR files for any dependencies of the java_library
rule are also made available to the java_binary
rule—and if those dependencies have dependencies of their own, they are added as well. This exhaustive cascade of dependencies is referred to as the rule's transitive closure.
Required dependencies are always built first
Buck guarantees that any dependencies that a rule lists that are required in order to build that rule are built successfully before Buck builds the rule itself. Note though that there can be special cases—such as apple_bundle
—where a rule's listed dependencies do not actually need to be built before the rule.
Visibility
In order for a build rule to take a dependency on another build rule, the build rule on which the dependency is taken must be visible to the build rule taking the dependency. A build rule's visibility
argument is a list of build target patterns that specify the rules that can take that rule as a dependency. For more information about the concept of visibility in Buck, see the Visibility topic.
Dependencies define a graph
Build rules and their dependencies define a directed acyclic graph (DAG). Buck requires this graph to be acyclic to make it possible to build independent subgraphs in parallel.
How to handle special cases: genrules and macros
Although Buck provides a rich set of built-in build rules for developers, it is not able to address all possible needs. As an "escape hatch," Buck provides a category of generic build rules called genrules. With genrules, you can perform arbitrary operations using shell scripts. The genrules supported by Buck are:
Multiple output files with genrules
In most cases, a build rule produces exactly one output file. However, with genrules, you can specify an output directory and write arbitrary files to that directory.
Macros
Finally, note that you can define functions that generate build rules. In general, this should not be something that you need to do, but taking advantage of this option might help you add needed functionality to Buck's without editing its source code. For more details, see the Custom Macros topic.