[Scons-users] Modifying the provided environment in an emitter?
Bill Deegan
bill at baddogconsulting.com
Mon Apr 24 13:07:15 EDT 2017
Marc,
Why not use a Value() node as the source for your symlink builder?
-Bill
On Mon, Apr 24, 2017 at 8:38 AM, Marc Branchaud <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
>> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://pairlist4.pair.net/pipermail/scons-users/attachments/20170424/cb00f7b1/attachment.html>
More information about the Scons-users
mailing list