7.1.2.  Installing Libraries

[ fromfile: reusinglibs.xml id: installingsoftware ]

When a library is built, it is placed in the directory specified by the qmake variable DESTDIR. For example, the project file for our dataobjects library contains the following relevant lines:

TEMPLATE = lib      # Build this as a library, not as an application
DESTDIR=$$(CPPLIBS) # Place the compiled shared object code here

For library templates, qmake can generate a Makefile with the install target so that the command

make install

will, after a successful build, copy the library to another particular location. For example, on a *nix platform, you can add the following lines to the project file for dataobjects:

target.path=/usr/lib
INSTALLS += target

Then, provided that you have write access there, the command

make install

will copy the libdataobjects.so files and their associated symlinks to the directory /usr/lib, making that library usable by anyone logged into that computer.

If you need to relocate a library, the procedure varies from platform to platform. In Windows, you can copy its .dll file into an appropriate directory listed in your PATH variable. In *nix, you can copy the shared object file and associated symbolic links into a directory listed in /etc/ld.so.conf or one listed in your LD_LIBRARY_PATH variable.

During development, it is usually sufficient to build libraries in your CPPLIBS directory, and adjust LD_LIBRARY_PATH appropriately. On a *nix system, if you have followed our advice and made consistent use of the CPPLIBS environment variable, you only need to add the line

export LD_LIBRARY_PATH=$CPPLIBS

to your .bashrc file, below the line in which you define CPPLIBS. At deployment time, on a *nix platform, it may be desirable to install the library in /usr/local, a systemwide location accessible to all other users. This would require superuser permissions.

[Note] QTDIR

The environment variable QTDIR is not required by Qt, but we sometimes use it in different parts of the book to refer to the base directory of an unzipped Qt tarball. It provides a convenient way to refer to the location of the examples, tutorials, binaries, and libraries of Qt. However, on systems like Ubuntu or Debian, where Qt is split into multiple folders and installed to different locations, QTDIR should not be, and is not defined (if you are using the distro's version of Qt). In that case, you can interpret our usage of QTDIR to mean "the parent directory of the Qt binaries" or "the parent directory of the Qt examples" (which may be two different directories in that case).

[Tip] Building DLLs

Building Dynamic Link Libraries, or DLLs, is more complicated on Microsoft platforms, because you need to define a unique "exporter" macro for each library.

This macro expands to the appropriate __declspec() export or import, depending on whether the header file is included from its own library or an external program.

You can use a handy preprocessor macro, Q_DECL_EXPORT, defined in <qglobal.h> that can conditionally switch on or off the declspec, and import or export the identifier at the right time.

So for example, in libdataobjects, we define an export macro, shown in Example 7.2 called DOBJS_EXPORT.

Example 7.2. src/libs/dataobjects/dobjs_export.h

#include <QtGlobal>
#ifndef DOBJS_EXPORT
/* This macro is only for building DLLs on windows. */
#ifndef Q_OS_WIN
#define DOBJS_EXPORT
#elif defined(DATAOBJECTS_DLL)
#define DOBJS_EXPORT Q_DECL_EXPORT
#else
#define DOBJS_EXPORT Q_DECL_IMPORT
#endif
#endif

This macro only exports symbols when DATAOBJECTS_DLL is defined from dataobjects.pro:

win32 {
   CONFIG(dll) {
      DEFINES += DATAOBJECTS_DLL
   }
}

Now, for any class that you want to export to the DLL, simply place the macro between the class keyword and the classname in the class definition:

class DOBJS_EXPORT DataObject : public QObject {
  [ . . . ]
}

There is a thread on the subject at qtcentre.org that might save you a lot of time when you build your first DLL.

[Note] QLibrary

The QLibrary class has methods to help you load and unload dynamic libraries at runtime in a platform-independent way.