<?xml version="1.0"?>
<!--
SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
SPDX-License-Identifier: MIT
SPDX-FileType: DOCUMENTATION

This file is processed by the bin/SConsDoc.py module.
-->

<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM '../doc/scons.mod'>
%scons;
<!ENTITY % builders-mod SYSTEM '../doc/generated/builders.mod'>
%builders-mod;
<!ENTITY % functions-mod SYSTEM '../doc/generated/functions.mod'>
%functions-mod;
<!ENTITY % tools-mod SYSTEM '../doc/generated/tools.mod'>
%tools-mod;
<!ENTITY % variables-mod SYSTEM '../doc/generated/variables.mod'>
%variables-mod;
]>

<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">

<cvar name="IMPLICIT_COMMAND_DEPENDENCIES">
<summary>
<para>
Controls whether or not &SCons; will
add implicit dependencies for the commands
executed to build targets.
</para>

<para>
By default, &SCons; will add to each target
an implicit dependency on the command
represented by the first argument of any
command line it executes (which is typically
the command itself). By setting such
a dependency, &SCons; can determine that
a target should be rebuilt if the command changes,
such as when a compiler is upgraded to a new version.
The specific file for the dependency is
found by searching the
<varname>PATH</varname>
variable in the
<varname>ENV</varname> dictionary
in the &consenv; used to execute the command.
The default is the same as
setting the &consvar;
&cv-IMPLICIT_COMMAND_DEPENDENCIES;
to a True-like value (<quote>true</quote>,
<quote>yes</quote>,
or <quote>1</quote> - but not a number
greater than one, as that has a different meaning).
</para>

<para>
Action strings can be segmented by the
use of an AND operator, <literal>&amp;&amp;</literal>.
In a segmented string, each segment is a separate
<quote>command line</quote>, these are run
sequentially until one fails, or the entire
sequence has been executed. If an
action string is segmented, then the selected
behavior of &cv-IMPLICIT_COMMAND_DEPENDENCIES;
is applied to each segment.
</para>

<para>
If &cv-IMPLICIT_COMMAND_DEPENDENCIES;
is set to a False-like value
(<quote>none</quote>,
<quote>false</quote>,
<quote>no</quote>,
<quote>0</quote>,
etc.),
then the implicit dependency will
not be added to the targets
built with that &consenv;.
</para>

<para>
If &cv-IMPLICIT_COMMAND_DEPENDENCIES;
is set to <quote>2</quote> or higher,
then that number of arguments in the command line
will be scanned for relative or absolute paths.
If any are present, they will be added as
implicit dependencies to the targets built
with that &consenv;.
The first argument in the command line will be
searched for using the <varname>PATH</varname>
variable in the <varname>ENV</varname> dictionary
in the &consenv; used to execute the command.
The other arguments will only be found if they
are absolute paths or valid paths relative
to the working directory.
</para>

<para>
If &cv-IMPLICIT_COMMAND_DEPENDENCIES;
is set to <quote>all</quote>,
then all arguments in the command line will be
scanned for relative or absolute paths.
If any are present, they will be added as
implicit dependencies to the targets built
with that &consenv;.
The first argument in the command line will be
searched for using the <varname>PATH</varname>
variable in the <varname>ENV</varname> dictionary
in the &consenv; used to execute the command.
The other arguments will only be found if they
are absolute paths or valid paths relative
to the working directory.
</para>

<example_commands>
env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=False)
</example_commands>
</summary>
</cvar>

<cvar name="PRINT_CMD_LINE_FUNC">
<summary>
<para>
A Python function used to print the command lines as they are executed
(assuming command printing is not disabled by the
<option>-q</option>
or
<option>-s</option>
options or their equivalents).
The function must accept four arguments:
<varname>s</varname>,
<varname>target</varname>,
<varname>source</varname> and
<varname>env</varname>.
<varname>s</varname>
is a string showing the command being executed,
<varname>target</varname>,
is the target being built (file node, list, or string name(s)),
<varname>source</varname>,
is the source(s) used (file node, list, or string name(s)),
and <varname>env</varname>
is the environment being used.
</para>

<para>
The function must do the printing itself.
The default implementation,
used if this variable is not set or is <constant>None</constant>,
is to just print the string, as in:
</para>
<example_commands>
def print_cmd_line(s, target, source, env):
    sys.stdout.write(s + "\n")
</example_commands>

<para>
Here is an example of a more interesting function:
</para>

<example_commands>
def print_cmd_line(s, target, source, env):
    sys.stdout.write(
        "Building %s -> %s...\n"
        % (
            ' and '.join([str(x) for x in source]),
            ' and '.join([str(x) for x in target]),
        )
    )

env = Environment(PRINT_CMD_LINE_FUNC=print_cmd_line)
env.Program('foo', ['foo.c', 'bar.c'])
</example_commands>

<para>
This prints:
</para>

<screen>
...
scons: Building targets ...
Building bar.c -> bar.o...
Building foo.c -> foo.o...
Building foo.o and bar.o -> foo...
scons: done building targets.
</screen>

<para>
Another example could be a function that logs the actual commands to a file.
</para>
</summary>
</cvar>

<cvar name="SPAWN">
<summary>
<para>
A command interpreter function that will be called to execute command line
strings. The function must accept five arguments:
</para>

<example_commands>
def spawn(shell, escape, cmd, args, env):
</example_commands>

<para>
<varname>shell</varname>
is a string naming the shell program to use,
<varname>escape</varname>
is a function that can be called to escape shell special characters in
the command line,
<varname>cmd</varname>
is the path to the command to be executed,
<varname>args</varname>
holds the arguments to the command and
<varname>env</varname>
is a dictionary of environment variables
defining the execution environment in which the command should be executed.
</para>
</summary>
</cvar>

<cvar name="SHELL_ENV_GENERATORS">
  <summary>
    <para>
A hook allowing the execution environment to be modified prior
to the actual execution of a command line from an action
via the spawner function defined by &cv-link-SPAWN;.
Allows substitution based on targets and sources,
as well as values from the &consenv;,
adding extra environment variables, etc.
    </para>

    <para>
The value must be a list (or other iterable)
of functions which each generate or
alter the execution environment dictionary.
The first function will be passed a copy of the initial execution environment
(&cv-link-ENV; in the current &consenv;);
the dictionary returned by that function is passed to the next,
until the iterable is exhausted and the result returned
for use by the command spawner.
The original execution environment is not modified.
    </para>

    <para>
Each function provided in &cv-SHELL_ENV_GENERATORS; must accept four
arguments and return a dictionary:
<varname>env</varname> is the &consenv; for this action;
<varname>target</varname> is the list of targets associated with this action;
<varname>source</varname> is the list of sources associated with this action;
and <varname>shell_env</varname> is the current dictionary after iterating
any previous &cv-SHELL_ENV_GENERATORS; functions
(this can be compared to the original execution environment,
which is available as <literal>env['ENV']</literal>, to detect any changes).
    </para>

    <para>Example:</para>
    <example_commands>
def custom_shell_env(env, target, source, shell_env):
    """customize shell_env if desired"""
    if str(target[0]) == 'special_target':
        shell_env['SPECIAL_VAR'] = env.subst('SOME_VAR', target=target, source=source)
    return shell_env

env["SHELL_ENV_GENERATORS"] = [custom_shell_env]
    </example_commands>

  <para><emphasis>Available since 4.4</emphasis></para>
  </summary>
</cvar>

</sconsdoc>
