Building a Complex Application from the Command Line
Problem
You wish to use your command-line tools to build an executable that depends on several static and dynamic libraries.
Solution
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.
Toolset |
Option |
---|---|
All |
-I |
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.
|
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 ..johnpaullibjohnpaul.lib ..georgeringolibgeorgeringo.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 FilesMicrosoft Visual Studio .NET 2003VCin 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
Discussion
Searching for included headers
The -I option is used to specify an include path. When a compileractually the preprocessorencounters 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
except that compilers generally don't interpret the given pathname relative to the location of the source file being processed.
Passing libraries to the linker
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 for this purpose, but Visual C++ and Intel for Windows use -lipath: and Metrowerks uses -search -L. 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 Unixand 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.
Running your application
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.
See Also
Recipe 1.10, Recipe 1.13, Recipe 1.18, and Recipe 1.23