c++17 parallel algorithms and CMake - c++

It looks like more and more standard libraries implementations are relying on TBB for their parallel algorithms. This is a bit surprising to me, as I didn't think that standard libraries would have external dependencies (outside of stuff like pthread), but that's a different question I imagine.
My issue is that I need to bake this into my CMakeLists.txt files now.
First bad news: There is no official CMake support for TBB, and TBB itself does not provide any FindTBB.cmake file. You can find it here and there on the web, but if standard libraries start relying on it, it would be nice to have it officially supported by CMake. Is this coming further down the line?
Then, I need to have some slightly convoluted code in my CMakeLists.txt file to find_package(TBB REQUIRED) and link the corresponding targets when required (depending on the standard library, version, etc.). It looks like Conan is already offering a package that hides all that stuff from the user. You just get parallelstl and that's it. Will we have something similar in CMake in the future?
We can already use these parallel algorithms in CMake today, but it would be great to make it easier to create such projects.

I have Ubuntu 21.10 with GCC and TBB (libtbb-dev 2020.3-1) installed.
Since TBB uses pkg-config what worked for me is this:
# file CMakeLists.txt
find_package(PkgConfig REQUIRED)
pkg_search_module(TBB REQUIRED tbb)
link_libraries(PkgConfig::TBB)
Unfortunately, when I later installed intel-oneapi 2021.4.0 which includes its own TBB (in /opt/intel/oneapi) this stopped working.
This newer version of TBB cannot be used as a backed for GCC's (parallel) STL apparently (generates compilation errors in my system), so I did this in order to pick the system's TBB and not the /opt/intel version.
link_libraries(-ltbb) #(PkgConfig::TBB)
This defeats the purpose of CMake, so I am also looking for a more robust solution.
My recommendation at the moment is do not install oneapi's TBB if what you want is to make it work with system's GCC.

Related

How do I properly integrate a modular boost build into my CMake project using FetchContent?

CMake FetchContent is a great way to manage build dependencies, by integration the dependency into your build and build it from source along with your own sources.
I would like to do this with Boost, too. I am encouraged by the fact that CMake support for Boost is steadily improving.
Of course since Boost is a large package, and one rarely uses all Boost libraries in a project, it would be rather wasteful to pull the entire Boost sources into one's own build. Given the modularity of the Boost project, using git submodules, it would be much more intelligent and efficient to only fetch the sources for the libraries actually used, and FetchContent supports this via its GIT_SUBMODULES option.
However, this doesn't seem to cater for dependencies between the Boost libraries. Do I need to handle this manually, or is there a more intelligent solution?
Furthermore, how do I control installation in this scenario? Many Boost libraries are header-only, and I don't want the headers included in my installation, since I'm only using them for my build. Is there a way to tell CMake that I don't want anything installed from what I fetch with FetchContent?
I have read Craig Scott's book, and of course the CMake documentation, but there's not much information about this sort of problem.
But maybe I'm trying something that I shouldn't be doing. Have others tried this, and can show me how it's done properly?

Setting Up Intel TBB with Nuwen

I've recently become interested in learning more about parallel computing, concurrency, etc. My main language is C++, so obviously I decided to use that in my personal studies.
After some research (read: looking things up on Google), I decided that using Intel's TBB library would be the most ideal.
The one thing that's got me stuck so far, though, is setting it up to use on my computer. I have looked on the Internet for some sort of tutorial on setting TBB up with MinGW (in my case, specifically Nuwen) and haven't really found anything.
So, here's my question: how would I set up TBB to use with a Nuwen distro?
TBB doesn't provides binaries for mingw in a Windows package. So you should build it from source code. You need compiler and GNU make;
Download source code(.zip) from https://github.com/01org/tbb/releases
Unpack somethere (not sure, but in common: beware of spaces in the dir path)
Open your console with compiler's environment, go to $archive_root/src and call gmake tbb tbbmalloc compiler=gcc. Also you could try to add stdver=c++11 in the build command if your complier supports this mode.
You will find a library build in the $archive_root/build/windows_... directory

How should I setup a C++ project on github so that it is portable?

I would like to start a C++ project on GitHub such that I will be able to clone/build on different operating systems (for example, OSX and unix). There will be lots of dependencies that need to be installed (for example curl, libxml2, etc), and much as possible I'd like to avoid having the user need to manually install the deps on the system. Is it possible to do this?
It depends on how much you want to bite off.
The short answer is let CMake do the work. It will generate projects for whatever platform and they should be usable. You don't need to distribute binaries for this, assuming they are readily available to you (and to them, by extension).
Here is an example that sets up sqlite, boost, and eigen that I used for one of my projects.
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/Modules)
# boost
find_package(Boost 1.42.0 REQUIRED )
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
find_package(Eigen REQUIRED)
include_directories(${EIGEN_INCLUDE_DIRS})
find_package(Sqlite3 REQUIRED)
include_directories(${SQLITE3_INCLUDE_DIR})
set(CMAKE_CXX_FLAGS "-std=c++0x")
include_directories(.)
link_libraries(
${Boost_LIBRARIES}
${SQLITE3_LIBRARIES}
)
add_executable(igd_sqlite
main.cpp
)
You'd take this and generate visual studio projects, makefiles, etc. Then build the project as you normally would.
CMake supports lots of libraries out of the box, though sometimes you do have to google for less popular ones and add them to your project.
I use it for my day-to-day work, even when I don't need cross platform.
When I do actually want to distribute binaries, I usually setup an external folder with the binary files.
Here is an example:
https://github.com/tomisarobot/curl_race
This works great if you don't have a lot of external dependencies and if they aren't huge. When that isn't the case, then I'd recommend putting each plattform in different repositories. Your source should be in its own too. You can use subprojects if you want, though that isn't strictly necessary. External deps dont change that often, so its not always worth the overhead. Usually I just write a bash script to document where to get everything. This script is usually necessary for a distribution build anyway.
Things like the maven-nar-plugin exist, though I am unaware of its maturity. If you're just creating all the binaries to distribute with your source anyway, then maybe it isn't that attractive. I don't see a lot of talk about it, so I assume adoption is low. Having seen what maven does for Java, it should be more popular.
Few thoughts
1) Tools
When possible, include the tool sources in the repository so that one can build them as a first-time-only step
When not possible, clearly specify what minimum version of what tool is required so that the user can install them herself
Possibly check if the dependency requirements are satisfied by running a script
2) Language
Compile with strict language compliance. For example
g++ -std=c++11 -pedantic

cmake How to avoid system libraries

I want to use a certain version of Qt4 in my project. I'm using debian and there is already an older version of Qt4 installed. When I'm using the find_package command in my CMakeLists file, of course, the system library is found, because the file /usr/share/cmake-2.8/Modules/FindQt4.cmake is used by cmake.
What I've done so far to link the newer Qt4, is to edit the paths with ccmake manually. The problem is I'm not allowed to install the newer Qt4 version in the directories of the system. Is there any easier solution to tell cmake don't use the system library just use another version. Of course I could create my own module and give the find_package command the path to my own module, but I think this is annoying and there have to be an more easier solution.
What I've also looked for, are there some environment variables which are used by the FindQt4.cmake module, but there aren't. - So, is there a general solution to avoid system libraries and to use libraries which installed in not system directories without doing some dirty tricks?
The only real way to use different versions of libraries on Linux is to use static linking. If you require the ability to use different versions of the same library simultaneously, you'll need to use an OS that supports that paradigm. Solaris (and its derivatives) is particularly good at that (compile with -L to point to the library to compile against and -R to indicate the path to that library at runtime). I believe BSD is the same.
Barring that, you'll want to create a chroot (a poor man's BSD jail) to deploy your application in. You'll install a copy of all the dependencies to the chroot, (use ldd to find them out) and the copy of Qt4 you wish to use.
Don't know about system libraries in general. For Qt, you set the search path to qmake and qt will do the rest. Qmake path is set through QT_QMAKE_EXECUTABLE, I use Qt commercial and this is how I set the path in Cmake.
set(QT_QMAKE_EXECUTABLE $ENV{HOME}/QtCommercialSDK/Desktop/483/gcc-64/bin/qmake)

find boost library path

I'm writing a program using boost program_options, I followed this instruction: http://www.boost.org/doc/libs/1_47_0/more/getting_started/unix-variants.html#build-a-simple-program-using-boost and everythings is fine. The point now is that I want to distribute the source, so my problem is how to find where the boost libraries are installed on other linux machines (supposing they are). For example on my pc they are in /usr/lib64 but on the other machine they're installed in non-standard places.
I don't want to use tool like autotools, I'm using a simple plain Makefile.
Is there some tool provided with the boost installation to find where the libraries are? Is there some enviroment variables?
You either need to use a tool like autotools (I thoroughly recommend CMake, it's awesome), or have it available in a place that your compiler can find it. You can't configure everyone's system for them though, so usually the latter is insufficient.