Build Mongo Cpp driver with SSL and prebuild Boost on Windows - c++

I'm having trouble building the Mongo legacy Cpp driver with the --SSL option on Windows.
The problem is that I'm using the prebuild versions of the Boost libraries thus as is detailed on the mongo driver build documentation page I must use the --libpath and --cpppath option to point to the boost libs and headers instead of the --extrapath option.
Due to the layout of the boost installation in the pre-built binaries,
you cannot use the --extrapath SCons flag to inform the build of the
installation path for the boost binaries. Instead, you should use the
--cpppath flag to point to the root of the chosen boost installation path, and --libpath to point into the appropriately named library
subdirectory of the boost installation.
But I also need the --libpath and --cpppath to point to the OpenSSL library.
I've tried:
Combining the paths with a ';' ex. --libpath="c:\boost-path\lib;c:\openssl-path\lib"
Specifying the --libpath and --cpppath twice, each with one
path
Set environment variables LIBPATH and CPPPATH
None seem to work, depending on what comes first I get a build warning about not finding Boost or not finding SSL.
How can I specify both?

The legacy driver build system honors several forms of setting the library and include search path. The one that you want to use here is the LIBPATH and CPPPATH Scons Variables, which are set after invoking SCons. Multiple arguments are separated with spaces within a quoted string. Try the following:
scons --ssl CPPPATH="c:\boost-path\include c:\openssl-path\include" LIBPATH="c:\boost-path\lib c:\openssl-path\lib"

Related

Custom library directory for cmake

For my project, I am building specific versions of the dependency libraries in a separate folder, say, /home/ubuntu/libs. I will use real libraries as an example, however, the question is pretty generic.
I was able to build the freetype library and make installed the headers into /home/ubuntu/libs/include, the built library into /home/ubuntu/libs/lib and also added the freetype-config.cmake to /home/ubuntu/libs/lib/cmake.
Now, I am trying to build the freetype-gl library that depends on freetype and has a line
find_package(freetype REQUIRED) in its CMakeLists.txt.
Typically, when I install the freetype library to a common path like /usr/local/lib or /usr/lib, cmake picks up the *-config.cmake files from the corresponding ./cmake directory. However, when I call it with
cmake -DCMAKE_TOOLCHAIN_FILE=/my/custom/toolchain -DCMAKE_LIBRARY_PATH=/home/ubuntu/libs/lib -DCMAKE_INCLUDE_PATH=/home/ubuntu/libs/include /path/to/freetype-gl
it fails with the following error
CMake Error at CMakeLists.txt:102 (find_package):
By not providing "Findfreetype.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "freetype",
but CMake did not find one.
Could not find a package configuration file provided by "freetype" with any
of the following names:
freetypeConfig.cmake
freetype-config.cmake
Add the installation prefix of "freetype" to CMAKE_PREFIX_PATH or set
"freetype_DIR" to a directory containing one of the above files. If
"freetype" provides a separate development package or SDK, be sure it has
been installed.
What am I doing wrong? How to show the place of "freetype-config.cmake" to cmake.
as you state in your second paragraph:
I was able to build the freetype library and make installed the headers into /home/ubuntu/libs/include, the built library into /home/ubuntu/libs/lib and also added the freetype-config.cmake to /home/ubuntu/libs/lib/cmake.
find_package() in CMake works in a way that it checks the standard system paths on default. If you are using CMake version 3.17 you can (instead of reading the documentation) view these paths simply by adding this line to your CMakeLists.txt
SET(CMAKE_FIND_DEBUG_MODE TRUE)
In your case what you need to do is point CMake in the right direction of the cmake file you are looking for. In your case that would be the /home/ubuntu/libs/lib/cmake. So somewhere in the top of your CMakeLists.txt (before you call find_package()) add this line:
LIST(APPEND CMAKE_MODULE_PATH "/home/ubuntu/libs/lib/cmake")
Provided that this bash command:
ls /home/ubuntu/libs/lib/cmake | grep "*.cmake"
Returns an occurance of freetypeConfig.cmake (you get the drill :) )
You can read about CMAKE_MODULE_PATH variable here: https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
In short your CMake doesn't find the config file because it is not in the standard path where it expects to find it.
EDIT: You can ofcourse do the same via these variables as the error suggests - CMAKE_PREFIX_PATH or freetype_DIR
Presumably you also don't want the libraries you build to find their dependencies installed on our system, if any.
I've spent some time investigating how to isolate CMake builds, and my best recipe is below.
First, the terminology:
An installation "prefix" of a library is a directory where the binaries and headers are installed (normally in include and lib subdirectories). I preder distinct prefixes for each library.
A "dependency" of a library is any of other library it needs when compiling.
CMake path separator - the character used to separate path lists for CMake. It's : character on Windows and ; on Linux (when cross-compiling, the host system matters, not the target).
Yes, it's the opposite of what the documentation claims.
By Windows I mean MSYS2. If you want to build outside of it, check that : is still the right separator.
Environment variables for CMake:
PKG_CONFIG_PATH to empty string
PKG_CONFIG_LIBDIR to a :-separated list, for each dependency add <prefix>/lib/pkgconfig and <prefix>/share/pkgconfig.
(I didn't need to do it for any library I used, so this is theoretical. But in any case don't leave this variable unset, at least use an empty string. Otherwise some undesired dependencies from your system might leak in.)
CMake flags:
-DCMAKE_INSTALL_PREFIX=... - the installation prefix for this library.
-DCMAKE_PREFIX_PATH=... - a path list: the installation prefix, followed by the prefixes of all dependencies. Use the CMake path separator, as described above. All paths here must be absolute.
-DCMAKE_FIND_USE_CMAKE_SYSTEM_PATH=OFF
This prevents CMake from finding some system-wide dependencies. If I remember correctly, not doing this makes CMake look for dependencies in directories listed in PATH and their parent directories, which is annoyting.
This has an undesired effect of disabling some ..._SYSTEM_... CMake variables, so we can't use those, even though some of them would be more appropriate.
-DCMAKE_STAGING_PREFIX=/. On Windows hosts replace / with the current drive name, e.g. C:.
This is only useful when cross-compiling, to disable the effects of CMAKE_FIND_ROOT_PATH in the toolchain file, which otherwise limits dependency search to that path.
This also messes up the installation path that would otherwise be taken from CMAKE_INSTALL_PREFIX, the fix is explained below.
Only on Windows hosts:
-DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF - otherwise CMake tends to look for dependencies in the PATH and parent directories, which is annoying. This is hardcoded to only happen on Windows hosts, which is nonsense and was reported here.
We don't want to set this unconditionally, because it has a side effect of requiring all your toolchain executables to be in the same directory, which is annoying in general, but IMO tolerable on Windows.
It also prevents CMake from searching for executables in PATH, so we also need...
-DCMAKE_PROGRAM_PATH= - set this to the contents of PATH, with the original separator replaced with the CMake path separator. At least on MSYS2 the separators are the same, so no modifications are needed.
-DCMAKE_MAKE_PROGRAM=ninja -GNinja - here CMAKE_MAKE_PROGRAM is strictly necessary on Windows hosts because of CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF, and doesn't hurt on other platforms. -G... is to make sure CMake doesn't pick a different generator that doesn't match CMAKE_MAKE_PROGRAM. You can use any other generator+program if you wish.
Then build with cmake --build <build_dir> -j<num_threads> as usual.
Install with cmake --install <build_dir> --prefix <prefix>. We need to explicitly set prefix because of CMAKE_STAGING_PREFIX=/.

What do I need to do in order to use CMake from a custom directory?

I've installed a version of CMake to /some/where/cmake, and have put /some/where/cmake/bin in the PATH.
What environment variables do I need to set, and what other actions do I need to take, in order for my custom CMake to function properly? Specifically, how do I ensure it looks in /some/where/cmake/share before /usr/share for CMake-related files?
Notes:
The OS is GNU/Linux.
I'm using CMake 3.16.6.
If I issue the CMake command message(STATUS ${CMAKE_ROOT}), I get: /some/where/cmake/share/cmake-3.16
What environment variables do I need to set, and what other actions do I need to take, in order for my custom CMake to function properly? Specifically, how do I ensure it looks in /some/where/cmake/share before /usr/share for CMake-related files?
Nothing! CMake is designed to look relative to the binary's actual location on your filesystem and otherwise ignore standard system directories for its own functioning (of course it will detect these for toolchain purposes).
I have personally installed CMake 3.1 -- 3.20 on Ubuntu Linux by just downloading and untarring the release archives here to /home/alex/bin/cmake-3.X.Y and creating corresponding symlinks cmake-3.X, ctest-3.X, and cpack-3.X in /home/alex/bin (which is in my PATH). I use these regularly to test answers I post here on StackOverflow. Took all of 5 minutes to set up.

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.

Cmake unable to locate Boost Libraries (Windows)

I'm currently trying to build the Apache qpid messaging broker on Windows using CMake and the Boost (C++). I went through the initial steps of setting up Qpid on Windows as specified in this file. I set the variable BOOST_ROOT to "C:/< Home >/Downloads/boost_1_61_0" initially so that CMake could find the Boost Libraries (e.g. random, math, chrono, etc.) but I got this log saying that it could only find some of the libraries, but not others. I thought that maybe the filepath needed to include the directory where the Boost libraries were actually located (i.e. C:/< Home >/Downloads/boost_1_61_0/boost) but I was unable to reset the BOOST_ROOT environment variable despite deleting it and creating another one.
I was advised on this forum to delete the cache file for CMake using the GUI so I could reset the variable, but that didn't seem to work either.
Am I using the correct file path for BOOST_ROOT? If not, how should I go about changing it?
Some of the Boost libraries (e.g. chrono) need to be compiled first. If you have only downloaded Boost library from the website, you probably have not built these libraries. Check Boost website for instructions how to build on Windows. The site also lists which libraries need to be built. Alternatively, you can search for sites where pre-built Boost libraries are hosted. You can download and install from there.

Building libtorrent with openssl with BJam

I am trying to build libtorrent (http://www.libtorrent.org/) using the provided jamfile. If I try to build it in its vanilla state everything goes well. I am then building using this command:
bjam msvc-12.0 boost=source
However I want to build it with OpenSSL which there seem to be support for. This is where I run into problems. Most likely because it is the first time I use Bjam (actually anything else than make files). I now try to run the following command:
bjam msvc-12.0 boost=source encryption=openssl
Now the compiler starts to complain about not finding the OpenSSL include files.
So I guess I have to include this path in the JAM file. But I have no idea where.
I also tried to add the path into the INCLUDE environment varaible in windows but that doesn't seem to be picked up by BJAM or msvc. Any suggestions?
My understanding of how this is normally done on windows is by installing libraries and headers into visual studio's include and lib folders.
(That's how I install openssl on windows at least).
The jamfile is also supposed to pick up CXXFLAGS and LDFLAGS environment variables, which you could use to introduce the library- and include paths. However, it only does this when boost=system is specified, i.e. you're building against "system" boost libraries instead of from source.