Target
- Overview
- Overrides
- Methods
- id
- path
- branch
- rule
- set_cleanable
- cleanable
- set_built
- built
- timestamp
- last_write_time
- outdated
- add_filename
- set_filename
- clear_filenames
- filename
- filenames
- directory
- set_working_directory
- add_dependency
- remove_dependency
- add_implicit_dependency
- clear_implicit_dependencies
- add_ordering_dependency
- add_passive_dependency
- parent
- working_directory
- dependency
- dependencies
- ordering_dependencies
- any_dependencies
Overview
Targets are the nodes in the dependency graph. Typically each target represents a single file but targets can also represent a single directory, multiple files, multiple directories, and even groups of targets that are useful to build together but aren’t directly related to anything on disk (e.g. the all targets in the root and other directories).
Create targets by passing an identifier to one of the target creation functions forge:SourceFile()
, forge:File()
, or forge:Target()
to create targets representing source files, intermediate files, or targets that will be defined later.
The identifier used to create a target is considered a relative path to the target to create. The relative paths is considered relative to Forge’s notion of the current working directory set to the path of the file currently being executed by Forge (e.g. the root build script of the currently executing buildfile).
Targets exist in a hierarchical namespace with the same semantics as operating system paths. Targets have an identifier, a parent, and zero or more children. Targets are referred to via /
delimited paths by using .
and ..
to refer to the current target and parent target respectively.
The hierarchical namespace is similar but not identical to the hierarchy of directories and files on disk. Targets are often bound to files on disk in quite separate locations from their location in the target namespace or even not bound to files at all.
Referring to a target with the same identifier always returns the same target. This allows late binding in the case of depending targets that refer to their dependencies before those dependencies are fully defined.
Anonymous targets can be created using the anonymous()
function to generate a unique identifier for the target instead of passing a specific identifier.
The order in which targets are built is specified implicitly by the dependencies between targets. Dependencies of each target are built before the target itself. Cyclic dependencies are lazily detected at build-time and generate a warning (but not an error).
Target paths and system paths always use /
as a delimiter. Convert paths to native paths prior to passing them to external tools if needed with the native()
function.
Although targets usually bind to a single file it is possible to create targets with no associated file (i.e. Make’s phony targets) or with multiple associated files (i.e. tools that generate multiple output files in one invocation).
The string passed to create a target is that target’s identifier or is used to generate the identifier for multiple targets. A target’s identifier is often different from its filename. In the example above the static library target’s identifier is hello_world
but it will build to a file named libhello_world.a or hello_world.lib when built with Unix and Windows toolchains respectively.
Targets without rules are valid. These targets are typically source files that aren’t updated by the build system and but still need to be tracked in order to determine when intermediate files that depend on them are outdated.
Create dependencies conditionally by storing a target in a local variable and making further dependency calls on it. Alternatively passing the same identifier (after string substitution) will return an already created target. So really all that needs to happen is the dependency call is made conditionally onto the same target.
Create dependencies dynamically using the same pattern as for conditional dependencies of storing a target in a local variable or reusing an existing identifier. A typical example of dynamic dependencies is looping over all toolsets to build executables to be combined into a macOS or iOS fat binary.
Overrides
create
function Target.create( toolset, identifier, rule )
The create()
function is called whenever a target for that rule is created by calling the rule table returned from Rule()
.
The parameters passed are the toolset that the target is being created with, the identifier that was specified, and the rule that was used to create the target (possibly nil).
depend
function Target.depend( toolset, target, dependencies )
The depend()
function is called whenever a call is made on a target for that rule. Typically this captures the use of calls of the form target { dependencies } to add dependencies or further define a target.
The parameters passed are the toolset that the target was created with, the target itself, and the dependencies that were passed in.
build
function Target.build( toolset, target )
The build()
function is called whenever an outdated target is visited as part of a build traversal. The function should carry out whatever actions are necessary to build the file(s) that it represents up to date.
The parameters passed in are the toolset that the target was created with and the target itself.
clean
function Target.clean( toolset, target )
The clean()
function is called whenever a target is visited as part of a clean traversal. The function should carry out whatever actions are necessary to remove files that were generated during a build traversal.
Default behavior when visiting a cleanable target is to remove any files that the target is bound to. Custom clean behavior is only needed if removing all of the built files is not desired.
The parameters passed in are the toolset that the target was created with and the target itself.
Methods
id
function Target.id( target )
Return the identifier of this target.
path
function Target.path( target )
Return the full path of this target.
branch
function Target.branch( target )
Return the directory part of the path of this target.
rule
function Target.rule( target )
Return the rule for this target or nil for target’s without rules.
set_cleanable
function Target.set_cleanable( target, cleanable )
Set whether or not target
should be automatically cleaned. This has no effect on whether or not a clean function is called during a traversal simply whether or not the target will be automatically deleted if no explicit clean function is provided.
cleanable
function Target.cleanable( target )
Return true if target
is cleanable otherwise false.
set_built
function Target.set_built( target, built )
Set whether or not target
is considered to have been built successfully.
built
function Target.built( target )
Return true if target
has been built successfully at least once.
timestamp
function Target.timestamp( target )
Return the timestamp of target
.
If target
isn’t bound to a file then the last write time is always the beginning of the epoch - January 1st, 1970, 00:00 GMT. Because this is the oldest possible timestamp this will leave unbound targets always needing to be updated.
last_write_time
function Target.last_write_time( target )
Return the last write time of target
.
outdated
function Target.outdated( target )
Returns true if target
is outdated otherwise false.
add_filename
function Target.add_filename( target, filename )
Append filename
to the list of filenames that target
binds to.
set_filename
function Target.set_filename( target, filename, index )
Set filename at index
of this target
to filename
. This is the name of the file that this target will attempt to bind to during the bind traversal.
clear_filenames
function Target.clear_filenames( target )
Clear the list of filenames that target
binds to.
filename
function Target.filename( target, index )
Get the filename at index
for this target
. Return the filename of this target or an empty string if target
hasn’t been bound to a file or index
is greater than the number of files to bind for target
. The index
parameter is optional and defaults to 1 (the first filename) if not specified.
filenames
function Target.filenames( target, start, finish )
Iterate over the filenames of target
from start
to finish
. The start
and finish
parameters are optional and default to 1 and INT_MAX
respectively to give the effect of iterating over all filenames of target
.
directory
function Target.directory( target, n )
Get the directory portion of the n
th filename that target
will bind to. Return the empty string if n
is greater than the number of files to bind for target
.
set_working_directory
function Target.set_working_directory( target, working_directory )
Set the working directory of target
to the target working_directory
or to the root directory of its containing graph if working_directory
is nil.
The working directory is the target that specifies the directory that files specified in scripts for the target are relative to by default and that any commands executed by the target’s script functions are started in. If a target has no working directory then the root target is used instead.
add_dependency
function Target.add_dependency( target, dependency )
Add dependency
as an explicit dependency of target
.
If dependency
is null or the same as target
then this function quietly does nothing.
If dependency
is already an implicit, ordering, or passive dependency of target
then it is made the last explicit dependency of target
. That is the dependency is removed and added as the last explicit dependency.
Cyclic dependencies are not valid but are not reported here. Cyclic dependencies are detected during traversals and silently ignored.
remove_dependency
function Target.remove_dependency( target, dependency )
Remove dependency
as a dependency of target
. Removes the dependency regardless of whether that dependency is an explicit, implicit, ordering, or passive dependency.
add_implicit_dependency
function Target.add_implicit_dependency( target, dependency )
Add dependency
as an implicit dependency of target
.
If dependency
is null, the same as target
, anonymous, or already an explicit dependency of target
then this function quietly does nothing.
If dependency
is already an implicit, ordering, or passive dependency of target
then it is made the last implicit dependency of target
. That is the dependency is removed and added as the last implicit dependency.
clear_implicit_dependencies
function Target.clear_implicit_dependencies( target )
Clear the list of implicit dependencies of target
.
add_ordering_dependency
function Target.add_ordering_dependency( target, dependency )
Add dependency
as an ordering dependency of target
.
If dependency
is null, the same as target
, anonymous, or already an explicit or implicit dependency of target
then this function quietly does nothing.
If dependency
is already an ordering or passive dependency of target
then it is made the last ordering dependency of target
. That is the dependency is removed and added as the last ordering dependency.
add_passive_dependency
function Target.add_passive_dependency( target, dependency )
Add dependency
as a passive dependency of target
.
If dependency
is null, the same as target
, anonymous, or already an explicit, implicit, or ordering dependency of target
then this function quietly does nothing.
If dependency
is already a passive dependency of target
then it is made the last passive dependency of target
. That is the dependency is removed and added as the last passive dependency.
parent
function Target.parent( target )
Return the parent of target
. This is the target’s parent in the hierarchical namespace of targets not the target’s parent in the dependency graph (of which there may be many).
working_directory
function Target.working_directory( target )
Return the target that is the working directory of target
or nil if target
doesn’t have a working directory.
dependency
function Target.dependency( target, n )
Return the n
th explicit dependency of target
or nil if n
is greater than the number of dependencies of target
.
dependencies
function Target.dependencies( target, start, finish )
Iterate over the explicit dependencies of target
. The start
and finish
parameters are optional and default to 1 and INT_MAX
respectively to give the effect of iterating over all the explicit dependencies of target
.
ordering_dependencies
function Target.ordering_dependencies( target )
Iterate over the ordering dependencies of target
. The start
and finish
parameters are optional and default to 1 and INT_MAX
respectively to give the effect of iterating over all the ordering dependencies of target
.
any_dependencies
function Target.all_dependencies( target )
Iterate over all dependencies of target
. The start
and finish
parameters are optional and default to 1 and INT_MAX
respectively to give the effect of iterating over all dependencies of target
.