I found out headers under "bits" directory are internal headers which general headers include.
Then what does the name "bits" stand for?
Related
I am working with a library that nominally stores its internal headers in a directory that is not itself on the include path, although its parent is. Including the intended entry point header ends up failing because it links to other internal headers via quoted include without the directory name.
I do #include <SDL2/SDL.h> which the compiler does find, in /usr/include/SDL2/SDL.h on my system, but it then fails to find "begin_code.h" which is included several layers deeper in SDLs internal header code.
In file included from /usr/include/SDL2/SDL.h:32:
In file included from /usr/include/SDL2/SDL_main.h:25:
In file included from /usr/include/SDL2/SDL_stdinc.h:31:
In file included from /usr/include/SDL2/SDL_config.h:4:
In file included from /usr/include/x86_64-linux-gnu/SDL2/_real_SDL_config.h:33:
/usr/include/x86_64-linux-gnu/SDL2/SDL_platform.h:179:10: fatal error: 'begin_code.h' file not found
#include "begin_code.h"
^~~~~~~~~~~~~~
1 error generated.
Adding -iquote /usr/include/SDL2 manually works in my case, but what about in build environments where the SDL2 headers were downloaded to some local directory? The point of cmake is to work with local configurations that vary, so adding a hard-coded single path based on platform would be dumb. I want some future person who wants to compile my code with the SDL2 headers downloaded to ~/projects/headers/SDL2 to be able to compile after specifying only ~/projects/headers to their include path, for example, so they don't have to deal with SDLs internal issues.
It seems to me that all I need is to iterate on every dir on the -iquote path and, if it contains a directory name SDL2, add that directory to the -iquote. Does cmake make available the (system configuration dependent) -iquote path as an traversable list?
This question is my attempt to rephrase this unasnwered question for clarity.
Edit: I get that cmake is not responsible for fixing the issue, but cmake (or, rather, a CMakeList.txt file in my project) should be capable of working around this SDL bug. Hard-coding the assumed path is only reliable for build systems that install SDL2 headers via some standard package manager. I've never seen a unix dev manually download header files and stick them in the system include path, for fear that they might be overwritten or otherwise conflict with a future install of an official headers package. There are other valid places to put include files, so cmake should be able to search them. Isn't eliminating hard-coded paths half the point of cmake?
CMake doesn't provide a way for a custom iteration over include directories.
Instead, you could reformulate your intentions into the form "find a directory with the given header".
That form is expressed with command find_path, which is a natural way in CMake for search include directories.
E.g. that call:
# Task for CMake: Find a directory with "begin_code.h" header in it.
# Possibly, this is subdirectory 'SDL2' of a "normal" include directory.
find_path(SDL2_INCLUDE_DIR_1 "begin_code.h" PATH_SUFFIXES "SDL2")
will fill the variable SDL2_INCLUDE_DIR_1 with the directory containing the header begin_code.h.
This way works perfectly in case of local installation of SDL2, if that installation is hinted for CMake with CMAKE_PREFIX_PATH variable. For support other hints, e.g. SDL2DIR environment variable, you need to add appropriate PATHS options to your call:
find_path(SDL2_INCLUDE_DIR_1 "begin_code.h" PATH_SUFFIXES "SDL2" PATHS ENV SDL2DIR)
If you feel that SDL2 developers could rename the problematic file, but expect that file to be near the SDL2.h, then you could change the above command to search SDL2.h instead of begin_code.h:
find_path(SDL2_INCLUDE_DIR_1 "SDL2.h" PATH_SUFFIXES "SDL2" PATHS ENV SDL2DIR)
My colleague wrote a CMakeLists.txt, which contains things as below:
find_package(OpenCV 3 REQUIRED
COMPONENTS
opencv_core
opencv_imgproc
opencv_imgcodecs
CONFIG
)
As the project needs these components of Opencv3, my colleague downloaded the whole Opencv3, of course, it works.
But the whole Opencv3 is too big, so I get only the necessary lib files: libopencv_core.so, libopencv_imgproc.so and libopencv_imgcodecs.so and try to replace the whole Opencv3. The three so files are put here: /opt/opencv3/.
I don't know how to tell the CMakeLists.txt to look for the components of Opencv3 at the specific path instead of the path by default.
I'm totally a newbie on writing CMakeLists.txt...
CMake find_package() finds and configure project dependencies in CMake using two modes of operation, Module and Config, as described in its documentation.
In Module mode (not your case), it looks for a Find<package>.cmake file inside CMAKE_MODULE_PATH. This file searches for header files and libraries and set the necessary CMake variables in case of success.
In your case it is using Config, as requested by the CONFIG keyword. In Config mode CMake looks for for a <name>Config.cmake file or <lowercase-name>-config.cmake.
These config files describe the version of the dependency and the location of header files and library modules.
So you should look for OpenCVConfig.cmake or opencv-config.cmake in CMAKE_PREFIX_PATH or in OpenCV_DIR.
Please note that you have to set(OpenCV_DIR ...) before calling find_package().
How to tell CMake that directory is generated so that it doesn't complain before building process that directory doesn't exist?
My library project is used by many clients and for every client I have client-specific configuration generated by scripts and placed into generated/[client-name]/generated.h header. So for every client there's is folder generated. But parent project source files (*.cpp) include just generated.h. I wanted to add generated/[client-name] interface include directory for my library by using:
set_target_properties(mylib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "generated/myclient" ...)
but CMake complains even before starting compilation - Imported target "xxx" includes non-existent path. So I guess CMake doesn't like that include directory is missing when it starts building process although target depends on other targets which should create correct directory & header file within it.
You can create the directory first with CMake:
file(MAKE_DIRECTORY "generated/myclient")
This will have no effect if the directory exists already.
I have a project that uses a 3rd party library (let's call it somelib) for which I wrote a cmake file to search for it.
This is the somelibConfig.cmake file I wrote and placed in /usr/local/lib/cmake/somelib/:
FIND_LIBRARY(somelib_LIBRARY somelib
PATHS /usr/local/lib
NO_DEFAULT_PATH
)
SET(somelib_LIBRARIES ${somelib_LIBRARY})
FIND_PATH(somelib_INCLUDE_DIR somelib.hpp
PATHS /usr/local/include/somelib
NO_DEFAULT_PATH
)
SET(somelib_INCLUDE_DIRS ${somelib_INCLUDE_DIR})
Then, if I do find_package(somelib REQUIRED) it works ok.
However, if I move and rename somelibConfig.cmake to myproject/CMakeModules/Findsomelib.cmake (this directory is added to CMAKE_MODULE_PATH), after find_package I see that variables somelib_INCLUDE_DIRS and somelib_LIBRARY are correctly filled, but somelib_FOUND is not set (and even so, find_package does not abort the compilation).
Is that *Config.cmake valid for a Find*.cmake?
How is it possible that all the variables but the *_FOUND one are set?
Why does not find_package with REQUIRED abort the compilation if *_FOUND is not set?
Config files and find-modules are fundamentally different.
http://www.cmake.org/cmake/help/v3.0/manual/cmake-packages.7.html
Only the developers of somelib ship a config file (if they do). If they don't, then you need to write a find-module to find somelib. Such a find-module should not be copied to /usr/local as you did. Just keep it with your project and ask the somelib developers to ship a config file instead. config files shipped by upstream is superior to find modules written by you. It doesn't matter if somelib upstream does not use cmake. Both Qt and LLVM ship config files when using non-cmake buildsystems.
One example of inferiority is that when writing a find-module you need to set the _FOUND variable. More information about writing find-modules is here:
http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#manual:cmake-developer%287%29
If you are searching in default library folder your parameters should not contain NO_DEFAULT_PATH.
Try this,
SET(libraryName "somelibrary.so") #in linux .a or .so
FIND_LIBRARY(LIBRARY ${libraryName}
PATHS "/usr/local/lib/cmake/somelib/"
)
MESSAGE("library path ${LIBRARY})
If this was successful, LIBRARY_FOUND will be set.
P.S: Note the quotes
I'm building some code using CMake that should be compiled against the ScriptingBridge.
I'm seeing many tens of thousands of log lines such as:
In file included from /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmapple.h:30,
from /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/Security.h:25,
from /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSURLCredential.h:9,
from /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:70,
from /Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/AppKit.framework/Headers/AppKit.h:10,
from /Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/include/apple/itunes.h:5,
from /Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/src/osx/itunes_scripting_bridge.m:1:
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:142: warning: ‘CSSM_GUID’ is deprecated
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:143: warning: ‘CSSM_VERSION’ is deprecated
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:156: warning: ‘CSSM_GUID’ is deprecated
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:197: warning: ‘CSSM_DATA’ is deprecated
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:217: warning: ‘CSSM_DATA_PTR’ is deprecated
/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Security.framework/Headers/cssmtype.h:220: warning: ‘CSSM_DATA’ is deprecated
(Full extensive output here)
The files are being compiled with:
/usr/bin/c++ -I/Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/include -I/Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/../libwatchedit/include -x objective-c -o CMakeFiles/whatsplaying.dir/src/osx/itunes_scripting_bridge.m.o -c /Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/src/osx/itunes_scripting_bridge.m
/usr/bin/gcc -I/Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/include -I/Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/../libwatchedit/include -F/Developer/SDKs/MacOSX10.7.sdk/System/Library/Frameworks -x objective-c -o CMakeFiles/whatsplaying.dir/src/osx/itunes_scripting_bridge.m.o -c /Users/codebeaker/Projects/watchedit-client-code/src/libwhatsplaying/src/osx/itunes_scripting_bridge.m
Having reviewed the man page for (Clang) gcc on my Mac, there's this which sounds interesting:
-Fdir
Add the framework directory dir to the head of the list of directories to be searched for header files. These directories are interleaved with those
specified by -I options and are scanned in a left-to-right order.
A framework directory is a directory with frameworks in it. A framework is a directory with a "Headers" and/or "PrivateHeaders" directory contained
directly in it that ends in ".framework". The name of a framework is the name of this directory excluding the ".framework". Headers associated with
the framework are found in one of those two directories, with "Headers" being searched first. A subframework is a framework directory that is in a
framework's "Frameworks" directory. Includes of subframework headers can only appear in a header of a framework that contains the subframework, or in
a sibling subframework header. Two subframeworks are siblings if they occur in the same framework. A subframework should not have the same name as a
framework, a warning will be issued if this is violated. Currently a subframework cannot have subframeworks, in the future, the mechanism may be
extended to support this. The standard frameworks can be found in "/System/Library/Frameworks" and "/Library/Frameworks". An example include looks
like "#include ", where Framework denotes the name of the framework and header.h is found in the "PrivateHeaders" or "Headers"
directory.
-iframeworkdir
Like -F except the directory is a treated as a system directory. The main effect is to not warn about constructs contained within header files found
via dir.
Maybe I ought to be looking for -iframework. When building with -iframework on the terminal, manually this completes without any deprecation warnings.
However CMake doesn't support an option to use -framework. From their find_library() documentation:
CMake will use a -framework A, and a -F to link the framework to the target.
I'm looking for any way to have a quiet build. I also have (4x) smaller warnings from OpenSSL'x EVA interface, those I can handle... thanks in advance.
The answer was to use -iframework, probably as this is intended to ignore system level deprecation warnings when you can't resolve them.
Instead I was able to use -Wno-deprecated-declarations, a flag to GCC which is documented and available everywhere. It's reliable, and I include it in my CMake declaration as such:
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
find_and_add_framework(Foundation watchedit)
find_and_add_framework(Cocoa watchedit)
find_and_add_framework(AppKit watchedit)
find_and_add_framework(ScriptingBridge watchedit)
set_source_files_properties(${sources} PROPERTIES COMPILE_FLAGS
"-xobjective-c -Wno-deprecated-declarations")
set_source_files_properties(${sources} PROPERTIES LANGUAGE C)
ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
For anyone who would benefit, here's the implementation of find_and_add_framework. I'm not sure where I cribbed it from, but it's not my own work:
macro(FIND_AND_ADD_FRAMEWORK fwname appname)
find_library(FRAMEWORK_${fwname}
NAMES ${fwname}
PATHS ${CMAKE_OSX_SYSROOT}/System/Library
PATH_SUFFIXES Frameworks
NO_DEFAULT_PATH)
if( ${FRAMEWORK_${fwname}} STREQUAL FRAMEWORK_${fwname}-NOTFOUND)
MESSAGE(ERROR ": Framework ${fwname} not found")
else()
TARGET_LINK_LIBRARIES(${appname} ${FRAMEWORK_${fwname}})
# MESSAGE(STATUS "Framework ${fwname} found at ${FRAMEWORK_${fwname}}")
endif()
endmacro(FIND_AND_ADD_FRAMEWORK)