-
-
Notifications
You must be signed in to change notification settings - Fork 316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split out CPPDEFINES handling in Append methods #4263
Conversation
e2c9161
to
e4addd3
Compare
RELEASE.txt
Outdated
@@ -64,6 +69,17 @@ FIXES | |||
- Ninja: Fix execution environment sanitation for launching ninja. Previously if you set an | |||
execution environment variable set to a python list it would crash. Now it | |||
will create a string joining the list with os.pathsep | |||
- Inconsistent behavior of adding CPPDEFINES values via tuple arguments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this can change the CPPDEFINES, we should add a section at the top with
NOTE: The following usages of CPPDEFINES have changed
env.Append(CPPDEFINES,('a','b') ) now yields -Da -Db instead of -Da=b
etc..
Should be a fairly small set of these to clearly spell out what's changed?
CHANGES.txt
Outdated
@@ -86,7 +86,17 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER | |||
still run into problems on some configurations), and automated | |||
tests are now run on changes in this area so future problems can | |||
be spotted. | |||
|
|||
- Special-case handling for CPPDEFINES in the Append/Prepend routines |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be multiple bullets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can do that, but it's really convoluted - see the long report in the one issue of the various inconsistencies I had discovered. So there would be a bunch of "now get (b) instead of (a), but only if (c); if (d) the behavior was already (b); if (e), this previously did not work at all".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would be valuable. This whole PR is really about fixing some corner cases (and reorganizing the code so it's more sane), so explaining which corner cases are now fixed (changed) would be useful for anyone who updated and saw their build change, and/or has a build not doing what they expect and sees that the newer version solves that.
Bigger organizations often need a forcing function to move to a newer version.
If any element is a tuple (or list) | ||
then the first item of the tuple is the macro name | ||
and the second is the macro definition. | ||
If the definition is not omitted or <literal>None</literal>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value instead of definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought I was writing it in terms of how the C standard expresses those... although now I look, the standard uses "replacement" rather than "definition".
</example_commands> | ||
|
||
<para> | ||
:<emphasis>Changed in version 4.5</emphasis>: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4.5.0
CXXFLAGS=-std=c11 -O, CPPDEFINES=['RELEASE', 'EXTRA'] | ||
CPPDEFINES will expand to -DRELEASE -DEXTRA | ||
CXXFLAGS = -std=c11, CPPDEFINES = RELEASE | ||
CXXFLAGS = -std=c11 -O, CPPDEFINES = deque(['RELEASE', 'EXTRA']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adding deque here will most likely just confuse users. Many of whom aren't strong python programmers. I'd leave it just the list.
SCons/Environment.xml
Outdated
(<computeroutput>-DBAR=1</computeroutput>). | ||
&SCons; allows you to specify a macro with a definition | ||
using a <literal>name=value</literal> string, | ||
or a tuple <literal>(name, value)</literal> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this no longer be done with a list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can, it's just awkward to keep repeating multiples all over the place. It would be nice to use "sequence" as that covers all of tuple, list, UserList, etc. but it also includes str, which is not a data type that can be used for a name, value pair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed a rewording of this part.
CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2)] | ||
CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2), {'EXTRA': 'arg'}] | ||
CPPDEFINES = FOO | ||
CPPDEFINES = deque(['FOO', 'BAR=1']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deque?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code takes the initial value given to CPPDEFINES as-is, but once you further Append/Prepend it takes the liberty of converting to a type useful to it. It always did that, but the chosen compound type depends on the sequence of events - could be a list, a dict, etc. Or in the case of AppendUnique, it converted it to a type incorrectly in some cases. Now we consistently get a deque, allowing the processing to be sane. Yes, as noted elsewhere, it could be a list instead but that shouldn't really be important to the user. Which type is really only exposed if you dig, as it happens here trying to show an example.
</screen> | ||
|
||
<para> | ||
<emphasis>Changed in version 4.5</emphasis>: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4.5.0
<screen> | ||
$ scons -Q | ||
CPPDEFINES = ('MACRO1', 'MACRO2') | ||
CPPDEFINES = deque(['MACRO1', 'MACRO2', ('MACRO3', 'MACRO4')]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deque?
Curious: Why use deque instead of a list to hold the defines? |
This is a natural fit for a deque since it's designed to be added to from either end with Prepend and Append. Prepending a deque is as fast as appending, and this way don't have to play silly games (reverse the list, append to it, reverse back... that kind of thing). |
Would you expect all the examples in this sample code https://github.com/bdbaddog/scons-bugswork/tree/main/4254 This is the example run on current master:
This is the example run against this branch (Note FIXED=1 enables case 3 which crashes in master)
|
Rather than having lots of special-case code for CPPDEFINES in four separate routines, add a new _add_cppdefines function to handle it, paying attention to append/prepend, unique/duplicating, and keep-original/replace-original. The existing special case handing was then removed from Append and AppendUnique (it was never present in Prepend and PrependUnique anyway - see SCons#3876, but these now get it due to a call to the new function). Tuple handling is now consistent with list handling: a single tuple is treated as macro names to add, not as a name=value pair. A tuple or list has to be a member of a containing tuple or list to get the macro=value treatment. This *may* affect some existing usage. macro=value tuples without a value can now be entered either in (macro,) form or (macro, None) form. Internally, whenever append/prepend is done, existing contents are forced to a deque, which allows efficient adding at either end without resorting to the tricks the Prepend functions currently do (they still do these tricks, but only in non-CPPDEFINES cases). As a result, values from a dict are not stored as a dict, which has some effect on ordering: values will be *consistently* ordered, but the ones from the dict are no longer necessarily sorted. In SCons/Defaults.py, processDefines no longer sorts a dict it is passed, since Python now preserves dict order. This does not affect the E2E test for CPPDEFINES - since those all call an Append routine, CPPDEFINES will always be a deque, and so processDefines never sees a dict in that case. It could well affect real-life usage - if setup of CPPDEFINES was such that it used to contain a dict with multiple entries, the order might change (sorting would have presented the keys from that dict in alphabetical order). This would lead to a one-time rebuild for actions that change (after that it will remain consistent). In the E2E test CPPDEFINES/append.py some bits were reformatted, and the handler routine now accounts for the type being a deque - since the test does a text comparison of internally produced output, it failed if the word "deque" appeared. Some new test cases were added to also exercise strings with spaces embedded in them. Changes were made to the expected output of the E2E test. These reflect changes in the way data is now stored in CPPDEFINES, and in some cases in order. Most of these do not change the meaning (i.e. "result" changes, but "final" output is the same). These are the exceptions: - "appending a dict to a list-of-2lists", AppendUnique case: order now preserved as entered (previously took the order of the appended dict) - "appending a string to a dict", Append case: not stored as a dict, so ordering is as originally entered. - "appending a dict to a dict", Append case: no longer merge into a dict, so this is now an actual append rather than a merge of dicts which caused the uniquing effect even without calling AppendUnique (arguably the old way was incorrect). A new test/CPPDEFINES/prepend.py is added to test Prepend* cases. append.py and prepend.py are structured to fetch the SConstruct from a fixture file. append.py got an added test in the main text matrix, a string of the macro=value form. The same 5x5 maxtrix is used in the new prepend.py test as well ("expected" values for these had to be added as well). Cosmetically, append and prepend now print their test summary so strings have quotation marks - the "orig" lines in the expected output was adjusted. This change looks like: - orig = FOO, append = FOO + orig = 'FOO', append = 'FOO' The other tests in test/CPPDEFINES got copyright updating and reformatting, but otherwise do not change. Documentation updated to clarify behavior. Fixes SCons#4254 Fixes SCons#3876 Signed-off-by: Mats Wichmann <mats@linux.com>
Signed-off-by: Mats Wichmann <mats@linux.com>
The test output for append and prepend generated tabs, and so the "expected" strings had to contain tab indents. This made Sider on the CI extremely noisy. There's no specific benefit to tabs here, so just change them to spaces. Signed-off-by: Mats Wichmann <mats@linux.com>
Fix a typo Try to further clarify how to add valued macros. Signed-off-by: Mats Wichmann <mats@linux.com>
b709896
to
6ea34c0
Compare
I've pushed a rebase of this (had to force), dealing with Util having been refactored meanwhile. A couple of small changes, plus test expansion to make sure those cases are covered, coming next. Then back to the RELEASE/CHANGES material. |
A few places were deciding what to do based on result of is_List, when the intent was really list-or-tuple-or-derivatives - changed to is_Sequence. Added some test cases, including a unit test for processDefines (which would have caught one of these cases). Signed-off-by: Mats Wichmann <mats@linux.com>
FWIW, this is the output from the current version:
|
So only case 0 is correct? |
Define correct here. If you specifically wanted the output result [('z','case2')]
{'z': 'case2'}
"z=case2" Only your case0 uses one of those three forms. Otherwise, I'm not sure what you're after... the appending is all being handled as I expect now. |
Updated logic to match current behavior when you append a tuple to yield |
…ctionaries to specify CPPDEFINES
The only question mark is, do we change specifying CPPDEFINES initially as a tuple to yield Thoughts? |
RELEASE.txt
Outdated
@@ -17,6 +17,9 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher), | |||
see unexpected rebuilds. This is due to Python internals changing which changed | |||
the signature of a Python Action Function. | |||
|
|||
NOTE: If you use dictionaries to specify your CPPDEFINES, most likely the order of the CPPDEFINES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That note, basically, was already in place. Okay if you think it's helpful to have it at the top as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We always put the "it may rebuild" warnings at the top. to try to minimize the TL;DR issue...
If you're okay with tuple specifically having a different meaning than list - personally, I think that is inconsistent. If so, then some further rework is needed (see below). What do you propose happens if someone tried to Append, say, Rework:
elif SCons.Util.is_List(d) or isinstance(d, tuple):
if len(d) >= 2:
l.append(str(d[0]) + '=' + str(d[1]))
else:
l.append(str(d[0])) |
Attaching the result of running the CPPDEFINES tests as they exist in the PR against a version that changes both the add-single-tuple and the |
Even with the two changes there's still a hole: appending a tuple works as you want, and initializing to a single tuple works (because then |
One more question is what to do with strings - when to split on space and when not. We know a string entry inside a list is promised not to be split, so you can enter entries with spaces (that's not CPPDEFINES specific, of course). But: initial 'FOO BAR=22' without adds -> ['FOO BAR=22'] # initial is not split if never added to
iniitial 'FOO BAR=22' Append ('B', 'DEBUG') -> ['FOO', 'BAR=22', 'B=DEBUG'] # initial has been split
initial None Append 'BAZ B=DEBUG' -> ['BAZ', 'B=DEBUG'] # addition has been split
initial 'FOO BAR=22' Append 'BAZ B=DEBUG' -> ['FOO', 'BAR=22', 'BAZ B=DEBUG'] # initial split, addition has not been split Isn't this fun? |
Seems like a tuple should always defined |
oopsie.. accidently closed. |
If the decision is that's what a tuple is, then it should be consistently so - see my quote from earlier:
|
After the previous proposals, addition of a bare tuple is restored to the valued-macro behavior (this previously did not work consistently). Strings are now consistently split if they contain spaces, except if entered as a list member, in which case (as documented) they are left alone. tuples with nore than two members are now flagged as a UserError; previously the first two members were taken as name=value and any further members were silently ignored. More tests added. Signed-off-by: Mats Wichmann <mats@linux.com>
In a hope to make the tests runnable against a checkout that does not include PR SCons#4263, add some try blocks so the things which used to blow up can generate errors rather than aborting the test run. The prepend test still fails against master. Signed-off-by: Mats Wichmann <mats@linux.com>
…negative test for non-two-tuple. Minor wording change
Added another try block so complete prepend e2e test can be run on a branch where PR SCons#4263 is not applied (for comparison). Added license header. Changed invalid-tuple unittest to use assertRaises (behavior is the same) Also added a versionadded and a versionchanged to docstrings. Signed-off-by: Mats Wichmann <mats@linux.com>
For completeness, tweaked tests slightly so tests can run against master without the changes applied. Such a test run is attached here for comparison (these tests run "clean" on the current PR version): |
oops, spotted that I'd made an error in preparing the Prepend test (copy-paste error, hadn't changed one instance of Append to Prepend), and fixed it... and then didn't remember to go fix the "expected" text. Fix for that forthcoming. |
Signed-off-by: Mats Wichmann <mats@linux.com>
rewording of CHANGES.txt info. Changed versionadded to 4.5.0
Rather than having lots of special-case code for
CPPDEFINES
in four separate routines, add a new_add_cppdefines
function to handle it, paying attention to append/prepend, unique/duplicating, and keep-original/replace-original. The existing special case handing was then removed fromAppend
andAppendUnique
(it was never present inPrepend
andPrependUnique
anyway - see #3876, but these now get it due to a call to the new function).Tuple handling is now consistent with list handling: a single tuple is treated as macro names to add, not as a name=value pair. A tuple or list has to be a member of a containing tuple or list to get the macro=value treatment. This may affect some existing usage. macro=value tuples without a value can now be entered either in
(macro,)
form or(macro, None)
form.Internally, whenever append/prepend is done, existing contents are forced to a deque, which allows efficient adding at either end without resorting to the tricks the Prepend functions currently do (they still do these tricks, but only in non-
CPPDEFINES
cases). As a result, values from a dict are not stored as a dict, which has some effect on ordering: values will be consistently ordered, but the ones from the dict are no longer necessarily sorted.In
SCons/Defaults.py
,processDefines
no longer sorts a dict it is passed, since Python now preserves dict order. This does not affect the E2E test forCPPDEFINES
- since those all call anAppend
routine,CPPDEFINES
will always be a deque, and so processDefines never sees a dict in that case. It could well affect real-life usage - if the setup of CPPDEFINES was such that it used to contain a dict with multiple entries, the order might change (sorting would have presented the keys from that dict in alphabetical order). This would lead to a one-time rebuild for actions that change (after that it will remain consistent).In the E2E test CPPDEFINES/append.py some bits were reformatted, and the handler routine now accounts for the type being a deque - since the test does a text comparison of internally produced output, it failed if the word "deque" appeared. Some new test cases were also added to exercise strings with spaces embedded in them.
Changes were made to the expected output of the E2E test. These reflect changes in the way data is now stored in
CPPDEFINES
, and in some cases in order. Most of these do not change the meaning (i.e. "result" changes, but "final" output is the same). These are the exceptions:"appending a dict to a list-of-2lists",
AppendUnique
case: order now preserved as entered (previously took the order of the appended dict)"appending a string to a dict",
Append
case: not stored as a dict, so ordering is as originally entered."appending a dict to a dict",
Append
case: no longer merge into a dict, so this is now an actual append rather than a merge of dicts which caused the uniquing effect even without callingAppendUnique
(arguably the old way was incorrect).A new
test/CPPDEFINES/prepend.py
is added to testPrepend*
cases.append.py
andprepend.py
are structured to fetch the SConstruct from a fixture file.append.py
got an added test in the main text matrix, a string of the macro=value form. The same 5x5 maxtrix is used in the newprepend.py
test as well ("expected" values for these had to be added as well).Cosmetically, append and prepend now print their test summary so strings have quotation marks - the "orig" lines in the expected output was adjusted. This change looks like:
The other tests in
test/CPPDEFINES
got copyright updating and reformatting, but otherwise do not change.Documentation updated to clarify behavior.
Fixes #4254
Fixes #3876
Signed-off-by: Mats Wichmann mats@linux.com
Contributor Checklist:
CHANGES.txt
(and read theREADME.rst
)