[cmake-developers] Generator options per-directory v. global
Stephen Kelly
steveire at gmail.com
Wed Oct 5 18:38:18 EDT 2016
Brad King wrote:
> On 10/04/2016 05:46 PM, Stephen Kelly wrote:
>> This causes problems because now the code has to read the value for each
>> directory and can't assume that the value is always the same as the value
>> from the top-level CMakeLists file.
>
> Many of these are honored only in the top-level directory anyway.
Some do...
src/cmake$ git grep -c -e Makefiles --and -e "\[0\]"
Source/cmGlobalGenerator.cxx:6
Source/cmGlobalUnixMakefileGenerator3.cxx:1
Source/cmake.cxx:1
src/cmake$ git grep -c -e LocalGenerators --and -e "\[0\]"
Source/cmExtraEclipseCDT4Generator.cxx:4
Source/cmExtraKateGenerator.cxx:1
Source/cmGlobalGenerator.cxx:1
Source/cmGlobalKdevelopGenerator.cxx:1
Source/cmGlobalNinjaGenerator.cxx:10
Source/cmGlobalUnixMakefileGenerator3.cxx:6
Source/cmGlobalVisualStudioGenerator.cxx:2
Source/cmLocalNinjaGenerator.cxx:1
Source/cmake.cxx:1
... but it is far more common for generate-time code to just get the closest
cmMakefile and call GetDefinition on it.
> Such cases could have documentation updated.
>
> Some of them may be per-`project()`.
CMake doesn't have an appropriately scoped data for that, AFAIK (touched on
below).
>> Is the answer 'Use global properties or a cache variable instead'?
>
> The options need to be something easy for the project to set itself
> or for a user to set.
> A cache entry can work for that, but we don't
> really often read cache entries directly and instead read variables
> that fall back to cache entries if not defined.
Yes, my suggestion is that this can be problematic.
> The scoping doesn't
> match the generator semantics exactly, but it is easy to use and
> hasn't been a big problem.
My mail is suggesting that it is a problem and is undesirable to maintain.
Big is subjective, and there are not many complaints, because generally
people don't try to set things like this per-directory (and if they did it
would probably mostly do what they expect).
The problems are
1) It is a behavior which is often not intended by the programmer.
2) It makes refactoring harder if such unintended behavior must be
preserved.
3) It is unintuitive, because code such as
set(FOO ON)
project(p)
add_library(bar ...)
set(FOO OFF)
looks like FOO is ON when defining the project and the target, but in
reality it is only the value at the end of the directory that is consumed.
Those are not problems users or contributors adding features encounter, so
that might affect a perception of 'big'ness. These problems only bubble up
during refactoring or under longer-term maintenance when the true semantics
of the code become known.
The suggestion to use the first cmMakefile for these kinds of definitions is
a good one
1) It can be documented that the variable can only be set in the top level
2) It is what people already do probably
3) It is more convenient than the API for setting cache or global properties
In this CODELITE case, I can't intuitively understand where the value will
come from in the case of a tree of directories, some of which contain
project() and others which don't, others which contain multiple project()
calls, and where the project() may appear in between add_subdirectory()
calls.
I can't read the code and know that, because I know how subtle the
projectMap stuff and the vector of cmLocalGenerator* is.
I think code such as
set(CMAKE_CODELITE_USE_TARGETS ON)
will be ignored if it occurs in a directory which does not contain a
project(). I might be wrong though, and there may be other semantics of the
code as written which are unexpected.
Should CMAKE_CODELITE_USE_TARGETS be changed to be 'global' and use
something like the result of gg->GetMakefiles()[0]->GetDefinition() and
should that be the model for how to access these kinds of settings in the
future?
cmGlobalGenerator could gain a GetGlobalSetting() for that purpose.
Thanks,
Steve.
More information about the cmake-developers
mailing list