Opened 5 years ago

Last modified 5 years ago

#48288 new defect

CMake generating broken Xcode projects when using OpenCV

Reported by: christian.richardt@… Owned by: macports-tickets@…
Priority: Normal Milestone:
Component: ports Version: 2.3.3
Keywords: Cc: stromnov (Andrew Stromnov), michaelld (Michael Dickens), cssdev, ryandesign (Ryan Schmidt)
Port: opencv cmake

Description (last modified by larryv (Lawrence Velázquez))

I use OpenCV in projects for which I create Xcode projects using CMake. I found some issues in OpenCV configuration files that cause CMake to create invalid Xcode projects (error: "Project … cannot be opened because the project file cannot be parsed.")

I'm using

  • opencv @3.0.0_0+eigen+opencl+openni+python27+qt4+tbb+vtk
  • cmake @3.2.3_0+docs+gui+python27+qt4

I think that one or more of these OpenCV variants might trigger this bug, but it could also be a bug in OpenCV rather than its MacPort. However, as I've not found anyone else complaining about it online, I assume it's a MacPort-specific issue.

Essentially, the string "//System/Library/Frameworks" somehow ends up in /opt/local/lib/pkgconfig/opencv.pc:

[...]
Libs.private: -l-framework OpenCL -L/opt/local/lib [...] -ltbb -ltbbmalloc -L//System/Library/Frameworks -lAGL -lOpenGL
[...]

and in /opt/local/share/OpenCV/OpenCVModules-release.cmake:

[...]
set_target_properties(opencv_hal PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "-ltbb -ltbbmalloc;//System/Library/Frameworks/AGL.framework;//System/Library/Frameworks/OpenGL.framework"
  IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libopencv_hal.a"
  )
[...]
set_target_properties(opencv_ts PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "opencv_hal;opencv_core;opencv_imgproc;opencv_imgcodecs;opencv_videoio;opencv_highgui;-ltbb -ltbbmalloc;//System/Library/Frameworks/AGL.framework;//System/Library/Frameworks/OpenGL.framework"
  IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libopencv_ts.a"
  )
[...]

In a CMake project that uses OpenCV, any Xcode project created for it will contain the following line in "Project.xcodeproj/project.pbxproj":

FRAMEWORK_SEARCH_PATHS = (//System/Library/Frameworks, );

which prevents Xcode from opening the generated project as it cannot be parsed.

Removing the "FRAMEWORK_SEARCH_PATHS" lines manually from "project.pbxproj" fixes the parsing error and the Xcode project can be opened as expected.

Replacing the double leading slash in the two files mentioned above with a single slash, and re-running CMake, prevents the FRAMEWORK_SEARCH_PATHS lines from appearing in the first place, and Xcode projects work fine.

This leads me to believe that the double slash should be replaced with a single slash, when /opt/local/lib/pkgconfig/opencv.pc and /opt/local/share/OpenCV/OpenCVModules-release.cmake are generated.

Change History (6)

comment:1 Changed 5 years ago by christian.richardt@…

Cc: christian.richardt@… added

Cc Me!

comment:2 Changed 5 years ago by larryv (Lawrence Velázquez)

Cc: stromnov@… michaelld@… css@… added; christian.richardt@… removed
Description: modified (diff)
Port: cmake added

comment:3 in reply to:  description Changed 5 years ago by ryandesign (Ryan Schmidt)

Cc: ryandesign@… added

I'm guessing the double slash is coming from the cmake 1.0 portgroup which sets -DCMAKE_OSX_SYSROOT="/" when the sdk is not set (otherwise it sets it to the sdk). My recollection is that we have to set CMAKE_OSX_SYSROOT to a non-empty value, because cmake requires this when MACOSX_DEPLOYMENT_TARGET is set, which in MacPorts it always is. I am remembering that if we did not do this, cmake would either error out, or choose an SDK to use even when we had not asked for one.

A double slash in a path should not be a problem; the OS is able to handle that and collapse multiple slashes down to a single one. So what exactly is the problem? You said FRAMEWORK_SEARCH_PATHS = (//System/Library/Frameworks, ); cannot be parsed. Why is it invalid? What would be valid? Is the problem really the double slash at the beginning, or is it perhaps the comma at the end? (Apple documentation on FRAMEWORK_SEARCH_PATHS says it is a space-separated list, so the comma seems wrong to me.)

I agree with you that this may be caused by one of the variants you've selected, because I don't see this on my system nor do I see it in our binary packages. Can you narrow it down? I am suspicious of the way that opencv's tbb variant messes with OPENCV_LINKER_LIBS, which none of the other variants do, but even if I install opencv with the tbb variant I don't see a reference to the frameworks directory in the places where you've reported seeing it.

comment:4 Changed 5 years ago by christian.richardt@…

The problem in FRAMEWORK_SEARCH_PATHS = (//System/Library/Frameworks, ); indeed appears to be the double slash. Deleting one of the slashes manually (in all instances) fixes the Xcode project. Seems like Xcode is a little fragile in that respect, and maybe it's a a regression in Xcode.

I narrowed it down to the qt4 variant that adds the double slash in OpenCV:

$ diff -c OpenCVModules-release\@3.0.0_0.cmake OpenCVModules-release\@3.0.0_0+qt4.cmake 
*** OpenCVModules-release@3.0.0_0.cmake	2015-06-22 21:27:25.000000000 +0200
--- OpenCVModules-release@3.0.0_0+qt4.cmake	2015-07-09 23:47:38.000000000 +0200
***************
*** 9,14 ****
--- 9,15 ----
  set_property(TARGET opencv_hal APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
  set_target_properties(opencv_hal PROPERTIES
    IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
+   IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "//System/Library/Frameworks/AGL.framework;//System/Library/Frameworks/OpenGL.framework"
    IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libopencv_hal.a"
    )
  
***************
*** 154,160 ****
  set_property(TARGET opencv_ts APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
  set_target_properties(opencv_ts PROPERTIES
    IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
!   IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "opencv_hal;opencv_core;opencv_imgproc;opencv_imgcodecs;opencv_videoio;opencv_highgui"
    IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libopencv_ts.a"
    )
  
--- 155,161 ----
  set_property(TARGET opencv_ts APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
  set_target_properties(opencv_ts PROPERTIES
    IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
!   IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE "opencv_hal;opencv_core;opencv_imgproc;opencv_imgcodecs;opencv_videoio;opencv_highgui;//System/Library/Frameworks/AGL.framework;//System/Library/Frameworks/OpenGL.framework"
    IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libopencv_ts.a"
    )
$ diff opencv\@3.0.0_0.pc opencv\@3.0.0_0+qt4.pc 
13c13
< Libs.private: -l-framework Cocoa -L/opt/local/lib -lpng -ltiff -ljasper -ljpeg -lImath -lIlmImf -lIex -lHalf -lIlmThread -lavcodec -lavformat -lavutil -lswscale -lavresample -lz -lbz2 -l-framework VideoDecodeAcceleration -l-framework QTKit -l-framework QuartzCore -l-framework AppKit
---
> Libs.private: -L/opt/local/lib -lQtOpenGL -lQtGui -lQtTest -lQtCore -lpng -ltiff -ljasper -ljpeg -lImath -lIlmImf -lIex -lHalf -lIlmThread -lavcodec -lavformat -lavutil -lswscale -lavresample -lz -lbz2 -l-framework VideoDecodeAcceleration -l-framework QTKit -l-framework QuartzCore -l-framework AppKit -L//System/Library/Frameworks -lAGL -lOpenGL

I tracked down the source to the following: if OpenCV is configured WITH_QT, and Qt is found, OpenCVFindLibsGUI.cmake also adds ${OPENGL_LIBRARIES} (AGL and OpenGL) to OPENCV_LINKER_LIBS. This appears to be the step that produces the broken paths. For some reason, the SDK path component is missing, which I do get if I do

find_package(OpenGL REQUIRED)
message(STATUS ${OPENGL_LIBRARIES})

in a test project:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/AGL.framework
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/OpenGL.framework

I don't understand why find_package(OpenGL REQUIRED) produces different paths when MacPort configures OpenCV than when I use it in my own project?

comment:5 in reply to:  4 Changed 5 years ago by ryandesign (Ryan Schmidt)

Replying to christian.richardt@…:

The problem in FRAMEWORK_SEARCH_PATHS = (//System/Library/Frameworks, ); indeed appears to be the double slash. Deleting one of the slashes manually (in all instances) fixes the Xcode project. Seems like Xcode is a little fragile in that respect, and maybe it's a a regression in Xcode.

That's unfortunate. Arguably, Xcode is correct to complain about double slashes because they are not canonical. But we did encounter problems in MacPorts before adopting our current strategy of using "/" as the SDK path when no SDK path need otherwise be specified. It is possible that newer versions of cmake have made this unnecessary, but if not, then we need to keep it, or find another workaround.

I do see that a change went into cmake 3.1 to allow SDK "/" to be treated as the current OS X version. Not sure what we were doing before that; maybe we were patching cmake.

We do have a long history of changing this behavior in the cmake portgroup, with good intentions, but with the consequence of inadvertently breaking some ports while fixing others, so we need to tread very carefully. For further reading on past issues, see Joshua's list of tickets and revisions in comment:ticket:44125:12.

> Libs.private: -L/opt/local/lib -lQtOpenGL -lQtGui -lQtTest -lQtCore -lpng -ltiff -ljasper -ljpeg -lImath -lIlmImf -lIex -lHalf -lIlmThread -lavcodec -lavformat -lavutil -lswscale -lavresample -lz -lbz2 -l-framework VideoDecodeAcceleration -l-framework QTKit -l-framework QuartzCore -l-framework AppKit -L//System/Library/Frameworks -lAGL -lOpenGL

-L//System/Library/Frameworks is wrong in any case, because //System/Library/Frameworks is a directory that contains frameworks, not libraries, so the correct flag would be -F//System/Library/Frameworks.

I tracked down the source to the following: if OpenCV is configured WITH_QT, and Qt is found, OpenCVFindLibsGUI.cmake also adds ${OPENGL_LIBRARIES} (AGL and OpenGL) to OPENCV_LINKER_LIBS. This appears to be the step that produces the broken paths. For some reason, the SDK path component is missing, which I do get if I do

find_package(OpenGL REQUIRED)
message(STATUS ${OPENGL_LIBRARIES})

in a test project:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/AGL.framework
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/OpenGL.framework

I don't understand why find_package(OpenGL REQUIRED) produces different paths when MacPort configures OpenCV than when I use it in my own project?

The SDK path component is not missing under MacPorts; rather, when there is no particular need for an SDK, we specify (in the cmake 1.0 portgroup, as mentioned above) that the SDK path shall be "/", and everything else follows from that. The reason you see a difference in your own project is that you are presumably specifying the path to the 10.10 SDK, not "/".

I do have an open proposal for MacPorts to always use the real SDK path, even when it is not needed: #41783. Although this seems to work well for me, and might solve this particular problem you're having (you could try it), it causes other problems, which is a reason why we haven't committed it yet, and might never do so.

I'm not entirely sure it's correct for cmake to be prepending the SDK path to the other paths, like it's doing. In Xcode and other build systems, the SDK is a separate setting, not mixed directly with paths in other variables.

comment:6 Changed 5 years ago by ryandesign (Ryan Schmidt)

-l-framework is wrong too

Note: See TracTickets for help on using tickets.