Cmake - Find_package NO_DEFAULT_PATH not working properly? - cmake

I'm trying to include OpenCv in a project, I actually have 2 times the same version of this lib on my computer. One compiled with additionnal needed functions ( Cuda&OpenGl support) at /good/path and one compiled without thoses needed function at /old/non/suitable/path.
I'm curently doing this in my cmake :
message(${OpenCV_LIBS})
message(${OpenCV_INCLUDE_DIRS})
message(${HINTS})
find_package( OpenCV 3.2.0 REQUIRED CONFIG PATHS "/good/path" NO_DEFAULT_PATH )
message(${OpenCV_INCLUDE_DIRS})
The first 3 messages reports errors, in other words the variable are empty.
And the last message writes "/old/non/suitable/path/include"
According to the find package documentation, with adding the NO_DEFAULT_PATH option I should check only the explicit PATHS and HINTS but HINTS is empty as I checked it.
Does anyone have any idee on why I find the other old library instead of the one in the /good/path which once more should be the only path checked ?
Edit : For anyone having the same issue of not successfully selecting the wanted library, one solution is to rename the LibConfig.cmake of the old library to anything else. That will force cmake to find the last library.
Still, that's pretty awful and I have no idee why NO_DEAULF_PATH ins't working as it should be.
I'm waiting here a few days in case somebody sees an answer and if there isn't any response, I will open an issue directly on the cmake website.

Removing the build directory is the way to go.
Otherwise a cached path in the build directory overwrite the path modification in the cmake.
Ps : The answer is in Tsyvarev comment, I'm answering myself to close the question.

Related

CMake Find library issues if "lib" is a directory in the path

I have found a workaround for this problem, but I don't know why it works:
I am creating a CMake toolchain for a platform with many libs provided by COMPANY in a few locations.
Note: SDK_PATH is passed as an environment variable.
As an example, the provided C++ lib is at ${SDK_PATH}/COMPANY/stl/libc++-COMPANY/lib/libc++.so and another lib is at ${SDK_PATH}/lib/COMPANY/libCOMPANY_ext_logging.so
For the C++ lib, I can find it as expected with:
find_library(CPP
NAMES
c++
HINTS
${SDK_PATH}/COMPANY/stl/libc++-COMPANY/lib
NO_DEFAULT_PATH
)
However, I can not find the logging library with:
find_library(LOGGING
NAMES
COMPANY_ext_logging
HINTS
${SDK_PATH}/lib/COMPANY
NO_DEFAULT_PATH
)
However, I have found that if I copy the problematic libraries into a further subdirectory "lib" then things work (I guess that is a keyword CMake looks for somehow)
IE if I copy the logging lib to ${SDK_PATH}/lib/COMPANY/lib/libCOMPANY_ext_logging.so and alter the find command to be:
find_library(LOGGING
NAMES
COMPANY_ext_logging
HINTS
${SDK_PATH}/lib/COMPANY/lib
NO_DEFAULT_PATH
)
then things work fine. Which makes little sense to me.
I believe I had this working without the workaround about a year ago, but am unsure (I ran into this while updating both my CMake and the version of the company libraries)
Is there better CMake syntax I could use to avoid needing the workaround and still find libraries at the path ${SDK_PATH}/lib/COMPANY ?
Note2: I have tried using "Paths" rather than "Hints" with no change in results (The successful finds still work, and the failing ones still fail)

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.

Do CMake's find_<something> commands traverse symlinks?

I'm writing a Find<library>.cmake module, because no good one exists for the library in question. This necessitates usage of the find_path and find_library commands. I'm testing it on macOS El Capitan.
Through means that are not relevant to this question, I determine that on macOS, this library is installed in /usr/local/opt/<brew formula name>, which is in fact a symlink to somewhere else (the exact location isn't relevant). Let's call this path MYLIB_BREW_ROOT.
The headers and dylib's for this formula are available in ${MYLIB_BREW_ROOT}/include and ${MYLIB_BREW_ROOT}/lib, respectively. I add these paths, as written here, to the relevant find command search paths. So why isn't CMake finding them? Does CMake traverse symlinks? If so, how do I enable it? If not, how do I work around it?
Ultimately, the answer is yes. Symlinks work exactly as I expected them to. The real problem I had was unrelated to CMake; it had to do with pkg-config and the relevant libraries not having entries for it.

CMAKE_SYSROOT in CMakeTestCCompiler

I have a project which builds for PPC, the Toolchain is working correctly, i can build when the sysroot is installed under /opt/poky/1.5. Now i tried to move that Installation to the Project Directory (it is not a part of the Repository there, it is just installed there so it is not reliant on that fix path, so that everyone can check out the project and build it wothout setting up the sysroot under that fixed folder).
To achieve this I set CMAKE_SYSROOT to "${PROJECT_SOURCE_DIR}/poky" where the poky will be installed upon execution of a custom build script (the project also needs to build a secure image, so it is way simpler to use a build script instead of anything else, also this is convenient for jenkins).
Since the CMAKE_SYSROOT is build from the PROJECT_SOURCE_DIR which is different for the CMakeTestCCompiler Project, the cmake call fails teloling me that the CCompiler is broken of course. So I want to know, how I am supposed to get the CMakeTestCCompiler Project to compile with the same CMAKE_SYSROOT variable, without altering the CMakeTestCCompiler Project itself (of course).
Somehow I cannot find an answer anywhere, it seems that noone ever had this issue (which frankly i cannot understand, this should be a common setup in my opinion). (Or maybe i am just too much of a noob when it comes to CMAKE, which i will gladly admit)
I am not interested in solutions like: "JUST INSTALL IT IN A FIX PATH" or such... please, I need the setup like this, I have reasons for that.
THX for reading/trying/answering/helping
Have a nice day
EDIT1:
In CMakeLists.txt (top level CMakeFile so it should be used by any build):
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
In ToolchainCMake (the one given to the cmake as CMAKE_TOOLCHAIN_FILE):
`SET(CMAKE_SYSTEM_NAME Linux)`
`SET(CMAKE_SYSTEM_VERSION 1)`
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
`SET(COMPILER_ROOT ${PROJECT_SOURCE_DIR}/poky/sysroots/i686-pokysdk-linux/usr/bin/powerpc-poky-linux-gnuspe)`
`SET(CMAKE_C_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-gcc)`
`SET(CMAKE_CXX_COMPILER ${COMPILER_ROOT}/powerpc-poky-linux-gnuspe-g++)`
`MESSAGE("CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")`
`MESSAGE("CMAKE_CXX_COMPILER: ${CMAKE_CXX_COMPILER}")`
`MESSAGE("COMPILER_ROOT: ${COMPILER_ROOT}")`
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)`
`SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)`
EDIT2:
I used the
`set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "")`
`set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "")`
settings to simulate the CMakeTestCCompiler build succeeding and realized that I am facing some additional problems: It seem that the packages are looked up on the system instead of the CMAKE_SYSROOT folder. Even tried the
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
to try to force the search in there, but without luck. In the CMakeError.log I can see, that the compiler itself was configured with the prefix option that points to /opt/poky/1.5, the path that i want to "overwrite", now I am not sure if the compiler could even deal with an alternate path.
I felt the need to add these information, they not really add to the problem at hand.
ERRORS:
I also found some errors in the above cmake:
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots")`
must be
`SET(CMAKE_SYSROOT "${PROJECT_SOURCE_DIR}/poky/sysroots/ppce500v2-poky-linux-gnuspe")`
instead and therefor the
`SET(CMAKE_FIND_ROOT_PATH ${SYS_ROOT}/ppce500v2-poky-linux-gnuspe)`
changes to
`SET(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})`
EDIT: Whole answer changed.
My first suspicion was that the problem is that value of ${PROJECT_SOURCE_DIR} is not known in CMAKE_TOOLCHAIN_FILE as it is processed before CMakeLists.txt. But this isn't true.
I had similar problem (CMake 2.8.12.2), everything worked OK, when I passed cross compiler by CC environment variable with --sysroot option, i.e. CMake was invoked as follows:
CC="arm-linux-gnueabi-gcc --sysroot=/path/to/sysroot" cmake /path/to/sources
When I switched to using toolchain file, CMake started to report that C compiler doesn't work.
To workaround this problem, I use CMakeForceCompiler package. Parts toolchain file (along with comments) I think are relevant:
include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# Force compiler - only option that actually works
cmake_force_c_compiler (${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-gcc GNU)
cmake_force_cxx_compiler(${TOOLCHAIN_PATH}/bin/arm-linux-gnueabi-g++ GNU)
# NOTE: CMAKE_SYSROOT doesn't work as expected
add_definitions("--sysroot=${TOOLCHAIN_SYSROOT}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${TOOLCHAIN_SYSROOT}" CACHE INTERNAL "" FORCE)
Note, that TOOLCHAIN_PATH and TOOLCHAIN_SYSROOT are my local variables set before.

pkg_check_modules cannot find *.pc.cmake

I am using a 3rd party library rbdl, which contains rbdl.pc.cmake, which 'I suppose' is included for using pkg_check_modules in a cmake file.
I update PKG_CONFIG_PATH to point at the rbdl folder
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_BINARY_DIR}/externals/rbdl")
pkg_check_modules(RBDL rbdl)
but pkg_check_modules says it cannot find the module.
When I manually duplicate rbdl.pc.cmake, rename the copy into rbdl.pc and run pkg-config --cflags --libs rbdl in terminal, then my cmake also start working!
Interestingly, now even if I delete rbdl.pc, rbdl module if perfectly found by rbdl.pc.cmake!
So my questions are:
What is the difference between *.pc and *.pc.cmake?
How do I correctly setup my cmake to work with original rbdl.pc.cmake?
Why rbdl.pc.cmake starts to be accepted by pkg_check_modules after that tweak with duplicating it, renaming the copy and running pkg-config manually?
You understand it wrong! rbdl.pc.cmake is just a template file. It is not supposed to be used by you! Take a look into CMakeLists.txt line 160 -- configure_file() used to render variables ("quoted" by # in template file) and produce a rbdl.pc (a real pkg-config) file. Latter should be installed (some way) and then will be available to pkg-config hence can be used in your project.
pkg-config is stupid do not interpret or validate compiler/linker flags any way, so your renamed file "works" (yeah, producing invalid command line for compiler/linker).
I wish you to read CMake documentation before trying to code something using it! It'll save your time and give you a necessary knowledge which stops you from doing stupid things like you described in your question ;-)