Please update extra-cmake-modules, kdelibs (and plasma-frameworks)

Alexander Neundorf neundorf at kde.org
Mon Mar 4 18:21:22 UTC 2013


Hi,

back from the weekend...

On Friday 01 March 2013, Stephen Kelly wrote:
> Alexander Neundorf wrote:
> > On Thursday 28 February 2013, David Faure wrote:
> > ...
> > 
> >> ... which means it will also fail at link time, not at cmake time.
> >> So I don't see the point in this change. I'd must rather write
> >> KF5::Solid than ${Solid_LIBRARIES}, where I can never remember if
> >> that's LIBRARY or LIBRARIES, and Solid or SOLID, and where such
> >> variables come from, etc. They look like an unnecessary additional
> >> layer on top...
> > 
> > Yes, they are an additional layer on top.
> 
> An *unnecessary* additional layer :).
> 
> One reason I prefer the target names is that it simplifies debugging by
> removing an unnecessary layer. When I see
> 
>  target_link_libraries(user ${FOO_LIBRARIES})
> 
> and something is wrong, the first thing I have to do is
> 
>  message("FOO_LIBRARIES: ${FOO_LIBRARIES}")
> 
> to see what is hidden inside. Please let's not hide things unnecessarily.
> 
> If instead it is
> 
>  target_link_libraries(user Foo2::foowidgets Foo3::foonetwork )
> 
> I can skip the 'remove an unnecessary layer' step and go directly to step
> two.
> 
> > For all KF5-libraries, the names are <ExactCaseName>_LIBRARIES.
> 
> And the targets are all KF5::<ExactCaseName>. Following a pattern doesn't
> proove usefulness one way or the other.
> 
> I agree with David here and Brad on the CMake list that using namespaced
> imported target names is better. I wish you hadn't made the change to use
> variables like that, but now we at least have the topic in discussion.
> 
> I suggest that we have consensus (yes, it's not unanimous) that we should
> use target names and imported target names instead.
> 
> We're already using imported target names for Qt targets in some of the
> cases. Please don't replace those with variables. Let's finish the job in
> the direction of using imported targets instead.
>
> We're also using target names in many cases for in-build targets. Please
> don't wrap any more of those in variables either.

In case it's not obvious: inside kdelibs, there is, in the current state, for 
technical reasons no other option than using variables. So we do not have to 
discuss that at all.

Currently, kdelibs can be built all together as one, or, alternatively, 
kdeqtstaging and all libraries in tier1/ and tier2/ can be built also 
separately (*1).
The targets have different names when used in-project vs. when using as 
imported targets ("KCoreAddons" vs. KF5::KCoreAddons").
So by converting all uses of libraries which are already in tier1/ or tier2/ 
to use variables, those places have already been prepared for their move to 
tier[123]/.


I also would like to get a concensus on what to  use, that's why I posted this 
issue here.
I don't think it is KDE style to reach concensus by forcing the majority vote 
on the maintainer and just dismiss his arguments.

Until last week I was undecided, now that I worked more with them and thought 
more about it I see more advantages for using variables than for target names 
directly. If you can convince me that they are not valid, fine.


So here are the pro's and con's I see for imported targets:

Pro's 

* It makes the imported targets more visible, so cmake users will learn faster 
about them. This is a good thing.




Con's

* Using imported target names directly extends the scope of cmake source 
compatibility. Anything which makes more stuff significant for compatibility 
is bad, e.g. that's why we have d-pointers in C++.
By using the target names directly, the scope of cmake source compatiblity 
extends from the variables which are defined in a Find-module or a 
Config.cmake file, to also include the names of the targets in the used 
project. So that additional layer is useful.

* First sentences from the documentation of find_package():
"Finds and loads settings from an external project. ... When the package is 
found package-specific information is provided through variables documented by 
the package itself."
So the public interface of find_package() *is* the set of variables it 
defines. Simply put, by using variables, we use the interface as defined by 
find_package(), while by using target names, we ignore the defined interface 
and use string literals, independent from any find_package() call.
So that additional layer is not only useful, but actually the documented way 
how to use the results from find_package().

* By using variables, the way to use find_package() stays the same. This is 
good. Requiring users to learn something new is not good if there is no good 
reason for it.

* For the naming of variables which hold the result of a find_package()-call 
there are strong recommendations (I don't dare to say standard, but I could), 
see readme.txt, for naming targets there aren't.
So if you do 
find_package(Something)
if the Find-module or Config.cmake file follows the recommendations, the 
result of a successful find_package() call will be ${Something_INCLUDE_DIRS} 
and ${Something_LIBRARIES}. There are a few variations from that, like the 
same but ALLUPPERCASE, and using _INCLUDES or _LIBS. Those together cover 
probably over 90 percent of the existing Find-modules.
All packages coming from KF5 will follow the recommendations, many others 
follow them too or at least closely.
There are ZERO recommendations how a developer should names his targets in 
relation to the Config.cmake file he will install, and there are ZERO 
recommendations how he should call the namespace. There is not even an 
official recommendation to use a namespace at all when exporting.
So from find_package(SomeLib) you cannot even guess what the name of the 
imported target will be (looking beyond KF5 and Qt5), it may be "Some::Lib", 
or "somelib", or "some" or anything else.
So, this is not "following a pattern or not", this is more basically whether 
some kind of standard for naming those things exists, it does for variables, 
it does not for targets and namespaces.

* By using imported target names, there is the chance to add a second meaning 
to the error message "ld: cannot find -lsolid". This is not desirable.
I have talked with many people who like or dislike CMake in the last 7 years, 
those that dislike it find enough issues they complain about, I don't think it 
is necessary to add another one which they can use to ridicule cmake "CMake, 
the buildsystem that makes up library names to confuse its users". This is not 
necessary, I don't know why this should be our preferred option.

* If we stay with the convention as defined by the find_package() 
documentation, whenever a developer sees e.g. a
target_link_libraries(... ${Stream_LIBRARIES})
, he can assume that there is somewhere a find_package(Stream) call. This is 
good. If there is instead
target_link_libraries(... stream)
there is no indication whether this is an in-project target or an imported 
target, or whether it's just the name of the library and happened to work on 
the original developers machine because it was installed in a standard 
location. So I see an advantage here too for using variables.

* Since currently it must be variables inside kdelibs, it would be somewhat 
inconsistent and maybe confusing for our developers to do it differently in 
plasma-frameworks. This may be a temporary situation, but it is what we 
currently have and which will last for a few months more.



Neither option is more "elegant" or "pretty" or requires significantly more 
typing or anything like that, so that doesn't matter.

The only real strong, forcing argument in that whole list is that currently in 
kdelibs it must be variables, all others are much weaker, on both sides, I 
know that.



I respect David a lot, but in this regard I consider his opinion as the 
opinion of a KF5 developer who wants to have a buildsystem as convenient as 
possible for him when working on KF5.

This is an important POV, but not the only one, and for me not the most 
important one.
There is also the POV of a cmake expert (e.g. Brad and Stephen), the POV of 
somebody who just wants to build some package he downloaded, and the POV of a 
developer using cmake with basic cmake knowledge (most developers, including 
KDE developers). All of them are important (maybe the cmake expert not so 
much, because I assume that a cmake expert will figure it out anyway).
I try to take all those into account when coming to conclusions. E.g. 
redefining the meaning of a well-known error message is definitely not a good 
point IMO from the POV of a non-CMake expert, and it's good if this can be 
avoided.


I could start repeating things like "code is read much more often than 
written", or point to the "Convenience Trap" ( http://qt-project.org/wiki/API-
Design-Principles ).
My main points I want to achieve in the buildsystem are:
* it shall be as easy to read and understand as possible. This is very 
different from "it shall require very little work from the developer". It 
includes trying to make things explicit and visible, sometimes preferring a 
local copy (which an app maintainer may dare to modify) over a shared file he 
will never touch, and often involves more typing instead of less.

* it shall be usable as an example for projects outside KDE which look around 
for how cmake should be used (that's why it doesn't matter that in KF5, all 
exported targets have the same prefix and the library has the same name as the 
package. This is simply irrelevant for other projects).



Alex

--

(*1) Ok, variables are not the only existing option, but the only viable 
option. Other alternatives are e.g.

- using something like target_link_libraries(... ${KF5PREFIX}KCoreAddons )
but I don't see where this would be better
- using only the in-project targets, and have only the all-in-one build 
working until the one day where we make the big switch, and from then on 
everything can be built separately and only separately, but this is IMO not 
feasible, at least I don't want to work in such a way, stuff will be broken 
for quite some time, while being able to have both ways working in parallel 
makes for a smooth transition


More information about the Kde-frameworks-devel mailing list