Report the location where find_package(Foo) found FindFoo.cmake - cmake

First, there is this answer that describes how to fiddle with FindCUDA.cmake so that we can link with CUDA 9.0+'s renamed NPP libraries correctly, but the default CMake 3.5.1 in Ubuntu 16.04 requires this code to be added manually.
However, if someone forgets to apply that change, or search paths are such that an older FindCUDA.cmake is picked up, I want to report an error. This code almost does that:
find_package(CUDA)
if (CUDA_VERSION VERSION_GREATER_EQUAL "9.0")
if (NOT CUDA_nppial_LIBRARY)
message(FATAL_ERROR "CUDA 9.0+ libraries not set in file at ${FINDCUDA_FILE}")
endif()
target_link_libraries(foo ${CUDA_nppial_LIBRARY})
endif()
Except that I don't know what to use for ${FINDCUDA_FILE} and searching the code doesn't give me any clues. Is there such a variable or other way to find that file?

Related

Why is VULKAN_LIBRARY set to VULKAN_LIBRARY-NOTFOUND yet VULKAN_FOUND is TRUE?

I'm interested in trying out Vulkan for myself, but I'm having difficulty getting CMake to link to it reliably. I decided to use CMake's FindVulkan module... or at least how I think it should work. Here's how I did it:
# Hey CMake. Look for Vulkan.
find_package(Vulkan REQUIRED)
# Alright, no errors? Tell me what you found!
message("Vulkan found? " ${VULKAN_FOUND})
message("Alright, where is it? " ${VULKAN_LIBRARY})
message("And I can include it? " ${VULKAN_INCLUDE_DIR})
And a little later in the file:
# Let's make a library and link vulkan
include_directories(${VULKAN_INCLUDE_DIR})
add_library(myLib myLib.cpp myLib.h)
target_link_libraries(myLib ${VULKAN_LIBRARY})
So, I get my results! First off, my CMake output:
Vulkan found? TRUE
Alright, where is it? VULKAN_LIBRARY-NOTFOUND
And I can include it? C:/VulkanSDK/1.0.65.1/Include
-- Could NOT find Vulkan (missing: VULKAN_LIBRARY)
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Using Win32 for window creation
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
VULKAN_LIBRARY (ADVANCED)
linked by target "TOVE" in directory C:/Users/User/Desktop/TOVE
Odd, looks like you found my include directory, but you can't find my library. The messages in the middle are actually GLFW. I kept them in just incase they meant something more. Finally, CMake stops with an error.
Some additional testing reveals that both ${VULKAN_LIBRARIES} and ${VULKAN_INCLUDE_DIRS} are blank. As expected, swapping them out with their singular counterparts makes Visual Studio 2017 mountains of confused about my vulkan/vulkan.h include.
I can't find any case on the internet where someone gets a VULKAN_LIBRARY-NOTFOUND, but there might be another library that has similar issues. Why am I finding only half of the information here? Is it an issue with Vulkan or CMake, or am I just really bad at writing with CMake. I'm relatively new to CMake, and I'm just experimenting with it so I apologize if it was just me misusing some important function or something among those lines.
I had the same error while trying to compile GLFW 3.2.1 on Windows. The problem is that GLFW CMakeLists uses its own FindVulkan.cmake in "${GLFW_SOURCE_DIR}/CMake/modules" which seems a bit outdated.
Taking some code from the FindVulkan.cmake inside CMake distribution (3.10) to modify the GLFW file works as expected and VULKAN_LIBRARY cache var is filled with the path of the .lib file.

Set CMAKE_INSTALL_PREFIX in toolchain.cmake

I have a toolchain.cmake defined for the platform I'm building for and in it I've specified the location where I want my files installed. However, when I run make install, the files go to the default location /usr/..... My toolchain.cmake is setup as follows:
# this one is important
SET(CMAKE_SYSTEM_NAME Linux)
#this one not so much
SET(CMAKE_SYSTEM_VERSION 1)
# specify the cross compiler
SET(CMAKE_C_COMPILER /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/bin/i686-aldebaran-linux-gnu-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/bin/i686-aldebaran-linux-gnu-g++)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot)
SET(CMAKE_SYSROOT /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
SET(THREADS_PTHREAD_ARG 1)
SET(CMAKE_INSTALL_FULL_INCLUDEDIR /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot/usr/local/include)
SET(CMAKE_INSTALL_FULL_LIBDIR /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot/usr/local/lib)
SET(CMAKE_INSTALL_FULL_MANDIR /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot/share/man)
SET(CMAKE_INSTALL_PREFIX /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot)
SET(CMAKE_STAGING_PREFIX /usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot)
As can be seen, I've gone overkill on setting paths, but none of them work. In order to have make install place the file in the correct location, I have to pass -DCMAKE_INSTALL_PREFIX=<path> in the cmake command as shown below:
cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=~/myScripts/Toolchain-Naoqi.2.1.4.13.cmake -DCMAKE_INSTALL_PREFIX=/usr/local/naoqi-sdk-2.1.4.13-mac64/ctc-mac64-atom-2.1.4.13/cross/i686-aldebaran-linux-gnu/sysroot ..
It would be nice not to have the path set in my toolchain.cmake as it applies to all the projects I'm building.
The reason why your paths are overwritten is that the call to project() comes after the execution of this Toolchain file. The project() function, among other things, sets CMAKE_INSTALL_PREFIX to some default value.
It is good practice not to specify CMAKE_INSTALL_PREFIX in your CMakeLists.txt, to ensure cross-platform compatibility. For example, your approach would prevent someone with a non-Unix-like system of using your file.
If you really want to go on and specify it within the code, I see two options:
Hardcode CMAKE_INSTALL_PREFIX in one of the CMakeLists.txt of your project, i.e. after the call to project().
Provide a custom 'platform' file, located in some_folder/Platform/<My_Platform>.cmake, and add some_folder to your CMAKE_MODULE_PATH. In this platform file, you then specify CMAKE_INSTALL_PREFIX, such that you don't need to clobber your other CMakeLists.txt (my assumption here is that you only need this installation folder for this specific platform).
It looks like this issue is caused by a bug in CMake itself, based on an old bug report in their former bug tracker, which was closed without fixing the problem.
The issue is summarised as
Specifying CMAKE_INSTALL_PREFIX in a CMAKE_TOOLCHAIN_FILE file has no
effect
which exactly describes the problem you are encountering.
For what it's worth, I also encounter this same problem when trying to cross-compile with CMake v3.5.1 using a toolchain file, so I don't think that the issue has been fixed.
The migrated bug report in CMake's current bug tracker may be found here.
Besides the workaround you have identified involving setting CMAKE_INSTALL_PREFIX inline in the install command, a more permanent solution might be reached by petitioning the CMake team to fix this bug, by adding your comments to the conversation in the migrated bug report.

How to set RPATH in CMAKE?

I wish to build and install a software locally to the $HOME/.local/ path instead of a system-wide /usr/ folder. The software uses CMAKE for compilation.
After installation, the software binaries and libraries get stored in $HOME/.local/bin/ and $HOME/.local/lib/, respectively. However, when I try to run the program, it throws an error that the required library is not found (which, by the way, is present in $HOME/.local/lib/).
The program works fine if I set the $LD_LIBRARY_PATH to $HOME/.local/lib. But I don't want to do this. Hence, instead of this, I would like to know how to specify the RPATH variable (which would point to $HOME/.local/lib) while compiling the software using CMAKE.
Kindly help.
I am using the following two lines in the CMakefile
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
(the first one is required only if you use MacOSX)
you may also use:
set(CMAKE_BUILD_RPATH "/my/libs/location")
specifying runtime path (RPATH) entries to add to binaries linked in the build tree (for platforms that support it). The entries will not be used for binaries in the install tree. See also the CMAKE_INSTALL_RPATH variable.
CMAKE_INSTALL_RPATH is a predefined list, so I can see scenarios where it would be better to do
list( APPEND CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib )
If you include( GNUInstallDirs ) you could also
list( APPEND CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_LIBDIR} )
I am a CMake novice though, so if someone sees an issue with the above please let me know.

Changed find_library behavior from CMake 2.8 to CMake 3.2

I have got the following problem while migrating from CMake 2.8.x to 3.2.x. Thereby, it seems that the internal behavior of find_library changed. Here is a minimal example which demonstrates my problem.
Consider that we are search for library called libopenblas.so which is located in /scratch/local_install/lib and /usr/lib/openblas-base. The LD_LIBRARY_PATH environment variable is set to /scratch/local_install/lib.
The CMakeLists.txt file is the following:
PROJECT(TEST)
cmake_minimum_required(VERSION 2.8)
SET(_libname "openblas")
SET(_libdir ENV LD_LIBRARY_PATH "/usr/lib/openblas-base")
find_library(OPENBLAS_LIBRARY
NAMES ${_libname}
HINTS ${_libdir}
PATHS ${_libdir}
)
MESSAGE("OPENBLAS: ${OPENBLAS_LIBRARY}")
If I execute this using CMake 2.8.7 or 2.8.12, I get
OPENBLAS: /scratch/koehlerm/local_install/lib/libopenblas.so
If I configure the code using CMake 3.2.1, I get
OPENBLAS: /usr/lib/openblas-base/libopenblas.so
which I only want to get if there is none libopenblas.so in the LD_LIBRARY_PATH. How can I restore the old behavior of CMake 2.8.x even if the code is configured with CMake 3.2.x?
Use NO_DEFAULT_PATH for find_library, then it will ignore the default location. See the documentation.
To get the bahvior you want, use find_library twice. First with NO_DEFAULT_PATH and after that without. If it is found the first time, the result is cached and the second call including the default path is skipped. If nothing is found first, it will be re-run and look at the default paths, too.

Linking against GLEW with CMake

My project depends on GLEW and is built with CMake, so i took the FindGLEW.cmake from here http://code.google.com/p/nvidia-texture-tools/source/browse/trunk/cmake/FindGLEW.cmake?r=96 and wrote find_package(GLEW REQUIRED) in my CMakeLists.txt. Problem is that i am working on a cluster PC were several versions of GLEW are available. One version is stored in /usr/lib which is not the latest. the latest version is stored in /opt/local/lib64. this is the version i want to link against. so i added the path to the FindGLEW.cmake under the GLEW_LIBRARY paths. the problem is that the makefile always links against the older version, but i need the newest version (1.7) for using stuff like GL_PATCHES, GL_PATCH_PARAMETERS and so on. can i some how force CMake to use the newer version like it is the case with FindBoost.cmake. one solution is to erase the older one's but this is not an option. i also changed the order of the paths in the GLEW_LIBRARY list, but without success.
in my old Makefile i just wrote LDDFLAGS = -L/opt/local/lib64 -lGLEW so the path is absolutely clear, but now with CMake i want to use the find feature, but want to prefer a specific version.
I use this to link statically to a custom compiled GLEW lib at a specific location:
#GLEW libraries
add_library(glew_static STATIC IMPORTED)
set_target_properties(glew_static PROPERTIES
IMPORTED_LOCATION /home/ryan/DevLibrary/glew-1.9.0/lib/libGLEW.a)
target_link_libraries(smolder glew_static)
With this in place you can remove
find_package(GLEW REQUIRED)
You can use this with shared libraries as well, simply remove the STATIC keyword from add_library.