CMake with boost( on windows) :Could not find libraries? - c++

I am trying to build my project using CMake. Iam also using boost.
The find package statement in my CMakeLists.txt file is:
find_package(Boost 1.42 REQUIRED COMPONENTS
python
system
filesystem
serialization
thread
program_options
regex
test_exec_monitor
)
The build fails and the error message i get is:
The following Boost libraries could not be found:
boost_system
boost_filesystem
boost_serialization
boost_thread
boost_program_options
When i check my lib directories i find that the libraries are by name:
libboost< library_name >-vc100-mt.lib and not by boost_< Library_name >
Infact when i rename a single library in my lib files to fit according the boost_< LibraryName > Prefix, it doesn't complain for that library.
I see 2 solutions for the same:
1.Make changes in the CMakeLists.txt file so that it searches for libraries with correct Prefix( and suffix ).
2.Others
What could be the best one.

From the FindBoost.cmake
These last three variables are available also as environment variables:
Also, note they are completely UPPERCASE, except Boost_DIR.
Boost_DIR or The preferred installation prefix for searching for
BOOST_ROOT or BOOSTROOT Boost. Set this if the module has problems finding the proper Boost installation.
Use these variables to point on folder where your boost libs installed. For example
cmake .. -DBOOST_ROOT=C:/Boost

Related

How to use cmake to check if some libraries exists before build our sources?

Usually, open source packages will have cmake to check if some headers or libraries exists or not, I wish my own project has this same functionality.
So I wish to know if cmake provides some command to check if some ".so"/".a"/".h" files exists in the current linux system or not, if not cmake will give me some hint to install them?
How does cmake support this?
Usually one would use the find_package(ABC REQUIRED) and then refer to it in your project. This will ensure that the dependent library is installed and cmake will fail if it is not.
You can find lot's of example on how this works in your cmake installation, for example C:\Program Files\CMake\share\cmake-3.13\Modules\FindZLIB.cmake will search for the zlib library by looking in the file system for normal places where this library would be installed and if it finds it will set these variables accordingly:
# ZLIB_INCLUDE_DIRS - where to find zlib.h, etc.
# ZLIB_LIBRARIES - List of libraries when using zlib.
# ZLIB_FOUND - True if zlib found.
To achieve this header files are found using the cmake command find_path, and libraries (static and shared) are found using find_library.
To search for arbitrary library you can use find_library() command. Same task for headers is accomplished by find_file(). You can also search for executables with find_program().
As #Damian said in his naswer, many libraries provide "config" files, like FindBoost.cmake. Such libraries can be found by calling find_package(Boost) command. This command would locate and load config file and set corresponding variables.
You need to provide -config.cmake files to tell other projects where your libraries and headers are. Here, you will found what are you looking for.

Compiling C++ with Boost 1.68.0 on Windows using CMake and MinGW

I want to use the Boost library on Windows but doing so has been troublesome. I downloaded the Windows package from here and extracted it to C:\Boost:
I added the following to my CMake file:
find_package(Boost 1.68 REQUIRED COMPONENTS filesystem)
# ...
target_link_libraries(MyExecutable ${Boost_LIBRARIES})
I'm getting the following CMake error:
C:\Users\User\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\183.4284.104\bin\cmake\win\bin\cmake.exe -DCMAKE_BUILD_TYPE=Debug "-DCMAKE_MAKE_PROGRAM=C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/bin/mingw32-make.exe" "-DCMAKE_C_COMPILER=C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/bin/x86_64-w64-mingw32-gcc.exe" "-DCMAKE_CXX_COMPILER=C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/bin/x86_64-w64-mingw32-g++.exe" -G "CodeBlocks - MinGW Makefiles" D:\Cpp\MyProject
CMake Error at C:/Users/User/AppData/Local/JetBrains/Toolbox/apps/CLion/ch-0/183.4284.104/bin/cmake/win/share/cmake-3.12/Modules/FindBoost.cmake:2048 (message):
Unable to find the requested Boost libraries.
Boost version: 1.68.0
Boost include path: C:/Boost
Could not find the following Boost libraries:
boost_filesystem
Some (but not all) of the required Boost libraries were found. You may
need to install these additional Boost libraries. Alternatively, set
BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT
to the location of Boost.
Call Stack (most recent call first):
CMakeLists.txt:6 (find_package)
-- Configuring incomplete, errors occurred!
See also "D:/Cpp/MyProject/cmake-build-debug/CMakeFiles/CMakeOutput.log".
[Failed to reload]
It apparently cannot find filesystem but it's there in C:\Boost\boost\filesystem (here is the documentation on FindBoost).
How do I setup my CMake file to use Boost properly? I tried setting the Boost environment variables as well but it still didn't work:
SET (BOOST_ROOT "c:/Boost")
SET (BOOST_INCLUDEDIR "c:/Boost/boost")
SET (BOOST_LIBRARYDIR "c:/Boost/libs")
FIND_PACKAGE(Boost 1.68.0 REQUIRED COMPONENTS filesystem)
Also, Boost says that most things don't have to be compiled so I didn't do that.
It cannot find the library boost::filesystem. Because boost::filesystem is one of the few libraries that need to be compiled (all the ones that you have to specify in the find package command have to be compiled).
You need to build boost first:
./booststrap.sh
And then:
bjam
It picks up whatever compiler is available, so you may have to set the proper toolset manually.
Not completely related, but I think your link line is incorrect, instead of:
target_link_libraries(MyExecutable Boost::filesystem)
it should say:
target_link_libraries(MyExecutable ${Boost_LIBRARIES})
Boost_LIBRARIES is automatically defined once Boost is found, so it's for free.
The CMake FindBoost macro only fills Boost_Libraries if the find_package contains a COMPONENTS section and the macro actually finds those libraries on disk.
So here I'd be saying I need Boost to be found AND it must have filesystem
find_package(Boost 1.66.0 REQUIRED COMPONENTS filesystem)
The macro then tries to construct a bunch of potential filenames for the filesystem (taking into account if I want shared version, debug, multi-threaded etc.) and searches for those names under Boost_ROOT. If it doesn't find the file it may error and won't fill out Boost_Libraries.
If in doubt, add a line like this to your CMake prior to find_packages() to see what libs the macro is looking for and compare to what you actually have:
set (Boost_DEBUG ON)
For me I discovered that I had a Boost that placed an -x32 and -x64 architecture version of the libs, e.g. "libboost_system-mgw92-mt-x64-1_66.a". The macro wasn't filling in the architecture prefix into the filename it was looking for and failed.
I had to add a line like this to give the macro a clue which version I wanted:
set (Boost_ARCHITECTURE "-x64")
After that ${Boost_Libraries} expanded correctly and I was able to correctly use it to link.

Cmake FindBoost.cmake MinGW-W64: searching for library with incorrect name

I have built Boost 1.68 (using instructions from https://gist.github.com/sim642/29caef3cc8afaa273ce6, and adding link=static,shared to the b2 command line to also build shared libraries.)
The libraries appear to build correctly, and I have set the BOOST_INCLUDEDIR and BOOST_LIBRARYDIR environment variables correctly.
However, when I add the following to a CMakeLists.txt:
find_package(Boost REQUIRED COMPONENTS system context coroutine thread random REQUIRED)
and generate with MinGW Makefiles, I get the following error:
CMake Error at C:/Users/pbelanger/AppData/Local/JetBrains/Toolbox/apps/CLion/ch-0/182.4129.15/bin/cmake/win/share/cmake-3.12/Modules/FindBoost.cmake:2044 (message):
Unable to find the requested Boost libraries.
Boost version: 1.68.0
Boost include path: C:/boost/install/include/boost-1_68
Could not find the following static Boost libraries:
boost_system
boost_context
boost_coroutine
boost_thread
boost_random
Some (but not all) of the required Boost libraries were found. You may
need to install these additional Boost libraries. Alternatively, set
BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT
to the location of Boost.
I have placed the output of adding set(Boost_DEBUG ON) before the find_package line here: https://pastebin.com/yRd5DPt4
According to the debug output, the find script is searching in the correct directory (c:\boost\install\lib), but is not finding the boost libraries since they have a different naming scheme. For example, the system library is named libboost_system-mgw81-mt-x64-1_68.dll, but the find script is passing he library name boost_system-mgw81-mt-1_68 to CMake's find_library. Notice that the addressing model (-x64)is not listed in the latter name.
My question is whether this is an issue with Boost, or the findCMake script? Can this be fixed by setting a specific cmake variable before the findCMake script?
After hours of research, the answer given by Paul Belanger saved my day.
Digging a bit more in the codebase, they added a new option to manage exactly this case, so with the latest version of CMAKE you can add the following option:
set (Boost_ARCHITECTURE "-x64")
Source: https://github.com/Kitware/CMake/commit/1e08b625c291e0bb57d253b6656e812dc8848bd8#diff-555801259d7df67368f7deab1f9deacd
Looking at the source of FindBoost.cmake, line 1478,
the script looks at the value of CMAKE_CXX_COMPILER_ARCHITECTURE_ID in order
to build the correct architecture tag. However, on my compiler (MinGW-W64 8.1
64-bit), this string is empty. Therefore, the architecture tag is omitted.
I have to set the value of this variable manually by putting the following
before my find_package line:
if(WIN32 AND "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x")
message(WARNING "WIN32 compiler does not specify CMAKE_CXX_COMPILER_ARCHITECTURE_ID -- filling in manually")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(CMAKE_CXX_COMPILER_ARCHITECTURE_ID "x64")
else()
set(CMAKE_CXX_COMPILER_ARCHITECTURE_ID "x86")
endif()
message(STATUS "Compiler architecture: ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}")
endif()
# now we should be able to find boost correctly.
find_package(Boost REQUIRED COMPONENTS system context coroutine thread random REQUIRED)
This makes the find_package work correctly.

How to know variable such as 'OpenCV' in CMake

I am using OpenCV with gcc and cmake. And I found a tutorial https://docs.opencv.org/3.4.0/db/df5/tutorial_linux_gcc_cmake.html .In the file CMakeLists.txt, there are some variables such as OpenCV and OpenCV_INCLUDE_DIRS.
cmake_minimum_required(VERSION 3.9)
project(VideoRecord)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(VideoRecord main.cpp)
target_link_libraries(VideoRecord ${OpenCV_LIBS})
I want to know where to find these variables definition.
EDIT
Thanks #qbranchmaster's answer. I tried to search FindOpenCV.cmake but failed.
First try.
➜ ~ cmake --help-module-list | grep "FindOpen"
FindOpenACC
FindOpenAL
FindOpenCL
FindOpenGL
FindOpenMP
FindOpenSSL
FindOpenSceneGraph
FindOpenThreads
Another try.
➜ / find . "FindOpenCV.cmake"
In addition, my os is osx and I install cmake with brew. I comiple and install OpenCV manually.
These variables are part of the package config script shipping with OpenCV.
Note that find_package is a two-headed beast. The classic mode of operation is finding libraries through find-scripts. This is still the approach being used today for third-party libraries that are not aware of CMake. However, if your dependency is itself being built with CMake, it can provide a package config file instead, which allows for a more powerful mode of operation.
The idea here is that instead of you telling CMake how to find a dependency, the dependency itself tells CMake how clients can find it. This is the approach that is taken by libraries like OpenCV and Qt.
To answer your question, those variables are being set by the package config file in your local OpenCV installation, the template of which can be found in the OpenCV source code under cmake/templates/OpenCVConfig.cmake.in.
They are defined in CMake OpenCV module. CMake has numerous modules that aid in finding various libraries like OpenCV (FindOpenCV.cmake module).
Using this command you can get a list of modules that your CMake supports:
cmake --help-module-list
Some libraries come with their own *.cmake modules which should be installed in some system path. If you are using Ubuntu, your cmake modules should be localised in:
/usr/share/cmake/Modules/
If not, just search system for file FindOpenCV.cmake. In that file you will find these variables.
In general, you get variable names from the documentation or source code of the package you want to find.
Often you can derive the name to put into find_package from the provided FindFoo.cmake module file name, because "Foo" would be the name. The find module is either part of CMake or comes with the third-party library.
If there is no find module, some modules provide FooConfig.cmake files, where "Foo" is again the string to put into find_package.
If you have neither a find nor a config file, you need to find the library by other means, e.g., FindPkgConfig or find_library / find_file.

How do I include packages in different directory with CMake?

I am trying to compile a piece of C++ code on a server with CentOS. I need to include a library (NLopt) that is installed as a module at the location "/services/tools". I have tried "module load NLopt", but CMake does still not find the library.
What do I need to do to make CMake find the package?
"By default, [it] installs the NLopt static library (libnlopt.a) in /usr/local/lib and the NLopt header file (nlopt.h) in /usr/local/include, as well manual pages and a few other files."
So, you can include the header as
include_directories("/usr/local/include")
and link the library as
target_link_libraries(project "/usr/local/lib/lbnlopt.a")
Ideally you could try to find a CMake find module for the library.
Assuming your libraries are in /service/tools/lib and the headers in /service/tools/include, you can also set CMAKE_PREFIX_PATH, like this:
list(APPEND CMAKE_PREFIX_PATH /service/tools)