When developing programs with command-line tools, you typically iterate the following steps:
Edit: Use an editor to develop the code in your programming language of choice. Result: a text file with the source code of the program (e.g. hello.c)
Compile: Use a compiler to translate the source code into a version understood by the machine. Result: a binary file with the executable code of the program (e.g. hello)
Run: Execute the program on the machine. Result: you see the result of executing your program (e.g. messages printed by the program)
This section is a practical on how to use common Linux tools to develop simple programs (we mainly cover C here), to compile a program on the command line and to run the resulting executable. Most of the information here is typical for this Edit-Compile-Run development cycle on the command-line. If you use different languages or compilers you naturally need to adjust the specific commands (and flags), but the overall structure is the same.
This section has evolved out of short summaries about basics of compilation, and more details on this can be found in the slides here.
There are a lot of good editors for Linux out there, and some of them are discussed in the Section called Editors. In this practical we will used emacs as editor, which by default has a programming language mode for C including highlighting etc.
To get started, download the program called hello.c executing the following command from the commandline (or using this URL):
$ wget http://www.macs.hw.ac.uk/~hwloidl/Courses/F28HS/srcs/hello.c |
$ ls -ltr |
Now we want to edit this file using emacs. To do so type
$ emacs hello.c |
Use either mouse or cursor keys to navigate, and the menus for basic operations. Useful short-cut commands are CTRL-x CTRL-s for saving the current file and CTRL-x CTRL-c for exiting the editor. A quick-reference card for emacs with the main short-cuts is available here. Also Chapter 7 in Sobell's Linux Guide has a section on the most important commands.
Before we can run the program we need to compile it. This means, we need to run a program that takes the C program as input, and produces an executable file, i.e. a file in a format that is understood by the machine. In an IDE the steps of compiling and executing are often conflated by just clicking at a run button. However, conceptually it is important to separate the two steps, because they do very different things.
Now, to compile our hello.c program, we execute the following line:
$ gcc -o hello hello.c |
Now that we have generated an executable file, we can run it like this:
$ ./hello Hello world! |
We have now gone through one cycle of edit-compile-run, where the edit phase was just the download (and viewing) of a file. Now, we want to modify our program slightly and go through this cycle again, and in doing so meet several other useful developer tools.
Our goal is to add the name of the machine we are running this program on to the string that is displayed. This is a simple step of customisation to our working environment. First we copy the file hello.c to hello0.c, for our new program, and we start the editor on this new file:
$ cp hello.c hello0.c $ emacs hello0.c |
Now we need to know how to get the name of the machine, or in short the hostname, by using the right library function that is available in C. For this we can use the Linux man pages and the man that we have met in the Section called Basic Linux Usage. The man pages have different sections to separate user commands from library functions, configuration files etc (type man man for an explanation of this structure). A good starting point for us is Section 7, which explains the main concepts. We can use the section number as an additional, first argument to the man command like this:
$ man 7 hostname |
$ man 2 gethostname |
#include <unistd.h> int gethostname(char *name, size_t len); |
sethostname() sets the hostname to the value given in the character array name. The len argument specifies the number of bytes in name. (Thus, name does not require a terminating null byte.) |
We now have the information that we need, and we can modify the program to also print the hostname. We need to add the #include line at the beginning. In the main function we need to declare a string, or an array of characters, to hold the hostname. We fix the string to a size of 80 characters, and therefore also need to pass 80 as a second argument to gethostname, for the security reasons explained above. Finally we modify the printf call to print both lines. The screenshot below shows the emacs window with the modified C program.
Now we want to compile our program again, typing:
$ gcc -o hello0 hello0.c |
hello0.c: In function 'main': hello0.c:10: error: invalid operands to binary + (have 'char *' and 'char *') |
The problem here is that we try to use the operator + on strings, however unlike Java or C#, this is not possible in C, and that is what the error message is telling us. The easiest way of achieving a concatenation of strings like this, is to use the format-string capabilities of the printf command. Again, an explanation of this can be found in the man pages:
$ man 3 printf |
printf("Hello world!\nThis is running on machine %s\n", name); |
$ gcc -o hello2 hello2.c |
Now that we have generated an executable file, we can run it like this:
$ ./hello2 Hello world! This is running on machine lxhwloidl |
This section presented a simple example of using the edit-compile-run cycle for a simple C program from the command-line. There are many more useful things that you can try out at this point. For example, if you need to debug your program to locate a problem, you can compile the program with option -g and than use the GNU debugger gdb to single step through the program. The first slide set at this C revision discussed this debugging process, and some more flags to gcc, in more detail.
<<< Previous | Home | Next >>> |
Linux Applications | Practical: Edit-Compile-Run Cycle for Java Programs |