[CMake] Disabling Argument Parsing in CMake -P Scripts
Eskandar Ensafi
Ensafi at SpaceComputer.Com
Fri Nov 2 17:44:38 EDT 2012
I'm not sure if I'm qualified to propose a patch, but I will look at the source code to see what I can come up with. I have additional concerns about the way the CMAKE_ARGVn variables are initialized, and this might be a good time to address these concerns.
I don't know if this was a design choice, but with some exceptions, CMake seems to first parse the entire command-line, and then it runs each -P script in order, with CMAKE_ARGC/ARGVn initialized to the entire command-line, not just the arguments following the appropriate -P script. When the command-line is parsed, some recognized options are removed (e.g. -L[A][H], -N) with no ill effect, others are removed but interfere with the initialization of CMAKE_ARGC/ARGVn (e.g. --help, --version, and all variants), and some are parsed but NOT removed (e.g. -D name:type=value, -G generator, contrary to comments in my previous e-mail). A more robust treatment of these command-line arguments would be to fail with an error if incompatible combinations of options are detected, and if any options are recognized and parsed by CMake, they should be removed from the command-line. Parsing errors should cause to CMake to exit with an error, but this is not consistent (-G fails given a bogus generator, but -D with a badly formed argument allows CMake to continue).
To demonstrate, take the following simple example:
# MyScript.cmake
MESSAGE(">>> BEGIN SCRIPT >>>")
IF (DEFINED MyVar)
MESSAGE("MyVar = ${MyVar}")
ENDIF()
MESSAGE("CMAKE_ARGC = ${CMAKE_ARGC}")
MATH(EXPR ARGC "${CMAKE_ARGC} - 1")
FOREACH(I RANGE 0 ${ARGC})
MESSAGE("CMAKE_ARGV${I} = ${CMAKE_ARGV${I}}")
ENDFOREACH()
MESSAGE("<<< END SCRIPT <<<")
Then run it as follows:
cmake -P MyScript.cmake testing -DMyVar=Test one two three -P MyScript.cmake four five six
>>> BEGIN SCRIPT >>>
CMAKE_ARGC = 13
CMAKE_ARGV0 = cmake
CMAKE_ARGV1 = -P
CMAKE_ARGV2 = MyScript.cmake
CMAKE_ARGV3 = testing
CMAKE_ARGV4 = -DMyVar=Test
CMAKE_ARGV5 = one
CMAKE_ARGV6 = two
CMAKE_ARGV7 = three
CMAKE_ARGV8 = -P
CMAKE_ARGV9 = MyScript.cmake
CMAKE_ARGV10 = four
CMAKE_ARGV11 = five
CMAKE_ARGV12 = six
<<< END SCRIPT <<<
>>> BEGIN SCRIPT >>>
MyVar = Test
CMAKE_ARGC = 13
CMAKE_ARGV0 = cmake
CMAKE_ARGV1 = -P
CMAKE_ARGV2 = MyScript.cmake
CMAKE_ARGV3 = testing
CMAKE_ARGV4 = -DMyVar=Test
CMAKE_ARGV5 = one
CMAKE_ARGV6 = two
CMAKE_ARGV7 = three
CMAKE_ARGV8 = -P
CMAKE_ARGV9 = MyScript.cmake
CMAKE_ARGV10 = four
CMAKE_ARGV11 = five
CMAKE_ARGV12 = six
<<< END SCRIPT <<<
Notice how the entire command-line, including intervening -P options and the parsed -D option, is made available to both scripts (i.e. they are both executed with the same CMAKE_ARGC/ARGVn even though CMAKE_ARGV7 was the last argument for the first script, and CMAKE_ARGV10 to CMAKE_ARGV12 were the arguments for the second script). This may or may not be useful, but to avoid breaking compatibility, I propose defining something like CMAKE_ARGC_FIRST and CMAKE_ARGC_LAST in each -P script invocation so that we can determine the range of options specific to the script being executed.
Now, if we deliberately introduce an error in the -D flag as follows:
cmake -P MyScript.cmake testing -DMyVar one two three -P MyScript.cmake four five six
Then CMake will run the first script, and it will exit with an error when it tries to parse -DMyVar (missing value).
Since implementing a "--" option will require some changes to CMake's command-line parsing logic, I suggest that we fix the aforementioned issues as part of this effort. Again, I am not the best person to undertake this effort due to my lack of familiarity with the CMake code base, but if someone with more experience would like to collaborate with me, I would be more than happy to help.
Best,
Eskandar
On Nov 2, 2012, at 2:45 AM, David Cole wrote:
> "--" for script mode is a good idea. (Actually, if we had this for
> non-script mode even, it would then make sense to expose the command
> line arguments in similar variables even when configuring a CMakeLists
> file. Presently, the CMAKE_ARGVn vars are only available in script
> mode.)
>
> Can you propose a patch?
>
> If so, open a feature request in the bug tracker, and attach a "git
> format-patch -1" file.
>
> Thanks,
> David
>
>
> On Fri, Nov 2, 2012 at 12:21 AM, Eskandar Ensafi
> <Ensafi at spacecomputer.com> wrote:
>> Hello,
>>
>> I often find it very useful to run CMake scripts of the form "cmake -P script-name arg1 arg2 ..." as a cross-platform scripting solution that doesn't rely on Perl, Python, etc. One major limitation is that CMake continues to parse all arguments after the script name. For example, if arg1 is "-i" then CMake will enter wizard mode before executing the script, and options such as "-D", "-G" and "-L" will be parsed and removed from the command-line by CMake. The current behavior limits the flexibility of CMake's script mode by making it impossible to pass arbitrary options to be parsed directly by the script.
>>
>> It would be great if I could somehow specify "cmake -P script-name -- arg1 arg2 ..." to tell CMake to stop parsing all subsequent arguments while still placing arg1, arg2, etc. in the CMAKE_ARGVn variables. If the "--" flag is potentially problematic and may pose compatibility problems, perhaps another syntax can be adopted, such as "cmake -PP script-name arg1 arg2 ..." where -P is doubled.
>>
>> Is this something that can be easily implemented?
>>
>> Best,
>>
>> Eskandar
>> --
>>
>> 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
More information about the CMake
mailing list