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

Nicolas Desprès nicolas.despres at gmail.com
Fri Apr 20 09:27:58 EDT 2012


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


More information about the CMake mailing list