Skip to content

Substitution of special attributes of special variables like $SOURCE does not work in builder calls #4660

@mwichmann

Description

@mwichmann

This topic was previously raised in #2905, which was closed in 2018 without apparently having been really resolved. This issue is created because of a fresh mention.

The User Guide claims that you can do substitutions on SOURCE and TARGET in sources and targets, in the chapter about the Command builder:

https://scons.org/doc/production/HTML/scons-user.html#chap-builders-commands

Specifically:

Note that $SOURCE and $TARGET are expanded in the source and target as well, so you can write:

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

Besides that SCons variables don't have a special attribute basename, this fails even if filebase (which is documented) is used. You get deep into a chain of calls, and eventually StringSubber.expand fails because it tries to eval the string to be substituted and because of the apparent attribute access in there, you get an AttributeError:

AttributeError: 'str' object has no attribute 'filebase'

At this point, the call trace looks like this:

(Pdb) bt
  /home/mats/.pyenv/versions/venv-system312/bin/scons(8)<module>()
-> sys.exit(main())
  /home/mats/github/scons/SCons/Script/Main.py(1515)main()
-> _exec_main(parser, values)
  /home/mats/github/scons/SCons/Script/Main.py(1469)_exec_main()
-> _main(parser)
  /home/mats/github/scons/SCons/Script/Main.py(1111)_main()
-> SCons.Script._SConscript._SConscript(fs, script)
  /home/mats/github/scons/SCons/Script/SConscript.py(281)_SConscript()
-> exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals)
  /tmp/dot/SConstruct(7)<module>()
-> env.Command('${SOURCE.filebase}.out', 'foo.in', build)
  /home/mats/github/scons/SCons/Environment.py(2320)Command()
-> return bld(self, target, source, **kw)
  /home/mats/github/scons/SCons/Builder.py(673)__call__()
-> return self._execute(env, target, source, OverrideWarner(kw), ekw)
  /home/mats/github/scons/SCons/Builder.py(579)_execute()
-> tlist, slist = self._create_nodes(env, target, source)
  /home/mats/github/scons/SCons/Builder.py(524)_create_nodes()
-> tlist = env.arg2nodes(target, target_factory, target=target, source=source)
  /home/mats/github/scons/SCons/Environment.py(691)arg2nodes()
-> v = node_factory(self.subst(v, **kw))
  /home/mats/github/scons/SCons/Environment.py(722)subst()
-> return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv, overrides=overrides)
  /home/mats/github/scons/SCons/Subst.py(854)scons_subst()
-> result = ss.substitute(strSubst, lvars)
  /home/mats/github/scons/SCons/Subst.py(459)substitute()
-> result = _dollar_exps.sub(sub_match, args)
  /home/mats/github/scons/SCons/Subst.py(454)sub_match()
-> return self.conv(self.expand(match.group(1), lvars))
> /home/mats/github/scons/SCons/Subst.py(393)expand()
-> raise_exception(e, lvars['TARGETS'], old_s)
(Pdb)

Everything at this point looks as one might expect. The string to sub is '${SOURCE.filebase}', the code has extracted the relevant part so the key variable is 'SOURCE.filebase', lvars has the right values for the special variables in it:

{'__env__': <SCons.Script.SConscript.SConsEnvironment object at 0x7f105c0e2780>,
'TARGETS': ['${SOURCE.filebase}.out'],
'TARGET': '${SOURCE.filebase}.out',
'CHANGED_TARGETS': '$TARGETS',
'UNCHANGED_TARGETS': '$TARGETS',
'SOURCES': ['foo.in'],
'SOURCE': 'foo.in',
'CHANGED_SOURCES': '$SOURCES',
'UNCHANGED_SOURCES': '$SOURCES',
'__return__': None}

But the attempt to evaluate it fails:

s = eval(key, self.gvars, lvars)

A few lines prior to that line, there was an attempt to detect a period in the string, but then nothing is done with that information until later. That initial check is here:

if key[0] == '{' or '.' in key:

Metadata

Metadata

Assignees

No one assigned

    Labels

    substProblems with quoting, substitution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions