Topic: Preventing Unwanted Recompiles
Author: jones@cais.cais.com (Ben Jones)
Date: 1 Aug 1994 15:05:39 GMT Raw View
John Max Skaller (maxtal@physics.su.OZ.AU) wrote:
: In article <31bd9m$t1s@sun.cais.com> jones@cais.cais.com (Ben Jones) writes:
: >John Max Skaller (maxtal@physics.su.OZ.AU) wrote:
: >
: >: This mechanism isnt really a module system -- but its pretty close!
: >
: >This is very close to what I have in ARC++:
: >
: Unfortunately, I like using integrated environments,
: which do not take kindly to pre-processing of the input.
: I would dearly love to have integrated literate programming.
: Does ARC++ do a full error diagnosis of the input?
: (If it does, its hookable, otherwise it isnt)
Yes it does. As far as being hookable, that depends on the integrated
environment. For example:
* Last time I looked, Symantec C++ on the Macintosh required "drop-in"
translators to use a very Symantec-specific "main" routine and there
didn't seem to be any good way to invoke the C++ compiler from a
translator.
* Borland C++ 4.0 lets you indicate what file extensions invoke what
translators and it lets us call a program which spawns ARC++ and then
"bc4" (the command-line compiler).
ARC++ generates #line directives in its output source. Most debuggers
will be able to map the object code back into the original source this
way but some don't.
ARC++ also includes a facility for processing a renamed header file to
generate the header actually included by regular C++ programs. This makes
it possible to achieve dramatic reductions of unnecessary recompilation
without changing anything except the makefile/project file.
Ben Jones
jones@arsoftware.arclch.com
Author: clamage@taumet.Eng.Sun.COM (Steve Clamage)
Date: 28 Jul 1994 19:56:03 GMT Raw View
In article Io3@ukpsshp1.serigate.philips.nl, baynes@ukpsshp1.serigate.philips.nl (Stephen Baynes) writes:
>
>Yes the designers of C++ missed a big improvement when they decided to
>continue with include files. I think sorting out extern/module scope properly
>would have added more to C++ over C than many of the other things it has
>added.
Discussion of this sort are always fun. But I strongly recommend that people
read "The Design and Evolution of C++", Stroustrup, 1994 before posting long
discussions about how C++ could or should have been designed. It isn't
usually the case that Stroustrup didn't think of it (whatever "it" is),
or that he didn't know how to implement it. Most often you are looking
at a deliberate engineering compromise. C++ was intended to be widely
implementable, easy to port to new systems, and easy to adapt existing
C programs to.
Ada, to make a common comparison, has lots of nice features many people
(especially in this thread) wish C++ had. Ada had the backing of the
US government, and was REQUIRED for use in many application areas. Eiffel
and Modula-3 have lovely, clean designs, and many nice properties. C++
had no official backing, and the only people who used it were those who
wanted to.
How widely available are Ada compilers, and how many applications written
in Ada? Eiffel? Modula-3? C++? (rhetorical questions). This indicates,
I think, the real-world relative importance of ideal design versus the kind
of compromises Stroustrup selected.
---
Steve Clamage, stephen.clamage@eng.sun.com
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Fri, 29 Jul 1994 07:38:21 GMT Raw View
In article <31352q$a1p@sun.cais.com> jones@cais.cais.com (Ben Jones) writes:
>There are those who argue that it is good engineering to separate the
>implementation from the interface. I agree but C++ carries it to an
>extreme. Look at the Ada language. You declare a "package". The
>compiler extracts the public interface of that package and then makes
>it available to other modules in the project which import that package
>using the "with" statement. Ada also allows you to separate the
>interface and implementation.
Eiffel does the same.
>
>Suppose that you could say the following in C++:
>
> export class name { ... };
> ..
> import name;
Actually, I propose something slightly different.
unit fred; // name translation unit.
using unit fred; // include interface of the unit.
This requires less changes to the C++ language an compilation model.
Existing "include" files could be compiled. You could
implement whole classs with inline methods and just "use" it.
The _compiled_ symbol table for the class is loaded, unless
the file has changed, which triggers a recompile (recursively).
This mechanism isnt really a module system -- but its pretty close!
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: jones@cais.cais.com (Ben Jones)
Date: 29 Jul 1994 16:48:49 GMT Raw View
Steve Clamage (clamage@taumet.Eng.Sun.COM) wrote:
: In article Io3@ukpsshp1.serigate.philips.nl, baynes@ukpsshp1.serigate.philips.nl (Stephen Baynes) writes:
: >
: >Yes the designers of C++ missed a big improvement when they decided to
: >continue with include files. I think sorting out extern/module scope properly
: >would have added more to C++ over C than many of the other things it has
: >added.
: Discussion of this sort are always fun. But I strongly recommend that people
: read "The Design and Evolution of C++", Stroustrup, 1994 before posting long
: discussions about how C++ could or should have been designed. It isn't
: usually the case that Stroustrup didn't think of it (whatever "it" is),
: or that he didn't know how to implement it. Most often you are looking
: at a deliberate engineering compromise. C++ was intended to be widely
: implementable, easy to port to new systems, and easy to adapt existing
: C programs to.
: Ada, to make a common comparison, has lots of nice features many people
: (especially in this thread) wish C++ had. Ada had the backing of the
: US government, and was REQUIRED for use in many application areas. Eiffel
: and Modula-3 have lovely, clean designs, and many nice properties. C++
: had no official backing, and the only people who used it were those who
: wanted to.
: How widely available are Ada compilers, and how many applications written
: in Ada? Eiffel? Modula-3? C++? (rhetorical questions). This indicates,
: I think, the real-world relative importance of ideal design versus the kind
: of compromises Stroustrup selected.
That is why I decided to extend C++ rather than inventing yet another
computer language. For what their worth, all of the extensions I've
advocated are implemented and available in ARC++ which piggybacks onto
C++ compilers. For more information, go to the anonymous FTP:
www.clark.net: /pub/arsoftwa/arc++
and get the file "ARC++.txt".
Ben Jones
jones@arsoftware.arclch.com
Author: jones@cais.cais.com (Ben Jones)
Date: 29 Jul 1994 17:12:22 GMT Raw View
John Max Skaller (maxtal@physics.su.OZ.AU) wrote:
: In article <31352q$a1p@sun.cais.com> jones@cais.cais.com (Ben Jones) writes:
: >There are those who argue that it is good engineering to separate the
: >implementation from the interface. I agree but C++ carries it to an
: >extreme. Look at the Ada language. You declare a "package". The
: >compiler extracts the public interface of that package and then makes
: >it available to other modules in the project which import that package
: >using the "with" statement. Ada also allows you to separate the
: >interface and implementation.
: Eiffel does the same.
: >
: >Suppose that you could say the following in C++:
: >
: > export class name { ... };
: > ..
: > import name;
: Actually, I propose something slightly different.
: unit fred; // name translation unit.
: using unit fred; // include interface of the unit.
: This requires less changes to the C++ language an compilation model.
: Existing "include" files could be compiled. You could
: implement whole classs with inline methods and just "use" it.
: The _compiled_ symbol table for the class is loaded, unless
: the file has changed, which triggers a recompile (recursively).
: This mechanism isnt really a module system -- but its pretty close!
This is very close to what I have in ARC++:
export package fred { ... }; // Translation unit "fred" enclosed in {}
...
use fred;
The "package", by the way is sort of like "namespace" except that it
is a class in which all members are static and it can inherit classes
and packages. An inherited class becomes an anonymous static member
of a class. If you later decide you want to instance the package,
you simply change it to "class".
The current implementation of ARC++ generates "name.ph", a text file, as
the interface. If there is a previously generated "name.ph", the two
are compared. If there is no difference, the new one is not saved.
If there is a difference but not one which would trigger recompilation,
the new one is back-dated. The only differences which should trigger
recompilation are:
* Symbols were deleted.
* The type or value of a symbol changed.
* The position of a non-static member changed.
* The position of a virtual function changed.
* The body of an inline function changed.
The "use" command will check for a ".h" file if it cannot find a ".ph"
file.
ARC++ also has a special mode where it processes an ordinary header file to
generate the header file actually #included by modules in a project. It
compares the old generated header to the new one (also checking for
preprocessor #defines) and backdates the new one appropriately.
The generation of the header file can then be included as a node in
a makefile or project file.
For more information, go to the anonymous FTP:
www.clark.net: /pub/arsoftwa/arc++
and get the file "ARC++.txt".
Ben Jones
jones@arsoftware.arclch.com
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 30 Jul 1994 15:57:27 GMT Raw View
In article <31bd9m$t1s@sun.cais.com> jones@cais.cais.com (Ben Jones) writes:
>John Max Skaller (maxtal@physics.su.OZ.AU) wrote:
>
>: This mechanism isnt really a module system -- but its pretty close!
>
>This is very close to what I have in ARC++:
>
Unfortunately, I like using integrated environments,
which do not take kindly to pre-processing of the input.
I would dearly love to have integrated literate programming.
Does ARC++ do a full error diagnosis of the input?
(If it does, its hookable, otherwise it isnt)
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
Author: baynes@ukpsshp1.serigate.philips.nl (Stephen Baynes)
Date: Thu, 28 Jul 1994 12:04:45 GMT Raw View
Ben Jones (jones@cais.cais.com) wrote:
: There are those who argue that it is good engineering to separate the
: implementation from the interface. I agree but C++ carries it to an
: extreme. Look at the Ada language. You declare a "package". The
: compiler extracts the public interface of that package and then makes
: it available to other modules in the project which import that package
: using the "with" statement. Ada also allows you to separate the
: interface and implementation.
: The nice thing about the way Ada works is that the development
: environment then becomes the arbiter of what needs to be recompiled.
: In C++, you are encouraged to put the class declaration in a header
: file and then #include that header everywhere the class is referenced.
: By its very nature, C++ forces the programmer to be careful not to
: modify the header file to often or a recompile will be triggered for
: every module which #includes that header. Indirection and other
: techniques are just that much more manual labor to be applied to
: a task which is very easily automated.
-snip-
Yes the designers of C++ missed a big improvement when they decided to
continue with include files. I think sorting out extern/module scope properly
would have added more to C++ over C than many of the other things it has
added.
A proper export facility would get round one of my pets hates with C++ - that
class names are effectively global. [Because classes need invisible code/data
to support them and there is no way to tell the compiler not to give these
extern scope. You want the compiler to make the extern if they are in an
include file, but not if it is in the main source file.] The effect of this is
you want a class that is only used by a single module, you still have to treat
it as if it is used globally which does not do your modularity much good.
--
Stephen Baynes baynes@mulsoc2.serigate.philips.nl
Philips Semicondutors Ltd
Southampton My views are my own.
United Kingdom
Author: jones@cais.cais.com (Ben Jones)
Date: 26 Jul 1994 14:03:06 GMT Raw View
There are those who argue that it is good engineering to separate the
implementation from the interface. I agree but C++ carries it to an
extreme. Look at the Ada language. You declare a "package". The
compiler extracts the public interface of that package and then makes
it available to other modules in the project which import that package
using the "with" statement. Ada also allows you to separate the
interface and implementation.
The nice thing about the way Ada works is that the development
environment then becomes the arbiter of what needs to be recompiled.
In C++, you are encouraged to put the class declaration in a header
file and then #include that header everywhere the class is referenced.
By its very nature, C++ forces the programmer to be careful not to
modify the header file to often or a recompile will be triggered for
every module which #includes that header. Indirection and other
techniques are just that much more manual labor to be applied to
a task which is very easily automated.
Suppose that you could say the following in C++:
export class name { ... };
Within the braces, declare functions with or without bodies but mark
inline functions as such. Let members be initialized. Non-static
initializations would imply default operations in the constructor
functions.
Then let the C++ compiler extract the interface from the class
declaration. Let other modules say:
import name;
Since the header is automatically extracted, the compiler can take steps
to prevent unnecessary recompilations of the importing modules:
1) If the interface doesn't change, don't recompile. The export
process can eliminate:
* Comments
* Non-inline function bodies.
* Initialization of members.
so any changes to these won't trigger a recompilation.
2) If the interface doesn't change in ways that would affect previously
compiled modules, don't recompile those modules. It just so happens that
the only things which could possibly affect previously compiled modules are:
* Removing a symbol definition (which might have been referenced).
* Changing the type or relative position within the object of a
non-static member (since object code would have taken these
into account).
* Changing the position of a virtual function declaration in the
most base class in which it was declared (since the object code
would use that position number to index into the vtable).
* Changing a function prototype or inline function body (since that
would affect generated code).
What this means is that the following changes can be made to the exporting
module without triggering unnecessary recompilation:
* Edit comments, function bodies, initializations.
* Add any non-virtual support functions.
* Override any virtual functions (since this would not change the position
of the function in the vtable.
* Add any static members.
* Add any members which don't change the positions of existing members
or the size of the object (You could reserve expansion space by using
an anonymous union containing an anonymous struct and an array which
would reserve a certain amount of space).
Another advantage of having "export" would be that there would be no
ambiguity about which module owns the initializations and virtual
function table of a given class.
Ben Jones
jones@arsoftware.arclch.com