Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

cmake - CMAKE_PREFIX_PATH and CMAKE_MODULE_PATH are both empty,find_package still works

I am new to cmake and currently studying find_package()

from doc : find_package

In Module mode, CMake searches for a file called Find.cmake. The file is first searched in the CMAKE_MODULE_PATH, then among the Find Modules provided by the CMake installation. If the file is found, it is read and processed by CMake. It is responsible for finding the package, checking the version, and producing any needed messages. Some find-modules provide limited or no support for versioning; check the module documentation.

for example,if I type find_package(OpenCV) and trun the cmake_find_debug_mode on by using :

cmake -DCMAKE_FIND_DEBUG_MODE=ON .

And, indeed the information print on the screen shows that it first try to search {Path where I install cmake}/Modules/FindOpenCV.cmake which i think but not truly sure is CMAKE_MODULE_PATH,but not found, and it keep searching and finally found OpenCVConfig.cmake from the environment variable OpenCV_DIR that I define in one script.

Everything would I expect until I print out the message

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

where the first one from doc is defined as "Path used for searching by FIND_XXX(), with appropriate suffixes added".

And both of them return nothing...

I have two questions :

(1) why is find_package even ${CMAKE_MODULE_PATH} is empty? (2) How to see all these environment variables define by cmake, e.g., CMAKE_MODULE_PATH ?

THANKS!!

question from:https://stackoverflow.com/questions/66057135/cmake-prefix-path-and-cmake-module-path-are-both-empty-find-package-still-works

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'll be brief.

One important thing you should realize, is that, unlike GNU Makefile, CMake variables and environment variables are different. You seem to be mixing these terms in your question.

The find_package doc is very precise about its search procedure. I believe if you read the entire thing, you can answer this question yourself.

It's not that I don't want to answer in detail. It's just that I can't explain more clearly than the doc itself.

Instead I'll just make some key points:

  • CMAKE_MODULE_PATH is where CMake searches "Find Modules", that is, FindOpenCV.cmake, if it exists, which does not in this world we live in, because of the next point.

  • Because the authors of OpenCV provide a "Config" file, there is no need for anyone to write a "Find Module". CMAKE_PREFIX_PATH is where CMake searches in lots of find_xxx APIs, including find_package, as it will be able to find OpenCVConfig.cmake, if you set the path correctly. But in your case, it's empty.

  • You've set the env var OpenCV_DIR, which is precisely why everything works. According to the doc, this var helps find the package:

Config mode search attempts to locate a configuration file provided by the package to be found. A cache entry called PackageName_DIR is created to hold the directory containing the file. By default the command searches for a package with the name PackageName. If the NAMES option is given the names following it are used instead of PackageName. The command searches for a file called PackageNameConfig.cmake or lower-case-package-name-config.cmake for each name specified. A replacement set of possible configuration file names may be given using the CONFIGS option. The search procedure is specified below. Once found, the configuration file is read and processed by CMake. Since the file is provided by the package it already knows the location of package contents. The full path to the configuration file is stored in the cmake variable _CONFIG.

Search paths specified in cmake-specific environment variables. These are intended to be set in the user’s shell configuration, and therefore use the host’s native path separator (; on Windows and : on UNIX). This can be skipped if NO_CMAKE_ENVIRONMENT_PATH is passed or by setting the CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH to FALSE:

PackageName_DIR

CMAKE_PREFIX_PATH

CMAKE_FRAMEWORK_PATH

CMAKE_APPBUNDLE_PATH


Edit:

Q: Why can CMake find OpenCV?

A: When find_package(OpenCV) is invoked, cmake will try to find OpenCVConfig.cmake from several locations. I've never bothered to remember the order of the locations (since I never have to).

It will look for:

  1. CMake variable CMAKE_PREFIX_PATH
  2. Environment variable CMAKE_PREFIX_PATH
  3. CMake variable OpenCV_DIR
  4. Environment variable OpenCV_DIR
  5. And a lot more...

Note: CMake variable is a semi-colon separated string, while environment variable on Unix systems is colon separated string.

From your description, it seems CMake finds OpenCV through option #4.

Note: Refer to the doc for more details since:

  • There are a lot more locations cmake will try looking up
  • There are small difference in these variables. (For instance they are controlled on/off by different find_package parameters, etc.)

Normally, one does not specify paths to find on a per-package basis. This is why CMAKE_PREFIX_PATH (Option #1) is more often used. (If not set, it's empty by default)

Usually, it is set on the command line, like this:

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

Then cmake will iterate each path separated by ;.

However of course, per-package basis has its own value: to prevent using the wrong version if multiple versions are installed on your pc (I've seen too many issues with /usr vs /usr/local/), like this:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...