find_libraryВ¶
A short-hand signature is:
The general signature is:
This command is used to find a library. A cache entry named by is created to store the result of this command. If the library is found the result is stored in the variable and the search will not be repeated unless the variable is cleared. If nothing is found, the result will be -NOTFOUND .
Specify one or more possible names for the library.
When using this to specify names with and without a version suffix, we recommend specifying the unversioned name first so that locally-built packages can be found before those provided by distributions.
Specify directories to search in addition to the default locations. The ENV var sub-option reads paths from a system environment variable.
Specify additional subdirectories to check below each directory location otherwise considered.
Specify the documentation string for the cache entry.
New in version 3.18.
Stop processing with an error message if nothing is found, otherwise the search will be attempted again the next time find_library is invoked with the same variable.
If NO_DEFAULT_PATH is specified, then no additional paths are added to the search. If NO_DEFAULT_PATH is not specified, the search process is as follows:
New in version 3.12: If called from within a find module or any other script loaded by a call to find_package(
) , search prefixes unique to the current package being found. Specifically, look in the _ROOT»> _ROOT» title=»
_ROOT CMake variable and the _ROOT»> _ROOT» title=»
_ROOT environment variable. The package root variables are maintained as a stack, so if called from nested find modules or config packages, root paths from the parent’s find module or config package will be searched after paths from the current module or package. In other words, the search order would be _ROOT , ENV < _ROOT>,
_ROOT> , etc. This can be skipped if NO_PACKAGE_ROOT_PATH is passed or by setting the CMAKE_FIND_USE_PACKAGE_ROOT_PATH to FALSE . See policy CMP0074 .
Once one of the calls succeeds the result variable will be set and stored in the cache so that no call will search again.
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. The NAMES_PER_DIR option tells this command to consider one directory at a time and search for all names in it.
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 ). Therefore one may specify library file names such as libfoo.a directly. This can be used to locate static libraries on UNIX-like systems.
If the library found is a framework, then will be set to the full path to the framework /A.framework . When a full path to a framework is used as a library, CMake will use a -framework A , and a -F to link the framework to the target.
If the CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX variable is set all search paths will be tested as normal, with the suffix appended, and with all matches of lib/ replaced with lib$
If the FIND_LIBRARY_USE_LIB32_PATHS global property is set all search paths will be tested as normal, with 32/ appended, and with all matches of lib/ replaced with lib32/ . This property is automatically set for the platforms that are known to need it if at least one of the languages supported by the project() command is enabled.
If the FIND_LIBRARY_USE_LIBX32_PATHS global property is set all search paths will be tested as normal, with x32/ appended, and with all matches of lib/ replaced with libx32/ . This property is automatically set for the platforms that are known to need it if at least one of the languages supported by the project() command is enabled.
If the FIND_LIBRARY_USE_LIB64_PATHS global property is set all search paths will be tested as normal, with 64/ appended, and with all matches of lib/ replaced with lib64/ . This property is automatically set for the platforms that are known to need it if at least one of the languages supported by the project() command is enabled.
cmake — find_library — custom library location
I’m currently trying to get CMake running for my project (on windows). I want to use a custom location where all libraries are installed. To inform CMake about that path I tried to do that:
But when I try to find the library with
CMake can’t find it. When I set my prefix path to
. the library is located.
So my question is: How can I configure CMake properly to work with a directory structore at a custom location which looks like that:
In «include» lie the public headers and in «lib» are the compiled libraries.
Hope someone can help me — Thanks in advance
edit: The current workaround for me is, to do this before i search for libraries:
But that way the default module for boost wont find it until it because the directory structore of boost is a bit different.
When I move the content if «boost-1_50» to «include» the library can be found but that way it’s not possible to handle multiple versions right?
6 Answers 6
The simplest solution may be to add HINTS to each find_* request.
For Boost I would strongly recommend using the FindBoost standard module and setting the BOOST_DIR variable to point to your Boost libraries.
I saw that two people put that question to their favorites so I will try to answer the solution which works for me: Instead of using find modules I’m writing configuration files for all libraries which are installed. Those files are extremly simple and can also be used to set non-standard variables. CMake will (at least on windows) search for those configuration files in
(which can be set through an environment variable). So for example the boost configuration is in the path
In that configuration you can set variables. My config file for boost looks like that:
Pretty straight forward + it’s possible to shrink the size of the config files even more when you write some helper functions. The only issue I have with this setup is that I havn’t found a way to give config files a priority over find modules — so you need to remove the find modules.
Hope this this is helpful for other people.
cmake find sqlite3 library on windows
I am having more trouble than I’d expect getting CMake to find the sqlite3.dll library on Windows 7 (64-bit if that matters). I have downloaded and placed the latest sqlite3.dll and sqlite3.def files to C:\Windows\System32 . I am using the FindSqlite3.cmake module below:
This works fine on Linux, but not on Windows. I have spent a few hours now attempting small changes to other CMAKE variables with no luck. It seems like it should be straight forward getting CMake to find this dll . Could I get some help getting this to find the sqlite3 library on Windows?
2 Answers 2
There are some issues here and also some weird Windows stuff!
First issue; when searching for a library on Windows with MSVC as the generator, CMake will always look for a «.lib» file — never a «.dll», even if you specify e.g. sqlite3.dll as the NAMES argument to find_library . This is unfortunately not properly documented, in fact the docs for CMAKE_FIND_LIBRARY_SUFFIXES wrongly state:
This specifies what suffixes to add to library names when the find_library command looks for libraries. On Windows systems this is typically .lib and .dll, meaning that when trying to find the foo library it will look for foo.dll etc.
You can easily check this; simply add
to your CMakeLists.txt. You should see output like:
This thread from the CMake mailing list further confirms this behaviour. If you really need to find the dlls, you’ll need to use the find_file command, e.g:
The next issue is a minor one. You should prefer PATHS to HINTS as the argument in find_xxx commands if it’s a hard-coded guess. From the docs for find_library :
3 . Search the paths specified by the HINTS option. These should be paths computed by system introspection, such as a hint provided by the location of another item already found. Hard-coded guesses should be specified with the PATHS option.
A slightly more serious issue is in the line:
You should specify sqlite3d first then sqlite3 or sqlite3 will incorrectly be chosen as the Debug library if both are available.
And now the weirdness.
On a Windows x64 system, the find_xxx partially ignores the C:\Windows\System32 directory in favour of the C:\Windows\SysWOW64 one.
If you don’t have the sqlite3.lib in C:\Windows\SysWOW64, then the find_library command will always fail, regardless of the PATHS argument.
However, if you do have C:\Windows\SysWOW64\sqlite3.lib, then any combination of C:/Windows/SysWOW64 and/or C:/Windows/System32 as the PATHS argument finds the library, but sets the full path to C:/Windows/System32/sqlite3.lib even if C:/Windows/System32/sqlite3.lib doesn’t exist! This is obviously useless if the library isn’t there; a linker error will result.
There is some further reading again from the CMake mailing list here.
Having said that, if you’re linking, you’ll be using the .lib files, not the .dlls, and System32 & SysWOW64 aren’t really the place for .lib files.
Как находить библиотеки с помощью CMake?
У меня в проекте используются библиотеки Boost и WebRTC. При попытке собрать проект возникает проблема со сборкой WebRTC вот скриншот.
CMakeLists.cmake:
LocalConfig.cmake:
P.S. В шапке верная версия. Советую внимательно смотреть на регистр переменных — имеет очень важное значение.
1 ответ 1
Поиск библиотек в CMake происходит с использованием базовых команд самого CMake, для поиска по файловой системе. Это такие команды как: find_path , find_library и т.д. Обычному пользователю, как правило, эти команды не нужны, потому что уже кто-то заранее написал скрипт CMake, состоящий из этих команд, который находит всю необходимую информацию по библиотеке/фреймворку.
Обычно такие скрипты имеют вид FindXXX.cmake, где XXX это имя библиотеки. Эти скрипты используются тогда, когда пользователь в своём CMake скрипте использует команду find_package . К примеру, find_package(Boost REQUIRED) ожидает найти файл FindBoost.cmake и когда находит его, то исполняет всё, что находится внутри этого файла.
CMake поставляется с целым набором таких файлов, которые можно найти в директории, где он установлен: share/cmake-xxx/Modules . Имея это список файлов мы можем посмотреть, что за библиотеки поддерживаются CMake из коробки, а также посмотреть, что могут потребовать соответствующие скрипты на вход, чтобы помочь найти ту или иную библиотеку.
Итак, мы перешили в эту директорию и нашли FindBoost.cmake. Благо этот скрипт имеет неплохую документацию, и из него мы сразу узнаём, что для помощи в нахождении boost, ему необходимо знать где находится папка с оным. Для этого он ждёт переменную BOOST_ROOT . Эта переменная может быть установлена как локально в скрипте CMake, так и глобально, как переменная окружения.
Т.е. для того, чтобы нам найти boost, мы можем написать следующее:
Но явно прописывать путь в общем файле это неправильно, лучше используйте переменную окружения или же некоторый обходной путь, который я опишу дополнительно позже.
Заметьте, что каждый скрипт уникален и то, что ожидает скрипт для boost, может отличаться от того, что требует другая библиотека. Поэтому всегда нужно смотреть документацию к скрипту, чтобы понять, чего он от тебя хочет. Если у скрипта хорошая документация, то всё сразу будет понятно. Если нет, тогда придётся из его содержимого понять самостоятельно, чего же он хочет (обычно это не так сложно).
Вооружившись всем вышеописанным идём искать FindWebRTC.cmake в директории CMake и не находим его. Что делать? Первым делом вбиваем в Яндекс FindWebRTC.cmake и, как правило, находим немало вариантов уже готового файла, один из котороых можно выбрать под свои нужды. Я взял первый попавшийся, и он ожидает установленной WEBRTC_ROOT_DIR в качестве помощи в поиске. Но как нам использовать этот файл, как сделать так, чтобы find_package его использовал? Очень просто: помещаем его в дерево исходников, скажем в 3rdParty/cmake . После чего добавляем в наш скрипт (до find_package ) такую строку:
После чего, скрипт должен находиться и выполняться. Нам же остаётся использовать его результаты ( WEBRTC_INCLUDE_DIR , WEBRTC_LIBRARIES ).
Пару слов хочется сказать по поводу того, как и где прописывать полные пути к директориям библиотек, которые помогают скриптам в поиске. Для этого я использую следующий механизм. В основном скрипте CMake добавляем такой код:
После чего добавляем файл LocalConfig.cmake со следующим содержимым:
И, собственно, всё. Каждый разработчик просто создаёт свой локальный конфиг, который никак не мешает основному файлу CMake.
Default values for CMAKE_FIND_LIBRARY_PREFIXES/CMAKE_FIND_LIBRARY_SUFFIXES
i guess i’m missing something very obvious here, but it seems to me that the cmake variables CMAKE_FIND_LIBRARY_PREFIXES/CMAKE_FIND_LIBRARY_SUFFIXES are not set to any «decent» default value depending on the current system/settings! i’ve checked the cmake docs and google, but there seems nothing about it really.
for example, a simple CMakeLists.txt essentially calling find_package(OpenSSL REQUIRED) will break unless you set the variables in your main file or directly invoke cmake -DCMAKE_FIND_LIBRARY_PREFIXES=lib -DCMAKE_FIND_LIBRARY_SUFFIXES=.so .. (on ubuntu w openssl/libssl-dev installed) on the other hand, the default values PREFIX/SUFFIX for targets are initialized «correctly» for each platform, even considering BUILD_SHARED_LIBS etc. why not for find_library?
does anyone know why/what the suggested (users) behaviour should be?
2 Answers 2
cmake variables CMAKE_FIND_LIBRARY_PREFIXES/CMAKE_FIND_LIBRARY_SUFFIXES are not set to any «decent» default value
Why do you think so? For instance:
Windows (Visual Studio):
calling find_package(OpenSSL REQUIRED) will break unless you set the variables in your main file
Just tested, works fine for me. Ubuntu 14.04. CMake 2.8.12.2 and CMake 3.1.0-rc2.
so i’ll answer this question myself again as i need more space than the comment allows.
The «something obvious» i’ve missed is that i accessed those values before invocation of «project(Foo)», and at that stage CMAKE_FIND_LIBRARY_PREFIXES and CMAKE_FIND_LIBRARY_SUFFIXES are not initialized yet. good to know in any case!
I was checking conditions on whether the main project could be built at all, and that involved checking if the cmake version is new enough and should be downloaded&built before anything further. on the other side, by cmake convention, you need to specify which minimum version you need before you issue any project commands. you see the deadlock there? so if i needed to build a newer cmake version on-the-fly, OpenSSL should be included if possible. this was detected using find_package(OpenSSL) , but that in turn accessed the un-initialized CMAKE_FIND_LIBRARY_PREFIXES and everything broke.