[Scons-users] finding out which env causes this error: Two different environments were specified for target

Dominic Binks dominic.binks at thebinkles.net
Mon Mar 28 03:35:17 EDT 2022


Hi Dagg

On 27/03/2022 08:58, daggs wrote:
> Greetings Dominic,
> 
>> Sent: Friday, March 25, 2022 at 9:18 PM
>> From: "Dominic Binks" <dominic.binks at thebinkles.net>
>> To: scons-users at scons.org
>> Cc: daggs at gmx.com
>> Subject: Re: [Scons-users] finding out which env causes this error: Two different environments were specified for target
>>
>> Hi Dagg,
>>
>> I've found the biggest problem with this issue is trying to find out
>> where the duplication is arriving from.
>>
>> To this end, I've created a small function:
>>
>> def check_for_problem_file(env, scons_nodes, needle_re):
>>     nodes = env.Flatten([scons_nodes])
>>     for n in nodes:
>>       if re.match(needle_re, str(n)):
>>         print("Filename match {} against {}".format(n, needle_re))
>>         print_stack()
>>
>> needle_re is a regular expression and a stack trace is printed whenever
>> the regular expression matches the name of a file that is passed in via
>> the scons_nodes.
>>
>> The other part to this is to have a replacement for the function that
>> seems to be giving rise to the duplicate entries.  You've identified
>> that InstallAs does this, so if you wrap the real InstallAs inside a
>> MyInstallAs method, then you can call check_for_problem_file with the
>> name of the file that is seeing the duplicate environment to figure out
>> where the two environments are originating from.
>>
>> It's then not too difficult (usually) to eliminate the duplication.
>>
>> While it's a bit crude, it's proved quite good at helping to eliminate
>> (most) of our duplicate environment warnings.
>>
>> Dominic
> 
> I've tried your func, the trace shows only one SConscript, the problematic on.
> should I put it in all SConscript files called in the tree?
> 
> Dagg.

This will depend a little on your layout of SConstruct/SConscript, or 
rather more environments.  You don't need this function in every 
SConscript, you need to make sure the MyInstallAs method is present in 
every environment.

You said your sconscript was something like this:

for folder in [ a, b, c ]:
   for modes in [ y. z ]:
      export('mode')
      sconscript("src/" + folder + "/SConscript", variant_dir = "out/" + 
folder + "." + mode, duplicate = 0. export('env'))

If, earlier in that file, you include check_for_problem_file() and then add

def MyInstallAs(env, *nargs, **kwargs):
    objs = env.InstallAs(*nargs, **kwargs)
    check_for_problem_file(env, objs, "duplicate-env-warning-file-name")
    return objs

env.AddMethod(MyInstallAs, "MyInstallAs")

Then, as long as you don't create new environments from scratch in the 
sub sconscripts MyInstallAs will report each time the filename matching 
the regex is amongst the generated files.

If you add the InstallAs method as say "RealInstallAs" like this:

env["BUILDERS"]["RealInstallAs"] = env["BUILDERS"]["InstallAs"]

then you can override InstallAs with MyInstallAs and call RealInstallAs 
in the MyInstallAs method which wiil ensure that every call to InstallAs 
gets checked, which may be helpful is you've got a lot of InstallAs targets.

That'd look something like this:

env["BUILDERS"]["RealInstalAs"] = env["BUILDERS"]["InstallAs"]

def MyInstallAs(env, *nargs, **kwargs):
    objs = env.RealInstallAs(*nargs, **kwargs)
    check_for_problem_file(env, objs, "duplicate-env-warning-file-name")
    return objs

# You may need to check this, I'm doing it from memory and I may have
# misremembered something about this.
env["BUILDERS"]["InstallAs"] = SCons.Builder.Builder(action=MyInstallAs)

I don't think you can use AddMethod because I don't think it will 
replace the existing InstallAs.

Hope this helps.

Dominic


More information about the Scons-users mailing list