Problem building GNURadio in custom environment - cmake

I am trying to build the latest GNURadio package on my development system. Unfortunately this system configuration is tightly controlled and I can't just install new packages of software on it as it is used to develop a product and all development systems are kept in lockstep. We are currently on an older version of RedHat.
While I cannot modify the system includes I can download and use newer versions of packages locally (in non-system directories) as long as that doesn't affect the product build/debug environment. Normally this isn't a problem.
However, when building GNURadio I found that our development platforms use an older version of the Boost libraries than is required to build GNURadio. So, I got the latest version of Boost and extracted it into my local (home) directory. I found several directions for, I thought, instructing CMake to use additional include directories. Unfortunately, this hasn't seemed to work with the Boost libraries. CMake keeps complaining that it finds the older version of Boost and not the newer one I have extracted locally.
I have tried using
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES=<dir>
and
-DCMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES_BEFORE=<dir>
and this had no effect. I then tried adding the following to the top-level CMakeLists.txt file:
SET(CMAKE_INCLUDE_DIRECTORIES_BEFORE ON)
SET(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES <dir>)
or, even
include_directories(BEFORE <dir>)
Again, no joy.
I did a bit of digging and found that there is a GrBoost.cmake module and it had an additional configuration for the boost directory so I added this:
list(PREPEND BOOST_LIBRARYDIR "<dir>")
to the top of the file. Again, no luck.
I've never used CMake before (and I'm not really keen on learning yet another build system if I don't have to - our company just switched to bazel and I am coming up to speed on that) so I am flying blind here.
What do I have to do to get CMake to look in my local directory to find the Boost stuff I downloaded?

Ok. As it often happens, just after asking the question I was able to find an answer.
It turns out that there is a command-line option to CMake (CMAKE_PREFIX_PATH=<dir>) where you can specify additional base paths to search for CMake config files. I just added this to the command-line and it was found just fine.
I wasn't even aware that Boost came with such config files. Live and learn.
#vre's comment would have probably worked just as well (maybe better, in fact).

Related

Support multiple cmake minimum versions for one project

I have a fairly popular open source project that has a minimum cmake version set that is fairly old (~Oct 2013).
cmake_minimum_required(VERSION 2.8.12)
This is great for supporting a wide variety of users, but it makes adding new things to our cmake builds challenging, since we cannot use any of the new features in later cmake versions. This leads to complicated cmake files and more maintenance burden to emulate future improvements made to cmake.
I would like to support two CMakeLists.txt files for the project that have different minimum versions, one legacy one at the 2.8.12 version, and another more modern one at a later 3.x version. Is there any canonical way to do this? It doesn't look like there is a way to support multiple CMakeFiles.txt at the root of the project.
The naive way is to just rename the legacy file CMakeFiles_Legacy.txt and have users that depend on the older cmakes manually switch out the CMakeFiles.txt on their own.
tl;dr: Just don't support old versions.
CMake is absurdly easy to upgrade. Literally every halfway-modern development platform natively packages at least CMake 3.16+, but Windows and macOS are both way ahead of the curve with constant updates to the included version.
Visual Studio receives periodic updates and 2022 includes CMake 3.21. The version on Chocolatey is always up to date.
On macOS the Homebrew version is always up to date.
On Debian derivatives, Kitware provides an official APT repo that is always up to date. There is also a Snap package that is always up to date.
On most other Linux distros, one can use the official binaries directly from Kitware without sudo access at all. They have x86_64 and aarch64 binaries. The binaries are statically linked and require only libc6 as a dependency. Glibc has been ABI-stable since 1997. It will work on your system. But even if it doesn't, building a recent CMake version isn't difficult anyway. Your users maintaining such archaic systems shouldn't be your liability.
(aside: I wrote an entire blog post on this... https://alexreinking.com/blog/how-to-use-cmake-without-the-agonizing-pain-part-1.html)

How to make deployable software which uses libraries that do not have apt-get options with CMake

I wrote a piece of software which works well on my own box. It has been a headache to get it onto another box, though.
The main problem is that there is a library which it uses which is not a library covered by apt-get; it's called pngwriter. And pngwriter is also very finicky, and it is not very easily installed. It also has version compatibility issues. To get around all of that, I thought it would be great to include the source for pngwriter with my project, and have CMake go ahead and make pngwriter with the rest of the code.
So my main question is: Is this type of deployment canon? Should CMake call the makefiles that the developers of the software already wrote, and then use FIND_PACKAGE locally, or will I need to rewrite all of their makefiles so that I can use ADD_LIBRARY?
I'd recommend using the ExternalProject_Add function.
The docs are OK, but there is a decent article which explains things in a bit more detail. From this article:
The ExternalProject_Add function makes it possible to say “download this project from the internet, run its configure step, build it and install it”
Bear in mind that you can skip the install step altogether, or you could choose to install to a location inside your own build directory.

Is there a way for cmake to automatically extend the system PATH variable to compiled executables?

Can cmake configuration files also be used to automatically extend the system PATH variable to include the directory paths to all the installed executable applications and if it is possible (and a standard practice), how can I do this?
This way, as soon as I configure all the CMakeLists.txt files and everything compiles (and hopefully runs) nicely, I can start using the applications, and the path configuration would be packaged together with the build process. I am working with Linux and my code is written in C++, but since cmake is cross-platform, the question extends to other systems as well.
I'm unaware of any capability in CMake to do this. However, we based what we do what Cantera does. They upgraded to SCONS recently instead of their old build system, but the idea still applies.
Anyway, there's a script that CMake configures with the paths during the configure step and then installs somewhere. So once built on Linux, one would run make install then source ~/setup_cantera and it sets up all the variables needed.
We do the same thing for our libraries built with CMake. It's possible to detect which shell the user is running and configure an appropriate template script.

How to automate building of third party library using cmake

What I am looking for:
Download library
Extract It
Apply custom patch
Run configure
Run build command
What library I am trying to build are:
Openssl
Boost
Thrift
C-ares
Curl
Pcre
Nginx
ICU
JsonCPP
I think I can do these things using external module: http://cmake.org/cmake/help/v2.8.8/cmake.html#module:ExternalProject
But I have following question?
I have different type of build and with different directory. Is it
going to build all these library for every different target? If yes
it will be painful as all these library take one hour to build. Is
there a way I can control it and it only build it once. As library
remains same for all these targets.
On switching directory to different name. Cmake force everything to
be rebuild-ed. Will it be same for external library. If yes? How to
solve this problem. I don't want to rebuild the library if I am not
changing them and want to use them while switching to different
branches without building them.
Yes, you can use CMake's ExternalProject feature to accomplish what you want to do.
When using cross-compilation in combination with external projects, the source code will be built once for each toolchain. You could avoid rebuilds if you checked in the results of the build into a source-control system, and re-checked it out on each new person's machine, but I do not recommend this. Instead, have one of your "set up new computer" tasks actually be allowing the compilation to run overnight, which will also act as a test that the machine is actually usable. That set-up task can be launched by a system administrator prior to a new hire's arrival, or you can leave it to the new hire, as circumstances require.
I'm not completely certain what you are asking in your second question, but if the library is unchanged, CMake will detect that it is unchanged and not recompile it. Typically, the source code would be in a single directory tree: each compiled version would be built in a distinct location. Thus, developers can access any compiled version at any time just by switching directories. This is particularly helpful because it allows you to mount these directories over NFS to embedded hardware, et cetera.

Library search path for libstdc++

I have compiled shared libraries dynamically linked against libstdc++.so using GLIBCXX_3.4.11. I want to send my code to someone whose stdc++ library is only of version 3.4.10. Rather than ask him to update his library version (this is a software customer, so I can't assume they'll be willing or able to change system files) I would like to ship the appropriate version of libstdc++.so, placed in a lib folder with the directory location of my code. How do I get my own code to use the appropriate (later) version? I find that /etc/ld.so.conf includes the directory /lib64, where an offending older version of libstdc++.so resides. Setting LD_LIBRARY_PATH does not override this. This seems to deviate from the advertised behavior. Any idea why this is happening? How do I complete my rather simple task?
Thanks.
I understand that this question is old, but I found it while trying to sort out my own linking trouble which was similar. You will have to build your program against a version of libstdc++ which is compatible with your colleague's version of the library. The easiest solution, of course, is to link against his version of the library so he doesn't need to make special tweaks on his side to link your library.
To do this, you will want to install a version of GCC which can build binary compatible libraries so you can actually link against his version of libstdc++. GLIBCXX_3.4.11 is from gcc-4.4 and later, so you will need gcc-4.3. Build your program using this and you should be in good shape.
You can consult the following page for a list of library ABI compatabilities:
http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html
You could also build an rpm/deb which requires the version of libstdc++ you already have and if it's not available, refuse to install. This gives you a bit of an interface which gives him a promise that if his system is setup with the correct dependencies, he can use your library. In that sense, it's like a loose SLA for your library in what you do and don't support.
Hope that helps!