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:
Transform source files into relocatable binary (.o) files, to be linked later into an executable file, a static (archive) library (.a) file (using– xar), or a dynamic (shared) library (.so) file
Link or relink object files or library files (or both) into an executable file
Compile an executable file with runtime debugging enabled (-g)
Compile an executable file with runtime statement or procedure-level profiling (-pg)
This section gives you a brief overview of how to use the C++ compiler to compile and run C++ programs. See 16.8 Using dlopen to Access a C++ Library From a C Program for a full reference to the command-line options.
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:
Using an editor to create a C++ source file with one of the valid suffixes listed in Table 2–1
Invoking the compiler to produce an executable file
Launching the program into execution by typing the name of the executable file
The following program displays a message on the screen:
example% cat greetings.cc #include <iostream> int main() { std::cout << “Real programmers write C++!” << std::endl; return 0; } example% CC greetings.cc example% ./a.out Real programmers write C++! example% |
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:
example% CC– o greetings greetings.cc |
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:
example% ./greetings Real programmers write C++! example% |
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.
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). In most cases, if you specify the same option more than once, the rightmost assignment overrides and there is no accumulation. Note the following exceptions:
All linker options and the -features, –I -l,– L, -library, –pti, –R, -staticlib, -U, -verbose, -xdumpmacros, and -xprefetch options accumulate, they do not override.
All –U options are processed after all –D options.
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:
example% CC -g -o growth growth.C fft.C |
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++ |
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++ |
Same action as .c suffix. |
|
C++ |
Same action as .c suffix. |
|
C++ |
Same action as .c suffix. |
|
C++ |
Same action as .c suffix. |
|
C++ |
Same action as .c suffix. |
|
C++ |
Preprocessor output file treated as C++ source file. Same action as .c suffix. |
|
Assembler |
Assemble source files using the assembler. |
|
Assembler |
Assemble source files using both the C language preprocessor and the assembler. |
|
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.) |
|
Object files |
Pass object files through to the linker. |
|
Static (archive) library |
Pass object library names to the linker. |
|
Dynamic (shared) library |
Pass names of shared objects to the linker. |
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.
This compiler does not use the cache by default. It only uses the cache if you specify -instances=extern. If the compiler makes use of the cache, it checks the cache directory’s version and issues error messages whenever it encounters cache version problems. Future C++ compilers will also check cache versions. For example, a future compiler that has a different template cache version identification and that processes a cache directory produced by this release of the compiler might issue an error that is similar to the following message:
Template Database at ./SunWS_cache is incompatible with this compiler |
Similarly, the compiler issues an error if it encounters a cache directory that was produced by a later version of the compiler.
When you upgrade your compiler, it is always good practice to clean the cache. Run CCadmin -clean on every directory that contains a template cache directory (in most cases, a template cache directory is named SunWS_cache). Alternatively, you can use rm -rf SunWS_cache.
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.
example% CC file1.cc file2.cc file3.cc -o prgrm |
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.
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.
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:
example% CC -c file1.cc Make new object file example% 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).
If you compile and link in separate steps, consistent compiling and linking is critical when using the compiler options listed in 3.3.3 Compile-Time and Link-Time Options.
If you compile a subprogram using any of these options, you must link using the same option as well:
In the case of the -library, -fast, -xtarget, and -xarch options, you must be sure to include the linker options that would have been passed if you had compiled and linked together. Use —dryrun to see the expansion of these options to determine the options needed on the link step.
With -p, -xpg, and -xprofile, including the option in one phase and excluding it from the other phase will not affect the correctness of the program, but you will not be able to do profiling.
With -g and -g0, including the option in one phase and excluding it from the other phase will not affect the correctness of the program, but it will affect the ability to debug the program. Any module that is not compiled with either of these options, but is linked with -g or -g0 will not be prepared properly for debugging. Note that compiling the module that contains the function main with the -g option or the -g0 option is usually necessary for debugging.
In the following example, the programs are compiled using the -library=stlport4 compiler option.
example% CC -library=stlport4 sbr.cc -c example% CC -library=stlport4 main.cc -c example% CC -library=stlport4 sbr.o main.o -o myprogram |
If you do not use -library=stlport4 consistently, some parts of the program will use the deafult libCstd, and others will use the optional replacement STlport library. The resulting program might not link, and would not in any case run correctly.
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 the last line (the link line) will be used to compile the instantiated templates.
Use the new -m64 option to specify the memory model of the target compilation. The resulting executable will work only on 64-bit UltraSPARC or x86 processors under Solaris OS or Linux OS running a 64-bit kernel. Compilation linking, and execution of 64-bit objects can only take place in a Solaris or Linux OS that supports 64-bit execution.
The -V option displays the name and version number of each program invoked by CC. The -v option displays the full command lines invoked by CC.
The —verbose=%all displays additional information about the compiler.
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:
Unrecognized options, which are preceded by a dash (–) or a plus sign (+), generate warnings.
Unrecognized nonoptions, which are not preceded by a dash or a plus sign, generate no warnings. (However, they are passed to the linker. If the linker does not recognize them, they generate linker error messages.)
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:
example% 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:
example% CC fast move.cc < - The user meant to type -fast move.CC: ld: fatal: file fast: cannot open file; errno=2 ld: fatal: File processing errors. No output written to a.out |
The C++ compiler package consists of a front end, optimizer, code generator, assembler, template prelinker, 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. Use the -v and -dryrun options to help with this.
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 |
---|---|---|
Front end (compiler preprocessor and compiler) | ||
Code optimizer |
-xO[2-5], -fast |
|
x86: Intermediate language translator |
-xO[2-5], -fast |
|
SPARC: Inline expansion of assembly language templates |
.il file specified |
|
Assembler | ||
SPARC: Code generator, inliner, assembler |
|
|
ube |
x86: Code generator |
-xO[2-5], -fast |
Template pre-linker |
used only with the -instances=extern option |
|
link editor |
This section discusses information about preprocessing directives that is specific to the C++ compiler.
The preprocessor directive pragma is part of the C++ standard, but the form, content, and meaning of pragmas is different for every compiler. See Appendix B, Pragmas for details on the pragmas that the C++ compiler recognizes.
Sun C++ also supports the C99 keyword _Pragma. The two invocations
#pragma dumpmacros(defs) _Pragma("dumpmacros(defs)") |
are equivalent. To use _Pragma instead of #pragma, write the pragma text as a literal string, enclosed in parentheses as the one argument of the _Pragma keyword.
The C++ compiler accepts #define preprocessor directives of the following form.
#define identifier (...) replacement_list #define identifier (identifier_list, ...) replacement_list |
If the macro parameter list ends with an ellipsis, an invocation of the macro is allowed to have more arguments than there are macro parameters. The additional arguments are collected into a single string, including commas, that can be referenced by the name __VA_ARGS__ in the macro replacement list. The following example demonstrates how to use a variable-argument-list macro.
#define debug(...) fprintf(stderr, __VA_ARGS__) #define showlist(...) puts(#__VA_ARGS__) #define report(test, ...) ((test)?puts(#test):\ printf(__VA_ARGS__)) debug(“Flag”); debug(“X = %d\n”,x); showlist(The first, second, and third items.); report(x>y, “x is %d but y is %d”, x, y); |
which results in the following:
fprintf(stderr, “Flag”); fprintf(stderr, “X = %d\n”, x); puts(“The first, second, and third items.”); ((x>y)?puts(“x>y”):printf(“x is %d but y is %d”, x, y)); |
Table A–2 in the appendix shows the predefined macros. You can use these values in such preprocessor conditionals as #ifdef.The +p option prevents the automatic definition of the sun, unix, sparc, and i386 predefined macros.
The #error directive no longer continues compilation after issuing a warning. The previous behavior of the directive was to issue a warning and continue compilation. The new behavior, consistent with other compilers, is to issue an error message and immediately halt compilation. The compiler quits and reports the failure.
The amount of memory a compilation requires depends on several parameters, including:
Size of each procedure
Level of optimization
Limits set for virtual memory
Size of the disk swap file
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. Try reducing the level of optimization. Alternately, split the largest procedures into separate files of their own.
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:
example% swap -s total: 40236k bytes allocated + 7280k reserved = 47516k used, 1058708k available |
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:
example# mkfile -v 90m /home/swapfile /home/swapfile 94317840 bytes example# /usr/sbin/swap -a /home/swapfile |
Compiling very large routines (thousands of lines of code in a single procedure) at -xO3 or higher can require a large 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 an 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 4 Gbytes:
example$ ulimit -d 4000000 |
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 4 Gbytes:
example% limit datasize 4G |
Each of these examples causes the optimizer to try to recover at 4 Gbytes 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 8 Gbytes of swap space, use the following commands:
In an sh shell:
example$ ulimit -d 4000000 |
In a csh shell:
example% limit datasize 4G |
The best setting depends on the degree of optimization requested and the amount of real memory and virtual memory available.
A workstation should have at least 2 gigabytes of memory; 1 gigabyte is recommended. See the product release readme (http://developers.sun.com/sunstudio/documentation/) for detailed requirements.
The Unix strip command should not be used with C++ object files, as it can render those object files unusable.
You can simplify complicated compiler commands by defining special shell aliases, using the CCFLAGS environment variable, or by using make.
The following example defines an alias for a command with frequently used options.
example% alias CCfx "CC -fast -xnolibmil" |
The next example uses the alias CCfx.
example% CCfx any.C |
The command CCfx is now the same as:
example% CC -fast -xnolibmil any.C |
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):
example% setenv CCFLAGS ’-xO2 -m64’ |
The next example uses CCFLAGS explicitly.
example% 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 -xO2 -m64 files...
The make utility is a very powerful program development tool that you can easily use with all Sun compilers. See the make(1S) man page for additional information.
When you are using the implicit compilation rules of the makefile (that is, there is no C++ compile line), the make program uses CCFLAGS automatically.