페이지

2020년 6월 19일 금요일

Compiling Java in the Shell(Optional)

 * Java programs get compiled into object code for an imaginary CPU called the "Java Virtual Machine"(JVM). Consequently, you can't execute compiled Java code directly, You must run program that simulates a JVM and let that simulated computer execute the Java code.

* That may seem a little convoluted, but the JVM simulator is easier to write than a "true" compiler. Consequently, JVM simulators can be built into other programs (such as web browsers), allowing Java code compiled on one machine to be executed on almost any other machine. By contrast, a true native-code compiler (e.g., g++) produces executable that can only be run on a single kind of computer.

* The command to compile Java code is "javac" ("c" for compiler) and the command to execute compiled java code is "java". So a typical sequence to compile and execute a single-file Java program would b

javac -g MyProgram.java
java MyhProgram


* Unlike most programming languages, Java includes some important restrictions on the file names used to store source code.

Java source code is stored in files ending with the extension ".java".

Each Java source code file must contain exactly one public class declaration.

* The base name of the file (the part before the extension) must be the same (including upper/lower case characters) as the name of the public class it contains.

So the command

javac -g MyProgram.java

* ocmpiles a file that must contain the code:

public 
class MyProgram ...

The output of this compilatioin will be a file named MyProgram.class ( and possibly some other .class files as well).

* If we have a program that consists of multiple files, we can simply compile each file in turn:

javac -g MyProgram.java
javac -g MyADT.java

but this might not be necessary. If one Java file imports another, then the imported file will be automatically compiled if no .class file for it exists.















Understanding the Error Message

* Cascading one thing to keep in mind i that errors, especially errors in declarations, can cascade, with one "misunderstanding" by the compiler leading to a whole host of later messages. For example, if you meant to write

string s;

but instead wrote

strng s;

* You will certainly get an error message for the unknown symbol strng. However, there's also the factor that the compiler really doesn't know what types any symbol of unknown type is supposed to be an int. So every time you subsequently uses in a "string-like" mananer, e.g.,

s = s + "abcdef";

or

sting t = s.substring(k,m);

* The compiler will probably issue further complaints. Sometimes, therefore, it's best to stop after fixing a few declaration errors and recompile to see how many of the other messages need to be taken seriously.

* Backtracking A compiler can only report where it detected a problem. Where you actually committed a mistake may be someplace entirely different.

The vast majority of error messages that C++ programmers will see are


* syntax eror (missing brackets, semi-colons, etc.)
undeclared symbols
undefined symbols
type errors (usually "cannot find a matching function" complaints)

const errors

Let's look at these from the point of view of the compiler.






Capturing Compiler Output

* There are other ways to capture the output of a compiler (or of any running program). You can run the compiler within the emacs editor, which then gives you a simple command to move from error message to error message, automatically bringing up the source code file on the line cited in the error message. This works with both the UNIX and the MS Windows ports of emacs, and is the technique I use myself. Vim, the "vi improved" editor will do the same.

* Finally, in UNIX there is a command clalled "script" that causes all output to your screen to be captured in a file.
Just say

script log.txt

and all output to your screen will be copied into log.txt until you say

exit

* script output can be kind of ugly, because it includes all the control characters that you type or that your programs use to control formatting on the screen, but it's still useful.


Pipes and redirection

* We introduced pipes and redirection earlier. The complicating factor here is that what you want to pipe or redirect is not the standard output stream, but the standard error stream. So, for example, doing something like

g++ myprogram.cpp >  compilation.log

or 

g++ mayprogram.cpp | more


* It won't work, because these commands are only redirecting the standard output stream. The error message will continue to blow on by.

How you pipe or redirect the standard error stream depends on the shell you are running:

Unix, running C-shell or TC-shell

* The > and | symbols can be modified to affect the standard error stream by appending a '&' character. So these commands do work:

g++ myprogram.cpp >& compilation.log
g++ myprogram.cpp |& more


* A useful program in this regard is tee, which copies its standard input both into the standard output and into a named file:

g++ myprogram.cpp |& tee compilation.log

Linux/CygWin , running bash

* The sequence "2>&1" in a command means "force the standard error to go wherever the standard output is going".. So we can do any of the following:

g++ myprogram.cpp 2>&1 > compilation.log
g++ myprogram.cpp 2>&1 | more

and we can still use tee:

g++ myporogram.cpp 2>&1 | tee compilation.log









Error Messages

* Unfortunately, once you start writing your own code, you will almost certainly make some mistakes and get some error messages from the compiler.

This is likely to lead to two problems: reading the messages, and understanding the messages.
Capturing the Error Messages



*Unless you are a far better programmer than I, you will not only get error messages, you will get so many that they overflow your telnet/xterm window.

How you handle this problem depends upon what command shell you are running, but there are two general approaches. You can use redirection and pipes to send the error messages somewhere more convenient or you can use programs that try to capture all output from a running program (i.e., the compiler).

*We've talked before about how many Unix commands are "filters", working from a single input stream and producing a single output stream. Actually, there are 3 standard streams in most operating systems: standard input, standard output, and standard error. These generally default to the keyboard for standard input and the screen for the other two, unless either the program or the person running the program redirects one or more of thes streams to a file or pipes the stream to / from another program.




Linkage Flags

-L directory                 Add directory to the list of places searched for precompiled libraries.
-llibname                   Link with the precompiled library liblibname.a


Compilation Flags

-c                               compile only, do not link
-o filename                  Use filename as the name of the compiled program
-Dsymbol-value             Define symbol during compilation.
-g                              Include debugging information in compiled code
                                 (required if you want to be able to run the gdb degugger).
-O                              Optimize the compiled code (produces smaller, faster programs
                                 but takes longer to compile)
-l directory                  Add directory to the list of places searched when a "system"
                                include (#include ...) is encountered.