Goal: The lab helps student to
- Review basic shell commands and practice with vim on Linux, Mac OS X.
- Review C programming with compiling and running a program on Linux, Mac OS X.
Content:
- Practice with vim text editor.
- Programming with C language.
- Compile a program with Makefile.
Result:
- After doing the lab, student can type a program without GUI on Linux/Mac OS C by vim.
- Student can compile and run a program using Makefile.
1 Introduction
1.1 Vim
Vim is the editor of choice for many developers and power users. Its a modal text editor based on the vi editor written by Bill Joy in the 1970s for a version of UNIX. It inherits the key bindings of vi, but also adds a great deal of functionality and extensibility that are missing from the original vi. Vim has two modes for users:
- Command mode: allows user to do functions such as find, undo, etc.
- Insert mode: allows user to edit the content of text.
To turn the Insert mode to Command mode, we type ESC key or CrtlC. Otherwise, to enter the Insert mode, type i or I, a, A, o, O. Some of basic commands in V im:
- Save: enter :w
- Quit without Save and discard the change: enter :q!
- Save and Quit: enter :wq
- Move the cursor to the top of file: gg
- Move to the bottom: G
- Find a letter/string by going forward: enter /[letter/string] <Enter>
- Find a letter/string by going backward: enter ?[letter/string] <Enter>
- Repeat the previous finding: enter n
- Repeat the previous finding by going backward: enter N
- Delete a line: enter dd
- Undo: enter u
- Redo: enter Ctrl-R
Furthermore, V im has a mode called visual that allows user to chose a paragraph for copying or, moving. To enter this mode, we need to turn the editor into Command mode and press v. After that, user use arrow keys to chose the paragraph, and then use the following commands:
- Copy: enter y
- Cut: enter d
- Paste: enter p
1.2 C programming on Linux/Mac OS X
GNU C Coding Standards
- Keep the length of source lines to 79 characters or less, for maximum readability in the widest range of environments.
- Put a comment on each function saying what the function does, what sorts of arguments it gets, and what the possible values of arguments mean and are used for.
- Please explicitly declare the types of all objects. For example, you should explicitly declare all arguments to functions, and you should declare functions to return int rather than omitting the int.
Reference: http://www.gnu.org/prep/standards/standards.html. Formatting your source code
Compiling process: It is important to understand that while some computer languages (e.g. Scheme or Basic) are normally used with an interactive interpreter (where you type in commands that are immediately executed). C source codes are always compiled into binary code by a program called a compiler and then executed. This is actually a multi-step process which we describe in some detail here.
source
code executable
(.c, .cc, .h) binaries
Preprocessor Compiler Assembler Linker
Figure 1.1: C Compiling scheme
Steps in compiling process:
- Preprocessor
- Compiler
- Assembler
- Linker
Compilers and Libraries: Apple provides a customized/optimized GNU CC, with backends for C, C++, Objective-C and Objective-C++. Compilers for many other languages are available either precompiled (such as the XL Fortran Advanced Compiler from IBM), or can be compiled from source, which is not any harder in general than compiling the same source on, say, Linux or FreeBSD. The LLVM compiler is the next-generation compiler, introduced in Mac OS X. In Xcode of Mac OS X, the LLVM compiler uses the Clang front end to parse source code and turn it into an interim format.
Figure 1.2: Clang in Mac OS X
Figure below shows a C program compiled in step by step.
% Preprocessed source f i l e$ gcc E [o hello . cpp ] hello . c% Assembly code$ gcc S [o hello .S] hello . c% Binary f i l e$ gcc c [o hello . o ] hello . c% Executable f i l e$ gcc [o hello ] hello . c |
1
2
3
4
5
6
7
8
9
10
11
2 Practice
2.1 Compile and run a program
Steps for creating a program
In general, the compiling progress includes these steps:
- Create source code file hello.c
#include <stdlib .h>#include <stdio .h>int main( int argc , char argv ) { printf (Hello , World! );return 0;} |
1
2
3
4
5
6
7
- Create object file:
$ gcc c souce_code_file . c # Example :
$ gcc c hello . c
# or
$ gcc c o hello . o hello . c
- Create executable file:
$ gcc o executable_file # Example :$ gcc o hello hello . o | object1 . o object2 . o | . . . |
We can compile the program directly from the source code file without the step of creating object file. However, this way can cause the difficulty when identifying errors.
- Create executable file:
$ gcc o executable_file # Example :$ gcc o hello hello . c | src1 . c src2 . c | . . . |
- Run the program:
$ ./ executable_file# Example : to l i s t the$ ls | crated | executable | binary | f i l e | ||
hello hello . c | hello . o | |||||
# To execute the$ ./ hello | binary | f i l e | ||||
- During compiling a program, the source code can make some errors. The compiler provides debuggers that show the information of errors. The structure of showing errors: <file>:<row>:<column_letter>:<type>:<detail>
- For example, error 1:
$ gcc o hello . o c hello . c hello . c :1:18: fatal error : stdo .h: No such compilation terminated . | f i l e | . . . |
- From the example of error 1:
- Error file: hello.c
- Error line: 1
- The column of error letter: 18
- Type of error: error
- Detail info: stdo.h not found
2.2 Makefile
A makefile is a file containing a set of directives used with the make build automation tool. Most often, the makefile directs make on how to compile and link a program. Using C/C++ as an example, when a C/C++ source file is changed, it must be recompiled. If a header file has changed, each C/C++ source file that includes the header file must be recompiled to be safe. Each compilation produces an object file corresponding to the source file. Finally, if any source file has been recompiled, all the object files, whether newly made or saved from previous compilations, must be linked together to produce the new executable program.[1] These instructions with their dependencies are specified in a makefile. If none of the files that are prerequisites have been changed since the last time the program was compiled, no actions take place. For large software projects, using Makefiles can substantially reduce build times if only a few source files have changed. A makefile consists of rules in the following form:
# comment# ( note : the <tab> in the command line# is necessary for make to work)target : dependency1 dependency2 . . .<tab> command |
Where,
- target: a target is usually the name of a file that is generated by a program; examples of targets are executable or object files. A target can also be the name of an action to carry out, such as clean.
- dependency1, dependency2,: a dependency (also called prerequisite) is a file that is used as input to create the target. A target often depends on several files. However, the rule that specifies a recipe for the target need not have any prerequisites. For example, the rule containing the delete command associated with the target clean does not have prerequisites.
- command: Needed commands is used for performing rules.
For example, we have three source code files including main.c, hello.h, hello.c.
// File : main . c#include hello .hint main() {helloworld ();return 0;} |
// File : hello . h void helloworld (void );
// File : hello . c
#include hello .h
#include <stdio .h>
void helloworld (void) { printf (Hello , world
);
}
In this example, we compile .c files into object files .o, and then link all of object files into a single binary. Firstly, that is the process of compiling source code files into object files.
- o: main function in main.c calls helloworld() which is declared in hello.h. Thereby, to compile main.c, we need the information declared from hello.h. To create main.o, we need hello.h and main.c. Therefore, the rule for creating main.o is:
main . o : main . c hello .h
gcc c main . c
- o: similar to the rule of main.o, we need two files named hello.c and hello.h to create hello.o. Note that hello.c using printf() in the library stdio.h to print the output on screen. However, this is the library integrated with GCC, so we do not need to fill in the dependency of the rule.
hello . o : hello . c hello .h gcc c hello . o
- hello: Because helloworld is declared in hello.h, but it is defined in hello.c and compiled into the binary in hello.o, therefore, if the main function calls this function, we need to link hello.o with main.o to create the final binary. This file depends on hello.o and main.o.
all : main . o hello . o gcc main . o hell . o o hello
- Finally, we can add the rule of clean to remove all of object files and binaries in case of compiling an entire program.
clean : rm f | .o hello |
The final result of Makefile:
all : main . o hello . o gcc main . o hello . o o hellomain . o : main . c hello .hgcc c main . chello . o : hello . c hello .h gcc c hello . cclean :rm f .o hello |
With this Makefile, to re-compile the whole program, we call make all. To remove all of object files and binaries, we call make clean. If we need to create an object file main.o, we call make main.o. If we only call make, the default rule of Makefile is executed make all.
References
- Coding style by GNU: http://www.gnu.org/prep/standards/standards.html.
- C programming
- Brian Kernighan, and Dennis Ritchie, The C Programming Language, Second Edition
- Randal E. Bryant and David R. OHallaron, Computer systems: A Programmers Perspective, Second Edition
- More information about Vim: http://vim.wikia.com/wiki/Vim_Tips_Wiki
- Makefile:
- A simple Makefile tutorial http://www.cs.colby.edu/maxwell/courses/ tutorials/maketutor/
- GNU Make Manual https://www.gnu.org/software/make/manual/make.
3 Exercises
3.1 Questions
- Compiling a program in the first time usually takes a longer time in comparisonwith the next re-compiling. What is the reason?
- Can we use Makefile for other programming languages?
- In case of source code files located in different places, how can we write a Makefile?
3.2 Programming exercises
Two header files named findsubstr.h and readline.h have the following contents:
// findsubstr . h#ifndef FIND_SUBSTR_H#define FIND_SUBSTR_H int find_sub_string (const char str ,#endif | const char sub ); |
// readline . h
#ifndef READ_LINE_H
#define READ_LINE_H int read_line (char str );
#endif
- Writing findsubstr.c implementing find_sub_string() function: find_sub_string gets two strings including str and sub. If str contains the substring substr that is similar to sub, the program returns the first letter of substr in str. Otherwise, the program returns -1. For example, find_sub_string(abcbc, bc) returns 1, while find_sub_string(abcbc, xy) returns -1.
- Writing readline.c implementing read_line(): read_line() function gets data from stdin (keyboard), line-by-line. The content from stdin will be recorded on the parameter of this function named str. The result of read_line() is the number of read letters, or -1 if it reads EOF (end of file). For example, with the input string below:
Hello , world
Operating system
Computer Science and Engineering
After calling the function, read_line() writes Hello,world into str and returns 12. The second calling will write Operating system into str and return 16. The third calling will write Computer Science and Engineering into str and return -1.
- Writing main.c to create an executable file named mygrep that has function similar to grep command on Linux/Mac OS X shell. In detail, mygrep gets the input being a string, and then reads one line of strdin at a time (each line does not exceed 100 letters). After that, the program checks which line contains the string being entered by user, and prints these lines on screen. Student finish main.c file, then write a Makefile to compile the program at least two targets:
- all: create mygrep from other files.
- clean: remove all of object files, binaries.
// main . c#include <stdio .h>#include readline .h#include findsubstr .hint main( int argc , char argv [ ] )// Implement mygrep}#endif | { |
Note: As these exercises are graded automatically, thereby, student need to implement the program by the requirements mentioned above. Student compress all of files (.c, .h, Makefile) in a folder named Student ID by .zip format.
Makefile example
FC=gfortranCC=gccCP=cp.PHONY: all cleanOBJS = mylib . o mylib_c . o# Compiler flagsFFLAGS = g traceback heaparrays 10 I . L/usr/ lib64 lGL lGLU lX11 lXextCFLAGS = g traceback heaparrays 10 I . lGL lGLU lX11 lXextMAKEFLAGS = W wPRJ_BINS=helloPRJ_OBJS = $( addsuffix . o , $(PRJ_BINS)) objects := $(PRJ_OBJS) $(OBJS) all : myapp%.o : %.f90$(FC) D_MACHTYPE_LINUX $< c o [email protected]%.o : %.F$(FC) D_MACHTYPE_LINUX $< c o [email protected]%.o : %.c$(CC) D_MACHTYPE_LINUX $< c o [email protected]myapp: objects$(CC) $(CFLAGS) $^ $( objects ) o [email protected]clean :@echo Cleaningup . . rm f .o rm f $(PRJ_BINS) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Revision History
Revision | Date | Author(s) | Description |
1.0 | 11.03.15 | PD Nguyen | created |
1.1 | 11.09.15 | PD Nguyen | add introduction and exercise section |
2.0 | 25.02.16 | PD Nguyen | Restructure the content to form an tutorial |
2.1 | 20.08.16 | DH Nguyen | Update C and Vim to Appendix |
Reviews
There are no reviews yet.