Hi guys.
I've been scratching my head for about two hours now, trying to figure out what kind of incantation I need to do in order to compile a module whose interface and implementation sections reside in different files.
-STOP-
Okay, I've composed two other mails before this (with the first couple of paragraphs being part of the second), and I've finally found what I needed.
It turns out that, in order to compile a module that has its interface and implementation sections in two different files, one has to compile them this way:
gpc -c --interface-only TAttributes.int.pas gpc -c --implementation-only TAttributes.imp.pas --include TAttributes.int.pas
Now, my question is, why do we need to include the interface part with the implementation part manually? Can't we tell gpc where to look, to find what it needs? The --unit-path command-line option did not help, and gpc warned about using --auto[make/build].
Also, --unit-destination-path doesn't work for me; I have compile from inside the directory where I want the .gpi and .o files to be placed.
Using (as per gpc -v): gpc version 20040516, based on gcc-3.3.3
Also tried with 20030830 (both with gcc 3.2.2).
Anyway, back to those unit tests. :D
On 30 May 2004 at 0:18, Neil Santos wrote:
Hi guys.
I've been scratching my head for about two hours now, trying to figure out what kind of incantation I need to do in order to compile a module whose interface and implementation sections reside in different files.
-STOP-
Okay, I've composed two other mails before this (with the first couple of paragraphs being part of the second), and I've finally found what I needed.
It turns out that, in order to compile a module that has its interface and implementation sections in two different files, one has to compile them this way:
gpc -c --interface-only TAttributes.int.pas gpc -c --implementation-only TAttributes.imp.pas --include TAttributes.int.pas
Have you tried using "{$include TAttributes.imp.pas}" in "TAttributes.int.pas"?
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
On 18:14 29/05/04, Prof A Olowofoyeku (The African Chief) wrote:
It turns out that, in order to compile a module that has its interface and implementation sections in two different files, one has to compile them this way:
gpc -c --interface-only TAttributes.int.pas gpc -c --implementation-only TAttributes.imp.pas --include TAttributes.int.pas
Have you tried using "{$include TAttributes.imp.pas}" in "TAttributes.int.pas"?
Yup; and, UIM, the second line does the same thing as what you've suggested. I was wondering why we have to include the interface section with the implementation; isn't there a way to tell GPC where to look for the implementation section(s), if we're building with (an) interface(s)--and, conversely, a way to tell GPC where to look for interface section(s)?
While I can get used to this method of compiling methods, I would really rather prefer to let the compiler look for the needed parts on its own.
Neil Santos wrote:
Hi guys.
I've been scratching my head for about two hours now, trying to figure out what kind of incantation I need to do in order to compile a module whose interface and implementation sections reside in different files.
File `mod1.pas': module mod1 interface; export mod1 = (c, f); const c = 0; function f: integer; end .
File `mod1-imp.pas': module mod1 implementation; function f: integer; begin f := 1 end; end .
File `pp.pas': program pp; import mod1; begin writeln ('f = ', f) end .
I can compile it with:
gpc --automake pp.pas mod1-imp.pas
(that command recompiles all interfaces, also it may fail due to `automake' design bug).
I can also compile parts separately:
gpc --automake --interface-only mod1.pas gpc -c --implementation-only mod1-imp.pas gpc pp.pas mod1-imp.o
Note that with gpc-20030830 I got incomplete mod1-imp.o, but with gpc-20040516 that works OK.
The first way means full rebuild of implementations (that remove main motivation to keep interfaces separate).
AFAIKS there are two remaining problems: 1) There is no default way to find implementation so plain `--automake' (or `gp' (alias `cgp', alias `gpmake')) can not find them. IMHO we need to introduce a convention here. I propose to have `module.p' for interface and `module-imp.p' for implementation.
2) gpc writes to the GPI files compiling implementation. That is disastrous for using `make' (one can not have dependencies on `.gpi' files) and limits `--automake' utility. Ideally gpc should write implementation info to a separate file. As a workaround I added to my version `--disable-gpi-extension' option which just disables writing to GPI files after creation -- that is enough to enable use of `make'. In fact, recent improvements to `--automake' and that option enabled me first time to compile some sources with cyclic dependencies.
On 19:15 29/05/04, Waldek Hebisch wrote:
AFAIKS there are two remaining problems:
- There is no default way to find implementation so plain `--automake' (or `gp' (alias `cgp', alias `gpmake')) can not find them. IMHO we need to introduce a convention here. I propose to have `module.p' for interface and `module-imp.p' for implementation.
That is one of my main points in my original message.
With all due respect, I propose a different system: one wherein we could tell gpc (through maybe a command-line parameter) where it could search for the sections it needs. We could then name our interfaces and implementations the same, and just store them in different directories; maybe interface/ and implementation/ directories, or something similar.
We could then, maybe, have other parameters to fine-tune the search: something like --prepend-interface-name or --append-interface-name, and --prepend-implementation-name --append-implementation-name.
This hypothetical version of gpc could then be invoked this way:
gpc myprog.pas --automake --module-interface-dir="./interface/" --module-implementation-dir="./implementation/" --append-interface-name="-interface" --append-implementation-name="-implementation"
Our hypothetical gpc would go compile myprog.pas, and when it encounters an import statement (say `import somemodule'), it goes into ./interface/ and looks for a file named `somemodule-interface.pas' to get the interface section, then goes to ./implementation/ and looks for a file named `somemodule-implementation.pas' to get the implementation.
Of course, employing such a system would have to be much more robust, considering modules don't have to be named the same as the file that contains them, and that modules can export items under a different name.
However, I believe that such a system would be much more flexible than requiring GPC users constrain themselves to having module implementations named `module-imp.pas'; no offense, Waldek. :)
(What does AFAIKS mean? I've Googled for it, but the only acronym I can find for IKS (I'm assuming AFA means As Far As) is `Imperial Klingon Ship', `Interkantonale Kontrollstelle fur Heilmittel' (which I can't decipher further than `International Something for Something'), and `Tiksi', which is Russian (or so acronymfinder.com tells me))
Neil Santos wrote:
On 19:15 29/05/04, Waldek Hebisch wrote:
AFAIKS there are two remaining problems:
- There is no default way to find implementation so plain `--automake' (or `gp' (alias `cgp', alias `gpmake')) can not find them. IMHO we need to introduce a convention here. I propose to have `module.p' for interface and `module-imp.p' for implementation.
That is one of my main points in my original message.
With all due respect, I propose a different system: one wherein we could tell gpc (through maybe a command-line parameter) where it could search for the sections it needs. We could then name our interfaces and implementations the same, and just store them in different directories; maybe interface/ and implementation/ directories, or something similar.
We could then, maybe, have other parameters to fine-tune the search: something like --prepend-interface-name or --append-interface-name, and --prepend-implementation-name --append-implementation-name.
This hypothetical version of gpc could then be invoked this way:
gpc myprog.pas --automake
--module-interface-dir="./interface/" --module-implementation-dir="./implementation/" --append-interface-name="-interface" --append-implementation-name="-implementation"
Our hypothetical gpc would go compile myprog.pas, and when it encounters an import statement (say `import somemodule'), it goes into ./interface/ and looks for a file named `somemodule-interface.pas' to get the interface section, then goes to ./implementation/ and looks for a file named `somemodule-implementation.pas' to get the implementation.
I do not like to split implementations and interfaces into different subdirectiories (at least for my programs). The `--append-...' options could of course work without the `...-dir..' options. However together we get rather have machinery, and still not very flexible.
Of course, employing such a system would have to be much more robust, considering modules don't have to be named the same as the file that contains them, and that modules can export items under a different name.
You can write:
import e1 in 'mod15m.pas';
to tell gpc that interface `e1' is contained in file 'mod15m.pas'. The drawback is that the "in 'mod15m.pas'" part is gpc extension, so you loose EP compatibility.
However, I believe that such a system would be much more flexible than requiring GPC users constrain themselves to having module implementations named `module-imp.pas'; no offense, Waldek. :)
If you want total flexibility then clearly you want to have a "catalog" giving correspondence interface <--> file(s). However, what I propose is very simple to implement and gives you one way to implement modular design. Also, having simple rule to get implementation file name from module name makes thing simpler for people.
On the other hand EP model fits well with database technology, so one can imagine a tool that stores sources in a database and at build time fetches needed parts for compilation. Anyway, more complicated interface <--> module <--> storage dependencies are better moved to a separate tool.
(What does AFAIKS mean? I've Googled for it, but the only acronym I can find for IKS (I'm assuming AFA means As Far As) is `Imperial Klingon Ship', `Interkantonale Kontrollstelle fur Heilmittel' (which I can't decipher further than `International Something for Something'), and `Tiksi', which is Russian (or so acronymfinder.com tells me))
s/K/C/
By the way, you wrote about `--include' option and the Chief suggested putting `{$incude ...}' directive in the interface. Both IMHO defeat the purpose of separate interface, as effectively interface and implementation are compiled jointly (only disk storage is separate).
Excuse the long post - ruminations on a Sunday morning... best to read to the end, I wrote it as I went along.
At 9:41 PM +0200 29/5/04, Waldek Hebisch wrote:
Neil Santos wrote:
On 19:15 29/05/04, Waldek Hebisch wrote:
That is one of my main points in my original message.
With all due respect, I propose a different system: one wherein we could tell gpc (through maybe a command-line parameter) where it could search for the sections it needs. We could then name our interfaces and implementations the same, and just store them in different directories; maybe interface/ and implementation/ directories, or something similar.
We could then, maybe, have other parameters to fine-tune the search: something like --prepend-interface-name or --append-interface-name, and --prepend-implementation-name --append-implementation-name.
This hypothetical version of gpc could then be invoked this way:
gpc myprog.pas --automake
--module-interface-dir="./interface/" --module-implementation-dir="./implementation/" --append-interface-name="-interface" --append-implementation-name="-implementation"
Our hypothetical gpc would go compile myprog.pas, and when it encounters an import statement (say `import somemodule'), it goes into ./interface/ and looks for a file named `somemodule-interface.pas' to get the interface section, then goes to ./implementation/ and looks for a file named `somemodule-implementation.pas' to get the implementation.
I do not like to split implementations and interfaces into different subdirectiories (at least for my programs). The `--append-...' options could of course work without the `...-dir..' options. However together we get rather have machinery, and still not very flexible.
You wouldn't *have* to as you say, it'd be your choice. It might be valid in a large team effort to give some members of the team access to only the interface files and not their implementation. Which I've always thought was part of the original concept behind implementing these things anyway...
Of course, employing such a system would have to be much more robust, considering modules don't have to be named the same as the file that contains them, and that modules can export items under a different name.
My only objection is that ideally the naming scheme would be tied to the code. One thing I hate with path info, etc. is that its always one more thing that's separate from the code that needs to be remembered.
Other than that the above looks good at first glance. Have a default search rule, but make command-line options for modifying it.
Incidentally, what was Modula-2's rule (if any) on this? I swore I had a book on Modula-2, but I can't find the thing. Anyway, perhaps Modula-2 implementations had some solution to this? Or perhaps Oberon?
You can write:
import e1 in 'mod15m.pas';
to tell gpc that interface `e1' is contained in file 'mod15m.pas'. The drawback is that the "in 'mod15m.pas'" part is gpc extension, so you loose EP compatibility.
This fits what I wrote above (lucky me :-), although now there is no "rigid" way of imposed a naming rule over a whole a project other than "just remembering" each time you go to use it. Also, now the interface and implementation sections are stuck where they are: you can't move them without editing the code.
An alternative might be to refer to the current implementation and interface directories with them to be defined from the command-line, etc. e.g.
import x in '$interface-dir/y.pas' ;
If you want total flexibility then clearly you want to have a "catalog" giving correspondence interface <--> file(s). However, what I propose is very simple to implement and gives you one way to implement modular design. Also, having simple rule to get implementation file name from module name makes thing simpler for people.
Come to think of it, there is an issue if different modules (or libraries of modules) adopt different schemes and then you want to use them in one program... the import x in 'y'; has no problem, but the command-line variant does (since it fixes the one location/append rule over the build), unless you build it in several steps.
Perhaps the directory naming concept above could be extended to any number of different directories defined someplace? e.g.
import x in '$someDir/y.pas' ;
with the definition of someDir defined elsewhere.
Perhaps a small implementation file could define these things (using #defines). A common defines file could be #include'd at the head of head file. And allow the compiler to override the defines from the command-line. The file of defines can then serve as the "database" of these mappings.
Starting to sound like a certain other language that these macros come from... but I think its OK all the same ;-) Now its all defined in the code and can be edited in one place for a complete project.
s/K/C/
OK, so you meant AFAICS. Sigh. Should have guessed.
Grant
Waldek Hebisch wrote:
... snip ...
By the way, you wrote about `--include' option and the Chief suggested putting `{$incude ...}' directive in the interface. Both IMHO defeat the purpose of separate interface, as effectively interface and implementation are compiled jointly (only disk storage is separate).
I agree about no $includes etc. Believe it or not I am trying to be constructive. To me a set of sources should be able to hold nothing more than ISO standard constructs, which means no special directives, peculiar comments, etc. etc. and a straight forward and immediately understandable set of compilation commands should be available. One command option may mean "compile interface module", another "compile implementation module", much as options to gcc now say "extract dependencies" or "generate assembly source" or "generate object code" FROM A SINGLE source. The complexities arise when multiple sources need to be compiled.
I think Frank (and possibly you) is/are much too close to the actual implementation. This makes you think in terms of --automake and gp, rather than a simplified approach. Old fashioned data flow charts, in the spirit of Yourdon, may be worth while. Of coarse you (collectively) are doing the work, which certainly entitles you to choose the methodology. And I may be totally ignorant of what is really existant, and thus blathering into the wind.
On 21:41 29/05/04, Waldek Hebisch wrote:
[quotes from my previous message snipped]
I do not like to split implementations and interfaces into different subdirectiories (at least for my programs). The `--append-...' options could of course work without the `...-dir..' options. However together we get rather have machinery, and still not very flexible.
The --[pre|ap]pend... options would be very much appreciated, although I wouldn't use it much, if at all. I'm rooting for the .*dir.* stuff. :)
You can write: import e1 in 'mod15m.pas'; to tell gpc that interface `e1' is contained in file 'mod15m.pas'. The drawback is that the "in 'mod15m.pas'" part is gpc extension, so you loose EP compatibility.
It's not so much the loosing of EP compatibility that bothers me; it's the fact that I'm limiting that module to whatever path I tell the compiler to look for it. This isn't much of a hassle if only one or two components uses a module imported with `in ...', but it becomes a maintenance nightmare when a bunch of them have to import modules this way.
If you want total flexibility then clearly you want to have a "catalog" giving correspondence interface <--> file(s). However, what I propose
Yes, that would seem like a good (if not the best) way of implementing the feature I've suggested.
fetches needed parts for compilation. Anyway, more complicated interface <--> module <--> storage dependencies are better moved to a separate tool.
You might have just given me an idea for what I could work on in the future, although by `future' I mean `fuuuuuture'. ;b
(What does AFAIKS mean? I've Googled for it, but the only acronym I
s/K/C/
Ahh. I thought that might be it. :D
By the way, you wrote about `--include' option and the Chief suggested putting `{$incude ...}' directive in the interface. Both IMHO defeat the purpose of separate interface, as effectively interface and implementation are compiled jointly (only disk storage is separate).
As does, if you'll pardon my saying so, GPC's `in ...' extension to imported modules--and that's also what I said in my original message, hence the convoluted feature request.
(What does AFAIKS mean? I've Googled for it, but the only acronym I can find for IKS (I'm assuming AFA means As Far As) is `Imperial Klingon Ship', `Interkantonale Kontrollstelle fur Heilmittel' (which I can't decipher further than `International Something for Something'), and `Tiksi', which is Russian (or so acronymfinder.com tells me))
I've always thought AKAIK mean as far as I know. Not sure what the s is even I've seen it 'round :-)
Grant