Open bdbaddog opened 3 years ago
Each variable can be one of following: unset, None, scalar, list, mapping. Also value that is passed to Append() etc can be anything of the above. That creates quite a combinatorial explosion. I think it's impossible to always do the right thing without knowing what is the variable expected to be. Like LIBS is supposed to be a list, SHLIBPREFIX is supposed to be a scalar etc. Currently SCons sets initial values to some variables that make things less unpredictable but still if you assign something directly to env["something"] you just overwrite it. I think safest would be to have some auto-coercion feature but it would need to hook directly into operations like []/__getitem__()/__setitem__()
and also there would have to be a way to tag a variable as particular kind, i.e. whether it's scalar or list or mapping.
I've gotten deeper into this than I ever wanted to so plenty of thoughts here, will probably dribble them out over time.
There is some auto-coercion - e.g. if you Append to CPPDEFINES, it immediately forces the existing value into a list. Well, if it was a string. LIBS needs to do the same bue doesn't. The special-casing extends only to Append and AppendUnique (with the latter containing some logic errors), and misses Prepend and PrependUnique. The idea of having four separate implementations of almost-the-same-thing was bound to lead to unintented divergence, and we have it. See #3876 for more on that.
I managed to implement all combinations of {Append|Prepend}{Non-unique|Unique} in a single C++ template function: https://github.com/loonycyborg/scons-plusplus/blob/master/src/python_interface/environment_wrappers.hpp#L165
But direct assignment is still not covered, so it's possible to unexpectedly assign a string to env["LIBS"] and a list/dict to env["SHLIBPREFIX"]. If there are custom __getitem__/_setitem__
those cases would be covered too.
The relevant class is actually SubstitutionEnvironment
, and of course there's already some "magic" hiding there.
Just note that in the past this was considered performance sensitive stuff... the __setarttr__
may not want to grow lots of checks.
So could some variant of Typing help? Right now SCons has a place where it's somewhat aware of types of things, that's in ParseFlags
, where there's a dictionary of knows consvars the method might distribute values to. A subset:
'CPPFLAGS' : CLVar(''),
'CPPPATH' : [],
That doesn't seem too wildly different from:
CPPFLAGS: CLVar = CLVar('')
CPPPATH: list = []
If that information is somewhere, the "checker mode" (or a separate sconslint
) could perhaps flag a warning that you just assigned a str
to env['CPPPATH']
... just thinking out loud, not sure how viable that is applied to dictionary key/values.
Just dropping this here to track an issue that isn't decided yet - modifications to env's in Action functions seem like a bad idea. Is this something a checker could detect and maybe warn about?
This is a WIP issue to gather all the ideas of what can reasonable be checked when setting, appending, replacing and Environment() variable.
@mwichmann
Started as dicussion on discord
Followed by