[CMake] Suggesting to FindQT4.cmake where to find QT4

Clinton Stimpson clinton at elemtech.com
Fri May 29 10:24:27 EDT 2009


Adolfo Rodríguez wrote:
> On Fri, May 29, 2009 at 5:48 AM, Clinton Stimpson 
> <clinton at elemtech.com <mailto:clinton at elemtech.com>> wrote:
>
>     Jed Brown wrote:
>
>         Alexander Neundorf wrote:
>          
>
>             On Monday 25 May 2009, Jed Brown wrote:
>                
>
>                 Bill Hoffman wrote:
>                      
>
>                     You can also set QMake on the cmake command line
>                     as well:
>
>                     cmake -DQT_QMAKE_EXECUTABLE=/path/to/qmake ../source
>                            
>
>                 Yeah, I'm much less concerned with this particular
>                 case as with the
>                 philosophy that the correct way to select
>                 installations is by modifying
>                 PATH.  Frustratingly, a new user will fire up cmake
>                 and get the wrong
>                 version (they're not even aware of exactly what the
>                 dependencies are,
>                 let alone the naming convention for the cache variable
>                 that will get the
>                 correct version).  So they interactively change a
>                 couple paths and
>                 reconfigure.  Lo and behold, they now have an
>                 inconsistent state because
>                 the cache wasn't flushed when they changed
>                 QT_QMAKE_EXECUTABLE (I don't
>                 know if this is the case with Qt, but is is with most
>                 packages).
>                      
>
>             ...
>                
>
>                 Using PATH and falling back on peculiarly named
>                 variables (hopefully
>                 only one non-advanced variable per package, so that
>                 it's unambiguous)
>                      
>
>             With the new cmake-gui this is now much easier :-)
>                
>
>
>         CMake gui is nice and it's easier to edit variables.  For this
>         case, I
>         think the only way it makes a difference is that you can go to
>         advanced
>         grouped mode and wipe out a whole group easily.  Some packages
>         have
>         dependencies, so this isn't a complete solution, but it does
>         make a big
>         difference.  I wrote the following before noticing that it was
>         easy to
>         clear groups, but I think it's still somewhat relevant.
>
>
>         The user doesn't know the name of special variables (like
>         QT_QMAKE_EXECUTABLE) until they press Configure.  If the wrong
>         version
>         is found on the first pass, it's typically too late to change
>         the path.
>         (There isn't a concept of dependent cache variables so very
>         few Find*
>         modules can clean up after an incorrect version is found.
>          There is an
>         implicit assumpition that if *any* installation is found, it
>         is the one
>         the user wanted.  FindQt4 might be a very rare exception to
>         this.  I
>         haven't tested its robustness since I don't use it, but I see
>         a lot of
>         QT_QMAKE_CHANGED logic so the author is at least trying to
>         handle this.)
>
>         So they have to flush the cache and define the special
>         variable *before*
>         CMake shows them that the variable exists.  Until packages can
>         robustly
>         support changing their path *after* the first pass finds an
>         undesired
>         version, I think that recognizing semi-standard environment
>         variables
>         like QTDIR would be good policy (e.g. the user is much more
>         likely to
>         guess QTDIR than QT_QMAKE_EXECUTABLE if they are unfamiliar
>         with CMake
>         and only know that the your package needs Qt).
>          
>
>     I don't think of QTDIR as anything of a standard anymore.  It was
>     necessary in Qt3 to make the qmake build system work.
>     Anyway...  read below.
>
>             Also, instead of setting PATH to /opt/qt-a.b.c/bin/ you
>             can also set CMAKE_PREFIX_PATH to /opt/qt-a.b.c/, also to
>             a list of directories, which cmake will search in the
>             order you specified.
>                
>
>
>         I know about these, but they have global scope and are thus not a
>         solution to the problem I stated.  You need to be able to specify
>         install paths *independently*.  As a concrete example, suppose
>         different
>         versions of MPI are installed at /usr and /usr/local.  Similarly,
>         suppose different versions of Qt are installed at /usr and
>         /usr/local.
>         I'm not claiming this is the best organization, but it's not
>         terribly
>         uncommon or pathological, so some users will have this
>         situation and
>         it's none of our business to tell them to reinstall just to
>         build our
>         package.
>
>         Qt and MPI are independent packages so their selection cannot be
>         dependent.  Modifying variables like PATH or CMAKE_PREFIX_PATH
>         will
>         choose versions for both of these packages.  FindMPI.cmake
>         cannot be set
>         independently, so if I wanted to get MPI from /usr, I have to
>         put /usr
>         first in PATH/CMAKE_PREFIX_PATH.  A new user will not know this in
>         advance.  To get Qt from /usr/local, I can set
>         QT_QMAKE_EXECUTABLE, but
>         a new user won't know this before running CMake (gui) and
>         looking at the
>         options.  If they are lucky, they will get the correct MPI on
>         the first
>         pass, and although the incorrect Qt is found, they can change
>         QT_QMAKE_EXECUTABLE and the QT_QMAKE_CHANGED logic will work
>         correctly
>         to give them a consistent build.  If the wrong MPI is found,
>         they have
>         no choice but to delete the cache, modify some global state
>         (PATH or
>         similar) and try again.  Note that very few Find* modules can
>         recover
>         from finding an incorrect package (it takes a lot of work, you
>         basically
>         have to work around the cache).  In addition, not many have a
>         single
>         variable to control which installation is found, thus
>         necessitating
>         global control which creates the locking problem.
>
>          
>
>     I think what is being asked here is a good idea.
>     There is already the CMAKE_PREFIX_PATH which gives
>     find_package(Qt4) a prefix to work from.
>     If I set it to one of my other Qt4, directories, it finds that Qt
>     installation fine.
>     But maybe adding something like a
>     QT4_PREFIX_PATH to have find_package(Qt4) prefer another directory
>     first
>     and
>     MPI_PREFIX_PATH to have find_package(MPI) prefer yet a different
>     directory
>     would be nice.
>
>     Maybe even extend that so if one did
>     find_program(MYVAR_EXECUTABLE ...)
>     find_library(MYVAR_LIBRARY ...)
>     a user of a CMakeLists.txt file containing that could set
>     MYVAR_PREFIX_PATH.
>
>     Or maybe use MYVAR_DIR so the same variable works when cmake
>     config files are found by find_package().
>
>     Maybe another step would be to detect if MYVAR_DIR changed, and
>     remove all dependent variables and do a re-find.
>
>     I see that FindBoost.cmake has a BOOST_ROOT that tries to do the
>     above, but a standard mechanism for all find_* would be better.
>     Or does cmake already have a standard way of doing this?
>
>
> This link [1] suggests that the correct name for the variable should 
> be QT$_ROOT_DIR (instead of QT4_PREFIX_PATH or QT4_ROOT)
>
> [1] 
> http://public.kitware.com/cgi-bin/viewcvs.cgi/Modules/readme.txt?root=CMake&view=markup 
> <http://public.kitware.com/cgi-bin/viewcvs.cgi/Modules/readme.txt?root=CMake&view=markup>
>
> I do something like this when looking for simple packages (thanks to 
> Greg Peele for a cool tip on this):
>
> # Get hint from environment variable (if any)
> if(DEFINED ENV{FOO_ROOT_DIR})
>   set(FOO_ROOT_DIR "$ENV{FOO_ROOT_DIR}" CACHE PATH "FOO base directory 
> location (optional, used for nonstandard installation paths)" FORCE)
>   mark_as_advanced(FOO_ROOT_DIR)
> endif()
>
> # Search path for nonstandard locations
> if(FOO_ROOT_DIR)
>   set(FOO_INCLUDE_PATH PATHS ${FOO_ROOT_DIR}/include NO_DEFAULT_PATH)
>   set(FOO_LIBRARY_PATH PATHS ${FOO_ROOT_DIR}/lib NO_DEFAULT_PATH)
> endif()
>
> # Find headers and libraries
> find_path(FOO_INCLUDE_DIR NAMES foo/FOO.h ${FOO_INCLUDE_PATH})
> find_library(FOO_LIBRARY NAMES FOO ${FOO_LIBRARY_PATH})
>
> ... then you can use FindPackageHandleStandardArgs or whatever you 
> like the most.
>
> I know that FindQT4 is a _lot_ more complicated than this, but anyway, 
> I find the FOO_ROOT_DIR (env. or cmake) variable very useful.
>

Yes, that's doable right now.
But, I was actually hoping for something that worked automatic like 
CMAKE_PREFIX_PATH.
Not something extra people have to code into their Find*.cmake files or 
extra things they have to do with their find_* calls.
Also, I was thinking of a cmake variable, not an environment variable.

Clint




More information about the CMake mailing list