This has an impact on the following functions:
When the executable hello is looking for the world library, the world library can be in several places:
Here is the order CMake will use to find headers and libraries, in this order:
Note that it makes no difference whether you are using qi_use_lib or find_package.
To make this work, we only use the CMAKE_FIND_ROOT_PATH cmake variable, and qi_use_lib calls find_package without any specific argument
This means that if you really need to find a library inside a toolchain, and never in the system, (for cross-compiling), you should use something like this for the toolchain file of your cross-toolchain
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
find_package(world)
Because we treat the CMAKE_FIND_ROOT_PATH variable very carefully ;)
Here’s what happens when you run qibuild configure hello:
In the main CMakeLists, you have project() before the call to find_package(qibuild).
So this means you go through the toolchain file first (calling project() makes cmake include the file passed with -DCMAKE_TOOLCHAIN_FILE.
The toolchain file generated by qitoolchain contains:
list(APPEND CMAKE_FIND_ROOT_PATH /path/to/toolchain/<name>)
(Note that qibuild configure calls cmake with the correct -DCMAKE_TOOLCHAIN_FILE for you)
Then, you go through qibuild-config.cmake which includes build/dependencies.cmake
The code in dependencies.cmake looks like
list(INSERT CMAKE_FIND_ROOT_PATH 0 /path/to/src/world/build/sdk)
So that sources are searched before the packages from toolchain
Finally, you go through qibuild/general.cmake
Here we do something like
set(CMAKE_FIND_ROOT_PATH "${QI_SDK_DIR}" ${CMAKE_FIND_ROOT_PATH})
so that self build dir is searched first.
Note that we never reset CMAKE_FIND_ROOT_PATH, so that if user set it from command lines, it exists even before going to the toolchain file, so it still has the priority.
When we call find_package(bar), we have several possible cases
Note
Due to strange CMake rules about case sensitivity, for this to work you it’s best you always use find_package() with an upper-case argument. find_package(GTest) won’t find gtest-config.cmake, but find_package(GTEST) will find it. (strange but true)
That’s why when we call find_package from qi_use_lib we alwayws use the upper-case version of the first argument.
To do this, we have to search for the -config.cmake files generated by qiBuild (or present ni qibuild/cmake/modules, then only for upstream Find-*.cmake in /usr/share/cmake)
This is not hard because find_package can be call with a special argument to only look for -config.cmake files.
From the comments in the cmake code:
# find_package in two calls. The first call:
# Uses NO_MODULE - looks for PKGConfig.cmake, not FindPKG.cmake
# Uses QUIET - no warning will be generated
# If Config is found, then PKG_DIR will be set so that the following
# find_package knows where to look
find_package(${_pkg} NO_MODULE QUIET)
# _PACKAGE_FOUND is only set when using qibuild/cmake modules,
# see comments in find.cmake for details.
if(NOT ${_U_PKG}_PACKAGE_FOUND)
find_package(${_pkg} QUIET REQUIRED)
endif()
# Right after find_package_handle_standard_args, ${prefix}_FOUND is
# set correctly.
# For instance, if foo/bar.h is not foud, FOO_FOUND is FALSE.
# But, right after this, since foo-config.cmake HAS been found, CMake
# re-set FOO_FOUND to TRUE.
# So we set ${prefix}_PACKAGE_FOUND in cache...
This has an impact on the functions:
And most of all, on find_package(qibuild)
We have several cases here:
To find the qibuild cmake files installed in a cross-toolchain, it is enough to do something like:
list(APPEND CMAKE_MODULE_PATH "${sysroot}/usr/share/cmake/Modules/")
To find the qibuild cmake files while using code from src/qibuild, we do something like:
# in python/qibuild/__init__.py
def get_cmake_qibuild_dir():
""" Try to guess where the qibuild cmake files are
"""
# in project.bootstrap()
cmake_module_path = get_cmake_qibuild_dir()
Then, when we run qibuild configure hello, the dependencies.cmake file is generated with the correct CMAKE_MODULE_PATH:
set(_qibuild_path "src/qibuild/cmake") # < this line configured by project.bootstrap()
list(FIND CMAKE_MODULE_PATH "${_qibuild_path}" _found)
if(_found STREQUAL "-1")
list(APPEND CMAKE_MODULE_PATH "${_qibuild_path}")
endif()