CMAKE_PREFIX_PATH и CMAKE_MODULE_PATH оба пусты, find_package все еще работает

#cmake

#cmake

Вопрос:

Я новичок в cmake и в настоящее время изучаю find_package()

из документа : find_package

В режиме модуля CMake выполняет поиск файла с именем Find.cmake. Поиск файла сначала выполняется в CMAKE_MODULE_PATH, затем среди модулей поиска, предоставляемых установкой CMake. Если файл найден, он считывается и обрабатывается CMake. Он отвечает за поиск пакета, проверку версии и создание любых необходимых сообщений. Некоторые модули поиска предоставляют ограниченную или вообще не поддерживают управление версиями; проверьте документацию модуля.

например, если я введу find_package(OpenCV) и проверю cmake_find_debug_mode с помощью :

 cmake -DCMAKE_FIND_DEBUG_MODE=ON .
 

И действительно, информация, отображаемая на экране, показывает, что сначала он пытается выполнить поиск {Path where I install cmake}/Modules/FindOpenCV.cmake , который, как я думаю, но не совсем уверен, есть CMAKE_MODULE_PATH , но не найден, и он продолжает поиск и, наконец, найден OpenCVConfig.cmake из переменной среды OpenCV_DIR , которую я определяю в одном скрипте.

Все, что я ожидаю, пока не распечатаю сообщение

 message(STATUS "CMAKE_PREFIX_PATH : ${CMAKE_PREFIX_PATH}")
message(STATUS "CMAKE_MODULE_PATH : ${CMAKE_MODULE_PATH}")
 

где первый из doc определяется как «Путь, используемый для поиска с помощью FIND_XXX(), с добавлением соответствующих суффиксов».

И оба они ничего не возвращают…

У меня есть два вопроса :

(1) почему find_package эвен ${CMAKE_MODULE_PATH} пуст? (2) Как увидеть все эти переменные среды, определенные cmake, например, CMAKE_MODULE_PATH ?

Спасибо!!

Ответ №1:

Я буду краток.

Одна важная вещь, которую вы должны понимать, заключается в том, что, в отличие от GNU Makefile, переменные CMake и переменные среды различны. Похоже, вы смешиваете эти термины в своем вопросе.

find_package Документ очень точно описывает свою процедуру поиска. Я верю, что если вы прочтете все это целиком, то сможете сами ответить на этот вопрос.

Дело не в том, что я не хочу отвечать подробно. Просто я не могу объяснить это более ясно, чем сам документ.

Вместо этого я просто сделаю несколько ключевых моментов:

  • CMAKE_MODULE_PATH где CMake выполняет поиск «Найти модули», то есть FindOpenCV.cmake , если он существует, чего нет в этом мире, в котором мы живем, из-за следующего пункта.
  • Поскольку авторы OpenCV предоставляют файл «Config», никому не нужно писать «Модуль поиска». CMAKE_PREFIX_PATH это место, где CMake выполняет поиск во множестве find_xxx API, в том числе find_package , как он сможет найти OpenCVConfig.cmake , если вы правильно зададите путь. Но в вашем случае он пустой.
  • Вы установили переменную env OpenCV_DIR , и именно поэтому все работает. Согласно документу, этот параметр помогает найти пакет:

Поиск в режиме конфигурации пытается найти файл конфигурации, предоставленный пакетом, который нужно найти. Для хранения каталога, содержащего файл, создается запись кэша с именем PackageName_DIR. По умолчанию команда ищет пакет с именем PackageName . Если задан параметр NAMES, вместо PackageName используются следующие за ним имена. Команда выполняет поиск файла с именем PackageNameConfig.cmake или с именем пакета в нижнем регистре config.cmake для каждого указанного имени. С помощью опции CONFIGS можно задать набор возможных имен файлов конфигурации для замены. Процедура поиска указана ниже. После нахождения файл конфигурации считывается и обрабатывается CMake. Поскольку файл предоставляется пакетом, он уже знает расположение содержимого пакета. Полный путь к файлу конфигурации хранится в переменной cmake _CONFIG .

Пути поиска, указанные в переменных среды, специфичных для cmake. Они предназначены для установки в конфигурации оболочки пользователя и, следовательно, используют собственный разделитель пути хоста (; в Windows и : в UNIX). Это можно пропустить, если передан NO_CMAKE_ENVIRONMENT_PATH или путем установки CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH в значение FALSE:

PackageName_DIR

CMAKE_PREFIX_PATH

CMAKE_FRAMEWORK_PATH

CMAKE_APPBUNDLE_PATH


Редактировать:

Вопрос: Почему CMake может найти OpenCV?

Ответ: При find_package(OpenCV) вызове cmake попытается найти OpenCVConfig.cmake из нескольких местоположений. Я никогда не утруждал себя запоминанием порядка расположения объектов (поскольку мне никогда не приходилось этого делать).

Он будет искать:

  1. Переменная CMake CMAKE_PREFIX_PATH
  2. Переменная среды CMAKE_PREFIX_PATH
  3. Переменная CMake OpenCV_DIR
  4. Переменная среды OpenCV_DIR
  5. И многое другое…

Примечание: переменная CMake представляет собой строку, разделенную точкой с запятой, в то время как переменная среды в системах Unix представляет собой строку, разделенную двоеточием.

Из вашего описания кажется, что CMake находит OpenCV с помощью опции # 4.

Примечание: обратитесь к документу для получения более подробной информации, поскольку:

  • Есть намного больше мест, которые cmake попытается найти
  • В этих переменных есть небольшая разница. (Например, они управляются включением / выключением с помощью разных find_package параметров и т.д.)

Обычно пути для поиска для каждого пакета не указываются. Вот почему CMAKE_PREFIX_PATH (вариант #1) используется чаще. (Если не задано, по умолчанию оно пустое)

Обычно он устанавливается в командной строке, например:

 cmake -D CMAKE_PREFIX_PATH="/install/path0;/install/path1/;...;/install/pathn/" .....
 

Затем cmake будет повторять каждый путь, разделенный ; .

Однако, конечно, для каждого пакета есть своя ценность: чтобы предотвратить использование неправильной версии, если на вашем ПК установлено несколько версий (я видел слишком много проблем с /usr vs /usr/local/ ), например:

 cmake -DOpenCV_DIR=/path/to/the/version/I/meant/to/use .....
 

Комментарии:

1. «Но в вашем случае он пустой. (Поскольку существует файл «Config», никому не нужно писать «Find Module»)» , я не совсем понимаю это предложение, особенно «существует файл «Config»», что это значит? И из этого cmake.org/cmake/help/v3.0/variable/CMAKE_PREFIX_PATH.html , CMAKE_PREFIX_PATH , по — видимому , означает быть пустым по умолчанию .

2. @Pro_gram_mer Извините, плохая формулировка. Я должен был объяснить, почему в этом мире нет «FindOpenCV.cmake», что никак не связано с тем, почему CMAKE_PREFIX_PATH пуст. Я отредактирую через минуту.

3. Хорошо, еще один вопрос по этой ссылке: cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html в нем говорится, что по умолчанию CMAKE_MODULE_PATH пуст, это на самом деле меня смущает, оно установлено пустым, однако, когда я запускаю cmake и включаю режим отладки, cmake фактически ищет пакет, находя что-то в {Path, где я устанавливаю cmake}/Modules/FindOpenCV.cmake.

4. @Pro_gram_mer Отредактировал еще немного внизу.

5. @Pro_gram_mer Это в значительной степени подходит для вашего случая. Просто для ясности, MODULE mode ищет FindOpenCV.cmake ; Config mode ищет OpenCVConfig.cmake . Когда авторы библиотеки предоставляют файл конфигурации, пользователям библиотеки не нужно писать FindOpenCV.cmake .