[CMake] Where is QT_USE_IMPORTED_TARGETS not safe to use?

Alexander Neundorf a.neundorf-work at gmx.net
Wed Jun 22 15:13:28 EDT 2011


On Wednesday 22 June 2011, Stephen Kelly wrote:
> Hi Alex, thanks for the more detailed explanation. It is indeed more clear.
> 
> However, I still don't think there is a linker error if I omit
> QT_USE_IMPORTED_TARGETS from the config file. I tried to re-create the
> error condition with a trivial project and could not re-create it.

Right.
Now after actually having a look at FindQt4.cmake, it's clear. There is:

    IF(QT_USE_IMPORTED_TARGETS)
        SET(QT_${basename}_LIBRARY       Qt4::${_camelCaseBasename} )
        SET(QT_${basename}_LIBRARIES     Qt4::${_camelCaseBasename} )
    ELSE(QT_USE_IMPORTED_TARGETS)


So, the targets are always created, but only if QT_USE_IMPORTED_TARGETS is set 
to TRUE, the variables like QT4_QTCORE_LIBRARY are set to use these targets 
instead of the paths.
So, it should be completely safe to have the imported targets as dependencies 
in your GrantleeTargets.cmake file.
 
> Alexander Neundorf wrote:
> >> IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG "Qt4::QtCore"
> > 
> > The statement above has the effect than when a user of Grantlee in a his
> > project named Foo links against the Grantlee library, it will
> > additionally link against "Qt4::QtCore".
> > 
> > If there is no target (imported or "normal", this doesn't matter) with
> > that name in the project Foo, then "Qt4::QtCore" is considered a direct
> > parameter for the linker and cmake will append (under Linux) a
> > "-lQt4::QtCore to the linker command line.
> > Which would be wrong.
> > 
> > So for that to work correctly, an imported target with the name
> > "Qt4::QtCore" must be created somewhere in the project Foo.
> > Typically by FindQt4, which should then create these imported targets.
> 
> "Qt4::QtCore" seems to be defined as an import unconditionally in FindQt4.
> Well, almost uncondiditionally. qmake has to be found, and it has to be
> either debug or release mode, but it doesn't look like FindQt4 is very
> useful if either case is false anyway.
> 
> So this works just fine:
> 
> $ cat CMakeLists.txt main.cpp
> 
> cmake_minimum_required(VERSION 2.8)
> 
> project(cmdline)
> 
> find_package(Qt4 REQUIRED QtCore )
> 
> INCLUDE_DIRECTORIES(${QT_INCLUDE_DIR})
> 
> 
> add_executable(cmdline
>   main.cpp
> )
> 
> target_link_libraries(cmdline
>   Qt4::QtCore
> )
> 
> #include <QtCore/QCoreApplication>
> 
> int main(int argc, char **argv)
> {
>   QCoreApplication app(argc, argv);
> 
>   return app.exec();
> }
> 
> 
> That example seems to indicate to me that even if using
> set(QT_USE_IMPORTED_TARGETS 1) in the Config file is the right thing to do
> and I should do it anyway, it won't cause a linker error if I leave it out.
> 
> Is there some way I can modify that example to re-create the linker error
> described in the comment?

Well, if simply the path is used, FindQt4.cmake does not have to be executed 
before.
If imported targets are used, FindQt4.cmake has to be executed before (or at 
least at some point), otherwise nobody creates the imported targets 
(independent from the USE_IMPORTED_TARGETS switch).

I think that's all.

> > You can still test in e.g. GrantleeConfig.cmake whether the target
> > Qt4::QtCore exists and fail with FATAL_ERROR if it doesn't.
> > 
> > I strongly recommend using these imported targets, one reason is because
> > otherwise when installing a binary package of Grantlee under Windows, it
> > will not be possible to freely choose the install location, or better the
> > location where Qt must be is then already hardcoded in
> > GrantLeeConfig.cmake (because then there won't be "Qt4::QtCore" in
> > GrantleeConfig.cmake, but something like
> > "c:/where/was/Qt/at/buildtime/QtCore.dll"). When then linking against
> > Grantleee, and Qt is installed somewhere else, it will fail.
> 
> Yes, this makes sense. I think that's something we almost covered in the
> review in Randa :). I am adding the setter to use the imported target
> feature so it will be in the next release, but I also want to understand it

What setter ?
I think you can simply use the exported targets.

Alex


More information about the CMake mailing list