spacing in -D option in cmake

CMake’s command line parsing is not very consistent or robust unfortunately.

This issue is probably down to the order in which you pass the arguments.

Internally, CMake iterates over the command line arguments twice. The first time it’s looking for non-cache arguments and skips any beginning with -D. Any that don’t fit into the list of proper args are assumed to be the path to the CMakeLists.txt file (or the directory, or the CMakeCache.txt).

It’s assuming that there will be only one path passed, and does nothing to validate that assumption. Herein lies the problem. If you’ve passed -D Foo=1, then -D is seen as a complete argument and is skipped, and Foo=1 is seen as a path.

On the second iteration through the args, it now grabs the values given via -D, but on this run it correctly handles spaces after the -D. So it understands that -D Foo=1 is setting Foo to 1.

So, the position of the path in your command line is all-important here.

cmake -D Foo=1 MyProject/CMakeLists.txt  # --> Works
cmake MyProject/CMakeLists.txt -D Foo=1  # --> Fails

To complicate things further, you can wrap the space in quotes and have CMake parse it, but the variable name then includes the space and is unusable in the CMakeLists file.

cmake MyProject/CMakeLists.txt "-D Foo=1"  # --> Defines the unusable var ${ Foo}

Another inconsistency is that other command line flags work with or without a space (e.g. -G), and others require a space (e.g. -E).

My own advice would be to always avoid adding a space after the flag unless it’s required. I guess always passing the path last would help too, although that shouldn’t be required if you don’t add extra spaces.

Leave a Comment