Skip to content

CPPDEFINES handling of tuple arguments inconsistent #4254

@mwichmann

Description

@mwichmann

Filed so this slightly confusing situation is recorded somewhere.

Handling of CPPDEFINES gets some special-casing. In Append and AppendUnique (but not, currently, in the Prepend cousins - see #3876) they get some special handling, and then, along with normal substitution and further processing (*ixes), they get processed by SCons.Defaults.processDefines(). The processDefines call is currently unique to the processing of _CPPDEFFLAGS.

One of the ways you can declare a C preprocessor macro of the form macro=value through CPPDEFINES is to use a tuple of length at least two; the first and second values are then combined by processDefines into that NAME=Value form. Unfortunately, it is not clearly specified whether a single tuple argument should have this effect, or only a tuple that is an element of an iterable, and so it's kind of hard to determine what is expected behavior.

  1. If CPPDEFINES contains a single tuple (for example, by doing an Append to an uninitialized CPPDEFINES, although direct assignment, or initializing in the Environment call would have exactly the same effect), processDefines falls through to its "default" case, which is just to stringify the contents (l = [str(defs)]). Since we now have a single string, the eventual output of having a tuple like ("FOO", 2) is -D('FOO', 2), which is syntactically incorrect for both gcc-style compilers and msvc. We might expect either treating it as a macro=value tuple: -DFOO=2, or as simply an iterable of values just as if it were a list: -DFOO -D2.
  2. If you Append a list value to CPPDEFINES containing a single tuple, the Append routine does some try/except magic and ends up inserting the tuple into the front of the list. Thus, we could have CPPDEFINES = [('FOO', 2), 'BAR', 'BAZ']. processDefines turns this into ['FOO=2', 'BAR', 'BAZ'], and the final expansion is -DFOO=2 -DBAR -DBAZ.
  3. On the other hand, if you try to Append a single string value to CPPDEFINES containing a single tuple, it fails with AttributeError: 'str' object has no attribute 'insert' which is probably a surprise - you asked to "append" and you get a failure on "insert".
  4. If you Append a tuple to any existing value, the macro=value form is assumed. Say we started with CPPDEFINES set to the string value "BAR". After the addition, we have CPPDEFINES = ['BAR', ('FOO', 2)]. processDefines turns this into ['BAR', 'FOO=2'], and as output we get -DBAR -DFOO=2.
  5. Meanwhile, if you AppendUnique to a single tuple CPPDEFINES similar to 2) or 3) it fails with a TypeError. For example, if trying to add a list: TypeError: can only concatenate list (not "tuple") to list.

It's possible that the most "consistent" approach would be to treat a lone tuple as "just an iterable" and not as a special case, and activate the special macro=value handling only if the tuple is seen as an element of an iterable (usually a list). Such a change probably also has the highest chance of affecting existing build systems.

Metadata

Metadata

Assignees

Labels

AppendIssues in Append/Prepend + Unique variants

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions