Linking and Add Executable on CMAKE? - c++

I am learning CMAKE and the example I have has both link_directories before and after add_executable. My question is: how does the process work? Which is supposed to go first and what is the purpose of one going before the other?

Not sure if this order matter. Probably not. "link_directories" will tell the compiler where to look for the libraries you desire to use. The names of the libraries you put in "target_link_libraries" command.
Actually, with CMake, "link_directories" is not used too often. Usually you use a module script to find your libraries with "find_package" (e.g., findCUDA, findJPEG, etc...) and pass to "target_link_libraries" the variables defined by these scripts containing the full path of each library.

Related

How add compile-only dependency with cmake

I need to add a compile-only dependency to external lib my in CMake file - referred to as the_lib later in the question. By saying compile-only dependency I mean propagating compile-time properties, most importantly -I rules.
The library in question is created as a library target using add_library. Normally I would simply use target_link_libraries(my_exec the_lib), but this adds both compile-time and link-time properties, i.e., this adds both -I and -l/-L rules to compilation commands, while I only need -I. (If anyone is curios why I need such a setup, this is because reasons.)
Please note, target_include_directories with something like ${the_lib_SOURCE_DIR} (or anything similar to that effect) would not work for me, because it wouldn't add include directories necessary for the lib. I need something like ${the_lib_INCLUDE_DIRS} where the_lib_INCLUDE_DIRS would be populated to as -I rules required by the_lib - but I didn't find any variable which would match that.
It is worth noting that I can't (or shan't) modify the the_lib.
I need to add a compile-only dependency to external lib my in CMake
file
By an "external" lib, I take you to mean one that is not part of the same project -- i.e. one that is not configured within the scope of the same CMake build system as the target you're trying to build.
[...] Normally
dependencies are added with target_link_libraries(my_exec the_lib),
but this adds both compile-time and link-time dependency.
Well no, not necessarily. As it says on the tin, that adds a link dependency, which you can think of as an -l option. To the best of my knowledge, it does not generate any -I options for external libraries, or otherwise have any impact on the compilation phase with regard to external libraries. Similarly, as far as I am aware, it propagates transitive dependencies of any sort only when the the added library is another target configured and built by the same build system. That is, only for internal libraries, not external ones.
Please note, target_include_directories with something like
${the_lib_SOURCE_DIR} (or anything similar to that effect) would not
work for me, because it wouldn't add include directories necessary for
the lib. I need something like ${the_lib_INCLUDE_DIRS} where
the_lib_INCLUDE_DIRS would be populated to as -I rules required by
the_lib - but I didn't find any variable which would match that.
I think you're asking for the include directories that would be necessary to successfully use the_lib's headers, in a situation where those headers have their own external dependencies. There's a reason why you don't find a variable appropriate to that: there is no consistent or standard way to obtain that information for external libraries. The available techniques depend on the_lib. They will include some, but probably not all, of the following:
Use a CMake macro provided with the_lib or with CMake itself to define a CMake variable conveying the wanted information.
Use pkg-config to read the information from a pkg-config entry associated with the_lib.
Use some technique idiosynchratic to the_lib, along the line of Python's python-config.
Analyze the_lib's headers to determine the external packages they depend upon, and search explicitly, individually for those packages' headers.
Require the user to specify manually for any required packages that are not in the default include path.
There is no magic variable or function in CMake to automatically glean such information, because generally speaking, it is not available from the_lib's headers themselves. Note, too, that most of those would depend on the_lib's include dependencies being installed in specific places anticipated at the_lib's build time. That's pretty hard to ensure.

Locating "undefined" references in a C/C++ Project

I am building a C++ project on my Ubuntu 64bit system using a provided Makefile, and this project also provides an API library for developers.
The compilation was successful, no errors at all, but when I try to include in my files the API libraries provided in the "api" folder, then g++ complains about undefined references.
It is not a problem about dependencies (I already built the project succesfully), in fact the missing references are about classes and functions provided by the project, but they are in some specific (sub-)folders (I don't know which ones!), I guess in some .so files, and g++ is not finding them, probably because it does not know they are in those specific subfolders.
It is not the first time this happens when trying to use APIs from any project, then I think I am missing something or I am doing something wrong in general when trying to use the libraries provided in a project.
In particular, the main problem is that I don't know how to tell the compiler where some classes or data structures are declared, and moreover I don't know how to locate them in order to know where they are.
Usually, a workaround I use to avoid this problem is to run make install (as root or using sudo) so that libraries and APIs are installed in standard folders (like /usr/include or /usr/lib) and if I do this thend I can include the API libraries using #include <library>, but in this last case it didn't work either, because perhaps some required files containing the not found classes/structures are not properly installed in the right folders in the system.
Another workaround I used sometimes is to try to put all the project files in the same folder instead of using the project folder structure, but clearly this is not good! :-)
But I noticed that several other people managed to use the APIs, then apparently they know some way of finding the files containing the "undefined" references and including them in the compilation.
Then my general question is: given a "classic" C++ project based on "Makefile" files and with usual folder names like src, lib, build, bin, etc., if I want to write C++ files using the libraries provided by the project, but the compiler complains about undefined references, how can I find the files (.so or .o or .cpp) containing such references? Is there any tool to find them? And how can I tell the compiler where they are? Should I use some command-line option for g++ or should I use the #include macro in some smart way?
PS I also tried to use the pkc-config linux tool to get right options to use for compilation and they were available, but the compiler still complains about the undefined references.
Some more degails about the project i tried:
For interested people a link to the project is below:
https://github.com/dreal/dreal3
And instructions on how to build it:
http://dreal.github.io/download/
Look into the -rpath linker option - specifically with the "$ORIGIN" argument. That lets you find libraries relative to your executable location so you don't have to install them to the standard locations but just need to put them somewhere known, relative to the executable. That should help you with one piece of the puzzle.
Note: -Wl, can be used to pass arguments to the linker via g++.
As for pointing the compiler/linker at a library so it can resolve undefined references by using that library, use the -l (that's lowercase L) option to specify the library name and -L to specify directories to search for libraries.
As for looking into a library (.so) file to see what symbols are in there, you have a few tools at your disposal: objdump, nm, readelf and objcopy.

What is the difference between a lib and an module with autoconf

I have to check that certain libraries (libm, libdl) are present in order to compile my library.
In my configure.ac template file, there is PKG_CHECK_MODULES macros and PKG_CHECK_LIB macros.
I don't understand which one to use and how?
The PKG_CHECK_MODULES seems the most global one because it checks if a whole library is present and PKG_CHECK_LIB checks only if one function is accessible… But when I do PKG_CHECK_MODULES([LIBM],[libm],[],[exit -1]), it exists and I don't understand why.
I think I'm misunderstanding some concepts. Maybe someone could lead me to good references.
PKG_CHECK_MODULES is for integrating with packages that have pkg-config metadata. This metadata is typically stored in a file called foo.pc (for package foo) in someplace like /usr/share/pkgconfig. This file will say where foo and its associated files (header files, libraries, executables, data, etc.) have actually been installed.
However, most packages don't use the pkg-config system, including the standard C library which is where libm and libdl are. So you'll need to test for them using AC_CHECK_LIB.
You seem to be confused, so I'll go on a bit of a tangent here:
Once upon a time, there was X11; there were many incompatible installations of X11. To write code that would compile against each variant, people would write crazy autoconf macros to try to figure out automatically what libraries to list before, what libraries to list after, and what extra flags were needed in between. (see AC_PATH_X, AC_PATH_XTRA).
Some people tried more sensible approaches, and wrote shell scripts to install along the libraries; so you would just call them and they would give you all the magic flags needed for that specific libraries. (see sdl-config, wx-config, freetype-config, motif-config, etc)
Then the folks from freedesktop.org decided it was a chore for everyone to maintain those scripts that did essentially the same thing, so they wrote a tool (pkg-config) that would work like all those *-config scripts, and would not require a shell to run (yay for Windows users). All the library authors need to do is to write the metadata in the *.pc files, and install them along the libraries.
Regarding autoconf, it has low-level ways to poke around the system to find out about the libraries: AC_CHECK_HEADERS, to see if the headers are present and usable, and AC_CHECK_LIB, to see if it's possible to link against them.
The pkg-config tool comes with convenience macros for autoconf, mainly PKG_CHECK_MODULES, which instead of poking around, it simply looks for the metadata the library might have installed.
Regarding libm, libdl, as ldav1s said, they are part of the system; some systems need explicit link against libm (which provides math functions) and/or libdl (which provides functions for dynamically loading shared objects). Often other tools, like gcc or libtool, take care of linking against them. Unfortunately they don't come with meta-data for pkg-config, so if you have to find them manually, you'll have to poke around with the old AC_CHECK_HEADERS and AC_CHECK_LIB macros to find them.

Boost C++ libraries installation

I have just downloaded the boost libraries from the boost website and extracted them to my desktop. I was hoping to just have a quick look at them and have them installed on my machine and perhaps use them in the future when I am more accustomed to C++.
When I extracted it, I was confused with all of the extracted files. There is all of the headers in the boost directory but tutorials mention running bootstrap.bat (I'm using Windows).
So I am asking this: do I simply extract the headers to my compilers include directory like normal to get boost up and running or do I need to do something else?
As I understand it from searching about, apparently "most" of boost is just templates and can be used simply by including the headers, but what about the rest?
Am I totally barking up the wrong tree?
Thanks for any help
Since you mentioned you run Windows, take a look at this automated installer:
► http://www.boostpro.com/download/
Also, some general advice:
do I simply extract the headers to my compilers include directory
No! Do not pollute your compiler's includes with third-party includes; make a separate directory specifically for a particular library. You'll then need to tell your specific IDE in what directory it can find the library headers.
I usually use boostpro's installer, it is less work. I vaguely remember having to set up the BOOST_ROOT environment variable on one of my systems to use it.
The libraries that contained compiled source should be included in the installer.
If you don't use the installer (or don't set up your build correctly), and try to use the libraries that need it you will likely get some linker errors when you try and compile your program. Usually if you take those linker errors and plop them in google it tells you pretty quick which libraries you need to include in your build system. I use CMake for that and have been very happy..
Just add the root boost directory to include paths of your compiler/IDE (so if you have Boost extracted to C:\Boost, the compiler will use that path, not C:\Boost\boost).
Don't do any copying of the boost folder to your compiler's include directory, because it may make upgrading Boost harder in the future.
Also if you plan to use any of boost's compiled libraries, add Boost's lib directory to compiler's library search paths. Configuring the compiling step is a matter of putting the right toolset parameter to boost's build tool. If you have your command line environment configured properly, bootstrap should run and compile the builder without any problems, and the Boost builder should properly detect your toolset, so no parameters will be necessary.
As you do such configuration only once every time you do a clean install of your favorite compiler, it's not as hard or daunting as it seems.

Building Boost without filename decorations?

The default naming convention for the Boost C++ libraries is:
libboost_regex-vc71-mt-d-1_34.lib
where all libraries are built into the same directory. I'd like to modify the build process so that the filename does not contain the target architecture or build type (versions are okay). I want the file to end up in a different directory depending on the architecture being built for:
vc71/debug/libboost-1_34.lib
vc71/release/libboost-1_34.lib
Any idea on how to do this?
You can remove all decoration from the library filenames by passing "--layout=system". Your example above shows "vc71/release" paths -- there's no out-of-box way to get this layout. You can do that with a bit of hackign. In Jamroot, find the 'stage-proper' target, which specifies the location as:
<location>$(stage-locate)/lib
You can modify that to specify different locations depending on properties, e.g:
<variant>release:<location>$(stage-locate)/lib/release
<variant>debug:<location>$(stage-locate)/lib/debug
Please see Boost.Build website for more documentation
I don't know of any way to do that with the Boost build system, but you could use a fairly simple script to move and rename them without too much difficulty.
On the other hand, with most Windows compilers, you seldom need to concern yourself with the library filenames because, for those libraries that require a separate binary, Boost employs auto-linking:
Most Windows compilers and linkers have so-called “auto-linking support,” which eliminates the second challenge. Special code in Boost header files detects your compiler options and uses that information to encode the name of the correct library into your object files; the linker selects the library with that name from the directories you've told it to search.
Moving and renaming the files would break that.