10.3. Command-Line Targets
Prev | Chapter 10. Controlling a Build From the Command Line | Next

## 10.3. Command-Line Targets

### 10.3.1. Fetching Command-Line Targets: the `COMMAND_LINE_TARGETS` Variable

SCons provides a `COMMAND_LINE_TARGETS` variable that lets you fetch the list of targets that were specified on the command line. You can use the targets to manipulate the build in any way you wish. As a simple example, suppose that you want to print a reminder whenever a specific program is built. You can do this by checking for the target in the `COMMAND_LINE_TARGETS` list:

    if 'bar' in COMMAND_LINE_TARGETS:
        print("Don't forget to copy `bar' to the archive!")
    Default(Program('foo.c'))
    Program('bar.c')

Now, running SCons with the default target works as usual, but explicitly specifying the `bar` target on the command line generates the warning message:

    % scons -Q
    cc -o foo.o -c foo.c
    cc -o foo foo.o
    % scons -Q bar
    Don't forget to copy `bar' to the archive!
    cc -o bar.o -c bar.c
    cc -o bar bar.o

Another practical use for the `COMMAND_LINE_TARGETS` variable might be to speed up a build by only reading certain subsidiary `SConscript` files if a specific target is requested.

### 10.3.2. Controlling the Default Targets: the `Default` Function

You can control which targets SCons builds by default - that is, when there are no targets specified on the command line. As mentioned previously, SCons normally builds every target in or below the current directory unless you explicitly specify one or more targets on the command line. Sometimes, however, you may want to specify that only certain programs, or programs in certain directories, should be built by default. You do this with the `Default` function:

    env = Environment()
    hello = env.Program('hello.c')
    env.Program('goodbye.c')
    Default(hello)

This `SConstruct` file knows how to build two programs, `hello` and `goodbye`, but only builds the `hello` program by default:

    % scons -Q
    cc -o hello.o -c hello.c
    cc -o hello hello.o
    % scons -Q
    scons: `hello' is up to date.
    % scons -Q goodbye
    cc -o goodbye.o -c goodbye.c
    cc -o goodbye goodbye.o

Note that, even when you use the `Default` function in your `SConstruct` file, you can still explicitly specify the current directory (`.`) on the command line to tell SCons to build everything in (or below) the current directory:

    % scons -Q .
    cc -o goodbye.o -c goodbye.c
    cc -o goodbye goodbye.o
    cc -o hello.o -c hello.c
    cc -o hello hello.o

You can also call the `Default` function more than once, in which case each call adds to the list of targets to be built by default:

    env = Environment()
    prog1 = env.Program('prog1.c')
    Default(prog1)
    prog2 = env.Program('prog2.c')
    prog3 = env.Program('prog3.c')
    Default(prog3)

Or you can specify more than one target in a single call to the `Default` function:

    env = Environment()
    prog1 = env.Program('prog1.c')
    prog2 = env.Program('prog2.c')
    prog3 = env.Program('prog3.c')
    Default(prog1, prog3)

Either of these last two examples build only the prog1 and prog3 programs by default:

    % scons -Q
    cc -o prog1.o -c prog1.c
    cc -o prog1 prog1.o
    cc -o prog3.o -c prog3.c
    cc -o prog3 prog3.o
    % scons -Q .
    cc -o prog2.o -c prog2.c
    cc -o prog2 prog2.o

You can list a directory as an argument to `Default`:

    env = Environment()
    env.Program(['prog1/main.c', 'prog1/foo.c'])
    env.Program(['prog2/main.c', 'prog2/bar.c'])
    Default('prog1')

In which case only the target(s) in that directory are built by default:

    % scons -Q
    cc -o prog1/foo.o -c prog1/foo.c
    cc -o prog1/main.o -c prog1/main.c
    cc -o prog1/main prog1/main.o prog1/foo.o
    % scons -Q
    scons: `prog1' is up to date.
    % scons -Q .
    cc -o prog2/bar.o -c prog2/bar.c
    cc -o prog2/main.o -c prog2/main.c
    cc -o prog2/main prog2/main.o prog2/bar.o

Lastly, if for some reason you don't want any targets built by default, you can use the Python `None` variable:

    env = Environment()
    prog1 = env.Program('prog1.c')
    prog2 = env.Program('prog2.c')
    Default(None)

Which would produce build output like:

    % scons -Q
    scons: *** No targets specified and no Default() targets found.  Stop.
    Found nothing to build
    % scons -Q .
    cc -o prog1.o -c prog1.c
    cc -o prog1 prog1.o
    cc -o prog2.o -c prog2.c
    cc -o prog2 prog2.o

#### 10.3.2.1. Fetching the List of Default Targets: the `DEFAULT_TARGETS` Variable

SCons provides a `DEFAULT_TARGETS` variable that lets you get at the current list of default targets specified by calls to the `Default` function or method. The `DEFAULT_TARGETS` variable has two important differences from the `COMMAND_LINE_TARGETS` variable. First, the `DEFAULT_TARGETS` variable is a list of internal SCons nodes, so you need to convert the list elements to strings if you want to print them or look for a specific target name. You can do this easily by calling the `str` on the elements in a list comprehension:

    prog1 = Program('prog1.c')
    Default(prog1)
    print("DEFAULT_TARGETS is %s" % [str(t) for t in DEFAULT_TARGETS])

(Keep in mind that the manipulation of the `DEFAULT_TARGETS` list takes place during the first phase when SCons is reading up the `SConscript` files, which is obvious if you leave off the `-Q` flag when you run SCons:)

    % scons
    scons: Reading SConscript files ...
    DEFAULT_TARGETS is ['prog1']
    scons: done reading SConscript files.
    scons: Building targets ...
    cc -o prog1.o -c prog1.c
    cc -o prog1 prog1.o
    scons: done building targets.

Second, the contents of the `DEFAULT_TARGETS` list changes in response to calls to the `Default` function, as you can see from the following `SConstruct` file:

    prog1 = Program('prog1.c')
    Default(prog1)
    print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS])
    prog2 = Program('prog2.c')
    Default(prog2)
    print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS])

Which yields the output:

    % scons
    scons: Reading SConscript files ...
    DEFAULT_TARGETS is now ['prog1']
    DEFAULT_TARGETS is now ['prog1', 'prog2']
    scons: done reading SConscript files.
    scons: Building targets ...
    cc -o prog1.o -c prog1.c
    cc -o prog1 prog1.o
    cc -o prog2.o -c prog2.c
    cc -o prog2 prog2.o
    scons: done building targets.

In practice, this simply means that you need to pay attention to the order in which you call the `Default` function and refer to the `DEFAULT_TARGETS` list, to make sure that you don't examine the list before you have added the default targets you expect to find in it.

### 10.3.3. Fetching the List of Build Targets, Regardless of Origin: the `BUILD_TARGETS` Variable

You have already seen the `COMMAND_LINE_TARGETS` variable, which contains a list of targets specified on the command line, and the `DEFAULT_TARGETS` variable, which contains a list of targets specified via calls to the `Default` method or function. Sometimes, however, you want a list of whatever targets SCons tries to build, regardless of whether the targets came from the command line or a `Default` call. You could code this up by hand, as follows:

    if COMMAND_LINE_TARGETS:
        targets = COMMAND_LINE_TARGETS
    else:
        targets = DEFAULT_TARGETS

SCons, however, provides a convenient `BUILD_TARGETS` variable that eliminates the need for this by-hand manipulation. Essentially, the `BUILD_TARGETS` variable contains a list of the command-line targets, if any were specified, and if no command-line targets were specified, it contains a list of the targets specified via the `Default` method or function.

Because `BUILD_TARGETS` may contain a list of SCons nodes, you must convert the list elements to strings if you want to print them or look for a specific target name, just like the `DEFAULT_TARGETS` list:

    prog1 = Program('prog1.c')
    Program('prog2.c')
    Default(prog1)
    print("BUILD_TARGETS is %s" % [str(t) for t in BUILD_TARGETS])

Notice how the value of `BUILD_TARGETS` changes depending on whether a target is specified on the command line - `BUILD_TARGETS` takes from `DEFAULT_TARGETS` only if there are no `COMMAND_LINE_TARGETS`:

    % scons -Q
    BUILD_TARGETS is ['prog1']
    cc -o prog1.o -c prog1.c
    cc -o prog1 prog1.o
    % scons -Q prog2
    BUILD_TARGETS is ['prog2']
    cc -o prog2.o -c prog2.c
    cc -o prog2 prog2.o
    % scons -Q -c .
    BUILD_TARGETS is ['.']
    Removed prog1.o
    Removed prog1
    Removed prog2.o
    Removed prog2

Prev | Up | Next
10.2. Command-Line `variable`=`value` Build Variables | Home | Chapter 11. Installing Files in Other Directories: the `Install` Builder