Where does cmake look to find packages? - c++

In Ubuntu 14.04, I am compiling a C++ program, which depends on the following packages: CUDA and OpenNI. In the CMakeListst.txt file for this program, there is the following:
find_package(CUDA)
find_package(OpenNI)
And the output to cmake is:
Found CUDA: /usr/local/cuda (found version "6.5")
-- Could NOT find OpenNI (missing: OpenNI_LIBRARY OpenNI_INCLUDE_DIR)
So, it seems that CUDA was found, but OpenNI was not. Now, I have definitely installed OpenNI, but perhaps not in the standard location. Whereas the CUDA files are in usr/local/cuda as stated, my OpenNI files are in ~/Libraries/OpenNI.
My question is: How do I tell cmake where to look for to define the OpenNI_LIBRARY and OpenNI_INCLUDE_DIR variables? Is there a file somewhere which cmake has paths defined for all these variables, which I might need to manually edit?

It looks in CMAKE_MODULE_PATH.
Append to this path using expressions like this
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

There is no unified way that tells you where a find script will attempt to look for a library.
This is a bit unfortunate, but the only way to know for sure is to check the source of the find script itself. Most find scripts rely on find_library and similar commands to locate their files, which will by default search in a number of locations that are obvious candidates (like /usr/local/ on Unixes).
Unfortunately, this alone does not get you very far. If you are stuck on a platform like Windows where there is no reasonable default location, or you want to avoid polluting the directory tree, you need another way. Most find scripts therefore allow injecting the location of the library in some way.
In my experience, the cleanest way to do this is through environment variables. They are flexible to configure and convenient to use. In particular, you can make them persistent by adding them to your user's environment, so you don't have to type them out each time you run CMake.
If you check for example the find script for CUDA that ships with CMake, you will notice that it uses the environment variables CUDA_PATH, CUDA_LIB_PATH, CUDA_INC_PATH and CUDA_BIN_PATH (along with a few others) for this purpose.
An alternative is to directly set the result variables of the find script in the cache from the command line via CMake's -D parameter.
In any case you will have to check the find script source to find out what is the best course of action.
A word of advice: Do not attempt to hardcode locations in your own CMakeLists. While this might seem like a quick solution, it's also a very dirty one that essentially makes your build system non-relocatable. Always reach for solutions that allow the user to configure the build system from the outside without having to change CMake code.

Even if this is a quite old question: If you call cmake with --debug-find it will tell you where it looks for a package that you requested through a find_package() call in your CMake script.
My personal preference, especially for packages residing in their very own dedicated location, is to define an environment variable <package_name>_DIR, which points to the package's configuration file (assuming that the lib provides one). See the find_package() documentation about the search procedure for more details.

Related

How to remove/delete a cmake target?

In my CMake project I get the following error:
"add_custom_target cannot create target "uninstall" because another
target with the same name already exists."
Therefore I would like to remove/delete the already existing target.
How can I do that?
The problem is, that I do not write the CMake code that creates these two targets. These two different CMake scripts are downloaded and executed during the execution of my own CMake script and therefore I do not have complete control over that part of the CMake script.
Since those two targets are defined by projects that are not your own (external dependencies), as you said, you don't have much control over them.
There's no way to delete targets at configure time after the point that they are defined, and anyway, the error will always happen at the point of definition when a non-unique target name is attempted to be used.
Someone else had a similar problem here: Isolating gitsubmodule projects in CMake, and indicated in the comments that they were able to resolve their issues by using the Hunter package manager, so perhaps you could give that a try.
What you can also do is reach out to the upstream maintainers of those external dependencies and politely ask them to make their packages more friendly to use-cases like yours by "namespacing" their target names to mitigate name collisions. See also How to avoid namespace collision when using CMake FetchContent?.
If those project maintainers say no, you could try to work around the problem by patching their CMake files after the download. If you're using the ExternalProject module or the FetchContent module (which is built on top of ExternalProject), you might be able to do this with the PATCH_COMMAND argument (see the docs), which "Specifies a custom command to patch the sources after an update.".
Or, if you're feeling impatient and like doing some open-source contributing, you can ask how you can help with this Kitware issue ticket by Craig Scott proposing a CMake feature for Project-level namespaces.

Adding third-party libs to my CMake Project

I cant seem to wrap my head around a certain train of thoughts and was hoping you guys could help me seeing things more clearly. As I understand the find_package command should be all whats necessary to import third-party dependencies into my projects in modern cmake.
Is it considered good practice to use those commands always in the root CMakeLists.txt of my Project hierarchy that features several subfolders, that are added with add_subdirectory.()? Or should I use find_package in the subdirectory where it is actually needed?
I dont get the difference between Find.cmake and Config.cmake files. I believe Config.cmake files are the result of a library author correctly exporting the targets of his lib while Find.cmake files are like an auxiliary measure if a lib does not provide cmake-support, i.e. do not support clients to use CMake. But CMake itself might offer suitable Find.cmake files for proper adoption. Correct? So when do I have to install and export my lib?
thank your for your help
EDIT:
thank you for your hep Thomas. As a concrete example, I would like to add libQGLViewer as a third-party library to my project. However, the package-manager under Ubuntu 16.04 only offers an older version which depends on Qt4. Still, my project uses Qt5 and so I thought, I just download the lib and build it from source to /opt, no sweat. libQGLViewer uses qmake and so I turned to google and found a FindQGLViewer.cmake file. I copied this file to /usr/share/cmake-3.5/Modules and as I understand, this should render the command find_package(QGLViewer) to complete succesfully upon which the Variables ${QGLViewer_LIBRARIES} etc. are populated. However, it doesnt work and I cant figure out what the problem is, probably due to a general lack of understanding regarding these matters
CMake Warning at /usr/share/cmake 3.5/Modules/FindQGLViewer.cmake:108 (MESSAGE):
Could not find libQGLViewer.so, failed to build?
Call Stack (most recent call first):
CMakeLists.txt:57 (_find_package)
CMakeLists.txt:109 (find_package)
1. This depends on your project structure. If you invoke find_package() before adding any sub-folders, then you will ensure that the package is available to all sub-folders. If you instead invoke find_package() in one of the sub-folders, then that package will only be available after the fact.
If there is a chance that more than one sub-folder will depend on the package and at least one of these sub-folders is always part of the build (i.e. not optional), then the prudent thing to do would be to invoke find_package() at top-level before adding the sub-folders to ensure its availability to all sub-folders that might need it, without having to consider the order in which you add the sub-folders.
2. Your understanding is largely correct. Here is the official explanation. Yes, CMake ships with a number of Find-modules for common libraries, but the list is far from exhaustive even in terms of common libraries.

What are the specifics of installing CMake 3.3 alongside CMake 2.8?

I already have CMake2.8 installed, but I would like to install CMake3.3. Can I run into problems when installing both versions alongside each other? Also, how could I specify which CMake version I would like to use when installing packages? To be more specific, how would I run CMake3.3 rather than CMake2.8 and vice versa?
In my experience, having multiple versions of CMake is no different than having multiple versions of any other program. Just make sure the one you are executing is the one you want, which means you either always reference it using an absolute path, or you manipulate your PATH environment variable so the one you want is before the one you do not want. To avoid problems and conflicts with the installers/package managers, I simply install CMake directly by either building it from source of unpacking a pre-built from an archive. This way, I control its installed location.
As a good practice inside a CMakeLists.txt, you should always use the CMAKE_COMMAND variable when invoking CMake subprocesses. Documentation for CMAKE_COMMAND says, it is "the full path to the CMake executable."

Installing GMP on Windows with cygwin

I am new to C++ and I have to handle large integers, so I have to install GMP through Cygwin.
Any documentation I can find on installing this already assumes that you know what you are talking about, and I really don't.
Anyway, I got the right .tar or whatever, extracted it properly, and now any website I see says to run ./configure --prefix=${gmp_install}...
What in the world is gmp_install? And what directory do I run configure from? Huh? I can run it from my little Cygwin terminal, but it just says no such file.
Next, I am supposed to type make. From where?
Help...
Welcome to StackOverflow (SO).
The source directory of GMP should probably contain the file called configure. This is the script which you have to execute to "configure" the build system in your environment. It means that during configuration Autotools (the build system which is used to build GMP) will gather information about your environment and generate the appropriate makefile. Gathering information includes things like: understanding that you are on Windows, understanding that you are using Cygwin, understanding that your compiler is GCC and its version is x.y.z, and etc. All these steps are important for successful build.
You can specify a lot of different options to this configure script to tweak the configuration process. In your case, you specify the prefix option which determines the installation directory, i.e. the directory where you want the built and ready-to-use GMP distribution to reside. For example:
./configure --prefix=/D/Libraries/GMP
will configure the build system to install the GMP binaries to D:\Libraries\GMP directory.
Assuming that the GMP source directory (the one you extracted from *.tar) is located at say D:\Users\Me\Downloads\GMP, in order to build and install GMP you should do the following:
cd /D/Users/Me/Downloads/GMP
./configure --prefix=/D/Libraries/GMP
make
make install
NOTE: The make command will actually execute the makefile (which was generated by configure script) I've mentioned earlier. This file describes the process of building and installing GMP on your system.
NOTE: ${gmp_install} is nothing, but an environment variable. For instance, you could do:
export gmp_install=/D/Libraries/GMP
./configure --prefix=${gmp_install}
this can be useful, for example, when you have to use the same path in multiple places, and don't want to type it everytime. There are other cases, when this is useful, but for that you'll have to learn more about environment variables, what they are for, and Bash scripting in general. However, all this goes far beyond the answer on your question.
You'll have to spend quite some time to understand all these things and how they fit together, and you'd probably have to ask more questions here on SO as understanding all that stuff for a beginner alone might be very challenging.

Installation Script for simple c++ command-line tool, tutorial?

I'm working on a simple command line tool in c++. Half as a fun learning-process thing, and half to distribute to friends/colleagues etc.
I assume the easiest way to make it distributable is just packaging the source code with an installation script---can anyone point me to a good tutorial for setting that up?
In other words, what must a script include to compile the program, put the files in good places*, and make it executable from any directory from the command line?
E.g. I know the compiled binary should go in /usr/local/bin/ , but if I'm writing-to and accessing a text file (for instance), where should that go? What about a file that stores settings/configuration-parameters?
I'm on mac osx, so that would be the starting point, but portability to windows, linux, etc would be great.
You can use CMake to make a cross platform build system, and you can use it's CPack (Wiki here) feature in order to generate binary only packages. First you create a build script that runs and installs on each platform (which CMake makes as easy as can be expected). You then run CPack to generate a package which just includes your binaries.
There is a good tutorial that covers the basic cmake process (including install commands) here.
CMake is generally considered simpler then autoconf (and has better windows support), but each has it's own strengths.
Do not assume that the user installing the program has root access. Prompt, or provide a command-line option, like --install-prefix=/home/user/apps, to specify where to install.
I HATE programs that install shit in /usr/local. If you do that, you'd best wrap it up in an .rpm or .deb or whatever the platform package is so that your app can be cleanly uninstalled.
I would suggest checking out autoconf