# Not Writing a Builder: the &Command; Builder

Creating a &Builder; and attaching it to a &consenv; allows for a lot of flexibility when you want to re-use actions to build multiple files of the same type. This can, however, be cumbersome if you only need to execute one specific command to build a single file (or group of files). For these situations, &SCons; supports a &f-link-Command; builder that arranges for a specific action to be executed to build a specific file or files. This looks a lot like the other builders (like &b-link-Program;, &b-link-Object;, etc.), but takes as an additional argument the command to be executed to build the file:

env = Environment() env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET")
foo.in

When executed, &SCons; runs the specified command, substituting &cv-link-SOURCE; and &cv-link-TARGET; as expected:

scons -Q

This is often more convenient than creating a &Builder; object and adding it to the &cv-link-BUILDERS; variable of a &consenv;.

Note that the action you specify to the &Command; &Builder; can be any legal &SCons; &Action;, such as a Python function:

env = Environment()

def build(target, source, env): # Whatever it takes to build return None

env.Command('foo.out', 'foo.in', build)
foo.in

Which executes as follows:

scons -Q

Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded in the source and target as well, so you can write:

env.Command('${SOURCE.basename}.out', 'foo.in', build)

which does the same thing as the previous example, but allows you to avoid repeating yourself.

It may be helpful to use the `action` keyword to specify the action, is this makes things more clear to the reader:

env.Command('${SOURCE.basename}.out', 'foo.in', action=build)

The method described in for controlling build output works well when used with pre-defined builders which have pre-defined `*COMSTR` variables for that purpose, but that is not the case when calling &f-Command;, where &SCons; has no specific knowledge of the action ahead of time. If the action argument to &f-Command; is not already an &Action; object, it will construct one for you with suitable defaults, which include a message based on the type of action. However, you can also construct the &Action; object yourself to pass to &f-Command;, which gives you much more control. Here's an evolution of the example from above showing this approach:

env = Environment()

def build(target, source, env): # Whatever it takes to build return None

act = Action(build, cmdstr="Building ${TARGET}") env.Command('foo.out', 'foo.in', action=act)
foo.in

Which executes as follows:

scons -Q