MantisBT - CMake
View Issue Details
0005139CMakeCMakepublic2007-06-07 09:052016-06-10 14:30
Philippe BERNERY 
Bill Hoffman 
normalminoralways
closedmoved 
 
 
0005139: find_path seems to not work correctly on Mac OS X
I have the following in a find script:

find_path(COIPMANAGER_INCLUDE_DIRS
  NAMES
    coipmanager/CoIpManager.h
  PATHS
    /Library/Frameworks/CoIpManager.framework/Headers
    ${MORE_PATH}
)

and COIPMANAGER_INCLUDE_DIRS contains /Library/Frameworks/CoIpManager.framework/Headers/coipmanager whereas it should contain /Library/Frameworks/CoIpManager.framework/Headers
No tags attached.
Issue History
2008-10-09 13:08Bill HoffmanNote Added: 0013796
2008-10-13 14:36Philippe BERNERYNote Added: 0013862
2009-06-03 10:16Hugues De KeyzerNote Added: 0016612
2009-06-03 10:18Hugues De KeyzerNote Edited: 0016612
2009-06-03 10:49Hugues De KeyzerNote Edited: 0016612
2009-06-03 11:22Hugues De KeyzerNote Edited: 0016612
2009-06-03 12:07Hugues De KeyzerNote Edited: 0016612
2009-06-04 04:10Hugues De KeyzerNote Edited: 0016612
2009-06-04 05:32Hugues De KeyzerNote Added: 0016632
2016-06-10 14:27Kitware RobotNote Added: 0041364
2016-06-10 14:27Kitware RobotStatusassigned => resolved
2016-06-10 14:27Kitware RobotResolutionopen => moved
2016-06-10 14:30Kitware RobotStatusresolved => closed

Notes
(0013796)
Bill Hoffman   
2008-10-09 13:08   
Is this still an issue?
(0013862)
Philippe BERNERY   
2008-10-13 14:36   
I cannot test it since I'm not working on this project anymore.
(0016612)
Hugues De Keyzer   
2009-06-03 10:16   
(edited on: 2009-06-04 04:10)
Yes, it is still an issue. I encountered the same problem with CMake 2.6.4 when using FindLibXml2. It uses the command:
FIND_PATH(LIBXML2_INCLUDE_DIR libxml/xpath.h HINTS ... PATH_SUFFIXES libxml2)

On GNU/Linux, this defines LIBXML2_INCLUDE_DIR as:
LIBXML2_INCLUDE_DIR:PATH=/usr/include/libxml2
This directory contains a subdirectory named libxml that contains xpath.h. As the headers are included as <libxml/xpath.h>, it is the correct value and it works fine.

On Mac OS X, this gives:
LIBXML2_INCLUDE_DIR:PATH=/Library/Frameworks/libxml2.framework/Headers/libxml
This directory contains xpath.h. With this value, the headers includes doesn't work. It should be /Library/Frameworks/libxml2.framework/Headers.

The way I use to solve this for now is by copying FindLibXml2.cmake into my source tree, and modifying it. I replace this part:

FIND_PATH(LIBXML2_INCLUDE_DIR libxml/xpath.h
   HINTS
   ${PC_LIBXML_INCLUDEDIR}
   ${PC_LIBXML_INCLUDE_DIRS}
   PATH_SUFFIXES libxml2
   )

by this:

IF (APPLE)
   SET(LIBXML2_FRAMEWORK_DIRECTORY libxml2/)
ENDIF (APPLE)

FIND_PATH(LIBXML2_INCLUDE_DIR ${LIBXML2_FRAMEWORK_DIRECTORY}libxml/xpath.h
   HINTS
   ${PC_LIBXML_INCLUDEDIR}
   ${PC_LIBXML_INCLUDE_DIRS}
   PATH_SUFFIXES libxml2
   )

This doesn't look really good, but at least it works…
[EDIT]
Correction: this doesn't work neither, as this gives
LIBXML2_INCLUDE_DIR:PATH=/Library/Frameworks/libxml2.framework
instead of:
LIBXML2_INCLUDE_DIR:PATH=/Library/Frameworks/libxml2.framework/Headers

[EDIT]
To make it work, we can use this even more crappy hack:

IF (APPLE)
   SET(LIBXML2_FRAMEWORK_DIRECTORY libxml2/)
   SET(LIBXML2_INCLUDE_DIR_PREVIOUS ${LIBXML2_INCLUDE_DIR})
ENDIF (APPLE)

FIND_PATH(LIBXML2_INCLUDE_DIR ${LIBXML2_FRAMEWORK_DIRECTORY}libxml/xpath.h
   HINTS
   ${PC_LIBXML_INCLUDEDIR}
   ${PC_LIBXML_INCLUDE_DIRS}
   PATH_SUFFIXES libxml2
   )

IF (APPLE AND NOT (LIBXML2_INCLUDE_DIR STREQUAL LIBXML2_INCLUDE_DIR_PREVIOUS))
   SET(LIBXML2_INCLUDE_DIR ${LIBXML2_INCLUDE_DIR}/Headers CACHE PATH "Path to a file." FORCE)
ENDIF (APPLE AND NOT (LIBXML2_INCLUDE_DIR STREQUAL LIBXML2_INCLUDE_DIR_PREVIOUS))

I’m rather new to CMake, so probably I’m not using it completely correctly.
[/EDIT]
[/EDIT]

I took a look at cmFindPathCommand::FindHeaderInFramework(). What seems to happen is that it tests whether /Library/Frameworks/libxml.framework/Headers/xpath.h exists, which is false, then it performs a glob search with "/Library/Frameworks/*.framework/Headers/libxml/xpath.h", finds /Library/Frameworks/libxml2.framework/Headers/libxml/xpath.h and returns that path without the filename. It should probably be better if the end of the string was compared with the searched filename and this part removed to form the path.

It should be even better if this function also used the PATH_SUFFIXES in its search.

One last thing, this function begins with:

std::string
cmFindPathCommand::FindHeaderInFramework(std::string const& file,
                                         std::string const& dir)
{
  cmStdString fileName = file;
  cmStdString frameWorkName;
  cmStdString::size_type pos = fileName.find("/");
  // if there is a / in the name try to find the header as a framework
  // For example bar/foo.h would look for:
  // bar.framework/Headers/foo.h
  if(pos != fileName.npos)
    {
    // remove the name from the slash;
    fileName = fileName.substr(pos+1);
    frameWorkName = file;
    frameWorkName =
      frameWorkName.substr(0, frameWorkName.size()-fileName.size()-1);
    // if the framework has a path in it then just use the filename
    if(frameWorkName.find("/") != frameWorkName.npos)
      {
      fileName = file;
      frameWorkName = "";
      }

This last if condition can never happen, as frameWorkName is formed by taking the start of the string, up to one character before the first '/'.

(0016632)
Hugues De Keyzer   
2009-06-04 05:32   
Frameworks on Mac OS X are a little tricky to handle. When including the OpenGL header, for example, with this instruction:

#include <OpenGL/gl.h>

it looks for <FRAMEWORK_DIRECTORIES>/OpenGL.framework/Headers/gl.h. <FRAMEWORK_DIRECTORIES> are the directory containing frameworks (/System/Library/Frameworks, /Library/Frameworks), which can be specified with -F on the gcc command line. So, with this include above, no special arguments are needed on the command line as the OpenGL framework is in a standard framework directory (/System/Library/Frameworks).

When using the FindOpenGL module, which uses:

FIND_PATH(OPENGL_INCLUDE_DIR OpenGL/gl.h DOC "Include for OpenGL on OSX")

it defines:

//Include for OpenGL on OSX
OPENGL_INCLUDE_DIR:PATH=/System/Library/Frameworks/OpenGL.framework

This value will not be used as -I argument on the command line, instead it will be used for adding a -F argument like this:

-F/System/Library/Frameworks

(Actually, it doesn't add this one, because it is the system default framework directory, but it would if the framework was in another directory.)

So, on Mac OS X, there are different cases that appear the same:

#include <OpenGL/gl.h>
#include <libxml/xpath.h>

The first one means “include the gl.h file from the OpenGL framework”, while the second means “include the libxml/xpath.h file from the libxml2 framework”. So first, we need to look whether the first part of the path is an existing framework, if it is, add a -F argument with the dir in which /the framework/ resides, if it's not, search all frameworks for the whole path, and add a -I argument with <PATH_TO_THE_FRAMEWORK>/Headers.
(0041364)
Kitware Robot   
2016-06-10 14:27   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.