BUY THIS BOOK
Add to Cart

Print Book $44.95


Add to Cart

Print+PDF $58.44

Add to Cart

PDF $35.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £31.95

What is this?

Looking to Reprint or License this content?


C++ Cookbook
C++ Cookbook By Ryan Stephens, Christopher Diggins, Jonathan Turkanis, Jeff Cogswell
November 2005
Pages: 592

Cover | Table of Contents


Table of Contents

Chapter 1: Building C++ Applications
This chapter contains recipes for transforming C++ source code into executable programs and libraries. By working through these recipes, you'll learn about the basic tools used to build C++ applications, the various types of binary files involved in the build process, and the systems that have been developed to make building C++ applications manageable.
If you look at the titles of the recipes in this chapter, you might get the impression that I solve the same problems over and over again. You'd be right. That's because there are many ways to build C++ applications, and while I can't cover them all, I try to cover some of the most important methods. In the first dozen or so recipes, I show how to accomplish three fundamental tasks—building static libraries, building dynamic libraries, and building executables—using a variety of methods. The recipes are grouped by method: first, I look at building from the command line, then with the Boost build system (Boost.Build), and then with an Integrated Development Environment (IDE), and finally with GNU make.
Before you start reading recipes, be sure to read the following introductory sections. I'll explain some basic terminology, provide an overview of the command-line tools, build systems and IDEs covered in the chapter, and introduce the source code examples.
Even if you'll be using a build system or IDE, you should start by reading the recipes on building from the command line: these recipes introduce some essential concepts that you'll need to understand later in this chapter.
The three basic tools used to build C++ applications are the compiler, the linker, and the archiver (or librarian). A collection of these programs and possibly other tools is called a toolset.
The compiler takes C++ source files as input and produces object files , which contain a mixture of machine-executable code and symbolic references to functions and data. The archiver takes a collection of object files as input and produces a static library
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Introduction to Building
This chapter contains recipes for transforming C++ source code into executable programs and libraries. By working through these recipes, you'll learn about the basic tools used to build C++ applications, the various types of binary files involved in the build process, and the systems that have been developed to make building C++ applications manageable.
If you look at the titles of the recipes in this chapter, you might get the impression that I solve the same problems over and over again. You'd be right. That's because there are many ways to build C++ applications, and while I can't cover them all, I try to cover some of the most important methods. In the first dozen or so recipes, I show how to accomplish three fundamental tasks—building static libraries, building dynamic libraries, and building executables—using a variety of methods. The recipes are grouped by method: first, I look at building from the command line, then with the Boost build system (Boost.Build), and then with an Integrated Development Environment (IDE), and finally with GNU make.
Before you start reading recipes, be sure to read the following introductory sections. I'll explain some basic terminology, provide an overview of the command-line tools, build systems and IDEs covered in the chapter, and introduce the source code examples.
Even if you'll be using a build system or IDE, you should start by reading the recipes on building from the command line: these recipes introduce some essential concepts that you'll need to understand later in this chapter.
The three basic tools used to build C++ applications are the compiler, the linker, and the archiver (or librarian). A collection of these programs and possibly other tools is called a toolset.
The compiler takes C++ source files as input and produces object files , which contain a mixture of machine-executable code and symbolic references to functions and data. The archiver takes a collection of object files as input and produces a static library, or archive, which is simply a collection of object files grouped for convenient use. The linker takes a collection of object files and libraries and
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Obtaining and Installing GCC
You wish to obtain GCC, the free GNU C/C++ compiler.
The solution depends on your operating system.

Windows

Install MinGW, Cygwin, or both.
To install MinGW, go to the MinGW homepage, www.mingw.org, and follow the link to the MinGW download page. Download the latest version of the MinGW installation program, which should be named MinGW-<version>.exe.
Next, run the installation program. It will ask you to specify where you want to install MinGW. It may also ask you which packages you wish to install; at a minimum, you must install gcc-core, gcc-g++, binutils, and the MinGW runtime, but you may wish to install more. When the installation is complete, you will be able to run gcc, g++, ar, ranlib, dlltool, and several other GNU tools from the Windows command line. You may wish to add the bin subdirectory of your MinGW installation to your PATH environment variable so that you can specify these tools on the command line by their simple names rather than by their full pathnames.
To install Cygwin, go to the Cygwin homepage, www.cygwin.com, and follow the link InstallCygwin Now to download the Cygwin installation program. Next, run the installation program. It will ask you to make a series of choices, such as where Cygwin should be installed.
I'm explaining the Cygwin installation process in detail because it can be a bit complicated, depending on what you want to install. The process may have changed by the time you read this, but if it has, it will probably have been made easier.
The most important choice you must make is the selection of packages. If you have enough disk space and a high-speed Internet connection, I recommend that you install all of the packages. To do this, click once on the word Default next to the word All at the top of the hierarchical display of packages. After a possibly long pause, the word Default should change to Install.
If you are short on disk space, or if you have a slow Internet connection, you can choose a smaller selection of packages. To select just the development tools, click once on the word Default next to the word Devel. After a possibly long pause, the word Default
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Simple "Hello, World" Application from the Command Line
You want to build a simple "Hello, World" program, such as that in Example 1-4.
Example 1-4. A simple "Hello, World" program
hello.cpp

#include <iostream>

int main()
{
    std::cout << "Hello, World!\n";
}
Follow these steps:
  1. Set any environment variables required by your toolset.
  2. Enter a command telling your compiler to compile and link your program.
Scripts for setting environment variables are listed in Table 1-5; these scripts are located in the same directory as your command-line tools (Table 1-3). If your toolset does not appear in Table 1-5, you can skip the first step. Otherwise, run the appropriate script from the command line, if you are using Windows, or source the script, if you are using Unix.
Table 1-5: Scripts for setting environment variables required by your command-line tools
Toolset
Script
Visual C++
vcvars32.bat
Intel (Windows)
iclvars.bat
Intel (Linux)
iccvars.sh or iccvars.csh
Metrowerks (Mac OS X)
mwvars.sh or mwvars.csh
Metrowerks (Windows)
cwenv.bat
Comeau
Same as the backend toolset
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Static Library from the Command Line
You wish to use your command-line tools to build a static library from a collection of C++ source files, such as those listed in Example 1-1.
First, use your compiler to compile the source files into object files. If your source files include headers located in other directories, you may need to use the -I option to instruct your compiler where to search for headers; for more information, see Recipe 1.5. Second, use your archiver to combine the object files into a static library.
To compile each of the three source files from Example 1-1, use the command lines listed in Table 1-8, modifying the names of the input and output files as needed. To combine the resulting object files into a static library, use the commands listed in Table 1-10.
Table 1-10: Commands for creating the archive libjohnpaul.lib or libjohnpaul.a
Toolset
Command line
GCC (Unix)Intel (Linux)Comeau (Unix)
ar ru libjohnpaul.a john.o paul.o johnpaul.oranlib libjohnpaul.a
GCC (Windows)
ar ru libjohnpaul.a john.o paul.o johnpaul.o
Visual C++Comeau (with Visual C++)
lib -nologo -out:libjohnpaul.lib john.obj paul.obj johnpaul.obj
Intel (Windows)
xilib -nologo /out:libjohnpaul.lib john.obj paul.obj johnpaul.obj
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Dynamic Library from the Command Line
You wish to use your command-line tools to build a dynamic library from a collection of C++ source files, such as those listed in Example 1-2.
Follow these steps:
  1. Use your compiler to compile the source files into object files. If you're using Windows, use the -D option to define any macros necessary to ensure that your dynamic library's symbols will be exported. For example, to build the dynamic library in Example 1-2, you need to define the macro GEORGERINGO_DLL. If you're building a third-party library, the installation instructions should tell you what macros to define.
  2. Use your linker to create a dynamic library from the object files created in step 1.
If your dynamic library depends on other libraries, you'll need to tell the compiler where to search for the library headers, and to tell the linker the names of the other libraries and where to find them. This is discussed in detail in Recipe 1.5.
The basic commands for performing the first step are given Table 1-8; you'll need to modify the names of the input and output files appropriately. The commands for performing the second step are given in Table 1-11. If you're using a toolset that comes with static and dynamic variants of its runtime libraries, direct the compiler and linker to use a dynamically linked runtime, as described in Recipe 1.23.
Table 1-11: Commands for creating the dynamic library libgeorgeringo.so, libgeorgeringo.dll, or libgeorgeringo.dylib
Toolset
Command line
GCC
g++ -shared -fPIC -o libgeorgeringo.so george.o ringo.o georgeringo.o
GCC (Mac OS X)
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Complex Application from the Command Line
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.
Table 1-12: Specifying directories to search for headers
Toolset
Option
All
-I<directory>
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
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Installing Boost.Build
You want to obtain and install Boost.Build.
Consult the Boost.Build documentation at www.boost.org/boost-build2 or follow these steps:
  1. Go to the Boost homepage, www.boost.org, and follow the Download link to Boost's SourceForge download area.
  2. Download and unpack either the latest release of the package boost or the latest release of the package boost-build. The former includes the full collection of Boost libraries, while the latter is a standalone release of Boost.Build. Place the unpacked files in a suitable permanent location.
  3. Download and unpack the latest version of the package boost-jam for your platform; this package includes a prebuilt bjam executable. If the package boost-jam is not available for your platform, follow the instructions provided with the package you downloaded in step 2 to build the executable from the source.
  4. Copy bjam to a location in your PATH environment variable.
  5. Permanently set the environment variable BOOST_BUILD_PATH to the Boost. Build root directory. If you downloaded the package boost in step 1, the root directory is the subdirectory tools/build/v2 of your Boost installation; otherwise, it is the directory boost-build.
  6. Configure Boost.Build for your toolsets and libraries by editing the configuration file user-config.jam, located in the Boost.Build root directory. The file user-config.jam contains comments explaining how to do this.
The most difficult part of using Boost.Build is downloading and installing it. Eventually Boost may provide a graphical installation utility, but for the time being, you must follow the above steps.
The purpose of step five is to help the build tool, bjam, find the root directory of the build system. This step is not strictly necessary, however, since there is another way to accomplish the same thing: simply create a file called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Simple "Hello, World" Application Using Boost.Build
You want to use Boost.Build to build a simple "Hello, World" program, such as the one in Example 1-4.
Create a text file named Jamroot in the directory where you wish the executable and any accompanying intermediate files to be created. In the file Jamroot, invoke two rules, as follows. First, invoke the exe rule to declare an executable target, specifying your .cpp file as a source. Next, invoke the install rule, specifying the executable target name and the location where you want the install directory. Finally, run bjam to build your program.
For example, to build an executable hello or hello.exe from the file hello.cpp in Example 1-1, create a file named Jamroot with the following content in the directory containing hello.cpp, as shown in Example 1-8.
Example 1-8. Jamfile for project hello
# jamfile for project hello

exe hello : hello.cpp ;

install dist : hello : <location>. ;
Next, change to the directory containing hello.cpp and Jamroot and enter the following command:
> bjam hello
This command builds the executable hello or hello.exe in a subdirectory of the current directory. Finally, enter the command:
> bjam dist
This command copies the executable to the directory specified by the location property, which in this case is the current directory.
As this book goes to press, the Boost.Build developers are preparing for the official release of Boost.Build version 2. By the time you read this, Version 2 will probably already have been released; if not, you can enable the behavior described in this chapter by passing the command-line option —v2 to bjam. For example, instead of entering bjam hello, enter bjam --v2 hello.
The file Jamroot is an example of a Jamfile. While a small collection of C++ source files might be managed using a single Jamfile, a large codebase will typically require many Jamfiles, organized hierarchically. Each Jamfile resides in a separate directory and corresponds to a separate
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Static Library Using Boost.Build
You want to use Boost.Build to build a static library from a collection of C++ source files, such as those listed in Example 1-1.
Create a Jamroot file in the directory where you wish the static library to be created. In the file Jamroot, invoke the lib rule to declare a library target, specifying your .cpp files as sources and the property <link>static as a requirement. Add a usage requirement of the form <include>path to specify the library's include directory, i.e., the directory with respect to which include directives for library headers should be resolved. You may need to add one or more requirements of the form <include>path to tell the compiler where to search for included headers. Finally, run bjam from the directory containing Jamroot, as described in Recipe 1.7.
For example, to build a static library from the source files listed in Example 1-1, your Jamroot might look like Example 1-11.
Example 1-11. A Jamfile to build the static library libjohnpaul.lib or libjohnpaul.a
# Jamfile for project libjohnpaul

lib libjohnpaul
    : # sources
      john.cpp paul.cpp johnpaul.cpp
    : # requirements 
      <link>static
    : # default-build
    : # usage-requirements
      <include>..
    ;
To build the library, enter:
> bjam libjohnpaul
The lib rule is used to declare a target representing a static or dynamic library. It takes the same form as the exe rule, as illustrated in Example 1-9. The usage requirement <include>.. frees projects that depend on your library from having to explicitly specify your library's include directory in their requirements. The requirement <link>static specifies that your target should always be built as a static library. If you want the freedom to build a library target either as static or as dynamic, you can omit the requirement <link>static. Whether the library is built as static or dynamic can then be specified on the command line, or in the requirements of a target that depends on the library target. For example, if the requirement
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Dynamic Library Using Boost.Build
You wish to use Boost.Build to build a dynamic library from a collection of C++ source files, such as those listed in Example 1-2.
Create a Jamroot file in the directory where you wish the dynamic library—and the import library, if any—to be created. In the file Jamroot, invoke the lib rule to declare a library target, specifying your .cpp files as sources and the properties <link>shared as a requirement. Add a usage requirement of the form <include>path to specify the library's include directory, i.e., the directory with respect to which include directives for library headers should be resolved. If your source files include headers from other libraries, you may need to add several requirements of the form <include>path to tell the compiler where to search for included headers. You may also need to add one or more requirements of the form <define>symbol to ensure that your dynamic library's symbols will be exported using _ _declspec(dllexport) on Windows. Finally, run bjam from the directory containing Jamroot, as described in Recipe 1.7.
For example, to build a dynamic library from the source files listed in Example 1-2, create a file named Jamroot in the directory georgeringo, as shown in Example 1-12.
Example 1-12. A Jamfile to build the dynamic library georgeringo.so, georgeringo.dll, or georgeringo.dylib
# Jamfile for project georgringo

lib libgeorgeringo
    : # sources
      george.cpp ringo.cpp georgeringo.cpp
    : # requirements
      <link>shared
      <define>GEORGERINGO_DLL
    : # default-build
    : # usage-requirements
      <include>..
    ;
To build the library, enter:
> bjam libgeorgeringo
As discussed in Recipe 1.8, the lib rule is used to declare a target representing a static or dynamic library. The usage requirement <include>.. frees projects which depend on your library from having to explicitly specify your library's include directory in their requirements. The requirement
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Complex application Using Boost.Build
You wish to use Boost.Build to build an executable that depends on several static and dynamic libraries.
Follow these steps:
  1. For each library on which the executable depends—unless it is distributed as a prebuilt binary—create a Jamfile as described in Recipe 1.8 and Recipe 1.9.
  2. Create a Jamroot file in the directory where you want the executable to be created.
  3. In the file Jamroot, invoke the exe rule to declare an executable target. Specify your .cpp files and the library targets on which the executable depends as sources. Also, add properties of the form <include>path as sources, if necessary, to tell the compiler where to search for library headers.
  4. In the file Jamroot, invoke the install rule, specifying the properties <install-dependencies>on, <install-type>EXE, and <install-type>SHARED_LIB as requirements.
  5. Run bjam from the directory containing Jamroot as described in Recipe 1.7.
For example, to build an executable from the source files listed in Example 1-3, create a file named Jamroot in the directory hellobeatles as shown in Example 1-13.
Example 1-13. A Jamfile to build the executable hellobeatles.exe or hellobeatles
# Jamfile for project hellobeatles

exe hellobeatles
    : # sources
      ../johnpaul//libjohnpaul
      ../georgeringo//libgeorgeringo
      hellobeatles.cpp
    ;

install dist 
    : # sources
      hellobeatles
    : # requirements
      <install-dependencies>on
      <install-type>EXE
      <install-type>SHARED_LIB
      <location>.
    ;
Now enter:
> bjam hellobeatles
from the directory hellobeatles. This first builds the two projects on which the target hellobeatles depends, and then builds the target hellobeatles. Finally, enter:
> bjam dist
This copies the executable hellobeatles and the dynamic library
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Static Library with an IDE
You wish to use your IDE to build a static library from a collection of C++ source files, such as those listed in Example 1-1.
The basic outline is as follows:
  1. Create a new project and specify that you wish to build a static library rather than an executable or a dynamic library.
  2. Choose a build configuration (e.g., debug versus release, single-threaded versus multithreaded).
  3. Specify the name of your library and the directory in which it should be created.
  4. Add your source files to the project.
  5. If necessary, specify one or more directories where the compiler should search for included headers. See Recipe 1.13.
  6. Build the project.
The steps in this outline vary somewhat depending on the IDE; for example, with some IDEs, several steps are combined into one or the ordering of the steps is different. The second step is covered in detail in Recipe 1.21, Recipe 1.22, and Recipe 1.23. For now, you should use default settings as much as possible.
For example, here's how to build a static library from the source code in Example 1-1 using the Visual C++ IDE.
Select New Project from the File menu, select Visual C++ in the left pane, select Win32 Console Application, and enter libjohnpaul as your project's name. From the Win32 Application Wizard go to Application Settings, select Static library, uncheck Precompiled header, and press Finish. You should now have an empty project with two build configurations, Debug and Release, the former being the active configuration.
Next, display your project's property pages by right-clicking on the project's name in the Solution Explorer and selecting Properties. Go to Configuration Properties Librarian General and enter the pathname of your project's output file in the field labeled Output File. The directory portion of the pathname should point to the directory
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Dynamic Library with an IDE
You wish to use your IDE to build a dynamic library from a collection of C++ source files, such as those listed in Example 1-2.
The basic outline is as follows:
  1. Create a new project and specify that you wish to build a dynamic library rather than static library or an executable.
  2. Choose a build configuration (e.g., debug versus release, single-threaded versus multithreaded).
  3. Specify the name of your library and the directory where it should be created.
  4. Add your source files to the project.
  5. On Windows, define any macros necessary to ensure that your dynamic library's symbols will be exported using _ _declspec(dllexport).
  6. If necessary, specify one or more directories where the compiler should search for included headers. See Recipe 1.13.
  7. Build the project.
As with Recipe 1.11, the steps in this outline vary somewhat depending on the IDE. The second step is covered in detail in Recipe 1.21, Recipe 1.22, and Recipe 1.23. For now, you should use default settings wherever possible.
For example, here's how to build a dynamic library from the source code in Example 1-2 using the Visual C++ IDE.
Select New Project from the File menu, select Visual C++ in the left pane, select Win32 Console Application and enter libgeorgeringo as your project's name. From the Win32 Application Wizard go to Application Settings, select DLL and Empty Project, and press Finish. You should now have an empty project with two build configurations, Debug and Release, the former being the active configuration.
Next, display your project's property pages by right-clicking on the project's name in the Solution Explorer and selecting Properties. Go to Configuration Properties Linker General and enter the pathname of your project's output file in the field labeled Output File. The directory portion of the pathname should point to the directory binaries which you created at the beginning of this chapter; the file name portion should be
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Complex Application with an IDE
You wish to use your IDE to build an executable that depends on several static and dynamic libraries.
The basic outline is as follows:
  1. If you are building the dependent libraries from the source, and they don't come with their own IDE projects or makefiles, create projects for them, as described in Recipe 1.11 and Recipe 1.12.
  2. Create a new project and specify that you wish to build an executable rather than a library.
  3. Choose a build configuration (e.g., debug versus release, single-threaded versus multithreaded).
  4. Specify the name of your executable and the directory in which it should be created.
  5. Add your source files to the project.
  6. Tell the compiler where to find the headers for the dependent libraries.
  7. Tell the linker what libraries to use and where to find them.
  8. If your IDE supports project groups, add all the projects mentioned above to a single project group and specify the dependency relationships between them.
  9. If your IDE supports project groups, build the project group from step 8. Otherwise, build the projects individually, taking care to build each project before the projects that depend on it.
As with Recipe 1.11 and Recipe 1.12, the steps in this outline vary somewhat depending on the IDE. The third step is covered in detail in Recipes Recipe 1.21, Recipe 1.22, and Recipe 1.23. For now, you should use the default settings wherever possible.
For example, here's how to build an executable from the source code in Example 1-3 using the Visual C++ IDE.
Select New Project from the File menu, select Visual C++ in the left pane, select Win32 Console Application and enter hellobeatles as your project's name. From the Win32 Application Wizard go to Application Settings, select Console Application
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Obtaining GNU make
You want to obtain and install the GNU make utility, useful for building libraries and executables from source code.
The solution depends on your operating system.

Windows

While you can obtain prebuilt binaries for GNU make from several locations, to get the most out of GNU make it should be installed as part of a Unix-like environment. I recommend using either Cygwin or MSYS, which is a part of the MinGW project.
Cygwin and MinGW are described in Recipe 1.1.
If you installed Cygwin, as described in Recipe 1.1, you already have GNU make. To run it from the Cygwin shell, simply run the command make.
To install MSYS, begin by installing MinGW, as described in Recipe Recipe 1.1. A future version of the MinGW installer may give you the option of installing MSYS automatically. For now, follow these additional steps.
First, from the MinGW homepage, http://www.mingw.org, go to the MinGW download area and download the latest stable version of the MSYS installation program. The name of the installation program should be MSYS-<version>.exe.
Next, run the installation program. You will be asked to specify the location of your MinGW installation and the location where MSYS should be installed. When the installation program completes, the MSYS installation directory should contain a file named msys.bat. Running this script will display the MSYS shell, a port of the bash shell from which you can run GNU make and other mingw programs such as g++, ar, ranlib, and dlltool.
To use MSYS it is not necessary for the bin subdirectories of either your MinGW installation or your MSYS installation to be in your PATH environment variable.

Unix

First, check whether GNU make is installed on your system by running make -v from the command line. If GNU make is installed, it should print a message like the following:
GNU Make 3.80 
Copyright (C) 2002  Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
...
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building A Simple "Hello, World" Application with GNU make
You want to use GNU make to build a simple "Hello, World" program, such as that in Example 1-4.
Before you write your first makefile, you'll need to know a little terminology. A makefile consists of a collection of rules of the form
targets: prerequisitescommand-script
Here targets and prerequisites are space-separated strings, and command-script consists of zero or more lines of text, each of which begins with a Tab character. Targets and prerequisites are usually files names, but sometimes they are simply formal names for actions for make to perform. The command script consists of a sequence of commands to be passed to a shell. Roughly speaking, a rule tells make to generate the collection of targets from the collection of prerequisites by executing the command script.
Whitespace in makefiles is significant. Lines containing command scripts must begin with a Tab rather than a Space — this is a source of some of the most common beginner errors. In the following examples, lines which begin with a Tab are indicated by an indentation of four characters.
Now you're ready to begin. Create a text file named makefile in the directory containing your source file. In this file, declare four targets. Call the first target all, and specify the name of the executable you wish to build as its sole prerequisite. It should have no command script. Give the second target the same name as your executable. Specify your application's source file as its prerequisite, and specify the command line needed to build the executable from the source file as your target's command script. The third target should be called install. It should have no prerequisites, and should have a command script to copy the executable from the directory containing the makefile to the directory where you want it installed. The last target should be called clean. Like install, it should have no prerequisites. Its command script should remove the executable and the intermediate object file from the current directory. The
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Static Library with GNU Make
You want to use GNU make to build a static library from a collection of C++ source files, such as those listed in Example 1-1.
First, create a makefile in the directory where you want your static library to be created, and declare a phony target all whose single prerequisite is the static library. Next, declare your static library target. Its prerequisites should be the object files that the library will contain, and its command script should be a command line to build the library from the collection of object files, as demonstrated in Recipe 1.3. If you are using GCC or a compiler with similar command-line syntax, customize the implicit patterns rules, if necessary, by modifying one or more of the variables CXX, CXXFLAGS, etc. used in make's database of implicit rules, as shown in Recipe 1.15. Otherwise, write a pattern rule telling make how to compile .cpp files into object files, using the command lines from Table 1-4 and the pattern rule syntax explained in Recipe 1.16. Next, declare targets indicating how each of your library's source files depends on the headers it includes, directly or indirectly. You can write these dependencies by hand or arrange for them to be generated automatically. Finally, add install and clean targets as demonstrated in Recipe 1.15.
For example, to build a static library from the source files listed in Example 1-2 using GCC on Unix, create a makefile in the directory johnpaul, as shown in Example 1-20.
Example 1-20. Makefile for libjohnpaul.a using GCC on Unix
# Specify extensions of files to delete when cleaning
CLEANEXTS   = o a 

# Specify the target file and the install directory
OUTPUTFILE  = libjohnpaul.a
INSTALLDIR  = ../binaries

# Default target
.PHONY: all
all: $(OUTPUTFILE)

# Build libjohnpaul.a from john.o, paul.o, and johnpaul.o
$(OUTPUTFILE): john.o paul.o johnpaul.o
    ar ru $@ $^
    ranlib $@

# No rule to build john.o, paul.o, and johnpaul.o from .cpp 
# files is required; this is handled by make's database of
# implicit rules

.PHONY: install
install:
    mkdir -p $(INSTALLDIR)
    cp -p $(OUTPUTFILE) $(INSTALLDIR)

.PHONY: clean 
clean:
    for file in $(CLEANEXTS); do rm -f *.$$file; done

# Indicate dependencies of .ccp files on .hpp files
john.o: john.hpp
paul.o: paul.hpp
johnpaul.o: john.hpp paul.hpp johnpaul.hpp
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Dynamic Library with GNU Make
You wish to use GNU make to build a dynamic library from a collection of C++ source files, such as those listed in Example 1-2.
First, create a makefile in the directory where you want your dynamic library to be created, and declare a phony target all whose single prerequisite is the dynamic library. Next, declare your dynamic library target. Its prerequisites should be the object files from which the library will be built, and its command script should be a command line to build the library from the collection of object files, as demonstrated in Recipe 1.4. If you are using GCC or a compiler with similar command-line syntax, customize the implicit patterns rules, if necessary, by modifying one or more of the variables CXX, CXXFLAGS, etc. used in make's database of implicit rules, as shown in Recipe 1.15. Otherwise, write a pattern rule telling make how to compile .cpp files into object files, using the command lines from Table 1-4 and the pattern rule syntax explained in Recipe 1.16. Finally, add install and clean targets, as demonstrated in Recipe 1.15, and machinery to automatically generate source file dependencies, as demonstrated in Recipe 1.16.
For example, to build a dynamic library from the source files listed Example 1-2 using GCC on Unix, create a makefile in the directory georgeringo, as shown in Example 1-22.
Example 1-22. Makefile for libgeorgeringo.so using GCC
# Specify extensions of files to delete when cleaning
CLEANEXTS   = o so

# Specify the source files, the target files, 
# and the install directory 
SOURCES     = george.cpp ringo.cpp georgeringo.cpp
OUTPUTFILE  = libgeorgeringo.so
INSTALLDIR  = ../binaries

.PHONY: all
all: $(OUTPUTFILE)

# Build libgeorgeringo.so from george.o, ringo.o, 
# and georgeringo.o; subst is the search-and-replace 
# function demonstrated in Recipe 1.16
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES)) 
    $(CXX) -shared -fPIC $(LDFLAGS) -o $@ $^

.PHONY: install
install:
    mkdir -p $(INSTALLDIR)
    cp -p $(OUTPUTFILE) $(INSTALLDIR)

.PHONY: clean 
clean:
    for file in $(CLEANEXTS); do rm -f *.$$file; done

# Generate dependencies of .ccp files on .hpp files
include $(subst .cpp,.d,$(SOURCES))

%.d: %.cpp
    $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
    sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building a Complex Application with GNU make
You wish to use GNU make to build an executable which depends on several static and dynamic libraries.
Follow these steps:
  1. Create makefiles for the libraries used by your application, as described in Recipe 1.16 and Recipe 1.17. These makefiles should reside in separate directories.
  2. Create a makefile in yet another directory. This makefile can be used to build your application, but only after the makefiles in step 1 have been executed. Give this makefile a phony target all whose prerequisite is your executable. Declare a target for your executable with prerequisites consisting of the libraries which your application uses, together with the object files to be built from your application's .cpp files. Write a command script to build the executable from the collection libraries and object files, as described in Recipe 1.5. If necessary, write a pattern rule to generate object files from .cpp files, as shown in Recipe 1.16. Add install and clean targets, as shown in Recipe 1.15, and machinery to automatically generate source file dependencies, as shown in Recipe 1.16.
  3. Create a makefile in a directory which is an ancestor of the directories containing all the other makefiles — let's call the new makefile the top-level makefile and the others the subordinate makefiles. Declare a default target all whose prerequisite is the directory containing the makefile created in step 2. Declare a rule whose targets consists of the directories containing the subordinate makefiles, and whose command script invokes make in each target directory with a target specified as the value of the variable TARGET. Finally, declare targets specifying the dependencies between the default targets of the subordinate makefiles.
For example, to build an executable from the source files listed in Example 1-3 using GCC on Unix, create a makefile as shown in Example 1-23.
Example 1-23. Makefile for hellobeatles.exe using GCC
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Defining a Macro
You want to define the preprocessor symbol name, assigning it either an unspecified value or the value value.
The compiler options for defining a macro from the command line are shown in Table 1-16. Instructions for defining a macro from your IDE are given in Table 1-17. To define a macro using Boost.Build, simply add a property of the form <define>name[=value] to your target's requirements, as shown in Table 1-15 and Example 1-12.
Table 1-16: Defining a macro from the command line
Toolset
Option
All
-D name [= value ]
Table 1-17: Defining a macro from your IDE
IDE
Configuration
Visual C++
From your project's property pages, go to Configuration Properties C/C++ Preprocessor and enter name[=value] under Preprocessor Definitions, using semicolons to separate multiple entries.
CodeWarrior
From the Target Settings Window, go to Language Settings C/C++ Preprocessor and enter:
                    #define 
                    name[
                    =
                    value]
                  
in the area labeled Prefix Text.
C++Builder
From Project Options, go to Directories/Conditionals and enter name[=value] under Preprocessor Definitions, using semicolons to separate multiple entries.
</