1.25. Causing a Source File to Be Linked Automatically Against a Specified Library

Problem

You’ve written a library that you’d like to distribute as a collection of headers and prebuilt static or dynamic libraries, but you don’t want users of your library to have to specify the names of the binaries when they link their applications.

Solution

If you are programming for Windows and using the Visual C++, Intel, Metrowerks, Borland, or Digital Mars toolsets, you can use pragma comment in your library’s headers to specify the names, and optionally the full file pathnames, of the prebuilt binaries against which any code that includes the headers should be linked.

For example, suppose you want to distribute the library from Example 1-1 as a static library libjohnpaul.lib together with the header johnpaul.hpp. Modify the header as shown in Example 1-26.

Example 1-26. Using pragma comment

#ifndef JOHNPAUL_HPP_INCLUDED
#define JOHNPAUL_HPP_INCLUDED

#pragma comment(lib, "libjohnpaul")

void johnpaul();

#endif // JOHNPAUL_HPP_INCLUDED

With this change, the Visual C++, Intel, Metrowerks, Borland, and Digital Mars linkers will automatically search for the library libjohnpaul.lib when linking code that includes the header johnpaul.hpp.

Discussion

In some ways, linking can be a more difficult phase of the build process than compiling. One of the most common problems during linking occurs when the linker finds the wrong version of a library. This is a particular problem on Windows, where runtime libraries—and the libraries that depend on them—frequently come in many variants. For this reason, libraries for Windows are often distributed with names mangled to reflect the various build configurations. While this helps to reduce version conflict, it also makes linking harder because you have to specify the correct mangled name to the linker.

For this reason, pragma comment is a very powerful tool. Among other things, it allows you to specify the correct mangled name of a library in a header file, saving the user the trouble of having to understand your name-mangling convention. If, in addition, you design your installation process to copy the binary files to a location automatically searched by the linker—such as the lib subdirectory of the Visual C++, CodeWarrior, or C++Builder root directories—programmers will be able to use your library simply by including your headers.

So far, so good. There’s just one problem: pragma comment is not recognized by all compilers. If you wish to write portable code, you should invoke a pragma only after verifying that it is supported by the toolset being used. For example, you could modify johnpaul.cpp to read:

#ifndef JOHNPAUL_HPP_INCLUDED
#define JOHNPAUL_HPP_INCLUDED

#if defined(_MSC_VER) || \
    defined(_  _ICL) || \
    defined(_  _MWERKS_  _) && defined(_WIN32) || \
    defined(_  _BORLANDC_  _) \
    defined(_  _DMC_  _) \
    /**/
# pragma comment(lib, "libjohnpaul") 
#endif

void johnpaul();

#endif // JOHNPAUL_HPP_INCLUDED

This example is already pretty complex, and, unfortunately, it’s still not exactly right: some compilers that don’t support pragma comment define the macro _MSC_VER for compatibility with Visual C++. Fortunately, Boost provides an easy solution:

#ifndef JOHNPAUL_HPP_INCLUDED
#define JOHNPAUL_HPP_INCLUDED

#define BOOST_LIB_NAME libjohnpaul
#define BOOST_AUTO_LINK_NOMANGLE
#include <boost/config/auto_link.hpp>

void johnpaul();

#endif // JOHNPAUL_HPP_INCLUDED

Here, the line:

#define BOOST_LIB_NAME libjohnpaul

specifies your library name, the line:

#define BOOST_AUTO_LINK_NOMANGLE

indicates that you don’t want to use the Boost name-mangling convention, and the line:

#include <boost/config/auto_link.hpp>

invokes pragma comment for compilers which support it.

See Also

Recipe 1.23

Get C++ Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.