Very fascinating! I've similarly had to deal with spiraling dependencies in
our local code.
I had two thoughts toward the problems you mentioned below. To handle unique
naming of temporaries, you could do something like introduce a counter
(probably as a global property) and append it to your variable names. In
psuedocode:
RecursingMacro()
# Get Global Property= oNEST
# Increment Global Property = iNEST= NEST+1
# Set Global Property= iNEST
# Use for uniqueness
foreach (depname ${depnames})
set ( ${depname}_DIR_{$iNEST} ...)
...
However, you might not need to do that. You could use functions and then just
store your results in global properties, with a list of their names in a known
property (continuously append the new variable names). Then at the end of the
recursive dependency walk, you can import those properties into variables at
the parent scope.
Anyway, just a thought..
Aaron Meadows
-Original Message-
From: cmake-boun...@cmake.org [mailto:cmake-boun...@cmake.org] On Behalf Of
François Mauger
Sent: Thursday, February 23, 2012 6:11 PM
To: Jean-Christophe Fillion-Robin; cmake@cmake.org
Subject: Re: [CMake] lexical scoping ... back to the future !
On 23/02/2012 02:00, Jean-Christophe Fillion-Robin wrote:
Hi François,
Would the use of function be helpful ?
See
http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:function
and http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:set
If PARENT_SCOPE is present, the variable will be set in the scope
above the current scope. Each new directory or function creates a new scope.
This command will set the value of a variable into the parent
directory or calling function (whichever is applicable to the case at hand).
I created a small example showing that variable set within a function
don't interfere with the parent scope if not explicitly required.
git clone git://gist.github.com/136.git
http://gist.github.com/136.git
cmake -P 136/cmake-illustrate-function-scope.cmake
Hi JC
I've also played around with functions vs macros to check for scoping features
and I have basically written the same test script for my own learning. I agree
that SET coupled with the PARENT_SCOPE directive can solve some scope issues
within function, preserving the very useful ability to have pure local
variables and still making possible for a given variable to be visible ONE
scope level up. The problem is when you need to invoke several find_package
commands from a thread of nested function/macros, eventually with some
recursive pattern.
AFAIU, a find_package() command implies to be invoked from a macro, and not a
function, to preserve the global scoping of the xxx_LIBRARIES and
xxx_INCLUDE_DIRS variables set from a FindXxx.cmake or xxx-config.cmake file,
and thus make them visible at the top-level CMakeLists.txt file for example.
May be I'm wrong and I miss something but it seems other people, trying to
setup a set of homemade macros/functions to traverse automatically a dependency
tree, have also faced this kind of scoping issue.
Because I have to build some complex applications and libraries from a large
set of low-level dedicated home-made libraries that have dependency links
between them (not cyclic of course, but possibly diamond shaped), I've
implemented a basic CMake dependency driver that uses a simple lists of
dependency rules for any new home-made library (let's call it 'xxx') that
depends on some other libraries I have at hand.
from the xxx's top-level CMakeLists.txt, I just have to set:
{{{
SET( xxx_deprules GSL:=1.12;Python:=2.6:=2.7.3;foo:=2.1;bar:=3.2 ) }}}
which means I want to check and use:
- GSL libs with ver =1.12
- Python (interp+libs) with ver in [2.6-2.7.3]
- my home-made foo lib with ver =2.1
- my home-made bar with ver==3.2
and then automatically build some xxx_INCLUDE_DIRS and xxx_LIBRARIES from these
rules.
There is a special set of macros that are given the xxx_deprules list and are
supposed to invoke the 'find_package (...)' command to check if the
dependencies in the list are fulfilled. Then the macros collect/aggregate the
various [GSL|Python|foo|bar]_INCLUDE_DIRS and [GSL|Python|foo|bar]_LIBRARIES
variables. Note that packages like GSL and Python or Boost use typically the
so-called 'Module' find_package mode (FindGSL, FindPythonInterp, FindBoost...)
while my foo and bar package uses the 'Config' mode through well-formatted
foo-config.cmake and bar-config.cmake files.
Note also that because the FindXxx.cmake files provided with the CMake
distribution does not follow a strict pattern and standard (variable names...),
I have to wrap the find Module within some dedicated macros to standardize the
output (examples: Boost_VERSION gives 104700 and not 1.47.0, argh ! ).
So far, so good. Now assume that the foo lib depends also on external libs,
say : 'john' and 'doe