[cmake-developers] conditionals in generator expressions
Stephen Kelly
steveire at gmail.com
Thu Aug 30 04:33:02 EDT 2012
Brad King wrote:
> On 08/29/2012 09:25 AM, Brad King wrote:
>>> I've pushed a generator-expression-refactor branch to my clone. It needs
>>> some clean-up, de-duplication etc, but I'm looking for feedback on the
>>> approach.
>>>
>>> In my branch, all parameters must be separated by ','. All commas and
>>> colons must appear literally in the expression. This makes escaping
>>> not-needed, and multiple-parameter-separators consistent accross all
>>> generators.
>>
>> Great. I'll take a look when I get a chance.
>
> That looks like a good start. Pre-parsing the entire expression tree
> is the right approach.
>
> While quoting/escaping expanded values is not needed we still need
> it for the input, like STREQUAL comparing to "," for example.
The first solution that comes to mind within the current implementation is a
<COMMA> or similar.
Reading on...
>
> When we first designed generator expressions it was just for the
> basic "$<TARGET_FILE:tgt>"-type expressions. The format for target
> names was restricted so we didn't need to think about handling
> arbitrary content. The $<0:...> and $<1:...> expressions can
> have arbitrary content other than ">" but they always have exactly
> one "parameter" so there is no real parsing involved.
>
> When I mentioned the "$<RANGLE>" expression it was just as an example
> of what the current approach can do (a better name might be ANGLE-R).
> However, now that you're writing a real lexer/parser we need to think
> about how this new mini-language will work syntactically. There should
> be no need for $<ANGLE-R> if we have proper quoting rules. Consider
> bash syntax like
>
> echo $(echo 'nested command with )')
>
> where the quoting protects the close-parenthesis inside $(...) syntax.
> In order to allow more readable inputs we could consider allowing
> arbitrary whitespace to separate arguments, as in:
>
> $<STREQUAL "$<TARGET_PROPERTY:TYPE>"
> "EXECUTABLE">
>
> just like the CMake language itself. If quoting is parsed as part
> of the syntax then it can be used for '>' too e.g.
>
> $<STREQUAL "a" ">">
>
> where quoting protects argument contents as in bash.
Other examples:
$<STREQUAL "a" " ">
$<STREQUAL "a" "\"">
Which looks like a fairly 'normal' escaping scheme from a c++ point of view.
However, the problem is that these generator expressions are in strings
already. Which means we'll have this:
set_target_properties(foolib
PROPERTIES INCLUDE_DIRECTORIES
"$<$<STREQUAL \"a b\" \"\\\",\"> \"/bar bat/bag\">"
)
because that set_target_properties signature can only take one argument
(there are other bug reports about this I think, but I don't recall if it's
changable).
I don't think it's very readable.
In my branch it would be this instead:
set_target_properties(foolib
PROPERTIES INCLUDE_DIRECTORIES
"$<$<STREQUAL:a b,\"$<COMMA>>:/bar bat/bag>"
)
which is also not perfect, but is better.
In the case of:
set_property(TARGET foolib
[APPEND] PROPERTY INCLUDE_DIRECTORIES
$<$<STREQUAL "a" "\""> "/bar bat/bag">
)
it will create a list of strings. So the const char *input to the generator
expression will contain a ';' separated list of strings.
>
> One way to distinguish expressions with free-form arguments from
> those without is whether there is a ':' or whitespace after the
> expression name.
I don't think that benefits readability.
So the options are either:
1) Require the use of $<ANGLE-R> or $<COMMA> inside generator expressions
2) Introduce proper quoting rules. I don't think the current proposal for
that is readable enough to be beneficial, but with a different
parsing/quoting scheme not based on whitespace and "\"", it might be
workable.
I think that (1) is cheap and worth it. One unfortunate place where it
doesn't fit and where $<COMMA> would have to be broadly used would be this:
set_target_properties(foolib
PROPERTIES COMPILE_OPTIONS
"$<$<CONFIG:Debug>:-Wl$<COMMA>no-undefined>"
)
That is fixable if we choose a different parameter separation character (and
port $<AND> and $<OR> to it too).
Colon is not an option because it makes the language more confusing, and
would require a $<COLON>, which would need to be broadly used to escape
'Qt5::Core' etc.
Looking at my keyboard, how about '?' '|' '\'' '#' or '*'?
$<AND:$<STREQUAL:a*b>*$<TARGET_PROPERTY:TYPE*EXECUTABLE>>
$<AND:$<STREQUAL:a|b>|$<TARGET_PROPERTY:TYPE|EXECUTABLE>>
$<AND:$<STREQUAL:a'b>'$<TARGET_PROPERTY:TYPE'EXECUTABLE>>
$<AND:$<STREQUAL:a#b>#$<TARGET_PROPERTY:TYPE#EXECUTABLE>>
$<AND:$<STREQUAL:a?b>?$<TARGET_PROPERTY:TYPE?EXECUTABLE>>
I prefer '*' because '?' doesn't stand out enough and :a?b seems wrong.
'|' means OR more strongly to me than '*' would mean multiply in this
context, and stands out well.
'#' might work too, but I think it would be parsed as a comment if the whole
expression was not surrounded in quotes?
Thanks,
Steve.
More information about the cmake-developers
mailing list