[Cmake] variables set in SUBDIRS() available to top-level CMakeList?

Zachary Pincus zpincus at stanford.edu
Tue, 13 Apr 2004 20:45:02 -0700


First, disregard my previous email. The issues involved were more 
complex that I thought.

Unfortunately, it appears that using CACHE variables is not a perfect 
way to pass information back from CMakeLists called via SUBDIRS.

This is because the top-level CMakeList is *completely* executed before 
any commands from the directories in SUBDIRS are executed.

Thus, the following construction will not work:

SUBDIRS(foo bar baz)
# where the CMakeLists in foo, bar, baz modify CACHE_VAR
DO_SOMETHING(${CACHE_VAR})

because DO_SOMETHING gets called *before* the CMakeLists from the sub 
directories are even called! So using cached variables isn't really 
optimal for this kind of communication.

OK, you say, we'll just have to run the configure process twice: once 
to get the variables in the cache from foo, bar, baz, etc, and then 
once so that DO_SOMETHING actually works.

A ha -- a problem: the second time things execute, DO_SOMETHING gets 
the version of the cached variables that existed after the end of the 
first run (which is what we wanted in the first place) *but* the cached 
variables are then operated on *again* by foo, bar, etc. If each of the 
CMakeLists in these directories appends values (say) to CACHE_VAR, then 
after the end of the second configuration, CACHE_VAR is too long. And 
it grows out of control with subsequent configure runs.

A solution? Clear the cache var at the end of the top-level CMakeList. 
Then we just have to run configure twice, and everything works fine 
after that. Right, BUT, doing such a thing doesn't work as you would 
expect (see my companion email about this odd behavior). But even if 
that bug (or whatever) is resolved, this is still a very ugly way of 
doing things.

Any thoughts on a clean way to propagate information from CMakeLists 
called in SUBDIRS commands to the top-level CMakeLists?

Zach Pincus

Department of Biochemistry and Program in Biomedical Informatics
Stanford University School of Medicine

On Apr 13, 2004, at 7:03 PM, Zachary Pincus wrote:

> Bill, thanks for your reply.
>
> I'm trying to collect a list of values (generated by CMakeLists in 
> each subdirectory) into a single cache variable that then gets 
> processed by the top-level CMakeList.
>
> I've run into one difficulty here:
>
> First, CACHE variables are retained between cmake configuration runs. 
> So if I have each CMakeLists in each subdirectory append a value to a 
> single cache variable, then each time I re-configure, that variable 
> grows longer and longer.
>
> This is of course totally reasonable. However, it isn't the behavior I 
> want, so I tried something like this:
>
> SET(Accumulator "")
> SUBDIRS(foo bar baz)
>
> where the CMakeLists in foo, bar, and baz all add information to the 
> end of Accumulator.
>
> This breaks everything: now "Accumulator" gets cleared after EACH 
> subdir is processed.
> Why does CMAKE appear to be running the SET(Accumulator "") after each 
> subdir is processed?
> Is there any way to circumvent this behavior, and only clear the 
> variable ONCE each configuration run?
>
> Thanks,
>
> Zach Pincus
>
> Department of Biochemistry and Program in Biomedical Informatics
> Stanford University School of Medicine
>
> On Apr 13, 2004, at 5:40 AM, William A. Hoffman wrote:
>
>> Subdir variables and commands do not affect the parent directories.
>> In the hello example, it sets the directories for the whole project at
>> the top.   You could and should only set the include directories where
>> they are needed.  The only way to pass information up to a parent 
>> directory
>> is via CACHE variables which once set are available to the entire 
>> project.
>>
>> -Bill
>>
>>
>> At 03:29 PM 4/9/2004, Zachary Pincus wrote:
>>> Hello,
>>>
>>> If a CMakeLists file called via SUBDIRS(...) sets some variables, 
>>> are these available to commands in the top-level file?
>>>
>>> For example, I have a simple project which builds a library and an 
>>> executable.
>>>
>>> Top Level CMakeLists:
>>> PROJECT(foo)
>>> SUBDIRS(./lib)
>>> ...
>>>
>>> Lib CMakeLists:
>>> INCLUDE_DIRECTORIES(./headers)
>>>
>>> So, will commands in the top level cmakelists subsequent to the 
>>> subdirs() call be able to see the INCLUDE_DIRECTORIES set in the 
>>> lower-level cmakelist? If so, will the relative path be properly 
>>> translated, or would I have to be more careful in setting the 
>>> address as relative to the upper-level project root? (Is there a way 
>>> to get the path to the current directory, relative to the project 
>>> root, from cmake?)
>>>
>>> I ask this because doing things this way seems more robust than the 
>>> method here:
>>> http://cmake.org/HTML/Examples.html
>>> where one sets the INCLUDE_DIRECTORIES for the headers in the 
>>> "hello" directory NOT in the "hello" CMakeLists file, but in a 
>>> CMakeLists outside of the "hello" directory. It seems like it would 
>>> be nicer to set every variable relevant to a given directory in that 
>>> directory's CMakeLists file, so that changes to a directory 
>>> structure necessitate editing only one CMakeLists file.
>>>
>>> Thanks,
>>>
>>> Zach Pincus
>>>
>>> Department of Biochemistry and Program in Biomedical Informatics
>>> Stanford University School of Medicine
>>>
>>> _______________________________________________
>>> Cmake mailing list
>>> Cmake at www.cmake.org
>>> http://www.cmake.org/mailman/listinfo/cmake
>>
>> _______________________________________________
>> Cmake mailing list
>> Cmake at www.cmake.org
>> http://www.cmake.org/mailman/listinfo/cmake
>>
>
> _______________________________________________
> Cmake mailing list
> Cmake at www.cmake.org
> http://www.cmake.org/mailman/listinfo/cmake
>