Where do I put third-party libraries to set up a C++ Linux development environment? - c++

I'm not new in C++ although I'm new in Linux. I'm using CMake to precompile a cross-platform game engine with some third-party components, but I have a lot of doubts about using libraries. My question is how to work with third-party libraries and where to put them. Apt installs libs in their official place (/usr/local, /usr/lib/ ..) but I develop in Windows using local libs that are in a folder in my project dir.
Also, I need a good tutorial to know the rules of how libraries work. For example: when trying to compile my project, luabind is asking for liblua.s0.1, but AFAIK there is no way to generate this library with the source provided by Lua (at least doing make, make install).
I know, this question is fuzzy but I haven't enough experience to be more concise.
Update: After reading some answers, a more concise question is the following. If I install all third-party libraries, how can I distribute my program? How do I manage dependencies without using a large readme?

Where to put libraries
The best solution is to use your Linux distribution's packaging system (apt-get, yum, or similar) to install libraries from distro-provided packages wherever possible.
If the distro's packaged libraries aren't of a recent enough version, or if you need some nonstandard build options, or if you need a library that your distro doesn't provide, then you can build and install it yourself. You have two main options for where to put the library:
/usr/local (libraries under /usr/local/lib, headers under /usr/local/include). This installs the libraries systemwide and is probably the simplest solution, since you should then be able to build against them without taking any extra steps. Do NOT install libraries directly under /usr, since that will interfere with your distro's packaging system.
Under your project directory, as you did under Windows. This has the advantages of not requiring root access and not making systemwide changes, but you'll have to update your project's include paths and library paths, and you'll have to put any shared library files someplace where the dynamic linker can find them (using LD_LIBRARY_PATH or ld.so.conf - see the link for more details).
How libraries work
See David A. Wheeler's excellent Programming Library HOWTO. I'd recommend reading that then posting any specific questions as new topics.
How to distribute your program
Traditionally, Unix / Linux programs do not include copies of their dependencies. It's instead up to the end user or developer to install those dependencies themselves. This can require a "large README," as you said, but it has a few advantages:
Development libraries can be installed, managed, and updated via the distro's package manager, instead of each source copy having its own set of libraries to track.
There's only one copy of any given library on a system, so there's only one place that needs updating if, for example, a security flaw is found. (For example, consider the chaos that resulted when zlib, a very widely used compression library, was found to have a security flaw, so every application that included an affected version needed to be updated.)
If your program is popular enough (and is open source or at least freely available), then package maintainers for various Linux distributions may want to package it and include it in their distro. Package maintainers really don't like bundled libraries. See, for example, Fedora's page on the topic.
If you're distributing your program to end users, you may want to consider offering a package (.dpkg or .rpm) that they could simply download and install without having to use source. Ideally, from the end user's perspective, the package would be added to distros' repositories (if it's open source or at least freely available) so that users can download it using their package managers (apt-get or yum). This can all get complicated, because of the large number of Linux distros out there, but a Debian/Ubuntu compatible .dpkg and a Red Hat/CentOS/Fedora-compatible .rpm should cover a good percentage of end users. Building packages isn't too hard, and there are good howtos online.

for the first part of your question regarding Windows: there's no real standard place for libraries/headers on Windows, so the easy solution is: create your own. Simply provide a single lib/ and include/ on your system and have all your projects use it (by setting the path in a cmake file that you include everywhere). Put all third party libs in there, for example:
your projects:
d:/projects/projectA
d:/projects/projectB
third party stuff:
d:/api/lib/lua.lib
d:/api/include/lua/....
(you can even use symlinks aka 'directory junctions' if you have different version)
and the corresponding cmake file:
include_directories( d:/api/include )
link_directories( d:/api/lib )

Okay, so this is one of the basic questions and while I myself might not come across very clear on this, here goes:
While building a project, your compiler will need to find the header files of the libraries. The headers must be in the include path.
after compilation is done, the linker will look for the library binaries (files.so or something like that). These must be in the Library path.
That's the basics.
If you have some specific libaries, you can add them to your own project-specific lib/ and include/ directories and add them to the include path and the library path respectively.
Adding these dirs to these paths can be done in many ways, depending upon how you are building the project. I'm sure there is something called LD_PATH involved in all this... But I don't really know the specifics involved with CMake.
A little googling can help you do the above with CMake.
Hope that helps,
jrh

If you are installing the libraries with a package manager, they will probably all end up in the right place. If not you can get the compiler to search for the by providing the an additional search path using the -L <path> flag. You should be able to pass this extra flag to CMake.
Incidentally the -I <path> can be used to add an extra directory to search for include files.

Related

CMake build a standalone binary for RedHat EL6 from Ubuntu with dependent shared libraries

I have been developing a research code using CMake to generate the Makefiles for a c++ code on an Ubuntu machine. I link in several shared libraries which are rather involved to setup and build on a machine (one in particular has a dozen or so version specific dependencies which themselves are non trivial to build). Some are also custom builds of the library (bug fixes).
I am more familiar with the windows environment with the CLR, but, what I am hoping to achieve is building the binary and including all of the shared libraries along with it. Hopefully the linker on the other environment (redhat EL6) would then be able to use those shared objects at runtime.
Since the linker doesn't look in the applications path, I assume I would also need to bring the shared libraries into a user specific library path for it to find.
Is there a nice way using Cmake (perhaps Cpack), to build the binary and 'package' all of the shared objects with it for the other machine? Then I could (even if manually) install the shared libraries for my user only, and run the binary there.
I'm hoping the answer is not using static libraries, as that has given me a lot of trouble for these dependencies in the past.
I'm a linux noob, so if my issues is in lack of understanding a better approach I am all ears :)
One approach is to set the "rpath" of the binary, which hardcodes some additional search paths. One can set it to $ORIGIN, which means that libraries in the same directory as the binary itself will be used first.
IF(UNIX)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH}:\$ORIGIN/../bin:\$ORIGIN")
ENDIF()
This CMake code takes effect at install time (make install), so first you need to set up the INSTALL commands of your CMake setup. INSTALL both your binary and all extra shared objects. Finally, CPack internally runs an "install", so once make install works, you can use CPack to automatically build a TGZ, or even an RPM if you're willing to invest the time to get it set up.
Here's an old answer of mine which talks about a similar but not identical issue, linked for completeness:
https://stackoverflow.com/a/22209962/1401351

How do you link to a library from the software manager on Linux?

So I recently got fed up with Windows and installed Linux Mint. I am trying to get a project to build I have in Code::Blocks. I have installed Code::Blocks but I need glew(as well as a few other libraries). I found it in the software manager and installed it. I've managed to locate and include the header files. But I feel like the next step should be relatively straightforward and all over the internet but (perhaps due to lack of proper terminology) I have been as of yet unable to locate an answer.
Do I need to locate the files on my system and link to each library manually? This is what I did on windows but I just downloaded the binaries and knew where they were. I found one library from the software manager and linked to it manually but it just feels like I'm doing it the wrong way. Since it's "installed" on the system is there some quick way to link?
You should use two flags for linker '-l' and '-L'. You can set these flags somewhere in project properties.
The first one '-l' tells linker to link with particular library. For example glew, probably in /usr/lib is a file named libglew.so, when you link your program with '-lglew' flag, it will link it with glew library. Linker looks for libraries in few standard places: /usr/lib, /usr/local/lib and few extra. If you have your libs in nonstandard place, use '-L' flag to point these dirs.
Many linux distributions provide two kinds of packages with libraries, regular ones just with runtime, and devel ones (usually prefixed or suffixed with dev or devel) with header files and development version of libraries.
use build systems, Luke!
the typical way to develop/build software in *nix world is 3 steps:
configure stage -- before building smth you have to realize in what environment you are going to build your software... is everything that required is installed... it wouldn't be good if at compile stage (after few hours of compilation) you (or user who build your soft) got an error: unable to #include the 'xxx.h'. the most popular build systems are: cmake, my favorite after autotools. yout may try also scons or maybe crazy (b)jam...
compile stage -- usually just make all
install stage -- deploy just built software into the system. or other way: build packages for target distro (.deb/.rpm/&etc)
at configuration stage using test scripts (don't worry there are plenty of them for various use cases) you can find all required headers/libraries/programs/compiler options/whatever you need to compile your package... and yes: do not use hardcoded paths in your Makefiles (or whatever you use to make your binaries)
Answer to this question really depends on what you want to achieve. If you want just to build you app by yourself then you can just write path to libraries in your makefile, or your code editor settings. You may not even have to do that as if libraries installed by your linux distribution package manager, headers usually go to /usr/include and libraries to /usr/lib or /urs/lib64 etc. That locations are standard and you do not need to specify them explicitly. Anyway you need to specify libraries you want to link to.
If you want to create application that can be build by others, or by you on many different configurations/environments using something like cmake would be very helpful.

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)

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.

library location for project

I have started an C++ SFML project for linux. I was wondering where the .so's should go.
Should they go inside the project folder so a user can simply run the program after they get it? Or should the user have the SFML library installed on there linux machine before they run my program?
Even if you did include the .so files, you have no guarantee that the user will be able to run it (different architecture, libraries linked against different libc, ...). Either link statically, or better yet, just let them provide the supporting libraries themselves.
#Joel J. Adamson's answer to use autoconf is a good idea. SFML doesn't come with a pkg-config file, so you will check for SFML as follows:
dnl Checking for a C++ compiler
AC_PROG_CXX
dnl Checking C++ features. This tells configure to use the C++ compiler for checks.
AC_LANG_PUSH([C++])
dnl Check for a SFML header.
AC_CHECK_HEADER([SFML/Config.hpp], [], [AC_MSG_ERROR([SFML headers not found.])])
AC_LANG_POP([C++])
Checking for the libraries is a bit more difficult because of name mangling and so on. Tyler McHenry wrote a good article on this part, if you want to be thorough.
At the distribution level SFML will be a dependency, i.e. a user will have to install it (or their package manager will have to install it) before compiling your program. If a user wants to compile it, they will also need the header files (often there's a separate "devel" package to install). You shouldn't have to distribute the .so files, and it's probably better (for everybody) if you don't.
You will need to check if the user has it, e.g. using autoconf you need to check for the relevant headers in your configure.ac for the application project. For example, to check for the math library, because I'm using the exp() function, I'll use
AC_CHECK_LIB([m], [exp])
to create a check during the configure step. Luckily autoscan can check this for you and create a skeleton configure.ac file called configure.scan. See also Cmake.
HTH.
You should make your program depend on the specific library (and version) that it needs. If you're planning to package it into an rpm/deb file you should add the dependency there too so that it can be checked and applied by package managers (e.g. apt can install all the dependency packages of a given package)