compilation file dependency

M

Michael Gaab

Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

If I use a flag that will not link the code, order of compilation is not an
issue, right? I am not that familiar with compilers so I am not sure. It
seems to me that it would not make a difference as to *which* file was
compiled *when*. Dependencies are only an issue during linking?

Thanks, Mike
 
T

Thomas Matthews

Michael said:
Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

If I use a flag that will not link the code, order of compilation is not an
issue, right? I am not that familiar with compilers so I am not sure. It
seems to me that it would not make a difference as to *which* file was
compiled *when*. Dependencies are only an issue during linking?

Thanks, Mike

The only compilation dependencies are the declarations. The
declarations must be processed before the statements. Other than
that, each "file" is treated as an independent translation unit.

The linking phase is used to resolve any external references from
a translation unit. Some tools require the files specified in
a special order before linking. All the external references
must be resolved before creating an executable image.

Many projects will have source units translated into "object"
units. The final phase consists of "linking" these object
units to form an executable image. If an object unit is not
modified, its source unit will not be translated, thus
speeding up the "build". However, some tools will only
produce debugger symbols from compiled units. :-(

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
J

Jack Klein

Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

If I use a flag that will not link the code, order of compilation is not an
issue, right? I am not that familiar with compilers so I am not sure. It
seems to me that it would not make a difference as to *which* file was
compiled *when*. Dependencies are only an issue during linking?

Thanks, Mike

Actually the C standard specifically defines 8 stages of translation,
but linking is indeed the final one. Nothing in the C standard allows
for a difference based on when or in what order individual translation
units pass through the first 7 stages.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
B

Bill Cunningham

Michael Gaab said:
Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

Great but what about the profiler. Isn't profiling in there somewhere?
 
E

E. Robert Tisdale

Michael said:
Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

If I use a flag that will not link the code,
order of compilation is not an issue, right?
I am not that familiar with compilers so I am not sure.
It seems to me that
it would not make a difference as to *which* file was compiled *when*.
Dependencies are only an issue during linking?

The compiler calls the link editor to link together the object files
left behind by the assembler.
The link editor doesn't care when the file was compiled either.
You just tell it which [object] files to link together
and it will resolve all of the links.
You just need to make sure that the link editor
knows how to find all of the object files.
The compiler passes the location of standard library archives
to the link editor along with the location of the object files
left behind by the assembler. The location of other object files
or library archives that are required to resolve all of the links
must be specified explicitly so that they can also be passed
along to the link editor.
 
J

Joona I Palaste

Michael Gaab said:
Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

Wouldn't it be possible (although not mandatory) to skip phase 3?
AFAIK preprocessing transforms C to C, and compilation transforms C to
another language. Assembly would be transforming this another language
to yet another language. Why not transform C directly into this yet
another language?
Linking would still be necessary, to allow for multiple translation
units. An unlinked object file is full of object references, that can
be thought of saying: "An object with this name, of this type, but I
don't know where it is". Linking simply finds out where these objects
are, and replaces the object references with their addresses.

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"I am not very happy acting pleased whenever prominent scientists overmagnify
intellectual enlightenment."
- Anon
 
A

Alexander Bartolich

begin Joona I Palaste:
Wouldn't it be possible (although not mandatory) to skip phase 3?

Sure.

Borland C reached it's famous spead by doing steps 1 to 3 in one go.
This had the additional advantage that the pre-processor was fully
aware of C and could handle things like sizeof(int) in #if.
 
J

Joona I Palaste

Alexander Bartolich said:
begin Joona I Palaste:

Borland C reached it's famous spead by doing steps 1 to 3 in one go.
This had the additional advantage that the pre-processor was fully
aware of C and could handle things like sizeof(int) in #if.

Thanks, this was more or less what I was thinking. I don't know anything
about Borland specifics but I thought that doing steps 2 and 3 in one go
was fully possible.
 
C

Chris Torek

[As someone else noted elsethread, the C standard specifies eight,
not four, phases -- but typically various ones are combined in a
single "user-visible" step.]

Of course, Standard C forbids "handling" sizeof(int) in #if
expressions, because by this phase keywords do not yet exist --
the only tokens are "preprocessing tokens" (pp-tokens), which are
actually more general than C tokens, and no pp-token is a keyword.
(The pp-token "defined" is recognized in #if expressions, but is
not a "keyword" in the Standard's sense.) Since both sizeof and
int are keywords, the preprocessor is not supposed to know about
them. Moreover, in #if expressions, sizeof and int match the format
allowed for identifiers, so if they are not already #define'd to
some expansion, they must behave as does any other undefined
identifier, and be considered identical to an integral constant
zero:

#if sizeof ( int ) == 2

and

#if 0 ( 0 ) == 2

are quite literally identical in this context. The latter is a
syntax violation and must draw a diagnostic. (Note that once the
one required diagnostic comes out, THEN the compiler can go back
and re-interpret the line and turn "sizeof" and "int" into keywords,
though!)

This "undefined identifier acts like 0" is sometimes quite annoying,
as it might be nice to get diagnostics for typos:

#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#define PDP_ENDIAN 3412

#define BYTE_ORDER LITTLE_ENDIAN

/* many lines later */
#if BYTE_ODRER == LITTLE_ENDIAN
... some code here ...
#endif

This translates in the same manner as "#if 0 == LITTLE_ENDIAN",
because of the transposition error in turning BYTE_ORDER into
BYTE_ODRER. (Of course, a "high quality" compiler might have an
optional warning anyway.)

Thanks, this was more or less what I was thinking. I don't know anything
about Borland specifics but I thought that doing steps 2 and 3 in one go
was fully possible.

Indeed, doing all eight translation phases in one go is *also*
possible. Separate compilation, in such a system, is handled by
recording the files to compile (and perhaps doing a pre-scan to
check for errors that might be easy to discover early). The trick
is not so much "what is possible", but rather "what is the most
practical and useful" -- and it turns out that a number of different
approaches have a number of different advantages and disadvantages.
On systems with multiple CPUs, it can be fastest, as measured by
"stopwatch time", to run many separate translation phases, one on
each CPU. A traditional Unix-like "cpp | cc1 | as" sequence can
run on three separate CPUs, with all three doing useful work at
the same time and producing results twice as fast (as measured by
stopwatch) as an all-in-one-process compiler.

As another example, the Plan 9 C compiler defers actual code
generation to link-time, so as to be able to do global register
allocation -- i.e., global variables can wind up in registers, or
a register can be shared between two or three functions even if
they are in separate .c source files -- and other such optimizations.
This turns out to be a strong disadvantage sometimes, because
compiling 100 or so modules takes, e.g., two seconds in the "compile"
stage (running on eight CPUs) and then 30 seconds in the "link"
stage (on one CPU). Had more work been done in the "compile" stage,
the eight CPUs could have taken, say, 6 seconds, leaving only two
or three seconds of work to do in the "link" stage. The code might
run somewhat slower, but one could then have a compile-time switch
for "how much to defer".
 
A

Alan Balmer

Wouldn't it be possible (although not mandatory) to skip phase 3?
AFAIK preprocessing transforms C to C, and compilation transforms C to
another language. Assembly would be transforming this another language
to yet another language. Why not transform C directly into this yet
another language?

Certainly possible. The Watcom compiler, for example, compiles to
binary. If you ask for assembler source, it invokes a dis-assembler.
 
G

Gordon Burditt

Compilation in c generally has four phases
1. Preprocessing
2. Compilation
3. Assembly
4. Linking.

If I use a flag that will not link the code, order of compilation is not an
issue, right?

It depends on the build procedure for the application in question.
For some applications (gcc comes to mind, at least some versions
of it), it is necessary to Preprocess, compile, assemble, link, and
*RUN* a program to produce a header file necessary to preprocess a
file used in the creation of another program.

On occasion the build procedures get really tricky. With compilers
themselves, it is not uncommon to have steps:

1. Compile the source using the native compiler creating stage-1.
2. Compile the source using stage-1 creating stage-2.
3. Compile the source using stage-2 creating stage-3.
4. Verify that stage-2 and stage-3 are identical (modulo things
like time stamps embedded in the executable). If it is not,
something is broken. It is not at all unusual, however, to have
stage-1 and stage-2 different.

I am not that familiar with compilers so I am not sure. It
seems to me that it would not make a difference as to *which* file was
compiled *when*.

For simple situations, this is true. When code is dynamically
generated from something else, it may not be. You may need to link
and run something in order to create the source code needed for
another part of the package. Or, the program may have to "bootstrap"
itself. Consider a klutzenmeyer compiler (which generates C as
output) written partly in klutzenmeyer.
Dependencies are only an issue during linking?

Gordon L. Burditt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top