C++ User's Guide

Chapter 2 Using the C++ Compiler

This chapter describes how to use the C++ compiler.

The principal use of any compiler is to transform a program written in a high-level language like C++ into a data file that is executable by the target computer hardware. You can use the C++ compiler to:

Getting Started

This section gives you a brief overview of how to use the C++ compiler to compile and run C++ programs. See Chapter 3, C++ Compiler Options for a full reference to command-line options.


Note -

The command-line examples in this chapter show CC usages. Printed output might be slightly different.


The basic steps for building and running a C++ program involve:

The following program displays a message on the screen:


demo% cat greetings.cc
	#include <iostream>
    int main()  {
      std::cout << "Real programmers write C++!" << std::endl;
      return 0;
    }
demo% CC greetings.cc
demo% a.out    
 Real programmers write C++!
demo%

In this example, CC compiles the source file greetings.cc and, by default, compiles the executable program onto the file, a.out. To launch the program, type the name of the executable file, a.out, at the command prompt.

Traditionally, UNIX compilers name the executable file a.out. It can be awkward to have each compilation write to the same file. Moreover, if such a file already exists, it will be overwritten the next time you run the compiler. Instead, use the -o compiler option to specify the name of the executable output file, as in the following example:


demo% CC -o greetings greetings.C

In this example, the -o option tells the compiler to write the executable code to the file greetings. (It is common to give a program consisting of a single source file the name of the source file without the suffix.)

Alternatively, you could rename the default a.out file using the mv command after each compilation. Either way, run the program by typing the name of the executable file:


demo% greetings 
Real programmers write C++!
demo%

Invoking the Compiler

The remainder of this chapter discuss the conventions used by the CC command, compiler source line directives, and other issues concerning the use of the compiler.

Command Syntax

The general syntax of a compiler command line is as follows:


CC 
[options]
[source-files
] [object-files
] [libraries]

An option is an option keyword prefixed by either a dash (-) or a plus sign (+). Some options take arguments.

In general, the processing of the compiler options is from left to right, allowing selective overriding of macro options (options that include other options). However, note the following exceptions:

Source files, object files, and libraries are compiled and linked in the order in which they appear on the command line.

In the following example, CC is used to compile two source files (growth.C and fft.C) to produce an executable file named growth with runtime debugging enabled:


demo% CC -g -o growth growth.C fft.C

File Name Conventions

The suffix attached to a file name appearing on the command line determines how the compiler processes the file. A file name with a suffix other than those listed in the following table, or without a suffix, is passed to the linker.

Table 2-1 File Name Suffixes Recognized by the C++ Compiler

Suffix  

Language 

Action  

.c

C++ 

Compile as C++ source files, put object files in current directory; default name of object file is that of the source but with an .o suffix.

.C

C++ 

Same action as .c suffix.

.cc

C++ 

Same action as .c suffix.

.cpp

C++ 

Same action as .c suffix.

.cxx

C++ 

Same action as .c suffix.

.i

C++ 

Preprocessor output file treated as C++ source file. Same acton as .C suffix.

.s

Assembler  

Assemble source files with the assembler.  

.S

Assembler 

Assemble source files with both the C language preprocessor and the assembler. 

.il

Inline expansion 

Process assembly inline-template files for inline expansion. The compiler will use templates to expand inline calls to selected routines. (Inline-template files are special assembler files. See the inline(1) man page.)

.o

Object files  

Pass object files through to the linker. 

.a

Static (archive) library 

Pass object library names to the linker. 

.so

.so.n

Dynamic (shared) library 

Pass names of shared objects to the linker. 

Using Multiple Source Files

The C++ compiler accepts multiple source files on the command line. A single source file compiled by the compiler, together with any files that it directly or indirectly supports, is referred to as a compilation unit. C++ treats each source as a separate compilation unit. A single source file can contain any number of procedures (main program, function, module, and so on). There are advantages to organizing an application with one procedure per file, as there are for gathering procedures that work together into a single file. Some of these are described in C++ Programming Guide.

Compiling and Linking

This section describes some aspects of compiling and linking programs. In the following example, CC is used to compile three source files and to link the object files to produce an executable file named prgrm.


demo% CC file1.cc file2.cc file3.cc -o prgrm

Compile-Link Sequence

In the previous example, the compiler automatically generates the loader object files (file1.o, file2.o and file3.o) and then invokes the system linker to create the executable program for the file prgrm.

After compilation, the object files (file1.o, file2.o,and file3.o) remain. This convention permits you to easily relink and recompile your files.


Note -

If only one source file is compiled and a program is linked in the same operation, the corresponding .o file is deleted automatically. To preserve all .o files, do not compile and link in the same operation unless more than one source file gets compiled.


If the compilation fails, you will receive a message for each error. No .o files are generated for those source files with errors, and no executable program is written.

Separate Compiling and Linking

You can compile and link in separate steps. The -c option compiles source files and generates .o object files, but does not create an executable. Without the -c option, the compiler invokes the linker. By splitting the compile and link steps, a complete recompilation is not needed just to fix one file. The following example shows how to compile one file and link with others in separate steps:


demo% CC  -c file1.cc                        Make new object file
demo% CC  -o prgrm file1.o file2.o file3.o       Make executable file

Be sure that the link step lists all the object files needed to make the complete program. If any object files are missing from this step, the link will fail with "undefined external reference" errors (missing routines).

Consistent Compiling and Linking

If you do compile and link in separate steps, consistent compiling and linking is critical when using the following compiler options:

If you compile any subprogram with any of these options, be sure to link with the same option as well:

In the following example, the programs are compiled using the -xcg92 compiler option. This option is a macro for -xtarget=ss1000 and expands to: -xarch=v8 -xchip=super -xcache=16/64/4:1024/64/1

If the program uses templates, it is possible that some templates will get instantiated at link time. In that case the command line options from last line (the link line) will be used to compile the instantiated templates.


 demo% CC -c -xcg92 sbr.cc
 demo% CC -c -xcg92 smain.cc
 demo% CC -xcg92 sbr.o smain.o

Compiling for SPARC V9

You can create both 32-bit and 64-bit binaries using the C++ 5.0 compiler.

Compilation, linking, and execution of 64-bit objects can take place only in a V9 SPARC, Solaris 7 environment with a 64-bit kernel running. Compilation for 64-bit Solaris 7 is indicated by the -xarch=v9 and -xarch=v9a options.

Diagnosing the Compiler

You can use the -verbose option to display helpful information while compiling a program. See Chapter 3, C++ Compiler Options for more information.

Any arguments on the command line that the compiler does not recognize are interpreted as linker options, object program file names, or library names.

The basic distinctions are:

In the following example, note that -bit is not recognized by CC and the option is passed on to the linker (ld), which tries to interpret it. Because single letter ld options can be strung together, the linker sees -bit as -b -i -t, all of which are legitimate ld options. This might not be what you intend or expect:


demo% CC -bit move.cc           <- 
 -bit is not a recognized 
CC option

CC: Warning: Option -bit passed to ld, if ld is invoked, ignored otherwise

In the next example, the user intended to type the CC option -fast but omitted the leading dash. The compiler again passes the argument to the linker, which in turn interprets it as a file name:


demo% CC fast move.cc           <-   The user meant to type 
-fast
move.C:
ld: fatal: file fast: cannot open file; errno=2
ld: fatal: File processing errors.  No output written to a.out

Understanding the Compiler Organization

The C++ compiler package consists of a front end, optimizer, code generator, assembler, template pre-linker, and link editor. The CC command invokes each of these components automatically unless you use command-line options to specify otherwise.

Because any of these components may generate an error, and the components perform different tasks, it may be helpful to identify the component that generates an error.

Figure 2-1 The Compilation Process

Graphic

As shown in the following table, input files to the various compiler components have different file name suffixes. The suffix establishes the kind of compilation that is done. Refer to Table 2-1 for the meanings of the file suffixes.

Table 2-2 Components of the C++ Compilation System

Component 

Description 

Notes on Use 

ccfe

Front end (Compiler preprocessor and compiler) 

 
iropt

Code optimizer 

(SPARC) -xO[2-5], -fast

xcg386

Intermediate language translator 

(x86) Always invoked

inline

Inline expansion of assembly language templates 

(SPARC).il file specified

mwinline

Automatic inline expansion of functions 

(x86) -xO4, -xinline

fbe

Assembler 

 

cg

Code generator, inliner, assembler 

(SPARC)

codegen

Code generator 

(x86)

CClink

Template pre-linker 

 

ld

Non-incremental link editor 

 

ild

Incremental link editor 

-g, -xildon

Memory Requirements

The amount of memory a compilation requires depends on several parameters, including:

On the SPARC platform, if the optimizer runs out of memory, it tries to recover by retrying the current procedure at a lower level of optimization. The optimizer then resumes subsequent routines at the original level specified in the -xOlevel option on the command line.

If you compile a single source file that contains many routines, the compiler might run out of memory or swap space. If the compiler runs out of memory, try reducing the level of optimization. Alternately, split multiple-routine source files into files with one routine per file, using fsplit(1).

Swap Space Size

The swap -s command displays available swap space. See the swap(1M) man page for more information.

The following example demonstrates the use of the swap command:


demo% swap -s 
total: 40236k bytes allocated + 7280k reserved = 47516k used, 1058708k available

Increasing Swap Space

Use mkfile(1M) and swap (1M) to increase the size of the swap space on a workstation. (You must become superuser to do this.) The mkfile command creates a file of a specific size, and swap -a adds the file to the system swap space:


 demo# mkfile -v 90m /home/swapfile 
 /home/swapfile 94317840 bytes 
 demo# /usr/sbin/swap -a  /home/swapfile

Control of Virtual Memory

Compiling very large routines (thousands of lines of code in a single procedure) at -xO3 or higher can require an unreasonable amount of memory. In such cases, performance of the system might degrade. You can control this by limiting the amount of virtual memory available to a single process.

To limit virtual memory in a sh shell, use the ulimit command. See the sh(1) man page for more information.

The following example shows how to limit virtual memory to 16 Mbytes:


 demo$ ulimit -d 16000

In a csh shell, use the limit command to limit virtual memory. See the csh(1)man page for more information.

The next example also shows how to limit virtual memory to 16 Mbytes:


 demo% limit datasize 16M

Each of these examples causes the optimizer to try to recover at 16 Mbytes of data space.

The limit on virtual memory cannot be greater than the system's total available swap space and, in practice, must be small enough to permit normal use of the system while a large compilation is in progress.

Be sure that no compilation consumes more than half the swap space.

With 32 Mbytes of swap space, use the following commands:

In a sh shell:


demo$ ulimit -d 16000

In a csh shell:


demo% limit datasize 16M

The best setting depends on the degree of optimization requested and the amount of real memory and virtual memory available.

Memory Requirements

A workstation should have at least 24 megabytes of memory; 32 megabytes are recommended.

To determine the actual real memory, use the following command:


demo% /usr/sbin/dmesg | grep mem 
mem = 655360K (0x28000000)
avail mem = 602476544

Simplifying Commands

You can simplify complicated compiler commands by defining special shell aliases, using the CCFLAGS environment variable, or by using make.

Using Aliases Within the C Shell

The following example defines an alias for a command with frequently used options.


demo% alias CCfx "CC -fast -xnolibmil"

The next example uses the alias CCfx.


demo% CCfx any.C

The command CCfx is now the same as:


demo% CC -fast -xnolibmil any.C

Using CCFLAGS to Specify Compile Options

You can specify options by setting the CCFLAGS variable.

The CCFLAGS variable can be used explicitly in the command line. The following example shows how to set CCFLAGS (C Shell):


 demo% setenv CCFLAGS '-silent -fast -Xlist'

The next example uses CCFLAGS explicitly.


 demo% CC $CCFLAGS any.cc

When you use make, if the CCFLAGS variable is set as in the preceding example and the makefile's compilation rules are implicit, then invoking make will result in a compilation equivalent to:

CC -silent -fast -Xlist files...

Using make

make is a very powerful program development tool that you can easily use with all Sun compilers. See the make(1) man page for additional information.

Using CCFLAGS Within make

When you are using the implicit compilation rules of the makefile (that is, there is no C++ compile line), CCFLAGS is used automatically by the make program.

Adding a Suffix to Your Makefile

You can incorporate different file suffixes into C++ by adding them to your makefile. The following example adds .C as a valid suffix for C++ files.Add the SUFFIXES macro to your makefile:

.SUFFIXES: .cpp .cpp~

(This line can be located anywhere in the makefile.)

Add the following lines to your makefile. Indented lines must start with a tab.


.cpp:
    $(LINK.cc) -o $@ $< $(LDLIBS)
.cpp~:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(LINK.cc) -o $@ $*.cpp $(LDLIBS)
.cpp.o:
    $(COMPILE.cc) $(OUTPUT_OPTION) $<
.cpp~.o:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(COMPILE.cc) $(OUTPUT_OPTION) $<
.cpp.a:
    $(COMPILE.cc) -o $% $<
    $(COMPILE.cc) -xar $@ $%
    $(RM) $%
.cpp~.a:
    $(GET) $(GFLAGS) -p $< > $*.cpp
    $(COMPILE.cc) -o $% $<
    $(COMPILE.cc) -xar $@ $%
    $(RM) $%

Using make With iostreams

The standard iostream file names do not have ".h" suffixes. Instead, they are named istream, fstream, and so forth. In addition, the template source files are named istream.cc, fstream.cc, and so forth. If you include a standard iostream header, such as <istream>, in your program and your makefile has .KEEP_STATE, you will encounter problems. For example, if you include <istream>, make thinks that istream is an executable and uses the default rules to build istream from istream.cc resulting in very misleading error messages. (Both istream and istream.cc are installed under SC5.0/include/CC). To prevent make from using the default rules, use the -r option.