Important GCC Flags in Linux

If you program in C or C++ using Linux, the compilation process is going to be handled by the GCC, aka the GNU project C and C++ compiler.

And as always, you can use flags to extend the functionality.

So let's look at some of the most important GCC flags.

Important GCC Flags

To make things easy to understand, I will be using the following C program:

#include<stdio.h>

int main(void)
{
   printf("\n Linuxhandbook \n");
   return 0;
}

Pretty simple, right? Don't judge my programming skills.

1. Specify the output filename using -o

In the most basic term, you will use the GCC compiler as follows:

gcc main.c

And the above command will compile the program and it will create an executable with the name a.out.:

To specify the output executable filename, all you need to do is append the filename with the -o flag as shown below:

gcc main.c -o Filename

For example, here, I named the executable file Result:

gcc main.c -o Result

2. Enable every warning with -Wall

If you want to print every warning so that you can examine your code and make it better than ever, use the -Wall flag.

gcc -Wall main.c -o Result

For example, here, I will be using a code without initialing the variable:

#include<stdio.h>

int main(void)
{
   int i;
   printf("\n Linuxhandbook [%d]\n", i);
   return 0;
}

And when I executed the code, it gave me a warning saying ‘i’ is used uninitialized:

To link the C program with a shared library, all you have to do is append the name of the shared library with the -l flag

For example, here I have linked the code main.c with the shared library pthread to produce the final executable Result:

gcc main.c -o Hello -lpthread

But what if you want to link the external libraries? In that case, you'd have to specify the location of the external library using the -L.

For example, here, I have linked the shared library “LHB” stored in /home/user/LHB:

gcc -L/home/user/LHB -o main.c Results -lLHB

4. Get the preprocessor output only using -E

The pre-processing is the first stage of compilation and if you are only concerned with what happens to your code in the first stage, you can use the -E flag.

Here, I have redirected the standard output to first-stage.i file:

gcc -E main.c > first-stage.i

5. Get the assembly code using -S

If you are concerned with the assembly output during the compilation, it can easily be produced using the -S flag.

Here, I have produced the assembly output of the main.c named as main.s:

gcc -S main.c > main.s

6. Produce compiled code only using -C

To get compiled code without any linking, all you have to do is use the -C flag.

For example, here, I have produced the compiled code of main.c in the file named compiled:

gcc -C main.c -o compiled

7. Produce all the intermediate files using -save-temps

Previously, I explained how you can get the pre-processed, assembly, and compiled output but what if I tell you that you can have all of them at once?

It is quite easy and can easily be produced using -save-temps flag.

Let's say I want to produce all the intermediate files for the main.c file so I will be required to follow the given command:

gcc -save-temps main.c

8. Convert warnings into errors with -Werror

While testing, we programmers tend to ignore the warnings which may indicate the loopholes and security threats in your application.

To make your code rock solid, I would suggest you convert your warnings to the errors using the -Werror flag.

Here, I have used code that would get you a warning saying "undefined variable c":

#include<stdio.h>

int main(void)
{
  char c;
  // Print the string
   printf("\n Linuxhandbook [%d]\n", c);
   return 0;
}

But when I used the -Werror flag while executing, and instead of a warning, it gave me an error:

9. Get a position-independent code using -fPIC

This flag can be crucial for those who are dealing with dynamic linking, especially with shared libraries.

While creating shared libraries, you should have the position-independent code so that you can load the shared library from any address rather than a static one.

For example, here, I have created a shared library named libmain.so from the main.c:

gcc -c -Wall -Werror -fPIC main.c
gcc -shared -o libmain.so main.o

10. Get the verbose output of compilation using -V

If you want to know what is GCC doing with your code line by line, you can use the -V flag to have verbose output.

gcc -Wall -v main.c -o Result

Bonus: Apply GCC flags using the file

If you are using the same set of flags to compile the program, having a file containing the necessary option can save you a lot of time.

First, let's create a file using the touch command:

touch Flags

Now, you can use any of your preferred text editors to enter the flags. Just make sure to separate them with spaces.

And I have saved 3 flags in the file:

Once you are done with adding flags, all you have to do is append the text file with @ symbol:

gcc main.c @Flags

And as you can see, it converted warnings to errors and created all the intermediate files.

Wrapping Up

In this tutorial, I went through some of the most important GCC flags you can use for your daily compilation.

I would highly recommend the bonus tip that I mentioned in the end as it has saved a lot of time and is so convenient to use.

And if you have any queries or suggestions, let me know in the comments.