C/C++ program compilation under Linux system


Introduction


In the Linux operating system, GCC is a modern compiler collection, which can be used to compile a variety of programming languages, including C language and C++ language .

By using the GCC compiler, you can write efficient, safe and reliable programs. For C programs, it is recommended to use gcc for compilation, but for C++ programs, it is recommended to use g++ . If you need to build large-scale C programs and manage source files, you can use makefiles and make tools to accomplish this task.

  • Makefile is a text file that contains targets, dependencies, and commands to execute. Multiple targets can be created and specify dependencies and command sequences according to program complexity.

  • The Make command can automatically build a program, it will read the Makefile and generate the necessary commands to ensure that the target dependencies are followed without having to manually enter a series of compilation commands.

Therefore, when facing a large C program, using makefile and make tools can significantly improve the efficiency and convenience of compilation, and reduce the occurrence of common errors and problems.

The process of compiling a C program mainly includes four stages: compilation preprocessing , compilation optimization , assembly , and linking .

  • In the compilation preprocessing stage, the compiler will read the preprocessing commands in the source program (for example, macro definition commands, conditional compilation instructions, header file inclusion instructions, etc.) and special symbols (for example, LINE appearing in the source program is Interpreted as the current line number expressed in decimal; FILE is interpreted as the file name of the currently compiled source program, and replaced with the corresponding content, while adding the definition in the header file, etc.).

  • In the compilation and optimization stage, the compiler will translate the code into corresponding assembly code after confirming that all instructions conform to the grammatical rules through lexical analysis and syntax analysis, and perform optimization processing. There are two ways to optimize, one is optimization for the code itself (for example, delete common expressions, loop optimization, code extraction, deletion of useless code assignment, etc.), and the other is instruction optimization for computer hardware (for example, Adjust and optimize the instructions according to the characteristics of the machine hardware execution instructions, reduce the length of the object code, improve the execution efficiency, etc.).

  • In the assembly stage, the compiler will produce an assembly file, and then convert it into a sequence of target machine instructions through the assembler to generate a corresponding target file. The target file generally contains at least a code segment and a data segment.

  • In the linking phase, the linker will link multiple object files together, resolve symbolic references, and generate an executable. According to different connection methods, link libraries can be divided into static link and dynamic link. In static linking, the code of the function will be copied directly into the final executable file; in dynamic linking, the code of the function is placed in the shared object, and the name of the shared object and a small amount of Key Information.


C program compilation


Generate an executable program from a single source file

Take the following simple C program as an example, the code of the program is as follows:

/* hello.c */
#include <stdio.h>

int main(int argc,char *argv[])
{
    
    
	printf("Hello cqupthao!\n");
	return 0;
}

The easiest and direct way to compile the above code into an executable program is to save the code as a file hello.c, and execute the following command in the corresponding directory:

gcc hello.c -Wall

The GCC compiler can identify it as a C source code file by checking the suffix of the file specified in the command line (GCC default action: compile the source code file to generate an object file, link the object file to obtain an executable program, delete the object file, and the compiler default executable filename a.out).

Enter a command of the following format in a terminal to have it run and display the results:

./a.out

## result
Hello cqupthao!

You can use the option -oto specify the executable program with the specified file name. For example, enter the following command to generate an helloexecutable program named :

gcc hello.c -o hello -Wall

Enter the following command format in the terminal to make it run and display the result:

./hello

## result
Hello cqupthao!

注意: If you need to compile math.ha standard library that is not called by GCC by default, such as the library, you should use the option -lm.


Executable program generated from multiple source files

When multiple source code files are compiled, the GCC compiler will automatically perform the link operation. For example, a program named hellomain.cfile calls the sayhello() function sayhello.cof a program named file whose code is as follows:

/* hellomain.c */
void sayhello(void);

int main(int argc,char *argv[])
{
    
    
	sayhello();
	return 0;
}

The following program code is saved in the sayhello.cfile named program definition sayhello() function:

/* sayhello.c */
#include <stdio.h>

void sayhello()
{
    
    
	printf("Hello cqupthao!\n");
}

Compile the two files into object files and link it into the executable program hello , and delete the object file, enter the command in the following format:

gcc hellomain.c sayhello.c -o hello -Wall

Enter the following command format in the terminal to make it run and display the result:

./hello

## result
Hello cqupthao!

Source files generate object files

When the option is used during compilation -c, GCC will compile the source code file, but will not link the object file to generate an executable file. At the same time, the program can save the generated target files to the disk to facilitate subsequent operations and debugging.

In this case, GCC's default output file name is the same as the source code file name, but the suffix is ​​changed .oto indicate that this is an object file, that is, a binary file that is not linked. Thus, when compiling a large C program, multiple source files can be compiled separately into object files, which are then combined at the link stage to produce the final executable.

For example, to generate hello.oan object file named , enter a command of the form:

gcc -c hello.c -Wall

option -ocan be used to generate an object file with the specified filename. For example, entering the following command produces sayhello.oan object file named :

gcc -c hello.c -o sayhello.o -Wall 

When building an object library or generating a series of object files for later linking, you can generate the corresponding object file name and object file from multiple source code files (eg, hello.c callhello.c sayhello.c), enter the hello.ofollowing format The command:callhello.osayhello.o

gcc -c hello.c callhello.c sayhello.c -Wall

## result
hello.o callhello.o sayhello.o

Compile preprocessing

option -Einstructs the compiler to do only compilation preprocessing. For example, to preprocess source files hello.cand list the results on standard output, enter a command of the form:

gcc -E hello.c

option -ois used to direct the preprocessed code to a .iC source code file that does not need to be preprocessed and has a suffix of , for example, enter a command in the following format:

gcc -E hello.c -o hello.i

generate assembly code

option -SInstructs the compiler to generate assembly language code and then exit. hello.cFor example, to generate an assembly language file from a C source code file hello.s, enter a command in the following format:

gcc -S hello.c

The form of assembly language depends on the target platform of the compiler. If multiple source code files are compiled, each file will generate a corresponding assembly code module.


Build a static library

A static library is a set of files .owith , which are compiled from the same source code library. Static linking of code, in contrast to dynamic libraries, means that when the program runs, all dependencies are linked and copied, so all necessary code is included in the executable.

In this way, dynamic link errors can be avoided when the program is running, and the performance loss of the dynamic link library can be eliminated. In addition, static libraries are portable and self-contained because they are not dependent on a specific version of the operating system or computer hardware.

Another name for a static library is an archive, because it is actually a series of .oarchives of files. To build a library, you must first compile the object modules needed in the library. firsthello.cFor example, the file names of the following two programs are and respectively secondhello.c, and their source codes are as follows:

/* firsthello.c */
#include <stdio.h>

void firsthello()
{
    
    
        printf("This is the first hello!\n");
}
/* secondhello.c */
#include <stdio.h>

void secondhello()
{
    
    
	printf("This is the second hello!\n");
}

Before using the static library, the source code files that need to be compiled need to be compiled into object files (suffix .o) respectively, and then arthey can be packaged into an archive file (also called a static library file, suffix .a) using the command. For example, to compile these two source code files into object files, enter commands in the following format:

gcc -c firsthello.c secondhello.c -Wall 

Under the Linux system, arthe tool is usually used to manage and create archive files, and arwith the parameter -rto create a new library and insert the object file. -rThe argument will create a new library if it does not exist , and add (by replacing if necessary) the object module to the archive. For example, to create a libhello.astatic library named containing the two object modules in this example, enter a command of the form:

ar -r libhello.a firsthello.o secondhello.o

Call these two functions in the library and write a uselib.cprogram named as follows:

/* uselib.c */
void firsthello(void);
void secondhello(void);

int main(int argc,char *argv[])
{
    
    
	firsthello();
	secondhello();
	return 0;
}

Programs can be compiled and linked with a single command by specifying the library on the command line, as follows:

gcc uselib.c libhello.a -o uselib -Wall 

Enter the following command format in the terminal to make it run and display the result:

./uselib

## result
This is the first hello!
This is the second hello!

The naming convention of the static library starts with lib and the suffix is .a, for example, libhello.a. This naming convention is widely used in various operating systems and programming languages. In the Linux system, all system libraries adopt this naming convention. The compiler provides -loptions to specify the name of the library file to be linked, and the name of the library on the command line can be specified in shorthand, similar to the form of -l<library name> . For example, in the above command, use to -lhellopoint to libhello.athe static library, and uselib.clink the library with the file to generate an executable file uselib.

It should be noted that the compiler will search for libhello.athe library file from the default system library directory. If the library file exists in a specific directory, you can use the full path name or relative path name to specify the location of the library file. If you specify a specific path name, you can use the absolute path or relative path format to express. For example, assuming the library files are stored in the liblibhello.a directory under the current directory , the following command can be used:

gcc twohellos.c -L./lib -lhello -o twohellos -Wall 

In this command, the option specifies that the library file is in the lib-L./lib directory under the current directory , and the option refers to the static library file, so that the compiler will search for the static library file in the specified directory to realize the link operation.-lhellolibhello.alibhello.a


build shared library

Shared library (shared library), also known as dynamic link library (dynamic library), is a collection of object files generated by the compiler in a special way. During the compilation process, all addresses (including variable references and function calls) in the object file module are relative rather than absolute, which enables the shared library to be dynamically loaded when the program is running and supports simultaneous use by multiple processes. Thereby saving memory space and realizing code reuse.

Unlike static libraries, shared libraries are not linked into the final execution file, but are loaded into memory when the program runs. Therefore, the shared library has better portability and reusability, and can be shared and used in different applications, thereby better realizing code reuse.

To build a shared library, you first need to compile the object file (.o file). For example, in the following example we compile two source code files sharedfirst.cand to generate object files and respectively :sharedsecond.csharedfirst.osharedsecond.o

/* sharedfirst.c */
#include <stdio.h>

void sharedfirst()
{
    
    
	printf("This is the first hello from a shared library!\n");
}
/* sharedsecond.c */
#include <stdio.h>

void sharedsecond()
{
    
    
	printf("This is the second hello from a shared library!\n");
}

To compile the above two source code files into object files, enter the command in the following format:

gcc -c -fpic sharedfirst.c sharedsecond.c -Wall 

option -ctells the compiler to generate only .othe object files of . option -fpicCauses the generated object modules to take floating (relocatable) addresses.

The following gcc command builds the object files into a shared library called hello.so:

gcc -shared shellofirst.o shellosecond.o -o hello.so

When compiling a shared library, there is no obvious entry point function, such as the main() function , that is called when the program runs, so you need to use options -sharedto tell the compiler to create a shared library instead of an executable file. This option tells the compiler not to link according to the entry address agreed by the operating system, but to treat the compiled object file collection as a shared object.

Since the compiler can recognize the file extension .cand know how to compile it into an object file, the compilation step can be omitted, and a command of the following format will directly compile and link two source code files sharedfirst.cand sharedsecond.c, and build them into a shared library libshello.so. In this case, the compiler automatically compiles the source files into object files and links those object files as shared libraries:

gcc -fpic -shared sharedfirst.c sharedsecond.c -o hello.so -Wall 

Write a program file called uessharedlib.cthe main program that calls two functions in the shared library. The code of the program is as follows:

/* usesharedlib.c */
void sharedfirst(void);
void sharedsecond(void);

int main(int argc,char *argv[])
{
    
    
	sharedfirst();
	sharedsecond();
	return 0;
}

The program can be compiled and linked with the shared library with the following commands:

gcc usesharedlib.c hello.so -o usesharedlib -Wall 

To run it, it must be able to locate the shared library hello.so, because the functions in the library are loaded when the program is running. It should be noted that the current working directory may not be in the search path of the shared library, so you need to use the following command line to set the environment variable LD_LIBRARY_PATH:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

Enter the following command format in the terminal to make it run and display the result:

./usesharedlib

## result
This is the first hello from a shared library!
This is the second hello from a shared library!

C++ program compilation


Generate an executable program from a single source file

Take the following simple C++ program as an example, the code of the program is as follows:

/* hello.cpp */
#include <iostream>

int main(int argc,char *argv[])
{
    
    
    std::cout << "Hello cqupthao!" << std::endl;
    return(0);
}

The program uses cout defined in the header file iostreamto write a simple string to the standard output. The simplest and direct way to compile the above code into an executable program is to save the code as a file and execute the following command in the corresponding directory :hello.cpp

g++ hello.cpp -Wall

Compiler g++ recognizes it as a C++ source code file by checking the extension of the file specified on the command line. The default action of the compiler: Compile the source code file to generate an object file, link the object file and the functions in the libstdc++ library to obtain an executable program, and then delete the object file. The compiler does not specify the file name of the executable program by default a.out. Enter the following form in the terminal to make it run and display the result:

./a.out

## result
Hello cqupthao!

You can use the option -oto specify the executable program with the specified file name. For example, enter the following command to generate an helloexecutable program named :

g++ hello.cpp -o hello -Wall

Enter the following command format in the terminal to make it run and display the result:

./hello

## result
Hello cqupthao!

注意: g++ is a special version that sets the default language of gcc to C++, and it automatically uses the C++ standard library instead of the C standard library when linking.

By following the naming convention of the source code and specifying the name of the corresponding library, it is feasible to compile and link the C++ program with gcc, for example, enter the command in the following format:

gcc hello.cpp -lstdc++ -o hello -Wall

Enter the following command format in the terminal to make it run and display the result:

./hello

## result
Hello cqupthao!

option (ell) transforms the name following it into the name of the library libstdc++.a-l by adding the prefix liband suffix , which it then looks for in the standard library path. The compilation process and output files of gcc are exactly the same as those of g++..a

On most systems, GCC installs a program called c++, which is equivalent to g++. For example, enter a command in the following format:

c++ hello.cpp -o hello -Wall

Enter the following command format in the terminal to make it run and display the result:

./hello

## result
Hello cqupthao!

Executable program generated from multiple source files

If multiple source files are specified in the g++ command, they will all be compiled and linked into a single executable. For example, the following speak.hheader file named , which contains the definition of a class with only one function, has the following code:

/* speak.h */
#include <iostream>

class Speak
{
    
    
    public:
        void sayHello(const char *);
};

The following program code lists speak.cppthe contents of the file, including the function body of the sayHello() function:

/* speak.cpp */
#include "speak.h"

void Speak::sayHello(const char *str)
{
    
    
    std::cout << "Hello " << str << "\n";
}

Write a hellospeak.cppprogram named as using the Speak class, the code of the program is as follows:

/* hellospeak.cpp */
#include "speak.h"

int main(int argc,char *argv[])
{
    
    
    Speak speak;
    speak.sayHello("cqupthao!");
    return(0);
}

To compile and link the above two source code files into a single executable program, enter the command in the following format:

g++ hellospeak.cpp speak.cpp -o hellospeak -Wall

Enter the following command format in the terminal to make it run and display the result:

./hellospeak

## result
Hello cqupthao!

注意: This code speak.cppis included in #include "speak.h", which means that the file will be searched in the current directory before searching the system header file directory “speak.h“, and it is in this directory, so it does not need to be specified in the command.


Source files generate object files

When compiling, the option can be used -cto tell the compiler to compile the source code but not to execute the link. The output result is an object file. The default name of the file is the same as that of the source code file, but its suffix is ​​changed to .o. For example, a command of the following form will compile source files hellospeak.cppand generate object files hellospeak.o:

g++ -c hellospeak.cpp -Wall

g++ recognizes .othe file and passes it to the linker as an input file. For example, entering a command of the following form will compile source files into object files and link them into a single executable program:

g++ -c hellospeak.cpp -Wall 
g++ -c speak.cpp -Wall 
g++ hellospeak.o speak.o -o hellospeak 

Enter the following command format in the terminal to make it run and display the result:

./hellospeak

## result
Hello cqupthao!

Options -ocan be used not only to name executable files, but also to name other files output by the compiler. For example, the following command produces the exact same executable as above, except that the intermediate object files have different names:

g++ -c hellospeak.cpp -o hellotmp.o -Wall
g++ -c speak.cpp -o speaktmp.o -Wall
g++ hellotmp.o speaktmp.o -o hellospeak 

Enter the following command format in the terminal to make it run and display the result:

./hellospeak

## result
Hello cqupthao!

Compile preprocessing

option -EMake g++ do not perform other actions after processing the source code with the compiling preprocessor. For example, to preprocess a source file hellospeak.cppand display the result on standard output, enter a command of the form:

g++ -E hellospeak.cpp

The preprocessed file suffix is .ii, it can -obe generated by option, for example, enter the command in the following format:

gcc -E hellospeak.cpp -o hellospeak.ii

generate assembly code

Option -SInstructs the compiler to compile the program into assembly language, output the assembly language code and then end. hellospeak.cppFor example, to generate an assembly language file from a C++ source code file hellospeak.s, enter a command in the following format:

g++ -S hellospeak.cpp

The form of assembly language depends on the target platform of the compiler. If multiple source code files are compiled, each file will generate a corresponding assembly code module.


Build a static library

A static library is a collection of object files generated by a compiler. When linking a program, it is the same whether to use the object file in the library or the object file in the directory. The members in the library include ordinary functions, class definitions, object instances of the class, and so on. Another name for a static library is an archive file, and the tool for managing such archive files is called ar.

For example, create two object modules and use them to generate a static library. Write a program whose header file name say.hcontains the prototype of the function sayHello() and the definition of the class Say . The code of the program is as follows:

/* say.h */
#include <iostream>

void sayhello(void);

class Say {
    
    
    private:
        char *string;
    public:
        Say(char *str)
        {
    
    
            string = str;
        }
        void sayThis(const char *str)
        {
    
    
            std::cout << str << " from a static library!\n";
        }
        void sayString(void);
};

The program named below say.cppis the source code of one of the two object files that need to be added to the static library. It contains the definition body of the sayString() function in the Say class and the declaration of an instance librarysay of the class Say . The code of the program is as follows :

/* say.cpp */
#include "say.h"

void Say::sayString()
{
    
    
    std::cout << string << "\n";
}
 
Say librarysay("Library instance of Say!");

The program whose source code file is named sayhello.cppis the source code of the second object file that needs to be added to the static library. It contains the definition of the function sayhello() . The code of the program is as follows:

/* sayhello.cpp */
#include "say.h"

void sayhello()
{
    
    
    std::cout << "The hello from a static library!\n";
}

A sequence of commands of the following form compiles source code files into object files, which the command arstores in a library:

g++ -c sayhello.cpp -Wall
g++ -c say.cpp -Wall
ar -r libsay.a sayhello.o say.o

Write a main program saymain.cppto call the corresponding program code in the library libsay.a :

/* saymain.cpp */
#include "say.h"

int main(int argc,char *argv[])
{
    
    
    extern Say librarysay;
    Say localsay = Say("Local instance of Say!");
    sayhello();
    librarysay.sayThis("howdy");
    librarysay.sayString();
    localsay.sayString();
    return(0);
}

The program can be compiled and linked using commands of the form:

g++ saymain.cpp libsay.a -o saymain

Enter the following command format in the terminal to make it run and display the result:

./saymain

## result
The hello from a static library!
howdy from a static library!
Library instance of Say!
Local instance of Say!

  • Reference book: "Linux Embedded C Development" (by Hua Qingyuan)

Guess you like

Origin blog.csdn.net/qq_46457076/article/details/130792005
Recommended