5

I'm using CMake 3.3.2 on OS X Yosemite. If I put a framework path into include_directories the generated Makefile doesn't include that directory. A short example:

cmake_minimum_required(VERSION 3.0)
project(testproj)
include_directories(/System/Library/Frameworks/OpenGL.framework)
add_library(testlib test.c)

The make output:

Scanning dependencies of target testlib
/Library/Developer/CommandLineTools/usr/bin/make -f CMakeFiles/testlib.dir/build.make CMakeFiles/testlib.dir/build
[ 50%] Building C object CMakeFiles/testlib.dir/test.c.o
/Library/Developer/CommandLineTools/usr/bin/cc    -o CMakeFiles/testlib.dir/test.c.o   -c /Users/wrar/test/test.c

I expected the include_directories command to have an effect on the compiler line, and as the official OPENGL_INCLUDE_DIR has the value I passed in the example, I expect it to be a correct value. What am I missing?

wRAR
  • 25,009
  • 4
  • 84
  • 97
  • `include_directories` should come **before** add_library for take effect on the library. – Tsyvarev Oct 25 '15 at 16:43
  • @Tsyvarev doesn't make any difference, I've updated the example – wRAR Oct 25 '15 at 17:21
  • Does `target_include_directories` work for you? – usr1234567 Oct 26 '15 at 08:01
  • To filter out OSX framework paths is part of CMake's implementation: see [ENH: make sure default /System framework is not added with -F](https://github.com/Kitware/CMake/commit/5ed2141d12c6be54902cb26a83d2b97fba8699cb) commit. I think the reasoning behind it is that your CMake project should not depend on the OSX version/installation you are using. – Florian Oct 26 '15 at 09:31
  • @Florian well, that's what `FindOpenGL` gave me – wRAR Oct 26 '15 at 13:24
  • @wRAR I agree that this is confusing, but - since it's an integral part of CMake for OSX - I don't think you can easily change this. You could e.g. add a `message(STATUS "OPENGL_INCLUDE_DIR: ${OPENGL_INCLUDE_DIR}")` to document where `OpenGL` was found. And - if you don't want the framework to be first - you may want to look at `CMAKE_FIND_FRAMEWORK` global variable, which takes `FIRST`, `LAST` and `NEVER`. For some additional information on the topic see [here](https://cmake.org/pipermail/cmake/2005-December/007740.html) and [here](https://cmake.org/Wiki/CMake:HowToUseExistingOSXFrameworks). – Florian Oct 26 '15 at 13:58
  • @usr1234567 no difference – wRAR Oct 26 '15 at 15:16
  • @Florian I admit I'm missing something important. I've used `find_package(OpenGL REQUIRED)` and then `include_directories(${OPENGL_INCLUDE_DIR})` and this doesn't work on OS X while working on Linux and looking correct according to docs. Do I need additional commands to make it work on OS X or where is the problem? – wRAR Oct 26 '15 at 15:21
  • @wRAR The theory is that you don't need those framework include paths because they are implicit. Could you please add the error messages you get? I suppose "include not found", but the details may be interesting. – Florian Oct 26 '15 at 15:33
  • @Florian looks like the problem is this: the software ships `glext.h` which should be included before the system one. – wRAR Oct 26 '15 at 16:09
  • @wRAR See also [cmake not finding gl.h on OS X](http://stackoverflow.com/questions/26745284/cmake-not-finding-gl-h-on-os-x). I've just tested it and if I do `#include ` the header in the framework is found. But if I understand correctly, you have two versions of `glext.h` and you want the version in `/some/other/path` to be preferred. So if I give `include_directories(SYSTEM /some/other/path)` I get `cc -isystem /some/other/path -o CMakeFiles/testlib.dir/test.c.o -c /Users/Shared/Projects/IncludesOpenGL/test.c`. – Florian Oct 26 '15 at 19:04

1 Answers1

5

Turning my comments into an answer

Standard framework include paths are filtered by CMake

CMake has a lot of special handling for OS X Frameworks. One of it is to remove explicitly named framework include and library search paths (see this commit).

I agree that it's confusing that

find_package(OpenGL REQUIRED)
message(STATUS "OPENGL_INCLUDE_DIR: ${OPENGL_INCLUDE_DIR}")
include_directories(${OPENGL_INCLUDE_DIR})
add_library(...)

does return OPENGL_INCLUDE_DIR: /System/Library/Frameworks/OpenGL.framework but you don't find this path in the cc command line.

But this search path is implicit, meaning the compiler knows best where to find the framework's header files. So this filtering of the OS X framework include/library directories in CMake does reflect the special handling of the compiler/linker when working with frameworks.

How does the compiler find a framework's include file?

By the framework's name given as an include's directory name. See MAC Developer Library/Framework Programming Guide/Including Frameworks:

You include framework header files in your code using the #include directive. [...]

  #include <Framework_name/Header_filename.h>

See cmake not finding gl.h on OS X for more details.

I've just tested your example and added e.g. #include <OpenGL/glext.h> to test.c and the header in the framework is found.

If you don't want the OpenGL standard framework to be found first (the default), see find_path documentation and look for CMAKE_FIND_FRAMEWORK.

Or if you have your own OpenGL distribution in /some/other/path - and you omit the use of find_package(OpenGL) - you can give include_directories(SYSTEM /some/other/path).

Community
  • 1
  • 1
Florian
  • 39,996
  • 9
  • 133
  • 149
  • Passing the local dir via `-isystem` doesn't help the compiler to use the local header first (the code includes `` before `"glext.h"`), do I need to change the code? – wRAR Oct 27 '15 at 15:18
  • @wRAR You could add `add_compile_options("$<$:-include/some/other/path/glext.h>")` before your `add_library()` call. That would [enforce the include](http://stackoverflow.com/questions/3387453/include-header-files-using-command-line-option) to be first in all files you compile in your project on OS X. Or you use the same with [`target_compile_options()`](https://cmake.org/cmake/help/v3.4/command/target_compile_options.html) to be more specific. – Florian Oct 27 '15 at 20:08