1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
=================
Automatic Parsers
=================
cmake provides help commands which can print out the usage information for all
of the builtin statements that it supports. You can get a list of commands
with
.. code::
cmake --help-command-list
And you can get the help text for a command with (for example):
.. code::
cmake --help-command add_custom_command
In general (but not always) the usage string is given an a restructured-text
block that looks like this:
.. code::
::
add_custom_command(TARGET <target>
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL])
The syntax of these usage strings isn't 100% consistent but if we could
generate a parser that even understands *most* of these strings then that
would greatly reduce the maintenance load.
--------------
Expect Objects
--------------
The output of the specification parser is an "Expect Tree". A tree of
objects representing what is expected from a statement. If a sequence
of tokens satisfies an expected subtree then the a corresponding parse
tree is generated. If a mandatory expected subtree is not satisfied
then an error is generated. If an optional expected subtree is not
satisfied then the next sibling is tried.
------------
Case studies
------------
Inconsistent usage of angle brackets
====================================
Sometimes mandatory arguments are shown in angle brackets, sometimes not. I
can't really figure a pattern for when they are used and when they are not.
Ellipses
========
Whether or not there is a space between an elipsis and the preceding token
seems to imply something about what is repeated.
::
add_custom_command(TARGET <target>
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL])
Note that the elipsis for "COMMAND" is inside the bracket above, but is
outside the bracket here:
::
add_dependencies(<target> [<target-dependency>]...)
Choices
=======
Pipe character is used to separate choices.
::
configure_file(<input> <output>
[COPYONLY] [ESCAPE_QUOTES] [@ONLY]
[NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
Sometimes it's a mandatory choice
::
ctest_test([BUILD <build-dir>] [APPEND]
[START <start-number>]
[END <end-number>]
[STRIDE <stride-number>]
[EXCLUDE <exclude-regex>]
[INCLUDE <include-regex>]
[EXCLUDE_LABEL <label-exclude-regex>]
[INCLUDE_LABEL <label-include-regex>]
[EXCLUDE_FIXTURE <regex>]
[EXCLUDE_FIXTURE_SETUP <regex>]
[EXCLUDE_FIXTURE_CLEANUP <regex>]
[PARALLEL_LEVEL <level>]
[TEST_LOAD <threshold>]
[SCHEDULE_RANDOM <ON|OFF>]
[STOP_TIME <time-of-day>]
[RETURN_VALUE <result-var>]
[CAPTURE_CMAKE_ERROR <result-var>]
[QUIET]
)
Sometimes the choice is among literals, in which case there are no surrounding
brackets.
::
file(GLOB <variable>
[LIST_DIRECTORIES true|false] [RELATIVE <path>]
[<globbing-expressions>...])
Manditory Sequence
==================
In this case the literal pattern is listed inside the mandatory group pattern
(angle brackets).
::
file(GENERATE OUTPUT output-file
<INPUT input-file|CONTENT content>
[CONDITION expression])
This one is pretty complex, and also demonstrates the nested bracket usage.
I think the indication here is that "you must have one of these choices.
::
get_property(<variable>
<GLOBAL |
DIRECTORY [dir] |
TARGET <target> |
SOURCE <source> |
INSTALL <file> |
TEST <test> |
CACHE <entry> |
VARIABLE>
PROPERTY <name>
[SET | DEFINED | BRIEF_DOCS | FULL_DOCS])
Nested Optionals
================
::
install(TARGETS targets... [EXPORT <export-name>]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
[INCLUDES DESTINATION [<dir> ...]]
)
Multiple Forms
==============
::
string(SUBSTRING <string> <begin> <length> <output variable>)
string(STRIP <string> <output variable>)
string(GENEX_STRIP <input string> <output variable>)
string(COMPARE LESS <string1> <string2> <output variable>)
----------
Conclusion
----------
After implementing a prototype parser and testing it on some of the above cases
it is clear that the help text is not very consistent and is likely to be very
challenging to get an implementation that works reliabily and knows when it
fails. For example:
::
add_custom_command(TARGET <target>
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL])
In this form of the command, the `PRE_BUILD` `PRE_LINK` or `POST_BUILD`
argument is required. Normally it seems like they would put this in angle
brackets as `<PRE_BUILD|PRE_LINK|POST_BUILD>` but they do not. So it's
ambiguous where the pipes are splitting and what the groups are.
|