How is cmake finding my llvm cmake configuration?

I am wondering how is cmake finding my llvm cmake configuration if I haven't given it any variable telling it where to find it.

I am an LLVM newcomer. I am building a Hello World LLVM pass. I am on Ubuntu 16.04. My version of LLVM is 8.0.0. My version of CMake is 3.5.1.

This is my /CMakeLists.txt file:

cmake_minimum_required(VERSION 3.1)
project(FunctionDebugger)

find_package(LLVM REQUIRED CONFIG)
include_directories(${LLVM_INCLUDE_DIRS})

add_subdirectory(FunctionDebugger)
set(CMAKE_VERBOSE_MAKEFILE on)

This is the FunctionDebugger/CMakeLists.txt file:

add_library(LLVMFunctionDebugger MODULE
  FunctionDebugger.cpp
  )

set_target_properties(LLVMFunctionDebugger PROPERTIES
  COMPILE_FLAGS "-fno-rtti -std=c++11"
  )

I configure and compile like this:

mkdir build && cd build
cmake ..
make

It correctly compiles and links a shared library called libLLVMFunctionDebugger.so. What I don't understand is how cmake could find the package requested in:

# <project-root>/CMakeLists.txt
find_package(LLVM REQUIRED CONFIG)

I am not giving it any path nor I have anything defined in the environment but the path to the LLVM binaries. I read the CMake documentation, but it says that the find_package looks in folders under CMAKE_PREFIX_PATH. I print that variable with message(STATUS ${CMAKE_PREFIX_PATH}) and the output is empty.

Upvotes: 5

Views: 4597

Answers (2)

heturing
heturing

Reputation: 150

Since cmake 3.17, you can use cmake --debug-find <cmake-options> to ask cmake to output a bunch of debugging information on find_* functions. On my machine, it outputs

Standard system environment variables [CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].

/home/jiaqi/Documents/LLVM/llvm-project/build
/home/jiaqi/.local
/home/jiaqi/.yarn
/home/jiaqi/anaconda3
/home/jiaqi/anaconda3/condabin
/usr/local
/usr
/
/usr/games
/usr/local/games
/snap

... outputs omitted...

find_package considered the following locations for LLVM's Config module:

/home/jiaqi/Documents/LLVM/Test/build/CMakeFiles/pkgRedirects/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/Test/build/CMakeFiles/pkgRedirects/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/cmake/LLVMConfig.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/cmake/llvm-config.cmake
/home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake

The file was found at

/home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake

So, the cmake is using Config mode here and the file is located at /home/jiaqi/Documents/LLVM/llvm-project/build/lib/cmake/llvm/LLVMConfig.cmake

To figure out how cmake finds the LLVMConfig.cmake, take a look at https://cmake.org/cmake/help/latest/command/find_package.html#search-procedure

For step 5, it says the cmake will search the environment variable $PAT, and note that

Path entries ending in /bin or /sbin are automatically converted to their parent directories.

Since I have put the path to llvm executables in $PATH:

$ echo $PATH
/home/jiaqi/Documents/LLVM/llvm-project/build/bin:/home/jiaqi/.local/bin:/home/jiaqi/.yarn/bin:/home/jiaqi/anaconda3/bin:/home/jiaqi/anaconda3/condabin:/home/jiaqi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

The folder /home/jiaqi/Documents/LLVM/llvm-project/build will be used as prefix. According to https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure, the folder <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ will be searched.

Upvotes: 3

banach-space
banach-space

Reputation: 1811

Your set-up looks correct and clearly CMake is finding LLVMConfig.cmake script (i.e. the script that find_package consumes to propagate the necessary CMake variables with LLVM 8 set-up).

On the Ubuntu 16.04 machine that I have access to, LLVMConfig.cmake is located in /usr/lib/llvm-8/lib/cmake/llvm/LLVMConfig.cmake, but there's also a symlink in /usr/lib/llvm-8/cmake/. So the natural questions is: does CMake know that it should look there? The answer is yes. In CMake docs you can see that one of the search paths is:

<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/  (U)

You can verify that usr is on the list of prefixes by printing CMAKE_SYSTEM_PREFIX_PATH. On my machine that's set-up to:

/usr/local;/usr;/;/usr;/usr/local

Finally, you can print LLVM_DIR in your CMake script to check which version/installation of LLVM was picked by find_package. The variable will be empty on the first execution of CMake, but then find_package finds LLVM-8, the variable is set and saved in CMakeCache.txt.

Hope this helps.

EDIT

This answer was tested on Ubuntu 16.04 on which LLVM 8 was installed in the default, system-wide location through apt-get. If you install LLVM 8 elsewhere, then there are various ways of pointing CMake to the right location, see the docs for find_package. Editing the PATH variable is one of them:

  1. Search the standard system environment variables. This can be skipped if NO_SYSTEM_ENVIRONMENT_PATH is passed. Path entries ending in /bin or /sbin are automatically converted to their parent directories:

PATH

Upvotes: 3

Related Questions