[CMake] Add --help-option command line option.

David Cole david.cole at kitware.com
Fri Apr 20 09:57:52 EDT 2012


2012/4/20 Nicolas Desprès <nicolas.despres at gmail.com>:
> 2012/4/20 Eric Noulard <eric.noulard at gmail.com>:
>> Le 20 avril 2012 13:40, Nicolas Desprès <nicolas.despres at gmail.com> a écrit :
>>> 2012/4/20 Eric Noulard <eric.noulard at gmail.com>:
>>>> Le 20 avril 2012 10:44, Nicolas Desprès <nicolas.despres at gmail.com> a écrit :
>>>>> Hi,
>>>>>
>>>>> I would like to have your opinion before to start to implement it.
>>>>>
>>>>> I would like to add the following options to the cmake command line interface:
>>>>> --help-option opt [file]   = Print help for a given option and exit.
>>>>> --help-option-list [file]  = List available options and exit.
>>>>> --help-options [file]      = Print help for all options and exit.
>>>>>
>>>>> The goal is to have access to the project build options from the
>>>>> command line interface like you can see them in ccmake and cmake-gui.
>>>>> Advanced variable will be marked as such, of course. The output will
>>>>> be similar to --help-variable* options.
>>>>>
>>>>> I have noticed that most cmake based projects document their options
>>>>> in their README file whereas the documentation is already included in
>>>>> cmake when you call the option() and set() commands. I hope this
>>>>> feature will help to remove this duplication and people will just
>>>>> write in their README file a "see cmake --help-options for available
>>>>> build options".
>>>>>
>>>>> Comments?
>>>>
>>>> I think that Enabling/Designing some way to document user written CMake scripts
>>>> is a very interesting goal.
>>>>
>>>
>>> Thanks.
>>>
>>>> I started doing something along that line using basic markup, which has been
>>>> used to improve CPack documentation (--help-variable and
>>>> --help-command) in 2.8.8.
>>>> see: http://www.cmake.org/Bug/bug_relationship_graph.php?bug_id=10067
>>> Thanks for the pointer. Indeed, it is nice piece of work.
>>>>
>>>> My approach does not need to actually "parse" CMake script but only to
>>>> catch comment line blocks.
>>>> I say that because the problem with options is that
>>>> you may need to parse **AND EVALUATE** some CMake script code
>>>> in order to know whether if the OPTION is active or not.
>>>>
>>>> See e.g.
>>>> cmake --help-module CMakeDependentOption
>>>
>>> Thanks for the pointer. I was not aware of this module.
>>>
>>>>
>>>> So how would grab the documentation from OPTION or CMAKE_DEPENDENT_OPTION?
>>>>
>>>> 1a) Read out the provided CMake [file]  and custom parse  OPTION  and
>>>> CMAKE_DEPENDENT_OPTION ?
>>>> (possibly disregarding the control flow like OPTION inside IF(WIN32),
>>>> IF(APPLE) etc...) ?
>>>>
>>>> 1b) Evaluate the CMakeLists.txt as ccmake and make-gui do?
>>>>
>>>> 2) Would you also handle "INCLUDE" and handle OPTION find in there as well?
>>>>
>>>> I think that a full parse (as done by ccmake and/or cmake-gui) is not
>>>> easy at all.
>>>> I'd suggest to parse OPTION (and CMAKE_DEPENDENT_OPTION) found in any
>>>> CMakeLists.txt recursively, beginning with the one given on the command line,
>>>> i.e. 1a) + recursion without 2).
>>>>
>>>> The main problem with this approach (be it recursive or not) is that you may
>>>> list options which are platform dependent and/or conditionally evaluated.
>>>>
>>>> Another way to go is to require an extra ##option markup (in any
>>>> script including CMakeLists.txt)
>>>> that could be placed anywhere but ideally just before the real
>>>> "OPTION/CMAKE_DEPENDENT_OPTION" statement.
>>>> That way you can parse it the way I did for CPack doc without the need
>>>> for any kind of CMake
>>>> script evaluation.
>>>> I know this duplicate the "comment" somehow, but it would give to the
>>>> developer a mean to
>>>> have more control concerning what is shown and what is not shown in
>>>> terms of documentation.
>>>>
>>>> Using this scheme we can imagine some "unified" way to get user doc
>>>> from user file (CMakeLists.txt or any *.cmake):
>>>>
>>>> --help-user-list <file>  --> list any user documented item from file
>>>> (variable, command/macro, option, property etc...)
>>>> --help-user <file>       --> dump all user doc whatever the category
>>>>
>>>> we can imagine some way to filter out the category we want
>>>>
>>>> --help-user-list <file> option
>>>> --help-user <file> option <optionname>
>>>> --help-user <file> variable <varname>
>>>>
>>>> etc...
>>>>
>>>
>>> First of all thanks for replying. Although, that's an interesting
>>> approach, I find it quite complex. Actually, I haven't dug into the
>>> source code yet but what I had in mind was to basically/naively do the
>>> same job that is done by ccmake and cmake-gui. I think (I haven't
>>> checked yet) the code is already factored in some way, so I could just
>>> call the right functions.
>>
>> If you go this way then calling:
>> cmake --help-option-list CMakeLists.txt
>
> I would have say: cmake --help-option-list <builddir> like when you call ccmake.
>
>>
>> will begin the configuration work which does not seem wise if you
>> simply want to list some help.
>>
>> I wouldn't personally expect to get some side effect from --help-xxxx.
>>
>
> We can name the command line option differently if it is problem.
> --build-option-list for instance.
>
>>> That's said. Maybe ccmake and cmake-gui have some issues I am not
>>> aware of and your approach try to address them.
>>
>> They don't have issue they do not do the same task.
>> ccmake and cmake-gui (just like cmake) do **PROCESS**
>> the CMakeLists.txt scripts so that when you push 'c' or 'configure'
>> cache **file** gets populatedd, any configure_file is done etc...
>
> Ok. From my understanding, they all do the same job but with a
> different user interface:
> * cmake: command line
> * ccmake: curses
> * cmake-gui: gui
>
> As you have spotted below cmake differs from the others since it does
> the configuration and the generation each time it is called.
>
>>
>> at least ALL the default case CMakeLists.txt is interpreted.
>
> I agree.
>
>>
>> none of the current  cmake --help-xxxx have any side-effect.
>
> Ok. So, we can name the option differently.
>
>>
>>> One thing I forgot to mention in my first email is the handling of
>>> variables marked as red in cmake-gui and with a * in ccmake. Honestly,
>>> I have never really understood the logic behind this feature, but
>>> again I think all that code is factored.
>>
>> ccmake and cmake-gui do a "one time" evaluation of all CMakeLists.txt hierarchy
>> but do not generate (unlike cmake command) the generator files
>> (Makefile, project files etc...).
>> Before that they offer you a chance to further chose "option" or set values for
>> some variables (CMAKE_INSTALL_PREFIX) etc...
>>
>> Then if you do mmodify something using the GUI/TUI you can hit
>> 'c/configure' again.
>> Each time you "configure" ccmake or cmake-gui shows you the "newly
>> created variables",
>> which is useful to know because for example after the first run you
>> ticked an extra option
>> which triggers the discovery of some program or file etc...which
>> translates into a new
>> CMake variable you can spot easily.
>>
>> As you already guess on the "configure" when you start ccmake/cmake-gui from
>> an empty cache/build dir you get an "all red/all starred" var on subsequent call
>> only new vars get displayed this way.
>>
>> I personally think you cannot implement some "--help-whatever" option
>> that could possibly
>> populate (even partially) the build tree, so that building
>> "--help-whatever" on top on
>> current functions implemented for ccmake or cmake-gui is a clear no GO.
>>
>> (as an explanation why it would be bad, for example bash completion
>>  for cmake uses --help-xxx a lot in order to offer completion
>>  see: http://www.cmake.org/Bug/view.php?id=13056)
>>
>> That's my own point of view, but I expect others will give their
>> opinion as well.
>
> Ok. Thank you for the clarification. You have spotted interesting
> points I did not really think about and mentioned in my first email.
>
> My main goal is to add to cmake the same features you have in ccmake
> and cmake-gui and to ease the users to find out the interesting option
> they have to pass to cmake without duplicating the documentation which
> is already written in the CMakeLists.txt and the .cmake files. Also
> that will provide something more or less similar as what you get with
> configure --help when it is generated by autoconf.
>
> First, let's forget about naming the options --help-XXX since as you
> have said they have side effects and could not be used in completion
> scripts. Here the workflow, I have in mind:
>
> $ cd myproject
> $ mkdir _build
> $ cd _build
> $ cmake --build-options ..
> # The configuration and generation is performed.
> # All the options and their value (including the advanced one? maybe
> an extra argument would be necessary here?) are printed and marked
> with a * like in ccmake.
> $ cmake --build-options .
> # The configuration and generation is performed.
> # All the options and their value (including the advanced one? maybe
> an extra argument would be necessary here?) are printed without the *.
>
> Now the users know they have to at least set CMAKE_BUILD_TYPE and
> CMAKE_INSTALL_PREFIX for instance:
>
> $ cmake -DCMAKE_BUILD_TYPE=Release
> -DCMAKE_INSTALL_PREFIX="$HOME/usr/stow/myproject" .
> # The configuration and generation is performed.
>
> I think you get the idea. This approach does not change the current
> behavior of cmake.
>
> Another approach, if we want to mimic more ccmake and cmake-gui, would
> be to add --configure and --generate flags. They should be used only
> when one of the --build-option* flag is present, in order to keep the
> default current behavior. The behavior of --configure and --generate
> would be the same as pushing respectively the "configure" and
> "generate" button in cmake-gui. So, the workflow will look like:
>
> $ cd myproject
> $ mkdir _build
> $ cd _build
> $ cmake --build-options .
> CMake Error: The source directory "/home/despre_n/open-src/cmake/_b"
> does not appear to contain CMakeLists.txt.
> Specify --help for usage, or press the help button on the CMake GUI.
> $ cmake --build-options ..
> Empty cache.
> Please configure first by specifying --configure.
> $ cmake --build-options --configure ..
> [...]
> -- Configuring done
> Build options available in this project:
> (* mark newly created variables ; you can set this options using the -D flag)
>
> FOO*:BOOL=''
>       Foo documentation
> CMAKE_BUILD_TYPE*:STRING=''
>       Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
> CMAKE_C_FLAGS are used)
>       Debug Release RelWithDebInfo MinSizeRel
> $ cmake -DCMAKE_BUILD_TYPE=Debug --build-options .
> Build options available in this project:
> (* mark newly created variables ; you can set this options using the -D flag)
>
> FOO*:BOOL=''
>       Foo documentation
> CMAKE_BUILD_TYPE*:STRING='Debug'
>       Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
> CMAKE_C_FLAGS are used)
>       Debug Release RelWithDebInfo MinSizeRel
> $ cmake --configure .
> [...]
> -- Configuring done
> $ cmake --build-options .
> Build options available in this project:
> (* mark newly created variables ; you can set this options using the -D flag)
>
> FOO:BOOL=''
>       Foo documentation
> CMAKE_BUILD_TYPE:STRING='Debug'
>       Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
> CMAKE_C_FLAGS are used)
>       Debug Release RelWithDebInfo MinSizeRel
> $ cmake --generate .
> -- Generating done
> -- Build files have been written to: <path to the build directory>
>
> What do you think of these approaches?
>
> --
> Nicolas Desprès
> --
>
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake


Don't spend too much effort/time on this without gathering a good
consensus first, because I think we'll be unlikely to accept a patch
that simply documents every darn thing under the sun. Only the
project-specific things should be documented in project-specific help.

These are good ideas, but the problem that we've identified and never
figured out a good way around is that you'll end up with incomplete
project documentation in this manner. Think about how options and
variable set commands may be hidden inside if/else constructs that do
not get processed, or subdirectories that are completely optional and
do not get traversed. (We've had verbal discussions about this very
thing for YEARS now... not sure if there are any mailing list
discussions on archive about it.)

In my opinion, it would be better to have a mode of processing the
CMakeLists files that gathers the relevant documentation strings from
ALL occurrences of set, option and any other commands that have doc
strings attached to them, for ALL POSSIBLE cmake code paths, and then
cache the documentation after doing such processing. That is a
completely different beast than the processor that we currently have
in place, but it would produce complete project documentation.

Another alternative would be to have projects specify their own help
in a yet-to-be-invented form, and then be able to reference that help
from the various set and option commands throughout their CMakeLists
files. Perhaps a ProjectHelp.cmake file, with certain variables set in
it, those variables indicating what other variables to document, such
file to be included in the CMakeLists file? That would be better, in
my opinion, because it would allow project authors to filter out stuff
that they DON'T want documented.


HTH,
David


More information about the CMake mailing list