Under Unix, there are many compilers and interpreters, but here we will discuss only
gcc as a means of compiling C code, and briefly touch on using
perl as an example interpreter.
Gcc
GCC is a set of compilers with a very respectable age and distributed under the GPL license. It is known as a tool for working with C and C ++ programs. A free license and widespread prevalence on Unix-like systems have become the key to its continued popularity, although there are more modern alternatives using LLVM infrastructure, such as
Clang .
The main
gcc executable file is best presented not as a compiler in the usual sense, but as a layer of abstraction over a multitude of individual programming tools that perform code parsing, compilation, linking and other actions. This means that using it you can not just get a working binary from C code, but explore in detail all the steps of this complex process, and if necessary adjust it to fit your needs.
')
Here I will not discuss the use of make-files, although they will certainly be needed for any project more difficult than in a single file. Makefile I touch in the next article on the automation of the assembly.
Compiling and building object code
The object code is compiled with this command:
$ gcc -c example.c -o example.o
If the code is correct, an unlinked binary object file named
example.o
will be created in the current folder, or problems will be reported. You can look inside the received file and see its contents in assembly language like this:
$ objdump -D example.o
Alternatively, you can ask gcc to immediately show the final assembly code with the
-S parameter:
$ gcc -c -S example.c -o example.s
The output of the assembler code can be useful to combine with the output of the source itself, which can be achieved by typing:
$ gcc -c -g -Wa,-a,-ad example.c > example.lst
Preprocessor
The C preprocessor (
cpp ) is commonly used to include header files and define macros. This is a standard part of the
gcc compilation process, but you can view the code it generates by calling
cpp directly:
$ cpp example.c
The source code will be displayed in the final form, ready for compilation, with macros replaced and substitution of included external files.
Linking objects
One or several object files can be linked to the corresponding executable file:
$ gcc example.o -o example
In this example,
gcc just calls
ld , the GNU linker. The command will create an executable file named
example
.
Compilation, assembly and linking
All of the above can be done in one step with the command:
$ gcc example.c -o example
This method is simpler, but compiling objects separately gives some performance gain: you do not need to compile unchanged code, but we'll talk about this in the next article.
Include external files and bind
C files and header files can be explicitly included in the compilation using the
-l option:
$ gcc -I/usr/include/somelib.h example.c -o example
Similarly, if the code needs to be dynamically linked to an already compiled system library, available in one of the system folders (
/lib
or
/usr/lib
), for example,
ncurses , this can be achieved using the
-l option :
$ gcc -lncurses example.c -o example
If in the process of compiling external links a lot, it makes sense to add them to the environment variables:
$ export CFLAGS=-I/usr/include/somelib.h $ export CLIBS=-lncurses $ gcc $CFLAGS $CLIBS example.c -o example
By the way, the Makefile is then created to save us from worrying about such trifles.
Compilation plan
To see the details of the
gcc internal kitchen, you can add the
-v option , and the compilation plan will be output to the standard error output stream:
$ gcc -v -c example.c -o example.o
If there is no need to generate object or executable files, then for accuracy you can use
- ### :
$ gcc -
It is very useful to see what actions
gcc takes without our knowledge, in addition, so we can identify unwanted steps during compilation.
Advanced error reporting
It is possible to add the
-Wall and / or
-pedantic keys so that gcc warns us about cases that are not necessarily errors, but can be:
$ gcc -Wall -pedantic -c example.c -o example.o
It is convenient to include such options in the
Makefile
or in the definition of a
makeprg
for
Vim , as they are perfectly combined with the quickfix window, and help to write readable, compatible and error-free code.
Profiling the compilation process
You can enable the
-time option
so that
gcc displays the execution time of each step in the output text:
$ gcc -time -c example.c -o example.o
Optimization
Gcc has optimization keys, indicating that you can ask it to create more efficient object code and related binaries by increasing the compile time. I consider -O2 as the golden mean for the released code:
gcc -O1 gcc -O2 gcc -O3
Like any Bash command, all this can be invoked directly from Vim:
:!gcc % -o example
Interpreters
The approach to interpreted code in Unix-systems is different. In my examples I will use Perl, but the same principles apply for code, for example, in Python or Ruby.
Inline code
You can string Perl-code directly to the interpreter in any of the following ways: The first is probably the easiest and most common way to work with
Perl ; the second uses the
heredoc syntax, and the third is the classic Unix pipeline.
$ perl -e 'print "Hello world.\n";' $ perl <<<'print "Hello world.\n";' $ echo 'print "Hello world.\n";' | perl
Of course, in everyday life we store the code in a file that can be called directly like this:
$ perl hello.pl
You can check the syntax of the code without executing it with the
-c option :
$ perl -c hello.pl
Sometimes you want to use the script like any binary executable, without worrying about what it represents. To do this, the script adds the first line to the so-called "
shebang ", indicating the path to the interpreter, which should be transferred to the execution of the file.
The script can then set the attribute of the executable file by calling
chmod . It is also considered good practice to rename a file, removing extensions, since it is now considered almost a real executable file:
$ mv hello{.pl,} $ chmod +x hello
Then the file can be called directly without an interpreter:
$ ./hello
This whole kitchen works so well that many standard Linux system utilities, such as
adduser , are actually Perl or Python scripts.
In the next post I will talk about the methods of working with
make to build projects that are comparable to the usual IDE.
To be continued...Unix as IDE: IntroductionUnix as IDE: FilesUnix as IDE: Working with TextUnix as IDE: Compile