View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0011868CMakeCMakepublic2011-02-16 13:582011-06-17 18:26
Reporterhkrishna 
Assigned ToClinton Stimpson 
PrioritynormalSeveritymajorReproducibilityalways
StatusclosedResolutionfixed 
PlatformAppleOSMac OS XOS Version10.5
Product VersionCMake 2.8.3 
Target VersionCMake 2.8.5Fixed in VersionCMake 2.8.5 
Summary0011868: FindQt4 and framework v. non-framework
DescriptionHi All,

I was trying to build the VisIt software package on my Mac OSX 1.5 . This package uses Qt 4.6.1 during its build. I ran into an issue where the QtCore path finds my globally installed version of Qt (4.7) as apposed to the Qt (4.6.1) installed by VisIt.

While digging around I found that FIND_PATH (code included below) in FindQt4.cmake is pulling information from the system path and assigning this value to the QT_QTCORE_INCLUDE_DIR. This is causing a build failure where the rest of the QT headers are using 4.6.1 and QtCore is using version 4.7.

The value in ${qt_headers} points to the correct 4.6.1 location yet FIND_PATH does not use this parameter. Adding NO_CMAKE_SYSTEM_PATH finds the proper path.

I believe this might indicate a bug in FIND_PATH because according to the CMAKE documentation on FIND_PATH (http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:find_path [^]) the HINTS option is number three in the search order and the system path is number five.

     _qt4_query_qmake(QT_INSTALL_HEADERS qt_headers)
     SET(QT_QTCORE_INCLUDE_DIR NOTFOUND)
     FIND_PATH(QT_QTCORE_INCLUDE_DIR QtCore
               HINTS ${qt_headers}
               ${QT_LIBRARY_DIR}/QtCore.framework/Headers
               PATH_SUFFIXES QtCore
       )
Steps To ReproduceWill try to make a simpler test to reproduce this error.
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0025452)
Brad King (manager)
2011-02-16 16:19

The code

  SET(QT_QTCORE_INCLUDE_DIR NOTFOUND)

is not necessarily enough to make sure the search runs again. It only sets the local CMake variable but the command also checks whether the CMakeCache.txt entry is present. You need to use

  UNSET(QT_QTCORE_INCLUDE_DIR CACHE)
  FIND_PATH(QT_QTCORE_INCLUDE_DIR ...)

to ensure the search runs every time you test.
(0025453)
hkrishna (reporter)
2011-02-16 16:59

Hi,

Thanks for looking into the matter.

The UNSET operation is good to know, but every time the QT_QTCORE_INCLUDE_DIR is set the path it finds is the incorrect one. I make sure to remove CMakeCache.txt before I rerun cmake and then check to see if CMakeCache.txt has a correct output. Unfortunately the path cmake finds is incorrect.

Ideally, if the solution was to edit FindQt4.cmake to resolve this issue. I would prefer this to be handled by the developers.

To me it seems odd that when FIND_PATH is given a path under HINTS the function picks the QT library in the system path ahead of the HINTS parameter. A few solutions I have been able to find include adding NO_CMAKE_SYSTEM_PATH and NO_DEFAULT_PATH to FindQt4.cmake.
(0025455)
Brad King (manager)
2011-02-16 17:29

I didn't actually look into it yet, I was just making sure you were running the test properly. I would appreciate a minimal test case. Preferably it would be just a find_path call that reproduces the problem with no ${} references in it.
(0025467)
hkrishna (reporter)
2011-02-17 20:28

Hi,

Sorry for the delay. I apologize for being long winded but I just wish to be thorough.


First step have QT 4.7 installed on system path.
Second install QT 4.6.1 in a different directory probably home. The versions should not really matter their location is what is important.

An "ls" to the local QT include path shows the directories that are found within it.

ls /path/to/qt/4.6.1/i386-apple-darwin10_gcc-4.2/include
Qt QtDesigner QtMultimedia QtSql QtUiTools
QtAssistant QtGui QtNetwork QtSvg QtXml
QtCore QtHelp QtOpenGL QtTest phonon


An "ls" to the QT in system path shows

ls /Library/Frameworks/
NyxAudioAnalysis.framework QtScriptTools.framework
PluginManager.framework QtSql.framework
Qt3Support.framework QtSvg.framework
QtCore.framework QtTest.framework
QtDBus.framework QtWebKit.framework
QtDeclarative.framework QtXml.framework
QtDesigner.framework QtXmlPatterns.framework
QtDesignerComponents.framework iLifeFaceRecognition.framework
QtGui.framework iLifeKit.framework
QtHelp.framework iLifePageLayout.framework
QtMultimedia.framework iLifeSQLAccess.framework
QtNetwork.framework iLifeSlideshow.framework
QtOpenGL.framework phonon.framework
QtScript.framework
 
and specifically the QtCore framework:

ls /Library/Frameworks/QtCore.framework/
Contents QtCore.prl QtCore_debug.prl
Headers QtCore_debug Versions
QtCore QtCore_debug.dSYM


The Contents of the CMakeLists.txt


cmake_minimum_required(VERSION 2.8)


#As long as the CMakeCache.txt is erased before the SET and UNSET are probably not necessary
#I tested it both commented and uncommented and had the same result
#SET(QT_QTCORE_INCLUDE_DIR NOTFOUND)
#UNSET(QT_QTCORE_INCLUDE_DIR CACHE)

#run find path
FIND_PATH(QT_QTCORE_INCLUDE_DIR QtCore
          HINTS /path/to/qt/4.6.1/i386-apple-darwin10_gcc-4.2/include)

MESSAGE("FIRST: ${QT_QTCORE_INCLUDE_DIR}")

UNSET(QT_QTCORE_INCLUDE_DIR CACHE)

FIND_PATH(QT_QTCORE_INCLUDE_DIR QtCore
          HINTS /path/to/qt/4.6.1/i386-apple-darwin10_gcc-4.2/include NO_CMAKE_SYSTEM_PATH)

MESSAGE("SECOND: ${QT_QTCORE_INCLUDE_DIR}")


The relevant output I get:

FIRST: /Library/Frameworks/QtCore.framework/Headers
SECOND: /path/to/qt/4.6.1/i386-apple-darwin10_gcc-4.2/include

As you can see with this test, the FIND_PATH variable picks the value from the system framework over the path given in HINTS.
(0025471)
Brad King (manager)
2011-02-18 09:04

From the documentation of find_path:
       On Darwin or systems supporting OS X Frameworks, the cmake variable
       CMAKE_FIND_FRAMEWORK can be set to empty or one of the following:

          "FIRST"  - Try to find frameworks before standard
                     libraries or headers. This is the default on Darwin.
          "LAST"   - Try to find frameworks after standard
                     libraries or headers.
          "ONLY"   - Only try to find frameworks.
          "NEVER" - Never try to find frameworks.


Add this to your example:

  message("CMAKE_FIND_FRAMEWORK=[${CMAKE_FIND_FRAMEWORK}]")

It will print "FIRST" as the value. That means it will walk the whole search path looking for headers inside frameworks first, and then go back and look for other headers.
(0025472)
Brad King (manager)
2011-02-18 09:11

The find_path command is behaving as documented. I don't know whether an issue remains with FindQt4 or not. This may be a matter of VisIt code needing to set CMAKE_FIND_FRAMEWORK to "NEVER".

I'm changing the title of this issue to be specific to FindQt4 and assigning to Clinton, the maintainer of that module. Clinton, if/when you determine that no changes to FindQt4 are needed to resolve this issue (i.e. only changes to VisIt are needed) please close.

(0025473)
hkrishna (reporter)
2011-02-18 11:04

Hi Brad,

Thanks for your response. I ran into the solution of setting CMAKE_FIND_FRAMEWORK to "LAST" a few days back unfortunately I believed this to be a quick fix rather than a solution.


I state this for the reason:

I am using FindQt4.cmake as an example. I do not know for sure if this is a FIND_PATH specific issue (see next paragraphs for the reasons to my confusion)

The main reason is that regardless of whether CMAKE_FIND_FRAMEWORK is set to "FIRST", "LAST" or whichever FindQt4.cmake should be consistent. I know on Darwin that this variable is set to "FIRST" because of the documentation. So if CMAKE_FIND_FRAMEWORK is the cause of the problem then I should find that every path QT_QTCORE, QT_QTGUI, QT_QTXML, etc. should all point to the headers in the system path. What I find is only QT_QTCORE is set to system path and the rest point to the other version's. This mixes the headers between multiple versions of QT. This is a problem that either resides with FindQt4.cmake doing something incorrectly or FIND_PATH having an error.


On a side note, I find the text on the cmake documentation for how FIND_PATH is using CMAKE_FIND_FRAMEWORK (http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:find_path [^]) to be ambiguous.

I interpreted this option in one of two ways:

1. The FIND_PATH search order is preserved and whenever multiple choice are given it uses CMAKE_FIND_FRAMEWORK to choose which to pick. For example, if the Environment (search order 2) variable has a path to a framework and a standard header/library. Then FIND_PATH will use the CMAKE_FIND_FRAMEWORK variable to pick between the two of them.

2. FIND_PATH will find all the paths and prioritize the frameworks on top regardless of the search order. (The one you pointed out)

I asked about this issue on the CMake mailing list mail titled (FIND_PATH issue in FindQt4.cmake and Clinton was on that thread), the other developers did not know the answer without having to look through the source code.

So if FIND_PATH is performing option 2. This documentation may need to be clarified or I may be the only person interpreting it this way (I would not be surprised :). The trouble I am having is that CMAKE_FIND_FRAMEWORK defaults to something that changes FIND_PATH's search order which is difficult to comprehend. Having frameworks always take priority regardless of search order just seems unintuitive to me. is there a reason why this is the default behavior? If this is the default action then I am satisfied in knowing how FIND_PATH functions.

I still believe that there is a problem especially since there should never be case where I should get QT_QTCORE to point at one header (QT 4.7) and the rest of the headers are pointing at a different version of QT (4.6.1)

Thanks,
Hari
(0025494)
Brad King (manager)
2011-02-18 15:06

http://www.cmake.org/pipermail/cmake/2011-February/042841.html [^]
(0025495)
Brad King (manager)
2011-02-18 15:10

The code that searches for frameworks before/after normal headers is here:

  http://cmake.org/gitweb?p=cmake.git;a=blob;f=Source/cmFindPathCommand.cxx;hb=v2.8.3#l113 [^]

Just below it is the code that actually looks in frameworks:

  http://cmake.org/gitweb?p=cmake.git;a=blob;f=Source/cmFindPathCommand.cxx;hb=v2.8.3#l133 [^]

Note that "foo.h" can be found under "foo.framework". This is probably why the problem only occurs for headers like "QtCore" whose names match their framework names.
(0025521)
hkrishna (reporter)
2011-02-19 00:03

Thanks for pointer to the relevant code. After looking at this it seems like FindQt4.cmake may be the culprit for this error.

For QT_QTCORE_INCLUDE_DIR

FIND_PATH(QT_QTCORE_INCLUDE_DIR QtCore
                HINTS ${qt_headers}
                ${QT_LIBRARY_DIR}/QtCore.framework/Headers
                PATH_SUFFIXES QtCore
        )

This code is missing NO_DEFAULT_PATH

All the other modules have this variable included
 
FOREACH(QT_MODULE ${QT_MODULES})
    STRING(TOUPPER ${QT_MODULE} _upper_qt_module)
    FIND_PATH(QT_${_upper_qt_module}_INCLUDE_DIR ${QT_MODULE}
              PATHS
              ${QT_HEADERS_DIR}/${QT_MODULE}
              ${QT_LIBRARY_DIR}/${QT_MODULE}.framework/Headers
              NO_DEFAULT_PATH
      )

I would propose that the missing NO_DEFAULT_PATH for QT_QTCORE_INCLUDE_DIR is causing this bug and modifying this should fix the issue.

1st case:

FIND_PATH(QT_QTCORE_INCLUDE_DIR QtCore
                HINTS ${qt_headers}
                ${QT_LIBRARY_DIR}/QtCore.framework/Headers
                PATH_SUFFIXES QtCore
                NO_DEFAULT_PATH
           )

A coworker of mine found a couple of more place where NO_DEFAULT_PATH is not included. I am including this just to ensure that all bases are covered I don't know if they are problematic or not but they are missing the NO_DEFAULT_PATH argument.

2ND CASE: Setup up of QT_PLUGINS_DIR

Old:
 # ask qmake for the plugins directory
 IF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)
   EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE}
     ARGS "-query QT_INSTALL_PLUGINS"
     OUTPUT_VARIABLE qt_plugins_dir )
   # make sure we have / and not \ as qmake gives on windows
   FILE(TO_CMAKE_PATH "${qt_plugins_dir}" qt_plugins_dir)
   SET(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins" FORCE)
 ENDIF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)

New: (uses output of cmake as a hint to FIND_PATH, instead of relying on qmake output directly)
 # ask qmake for the plugins directory
 IF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)
   _qt4_query_qmake(QT_INSTALL_PLUGINS qt_plugins_dir)
   SET(QT_PLUGINS_DIR NOTFOUND)
   foreach(qt_cross_path ${CMAKE_FIND_ROOT_PATH})
     set(qt_cross_paths ${qt_cross_paths} "${qt_cross_path}/plugins")
   endforeach(qt_cross_path)
   FIND_PATH(QT_PLUGINS_DIR NAMES accessible imageformats sqldrivers codecs designer
     HINTS ${qt_cross_paths} ${qt_plugins_dir}
     DOC "The location of the Qt plugins")
 ENDIF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR OR QT_QMAKE_CHANGED)


3RD CASE: Set of QT_MKSPECS_DIR

Old:
   FIND_PATH(QT_MKSPECS_DIR qconfig.pri PATHS ${qt_mkspecs_dirs}
     DOC "The location of the Qt mkspecs containing qconfig.pri"
     NO_DEFAULT_PATH )

New: (drops "NO_DEFAULT_PATH")
   FIND_PATH(QT_MKSPECS_DIR NAMES qconfig.pri
     HINTS ${qt_cross_paths} ${qt_mkspecs_dirs}
     DOC "The location of the Qt mkspecs containing qconfig.pri")

Thank you once again for resolving this issue. Please let me know what your final action for this issue will be.

Best regards,
Hari
(0025522)
hkrishna (reporter)
2011-02-19 00:24

I forgot to add that the solution of adding NO_DEFAULT_PATH or NO_CMAKE_SYSTEM_PATH to all the FIND_PATH would be one possibility.

An alternative would be to remove all the NO_DEFAULT_PATH from the other calls so that all the FIND_PATH calls find the framework and then use the CMAKE_FIND_FRAMEWORK to control whether the user would like to use the system framework or another alternative path.

There are probably a few viable alternatives out there.
(0025523)
Clinton Stimpson (developer)
2011-02-19 00:50

Adding NO_DEFAULT_PATH or NO_CMAKE_SYSTEM_PATH is going to break cross-compiling capabilities. The NO_DEFAULT_PATH's that are in there now are for finding things relative to other things already found.

I think I have a fix based on CMAKE_FIND_FRAMEWORK, but I'll have to do some testing with multiple Qt configurations. It poses an extra challenge because it doesn't know ahead of time if the qmake being used goes with frameworks or not.
(0025525)
Clinton Stimpson (developer)
2011-02-19 17:32

Fixed in git.

Merge topic 'qt4-macfind' into next
4167be0 Fix issues with find_path() for QtCore include dir on Mac. Fixes 11868.
(0026726)
David Cole (manager)
2011-06-06 18:25

Closing resolved issues that have not been updated in more than 3 months.

 Issue History
Date Modified Username Field Change
2011-02-16 13:58 hkrishna New Issue
2011-02-16 16:19 Brad King Note Added: 0025452
2011-02-16 16:59 hkrishna Note Added: 0025453
2011-02-16 17:29 Brad King Note Added: 0025455
2011-02-17 20:28 hkrishna Note Added: 0025467
2011-02-18 08:57 Brad King Assigned To => Brad King
2011-02-18 08:57 Brad King Status new => assigned
2011-02-18 09:04 Brad King Note Added: 0025471
2011-02-18 09:11 Brad King Note Added: 0025472
2011-02-18 09:11 Brad King Assigned To Brad King => Clinton Stimpson
2011-02-18 09:11 Brad King Summary FIND_PATH not following HINTS Command => FindQt4 and framework v. non-framework
2011-02-18 11:04 hkrishna Note Added: 0025473
2011-02-18 15:06 Brad King Note Added: 0025494
2011-02-18 15:10 Brad King Note Added: 0025495
2011-02-19 00:03 hkrishna Note Added: 0025521
2011-02-19 00:24 hkrishna Note Added: 0025522
2011-02-19 00:50 Clinton Stimpson Note Added: 0025523
2011-02-19 17:32 Clinton Stimpson Note Added: 0025525
2011-02-19 17:32 Clinton Stimpson Status assigned => resolved
2011-02-19 17:32 Clinton Stimpson Resolution open => fixed
2011-06-06 18:25 David Cole Status resolved => closed
2011-06-06 18:25 David Cole Note Added: 0026726
2011-06-17 18:26 David Cole Fixed in Version => CMake 2.8.5
2011-06-17 18:26 David Cole Target Version => CMake 2.8.5


Copyright © 2000 - 2018 MantisBT Team