gnuradio/gnuradio — pull request #231 by michaelld (2014-06-23 14:48:46+00:00)
Title: cmake: Boost once

I've been reading through the SWIG stuff, and haven't quite figured out what to do about it. In the meantime, a quick simple set of changes fixes the Boost multi-checking issue. The solution is simple, but the explanation is a bit involved as to why this is the best solution; bear with me:

0) CMake defines variables and values within a given context. By default, each context is the current directory and any subdirectories included by the context's CMake commands. A lower context is a subdirectory of the current directory / context included via "add_subdirectory" (GR gets around this for some subdirectories via a probably fragile CMake hack, to include subdirectories into the same context as the current directory). A higher context is a directory that contains the current directory as a subdirectory.

1) There are 2 primary types of variables in CMake: cached and uncached. Cached variables are available within all contexts once they are declared. Uncached variables are available within the current and all lower contexts once they are declared. Both types of variables can be overwritten in other contexts. An uncached variable, when set in the current context and modified in a lower context, will return to its original setting when back in the current context after returning from the lower context -- so, sort of a temporary overriding in the lower context; if undeclared in the current context but declared in a lower context, once back in the current context it will revert back to being undeclared. A cached variable once set will retain its setting no matter the context, so any change to this variable type impacts future CMake commands no matter the context; but, if overwritten by an uncached variable in a lower context then the change is valid only within that lower context and reverts back to the cached value once back in the current context.

2) The easiest way to accomplish a single Boost check is to do the Boost search at the top context; right now each component does its own Boost search (which is good practice, and should not be removed). Hence, since the Boost variables are not defined in each component's context by default, we have to re-run the Boost checks each time. We could cache the "__INCLUDED_GR_BOOST_CMAKE" variable to try to not have to include GrBoost at the top level, but then we would have to cache all of the BOOST variables. This variable is not currently cached, and because of the arguments below it should not be cached.

3) When not cached -- as Boost variables are not by default -- then for them to be defined in the current context we have to either define them in the current or a higher context, or cache them prior to use.

4) We don't want to cache them, because a lower context might override them -- this is what Volk does -- and then all future contexts would use the new values. Each context needs to be able to set the Boost variables independently of the other contexts, so caching is not the way to go.

5) Hence, we need to define in the top context and not cache, such that they are defined by default in each lower context, but can be independently changed in each lower context.

What fun! - MLD