CMake include_directories skips OS X frameworks - macos

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?

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).

Related

moltenvk project makefile- how to link via clang

This file: MoltenVK Runtime User Guide offers a nice description of how to link MoltenVK to a project that uses it, within XCode.
I prefer using makefiles, as it removes the need to boot up XCode to build (+ is a consistent workflow with the same project on Linux).
The problem is there's quite a bit of OSX/XCode specific terminology in the instructions, and I'm not quite sure how it translates to running clang via command line.
If you assume I'm looking to link only with the minimum specified to use MoltenVK, what would such a command line argument look like?
Here is my minimal attempt:
MOLTENVKDIR = /blah/vulkansdk-macos-1.1.108.0
a.out: my_headers.h my_src_files.cpp
clang -I$(MOLTENVKDIR)/MoltenVK/include -L$(MOLTENVKDIR)/MoltenVK/macOS/dynamic -lMoltenVK my_src_files.cpp
More specific questions:
How should I be setting LD_RUNPATH_SEARCH_PATHS? I assume this is a PATH-style variable that gets embedded in the executable with a list of places to look for the MoltenVK.dylib file?
In step 4 of the user guide, it says "drag (MoltenVK/macOS/dynamic/libMoltenVK.dylib) to the Link Binary With Libraries list"- is that essentially the -lMoltenVK line?
Where does step 5 come in? Should I append -framework Metal -framework Foundation -framework ...? What should I do with the .tbd file?
Is step 6 just ensuring that I copy the libMoltenVK.dylib file relative to a.out consistent with LD_RUNPATH_SEARCH_PATHS?
Is step 7 safe to ignore, as I'm not using XCode?
TLDR; I use g++, use the flags -lMoltenVK and -L$(MOLTENVK_DIR), and at the top define VK_ICD_FILENAMES using export VK_ICD_FILENAMES=$(ICD_DIR)
Header Search Paths is -I$(PATH)
Library Search Paths is -L$(PATH)
Runpath Search Paths is -rpath $(PATH) (with the space)
What I did was copy the .dylibs into a folder called lib in my project folder, set Library Search Path with -Llib, and link them with -lvulkan and -lMoltenVK. Since these dynamic libraries are hardwired to use #rpath when linking, I set -rpath lib.
You can see the vulkan tutorial for linux which uses a Makefile which shows a very basic version of making a Makefile for Vulkan on linux (no MoltenVK)
Most importantly, to not get a VkResult -9 when calling vkCreateInstance (MoltenVK not installed properly) make sure to define the VK_ICD_FILENAMES environment variable! I did this by writing export VK_ICD_FILENAMES=lib/MoltenVK_icd.json near the top of my Makefile, and copied the MoltenVK_icd.json file to my project! This is a file which points to where the dylib is, and is necesarry for MoltenVK to work. When installing MoltenVK, it was inside the same folder as libMoltenVK.dylib
Similarily, you must define VK_LAYER_PATH for validation layers to work.
Minimally, all you need for MoltenVK is:
export VK_ICD_FILENAMES=lib/MoltenVK_icd.json
main:
g++ test.cpp -o App -Llib -rpath lib -lMoltenVK
I'm not an expert in best practices and conventions, I do what works. Hope this helped

Use framework in static library

I have a library which is being generated as .a file (to be statically linked). There I want to include Qt framework (QtCore.framework) since I am on OSX. Is that possible? How could I do it using cmake?
My attempt:
In CMakeLists.txt I have
FIND_LIBRARY(QTCORE_LIBRARY NAMES QtCore
HINTS "${CMAKE_SOURCE_DIR}/osx/frameworks")
Then I print variable ${QTCORE_LIBRARY} and it gives right path.
Then in src/CMakeLists.txt (where my sources are) I link the library
TARGET_LINK_LIBRARIES(libname $${QTCORE_LIBRARY})
However when I launch the compilation it complains because it does not find
fatal error: 'QtGlobal' file not found
I have checked and QtCore.framework contains QtGlobal header
EDIT: In case someone has same problem I found solution.
I needed to add "${QTCORE_LIBRARY}/Headers" in my project include directories
Thanks in advance and regards
Why don't using the CMake "config.cmake" provided by Qt5 ?
something like:
# Qt Setting
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets)
...
target_link_libraries(libname Qt5::Core Qt5::Gui Qt5::Widgets)
CMake can find and use [...] Qt5 libraries. [...] Qt5 libraries are found using “Config-file Packages” shipped with Qt5
src: https://cmake.org/cmake/help/latest/manual/cmake-qt.7.html
In order for find_package to be successful, Qt 5 must be found below the CMAKE_PREFIX_PATH, or the Qt5_DIR must be set in the CMake cache to the location of the Qt5WidgetsConfig.cmake file. The easiest way to use CMake is to set the CMAKE_PREFIX_PATH environment variable to the install prefix of Qt 5.
src: http://doc.qt.io/qt-5/cmake-manual.html

Force CMake to use static libraries

[Shamelessly cross-posted from the CMake help list]
I'm trying to create binaries as statically as possible. The fortran code I've got has got X11 and quadmath as dependencies, and I've come across a number of issues (maybe each of these issues should be in a different question?):
My variables are currently
set(CMAKE_LIBRARY_PATH /usr/X11/lib /usr/X11/include/X11 ${CMAKE_LIBRARY_PATH})
find_package(X11 REQUIRED)
find_library(X11 NAMES X11.a PATHS /usr/X11/include/X11/ /usr/X11/lib)
find_library(X11_Xaw_LIB NAMES Xaw Xaw /usr/X11/include/X11/ /usr/X11/lib ${X11_LIB_SEARCH_PATH})
find_library(Xaw Xaw7 PATHS ${X11_LIB_SEARCH_PATH})
set(CMAKE_LIBRARY_PATH /usr/lib/gcc/x86_64-linux-gnu/4.7 /usr/lib/gcc/x86_64-linux-gnu/4.7/x32 /usr/lib/gcc/x86_64-linux-gnu/4.7/32 ${CMAKE_LIBRARY_PATH})
find_library(quadmath NAMES quadmath.a)
set(BUILD_SHARED_LIBS ON)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(LINK_SEARCH_START_STATIC TRUE)
set(LINK_SEARCH_END_STATIC TRUE)
set(SHARED_LIBS OFF)
set(STATIC_LIBS ON)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
Using these, CMake attempts to build every program statically (as expected) - however, it fails because I don't have Xaw.a - I can't find out whether this actually should exist. I have installed the latest libxaw7-dev which I was expecting to fix it. One option would be to compile the X11 libraries myself, but I don't really want to do that...
if I comment out only set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static"), then CMake compiles everything, but uses shared libraries for every program, even though I specify the location of .a X11 libraries in my find_library() calls. I was expecting CMake to use the .a files where it could and then only use shared libraries - is there a way to force this behaviour?
does anyone know yet of a fix for the bug described here: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46539; whereby gfortran seemingly can't statically link libquadmath? I tried the fix using gcc but I can't get CMake to recognise the libgfortran flag:
cmake -DCMAKE_Fortran_COMPILER=gcc -DCMAKE_Fortran_FLAGS=-gfortran
results in
-- The Fortran compiler identification is unknown
-- Check for working Fortran compiler: /usr/bin/gcc
-- Check for working Fortran compiler: /usr/bin/gcc -- broken
CMake Error at /usr/share/cmake-2.8/Modules/CMakeTestFortranCompiler.cmake:54 (message):
The Fortran compiler "/usr/bin/gcc" is not able to compile a simple test program.
However, as you might have noticed, I set the location of the libquadmath.a; when I build a program which doesn't use X11 but does use quadmath when I use
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
then the program does compile successfully (running ldd reports 'not a dynamic executable') - does this mean that the bug has been fixed, or does it only work because I set the location in CMake?
I was having a similar problem. Turns out that cmake was implicitly linking against libgfortran and libquadmath. To fix this I put the following in my top level CMakeLists.txt:
unset(CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES)
I could then explicitly link again the libraries using:
SET_TARGET_PROPERTIES(main_f PROPERTIES LINKER_LANGUAGE "C"
LINK_FLAGS
"/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libgfortran.a
/usr/local/Cellar/gcc/7.1.0/lib/gcc/7/libquadmath.a -lm -lgcc"
)
The static version of libgfortran is necessary because the shared library also depends on libquadmath. The added "-lm" and "-lgcc" bring in the system dynamic versions of these libraries. On a mac system, you would want to use the full path to your libm.a as well.
I guess your questions are not that much related, I don't know the answer for all of them.
For your static linking problems, since you're using GCC, you can pass multiple -static and -dynamic flags to it:
set(CMAKE_EXE_LINKER_FLAGS "-static ${STATIC_LIBS} -dynamic ${EVERYTHING ELSE} -static ${MORE_STATIC_LIBS}")
I don't know why Xaw.a isn't available on your system, probably because the package maintainer of your Linux distribution didn't really make them available.
Also, compiling everything static might make things not compatible between all distros out there and you cripple the ability for others to use improved, up-to-date libraries with your program, it might not be what you want.
If you intend to make a self-contained package of your program, it might be better just to include the shared libraries you used together, like Dropbox and many other proprietary applications do (Humble Bundle games are other example).

CMAKE: Build library and link against it

I'm trying to use cmake (on Linux with GNU make and g++) to build a project with two sub-directories: MyLib and MyApp. MyLib contains source for a static library; MyApp needs to link against that library. I'm trying to build on Linux with generated makefiles using the following CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (MyProj)
include_directories (MyLib)
file(GLOB MyLibSrc MyLib/*.cpp)
add_library(MyLibrary STATIC ${MyLibSrc})
file(GLOB MyAppSrc MyApp/*.cpp)
add_executable(MyApplication ${MyAppSrc})
target_link_libraries(MyApplication MyLibrary)
This 'almost' works. It fails at link time because while it generates libMyLibrary.a - it is in the root. When I add:
link_directories(${MyProj_BINARY_DIR})
it makes no difference.
I've got a few (inter-linked) questions:
What's the best way to coerce cmake into building my library and executable into a 'staging directory' — say MyStage — to keep targets separate from source?
How do I convince cmake to link the application against the library?
If I wanted to build a debug and a release version, what's the best way to extend my cmake scripts to do this — making sure that the debug application links against the debug library and the release application against the release library?
I'm a relative newcomer to cmake. I've read what I can find on the web, but find myself struggling to get my library to link with my executable. This sort of a configuration, to my mind, should be quite common. An example from which to crib would be very helpful, but I've not found one.
Well, it is better to read this example and do exactly as suggested.
cmake_minimum_required (VERSION 2.6)
project (MyProj CXX)
add_subdirectory(MyLib)
add_subdirectory(MyApp)
Then for each subdirectory specified, CMakeLists.txt files are created
MyLib\CMakeLists.txt
file(GLOB SRC_FILES *.cpp)
add_library(MyLib ${SRC_FILES})
MyApp\CMakeLists.txt
file(GLOB SRC_FILES *.cpp)
add_executable(MyApp ${SRC_FILES})
target_link_libraries(MyApp MyLib)
Use "out of the source build". Make a directory used only for build and while in it, call
cmake <path to the sources, it may be relative>
Either use
link_directories(${MyProj_BINARY_DIR}/MyLib)
or make CMakeLists.txt in each subdirectory - that would be better for project larger than very small.
This is a bit tricky, check out CMAKE_BUILD_TYPE in the docs (you can set it and/or "if" by it). You can also set it from command line:
cmake -DCMAKE_BUILD_TYPE=Debug
I've discovered the 'optimal' solution to (1)... so, thought I should post it here:
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY MyStage)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY MyStage)
The thing that confused me previously is that static libraries are not considered a LIBRARY by Cmake - they're considered to be ARCHIVEs.
Do not add libraries and executables in the root Cmakelists.txt. Add these libraries and executables in Cmakelists.txt of subdirectories.

Why doesn't Xcode recognize my LIBRARY_SEARCH_PATHS?

I've set LIBRARY_SEARCH_PATHS to /opt/local/lib, and verified that the library in question is there (I'm linking to GLEW):
$ls /opt/local/lib
libGLEW.1.5.1.dylib libfreetype.a libz.a
libGLEW.1.5.dylib libfreetype.dylib libz.dylib
libGLEW.a libfreetype.la pkgconfig
libGLEW.dylib libz.1.2.3.dylib
libfreetype.6.dylib libz.1.dylib
but Xcode gives me the linker error
library not found for -lGLEW
I'm generating the Xcode project with CMake, so I don't want to explicitly modify the Xcode project (if someone suggests adding it as a framework, or something like that). Xcode recognizes USER_HEADER_SEARCH_PATHS fine (as in this question); why doesn't it work here?
Perhaps adding something like this to your CMakeLists.txt?
find_library(GLEW_LIB GLEW /opt/local/lib)
if(NOT ${GLEW_LIB})
message(FATAL_ERROR "Could not find GLEW")
endif()
target_link_libraries(myprogram ${GLEW_LIB} ...)
Where myprogram is the name of the target executable that needs to link with the library. You would replace the ... with the other libraries you are using on that executable.
This way CMake would handle the library path details for you.
Xcode works on potentially multiple SDK's, so whenever your define these kinds of things (like HEADER_SEARCH_PATHS or LIBRARY_SEARCH_PATHS) the current SDK root is prepended to the actual path that's getting passed to the linker.
So, one way to make this work would be to add your directory to the SDK. For example, assuming you're building with the Mac OS X 10.5 sdk, you could add your opt dir:
ln -s /opt /Developer/SDKs/MacOSX10.5.sdk/opt
Your library would now be found on your system.
If you don't want to do this, then you will have to look at CMake and find out how to get it to generate a library requirement for your actual library (I don't know anything about CMake, so I can't help you there). This is also why you see a difference between USER_HEADER_SEARCH_PATHS and HEADER_SEARCH_PATHS re your other question.
As another option, you could also specify this path with the OTHER_LDFLAGS build variable:
OTHER_LDFLAGS=-L/opt/local/lib
This would cause the linker to search /opt/local/lib as well as its standard paths and wouldn't require you to generate a different project file.

Resources