How to add multiple include file names under NAMES while using FIND_PATH in CMAKE? - cmake

I am trying to include several header files under NAMES while using FIND_PATH, was wondering if there was a way to include them without specifying each one of them.
Currently i use below format for this purpose.
FIND_PATH(FILE_INCLUDE
NAMES "xyz/x.h"
"xy/y.h"
......
......
PATHS "${CMAKE_CURRENT_SOURCE_DIR}"
PATH_SUFFIXES xy/yx/xyz
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
I was wondering if there was a easier way to specify the list of NAMES as there are lot to be added.

CMake provides the following command for recursive files globing:
file(GLOB_RECURSE variable [RELATIVE path] [FOLLOW_SYMLINKS]
[globbing expressions]...) Command documentation:
http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:file

Related

find_library chooses the static library instead of the shared library

This has been asked on SO before and there's even a related bug on this in CMAKE. However, my issue is a variation and the answer is not clear.
My wrinkle is that I'm cross-compiling for Windows on Linux using MinGW. Static libs are named like this libGLESv2.dll.a and libiconv.dll.a for the DLLs libGLESv2.dll and iconv.dll respectively.
Examples:
find_library(FOUND_LIB_X NAMES "zlib1.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: zlib1.dll
find_library(FOUND_LIB_Y NAMES "libGLESv2.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: libGLESv2.dll.a
find_library(FOUND_LIB_Y NAMES "iconv.dll" PATHS ${CMAKE_FIND_ROOT_PATH}/bin/)
finds this: libiconv.dll.a
The CMAKE bug seems to be referring to traditional situations where the static lib is named blah.lib (Windows) or blah.a (Linux). In this cross-compiler situation with mingw on Linux, they are named blah.dll.a
I need it to find the file literally called iconv.dll and nothing else. If it doesn't literally find that, then abort. Am I using the wrong CMAKE function? (don't use find_library()?)
CMake uses definite order between iterating library names and directories when search the library. E.g., according to documentation,
When more than one value is given to the NAMES option this command by default will consider one name at a time and search every directory for it.
That is, with libraries at dir1/name2 and dir2/name1
find_library(MYLIB NAMES name1 name2 PATHS dir1 dir2)
message(${MYLIB})
will print dir2/name1.
Specifying NAMES_PER_DIR option reverse the choice:
find_library(MYLIB NAMES name1 name2 NAMES_PER_DIR PATHS dir1 dir2)
message(${MYLIB})
will print dir1/name2.
Things are different with trying library's prefix and suffix:
Each library name given to the NAMES option is first considered as a library file name and then considered with platform-specific prefixes (e.g. lib) and suffixes (e.g. .so).
It seems that checking for lib<name>.so is performed immediately after <name> when iterating directories.
That is, with libraries at dir1/libname.so and dir2/name
find_library(MYLIB NAMES name PATHS dir1 dir2)
message(${MYLIB})
will print dir1/libname.so.
That is why libiconv.dll.a is found in your case: lib/ directory is searched as system specific path at step 5 of find_library search algorithm, but directory bin/, specified as PATH option, is searched only at step 6.
The simplest way to find what you want is to use NO_DEFAULT_PATH option, so searching in lib/ will not be performed at all:
find_library(FOUND_LIB_Y
NAMES "iconv.dll"
PATHS ${CMAKE_FIND_ROOT_PATH}/bin/
NO_DEFAULT_PATH
)

Order of hint paths in cmake find_library

I'm using HINTS with find_library and was surprised to find that the last path had priority. Is this intentional or something that can be configured.
set(MY_HINT_PATHS_A "/path/to/a;/path/to/b")
find_library(MY_LIBRARY_A
NAMES MyLib
HINTS ${MY_HINT_PATHS_A}/lib
ONLY_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
)
set(MY_HINT_PATHS_B "/path/to/b;/path/to/a")
find_library(MY_LIBRARY_B
NAMES MyLib
HINTS ${MY_HINT_PATHS_B}/lib
ONLY_CMAKE_FIND_ROOT_PATH NO_DEFAULT_PATH
)
message("MY_LIBRARY_A: ${MY_LIBRARY_A}")
message("MY_LIBRARY_B: ${MY_LIBRARY_B}")
prints
MY_LIBRARY_A: /path/to/b/lib/libMyLib.a
MY_LIBRARY_B: /path/to/a/lib/libMyLib.a
I would have expected
MY_LIBRARY_A: /path/to/a/lib/libMyLib.a
MY_LIBRARY_B: /path/to/b/lib/libMyLib.a
CMake list is not a type, but an interpretation of string value. So any operations on list-variables are actually operations on strings.
${MY_HINT_PATHS_A}/lib doesn't append /lib to all elements in the list, it appends /lib only to the last element:
"/path/to/b;/path/to/a/lib"
It is absolutely equivalent to appending /lib to the variable's string-value.
For get desired effect you may use lib with PATH_SUFFIXES option to the find_library command. Or directly append /lib suffix to every element in the list.

CMake: Managing a list of source files

The problem I'm having at the moment is that I simply wish to manage my list of source files by grabbing everything and removing the few odds and ends that I do not need. I was hoping that Cmake provided nice built-in tools for this.
So I might start with:
file(GLOB A "Application/*.cpp")
I feel like I want to create another list of files to be removed and I want to tell CMake: Remove from list A items that are in list B.
If this were Python I might do something like:
C = [f for f in A if f not in B]
I may have screwed that syntax up but I'm wondering if there is built-in support for managing these lists of files in a more elegant way?
Even if I could do something like my Python example, A is list of absolute paths so constructing B is clunky.
And why absolute paths anyway? It seems like this will break your build as soon as you relocate the source.
You can do that by using the list command with the REMOVE_ITEM option:
list(REMOVE_ITEM <list> <value> [<value> ...])
Have a look:
file(GLOB FOO *)
set (ITEMS_TO_REMOVE "item;item2;item3")
message(STATUS "FOO is ${FOO}")
list(REMOVE_ITEM FOO ${ITEMS_TO_REMOVE})
message(STATUS "FOO is now ${FOO}")
Keep in mind that the paths returned by file(GLOB) are absolute, you might want to build your list of items to remove by prepending ${CMAKE_CURRENT_LIST_DIR} to each one of them:
set (ITEMS_TO_REMOVE "${CMAKE_CURRENT_LIST_DIR}/item;
${CMAKE_CURRENT_LIST_DIR}/item2;
${CMAKE_CURRENT_LIST_DIR}/item3")
If you like Python, you can generate your list of source files with execute_process. There is also possiblity to work with lists.
But I would recommend you to "hardcode" your list of source files.
File command documentation states:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.

CMake find_library matching behavior?

One specifies find_library(<var> name PATHS path1..pathn)
My question is how does find_library() match name to the library file (on Windows and Linux)?
For example, I am unable to have find_library() identify the MagicK and MagicK++ DLL files in the provided Windows binary installation of GraphicsMagicK:
The files is: CORE_RL_magick_.dll
Searching for the queries: magick or CORE_RL_magick does not work.
You might want to take a look at this documentation links:
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:find_library
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#variable:CMAKE_FIND_LIBRARY_PREFIXES
http://www.cmake.org/cmake/help/v2.8.10/cmake.html#variable:CMAKE_FIND_LIBRARY_SUFFIXES
find_library may accept one or more library names. Those names get the value of CMAKE_FIND_LIBRARY_PREFIXES prepended and CMAKE_FIND_LIBRARY_SUFFIXES
appended. This two variables should be set for each OS depending on how the librares are prefixed or suffixed there.
In your case I'd write for Windows
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
and for Linux
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
and then write
find_library(
magick
CORE_RL_magick_ (or NAMES if there are multiple names for the same library on different systems)
PATHS
path1
path2
...
(other options that are specified in documentation and would be usefull to you)
)
EDIT:
CMAKE_FIND_LIBRARY_PREFIXES and CMAKE_FIND_LIBRARY_SUFIXES are set automatically by project() command so calling it first and find_library() after that point is a better solution than setting the variables manually.
Why not use find_file() instead of find_library() if you want to find a .dll.

CMAKE aux_source_directory exclude pattern

I want to include all filed in source directory leaving one file.
Is there any way to using aux_source_directory or anything else I can include all files leaving that file ?
There are two possible solutions:
Use file (GLOB ... instead of aux_source_directory with a globbing expression that does not match that one file but includes all the others, e.g.:
file(GLOB _srcFiles "src/f[1-3].cpp")
This will match match files f1.cpp, f2.cpp, f3.cpp, but not f4.cpp.
Or use aux_source_directory and then remove the file to be excluded explicitly with a list(REMOVE_ITEM command, e.g.:
aux_source_directory(src _srcFiles)
list(REMOVE_ITEM _srcFiles "src/f4.cpp")