6.7. Order-Only Dependencies: the `Requires` Function
Prev | Chapter 6. Dependencies | Next

## 6.7. Order-Only Dependencies: the `Requires` Function

Occasionally, it may be useful to specify that a certain file or directory must, if necessary, be built or created before some other target is built, but that changes to that file or directory do not require that the target itself be rebuilt. Such a relationship is called an order-only dependency because it only affects the order in which things must be built--the dependency before the target--but it is not a strict dependency relationship because the target should not change in response to changes in the dependent file.

For example, suppose that you want to create a file every time you run a build that identifies the time the build was performed, the version number, etc., and which is included in every program that you build. The version file's contents will change every build. If you specify a normal dependency relationship, then every program that depends on that file would be rebuilt every time you ran SCons. For example, we could use some Python code in a `SConstruct` file to create a new `version.c` file with a string containing the current date every time we run SCons, and then link a program with the resulting object file by listing `version.c` in the sources:

    import time

    version_c_text = """
    char *date = "%s";
    """ % time.ctime(time.time())
    open('version.c', 'w').write(version_c_text)

    hello = Program(['hello.c', 'version.c'])

If we list `version.c` as an actual source file, though, then the `version.o` file will get rebuilt every time we run SCons (because the `SConstruct` file itself changes the contents of `version.c`) and the `hello` executable will get re-linked every time (because the `version.o` file changes):

    % scons -Q hello
    cc -o hello.o -c hello.c
    cc -o version.o -c version.c
    cc -o hello hello.o version.o
    % sleep 1
    % scons -Q hello
    cc -o version.o -c version.c
    cc -o hello hello.o version.o
    % sleep 1
    % scons -Q hello
    cc -o version.o -c version.c
    cc -o hello hello.o version.o

(Note that for the above example to work, we sleep for one second in between each run, so that the `SConstruct` file will create a `version.c` file with a time string that's one second later than the previous run.)

One solution is to use the `Requires` function to specify that the `version.o` must be rebuilt before it is used by the link step, but that changes to `version.o` should not actually cause the `hello` executable to be re-linked:

    import time

    version_c_text = """
    char *date = "%s";
    """ % time.ctime(time.time())
    open('version.c', 'w').write(version_c_text)

    version_obj = Object('version.c')

    hello = Program('hello.c',
                    LINKFLAGS = str(version_obj[0]))

    Requires(hello, version_obj)

Notice that because we can no longer list `version.c` as one of the sources for the `hello` program, we have to find some other way to get it into the link command line. For this example, we're cheating a bit and stuffing the object file name (extracted from `version_obj` list returned by the `Object` builder call) into the `$LINKFLAGS` variable, because `$LINKFLAGS` is already included in the `$LINKCOM` command line.

With these changes, we get the desired behavior of only re-linking the `hello` executable when the `hello.c` has changed, even though the `version.o` is rebuilt (because the `SConstruct` file still changes the `version.c` contents directly each run):

    % scons -Q hello
    cc -o version.o -c version.c
    cc -o hello.o -c hello.c
    cc -o hello version.o hello.o
    % sleep 1
    % scons -Q hello
    cc -o version.o -c version.c
    scons: `hello' is up to date.
    % sleep 1
    %     [CHANGE THE CONTENTS OF hello.c]
    % scons -Q hello
    cc -o version.o -c version.c
    cc -o hello.o -c hello.c
    cc -o hello version.o hello.o
    % sleep 1
    % scons -Q hello
    cc -o version.o -c version.c
    scons: `hello' is up to date.

Prev | Up | Next
6.6. Ignoring Dependencies: the `Ignore` Function | Home | 6.8. The `AlwaysBuild` Function