![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Darren New <dne### [at] san rr com> wrote:
> >> Warp wrote:
> >>> How do you resolve this? That's right: You tell the compiler which files
> >>> it needs to compile.
> >
> >> Nope. You tell the compiler which *object* file goes with the appropriate
> >> *source* file.
> >
> > Yeah, huge difference.
> And *this* is exactly why these arguments go on for so long.
> I can't tell whether you're being a truly masterful troll, or whether your
> misplaced egoism has completely blinded you.
> I make a comment. You strawman an argument against it. I point out that
> you're putting words in my mouth. Instead of saying "OK, I was wrong in my
> assertion, I don't see the difference, please explain again why it matters",
> you say "I wasn't wrong, because even tho I was *factually* incorrect, it
> doesn't make any difference, because there couldn't possibly be any
> difference, so I'm really right anyway."
I don't understand what you are talking about.
I said, "you need to tell the compiler which files it should use to
compile the program", and you answer with "no, you tell the compiler
which object file goes with the appropriate source file".
What exactly is the difference here? You are telling the compiler which
source files the program is composed of. What do the object files have
anything to do with this? In fact, you are making it sound *more* complicated
than it needs to be, (Why exactly would I need to specify which object
file goes with what source file? I don't care. Let the compiler figure
those things out. You are in fact making it sound like compiling a C#
program is actually more complicated than compiling a C++ program, if
you need to be explicitly pairing object files with source files.)
Whatever the building process might be, you still need to tell the
compiler in one way or another where your source files are, and that's
the point. If you have two files with the same name, you tell the compiler
which one of them to use. (Your original argument was, after all, what
happens if you have to C files of the same name.) I don't understand what
the "object files" have anything to do with this.
Also, I don't understand what "factually incorrect" thing I have said.
> And you know, for someone who distinguishes "invoking the compiler
> preprocessor" from "invoking the compiler", saying there's no significant
> difference between source code and object code just doesn't ring true.
Somehow it seems that you are talking about something else entirely.
This whole "you tell the compiler which files to compile" argument started
from your example of two C files with the same name. You have now made a
strange jump to some C# object files, and I have no idea why or how it's
related. It seems that you are thinking about something else entirely.
> > Are you saying that it's impossible to have a C# source file with the
> > same name in two different directories and which implement a class with
> > the same name?
> I'm saying that if you do, it doesn't matter, because your compilation isn't
> looking at that source code.
And why not? That's right: Because you only told the compiler to use
*one* of those files, rather than both. It's your decision which one.
You don't seem to get my point here. My point is that your argument about
the two C files with the same name is bogus. In other words, a bad example
and a bad argument.
It's anybody's guess what object files have anything to do with this
whole thing.
> >> Do you really not see the difference between saying "each time I compile
> >> something, I have to pick which source file to compile" and saying "each
> >> time I compile something, I have to pick the right source files that go with
> >> the corresponding libraries of every library I'll eventually link this with"?
> >
> > Not really.
> OK. Then I'm afraid I can't explain it to you.
Well, I just can't see the difference between the two sentences you wrote.
They are saying the same thing.
> > You have to specify which source files the program is
> > composed of.
> It's not my program.
There's a difference between "the" and "my". I wrote "the".
> I've never written a crypto library, nor have I written
> a video codec. But I've compiled the source code for parts of those
> libraries into every C program I've ever written that used them.
So you tell the compiler which source files it should use to compile
the program. So? Isn't that what I'm saying?
> > Your example of the same C file being in two different directories is simply
bogus.
> Why?
Because you tried to use it as some kind of example of why it's "not
possible to figure out dependencies by looking at the source codes only"
and that you need to specify where the compiler has to look for those
sources, and this, apparently, is some kind of "problem" in C.
My answer, which you still don't seem to understand, is that this has
nothing to do with C or any particular language. If you have a file with
the same name in more than one place, you need to tell the compiler which
one it should use. This is obviously true for any language. C isn't somehow
inferior because of this.
Then you start rambling something strange about object files.
> > It has nothing to do with C particularly.
> It is much more common in C than in other languages, I've found. YMMV, but
> that doesn't make me wrong.
You are blaming C for a somewhat common bad practice among C programmers?
If I were to go that path, I would say that C# and ASP are really crappy
languages, judging from what I have seen at thedailwtf. (Of course this
argument would be completely fallacious.)
> >> Indeed, when I use the C# equivalent of stdio (or any other third-party
> >> library), I don't need any source code I didn't write myself, nor do I need
> >> to specify where to find the libraries. I merely say which version of what
> >> implementation I want.
> >
> > And when I write C++, same thing. So what?
> So, when you use boost, you don't need to compile any source code to any
> software you didn't write yourself? Sorry, that's just a lie. I've looked at
> the boost code. It's mostly source code. And you know what? I've worked on
> projects where I've needed two different versions of boost in the same code,
> neither version of which was in the repository. It sucks. It's very
> difficult to get right.
You said, and you quoted it above: "when I use the C# equivalent of stdio",
to which I responded "and when I write C++, same thing". I don't think I
heve the source code for stdio even installed in my linux system.
Also, if talking about template code, in a different subthread I actually
advocated the advantages of having such code in header files, and mentioned
<vector> as an example of this.
I don't understand why you consider it a bad thing that eg. the boost
libraries are mostly in the header files (often because they are fully
templated and cannot be placed in precompiled libraries due to
compiler-technical reasons). So what if I need to "include someone else's
code in my program"? (The biggest issue with that for me would be the
usage license of the library, but that's completely tangential to the
subject.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Let's take a better example: Every time I want to use std::vector,
> > I have to #include <vector> in the source file where I want to do so.
> > Is there any advantage to this?
> For C++ and templates, yes. Altho (and I know you'll go apeshit over this
> comment) C# manages not to need the source code for generics like that.
It's not so much a question of making it work as much as a question of
optimization.
For example, if you create your own class or struct which has a few
member variables, and then you instantiate a vector of that type, it will
be quite space-optimal: Every element in the vector will only consume as
much memory as the size of the object. There is no ancillary data needed.
Of course the second efficiency advantage is that the compiler will be
able to inline code and to perform type-specific optimizations (for example,
sorting a vector of ints will be very efficient because the compiler will
be able to inline the element comparisons directly into the sorting routine
as a machine code register comparison opcode).
This still doesn't make it technically impossible to compile templates
into precompiled libraries. In fact, the current C++ standard defines such
a possibility (the so-called "export templates"). The only major problem
with export templates is that it's technically extremely difficult and
laborious to implement in compilers, which is why there's only one major
C++ compiler that supports it (and it's because of this that, faced with
the harsh realities of the marketplace, the standardization committee is
going to drop the feature from the next standard).
The problem is that templates need to be instantiated in the context
where they are used. Or in the case of export templates, the context needs
to be "brought" where the export template is being instantiated. This is
an extremely complicated thing to do.
For example, you could have this in one source file:
//--------------------------------------------------------
namespace
{
// 'Point' is a type local to this compilation unit
struct Point { int x, y; }
std::vector<Point> points;
}
//--------------------------------------------------------
And then you could have this in another source file:
//--------------------------------------------------------
namespace
{
// 'Point' is a type local to this compilation unit
struct Point { double x, y; }
std::vector<Point> points;
}
//--------------------------------------------------------
With regular templates this isn't any problem at all, and it's trivial
for compilers to handle. With export templates the problem is enormously
harder. (Basically, the 'vector' template class, if it was an export
template, would be instantiated at the linking stage in its own compilation
unit, with its own context, but it needs to also know the context in which
it was used, as above. The compiler needs to somehow carry all the context
information to the template instantiation process at the linking stage.)
And as far as I understand, the above example is just one of the *minor*
complexities in this whole thing.
On the other hand, it's not technically impossible, and it has been done,
so in principle it would be possible to have precompiled template libraries.
(They would only be slightly less efficient because functions which are not
implemented in the header file would not be inlined. OTOH this isn't different
from regular functions.)
As far as I understand "generics" do not handle things "inline" and
"by value", but instead simply handle references, and basically the only
thing they do is that they allow you to skip doing explicit upcasting.
Generics do not allow things like template metaprogramming, template
specialization, and such. (Well, this at least with Java generics. I have
no idea about C#. Also, at least in Java, you can't handle primitive types
with generics.)
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Let's take a better example: Every time I want to use std::vector,
> > I have to #include <vector> in the source file where I want to do so.
> Or, to phrase it differently:
> vector.hpp is a standard file from the standard library. Why the hell are
> you compiling it, over and over, every time you compile your program?
The advantage is that the end result is much more efficient (both
speedwise and memorywise) because it allows the compiler to perform
heavy-duty optimizations on the included code based on the types you are
using as well as many other things. (Of course that's not the *original*
reason to have include files, but it's a nice side-effect of them that
makes them actually quite useful.)
(Curiously, the next C++ standard will include a feature called "extern
template" which allows you to defer the compiling of the templated code
into one single compilation unit. This doesn't have efficiency advantages,
but it can speed up compilation and make object files smaller. It's still
not the same thing as an "export template" though, and shouldn't be confused
with it.)
> Doesn't it strike you as a bit odd that standard libraries that come with
> the compiler still get compiled on your CPU over and over?
Not for templated code, no. As for non-templated code, they usually come
in precompiled dynamically loadable versions (or statically linkable, if
you want).
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> No, I don't. You are writing about library sources now, and I have no
> idea what you are talking about.
So you don't think stdio.h is source file?
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > No, I don't. You are writing about library sources now, and I have no
> > idea what you are talking about.
> So you don't think stdio.h is source file?
Yes, it's a source file containing declarations.
When you talked about needing "the source for the library", it sounds
like you need the entire library in source code form if you want to use
it in your program.
While header files are source code like anything else from the point of
view of the compiler, it's not usually what is meant by "*the* source code
of the library", which would be *all* the source files needed to create
the precompiled library. When you say "you need *the* source code for
stdio", my answer is "no, I don't". Yes, I need the declarations, but
I don't need the full source code.
I know that you didn't mean the full source code, but you should try
to use common terminology, and "the source code" is not the common term
for "header files".
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> What exactly is the difference here?
I have explained it repeatedly, but it basically breaks down to "I don't
have to compile object code."
> (Why exactly would I need to specify which object
> file goes with what source file? I don't care.
So there's no need to use the right .h files for a given .so file?
> you need to be explicitly pairing object files with source files.)
You need to specifically pair object files you're *linking* against with the
source files you're compiling. But you don't have to find any *source* code
that came with the object code you're linking against.
> Whatever the building process might be, you still need to tell the
> compiler in one way or another where your source files are, and that's
> the point.
Right. And in C, I have to tell the compiler one way or another where *your*
source files are too.
> (Your original argument was, after all, what
> happens if you have to C files of the same name.)
No, that was a trivial oversimplification to try to explain what I meant
when I said the source code isn't sufficient to know what the dependencies
are. Don't apply it to other situations.
> Also, I don't understand what "factually incorrect" thing I have said.
I said "No. The programming language is such that it is impossible to figure
out by looking at the source code what the dependencies are on other source
code."
This is factually true. You argued "If that were true, then it would be
impossible to compile the program."
Then I gave an example of source code from which you could not deduce the
dependencies, and yet which is possible to compile.
Indeed, you're *making reference* to that example right here.
>> And you know, for someone who distinguishes "invoking the compiler
>> preprocessor" from "invoking the compiler", saying there's no significant
>> difference between source code and object code just doesn't ring true.
>
> Somehow it seems that you are talking about something else entirely.
> This whole "you tell the compiler which files to compile" argument started
> from your example of two C files with the same name. You have now made a
> strange jump to some C# object files, and I have no idea why or how it's
> related. It seems that you are thinking about something else entirely.
OK. If you can't read what *i'm* writing about a non-C language without
running it through your C filter and changing the words I'm saying into
something else, then I can't really explain it to you.
If you're going to change where I say "object code" into "source code" and
when I say "library" into "include file" and where I say "link" you say
"compile" and so on, then I'm just not going to be able to explain it to
you. I tried my best, including a couple of detailed and thought-out posts
which you still haven't commented on or said anything to imply you read.
>>> Are you saying that it's impossible to have a C# source file with the
>>> same name in two different directories and which implement a class with
>>> the same name?
>
>> I'm saying that if you do, it doesn't matter, because your compilation isn't
>> looking at that source code.
>
> And why not? That's right: Because you only told the compiler to use
> *one* of those files, rather than both. It's your decision which one.
No. It's because the equivalent code in C# would not look at *EITHER* of
those two source files.
> You don't seem to get my point here. My point is that your argument about
> the two C files with the same name is bogus. In other words, a bad example
> and a bad argument.
It was merely an argument to prove your assertion that having that is
impossible is bogus.
> It's anybody's guess what object files have anything to do with this
> whole thing.
Since it's pretty much the entire point I'm making, I'm not surprised this
is going around and around. You're taking an example I'm using to show one
point and saying "that is nonsense in the context of this other point!"
Well, yes, it's because it's a nonsense example to prove a very simple and
specific point, because you seem to be having trouble following the overall
discussion in a larger way.
>>>> Do you really not see the difference between saying "each time I compile
>>>> something, I have to pick which source file to compile" and saying "each
>>>> time I compile something, I have to pick the right source files that go with
>>>> the corresponding libraries of every library I'll eventually link this with"?
>>> Not really.
>
>> OK. Then I'm afraid I can't explain it to you.
>
> Well, I just can't see the difference between the two sentences you wrote.
> They are saying the same thing.
Here's a simple summary: When I compile code I wrote in C# or Java or etc, I
don't compile code I didn't write.
When I compile code I wrote in C, I almost invariably wind up also compiling
code I didn't write at the same time in the same compilation unit.
>>> You have to specify which source files the program is
>>> composed of.
>
>> It's not my program.
>
> There's a difference between "the" and "my". I wrote "the".
And now you're trolling. You're here *intentionally* ignoring the point I'm
making. You're saying "I don't understand the difference between your source
code and my source code." I say "I don't want to compile *your* source
code." You say "You have to compile *the* source code." Do grow up.
>>> Your example of the same C file being in two different directories is simply
bogus.
>
>> Why?
>
> Because you tried to use it as some kind of example of why it's "not
> possible to figure out dependencies by looking at the source codes only"
Yep! That was the point of the example. Why is it bogus.
> My answer, which you still don't seem to understand, is that this has
> nothing to do with C or any particular language.
Yet, surprisingly, you said "If that were true, then it would be impossible
to compile the program." That's all that example was about: showing you that
your assertion that you can deduce the dependencies solely from the source
code is bogus.
You made a factually incorrect statement. I showed you a trivial example of
how you are factually incorrect. You then denied that you were incorrect
*and* complained that the example was obviously stupid. Now you keep
bringing it up for some reason. Nice moves, Bats!
> If you have a file with
> the same name in more than one place, you need to tell the compiler which
> one it should use. This is obviously true for any language. C isn't somehow
> inferior because of this.
I didn't say it is.
>>> It has nothing to do with C particularly.
>
>> It is much more common in C than in other languages, I've found. YMMV, but
>> that doesn't make me wrong.
>
> You are blaming C for a somewhat common bad practice among C programmers?
Yep! Altho for some reason you seem to think there's some pejorative
"blame" going on here. I also blame any other language with disconnected
and non-modular declarations and defintions. (I don't like FORTRAN block
common statements either, for example, for the same sort of reason, altho
without macros it's somewhat less of a problem in fortran.)
> If I were to go that path, I would say that C# and ASP are really crappy
> languages, judging from what I have seen at thedailwtf. (Of course this
> argument would be completely fallacious.)
Feel free! It would be interesting to hear some of the criticisms of C#
technology.
> You said, and you quoted it above: "when I use the C# equivalent of stdio",
> to which I responded "and when I write C++, same thing". I don't think I
> heve the source code for stdio even installed in my linux system.
So, what happens when you #include <stdio>? Sorry, I thought stdio.h is
source code, yes? I mean, there are precompiled headers, but that's just
running parts of the compiler first and dumping the symbol table, afaik.
Now I'm really curious. What does your stdio.h look like? Cause mine's full
of C source code.
(And yes, I actually trusted you enough that I actually fired up Linux to
check. :-> Plus, there are three stdio.h files under my /usr/include right
now, so the whole idea that you might not know which is the right one isn't
as far-fetched as one might think.)
> So what if I need to "include someone else's code in my program"?
There's a whole slew of problems this enables. No, you might not run into
any of these problems. But let me list again what they might be:
1) There's no way to know which header files go with which object files.
Look at the man page for open() and tell me how you would figure out which
header files you need to include for that to work.
If you compile against object code declarations instead of source code
declarations, you don't have this problem. Instead of saying "I'm using the
version of open() defined in sys/types.h and sys/stat.h and fcntl.h", you
just say "I'm using the version of open() defined in crt.o". Instead of
saying "I'm using the MPEG decoder as specified in RMinit.h, RMerr.h,
RMinp.h, RMthis.h, RMthat.h, RMother.h oh wait I need to put RMthat.h before
RMthis.h, and if I include RMinp.h it includes RMother.h in turn so that
breaks...." I could just say "I'll be linking against RMlib.so, so use that
for declarations when I compile."
2) Header files can contain macros that change how your code behaves. Go
read my post about the awful libraries I used at work, including
#define char }}}}
put in there *explicitly* to fuck up the code of anyone trying to use the
library (in the name of portability, of course). Along with a bunch of crap like
#define IN
#define OUT
etc, to the point where you're reading a declaration and you can't even tell
looking at the arguments what are the types and what are the variable names.
If I'm compiling with declarations from object code, none of this happens,
because I'm only compiling the code I myself wrote.
3) Stuff like #define making it impossible in some cases to track down just
what name goes with what value, as I gave examples of.
Again, if I'm using declarations out of object code, the names vs values
have already been compiled, and they won't change depending on what I put in
my source code.
4) Compilation options for the compilation of a given library is usually not
stored in the object code, and you're recompiling the declarations for each
caller, so a change in calling convention, structure packing, etc between
what the library was compiled with and what the caller was compiled with
will often crash silently or messily, often without any indication of why.
If at compile time I'm supplying the object code instead of the source code,
the compiler can either reject it during compilation, or it can adjust
individual calling sequences to match the library being called.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> For example, if you create your own class or struct which has a few
> member variables, and then you instantiate a vector of that type, it will
> be quite space-optimal: Every element in the vector will only consume as
> much memory as the size of the object. There is no ancillary data needed.
C# does that. Of course, it's generating bytecodes not machine code.
> Of course the second efficiency advantage is that the compiler will be
> able to inline code and to perform type-specific optimizations (for example,
> sorting a vector of ints will be very efficient because the compiler will
> be able to inline the element comparisons directly into the sorting routine
> as a machine code register comparison opcode).
C# can do this too, but of course that's because it's not completely
compiled until you run the code.
The place C# lacks compared to C++ is that again *because* you're not
recompiling the declaration each time you use it, you have to make
guarantees at the compile time of the generic. So you can't write a generic
that would work on "any object that has a function X taking a single integer
and returns a float". The things you instantiate have to have particular
declarations as required by the generic. This is something I'd take from Go
perhaps - there doesn't seem to be any technical reason the language
couldn't be improved to support this sort of thing. The language already
knows hen you compile the generic if you're making calls you haven't
supported, and it knows when you instantiate the generic what calls are
supported by the class you're instantiating it with, so it would probably
just be an extension of the metadata.
> On the other hand, it's not technically impossible, and it has been done,
I had read that the guys who did it said basically it's impossible to do
right according to the standard, but you can get close. Not being an expert
on the esoteric details of C++ compiler implementation, I might have been
misunderstanding their conclusions. But sure, it can be done, but I'm not
sure what the benefit would be per se? Why does anyone care? Is it just to
hide (in a commercial sense) the source code for the template library?
> As far as I understand "generics" do not handle things "inline" and
> "by value", but instead simply handle references, and basically the only
> thing they do is that they allow you to skip doing explicit upcasting.
That's Java. In C#, they actually changed the object code format (which Java
couldn't afford to do) to support actual generics. So a list of points
doesn't have any pointers in it internally, and your example of
vector<Point> with two definitions of Point works fine too. That's why XNA
(for example) can build a model full of vertexes and not be absolutely
bogged down even on an implementation where the GC is
stop-the-work-mark-and-sweep sucky.
> Generics do not allow things like template metaprogramming, template
> specialization, and such.
Yes, specialization is another thing that (I think) C# lacks that I would
have liked to have on several occasions.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> I know that you didn't mean the full source code, but you should try
> to use common terminology, and "the source code" is not the common term
> for "header files".
It's not like I didn't say it three dozen different ways over the course of
the conversation, with repeated references to include files.
But now you understand what I'm saying. #include includes source code. No
other compiled language I use needs that feature.
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > For example, if you create your own class or struct which has a few
> > member variables, and then you instantiate a vector of that type, it will
> > be quite space-optimal: Every element in the vector will only consume as
> > much memory as the size of the object. There is no ancillary data needed.
> C# does that. Of course, it's generating bytecodes not machine code.
Can you compile a C# program into a stand-alone executable that does not
require a JIT compiler environment? (Well, I suppose that if the JIT
compiler is linked into the executable, it could perhaps work.)
But thinking about it, why is the final compilation into machine code
delayed until the program is run? Why cannot it be done at compile time?
> > On the other hand, it's not technically impossible, and it has been done,
> I had read that the guys who did it said basically it's impossible to do
> right according to the standard, but you can get close. Not being an expert
> on the esoteric details of C++ compiler implementation, I might have been
> misunderstanding their conclusions.
AFAIK they added export templates to the standard because they confirmed
that it can be done. They didn't predict, however, how hard it would be,
nor that major compiler writers would just skip doing it because of that.
> But sure, it can be done, but I'm not
> sure what the benefit would be per se? Why does anyone care? Is it just to
> hide (in a commercial sense) the source code for the template library?
Well, if you can avoid having to put tens of thousands of lines of code
in header files (just because the compiler forces you to), making compilation
slower and possibly bloating your program, that's always a plus. Often it's
beneficial when the compiler can inline templates, but there becomes a limit
where it actually becomes a hindrance when you have to put your entire
library in a header file. However, that's not the main problem.
Support for export templates would allow the templated code to have
types, functions and data that are local to the compilation unit (and
possibly shared among all the different template type instantiations)
where the templated code is implemented. This might sound like a small
thing, but it's actually a huge defect in templated code when the compiler
doesn't support export templates.
Just consider this simple example (in a source file):
//------------------------------------------
namespace
{
int counter = 0;
}
export template<typename T>
void foo()
{
++counter;
...
}
//------------------------------------------
What's so special about this? It's special in that all instantiations
of foo() will modify the *same* 'counter' (rather than there having one
'counter' per template type).
The above is simply *not possible* with current C++ compilers (except
Comeau, which is the only one that supports export templates).
(Ok, it's not completely impossible. You could make 'counter' global,
in which case the non-export foo() instantiations could modify it. However,
this obviously reduces modularity significantly, and grants unwanted
access for outside code to the variable.)
Even if you don't really need data that is shared among all the template
instantiations, just the ability to have most of your types, functions and
data local to the compilation unit where the templates using them are,
would increase modularity significantly. It can also reduce executable bloat
(because types and data that are common to all template instantiations do
not need to be duplicated for each one.)
AFAIK people working in the standardization committee are trying to come
up with a different solution to this problem which would be much easier for
compilers to implement.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Can you compile a C# program into a stand-alone executable that does not
> require a JIT compiler environment? (Well, I suppose that if the JIT
> compiler is linked into the executable, it could perhaps work.)
There's a tool called NGEN that takes the byte code file and inserts
compiled code too. For things you install into the "global assembly
container" (i.e., /lib basically) it runs that tool at install time.
> But thinking about it, why is the final compilation into machine code
> delayed until the program is run? Why cannot it be done at compile time?
I would think it would be difficult to do it before link time, if only
because of the fact that you can inherit from a superclass and then have the
superclass recompiled out from under you. (Which is, in part, why putting
something in the GAC requires that it be cryptographically signed yadda
yadda, so that sort of thing doesn't happen.) Basically, you'd need at
least the entire assembly available. (One assembly is the smallest unit of
compiled code you can distribute. It might be in multiple DLLs, but it
wouldn't make sense to distribute one DLL without the other.)
Also, if you compile the code before you run it and then never throw away
that code, you can't take advantage of precisely which chip it's running on
(like new SSE instructions or something) and you can't do optimizations like
cross-assembly code inlining. There's also odd stuff happening in the
background, whereby new optimizations get pulled down of the internet or
something weird? I don't know, I just turn all that stuff off, but
apparently there's some really deeply funky/screwy stuff going on in that
part of the code generation process.
(As an aside and completely irrelevant to the above points, I found it
really cool the XNA compiler will take per-pixel or per-vertex constant
calculations in shader code and hoist them back to the main CPU. I've never
seen a cross-CPU loop invariant hoist before. :-)
> AFAIK they added export templates to the standard because they confirmed
> that it can be done. They didn't predict, however, how hard it would be,
> nor that major compiler writers would just skip doing it because of that.
As I said, maybe I misunderstood it. The article was by the guys who wrote
the first compiler that supported it. Thinking on it, it's possible what
they were saying is they implemented draft proposals, found where that
broke, and then reported back to the committee, who then fixed those problems.
> Support for export templates would allow the templated code to have
> types, functions and data that are local to the compilation unit (and
> possibly shared among all the different template type instantiations)
> where the templated code is implemented. This might sound like a small
> thing, but it's actually a huge defect in templated code when the compiler
> doesn't support export templates.
Got it. So, making templates more like classes sorta? With "static"
variables and so on?
> (Ok, it's not completely impossible. You could make 'counter' global,
> in which case the non-export foo() instantiations could modify it. However,
> this obviously reduces modularity significantly, and grants unwanted
> access for outside code to the variable.)
Got it. Thanks for the explanation!
> AFAIK people working in the standardization committee are trying to come
> up with a different solution to this problem which would be much easier for
> compilers to implement.
That would be good. Unfortunately, I don't think it's easy to think up a
solution that has as much power as C++ templates (and be as easy) without
having the sources around at compile time.
LISP has macros that are super powerful, but there really isn't a whole lot
of static typing / overloading kind of stuff going on there.
Erlang, again, is dynamically typed. It has compiled macros that are
basically functions which take a AST as input and return another AST as a
result, and that's how you implement macros.
But both of these solutions require running code you just compiled before
you finish compiling, as part of the compilation process. Not something I
really see happening with a language targeting the kinds of projects C tends
to address (in terms of maximum efficiency and portability).
--
Darren New, San Diego CA, USA (PST)
"How did he die?" "He got shot in the hand."
"That was fatal?"
"He was holding a live grenade at the time."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |