[Scons-users] Modifying the provided environment in an emitter?

Marc Branchaud marcnarc at xiplink.com
Mon Apr 24 14:07:07 EDT 2017


On 2017-04-24 01:07 PM, Bill Deegan wrote:
> Marc,
>
> Why not use a Value() node as the source for your symlink builder?

Ignorance, mostly.  This pattern was adopted long ago, in other 
Builders.  When it came to to create our SymLink Builder, following the 
pattern required the fewest brain cycles.

		M.

> -Bill
>
>
> On Mon, Apr 24, 2017 at 8:38 AM, Marc Branchaud <marcnarc at xiplink.com
> <mailto:marcnarc at xiplink.com>> wrote:
>
>     On 2017-04-21 05:29 PM, Andrew C. Morrow wrote:
>
>
>         Hi all -
>
>         Is it legit to modify the passed in env in an emitter?
>
>
>     I dunno about "legit" but we do this all the time when we want to
>     pass info calculated in the emitter to the builder.
>
>     Here's a simple example:  One of the things we build is a complete
>     OS image in a variant subdir (which we then bundle into a tarball).
>     The OS image contains symlinks to absolute paths, which are
>     legitimate when the image is written onto a root partition, but
>     which are "dead" (the symlink's source doesn't exist) when they are
>     in the image's variant subdir.
>
>     So we have a SymLink Builder that lets us create these symlinks:
>
>             SymLink(target="name/of/symlink/in/os/image",
>                     source="/absolute/path/of/symlink/source")
>
>     Since the Builder's source isn't an actual file, the emitter sets
>     the source to None, so that SCons ignores it.  But we need to save
>     that source path to create the actual symlink, so we store it in a
>     dict in the environment.  The dict is keyed by the target's
>     variant-dependent absolute path.  (This emitter also works with
>     non-absolute-path symlink sources, by stripping the path that SCons
>     prepends to such things.)
>
>             def emitter(target, source, env):
>                 if '__SymLinkSources' not in env.Dictionary():
>                     env['__SymLinkSources'] = {}
>                 # The source of a symlink is just an arbitrary
>                 # string, but SCons thinks it's a file and so
>                 # prepends it with the path to the SConscript
>                 # that uses the SymLink builder.  Undo this.
>                 path = env.Dir('.').srcnode().abspath
>                 src = str(source[0])
>                 if src.startswith(path):
>                     src = src[len(path)+1:]
>                 env['__SymLinkSources'][target[0].abspath] = src
>                 return (target, None)
>
>     Then the builder simply extracts the source path from the dict:
>
>             def builder(target, source, env):
>                 # SCons can't tell the difference between a
>                 # symlink that points to an non-existent file
>                 # and a symlink that doesn't even exist.
>                 # So we need to be smart here, because we
>                 # might be asked to re-create a symlink that's
>                 # already there.
>                 tgt = target[0].abspath
>                 if os.path.lexists(tgt):
>                     # If the target already exists, just remove it.
>                     os.unlink(tgt)
>                 os.symlink(env['__SymLinkSources'][tgt], tgt)
>
>     Several of our Builders do this sort of thing.  Works great!
>
>                     M.
>
>
>             def add_lib_foo_emitter(target, source, env):
>                 libs = env.get('LIBS', [])
>                 libs.append('foo')
>                 env['LIBS'] = libs
>                 return (target, source)
>
>             def add_emitter(builder):
>                 base_emitter = builder.emitter
>                 new_emitter =
>         SCons.Builder.ListEmitter([add_lib_foo_emitter,
>         base_emitter])
>                 builder.emitter = new_emitter
>
>             target_builders = ['Program', 'SharedLibrary', 'LoadableModule',
>         'StaticLibrary']
>             for builder in target_builders:
>                 add_emitter(env['BUILDERS'][builder])
>
>         I've found myself wanting to do this with increasing frequency,
>         but am
>         unclear on whether this is acceptable. It appears to work, but the
>         documentation doesn't seem to offer any clear guidance that I've
>         found
>         on whether it is guaranteed to work. If so (which would be
>         great!), am I
>         guaranteed that the modification of env is scoped only to the
>         passed in
>         targets?
>
>         Thanks,
>         Andrew
>
>
>
>         _______________________________________________
>         Scons-users mailing list
>         Scons-users at scons.org <mailto:Scons-users at scons.org>
>         https://pairlist4.pair.net/mailman/listinfo/scons-users
>         <https://pairlist4.pair.net/mailman/listinfo/scons-users>
>
>     _______________________________________________
>     Scons-users mailing list
>     Scons-users at scons.org <mailto:Scons-users at scons.org>
>     https://pairlist4.pair.net/mailman/listinfo/scons-users
>     <https://pairlist4.pair.net/mailman/listinfo/scons-users>
>
>
>
>
> _______________________________________________
> Scons-users mailing list
> Scons-users at scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users
>


More information about the Scons-users mailing list