Quick review of compiling/running stuff from the command line

| C | C++ | Java | Flex | Bison | Interpreters (Python, etc) |


Compiled (and pre-compiled) languages

This involves taking source code and turning it into machine code, and, eventally, an executable.

C/C++

The C compiler on the department machines is gcc . It's fast, ANSI-compliant (well, it can be), and it's free.

gcc [-o outfile] [-c] source_file(s)

gcc is actually a wrapper, which takes care of compiling and linking. It is pretty smart, based on the file extensions of the input files. If you give it a file.o, it knows this to be an object file, won't bother compiling it, will just link.

E.g., say you have source files main.c (the driver), poker.c (types and functions to represent a deck of playing cards), and poker.h (the interface).

To compile and link all at once:

$ gcc poker.c main.c

The resulting program file is called a.out , by default. To explicitly name it:

$ gcc -o solitaire poker.c main.c

To compile each source file independently we use the -c option, to supress linking. The output for each is an object file. We finally take all the object files and link them together:

$ gcc -c poker.c
$ gcc -c main.c
$ gcc -o solitaire poker.o main.o

This will produce an executable called solitaire . The executable bits are already set, depending on your umask (use ls -o to see this). Note: .h files are *never* compiled directly.

To run it, just enter it at the command-line (note, if you don't have the current working directory, . , in your PATH, you need to tell the shell where to find it:

$ ./solitaire args to program
return to top

C++

g++ is used to compile C++ programs. For source files it'll accept these extensions: cc cp cxx cpp CPP c++ C

return to top

Java

Java goes through a compilation phase, so, will be discussed up here. Further, it requires that you explicitly invoke the interpreter (the JVM).

Environment/Setup

In my .bash_profile I have this line (I'm assuming ksh or bash here):

export JAVA_HOME='/usr/lib/jvm/java-6-sun/'

if you're using the Ant utility, you'll want this, too:

:export ANT_HOME='/usr/share/ant-core'

Packages

I'm not getting into them here. By default, all classes in the same directory are in the same package. If class foo uses/needs class bar , then bar should be in the same directory, or in your CLASSPATH .

Compiling source files into Byte Code

Java source files ( .java ) are compiled into byte code ( .class ). The order of the compilation is unimportant. If class foo uses/needs local class bar , then bar.java will be compiled automatically. To compile:

$ javac sourceFile(s)

Running a class file inside a JVM

The JVM reads .class files, and executes a "program" (whatever that is). Note, each class may have a main method, so, you need to tell the JVM which class to start in:

$ java startClass

Note that we do not list files as arguments, just classes. Say I have poker.class and solitaire.class in the current directory. To run the solitaire class (which uses the poker class):

$ java solitaire
return to top

Code Generators (scanners and parsers)

Lex/Flexx Scanner Generator

lex (flex, from gnu) reads a specification file, and spits out C source code for compilation.

flex expects, as input, a .l file. If this file contains a main function, flex will generate source for an entire program.

Let's say I have a lex specification file called mylang.l that describes the tokens for MyLang, and it includes a test driver (a main function):

$ flex mylang.l

flex creates a C-source file called lex.yy.c , which can be compiled, if you link in the flex library:

$ gcc -omylang lex.yy.c -lfl
return to top

Yacc/Bison Parser Generator

yacc (bison, from gnu) reads a specification file, and spits out C or C++ source code for compilation. Optionally, it will also spit out a header file, for the scanner generator (flex) to use.

The scanner parses input, breaks it into tokens, hands tokens (and values of those tokens, when needed) to the parser. The scanner and the parser need to agree on what a token is. They can be defined in the bison specification file; bison can be directed to crank out a header file containing these declarations, for flex to use.

Modifying the above example, mylang.l still contains a scanner for my language, but no main. Further, the tokens aren't enumerated. Instead there will be include statement, to grab this header.

mylang.y will be the input to bison; if asked, it will output mylang.tab.c, the source for the parser, and mylang.tab.h, the header file w/the definitions that are shared w/the lexer.

So, this compilation looks like this (and yes, the order is important, even the order of the options to gcc):

 $ bison -d mylang.y 
 $ flex mylang.l 
 $ gcc -omylang mylang.tab.c lex.yy.c -ly -lfl 
return to top

Interpreters

Bash, Python, Perl

These languages (and many others) are interpreted; they take, as input, scripts (human-readable source files) and "execute" (interpret) them directly. No compilation is necessary. Some of these interpreters have an interactive mode, where you, essentially, are in a new shell, typing at a command-line (Bash, of course, and Python).

A script may be run be explicitly invoking the interpreter, and giving the scriptname as an argument. Given Bash, Perl, and Python files hello, hello.pl, and hello.py, respectively :

 $ bash hello 
 $ perl hello.pl 
 $ python hello.py 

Most reasonable shells understand the sha-bang (#!), followed by the path to the appropriate interpreter. To make a script executable, set its execution bit, and provide a sha-bang and a path on the first line of the script.

So, the appropriate first lines for the examples above (on our dept. machines) would be:

 #!/bin/bash 
 #!/usr/bin/perl 
 #!/usr/bin/python 

(If you forget a sha-bang, the current shell will attempt to interpret the script. So, e.g., a perfectly good Python programm will generate many errors in Bash, since Bash doesn't speak Python.)

Awk, Sed

Other interpreters don't expect to see a scriptname as an argument, but rather files to act upon; if commands are stored in a scriptfile, these interpreters must be told. E.g.:

 $ awk -f tg.awk 
 $ sed -f uncap 

These will then wait, expecting the input to come from the keyboard, since no input file was provided.

So, a sha-bang for the awk and sed scripts above would be:

 #!/bin/sed -f 
 #!/usr/bin/awk -f 

You could make C source code "executable", have it compile itself, but please don't do this. Not the intended use of this mechanism.

return to top