Defining an emitter to work with a custom Builder
is a powerful concept, but sometimes all you really want
is to be able to use an existing builder but change its
concept of what targets are created.
In this case,
trying to recreate the logic of an existing Builder to
supply a special emitter can be a lot of work.
The typical case for this is when you want to use a compiler flag
that causes additional files to be generated.
For example the GNU linker accepts an option
-Map
which outputs a link map
to the file specified by the option's argument.
If this option is just supplied to the build,
SCons will not consider the link map file a tracked target,
which has various undesirable efffects.
To help with this, SCons provides construction variables which correspond
to a few standard builders:
$PROGEMITTER
for Program
;
$LIBEMITTER
for Library
;
$SHLIBEMITTER
for SharedLibrary
and
$LDMODULEEMITTER
for LoadableModule
;.
Adding an emitter to one of these will cause it to be
invoked in addition to any existing emitter for the
corresponding builder.
This example adds map creation as a linker flag,
and modifies the standard Program
emitter to know that map generation is a side-effect:
env = Environment() map_filename = "${TARGET.name}.map" def map_emitter(target, source, env): target.append(map_filename) return target, source env.Append(LINKFLAGS="-Wl,-Map={},--cref".format(map_filename)) env.Append(PROGEMITTER=map_emitter) env.Program('hello.c')
If you run this example, adding an option to tell SCons to dump some information about the dependencies it knows, it shows the map file option in use, and that SCons indeed knows about the map file, it's not just a silent side effect of the compiler:
% scons -Q --tree=prune
cc -o hello.o -c hello.c
cc -o hello -Wl,-Map=hello.map,--cref hello.o
+-.
+-SConstruct
+-hello
| +-hello.o
| +-hello.c
+-hello.c
+-hello.map
| +-[hello.o]
+-[hello.o]