find_package inside function: scope issue

Hi,

I’m wrapping some calls to find_package inside functions. The issue is that the variables set by find_package are not visible to the parent scope and I don’t know the list of this variables (so I cannot use set with PARENT_SCOPE option.

It would be difficult for me to convert the function to a macro as I’ve got some return() statements.

How can I do to forward these variables to the parent scope?

Regards,
A.

From what I know, find_package call essentially works like include - so it’s just adds code to the current scope and executes it. So basically the question is how to propagate function variable to parent scope without specifying it explicitly.
Unfortunately, I don’t think there’s a way to do it, besides using a macro and making code more nested to remove the need for return() statements.

There is a hack for avoiding return() in macros: if none of your return() statements is nested inside a loop, you can add an outermost one-iteration loop around the entire code of the macro, and then use break() with the same effect as return() from a function would have. Example:

function(foo)
  do_stuff()
  if(${stopEarly})
    return()
  endif()
  do_more()
endfunction()

# Can become:

macro(foo)
  foreach(dummy IN ITEMS 1)
    do_stuff()
    if(${stopEarly})
      break()
    endif()
    do_more()
  endforeach()
endmacro()

If you decide to go this route, I suggest document it well.

1 Like

Not quite what you asked, but I recommend that ideally you should not use any variables a package might define, relying instead only on the targets and commands it defines. Commands are global, and targets created by find_package() are visible at least in the current directory scope and below (they might also be global depending on whether the GLOBAL keyword was given or the CMAKE_FIND_PACKAGE_TARGETS_GLOBAL variable is set to true).

If you follow the above recommendation, then your project likely won’t care whether the find_package() call was made inside a function or other variable scope (like block() / end block()). I say “likely won’t care” because a package might define a non-cache variable outside of a function, expecting that variable to be available to that function’s implementation. But since functions are global, they could be called from any scope, including scopes where that variable isn’t visible. I consider such variables to be a bug in the package.

1 Like