The CS 6410 labs require you to program C/C++ on Linux/UNIX machines. This document should help you on your way with reading manual pages, compiling C/C++ programs, and understanding Makefiles that we will provide you with.
If you need to find information on Unix commands, system calls,
configuration files, etc., then man
is your friend. For
example,
% man socket
gives you the man page for the socket
system call.
(man man
gives you the manual page for man
itself.) Note that it may be necessary to specify which section of
the manual you wish to read. For example, man read
may
yield the man page for the wrong read
---the shell
read
rather than the read
system call. If
this is the case, try man 2 read
. In this case,
2
specifies the manual section; there are 8 sections. You
can find relevant man pages (and what section they are in) using
man -k
. For example,
% man -k read
shows a one-line description for each man page that has the word ``read'' in the description.
A compiler takes one or more source files and produces object files that contain machine code. Object files contain machine code and usually have a .o extension. C source files usually have a .c extension and g++ files usually have a .C or .cc extension. Object files may have undefined symbols (names of functions or global variables); linking object files into an executable resolves these undefined symbols. Note that one of the object files must have a main() function to create an executable.
Object files can be linked together to form an executable, provided that one (and only one) of the object files defines a main() function.
An executable is similar to an object file in that it contains machine code, but an executable contains some additional bits that allow the operating system to start the program and run it.
Compiling a source file into the equivalent object file is done
using g++ -c
. For example:
% g++ -c hello.C -o hello.o
The -c flag indicates pure compilation without
linking. Even if hello.C defines main()
, the
resulting hello.o is not executable. To compile a source
file into an executable, omit the -c flag:
% g++ hello.C -o hello
This creates an executable hello. Note that
g++ will bark at you if you try to create an executable
without a definition of main()
.
Note that all these examples assume you are compiling g++ files.
Use gcc
instead of g++
if you are compiling
plain old C files.
Multiple object files can be linked together into one executable. Suppose we have the following files:
#ifndef __COMMON_H #define __COMMON_H void hello(); void bye(); #endif // __COMMON_H
#include <stdio.h> #include "common.h" void hello() { printf("hello!\n"); }
#include <stdio.h> #include "common.h" void bye() { printf("bye!\n"); }
#include "common.h" int main() { hello(); bye(); }
To turn these files into a working executable, do:
% g++ main.C hello.C bye.C -o hellobye
This compiles main.C, bye.C, and
hello.C and links them together into an executable called
hellobye. The header file common.h declares---but
does not define---hello()
and bye()
so that the
compiler can compile main.C, without knowing the details
of their implementation.
Linking is only possible when no two object files try to define
C or g++ functions or global variables
with the same name. For example, try declaring a
variable int foo
in both hello.C and
bye.C. Compiling each file separately is no problem, but
linking fails with a multiple definition of `foo' error.
The same is true for functions. Depending on what you want, you can
avoid this problem in one of a number of ways:
foo
, you can declare one of them as extern
int foo
.foo
, then declare
one or both of them as
static int foo
. Keyword static
limits the scope of the declaration to just the current file.While doing the CS 6410 labs you probably won't need to create your own libraries, but the Makefile you get from us will cause your files to be linked with some of our libraries. This section gives a quick overview on how to create and use libraries.
You can create a small library using hello.o and bye.o by doing:
% ar cru libhellobye.a hello.o bye.o
This creates a library libhellobye.a. Now we can recompile and relink main.C with this new library.
% g++ main.C -L. -lhellobye -o hellobye
This compiles main.C and links the result with libhellobye.a into an executable called hellobye. The -lname flag tells g++ to search for a library called libname.a. The -Ldir flags tells g++ to add directory dir to the search path when looking for a library. In our case, libhellobye.a is in the current directory, hence -L..
While doing the CS 6410 labs you probably won't need to create your own Makefiles from scratch, because we will give them to you. However, you may need to modify them. This section gives a quick overview of what a Makefile is and how it is used.
A Makefile is used in conjuction with GNU make
and
describes how different source and header files in a project relate
and how to compile and link them. A Makefile usually bears the
meaningful name Makefile and its contents are probably
roughly similar to this example:
hellobye : libhellobye.a main.o g++ main.o -L. -lhellobye -o hellobye libhellobye.a : hello.o bye.o ar cru libhellobye.a hello.o bye.o # this command puts hello.o and bye.o in a library libhellobye.a hello.o : hello.C common.h g++ -c hello.C -o hello.o bye.o : bye.C common.h g++ -c bye.C -o bye.o main.o : main.C common.h g++ -c main.C -o main.o clean : rm -f *.a *.o hellobye
This Makefile has 6 sections. Each section describes a dependency on the first line and some action on the second. A dependency consists of a target file (before the colon) and prerequisite files (after the colon). Lines starting with # are comments.
When you run make
, it will execute a target's action
if any of the prerequisite files have been modified since
the target was last modified. make
executes the
action in much the same way as if you had typed it to the shell.
make
only tries to make sure that the very first
target in the Makefile is up to date. However,
if the first target depends on other targets, make
may end up executing multiple actions.
The first section in the Makefile above states that the file hellobye depends on libhellobye.a and main.o. If either libhellobye.a or main.o is newer than hellobye, then hellobye is rebuilt. Building the whole project is now as simple as typing
# make
If you write your Makefile correctly, make
will only compile
and link those parts of a project that have changed since the last
make
. If your project is big and the full compile/link
process takes a long time, then make
is your friend. It saves
time.
Notice that the last section in this Makefile is not a real dependency, but allows the user to conveniently call
# make clean
to remove all object files, the library, and the executable.
Makefiles can get pretty complicated, but this introduction should be sufficient for your CS 6410 needs.
You may find it useful to keep track of different versions of your work as you progress. A version control system allows you to checkpoint your work and may help you track down regressions in your code. The change log tracked by the VCS can serve to remind you what your intention was in making a particular change days or weeks afterwards.
You can easily install popular version control systems
(CVS,
Subversion,
Git, and
darcs) on the EC2 machines
(e.g. on debian based distributions like Ubuntu type apt-get install cvs
).
If you are familiar with one of these systems, you are welcome to use it.
If you are interested in learning one, you should be able to start relatively quickly.
There are massive amounts of documentation for each of these tools available online.