How to specify the variable which must be set and exist in cmake
Asked Answered
A

3

6

I have a need to have some variable to be specified and exist in the environment. In case it does not exist need to stop building.

example

if ( "${VARMUSTEXIST}" STREQUAL "ON" )
   message(STATUS is ON)
elif ("${VARMUSTEXIST}" STREQUAL "OFF")
   message(STATUS is OFF)
endif()

I don't want to put an if (defined VARMUSTEXIST) everywhere in the script. In bash there is an option for that "set -u".

Arias answered 21/9, 2016 at 9:43 Comment(1)
When dereference, CMake treats all not-defined variables as having empty value. As far as I know, there is no way to affect this behaviour. By the way, simple if(VARMUSTEXIST) will be treated as false if the variable is not defined. Same conditional may be use for select between "ON" and "OFF" - these strings have special meaning for if command.Cordwainer
K
10

Some preliminary points:

  • if ( "${VARMUSTEXIST}" STREQUAL "ON" ) [...] elif(AGAIN LONG EXPRESSION) [...] endif()
    normally in cmake is simply:
    if (VARMUSTEXIST) [...] else() [...] endif()
  • The command if (DEFINED VARMUSTEXIST) requires DEFINED to be upper case.
  • You mention bash and environment variables:
    Environment variables are read using $ENV{VARIABLE_NAME}
  • For environment variables you will do:

    if(NOT DEFINED ENV{VARMUSTEXIST})
        message(FATAL_ERROR "You must set VARMUSTEXIST environment variable")
    endif()
    

You say:

I don't want to put an if (defined VARMUSTEXIST) everywhere in the script

This is not clear to me: for each variable you need to check only once, possibly in the main CMakeLists.txt. Of course, you need to add NOT: if (NOT DEFINED VARMUSTEXIST) [stop]

If you can be more precise on your problem, we can design a macro that checks if one or a group of variables are defined or not.

Komatik answered 21/9, 2016 at 12:50 Comment(3)
The idea to have a macro at the beginning of the cmake script to check a list of variable is really good, but it fails to catch the case where a developer does a mistake and misspells the variable name. Cmake will silently continue. What I would like to do is the telling cmake that when reading the value of a variable it should always check if the variable is defined and fail if it isn't. For compatibility there must be away to enable this option only for the current cmake-file, otherwise it won't be possible to include existing cmake-file without breaking them.Arias
As for bash, I only mentioned it because of the feature enforcing that all variable must be defined. As an example the following bash script will cause an error: #!/bin/bash set -u VAR=Y echo ${VA} It would be cool to have the possibility to write something like: cmake_policy (SET READ_UNDEFINED_VARIABLES OFF) message (STATUS ${VA}) where the message line will now fail. One could still use if (DEFINED VA) to check for existence before using it.Arias
@D.Alex About the developer misspelling risk, the exact same issue was raised a few years ago, see here. Unfortunately, there's no workaround. Maybe you want to issue a feature request (Note that even in C there's a workaround). By the way, policies, which are introduced for backward compatibility, are not suitable for this purpose. See doc.Komatik
R
4

I think this is the best approach...

CMake Variable:

if(NOT DEFINED VARIABLE)
    message(FATAL_ERROR "VARIABLE is not set")
endif(NOT DEFINED VARIABLE)

Environment Variable:

if(NOT DEFINED ENV{VARIABLE})
    message(FATAL_ERROR "VARIABLE is not set")
endif(NOT DEFINED ENV{VARIABLE})
Relativize answered 12/3, 2022 at 0:55 Comment(0)
P
1

If by environment you mean OS environment variables then the syntax is wrong anyway.

If those are options to be provided by the user, then the literal comparisons with ON and OFF are incorrect, since CMake has more ways to express booleans and they are all in widespread use and became idiomatic. Thus, by expecting either ON or OFF, you're making your build script weird and against everyone's expectations. And you're also making more work for yourself, as you've noticed.

First, you should document the options and give them safe default values using option(). Then it won't ever be that a variable could be undefined.

# early in the top-level CMakeLists.txt
option(VARMUSTEXIST "You can provide it. It exists anyway." NO)

And then you'll check its truth or falsehood rather simply:

# later in top-level file or in subdirectories
if (VARMUSTEXIST)
   message("VARMUSTEXIST is true")
else()
   message("VARMUSTEXIST is false")
endif()
Peasant answered 26/6, 2020 at 22:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.