Is there a when once command for cmake files?

Does anyone know of an easy way to apply the "include once" pattern in CMake files? In C / C ++, the beginning and end of the header file required a # ifdef / # endif pair until #pragma became normal. You can of course do the same thing in CMake, but I thought it would be nice if it didn't require an explicit conditional statement.

Re-edition : It seems that the return () command should do this. And I would define a macro like this:

macro(include_once)
  if (INCLUDED_${CMAKE_CURRENT_LIST_FILE})
    return()
  endif()
  set(INCLUDED_${CMAKE_CURRENT_LIST_FILE} true)
endmacro()

      

Use the macro at the beginning of the file without any arguments. Since this is a macro, the return is from the include command for the file, not from the macro itself.

Note that the variable created has an odd name, but CMake seems to accept that.

+3


source to share


1 answer


The simplest pattern of protection against multiple module inclusion would be

if(<something-which-is-defined-in-your-module>)
    return()
endif()

      

For example, if your CMake module defines a function foo_func

, you can use this defender:

if(COMMAND foo_func)
    return()
endif()

      


Do you really need a guard?



Depending on the things defined in the module, the module may require the protection to re-enable multiple activation or not.

In many simple cases, protection is not needed: the module code will work even if it is included multiple times.

But in some other cases, improper protection can disrupt the use of the protected module.

  • The module defines a function or macro : no protection required .

    CMake allows you to redefine functions and macros.

  • The module defines a variable constant : no protection required .

    Like a function, CMake allows you to redefine a variable.

    But if you use defensive code in this case, it should check the variable , not the function:

    if(foo_var)
        return()
    endif()
    
          

    This is because functions have global visibility, but variables have local visibility. That is, if the module is included in another subtree, the function will already be visible in that subtree, but the variable is not.

  • The module defines a global variable via set(CACHE)

    : protection is needed only if the variable is defined as set(CACHE INTERNAL)

    .

    Variables defined with, for example, set(CACHE STRING)

    or find_library

    do not require protection.

  • The module defines a global property : protection is needed .

Please note that if your module uses a simple (non-CACHE) variable as global, it cannot work across multiple subtrees, so the protection must be

    if(foo_var)
        message(SEND_ERROR "Module <...> cannot be included twice")
    endif()

      

+3


source







All Articles