Add a means of finishing command line arguments processing
When invoking cmake in script mode, it often helps to be able to pass arbitrary arguments after the script name, so that the script could emulate some other command that doesn't have a cmake-compatible argument syntax. E.g. suppose that a cmake script was a wrapper for a compiler, then it might be invoked as
cmake -P myscript.cmake -Iinclude -Ddefine -Wall -o foo.o -c foo.c
Right now, cmake will run the list file (e.g. a script) as soon as it has read its name, and the list file will see all the command line arguments in CMAKE_ARGVn
variables - whether they are allowed by cmake or not. So far so good. But as soon as the list file is done, cmake will resume processing the arguments - and will bail out with a fatal error, since those arguments are not proper cmake arguments.
I propose the following solutions, and will implement the desired one ASAP as I need this functionality myself:
-
Support the rather common
--
switch to mean: Ignore any further arguments. Those arguments are available to the script (in any mode), but the argument processing stops immediately. The above command line would then become:cmake -P myscript.cmake -- -Iinclude -Ddefine -Wall -o foo.o -c foo.c
The script could then easily detect where it should start parsing arguments:
set(arg_n 0) function(next_arg) ... next_arg() while(NOT arg STREQUAL "--") next_arg() endwhile()
cmake::SetCacheArgs
andcmake::SetArgs
would be modified as follows:void cmake::SetArgs(const std::vector<std::string>& args) { ... for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (arg == "--") break; ... bool cmake::SetCacheArgs(const std::vector<std::string>& args) { ... for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (arg == "--") break; ...
Does this introduce any backwards-compatibility concerns? The argument would be naturally ignored in the sub-argument parsing, i.e. if
-foo
takes an option,-foo --
would work as it used to, without assigning any meaning to--
. The only way I see it being problematic would be if someone had a build script named--
. Perhaps we could name this switch----
to avoid any ambiguity. -
Allow the scripts to modify the
CMAKE_ARGN
andCMAKE_ARGVn
, with a policy that enables the changes to be fed back to the command argument processor in older cmake versions. This makes it backwards-compatible. It'd be the most intrusive change, as it'd have to modify theSetArgs
andSetCacheArgs
flow. Obviously, only the changes to arguments past the argument that triggered the execution of a given list file would be taken into account. SettingARGN
to a value smaller or equal than the argument that triggered the execution of the list file will automatically finish processing the argument list.CMAKE_ARGP
variable would be used to indicate the index of the argument that triggered the execution of the current list file. Its modification would be a developer warning, since it'd make no sense to move the "current argument" pointer. -
Expand the
return()
command to include optional argumentFINISH
, allowed in any mode at topmost scope, i.e. wherever areturn()
would finish processing the outermost list file. When present, no further command line arguments are processed. This has the problem that the arguments would still be processed bySetArgs
and could have unintended side effects. A developer warning is issued ifreturn(FINISH)
is used in the wrong scope.cmReturnCommand
would set a flag in the current state that would then interruptSetCacheArgs
.
If anyone has better ideas, I'd love to hear them and again: I'd like to implement it right away, so as not to waste anyone's time.