Switching build configuration from cmake link to proper version of boost library - c++

I am using Cmake to build my C++ project and I am using conan to maintain my boost libraries.
My conanfile.txt is very simple,
[requires]
boost/1.71.0#conan/stable
[generators]
cmake
When I install boost from conan, I can use following commands,
conan install ..
Or,
conan install .. -s build_type=Debug
Both command install bost libraries in two different folders in my C:/.conan foler.
In CMakeLists.txt I have following lines to find boost
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_DEBUG_LIBS ON)
set(Boost_USE_RELEASE_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED COMPONENTS program_options)
However, When I configure cmake,
cmake .. -DBoost_DEBUG=ON
it doesn't find the debug version of boost library. It always shows that it it pointing to release version. So naturally, the following command works,
cmake --build . --config Release
However, following command failed,
cmake --build . --config Debug
as it is still trying to link ot release version.
How can I reconfigure my cmake and conan setup so that I can easily switch between debug and release version? Any suggestion?
Cheers,
M

If you want to consume the libraries with find_package(Boost) you need to generate the corresponding files. Use the cmake_find_package generator (you need different folders for Debug and Release) or the cmake_find_package_multi one (both Debug and Release can live in the same folder). Just add them to your conanfile.txt:
[requires]
boost/1.71.0
[generators]
cmake_find_package_multi
Now, you can call CMake from the command line, but you need to tell where to find the generated FindBoost.cmake files (or the BoostConfig.cmake if you are using the multi generator):
cmake .. -DCMAKE_MODULE_PATH=<path/to/dir/with/findcmake> [...more arguments]
Take into account that, if you are not using the cmake generator and the call to conan_basic_setup, you need to be sure that the configuration used to build the Boost binaries you are getting from Conan matches the one you are using to build your project (otherwise you might get linker errors).

If you aren't already I'd recommend using https://github.com/conan-io/cmake-conan it makes life easier in some areas.
Unless you want to be able to build your project without conan there is no real need to use find_package with conan. See https://docs.conan.io/en/latest/integrations/build_system/cmake/cmake_generator.html. You can either use:
conan_basic_setup()
target_link_libraries(<target> ${CONAN_LIBS})
Or:
conan_basic_setup(TARGETS)
target_link_libraries(<target> CONAN_PKG::boost)
If you want to use find_package you need to use the cmake_find_package generator and add the following to your conanfile.txt:
[generators]
cmake_find_package
cmake_paths

Related

AUTOMOC set to true makes fail cmake build

I'm at the very first day of Qt + Cmake and Conan, trying to make things work. I'm not using qmake because I'll integrate everything into a bigger project using cmake.
By following QT's tutorial, I figured out that I need to compile QT macros, and for that there's a useful AUTOMOC CMake property, as suggested here.
The point is that it's making me fail cmake builds.
My conanfile.txt:
[requires]
qt/5.15.2
[generators]
cmake
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(qttest)
set(CMAKE_CXX_STANDARD 20)
set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE)
set (PROJECT_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
with the following output:
CMake Warning (dev) in CMakeLists.txt:
AUTOGEN: No valid Qt version found for target qttest. AUTOMOC disabled.
Consider adding:
find_package(Qt<QTVERSION> COMPONENTS Core)
to your CMakeLists.txt file.
This warning is for project developers. Use -Wno-dev to suppress it.
ouch, but adding the find doesn't make things better:
CMake Warning at CMakeLists.txt:6 (find_package):
By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Qt5", but
CMake did not find one.
Could not find a package configuration file provided by "Qt5" with any of
the following names:
Qt5Config.cmake
qt5-config.cmake
Actually the project compiles, Qt is there in its conan dir:
matteo#MacBook-Pro-de-matteo 96a68a791abfc7a246f2bc28aa2f6fc210be0f9f % cd ~/.conan/data/qt
matteo#MacBook-Pro-de-matteo qt % ls
5.15.2 6.2.2
matteo#MacBook-Pro-de-matteo qt %
how could I enable it, or make things easier to compile it along with cmake?
You need to tell CMake, where to find Qt.
So, as CMake suggests by itself:
find_package(Qt5 COMPONENTS Core)
for the most basic stuff, you might want to add some of the other components later.
Depending on the system you are working on and your Qt installation, you need to tell CMake where to search for the package configuration files (second error message). CMake has some default directories, where it looks for these files, but obviously, there is none. On Linux, this can be solved by installing Qt with a package manager (this will install the CMake config files to one of the Qt default locations). If you are on Windows or if you installed Qt to a different location, this can be solved by providing the path with the PREFIX_PATH-variable.
cmake -B $BUILD_DIR -S $SOURCE_DIR -DCMAKE_PREFIX_PATH=$QT_INSTALL_PATH/5.15.2/$ARCHITECTURE $OTHER_OPTIONS
(You can have different versions installed in the same installation path, that's why Qt adds an other folder with the version number. And you can have different compilers/architectures. On Windows for example, you might have a mingw73_32 and a msvc2017 folder to choose.)
As already mentioned in the comments, a project is no CMake target. CMake targets are either libraries (add_library), executables (add_executable) or custom targets (add_custom_target); the project is not. If you want to set the AUTOMOC property target wise, that's ok and even suggested by CMake, but you can also set it globally by using:
set(CMAKE_AUTOMOC ON)

How to install a Library for C++ like Eigen and sharkML at vs code?

I am trying to install libraries like eigen, sharkMl, xtensor, and others in VSCode for C++.
Please if anyone can help me to know the right way to do that.
All of these libraries use CMake for their build system so what I do is use CMake as my build system. My favorite way to do this is to use the libraries build systems to install them and then inlcude them with cmakes find_package function. This you can do by cloning the git repository for the library then build it and install it with cmake. On linux you do this by:
git clone https://gitlab.com/libeigen/eigen.git
cd eigen
mkdir build
cd build
cmake ..
sudo make install
VSCode has good integration for cmake so if you have the C/C++ Extension pack you will be able to build with cmake. In your project folder make a CMakeLists.txt file and add the packages you want:
add_executable(main main.cpp)
find_package(Eigen3 3.4 NO_MODULE)
target_link_libraries(main Eigen3::Eigen)
(This example assumes the main cpp file is main.cpp and creates an executable called main) Then when you press ctr+shift+p and perform CMake: Configure you can select your compiler and build the executable.

How to set up OpenCV with cmake to enable dynamic and static builds?

I've built and make installed opencv on my mac with SHARED_LIBS.
I want to be able to choose for each project if I built with or without shared libs.
When I compile an additional OpenCV build with -DBUILD_SHARED_LIBS=OFF how can I reference it in my project's CMakeLists and chose the build type I want?
I have the source with shared libs in my ~/opencv and I've already compiled it in ~/opencv/build followed by make install.
When I create another dir like ~/opencv/static_build how would I have to adapt my CMakeLists in order to make a static build app? So far I've used:
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(test ${OpenCV_LIBS})
But if I'm not mistaken, these lines all depend variables which have been added to cmake during my inital make install.
It works by configuring a different install location with the cmake flag -D CMAKE_INSTALL_PREFIX for each build and make install will then install them to their respective locations.
In order to distinguish between the specific builds and to allow cmake to find the library if it not in its path, one has to add the following line to the project's CMakeLists.txt:
set(OpenCV_DIR /path/to/build/lib/cmake)
before:
find_package( OpenCV REQUIRED )

Compile Boost with multi-configuration with CMake

I have a project which depends on the Boost library (and others). I created a CMakeLists to automatically download and compile dependencies with ExternalProject_Add.
I want to support multi-configuration (Release and Debug). So, for my other libraries I defined a CMAKE_BUILD_TYPE at the beginning of my CMakeLists. I propagate it by dependencies with -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} in the ExternalProject_Add command.
It works well on Windows and Linux.
For Boost however, based on the configuration I need to compile with variant=debug or variant=release. I created a if(${CMAKE_BUILD_TYPE) MATCHES Debug) statement and set the variant based on that requirement.
For Linux this works well but on Windows it works only if I change the CMAKE_BUILD_TYPE variable during the cmake. When I try to change the configuration in VS it doesn't change the CMAKE_BUILD_TYPE variable.
Is it possible to detect the configuration selected in VS in my CMakeLists ?
Thank you.
#-----------------------------------------------------------------------------
# Boost
#-----------------------------------------------------------------------------
message(STATUS "Installing Boost library.")
set(BOOST_BOOTSTRAP_COMMAND)
if(WIN32)
set(BOOST_BOOTSTRAP_COMMAND bootstrap.bat)
set(BOOST_B2_COMMAND b2.exe)
elseif(UNIX )
set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
set(BOOST_B2_COMMAND ./b2)
else()
# MacOSX
set(BOOST_BOOTSTRAP_COMMAND ./bootstrap.sh)
set(BOOST_B2_COMMAND ./b2)
endif()
set(BOOST_BUILD_TYPE variant=release)
if (${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BOOST_BUILD_TYPE variant=debug)
endif(${CMAKE_BUILD_TYPE} MATCHES Debug)
set(BOOST_INSTALL_DIR ${PROJECT_BINARY_DIR}/deps/boost-install)
ExternalProject_Add(boost
SOURCE_DIR "${PROJECT_BINARY_DIR}/deps/boost"
BUILD_IN_SOURCE 1
GIT_REPOSITORY "${git_protocol}://github.com/boostorg/boost"
GIT_TAG "5ec478a570bdc71c5d4854e7165a8b3f4fa82ad9"
CONFIGURE_COMMAND ${BOOST_BOOTSTRAP_COMMAND}
BUILD_COMMAND ${BOOST_B2_COMMAND} headers COMMAND ${BOOST_B2_COMMAND} install
link=static
${BOOST_BUILD_TYPE}
--prefix=${BOOST_INSTALL_DIR}
--with-filesystem
--with-program_options
--with-system
--with-thread
-j8
INSTALL_COMMAND ""
)
When CMake is being run, it is not possible to know what build type the user will choose at build time when using a multi-configuration generator (Visual Studio or Xcode). The user makes that choice after CMake has finished the configure and generate stage (i.e. after the cmake command completes). The user can build more than one build type too, so there is not a concept of a single build type with those generators.
One option may be to define a custom command which does the relevant build of boost as a build-time task rather than using ExternalProject. This is probably the closest to what you seem to be wanting to achieve. You can still have the source downloaded at configure time during the CMake run, a technique that is mentioned here with googletest as the example. That answer provides a link to an article which goes into more detail as well as a fully general implementation available on github which would potentially be suitable for your situation.

Include soci in cmake on windows

I have a HelloWorld project in JetBrains CLion and set up boost so I can build it fine.
I've managed to build soci using cmake and make with mingw outside the HelloWorld project.
For boost I used:
include(FindBoost)
find_package(Boost 1.55.0 COMPONENTS system filesystem)
How do I include the soci library in my cmake? Is there a similar method for including soci? I don't know where to start?
UPDATE
A bit further I think.
I added the following to my cmake options:
-D CMAKE_MODULE_PATH=D:\Development\Tools\lib\soci-3.2.2\cmake\modules
and this to my CMakeLists.txt:
find_package(Soci)
if(${SOCI_FOUND})
target_link_libraries(HelloWorld ${SOCI_LIBRARY} ${SOCI_sqlite3_PLUGIN})
else()
message(WARNING "SOCI NOT FOUND")
endif()
I still get SOCI NOT FOUND though but at least the soci variables turns up in the cmake cache.
This is obviously very late, but it worked for me:
target_link_libraries(HelloWorld soci_core soci_mysql)
I must admit I shame for my country mates because they provide so crapy CMakeLists.txt for SOCI lib. In order to mitigate they bad works, I wrote following intsturctions how to use SOCI in CMake based projects. I do it on Linux KDE Neon 5.16.5 (based on: Ubuntu 18.04 LTS), but on Windows probably you have only fix paths. This probalby will work. I am not 100% sure because I just start my project within I want to use SOCI.
This is obviously very late, but it probably works:
I build and install soci like this:
cmake "/home/szyk/!-EnergoKod/!-Libs/3rdparty/soci" -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu -DCMAKE_BUILD_TYPE=Release
cmake "/home/szyk/!-EnergoKod/!-Libs/3rdparty/soci" -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu -DCMAKE_BUILD_TYPE=Debug
make -j$(nproc)
sudo make install
I add to my project CMakeLists.txt:
set(SOCI_SOURCE_DIR "$ENV{HOME}/!-EnergoKod/!-Libs/3rdparty/soci")
set(CMAKE_MODULE_PATH ${SOCI_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(CMAKE_MODULE_PATH ${SOCI_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
find_package(Soci)
list(APPEND LIBS ${SOCI_LIBRARY} ${SOCI_sqlite3_PLUGIN})
# Link libraries
target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS})
That is generates good looking output:
Soci found: Looking for plugins
* Plugin mysql not found.
* Plugin odbc not found.
* Plugin postgresql not found.
* Plugin sqlite3 found /usr/local/lib/x86_64-linux-gnu/libsoci_sqlite3.so.
Found Soci: /usr/local/include/soci