7.2.2.  Installing Libraries

[ fromfile: reusinglibs.xml id: installingsoftware ]

After a library has been written and tested, it will be installed at the end of the build process in the directory specified by the DESTDIR variable. For example, the project file for our utils 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 some particular location. For example, on a *nix platform, the following lines could be added to the project file for utils:

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

Then, if you have write access there, the command

make install

would copy the libutils.so files and their associated symlinks to the directory /usr/lib.

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 that is listed in your PATH variable. In *nix, you can copy the shared object file and associated symbolic links into a directory that is listed in /etc/ld.so.conf or one that is findable by searching in LD_LIBRARY_PATH.

During development, it is usually sufficient to make and install libraries in your home directory, and adjust LD_LIBRARY_PATH appropriately. 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.

[Tip] Building DLLs

Building Dynamic Link Libraries, or DLLs, is more complicated on Microsoft platforms, because we need to add 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.

We use handy preprocessor macro, Q_DECL_EXPORT, defined in <qglobal.h> which can conditionally switch on or off the declspec, and import or export the identifier at the right time, as shown below.

So for example, in the libutils, we define an export macro, shown in Example 7.2 called UTILS_EXPORT.

Example 7.2. src/libs/utils/myexport.h

ERROR: /home/sae/public_html/oopdocbook/docs/reusinglibs.xml: Unable to open inputfile: /home/sae/public_html/oopdocbook/docs/src/libs/utils/myexport.h. 

This macro is only going to export symbols when UTILS_DLL is defined, which is only going to be from utils.pro:

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

Now, for any class that we wish to export to the DLL, simply place the macro between the class and the classname in the class definition:

 
class UTILS_EXPORT Command : public QProcess {
  [ . . . ]
}

Finally, we need to add Windows-specific directive to the library project file to indicate that a corresponding libraryName.lib file must be created. For example, in utils.pro, we wish to build a utils.dll, and a corresponding utils.lib. We specify the path of the latter file like this:

win32 {
    QMAKE_LFLAGS += /IMPLIB:$$(CPPLIBS)/utils.lib
    CONFIG(dll) {
        DEFINES += UTILS_DLL
    } 
}

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