[cmake-developers] Recommended use of imported targets...

Alexander Neundorf neundorf at kde.org
Wed Feb 27 16:37:19 EST 2013


Hi,

in old-style cmake, you do

find_package(Foo)

...
target_link_libraries(hello ... ${FOO_LIBRARIES} )

If Foo was not found, and you forgot to check for it, you get:

CMake Error: The following variables are used in this project, but they are 
set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake 
files:
FOO_LIBRARIES
    linked by target "hello" in directory /home/alex/src/tests/cmakelink



This is a good error message and you get it at cmake time.

If you make a typo:
target_link_libraries(hello ... ${FOOX_LIBRARIES} )

the variable will most likely be empty and you'll get "undefined references to 
...whatever" when linking, which is a strong hint that some library is 
missing.



Now to new-style cmake usage with imported targets:


find_package(Foo NO_MODULE REQUIRED)
...
target_link_libraries(hello ... foox )


Here the user used the imported target directly, but made a typo.
Now he'll get at link time: "ld: cannot find -lfoox"

This looks like there should be a library libfoox.so somewhere, but is not.
So in this regards cmake failed, if the configure run of cmake ended 
successfully, this should be more or less the guarantee that everything that's 
needed, including libraries are available.


I see a problem here.
If we recommend to use imported targets directly, those errors will become 
relatively common. People forget the "REQUIRED", or make typos, or the 
imported targets are renamed. There is no chance to detect that from cmake.


Two ideas: 
1) we should continue to recommend to use the variables (which will now be set 
to the name of the target). In case of typos, this will lead to an empty 
variable (as it did before with Find-modules), and undefined references when 
linking. This is at least no regression.
Also, it shields users somewhat from potential renaming of the imported 
targets. This should not happen, but who knows. (I just renamed targets in 
kdelibs, and they were referenced directly by name in a using project, so I 
got the "cannot find -lfoo" errors).


2) tll() can basically only guess whether some string "foo" is a library, so 
"-l" has to be added or whether it is a target. Without imported targets this 
is relatively safe, since all targets are defined within the project, so in a 
quite narrow scope, and it is in the hand of the developer to use the correct 
names from within the project. Now when more and more targets will be 
imported, many things, influenced by those external packages, can go wrong.
Having to mark strings explicitely as targets (and not as file paths or 
library names) would solve this.
safe_target_link_libraries(hello TARGET:foox
                                 FILE:/opt/lib/libbar.a
                                 LIBRARY:png)
(I didn't want to start with this again, but I'm afraid this leads back to the 
"use a completely new command for using all the target properties")



So, I'm afraid that in two years from now when there will be a lot of 
exporting and importing targets going on, getting failures like above "ld: 
cannot find -lKF5::KArchive" will be common, and the resulting errors will be 
cryptic to users.
I think this is something we really should try to avoid, since this would kind 
of defeat the purpose of the configure run (finding out reliable facts about 
the current system).

If we'll rely a lot on imported targets in the future, let's make them as 
robust and easy-to-debug as possible.

Comments ?

Alex



More information about the cmake-developers mailing list