May 9, 2024

Clear Explanation of How to Compile C++/C Code Files in Linux/Unix Command Line/Terminal

In this tutorial, you will learn how to compile C++/C code files in Linux/Unix command line (terminal) by using the GNU Compiler Collection (GCC) compiler. The motivation for creating this tutorial mainly comes from the fact that mechatronics and control engineering students are not very familiar with the Linux/Unix command line. However, in many cases and real-life scenarios, it is necessary to know how to use the Linux/Unix command line and how to quickly compile and run programs. This is especially the case for embedded system development. The YouTube tutorial accompanying this post is given below.

Compiling and Executing the Code Without the Need to Understand What is Happening Under the Hub

First, open a Linux terminal, and type in the Linux terminal the following

pwd

This command will show the current working directory. In my case it is: “/home/alex“. If you want to see the content of the current directory, you can write

ls -l

The command “ls” will list all the current files and directories. Next, we will create a two new folders. First type,

mkdir testCodes

This will create the folder called “testCodes”. Next, let us move to this folder and let us create a new folder in this folder. We can do that by typing

cd testCodes

mkdir firstCode

The command “cd” is an abbreviation for “change directory”. This command is used to change the current directly. The second command will create “firstCode” directory in the directory “testCodes”. Let us move to the “firstCode” folder by typing

cd firstCode

Next, we create an empty C file call “test1.c”. At the same time, we will edit this file. Consequently, we call the Linux text editor Gedit:

gedit test1.c

This will create the new file “test1.c” and the editor. Type this code in the Gedit editor

#include<stdio.h>

int main()
{
	int a=5;
	int b=7;
	
	int sum;
	
	sum=a+b;
	
	printf("\n\n The sum of %d and %d is: %d \n ",a,b,sum);

}

This is a C code file that will add two numbers and display the result. Next, save this file, and close the editor. You should be back in the terminal window. By typing

ls -l

you can observe that the new code file is created. Next, let us compile, link, and create an executable file. We can do that by using the GCC compiler as follows

gcc test1.c -o test1Executable

Here,

  • gcc is the compiler
  • test1.c is the name of the source file
  • -o is the parameter saying to the compiler that we want to specify the name of the executable file
  • test1Executable is the name of the executable file

If after this command, if you type

ls -l

you will notice that in the current directory there is a file called “test1Executable“. You should also note the attributes (permission) of the file. In our case, they are “-rwxrwxr-x”. The letter $x$ means that the file can be executed. If there is no “x”, you should type “chmod a+x test1Executable”. Now, if in the command line you simply write: “test1Executable“, you will get the following error

test1Executable: command not found

This means that you cannot execute the file like that. In Windows, the executable file usually have the extension “*.exe”, and you can directly execute the file by just typing their names without extensions. However, in Linux, you need to execute the file differently. To execute the file, you need to write the following

./test1Executable

Here,

  • ./ is the current path. That is, the path to the executable file. Note that in Bash shell, the default PATH variable does not include the current working directory. This is why we need to add the current path before the name of the file. In Windows systems, this is not the case, and consequently, we can directly type the name of the executable file.
  • test1Executable is the name of the executable file

The procedure for compiling, linking, and executing a C++ file is very similar. We actually use (almost) the same set of commands. The GCC compiler will automatically invoke the C++ compiler. This is done on the basis of the extension of the file. Let us illustrate this. First, in the current directory, let us create and edit the following C++ file:

gedit test2.cpp

Then, type the following C++ code in this file and save the file

#include<iostream>
using namespace std;

int main()
{

	int a=5;
	int b=7;
	
	int sum;
	
	sum=a+b;
	
	cout<<"\n\n The sum of "<<a<< " and "<<b<<" is "<< sum << endl;

return 0;

}

Then, to compile and link this file, you need to type

g++ test2.cpp -o test2Executable

Note that here, we are actually using a new command “g++”. If you would instead use “gcc test2.cpp -o test2Executable“, you would get a compiler error. Roughly speaking, this is because “gcc” is having challenges to properly compile/link C++ libraries or headers. We can still use gcc to compile the C++ code, however, we need to change the syntax as follows:

gcc test2.cpp -lstdc++ -o test3Executable

With the parameters -lstdc++ we perform explicit linking and this resolves the original problem.

That is it! You learned how to compile C/C++ codes and create executable files in the Linux terminal.

For People/Students Who Want to Know More

Behind the scenes, the GCC compiler compiles and creates executable files by performing the following 4 steps

  1. File preprocessing. During this step, the GCC compiler includes all the header files and expands all the macros that are created by using #define.
  2. Compilation. During this step, the GCC compiler compiles the pre-processed source file and creates and assembly file for a particular processor.
  3. Assembly. During this step, the assembly file is converted into machine code file that is also called the object file, and has an extension “.o”
  4. Linking. During this step the object file is linked with other library code files and as the result, an executable code file is produced.

Let us learn how to separate the creation of an object file and linking. We create the object file (steps 1,2, and 3) by typing

gcc -c test1.c

This command will produce the file “test1.o”. This is an object file. We can also explicitly specify the name of the object file. We can do that like this

gcc -c test1.c -o test1Object.o

We can link the created object file like this

gcc -g test1Object.o -o test1ExecutableFromObject

We can execute the created file like this

./test1ExecutableFromObject

We can activate the verbose mode during compilation as follows

gcc -v test1.c -o test1Executable

When compiling a program we have to keep in mind the type of code being generated. Depending on how you link the files, you can create

1.) Static linking – the output files are larger but they can be used as a stand alone binaries. This means that you can copy your executable files to another system and it does not depend on shared libraries when it is being executed. The machine code of external libraries is copied into your executable.

We can ensure that the static linking is performed by typing the keyword “-static” while compiling the file. That is, the command

gcc -static test1.c -o test1ExecutableStatic

will create the executable file called “test1ExecutableStatic“. The size of this file is 871832.

2.) Dynamic linking – the final executable code is much smaller and it depends on the shared libraries. If you copy the final executable file to another system, we have to make sure that the shared libraries are also present on this system. Before the executable file runs, the system loads the machine code needed for external function. This process is called the dynamic linking. This process enables us to have smaller executable files, and one copy of a library can be shared between several code files.

We can investigate the dependencies of the dynamically linked file as follows:

ldd test1Executable

The output is:

linux-vdso.so.1 (0x00007ffda75ea000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1a4a016000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1a4a24c000)

If we want to copy our executable to some other system, we have to make sure that “linux-vdso.so.1” , “libc.so.6 “, and “ld-linux-x86-64.so.2 ” are present. Here is important that files with the extension “.so” are shared libraries. The abbreviation “so” stands for “shared object”.

A comprehensive tutorial on most useful compiling options can be found here.