Cannot generate a safe linker search path CUDA - cmake

I want to add calls to the NVidia Monitoring Library to my CUDA application. However, the nvidia-ml library isn't part of CUDA; it's part of the device driver. Nevertheless, CUDA provides stubs for it. This appears to confuse CMake. I'm looking for a way to unconfuse CMake.
On the advice of my guru, I created a FindNvidiaML.cmake file
# set the base location
set(NVIDIA_ML_PATHS
/usr/lib64
/usr/lib64/nvidia
)
# Look for the library
find_library( NVIDIA_ML_LIBRARY
NAMES
nvidia-ml
HINTS
${NVIDIA_ML_PATHS}
)
# Make sure valid
if( NVIDIA_ML_LIBRARY )
SET( NVIDIA_ML_FOUND TRUE )
endif()
(NVIDIA_ML_LIBRARY has the value /usr/lib64/libnvidia-ml.so)
My main CMakeLists.txt file has this portion
find_package(NvidiaML REQUIRED)
The specific product illustrated here CMakeLists.txt file looks like this:
set(myTarget DspTests)
add_executable( ${myTarget}
Global_unittest.cpp
nvSMI_unittest.cpp
BlackmanHarris_unittest.cpp
BlackmanHarrisCU_unittest.cu
FFT_unittest.cu
FindPeakKernel_unittest.cu
)
target_include_directories( ${myTarget} SYSTEM PRIVATE
${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}
)
set_target_properties( ${myTarget} PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
POSITION_INDEPENDENT_CODE ON
)
target_link_libraries( ${myTarget}
dsp cufft ${NVIDIA_ML_LIBRARY}
gtest gtestApp
)
add_gtest( ${myTarget} )
CMake output:
CMake Warning at dsp/unit/CMakeLists.txt:13 (add_executable):
Cannot generate a safe linker search path for target DspTests because files
in some directories may conflict with libraries in implicit directories:
link library [libnvidia-ml.so] in /usr/lib64 may be hidden by files in:
/usr/local/cuda/targets/x86_64-linux/lib/stubs
Some of these libraries may not be found correctly.
Searching, I find
$ find /usr/ -name 'libnvidia-ml*' -ls 2>/dev/null
51097542 1512 -rwxr-xr-x 1 root root 1545404 Jun 11 2019 /usr/lib/libnvidia-ml.so.418.67
51102213 0 lrwxrwxrwx 1 root root 22 Jun 11 2019 /usr/lib/libnvidia-ml.so.1 -> libnvidia-ml.so.418.67
51102218 0 lrwxrwxrwx 1 root root 17 Jun 11 2019 /usr/lib/libnvidia-ml.so -> libnvidia-ml.so.1
34907591 1536 -rwxr-xr-x 1 root root 1569688 Apr 6 2019 /usr/lib64/libnvidia-ml.so.418.67
34907590 0 lrwxrwxrwx 1 root root 22 Jun 11 2019 /usr/lib64/libnvidia-ml.so.1 -> libnvidia-ml.so.418.67
34972797 0 lrwxrwxrwx 1 root root 22 Jun 11 2019 /usr/lib64/libnvidia-ml.so -> libnvidia-ml.so.418.67
17152088 32 -rwxr-xr-x 1 root root 31808 Apr 24 2019 /usr/local/cuda-10.1/targets/x86_64-linux/lib/stubs/libnvidia-ml.so
This is not a duplicate of CMake cannot generate a safe linker search path - yocto 2.4 or CMake Warning: Cannot generate a safe linker search path for target although the symptoms are similar. It is possibly a duplicate of CMAKE - runtime library hidden files
Despite the warning, the code does link properly to the library in /usr/lib64, and it does run. So there is no error condition here. However, such a verbose warning in the output certainly gives the illusion of an error. Given the installation path of the NVidia driver, and the search paths required for CUDA building, and the actual duplicate libraries, the condition seems unavoidable.
The question is, how can I silence this warning?
Environment:
CentOS 7.3
gcc 7.3
CUDA 10.1
CMake 3.13.5

The solution is to remove my FindNvidaML.cmake file. Turns out my guru's knowledge is dated and the intrisic support for CUDA in CMake, coupled with the stubs in CUDA 10.1 make this approach obsolete.
As the answers to other similar questions point out, the warning is describing the case where the code was linked against one library (in this case, explicitly /usr/lib64/libnvidia-ml.so) but at runtime may want to deduce a different library (found in /usr/local/cuda/targets/x86_64-linux/lib/stubs)
Changing the target CMakeList.txt file to be more generic results in a successful build and no warning:
target_link_libraries( ${myTarget}
dsp cufft nvidia-ml
gtest gtestApp
)

Related

Modern CMake Cross Compiling to AArch64 with Sysroots

Consider the following example project_(CMakeLists.txt):
cmake_minimum_required(VERSION 3.1)
project(CCL LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
find_package(PkgConfig REQUIRED)
find_package(ZLIB)
find_package(PNG)
find_library(MATH_LIBRARY m)
pkg_search_module(OpenEXR OpenEXR)
add_executable(main main.cpp)
if (MATH_LIBRARY)
target_link_libraries(main PUBLIC ${MATH_LIBRARIES})
endif()
Main.cpp:
#include <iostream>
#include <cmath>
int main(void)
{
std::cout << "Hello, sin()" << std::sin(30) << std::endl;
return 0;
}
I want to compile this project with the following CMake toolchain
(aarch64-toolchain.cmake):
# Cross-compilation system information.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
# The sysroot contains all the libraries we might need to link against and
# possibly headers we need for compilation.
set(CMAKE_SYSROOT /var/lib/schroot/chroots/ubuntu-focal-arm64)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)
# Install path when SYSROOT is read-only.
# set(CMAKE_STAGING_PREFIX aarch64-staging)
# Set the compilers for C, C++ and Fortran.
set(GCC_TRIPLE "aarch64-linux-gnu")
set(CMAKE_C_COMPILER ${GCC_TRIPLE}-gcc-10 CACHE FILEPATH "C compiler")
set(CMAKE_CXX_COMPILER ${GCC_TRIPLE}-g++-10 CACHE FILEPATH "C++ compiler")
set(CMAKE_Fortran_COMPILER ${GCC_TRIPLE}-gfortran CACHE FILEPATH "Fortran compiler")
# Automatically use the cross-wrapper for pkg-config when available.
set(PKG_CONFIG_EXECUTABLE aarch64-linux-gnu-pkg-config CACHE FILEPATH "pkg-config executable")
# Set the architecture-specific compiler flags.
set(ARCH_FLAGS "-mcpu=cortex-a53+crc+simd")
set(CMAKE_C_FLAGS_INIT ${ARCH_FLAGS})
set(CMAKE_CXX_FLAGS_INIT ${ARCH_FLAGS})
set(CMAKE_Fortran_FLAGS_INIT ${ARCH_FLAGS})
# Don't look for programs in the sysroot (these are ARM programs, they won't run
# on the build machine).
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Only look for libraries, headers and packages in the sysroot, don't look on
# the build machine.
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(CPACK_DEBIAN_PACKAGE_ARCHITECTURE arm64)
Where the sysroot (/var/lib/schroot/chroots/ubuntu-focal-arm64) was setup using:
name=ubuntu-focal
mk-sbuild --arch=arm64 --skip-proposed --skip-updates --skip-security --name=${name} focal
su - $USER
mk-sbuild --arch=arm64 --skip-proposed --skip-updates --skip-security --name=${name} focal
Configuration-wise, this works fine, however when I try to build this project
find_library 'correctly' finds the wrong libm.so library:
$ cmake -DCMAKE_TOOLCHAIN_FILE=../aarch-toolchain.cmake ..
$ make
Scanning dependencies of target main
[ 50%] Building CXX object CMakeFiles/main.dir/main.cpp.o
make[2]: *** No rule to make target '/var/lib/schroot/chroots/ubuntu-focal-arm64/usr/lib/aarch64-linux-gnu/libm.so', needed by 'main'. Stop.
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/main.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
Looking into the sysroot itself, the library is correctly found, but obviously,
it is a symlink to a file local to the sysroot, not the host:
$ ls -hal /var/lib/schroot/chroots/ubuntu-focal-arm64/usr/lib/aarch64-linux-gnu/
lrwxrwxrwx 1 root root 32 Apr 14 2020 libm.so -> /lib/aarch64-linux-gnu/libm.so.6
It seems to me that CMake is picking up the wrong library (find_library should
really be using the compiler libraries first), so I guess that my toolchain-file
is written incorrectly somehow. How should it be changed to correctly find the
math library, without changing the sysroot or project itself?
(Also, please note that this is an example project to illustrate the problem. I still need to be able to search the sysroot for packages.)
Edits
As requested in the comments, the end state should be a proper aarch64 binary
("main"). Essentially, the build commands below should succeed both with and
without the toolchain, and should yield a functional binary (although, the
aarch64 one naturally only work inside the sysroot).
$ mkdir -p host-build && cd host-build && cmake .. && make
$ mkdir -p device-build && cd device-build && cmake -DCMAKE_TOOLCHAIN_FILE=../aarch64-toolchain.cmake .. && make
TLDR: There is no easy way, as far as I know.
Your toolchain file is fine, it's the symlinks that are bad and they should ideally be relative and not absolute if you wish to use it for building. Below I mention a few options and explain the issue. This is all based on my experience with cross-compiling. Perhaps someone knows more.
There isn't anything wrong with your toolchainfile. From my perspective it is configured correctly. This is an issue as you pointed out with the symlinks being relative to your created rootfs and not absolute to the host machine but they are presented as absolute.
IIRC there is not much you can do here.
I'll give you a few options that I know of from personal experience:
Forget cross-compiling and using QEMU chroot into the environment and build there. This is the easiest option.
Get all the required libraries on your host machine (outside of the sysroot) and compile using them - You just have to make sure that you have the exact same libraries as the target machine. Your toolchain file would be then reconfigured to look for libraries among the ones here.
EDIT: As #josch pointed out in the comments under his answer I should expand on this point to make it more clear to users. However because he already mentioned the most important steps to take when applying this, I will refer the reader to his answer. I will however provide a link to debians official HowTo regarding Multi-arch
The other option would mean fixing your projects CMakeLists to more adapt to the cross-compiling. This would require you to specify the absolute paths to the correct libraries. There is a drawback as you need to always point to the newest library. You could for example create another .cmake file that helps you configure the correct paths and because target_link_libraries() allows you to specify absolute paths, you could use the newly created custom targets.
The last option would be to fix the symlinks (ideally by making them relative). This is in my opinion the preferred way. In the end the rootfs that you will be using for building will be just that, i.e. used for building.
As far as I know (I might be wrong here) but the mks-build is just a debian tool that is originally used for packaging .deb files and as such wasn't made to be complimentary to CMake. And if it was then the debian team probably has the toolchain files you are looking for (i.e. I would look for cross-compiling and package guides regarding .deb packages - if they exist they will be included).
CMAKE_SYSROOT, CMAKE_FIND_ROOT_PATH only add a prefix to specific find_ commands/functions. They pretty much can't change anything about the target system or the linker behavior (which is the issue here). Which means they are correctly configured. It's the fake system that is wrongly configured.
You wrote to the debian-cross mailing list so I assume that your question is Debian specific? If so, maybe tag your question as such. Here is how you cross compile any Debian package for amd64 (aarch64) using sbuild:
sbuild --host=arm64 your_package.dsc
sbuild will take care of setting up your chroot as required and call the build tools with the correct arguments. You do not even need to create a special build chroot for that and can just re-use your existing chroots (sbuild will know what to do with them).
If instead, you just want to cross-compile some software using CMake on Debian, the process is as simple as installing a cross-compiler and pointing CMake to it:
$ sudo apt install g++-aarch64-linux-gnu
$ cmake -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ .
$ make VERBOSE=1
...
/usr/bin/aarch64-linux-gnu-g++ -rdynamic CMakeFiles/main.dir/main.cpp.o -o main
...
$ file main
main: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1 ...
That's it. No need for a sysroot.
If you haven't set up arm64 as a foreign architecture on your system, you need to run this once:
dpkg --add-architecture arm64
apt-get update

CUDA_ARCHITECTURES is empty for target "cmTC_28d80"

I made a new CUDA executable project in CLion and when it opened I got CMake error:
CUDA_ARCHITECTURES is empty for target "cmTC_908f4".
CMakeLists.txt:
cmake_minimum_required(VERSION 3.19)
project(test CUDA)
set(CMAKE_CUDA_STANDARD 14)
add_executable(test main.cu)
set_target_properties(
test
PROPERTIES
CUDA_SEPARABLE_COMPILATION ON)
I tried searching for this error on internet but not much success. I only tried to set
set_target_properties(test PROPERTIES CUDA_ARCHITECTURES "35;50;72")
but that didn't help.
At this point I don't know what to do anymore.
Although I am 9 months late to this, I think I actually solved it. I just stumbled across (what I believe to be) exactly the same problem. It occurred while trying to set up a new CUDA Project in CLion, and I got the same error.
I have now contacted the JetBrains support for CLion, and they pointed me to the solution of this problem.
If you have the same problem, you should see an auto-detected "x86" architecture under "Settings/Preferences > Build, Execution, Deployment > Toolchains > [the toolchain you are using for this project]". Simply manually select "amd64" instead (or, I suppose, whatever arch your system is running on), and then the CMake build should run fine, and a simple Hello World should also compile and run without problems.
Version Data:
CLion 2021.3.4
CMake 3.21.1 (bundled with CLion)
CUDA Toolkit 11.6
MSVC 2022 / Version 17.0
Windows 11 Pro
I wonder if the order matters, e.g. set Cuda architecture before compile features. My CMakeLists that works (and didn't before adding the CUDA_ARCHITECTURE line) is:
cmake_minimum_required(VERSION 3.16)
project(myTarget LANGUAGES CXX CUDA)
# Locate sources and headers for this project
include_directories(${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include /usr/local/cuda/include )
file(GLOB sources ${PROJECT_SOURCE_DIR}/*.cc ${PROJECT_SOURCE_DIR}/src/*.cc)
file(GLOB headers ${PROJECT_SOURCE_DIR}/*.h ${PROJECT_SOURCE_DIR}/include/*.h)
file(GLOB cuda_sources ${PROJECT_SOURCE_DIR}/src/*.cu)
# Add the executable, and link
add_executable(myTarget ${sources} ${cuda_sources} ${headers})
target_link_libraries(myTarget pthread z)
# Compile Info
set_target_properties(myTarget PROPERTIES CUDA_ARCHITECTURES "35;50;72")
target_compile_features(myTarget PUBLIC cxx_std_11)
target_compile_features(myTarget PUBLIC cuda_std_11)
Try setting your DCMAKE_CUDA_COMPILER as described here: https://www.jetbrains.com/help/clion/cuda-projects.html#set-nvcc - add your nvcc path in settings for CMake.
Remember to put full path to executable - not only bin folder
I got similar problem and was wondering what actually that CMAKE_CUDA_ARCHITECTURES stands for. It seems that it stands for particular architecture of NVidia cards for which the program shall be optimized or minimum architecture on which it shall run at all. I have found this link how these architecture numbers relate to the GPU used.
To cite most important codes:
Turing - CUDA 10+ - 75 CMAKE default
Ampere - CUDA 11.1+ - 80,86,87
Lovelace - CUDA 11.8+ - 89
Hopper - CUDA 12+ - 90
It seems that CMake at some point realized that 75 might be soon outdated but does not want to update it constantly. Thus you shall set it by your own or it warns you and as of now puts 75 as default.
If you will search NVidia, they tend to name these architectures e.g. "compute_50". Because architecture 35 is deprecated in CUDA11 it is not wise to follow CMake example to set
set_target_properties(myTarget PROPERTIES CUDA_ARCHITECTURES "35;50;72")
but use rather
set_target_properties(myTarget PROPERTIES CUDA_ARCHITECTURES "75") to silence the warning and retain the behavior.

How to use libxml2 with CMake?

I am using CLion editor (with CMake) for my C project,
I've never used an external library though,
my question is how do I link an external lib (for ex. libxml2) to my project?
I've seen some questions similar to this but none worked for me.
My project is compiled on Windows, and I have libxml .dll, include, and .lib files(binaries for Windows).
Edit: My CMakeLists.txt file after the answer suggested:
cmake_minimum_required(VERSION 3.2)
project(time_table)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES
course.c
course.h
day.h
defines.h
find_tables.c
find_tables.h
item.h
parse_info.c
parse_info.h
table.c
table.h
time_table.c grades.c grades.h)
link_libraries(C:/Users/Gal/Desktop/time_table/libxml2-2.7.8.win32/lib)
add_executable(time_table ${SOURCE_FILES})
target_link_libraries(time_table libxml2)
and this is what I get:
"C:\Program Files (x86)\JetBrains\CLion 1.1.1\bin\cmake\bin\cmake.exe" --build C:\Users\Gal\.clion11\system\cmake\generated\2eda76ff\2eda76ff\Debug --target time_table -- -j 8
[ 14%] Linking C executable time_table.exe
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -llibxml2
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [time_table.exe] Error 1
CMakeFiles\time_table.dir\build.make:225: recipe for target 'time_table.exe' failed
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/time_table.dir/all' failed
mingw32-make.exe[2]: *** [CMakeFiles/time_table.dir/all] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/time_table.dir/rule' failed
mingw32-make.exe[1]: *** [CMakeFiles/time_table.dir/rule] Error 2
What is wrong?
There is a key work for libraries installed on your machine. <lib_name>_INCLUDE_DIR and <lib_name>_LIBRARIES once you have done find_package. This works for me.
find_package(LibXml2 REQUIRED)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<my_stuff> ${LIBXML2_INCLUDE_DIR})
add_executable(<my_exe> <my_source_files>)
target_link_libraries(<my_exe> ${LIBXML2_LIBRARIES})
---- Just a note for your curiosity ----
If you ever needed to build (1) a (static) library of your calculations, maybe reusable, and (2) an executable that uses that library and LIBXML2, do this.
find_package(LibXml2 REQUIRED)
# add a calculation library: file "lib<mycalc>.a"
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<your header files folder> ${LIBXML2_INCLUDE_DIR})
add_library(<mycalc> STATIC ${CMAKE_CURRENT_SOURCE_DIR}/<your src files folder>)
target_link_libraries(<mycalc> ${LIBXML2_LIBRARIES})
# add the executable: file <my_exe>
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/<your header files folder> ${LIBXML2_INCLUDE_DIR})
add_executable(<my_exe> <your exe src files>)
target_link_libraries(<my_exe> <mycalc> ${LIBXML2_LIBRARIES})
Assume that full path to the library(.lib) can be expressed as
<library_dir>/<library_name>.lib
For compile executable, which uses this library, you need:
CMakeLists.txt:
link_libraries(<library_dir>)
add_excutable(<my_exe> ..)
target_link_libraries(<my_exe> <library_name>)
For use(run) compiled executable, you need to have <library_name>.dll either under one of the directory, listed in the PATH environment variable, or within same directory with executable.
there are 32bit and 64bit version of libxml2, to be found here.
you can put them below the PATH - or the C:\Windows directory.
With moderns CMake (version 3.2 or newer), it got much easier:
Search for the library. CMake has an according find module, thus it boils down to
find_package(LibXml2 REQUIRED)
Then you can link the library it to your target foo
target_link_libraries(foo PUBLIC LibXml2::LibXml2)
That's it folks! No fiddling around with headers and libraries, all done automatically.
If you have not installed the library, you might want to set LibXml2_DIR to the location where LibXml2 is located, i.e., by passing -DLibXml2_DIR=C:\software\libxml2 to your CMake call. That will help CMake finding LibXml2.

.so with numerals after that, how to match them in find_library in cmake ? Error in linking shared objects which are found as sub-dependencies

Given
ls -lrt /usr/lib/libvpx* results
lrwxrwxrwx 1 root root 15 Feb 9 2012 /usr/lib/libvpx.so.1.0 ->libvpx.so.1.0.0
lrwxrwxrwx 1 root root 15 Feb 9 2012 /usr/lib/libvpx.so.1 -> libvpx.so.1.0.0
-rw-r--r-- 1 root root 646120 Feb 9 2012 /usr/lib/libvpx.so.1.0.0
ls -lrt /usr/lib/libschroedinger* results
lrwxrwxrwx 1 root root 29 Feb 8 2012 /usr/lib/libschroedinger-1.0.so.0 ->libschroedinger-1.0.so.0.11.0
-rw-r--r-- 1 root root 774044 Feb 8 2012 /usr/lib/libschroedinger-1.0.so.0.11.0
ls -lrt /usr/lib/libgsm* results
lrwxrwxrwx 1 root root 16 Nov 5 2009 /usr/lib/libgsm.so.1 -> libgsm.so.1.0.12
-rw-r--r-- 1 root root 50680 Nov 5 2009 /usr/lib/libgsm.so.1.0.12
This is a possible solution to issues found in Approach 1 of this question. You may/ may not refer that.
Possible Solution
As I mentioned in the parent question, we may need to add three find_library() functions. Below are contents from CMakeLists.txt
possible solution 1a
find_library(VPX_LIBRARIES NAMES libvpx.so.1 PATHS /usr/lib/ )
find_library(SCHROEDINGER_LIBRARIES NAMES libschroedinger-1.0.so.0-1.0 PATHS /usr/lib/)
find_library(GSM_LIBRARIES NAMES libgsm.so.1 PATHS /usr/lib/ )
target_link_libraries(MyLibraryOrMyExecutable ${VPX_LIBRARIES} ${SCHROEDINGER_LIBRARIES} ${GSM_LIBRARIES} )
possible solution 1b
find_library(VPX_LIBRARIES NAMES vpx PATHS /usr/lib/)
find_library(SCHROEDINGER_LIBRARIES NAMES schroedinger-1.0 PATHS
/usr/lib/) find_library(GSM_LIBRARIES NAMES gsm PATHS /usr/lib/)
target_link_libraries(MyLibraryOrMyExecutable ${VPX_LIBRARIES} ${SCHROEDINGER_LIBRARIES} ${GSM_LIBRARIES} )
Error
I get the same error for both the solutions 1a and 1b
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:
GSM_LIBRARIES
linked by target "MyLibraryOrMyExecutable" in directory /someDirectory
SCHROEDINGER_LIBRARIES
linked by target "MyLibraryOrMyExecutable" in directory /someDirectory
VPX_LIBRARIES
linked by target "MyLibraryOrMyExecutable" in directory /someDirectory
cmake looks for libvpx.so after reading vpx in NAMES from find_library(), but find a different file like libvpx.so.1 hence I used 1b too where I have given the exact names. But still no luck.
Q How do one resolve an issue like this where the name of the shared objects also include a number after the extension, and the exact name does not match with the name given in find_library(). ? I tried to give the exact names, that also does not work
Command find_library use CMAKE_FIND_LIBRARY_SUFFIXES and CMAKE_FIND_LIBRARY_PREFIXES variables to glue the real library name. For instance:
> cat CMakeLists.txt
message("suffixes: ${CMAKE_FIND_LIBRARY_SUFFIXES}")
message("prefixes: ${CMAKE_FIND_LIBRARY_PREFIXES}")
> cmake -H. -B_builds
suffixes: .so;.a
prefixes: lib
CMAKE_FIND_LIBRARY_SUFFIXES is a list variable and you can add a new suffix:
> cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .so.17)
find_library(library edata-book-1.2)
message("library: ${library}")
> cmake -H. -B_builds
library: /usr/lib/libedata-book-1.2.so.17
But I'm pretty sure that the real problem here is package manager usage (: Usually
lib<name>.so is a symlink to lib<name>.so.N.M file. So I recommend you to check manuals
and install your library in an appropriate way.

CMake FIND_LIBRARY returns wrong path

In my project I use differend 3rd libraries, which has been prebuild and added to external-debs subdirectory. I use multiple FindXXX CMake scripts to locate those requirements.
When I try to locate a FreeImage prebuild, CMake find the library successfully but returns always the wrong path lib/libfreeimage.a instead of ./external-debs/freeimage/lib/windows/x64/libfreeimage.a
This is my search operation:
FIND_LIBRARY(FREE_IMAGE_LIBRARY
NAMES ${LIB_PREFIX}freeimage.${LIB_POSTFIX}
HINTS ${FREE_IMAGE_LIBRARY_DIR}
)
And this are my predefintions:
# Determine platform architecture
IF (CMAKE_SIZEOF_VOID_P EQUAL 8 )
SET(ARCHITECTURE "x64")
ELSE()
SET(ARCHITECTURE "x86")
ENDIF()
#Determine platform specific include and library
#paths settings.
IF (WIN32)
IF (MINGW)
SET (LIB_PREFIX "lib")
SET (LIB_POSTFIX "a")
ELSEIF (MSVC)
SET (LIB_POSTFIX "lib")
ENDIF(MINGW)
SET (PLATFORM "windows")
ELSE (UNIX)
SET (LIB_PREFIX "lib")
SET (LIB_POSTFIX "a")
SET (PLATFORM "linux")
ENDIF (WIN32)
SET(FREE_IMAGE_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/external-deps/freeimage/include)
SET(FREE_IMAGE_LIBRARY_DIR ${CMAKE_SOURCE_DIR}/external-deps/freeimage/lib/${PLATFORM}/${ARCHITECTURE})
I use this same code to locate an other pre-build 3rd libary dependency (jsoncpp) located in same external-deps subfolder without any issue.
Execute: FindJSON.cmake
-- [INFO]: Find JSON include: ./external-deps/jsoncpp/include
-- [INFO]: Find JSON lib: ./external-deps/jsoncpp/lib/windows/x64/libjsoncpp.a
Execute: FindFreeImage.cmake
-- [INFO]: Find FreeImage include: ./external-deps/freeimage/include
-- [INFO]: Find FreeImage lib: /lib/libfreeimage.a
I'am using CMake 2.8.x on windows platform.
Has anyone an idea why CMake sometimes return a wrong library path?
It looks like CMake has found another installation of the library in your MinGW environment. This might be a false positive.
Use NO_DEFAULT_PATH if you want to force CMake to use a library from a specific directory:
FIND_LIBRARY(FREE_IMAGE_LIBRARY
NAMES ${LIB_PREFIX}freeimage.${LIB_POSTFIX}
HINTS ${FREE_IMAGE_LIBRARY_DIR}
NO_DEFAULT_PATH
)
Take a look at the CMake command reference to get some insight on the subtle rules that drive the path resolution in find_library.
One thing to remember about find_library() is that CMake does not do the search if it thinks it already knows where the library is. Removing CMake's cache (build directory) can often help.