I'm trying to write a FindQwt.cmake module. I've googled the existing modules and none of them work for my installation.
My module's find path call currently looks like this:
find_path ( QWT_INCLUDE_DIR
NAMES qwt_global.h
HINTS ${QT_INCLUDE_DIR}
PATHS
/opt
/usr/include
/usr/local
/usr/local/include
"$ENV{LIB_DIR}/include"
"$ENV{INCLUDE}"
PATH_SUFFIXES qwt
)
The actual qwt_global.h file resides at the path: /opt/qwt-6.1.2/src/qwt_global.h
I can get this to work if I add the path suffix qwt-6.1.2/src, but it seems to me like it's going to defeat the purpose of having a find module if I need to hard code every version into it (Assume I'm checking later in the module that the versions are compatible and don't care which version is used within the compatible set).
I've tried qwt* and qwt*/src in the PATH_SUFFIXES, but to no avail.
It seems like this would be a common problem. Does anyone know how to fix this find_path call to be robust to having version numbers in the path?
EDIT: I'm using cmake 3.0.2
You can use FILE(GLOB ...) for this.
file(GLOB QWT_SEARCH_PATHS "/opt/qwt-*" "/usr/include/qwt-*")
find_path(QWT_INCLUDE_DIR
NAMES qwt_global.h
PATHS ${QWT_SEARCH_PATHS})
For a cleaner implementation, build a list of directories, then iterate the list to append the "qwt-*" glob.
Related
I use some libraries that I don't want built as part of every project that uses them. A very understandable example is LLVM, which has 78 static libraries. Even having the cmake code to find and import these in every cmakefile is excessive.
The obvious solution seems to be to use the "include" command, and to factor out relevant chunks of cmake script into *.cmake files, and set up a CMAKE_MODULE_PATH environment variable.
Except it just plain doesn't work. Cmake doesn't find the file I specify in the include command.
On the off-chance, I even tried specifying the path in the environment variable several ways - once with backslashes, once with forward slashes... - and I restarted the command prompt each time and checked that the environment variable was present and correct.
In the cmake manual, it kind of implies that a "file" is different from a "module" - only a module gets the automatic add-the-extension-and-search-the-path treatment. But there is no explanation of what the difference is. I guessed that the missing extension might be enough (as with standard modules) but clearly it isn't.
Searching the manual for "module" isn't much help as the word seems to be overloaded. For example, a module is also a dynamic library loaded using LoadLibrary/dl_open.
Can anyone explain what the difference is between a file and a module in this context, and how I create my own module so that the cmake include command can find and use it?
I'm using cmake 2.8.1 on Windows.
EDIT
I'm pretty confident that the problem here is not understanding how cmake is supposed to work. I think what I should be doing is writing something that find_package can work with.
As things stand though, I'm still some way from being able to answer my own question.
I believe that a CMake 'module' is simply a file that can be used with the find_package directive. That is, when you run find_package(Module), it searches for a file in the MODULE_PATH that is named FindModule.cmake.
That said, if you include a file without the extension, it too will search through your MODULE_PATH for that file.cmake. In a CMake project I'm working on, I have a very similar directory structure as to what you propose.
+ root/
+ CMakeLists.txt
+ cmake/
| + FindMatlab.cmake
| + TestInline.cmake
| + stdint.cmake
+ src/
+ include/
In CMakeLists.txt I have:
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package (Matlab) # runs FindMatlab.cmake
include(TestInline) # defines a macro:
test_inline (CONFIG_C_INLINE)
include(stdint) # simply executes flat CMake code
Perhaps your issue is that you are trying to define the Module path from the environment. Instead, try to simply append to it within the very CMakeList you try to access the modules/files.
I had this same question after reading the CMake include() command documentation. It states:
Load and run CMake code from the file given. [...snip for brevity...] If a module is specified instead of a file, the file with name .cmake is searched first in CMAKE_MODULE_PATH, then in the CMake module directory.
This leaves a lot of interpretation as to what CMake considers a module vs. a file, because a CMake module is a file on the file system after all. So what's the difference?
The CMake source code is the only place I could find the answer. Basically CMake considers the argument to include() to be a file if it looks like an absolute path. This means:
On Linux/Unix
The argument starts with either '/' or '~'
On Windows
The argument's second character is ':' (as in C:)
The argument starts with '\'
CMake assumes anything else that doesn't meet the above criteria is a Module. In which case it appends '.cmake' to the argument and searches the CMAKE_MODULE_PATH for it.
File is CMake listfile, example is CMakeLists.txt. Use following command to get the list of command used in
cmake --help-command-list
Module is a cmake file (*.cmake) which contain cmake commands.
As Matt B. put, the CMAKE_MODULE_PATH is not environment variable of your shell, but cmake variable.
To append your module path to CMAKE_MODULE_PATH
LIST(APPEND CMAKE_MODULE_PATH ${YourPath})
Or if you perfer your modules to be used first
LIST(INSERT CMAKE_MODULE_PATH 0 ${Yourpath})
Suppose your project has multiple authors and depends on some libraries that must be installed on your system - you don't ship them with the project.
Some people have installed that libraries in /usr, /usr/local/, /opt or /opt/local.
What is the best practice to add them to the include path, without messing up CMakeLists.txt with all possible paths?
I am aware of xxx_ROOT variables like BOOST_ROOT, but not all library detections based on such a variable.
Teach your users / co-authors to use custom CMAKE_PREFIX_PATH which they can pass to their CMake call:
cmake -DCMAKE_PREFIX_PATH=/opt/local;/home/brandstifter/boost-1.70/ ..
For each find command, CMake will also search within the paths from CMAKE_PREFIX_PATH. See its documentation.
Trying to change FindSDL.make to work with SDL2. The problem is that using mingw it doesn't find SDL2_INCLUDE_DIR, even though SDL2 is installed.
I've change the whole file, but the problems is in this line:
find_path(SDL2_INCLUDE_DIR
NAMES
SDL.h
PATH_SUFFIXES
include/SDL2
)
Thought it should look up MinGW folder, but it looks like it doesn't.
Actually, even this one doesn't work:
find_path(TEST_PATH stdio.h)
So what is the proper way to use find_path under mingw on Windows? Can it be related to mingw install path (preferred one is C:\MinGW, but I've installed it to E:\Programs\MinGW)?
Should I always explicitly write -DCMAKE_INCLUDE_PATH=<my path to mingw>\include or use environment variable that points to mingw folder and use it as a HINT to find_path?
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
cmake version 2.8.4
I have the following apache portable runtime libraries that I have compiled myself and want my application to link against.
My project directory where my apr libraries are:
gw_proj/tools/apr/libs
In my CMakeLists.txt I have the following:
FIND_LIBRARY(APRUTIL NAMES "aprutil-1"
PATHS ${PROJECT_SOURCE_DIR}/tools/apr/libs)
My problem is on a machine that already has the apache portable runtime already installed it will look for it in this folder:
/usr/lib
So will always ignore my custom path.
How can I force the FIND_LIBRARY to always look in my custom directory:
gw_proj/tools/apr/libs
Many thanks for any suggestions
You can specify the search order using one or more of NO_DEFAULT_PATH, NO_CMAKE_ENVIRONMENT_PATH
, NO_CMAKE_PATH, NO_SYSTEM_ENVIRONMENT_PATH, NO_CMAKE_SYSTEM_PATH, CMAKE_FIND_ROOT_PATH_BOTH, ONLY_CMAKE_FIND_ROOT_PATH, orNO_CMAKE_FIND_ROOT_PATH.
From the docs for find_library:
The default search order is designed to be most-specific to least-specific for common use cases. Projects may override the order by simply calling the command multiple times and using the NO_* options:
find_library(<VAR> NAMES name PATHS paths... NO_DEFAULT_PATH)
find_library(<VAR> NAMES name)
Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again.
So in your case, you can do
FIND_LIBRARY(APRUTIL NAMES "aprutil-1"
PATHS ${PROJECT_SOURCE_DIR}/tools/apr/libs NO_DEFAULT_PATH)