CMake find_package() cannot find include dirs - c++

I am trying to install two projects: Foo and NeedsFoo. I have successfully compiled and locally installed Foo using cmake. However, I'm on a server and cmake doesn't appear to "remember" where Foo is.
In the cmake to configure NeedsFoo I have
list(APPEND CMAKE_MODULE_PATH "<prefix>/foo-install/CMake/FOO") # add path to FOOConfig.cmake
find_package(FOO REQUIRED)
if( FOO_FOUND )
MESSAGE(STATUS "Found FOO!")
endif( FOO_FOUND )
MESSAGE(STATUS ${FOO_INCLUDE_DIRS})
"Found Foo!" is printed --- so cmake finds FOO --- but the variable ${FOO_INCLUDE_DIRS} is empty and, therefore, the package does not compile. Any thoughts?
EDIT: There seems to be another copy of Foo installed on the server. Unfortunately, I can't use it (it is the 'master' branch of our project and I need to use my own branch). I tried changing the find_package call to
find_package(FOO REQUIRED PATHS "<prefix>/foo-install/CMake/Foo" NO_DEFAULT_PATH)
but that did not solve the problem.

Make sure the headers are installed, often you'll need to install a -dev or -devel package to get the headers. If they are installed and you can see them in your system, they might be on a path that cmake isn't expecting. Open the findFoo.cmake file (on Linux this will generally be in /usr/share/c make-x.y/modules) and check the list of expected locations, see if you're have installed in a less conventional one.

Related

find_package() ignores <PackageName>_ROOT

In my CMake script I append the path to a folder containing <PackageName>Config.cmake to <PackageName>_ROOT and then call find_package(<PackageName> REQUIRED) but it can't find my package.
When I use CMAKE_FIND_DEBUG_MODE I see my folder listed in <PackageName>_ROOT CMake variable [CMAKE_FIND_USE_PACKAGE_ROOT_PATH] (it is actually the only folder there), but it is not listed after find_package considered the following locations for the Config module:.
Why am I getting such behaviour? I use CMake 3.18.1 from Android Studio. The package I'm trying to find is OpenCV.
Relatively to my CMakeLists.txt file OpenCV is installed in ../../build/opencv-build<custom suffix>, so my code for finding it is:
get_filename_component(OPENCV_BUILD_DIRS_ROOT ../../build REALPATH)
file(GLOB OPENCV_BUILD_DIRS ${OPENCV_BUILD_DIRS_ROOT}/opencv-build*)
list(APPEND OpenCV_ROOT ${OPENCV_BUILD_DIRS})
find_package(OpenCV ${OPENCV_VERSION} REQUIRED ${OPENCV_PUBLIC_LIBRARIES} ${OPENCV_PRIVATE_LIBRARIES})
When I run it on Linux (WSL actually), everything works fine and CMake finds OpenCV succesfully in ../../build/opencv-build (or <project path>/build/opencv-build in the form of absolute path).
But when I try to build the project from Android Studio it doesn't, and I get this output from CMAKE_FIND_DEBUG_MODE:
CMake Debug Log at external/opencv/CMakeLists.txt:12 (find_package):
find_package considered the following paths for OpenCV.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/cmake/3.18.1/share/cmake-3.18/Modules/FindOpenCV.cmake
The file was not found.
<PackageName>_ROOT CMake variable [CMAKE_FIND_USE_PACKAGE_ROOT_PATH].
<project path>/build/opencv-build
CMAKE_PREFIX_PATH variable [CMAKE_FIND_USE_CMAKE_PATH].
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64
CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH variables
[CMAKE_FIND_USE_CMAKE_PATH].
Env variable OpenCV_DIR [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].
none
CMAKE_PREFIX_PATH env variable [CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].
none
CMAKE_FRAMEWORK_PATH and CMAKE_APPBUNDLE_PATH env variables
[CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH].
none
Paths specified by the find_package HINTS option.
none
Standard system environment variables
[CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH].
<a lot of unrelated directories>
CMake User Package Registry [CMAKE_FIND_USE_PACKAGE_REGISTRY].
none
CMake variables defined in the Platform file
[CMAKE_FIND_USE_CMAKE_SYSTEM_PATH].
C:/Users/<username>/AppData/Local/Android/Sdk/cmake/3.18.1
<other unrelated directories>
CMake System Package Registry
[CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY].
none
Paths specified by the find_package PATHS option.
none
find_package considered the following locations for the Config module:
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/opencv-config.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/opencv-config.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/i686-linux-android/21/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib/i686-linux-android/21/opencv-config.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/local/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/local/opencv-config.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/opencv-config.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/OpenCVConfig.cmake
C:/Users/<username>/AppData/Local/Android/Sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot/opencv-config.cmake
The file was not found.
So, the problem actually was that for Android (and, probably, iOS) CMake sets CMAKE_FIND_ROOT_PATH_MODE_PACKAGE variable (and other CMAKE_FIND_ROOT_PATH_MODE_* variables) to ONLY which makes find_package (and other find_* functions) prefix paths with what is in CMAKE_FIND_ROOT_PATH list.
To override this, one can do some of the following:
Set CMAKE_FIND_ROOT_PATH_MODE_* to BOTH or NEVER
Use CMAKE_FIND_ROOT_PATH_BOTH or NO_CMAKE_FIND_ROOT_PATH for each find_* call
It should also fix the issues when CMake ignores paths from HINTS, PATHS and other prefix construction steps.

How to have sub_directory use VCPKG in find_package() in CMake?

I'm trying to build PROJ from source. I don't have many of its dynamic dependencies on Centos 7, nor is it possible for me to obtain these dependencies through the system package manager.
In order to skirt these issues, I sought to use VCPKG. However VCPKG is in a lot of turmoil over PROJ and I cannot physically use any version past 7.2.x in VCPKG (I need newer features) and I can't load geo tiffs either (so most non trivial projections will straight up not work). So I can't use VCPKG and PROJ together at all.
However I can still comfortably get the dependencies required to run PROJ through VCPKG.
I tried to convert PROJ source into a subdirectory, however to my suprise it was still trying to use my system libraries despite -DCMAKE_TOOLCHAIN_FILE=... -DVCPKG_TARGET_TRIPLET=x64-linux being set.
I tried using the directory as a standalone library, but with the VCPKG variables set, and... it worked.
So I tried setting cache variables to see if somehow that wasn't propagated downwards, and it didn't work (error message same as below)
set(CMAKE_TOOLCHAIN_FILE "/home/user/Documents/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "TEST")
set(VCPKG_TARGET_TRIPLET "x64-linux" CACHE STRING "TEST")
add_subdirectory(external/PROJ)
My project is setup like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
...
my cmake is like this:
cmake_minimum_required(VERSION 3.13)
project(test)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(external/PROJ)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE PROJ::proj)
and I keep getting
-- Found Sqlite3: /usr/lib64/libsqlite3.so
-- Sqlite3 version: 3.7.17
CMake Error at external/PROJ/CMakeLists.txt:180 (message):
sqlite3 >= 3.11 required!
when PROJ is a subdirectory
and I get the correct thing:
-- Found Sqlite3: /home/user/Documents/vcpkg/installed/x64-linux/debug/lib/libsqlite3.a
-- Sqlite3 version: 3.36.0
when I don't use it as a sub-directory.
After the first project() call, it is much too late for CMAKE_TOOLCHAIN_FILE to do anything useful. Indeed, it won't even be read if it changes after the first project() call. Vcpkg, Conan, and the like must be used globally or not at all.
You could get away with writing something like this:
cmake_minimum_required(VERSION 3.21) # upgrade!! 3.13 is ancient
# Use vcpkg by default
if (EXISTS "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "TEST")
set(VCPKG_TARGET_TRIPLET "x64-linux"
CACHE STRING "default vcpkg triplet")
endif ()
project(test)
set(CMAKE_CXX_STANDARD 17
CACHE STRING "C++ standard to use")
if (CMAKE_CXX_STANDARD LESS 17)
message(FATAL_ERROR "Must compile `test` with C++17 or newer")
endif ()
add_subdirectory(external/PROJ)
add_executable(test main.cpp)
target_link_libraries(test PRIVATE PROJ::proj)
It is customary to set the environment variable VCPKG_ROOT to point to your vcpkg installation.
After fiddling around with this answer and wondering why it still wasn't working, I tried making an exact copy of the current MCVE in a different directory. To my surprise, it worked, and even worked with out caching (normal CMake command line variables). When using PROJ as a sub_directory, it actually only exposes PROJ as a target. However, I was trying to use PROJ::proj, a target apparently made by VCPKG to link against their install. Well I had uninstalled that, and wasn't using it as a dependency. Despite that, left over files in a separate build folder apparently were messing with my install, my directory originally looked like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
- cmake-build-debug
- cmake-build-release
Well, VCPKG stores some meta information about package caches and such in these directories. But with out completely deleting the whole directory I was not able to get it to "forget" about this old install. What's more, it took deleting both directories to get it to "fully" forget about proj.
So I deleted these files, like this:
- CMakeLists.txt
- main.cpp
- external
- PROJ
And reset/reloaded the CMake cache and file, and re-generated those build directories.
After doing this, I no longer had to worry about this extra target.

I'm stuck trying to clone a git repository which requires cmake files and dependancies

I want to download and use this repo:(https://github.com/rstebbing/subdivision-regression)
I have downloaded this repo, it's dependencies and their dependencies. Once downloaded, I've changed the CMakeList files (as instructed) with the new locations of the packages but when I try and 'sudo make install' it can't find the packages and won't install.
I am on a linux machine.
I downloaded these dependencies: ceres, common, gflags, rapidjson and believed they are install correctly.
When installing the subdivision I follow the git instructions and change the paths and ran cmake fine. When I use 'sudo make install' i get the error:
In file included from subdivision/doosabin/doosabin_pyx.h:12:0,
from subdivision/doosabin/doosabin_.cpp:615:
cpp/doosabin/include/doosabin.h:20:10: fatal error: Eigen/Dense: No such file or directory
#include "Eigen/Dense"
^~~~~~~~~~~~~
Even though I have specified the path to this file in the cpp/doosabin/CMakeLists and site.cfg:
site.cfg:
[Include]
EIGEN_INCLUDE ="/home/hert5584/RStebbing/eigen-git-mirror/"
COMMON_CPP_INCLUDE ="/home/hert5584/RStebbing/common/cpp/"ccd
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0)
PROJECT(DOO-SABIN)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin)
SET ( CMAKE_CXX_FLAGS "-std=c++11" )
MACRO(EXPECT_FILES VARIABLE)
FOREACH(EXPECTED_FILE ${ARGN})
IF (NOT EXISTS ${${VARIABLE}}/${EXPECTED_FILE})
MESSAGE(FATAL_ERROR
"Caller defined ${VARIABLE}: ${${VARIABLE}} does not contain "
"${EXPECTED_FILE}.")
ENDIF (NOT EXISTS ${${VARIABLE}}/${EXPECTED_FILE})
ENDFOREACH()
ENDMACRO(EXPECT_FILES)
SET(EIGEN_INCLUDE_DIR "/home/hert5584/RStebbing/eigen-git-mirror/")
EXPECT_FILES(EIGEN_INCLUDE_DIR Eigen/Dense)
INCLUDE_DIRECTORIES(${EIGEN_INCLUDE_DIR})
I also tested this without changing subdivision CMake files and only changing subdivions-regression and got a similar error about not finding functions.
Any help on how to install this properly, or any ideas about what I am doing wrong would be amazing!
Thank you
I made a mistake in setting up CMake. I was changing the paths manually inside the CMakeList files whereas it should be done with cmake:
cmake -DCOMMON_CPP_INCLUDE_DIR=/home/RStebbing/common/cpp -DEIGEN_INCLUDE_DIR=/home/RStebbing/eigen-git-mirror ../subdivision/cpp/doosabin/
Now working

how to get CMake to add MagickWand library linking automatically everywhere

I want to use CMake in my software that uses MagickWand.
CMake works on my machine and generates a useful Makefile.
On another machine, I have to manually add
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lMagickWand-6.Q16 -lMagickCore-6.Q16")
otherwise the linker can't find MagickWandGenesis() and other functions.
I found that -l flags via pkg-config --cflags --libs MagickWand.
Shouldn't CMake already generate linker flags for me with TARGET_LINK_LIBRARIES?
Did I miss something obvious, or why is this not working everywhere?
I have this code in CMakeLists.txt:
FIND_PACKAGE(ImageMagick
REQUIRED
COMPONENTS MagickWand
)
[...]
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16")
[...]
INCLUDE_DIRECTORIES(
${Boost_INCLUDE_DIR}
${ImageMagick_INCLUDE_DIRS}
${ImageMagick_MagickWand_INCLUDE_DIRS}
)
[...]
TARGET_LINK_LIBRARIES(application_name
[...]
${Boost_LIBRARIES}
${CURL_LIBRARIES}
${ImageMagick_LIBRARIES}
${ImageMagick_MagickWand_LIBRARY}
)
That last ${ImageMagick_MagickWand_LIBRARY} shouldn't even be necessary.
Using Magick 6.8.9.9, CMake 3.0.2 on both machines (Debian Jessie).
Short answer: the package ImageMagick is buggy.
Looking in CMake's sources, the REQUIRED mechanism is handled exclusively through the variable package-_FOUND, independently of the required components.
Looking in the package ImageMagick here, ImageMagick_FOUND is set as follows:
set(ImageMagick_FOUND ${IMAGEMAGICK_FOUND})
But IMAGEMAGICK_FOUND is not set anywhere in the package, so the call will always unset ImageMagick_FOUND, and it will always be evaluated to true (not actively set to false), wether or not the components are effectively found.
You can either debug the package (and propose a pull request) or check the component variable:
if(NOT ImageMagick_MagickWand_FOUND)
message(FATAL_ERROR "MagickWand not found")
endif()
I guess the test will fail on your second machine.
By the way, you should only use ImageMagick_INCLUDE_DIRS and ImageMagick_LIBRARIES to link to the library (the ImageMagick_MagickWand* variables are here redundant). If you choose to debug the package, you may also declare imported targets.
Figured it out, despite the output of
MESSAGE(${ImageMagick_FOUND})
MESSAGE(${ImageMagick_INCLUDE_DIRS})
MESSAGE(${ImageMagick_LIBRARIES})
MESSAGE(${ImageMagick_MagickWand_FOUND})
MESSAGE(${ImageMagick_MagickWand_INCLUDE_DIRS})
MESSAGE(${ImageMagick_MagickWand_LIBRARY})
being identical, the installed packages differed. I installed the magick-dev packages via virtual packages in aptitude, which for some reason used the graphicsmagick suite for some packages (a imagemagick fork) instead of the original imagemagick suite.
For reference, the used aptitude search one-liner was aptitude search 'magick ?installed' | sort which listed three graphicsmagick packages on the second machine where imagemagick packages were on the first machine.

CMake is not able to find BOOST libraries

I tried everything like:
Configure environment variable
Make fresh build
Re-install BOOST from source
sudo apt-get install libboost-all-dev
But still getting following Errors:
CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1131 (message):
Unable to find the requested Boost libraries.
Unable to find the Boost header files. Please set BOOST_ROOT to the root
directory containing Boost or BOOST_INCLUDEDIR to the directory containing
Boost's headers.
Call Stack (most recent call first):
CMakeLists.txt:147 (find_package)
CMake Error at /usr/share/cmake-2.8/Modules/FindBoost.cmake:1131 (message):
Unable to find the requested Boost libraries.
Unable to find the Boost header files. Please set BOOST_ROOT to the root
directory containing Boost or BOOST_INCLUDEDIR to the directory containing
Boost's headers.
Source code directory for boost: /usr/local/src/boost_1_45_0
Boost Library path: /usr/local/lib
Boost Header file: /usr/local/include/boost
Here is bashrc file:
BOOST_ROOT="/usr/local/src/boost_1_45_0"
Boost_LIBRARY_DIRS="/usr/local/lib"
BOOST_INCLUDEDIR="/usr/local/src/boost_1_45_0"
How to solve these Errors? Am i missing something?
Edit:
cmake -DCMAKE_TOOLCHAIN_FILE=$ANDTOOLCHAIN -DBOOST_ROOT=/usr/local/src/boost_1_45_0 -DBOOST_INCLUDEDIR=/usr/local/include/boost -DBOOST_LIBRARYDIR=/usr/local/lib -DPYTHON_LIBRARIES=/usr/local/lib/python2.7 -DPYTHON_INCLUDE_DIRS=/usr/include/python2.7 -DCMA-DRDK_BUILD_PYTHON_WRAPPERS=
Try to complete cmake process with following libs:
sudo apt-get install cmake libblkid-dev e2fslibs-dev libboost-all-dev libaudit-dev
I'm using this to set up boost from cmake in my CMakeLists.txt. Try something similar (make sure to update paths to your installation of boost).
SET (BOOST_ROOT "/opt/boost/boost_1_57_0")
SET (BOOST_INCLUDEDIR "/opt/boost/boost-1.57.0/include")
SET (BOOST_LIBRARYDIR "/opt/boost/boost-1.57.0/lib")
SET (BOOST_MIN_VERSION "1.55.0")
set (Boost_NO_BOOST_CMAKE ON)
FIND_PACKAGE(Boost ${BOOST_MIN_VERSION} REQUIRED)
if (NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >= 1.55) required.")
else()
message(STATUS "Setting up BOOST")
message(STATUS " Includes - ${Boost_INCLUDE_DIRS}")
message(STATUS " Library - ${Boost_LIBRARY_DIRS}")
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
endif (NOT Boost_FOUND)
This will either search default paths (/usr, /usr/local) or the path provided through the cmake variables (BOOST_ROOT, BOOST_INCLUDEDIR, BOOST_LIBRARYDIR). It works for me on cmake > 2.6.
I got the same error the first time I wanted to install LightGBM on python (GPU version).
You can simply fix it with this command line :
sudo apt-get install cmake libblkid-dev e2fslibs-dev libboost-all-dev libaudit-dev
the boost libraries will be installed and you'll be fine to continue your installation process.
seems the answer is in the comments and as an edit but to clarify this should work for you:
export BUILDDIR='your path to build directory here'
export SRCDIR='your path to source dir here'
export BOOST_ROOT="/opt/boost/boost_1_57_0"
export BOOST_INCLUDE="/opt/boost/boost-1.57.0/include"
export BOOST_LIBDIR="/opt/boost/boost-1.57.0/lib"
export BOOST_OPTS="-DBOOST_ROOT=${BOOST_ROOT} -DBOOST_INCLUDEDIR=${BOOST_INCLUDE} -DBOOST_LIBRARYDIR=${BOOST_LIBDIR}"
(cd ${BUILDDIR} && cmake ${BOOST_OPTS} ${SRCDIR})
you need to specify the arguments as command line arguments or you can use a toolchain file for that, but cmake will not touch your environment variables.
I just want to point out that the FindBoost macro might be looking for an earlier version, for instance, 1.58.0 when you might have 1.60.0 installed. I suggest popping open the FindBoost macro from whatever it is you are attempting to build, and checking if that's the case. You can simply edit it to include your particular version. (This was my problem.)
Thanks Paul-g for your advise. For my part it was a bit different.
I installed Boost by following the Step 5 of : https://www.boost.org/doc/libs/1_59_0/more/getting_started/unix-variants.html
And then I add PATH directory in the "FindBoos.cmake", located in /usr/local/share/cmake-3.5/Modules :
SET (BOOST_ROOT "../boost_1_60_0")
SET (BOOST_INCLUDEDIR "../boost_1_60_0/boost")
SET (BOOST_LIBRARYDIR "../boost_1_60_0/libs")
SET (BOOST_MIN_VERSION "1.55.0")
set (Boost_NO_BOOST_CMAKE ON)
Long answer to short, if you install boost in custom path, all header files must in ${path}/boost/.
if you want to konw why cmake can't find the requested Boost libraries after you have set BOOST_ROOT/BOOST_INCLUDEDIR, you can check cmake install location path_to_cmake/share/cmake-xxx/Modules/FindBoost.
cmake which will find Boost_INCLUDE_DIR in boost/config.hpp in BOOST_ROOT. That means your boost header file must in ${path}/boost/, any other format (such as ${path}/boost-x.y.z) will not be suitable for find_package in CMakeLists.txt.
I had the same issue inside an alpine docker container, my solution was to add the boost-dev apk library because libboost-dev was not available.