For the cmake “include” command, what is the diffe

2019-02-02 07:27发布

问题:

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.

回答1:

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_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.



回答2:

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.



回答3:

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})


标签: cmake