Prof. A Olowofoyeku (The African Chief) wrote:
[...]
- What things can be done in GPC without libgpc - for example, if
one produced an include file of libc exports and doesn't use units or Pascal strings or objects or file I/O at all?
Basically yes, though there isn't an "official" list of which internals require RTS calls (and this might change slightly over time), so one can only try, looking at the linker errors (undefined references).
Producing an empty libgpc.a to compile a simple "begin end." program produced 4 linker errors - rts version, initialize, finalize, and something else which I forget. I wrote simple stubs - functions returning 0 with those names and put them in libgpc.a.
That's just what I put in my last mail, with the (currently) correct declarations. Using nop-functions instead of procedures, and omitting parameters will work, of course, due to the default "C" calling convention. And a function instead of the variable works just because the compiler doesn't really do anything with the variable, just check for its presence (via the linker).
That sorted out those problems. I wrote a small include file with a few libc routines (malloc, free, puts, gets, system, printf, functions from string.h, etc) and wrote a little test program to test various things. The program compiled to between 5kb and 9kb, and I was able to read and write strings with it, get and set environment variables, and stuff. My little CGI program doesn't really need more than these routines. But the ensuing program would look more like C than Pascal.
Quite typical in such a setting. At least there's the possibility to expand its features when needed ...
What would be helpful is a way to specify a particular "libgpc" to the compiler at compile time - e.g., "gpc foo.pas --libgpc=small_libgpc"
So, instead "-lgpc", the compiler will get "-lsmall_libgpc". Can this be done at the moment?
Not at the moment, the name is hard-coded in gpc.c:
outfiles [i] = "-lgpc";
In principle I agree that making it configurable might be desirable. One thing to consider, though, is that after dropping automake, this adding of -lgpc and -lm will be one of the very few things left that gpc.c has to do different from gcc.c. So before we change anything there, we should probably look at GCC, e.g. whether gcc-4 or future versions may have a mechanism to automatically add such libraries (as other languages have to do the same with their runtime libs), and if so perhaps already a defined way of overriding them, so we might not need a separate gpc.c then at all. Just to avoid implementing something separate and perhaps incompatible. ATM I don't know if GCC has any such plans (or did anything already), perhaps Waldek knows.
Currently, a work-around is to produce .o files (manually or using gp), and link them with gcc (matching version, of course), adding the library explicitly.
It might also work to just add the new library, and just let gpc.c pass -lgpc. If your library comes first, its declarations should take precedence, and if no declaration from libgpc.a is used it's simply ignored by the linker.
Actually, one doesn't need a library for that. A plain unit using the appropriate linker names (or just embedding the code in the main program, as I just tried) will do. See the attached typescript.
The first example shows what happens when some of the linker names don't match -- though the messages are a bit surprising at first glance. The linker will pull the missing declarations from libgpc.a, thereby linking the library, and thus get duplicate symbols for the other (matching) linker names. So, this is a kind of warning against inadvertently using libgpc.a (though the executable size will tell you anyway).
The second example, matching the RTS version check (to my current GPC development number, yours will be different) works and produces a small exectuable. For comparison, the third example, compiling an empty file. (So removing code makes the executable bigger, isn't it funny? ;-)
- Would there be any mileage in producing a libc standard unit?
libc is a rather vague term here. Such a unit could be anything from a non-portable interface of the 6 most important libc calls (open, close, read, write, fork, exec, according to Linus ;-) to a fully portable interface to all known libc's on this planet, with interface to all functions supported by any of them plus emulations/errors where not supported ...
"Standard" GNU libc, if such a thing exists.
Actually I'm not sure if GNU libc on different platforms provides exactly the same features, or some non-portable ones as well, though one could omit the latter here if they exist.
That's quite a large beast already, and as I said rts.c only covers a part of it yet. If you like to extend it, go ahead, but of course, for inclusion into the RTS (whether the same or a new unit) we can't support GNU libc only, which means adding a lot of autoconf checks (which is actually sometimes the most work when adding a new function there).
Frank