Hello,
The gp fix solved the false cyclic dependencies problem.
The compilation runs smooth now. Thanks!
However, I probably missed something because gp does not succeed to make the programs completely for two main reasons.
First: There are some objects from c sources not found at link time. I put {$L my_c_extern.c} in a Pascal source but gp says "my_c_extern.c must be compiled" and stops instead of compiling it (I think since is knows that the source must be compiled, it should do it, no?). Then I tried {$L my_c_extern.o} instead and gp says " My_c_extern.c:999: undefined reference to 'symbol' where 'symbol' is defined in a third party library for which I put a -l directive on gp command-line.
Second: The link command. I put gp in verbose mode and made a copy of the link command which fails to find out what is going wrong.
I see that the list of my external (third party) libraries comes before any object in the link command. (-llib1 -llib2...)
By putting this list of libraries at the end of the link command, it worked. But since I have no control on this at the gp command-line level I cannot make it work.
Also, I noticed that objects are written in the same directory as gpi files despite the option --object-destination-path=obj on the gp command-line.
Am I trying to make gp do things it was never designed for?
Hope this is clearly explained.
I use gp with Debian Linux on x86 if this detail matters.
Thanks
Pascal Viandier pascal@accovia.com
-----Message d'origine----- De : gpc-owner@gnu.de [mailto:gpc-owner@gnu.de] De la part de Pascal Viandier Envoyé : November 11, 2005 15:36 À : gpc@gnu.de Objet : TR : RE : RE : compiling with gp (was
Sorry I made a typo in the description of the dependencires:
The third line of the schema should be:
. Module C implementation section imports Module A and Module B (not Module C)
Pascal Viandier pascal@accovia.com
-----Message d'origine----- De : gpc-owner@gnu.de [mailto:gpc-owner@gnu.de] De la part de Pascal Viandier Envoyé : November 11, 2005 15:21 À : gpc@gnu.de Objet : RE : RE : compiling with gp (was
Hi,
The schema of the cyclic dependencies I face is:
. Module A implementation section imports Module B . Module B implementation section imports Module A and Module C . Module C implementation section imports Module A and Module C
Please note the dependencies are in the implementation sections, not in the interfaces. Although for each module the interface section is in a separate file included in the appropriate implementation file (i.e. A.pas includes A.h but no other file), I think this is not the cause of the problem.
With this, gp says: cyclic interface dependency A.pas -> B.pas -> C.pas and it stops.
Hope this schema will help clarify the situation.
Regards
Pascal pascal@accovia.com
-----Message d'origine----- De : gpc-owner@gnu.de [mailto:gpc-owner@gnu.de] De la part de Frank Heckenbach Envoyé : November 11, 2005 09:03 À : gpc@gnu.de Objet : Re: RE : compiling with gp (was
Pascal Viandier wrote:
Just my two cents: Like Mr Van Os, I have myself the problem of cyclic dependencies in many programs I ported from SUN Pascal to GNU Pascal. There are hundreds of separate modules with cyclic dependencies up to 8th level.
To avoid misunderstandings: GP generally should be able to handle cyclic dependencies. I've used it compile a project with ~200 units, all interdependent (not written by me, obviously :-).
So we don't need to discuss whether to do that.
For now, I use make to build the programs because of these dependencies.
I
have to call it two times to build the interfaces, because there are
also
cyclic dependencies in some interface sections that import others.
Cyclic dependencies within interfaces are forbidden, both in Borland and Extended Pascal. (I.e., interface A uses interface B, and interface B uses interface A.) GP will also reject this, and there's really no sane way to do this, as you could easily construct circular definitions and contradictions this way.
What you can do is: Interface A uses interface B, and implementation B uses interface A. Then GP should, in this order, compile interface B, all of A, implementation B.
If that's what you need, then GP should work for you. There may be abug, perhaps the same one Adriaan found, and then, of course, I'd like to fix it, when I know what it is ...
Although I am not sure if I can completely build the programs with it
since
they link with many third party libraries and I have not found the way
to do
it in the gp documentation yet.
Libraries are easy. There are two ways, both work the same with GP as with automake, and the second one also with manual make:
Put {$L} directives in the source (see e.g., the GMP and RegEx units that come with GPC).
Add -l options on the command line.
I am now implementing for gp:
--compile-file Compile a file as fast as possible. Imported units that need recompilation are compiled --interface-only, which implies
that
successive linking will fail.
Therefore, this option is useful during the development phase only. This option implies -c --check-file Check the syntax of a file as fast
as
possible. Imported units that need recompilation are compiled
--interface-only. This option implies -c
It mostly works already (I will post a diff later). The time gain
is
dramatic.
IIUC, this is only necessary because of the bug you suppose in your previous mail (otherwise no other units would have to be recompiled if not changed)? So it might be a better use of time to concentrate on the acutal bug than on temporary work-arounds.
No, I consider this a valuable feature, although the impact may in general not be so dramatic as in my current project, porting an application to GPC with many cyclic dependencies (which I didn't write myself).
Perhaps I don't yet quite understand it. Provided GP makes no mistakes and imports are not recompiled unless necessary. So I suppose you mean the situation that you changed the implementation of an imported unit? But you don't want to compile (and therefore check for syntax errors) this other unit?
I will try to be useful and fix gp myself. Compile times are also spoiled by the quadratic operator search (http://www.gnu-pascal.de/crystal/gpc/en/mail10055.html) and that is something I cannot fix easily myself (at some points in the
compilation
I see the IDE's progress bar and line counter move line by line, often lines with calculations).
I see. BTW, Waldek are you interested in the general solution of this issue (including overloaded routines)? I'm not too much ATM (there are many more urgent issues). If you aren't either, perhaps I could at least try some quick fix to ease this problem somewhat. -- Still using name-based search, with all its disadvantages, but perhaps storing a list of actually defined operators in the OPERATOR_DECL (this will also be a preparation for the real solution), and then for each operator retrieve the type names and compare them -- I suppose if we get rid of the ACONCAT and get_identifier in the loop this way, this might make things much faster.
Frank
-- Frank Heckenbach, frank@g-n-u.de, http://fjf.gnu.de/, 7977168E GPC To-Do list, latest features, fixed bugs: http://www.gnu-pascal.de/todo.html GPC download signing key: ACB3 79B2 7EB2 B7A7 EFDE D101 CD02 4C9D 0FE0 E5E8
At 14:17 -0500 14/11/05, Pascal Viandier wrote:
First: There are some objects from c sources not found at link time. I put {$L my_c_extern.c} in a Pascal source but gp says "my_c_extern.c must be compiled" and stops instead of compiling it (I think since is knows that the source must be compiled, it should do it, no?). Then I tried {$L my_c_extern.o} instead and gp says " My_c_extern.c:999: undefined reference to 'symbol' where 'symbol' is defined in a third party library for which I put a -l directive on gp command-line.
I believe this is due to a bug I fixed in my copy of gp. It stems from the comment:
{ Just make sure the file is added to Deps. We don't need any dependency relations because files linked with linker directives can be compiled at any time. }
which I believe is erroneous. A patch (based on my subversion history) is attached below, but I do not know if it interacts with any of the other patches I've done.
Second: The link command. I put gp in verbose mode and made a copy of the link command which fails to find out what is going wrong.
I see that the list of my external (third party) libraries comes before any object in the link command. (-llib1 -llib2...)
By putting this list of libraries at the end of the link command, it worked. But since I have no control on this at the gp command-line level I cannot make it work.
I saw something like this with libpcre and libxml2 - reordering the libraries fixed the problem without any changes to gp.
Also, I noticed that objects are written in the same directory as gpi files despite the option --object-destination-path=obj on the gp command-line.
I can't help you much with that, as I don't use it. But for {$L}, gp stores a gpd file, so it would need to go somewhere.
gp patch follows. This is definitely not any sort of official patch. My gp has wandered far from the track. Peter.
Index: gp.pas =================================================================== --- gp.pas (revision 331) +++ gp.pas (revision 332) @@ -164,6 +164,7 @@ TUnitList = record Next: PUnitList; FileName, InterfaceName: TString; + IsUnit: Boolean; MD5: TMD5; Dep: PDep end; @@ -365,6 +366,17 @@ ErrorFile (FileName, 'no directory or not writable') end;
+function NewUsesElement (const InterfaceName, FileName: String; Next: PUnitList) = p: PUnitList; +begin + New (p); + p^.InterfaceName := LoCaseStr (InterfaceName); + p^.FileName := FileName; + MD5Clear (p^.MD5); + p^.Dep := nil; + p^.IsUnit := True; + p^.Next := Next +end; + { GPD file handling }
function ReadGPD (var Dep: TDep): TGPD; @@ -430,7 +442,9 @@ end;
function AddUnitList (var p: PPUnitList): Boolean; - var i, j: Integer; + var + i, j: Integer; + MD5: TMD5; begin AddUnitList := False; if not PascalFlag then @@ -438,17 +452,15 @@ ReadGPDError ('invalid unit dependency for C file'); Exit end; - New (p^); i := PosFrom (' ', Line, 3); j := LastPos (' ', Line); - if (i >= j) or not MD5Val (Copy (Line, j + 1), p^^.MD5) then + if (i >= j) or not MD5Val (Copy (Line, j + 1), MD5) then begin ReadGPDError ('invalid unit entry'); Exit end; - p^^.InterfaceName := Copy (Line, 3, i - 3); - p^^.FileName := Copy (Line, i + 1, j - i - 1); - p^^.Dep := nil; + p^ := NewUsesElement( Copy (Line, 3, i - 3), Copy (Line, i + 1, j - i - 1), nil ); + p^^.MD5 := MD5; p := @p^^.Next; AddUnitList := True end; @@ -568,7 +580,9 @@ begin while p <> nil do begin - WriteLn (f, Prefix, p^.InterfaceName, ' ', p^.FileName, ' ', MD5Str (p^.MD5)); + if p^.IsUnit then begin + WriteLn (f, Prefix, p^.InterfaceName, ' ', p^.FileName, ' ', MD5Str (p^.MD5)); + end; p := p^.Next end end; @@ -656,7 +670,7 @@ Assert (i = e + OptionCount); for i := 1 to n - m + 1 do Parameters^[e + OptionCount + i] := NewString (AdditionalParameters[i + m - 1]^); - if (Verbosity >= 2) or (@CmdLine <> nil) then + if (Verbosity >= 1) or (@CmdLine <> nil) then begin l := Length (Compilers[PascalFlag].ProgName); for i := 1 to Parameters^.Count do @@ -666,7 +680,7 @@ for i := 1 to Parameters^.Count do s^ := s^ + ' ' + Parameters^[i]^; if @CmdLine <> nil then CmdLine := s^; - Message (2, s^); + Message (1, s^); Dispose (s) end; ProgressMessageStartSubprocess; @@ -730,16 +744,6 @@ UnitNameMatch := LoCaseStr( Dep.SrcBaseName ) = LoCaseStr( InterfaceName ); end;
-function NewUsesElement (const InterfaceName, FileName: String; Next: PUnitList) = p: PUnitList; -begin - New (p); - p^.InterfaceName := LoCaseStr (InterfaceName); - p^.FileName := FileName; - MD5Clear (p^.MD5); - p^.Dep := nil; - p^.Next := Next -end; - procedure GetDep (var Dep: TDep);
function ReadBufferAndIncludes (var OutputFile: File; var StdErrFile: Text; var Buffer: PBytes; @@ -1345,10 +1349,13 @@ ps := DepToDo^.Dep^.LinkedFiles; while ps <> nil do begin - { Just make sure the file is added to Deps. We don't need - any dependency relations because files linked with - linker directives can be compiled at any time. } - Discard (FindDep (ObjectPath, ps^.s, '', fk_CFile)); + { Must compile $L files before implementation. } + CurrentDep := FindDep (ObjectPath, ps^.s, '', fk_CFile); + AddDepList (CurrentDep^.Dep^.UsedBy[False], DepToDo^.Dep); + DepToDo^.Dep^.UsedUnits[False] := NewUsesElement ( CurrentDep^.Dep^.InterfaceName, CurrentDep^.Dep^.SrcName, DepToDo^.Dep^.UsedUnits[False]); + // what FileName should I use? + DepToDo^.Dep^.UsedUnits[False]^.Dep := CurrentDep^.Dep; + DepToDo^.Dep^.UsedUnits[False]^.IsUnit := False; ps := ps^.Next end; DepToDo := DepToDo^.Next
Hello,
Thanks a lot for the patch. I will try it.
For the link problem, from my previous email:
By putting this list of libraries at the end of the link command, it
worked.
But since I have no control on this at the gp command-line level I cannot make it work.
I saw something like this with libpcre and libxml2 - reordering the libraries fixed the problem without any changes to gp.
The problem here is not the order of the libraries in the list (I had a lot of - let's say - "fun" with this in the past). It is the position of the list of libraries in the link command. It is placed between the -L and -I directives, and before the -o exec_name and the list of objects that make the program. Just moving the list of libraries at the end of the command solves the problem. Since the command is generated by gp, I hope something can be done about this in gp.
Thanks
Pascal Viandier pascal@accovia.com
Peter N Lewis wrote:
Pascal Viandier wrote:
First: There are some objects from c sources not found at link time. I put {$L my_c_extern.c} in a Pascal source but gp says "my_c_extern.c must be compiled" and stops instead of compiling it (I think since is knows that the source must be compiled, it should do it, no?). Then I tried {$L my_c_extern.o} instead and gp says " My_c_extern.c:999: undefined reference to 'symbol' where 'symbol' is defined in a third party library for which I put a -l directive on gp command-line.
I believe this is due to a bug I fixed in my copy of gp. It stems from the comment:
{ Just make sure the file is added to Deps. We don't need any dependency relations because files linked with linker directives can be compiled at any time. }
which I believe is erroneous. A patch (based on my subversion history) is attached below, but I do not know if it interacts with any of the other patches I've done.
<snip> Also, I noticed that objects are written in the same directory as gpi files despite the option --object-destination-path=obj on the gp command-line.
I can't help you much with that, as I don't use it. But for {$L}, gp stores a gpd file, so it would need to go somewhere.
gp patch follows. This is definitely not any sort of official patch. My gp has wandered far from the track.
I ran into the same problem this morning but Peter's patch, applied by hand to gp-0.61, solved the problem.
Regards,
Adriaan van Os
That's rigth. I applied the patch too and it solved this part of the gp problems. I try now to solve the other two I found: - The position of the libraries in the link command (this prevents the creation of the executable) - The --object-destination-path not passed along in the gpc command (this one clutters my gpi directory with objects).
Although I do not have much time I will try to make clean fixes and perhaps you will be interested to have them :-)
Regards
Pascal Viandier pascal@accovia.com
-----Message d'origine----- De : gpc-owner@gnu.de [mailto:gpc-owner@gnu.de] De la part de Adriaan van Os Envoyé : November 29, 2005 10:51 À : gpc@gnu.de Objet : Re: Compiling with gp
Peter N Lewis wrote:
Pascal Viandier wrote:
First: There are some objects from c sources not found at link time. I put {$L my_c_extern.c} in a Pascal source but gp says "my_c_extern.c must be compiled" and stops instead of compiling it (I think since is knows that the source must be compiled, it should do it, no?). Then I tried {$L my_c_extern.o} instead and gp says " My_c_extern.c:999: undefined reference to 'symbol' where 'symbol' is defined in a third party library for which I put a -l directive on gp command-line.
I believe this is due to a bug I fixed in my copy of gp. It stems from the comment:
{ Just make sure the file is added to Deps. We don't need any dependency relations because files linked with linker directives can be compiled at any time. }
which I believe is erroneous. A patch (based on my subversion history) is attached below, but I do not know if it interacts with any of the other patches I've done.
<snip> Also, I noticed that objects are written in the same directory as gpi files despite the option --object-destination-path=obj on the gp command-line.
I can't help you much with that, as I don't use it. But for {$L}, gp stores a gpd file, so it would need to go somewhere.
gp patch follows. This is definitely not any sort of official patch. My gp has wandered far from the track.
I ran into the same problem this morning but Peter's patch, applied by hand to gp-0.61, solved the problem.
Regards,
Adriaan van Os