You wish to use your command-line tools to build an executable that depends on several static and dynamic libraries.
Start by building the static and dynamic libraries on which your application depends. Follow the instructions distributed with the libraries, if they are from a third party; otherwise, build them as described in Recipe 1.3 and Recipe 1.4.
Next, compile your application’s .cpp files into object files as described in “Building a Simple “Hello, World” Program from the Command Line. You may need to use the -I option to tell your compiler where to search for the headers needed by your application, as shown in Table 1-12.
Finally, use your linker to produce an executable from the collection of object files and libraries. For each library, you must either provide a full pathname or tell the linker where to search for it.
At each stage of this process, if you are using a toolset which comes with static and dynamic variants of its runtime libraries, and if your program uses at least one dynamic library, you should direct the compiler or linker to use a dynamically linked runtime library, as described in Recipe 1.23.
Table 1-13 presents commands for linking the application hellobeatles from Example 1-3. It assumes that:
The current directory is hellobeatles.
The static library libjohnpaul.lib or libjohnpaul.a was created in the directory johnpaul.
The dynamic library georgeringo.dll, georgeringo.so, or georgeringo.dylib and its import library, if any, were created in the directory georgeringo.
Tip
Since Comeau can’t build dynamic libraries, as mentioned in Recipe 1.4, the entry for Comeau in Table 1-13 assumes that
libgeorgeringo has been built as a static library rather than as
a dynamic library. To build libgeorgeringo as a static library,
remove the modifier GEORGERINGO_DECL
from the
declaration of the function georgeringo()
in Example 1-2.
Table 1-13. Commands for linking the application hellobeatle.exe
Toolset |
Input files |
Command line |
---|---|---|
GCC (Unix) |
hellobeatles.olibjohnpaul.alibgeorgeringo.so |
g++ -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or g++ -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a../georgeringo/libgeorgeringo.so |
Intel (Linux) |
icpc -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or icpc -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a../georgeringo/libgeorgeringo.so | |
Comeau (Unix) |
como —no_prelink_verbose -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or como —no_prelink_verbose -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a ../georgeringo/libgeorgeringo.a | |
GCC (Mac OS X) |
hellobeatles.olibjohnpaul.alibgeorgeringo.dylib |
g++ -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or g++ -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a../georgeringo/libgeorgeringo.dylib |
Metrowerks (Mac OS X) |
mwld -o hellobeatles hellobeatles.o -search -L../johnpaul -search -L../georgeringo -ljohnpaul -lgeorgeringo or mwld -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a ../georgeringo/libgeorgering.dylib | |
GCC (Cygwin) |
hellobeatles.olibjohnpaul.alibgeorgeringo.dll.a |
g++ -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or g++ -o hellobeatles hellobeatles.o ../johnpaul/libjohnpaul.a../georgeringo/libgeorgeringo.dll.a |
GCC (MinGW) |
hellobeatles.olibjohnpaul.alibgeorgeringo.a |
g++ -o hellobeatles hellobeatles.o -L../johnpaul -L../georgeringo -ljohnpaul -lgeorgeringo or g++ —o hellobeatles hellobeatles.o../johnpaul/libjohnpaul.a../georgeringo/libgeorgeringo.a |
Visual C++ |
hellobeatles.objlibjohnpaul.liblibgeorgeringo.lib |
link -nologo -out:hellobeatles.exe -libpath:../johnpaul -libpath:../georgeringo libjohnpaul.lib libgeorgeringo.lib hellobeatles.obj |
Intel (Windows) |
xilink -nologo -out:hellobeatles-libpath:../johnpaul -libpath:../georgeringo libjohnpaul.lib libgeorgeringo.lib hellobeatles.obj | |
Metrowerks (Windows) |
mwld-o hellobeatles-search -L../johnpaul libjohnpaul.lib -search -L../georgeringo libgeorgeringo.lib hellobeatles.obj | |
Metrowerks (Mac OS X)[6] |
mwld -o hellobeatles hellobeatles.o -search -L../johnpaul -search -L../georgeringo libjohnpaul.a libgeorgeringo.dylib | |
CodeWarrior 10.0 (Mac OS X)[7] |
Consult the Metrowerks documentation | |
Borland |
bcc32 -q -WR -WC -ehellobeatles -L.../johnpaul -L.../georgeringolibjohnpaul.lib libgeorgeringo.lib hellobeatles.obj | |
Digital Mars |
link -noi hellobeatles.obj,hellobeatles.exe,NUL,user32.lib kernel32.lib ..\johnpaul\ ..\georgeringo\ libjohnpaul.lib libgeorgeringo.lib,, or link -noi hellobeatles.obj,hellobeatles.exe,NUL,user32.lib kernel32.lib ..\johnpaul\libjohnpaul.lib ..\georgeringo\libgeorgeringo.lib,, | |
Comeau (Windows) |
hellobeatles.objlibjohnpaul.liblibgeorgeringo.lib |
como —no_prelink_verbose -o hellobeatles ../johnpaul/ libjohnpaul.lib ../georgeringo/libgeorgeringo.lib hellobeatles.obj |
[6] hellobeatles may not execute properly when built with the indicated command line, since the application will make use of two copies of Metrowerks’s static runtime support libraries. (See Recipe 1.23.) [7] CodeWarrior 10.0 for Mac OS X will provide dynamic variants of its runtime support libraries; these should be used when building hellobeatles. (See Recipe 1.23.) |
For example, if you use Microsoft Visual Studio .NET 2003, and if it is installed in the standard location on the C drive, you can build hellobeatles.exe from the command line by changing to the directory hellobeatles and entering the following from the commands:
>"C:Program Files\Microsoft Visual Studio .NET 2003\VC\bin\
vcvars32.bat"
Setting environment for using Microsoft Visual Studio 2005 tools. (If you have another version of Visual Studio or Visual C++ installed and wish to use its tools from the command line, run vsvars32.bat for that version.) >cl -c -nologo -EHsc -GR -Zc:forScope -Zc:wchar_t -MD -I..
-Fohellobeatles hellobeatles.cpp
hellobeatles.cpp >link -nologo -out:hellobeatles.exe -libpath:../johnpaul
-libpath:../georgeringo libjohnpaul.lib libgeorgeringo.lib
hellobeatles.obj
The -I option is used to
specify an include path. When a
compiler—actually the preprocessor—encounters an include
directive of the form:
#include "file
"
it typically first attempts to find the referenced file by interpreting the given pathname relative to the location of the source file being processed. If this is unsuccessful, it attempts to locate the file in one of the directories specified with the -I option, and then in a list of toolset-dependent directories, which can often be configured using environment variables.
The situation is similar when an included header is specified using angle brackets, like so:
#include <file>
except that compilers generally don’t interpret the given pathname relative to the location of the source file being processed.
There are several interesting aspects of the command lines in Table 1-13.
On Windows, the input to the linker consists of object files, static libraries, and import libraries; on Unix, it consists of object files, static libraries, and dynamic libraries.
On both Windows and Unix, libraries can be passed to the linker in two ways:
By specifying a pathname on the command line
By specifying the simple name of the library together with a location to search for the library
Table 1-13 illustrates both methods.
The locations to search for libraries can usually be specified on the command line. Most linkers use the option -L<directory> for this purpose, but Visual C++ and Intel for Windows use -lipath: <directory> and Metrowerks uses -search -L<directory>. The Digital Mars linker allows library search paths to be listed on the command line alongside library files, with search paths distinguished from library files by a trailing backslash; it also requires that backslashes be used as pathname separators.
In addition to the locations explicitly specified, linkers usually search a list of toolset-dependent directories, which can often be configured using environment variables. On Windows, the list of directories typically includes the lib subdirectory of the toolset installation. As a result, if you copy .lib files to this directory, you can specify them by name on the command line without specifying a search location. If you combine this method with the technique described in Recipe 1.25, you can avoid passing the linker any information about a library.
The way the name of a library is specified to the linker differs between Unix and Windows. On Windows, the full name of the library is specified, including the file extension. On Unix—and on Windows when using the GCC toolset — libraries are specified using the -l option followed by the name of the library, with the file extension and the lib prefix removed. This means that the name of a library must begin with lib to be automatically found by the linker. More interestingly, it gives the linker the opportunity to choose between several versions of a library. If the linker finds both static and dynamic version of a library, the dynamic library is selected, unless otherwise specified. On some systems, the linker may choose between several versions of a dynamic library based on the portion of the file name following .so.
Finally, be aware that Unix linkers can be very sensitive to the order in which object files and static libraries are specified on the command line: if a static library or object file references a symbol defined in a second static library or object file, the first file must appear before the second file on the command line. To resolve circular dependencies, it is sometimes necessary to specify a given library or object file more than once. Another solution is to pass a sequence of object files and static libraries to linker bracketed by -( and -); this causes the file to be searched repeatedly until all references are resolved. This option should be avoided if possible because it can significantly degrade performance.
If your application uses a dynamic variant of your toolset’s runtime library, the runtime library must be available when your application is run and in a location where it will be found automatically by the operating system’s dynamic loader. Typically, this means that the dynamic runtime library must be placed either in the same directory as your application or in one of a list of system-specific directories. This is more of a concern when developing for Windows than when developing for Unix, since on Unix the appropriate runtime libraries are often already installed in the correct locations. The names of the dynamic runtime libraries distributed with the various toolsets are given in 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.