IndySockets / Indy

Indy - Internet Direct
https://www.indyproject.org
434 stars 147 forks source link

Unable to build for C++ Builder 5 #533

Closed megaXD2 closed 2 months ago

megaXD2 commented 2 months ago

Maybe I'm not reading the instructions correctly, but I can't seem to build the .BPL file required for a legacy project I maintain in C++ Builder 5. When running Fullc_5.bat in the Lib folder, I'm given a single error near the end: IdGlobal.pas(6211) Fatal: Internal error: C1093

The branch I'm trying to build under is Delphi5-workarounds. I did attempt to build under the master branch, but was given pretty much the same error.

Output of Fullc_5.bat: https://pastebin.com/90v1FUeZ

rlebeau commented 2 months ago

There is not enough information to diagnose why it failed. It is an internal error, the compiler crashed on something it can't handle.

That being said, I just updated the delphi5-workarounds branch with the latest code from master, so try updating and let me know if the problem still happens.

megaXD2 commented 2 months ago

Thanks for the quick response. I've pulled the changes and attempted to run it again, only to be met with the same error. The only difference being the line number changed ((6219) instead of (6211)).

Is there anything I can perform on my end to provide a better diagnosis on this issue?

rlebeau commented 2 months ago

Sorry, I didn't notice the line number on the error message.

So, the problem is with the implementation of the GetTickDiff64() function? USE_INLINE should be undefined for Delphi 5, so the inline shouldn't be a factor here. Maybe Delphi 5 has a problem with the Int64 return value? Or the Int64 type-casts? Maybe even the Int64 arithmetic? Int64 was still pretty new back then and handling of it was sometimes buggy.

megaXD2 commented 2 months ago

Something odd I noticed is that it would sometimes pass Compile IndySystem50 - Round 1 in the Fullc_5.bat file and would read IdGlobal.pas just fine, but then proceed to fail on the same file in Round 2 shortly afterwards. The only difference being a missing flag between the cfg1 and cfg2 of the IndySystem50.cfg files (-JPHNE). I'm honestly not sure if that's anything significant, but thought it would at least be worth mentioning.

Also, pardon my ignorance on this, but I'm not very familiar with Delphi itself, so I'm unsure what else I can do to help at this time. I'll keep trying with what I can on my end to see if there's anything else I can do.

megaXD2 commented 2 months ago

Disregard my previous comment. The error I keep encountering with IdGlobal.pas seems to be very random. I've persisted on each step in the Batch file and finally ran into an actual error (on Round 1a/1b/2 for IndyProtocols50):

IdHL7.pas(1575) Error: Undeclared identifier: 'PByte'
IdHL7.pas(1575) Error: There is no overloaded version of 'GetString' that can be called with these arguments
IndyProtocols50.dpk(268) Fatal: Could not compile used unit 'IdHL7.pas'

This error seems to happen regardless of the branch I use (master and Delphi5-workarounds)

rlebeau commented 2 months ago

I've persisted on each step in the Batch file and finally ran into an actual error (on Round 1a/1b/2 for IndyProtocols50):

IdHL7.pas(1575) Error: Undeclared identifier: 'PByte'
IdHL7.pas(1575) Error: There is no overloaded version of 'GetString' that can be called with these arguments
IndyProtocols50.dpk(268) Fatal: Could not compile used unit 'IdHL7.pas'

This error seems to happen regardless of the branch I use (master and Delphi5-workarounds)

That makes no sense. PByte is used all over the place in Indy, and especially in IdGlobal.pas which is compiled before IdHL7.pas. PByte absolutely does exist in C++Builder/Delphi 5.

megaXD2 commented 2 months ago

That makes no sense. PByte is used all over the place in Indy, and especially in IdGlobal.pas which is compiled before IdHL7.pas. PByte absolutely does exist in C++Builder/Delphi 5.

Yeah, I'm a bit confused about this as well. Not sure why it would be complaining about this one particular line, when it seemed to do fine on everything else. Given the issues I've had prior, I suspect that the machine I'm building on is just a bit too different for this to work. I'm going to try and build this on a different machine and see if maybe that's the issue.

megaXD2 commented 2 months ago

Different machine with a fresh install of C++ Builder 5 did not work. Maybe the copy of C++ Builder 5 I have isn't the right one? Regardless of where it's installed, it results in the exact same errors.

rlebeau commented 2 months ago

Unfortunately, I don't have C++Builder 5 available to install and test with. But if you figure out what is happening, I'll gladly incorporate a fix for it.

megaXD2 commented 2 months ago

Unfortunately, I don't have C++Builder 5 available to install and test with. But if you figure out what is happening, I'll gladly incorporate a fix for it.

Sure thing. If this matters at all, the installation of C++ Builder 5 I've been using comes from an .iso on WinWorld. It works for what I've needed so far. Seems to work fine on Windows 10 as well. And just FYI for anyone else that may see this, attempting to build Indy 10 (using Fullc_5.bat) on different versions of Windows (XP, 10, etc.) yields the same results.

I doubt I'll find anything any time soon, but if by some miracle I figure out what it's doing, then I'll let you know.

megaXD2 commented 2 months ago

I was able to figure out a fix for the unusual C1093 error I've been inconsistently getting. The only reference I had for this fix was from a different project on Github called "Fundamentals 5", where they suffered a similar issue with the Delphi 5 compiler. I think it had something to do with how Delphi 5 handles 64-bit variables, but I honestly have no idea (again, not an expert at this stuff). Either way, you were right to suspect Int64 arithmetic being the issue.

The fix involved splitting variables from the arithmetic operators and using a temporary variable to perform the arithmetic step-by-step instead:

function GetTickDiff64(const AOldTickCount, ANewTickCount: TIdTicks): TIdTicks;
{$IFDEF USE_INLINE}inline;{$ENDIF}
{$IFDEF VCL_50}
var
  d: TIdTicks;
{$ENDIF}
begin
  {This is just in case the TickCount rolled back to zero}
  if ANewTickCount >= AOldTickCount then begin
    {$IFDEF VCL_50}
    d := ANewTickCount;
    d := d - AOldTickCount;
    Result := TIdTicks(d);
    {$ELSE}
    Result := TIdTicks(ANewTickCount - AOldTickCount);
    {$ENDIF}
  end else begin
    {$IFDEF VCL_50}
    d := High(TIdTicks);
    d := d - AOldTickCount;
    d := d + ANewTickCount;
    d := d + 1;
    Result := TIdTicks(d);
    {$ELSE}
    Result := TIdTicks(((High(TIdTicks) - AOldTickCount) + ANewTickCount) + 1);
    {$ENDIF}
  end;
end;

This is by no means an elegant solution, but I'm able to run Fullc_5.bat without having to modify it to loop per "failed" round.

Unfortunately, I still haven't figured out the error with PByte and the issue with the overloaded GetString function. I'll keep looking into this, but I haven't found any good solutions so far.

EDIT: Couldn't help but notice this comment you made within IdSSLOpenSSL.pas (starting line 2177). Maybe something similar can be done to fix the other issue?

            {$IFNDEF VCL_6_OR_ABOVE}
            // RLebeau: for some reason, Delphi 5 causes a "There is no overloaded
            // version of 'GetString' that can be called with these arguments" compiler
            // error if the PByte type-cast is used, even though GetString() actually
            // expects a PByte as input.  Must be a compiler bug, as it compiles fine
            // in Delphi 6.  So, converting to TIdBytes until I find a better solution...
            RawToBytes(LBufPtr^, LLen)
            {$ELSE}
            PByte(LBufPtr), LLen
            {$ENDIF}
rlebeau commented 2 months ago

I was able to figure out a fix for the unusual C1093 error I've been inconsistently getting.

Does it still work ok if you use Inc() and Dec() instead?

function GetTickDiff64(const AOldTickCount, ANewTickCount: TIdTicks): TIdTicks;
{$IFDEF USE_INLINE}inline;{$ENDIF}
{$IFDEF VCL_50}
var
  d: TIdTicks;
{$ENDIF}
begin
  {This is just in case the TickCount rolled back to zero}
  if ANewTickCount >= AOldTickCount then begin
    {$IFDEF VCL_50}
    d := ANewTickCount;
    Dec(d, AOldTickCount);
    Result := d;
    {$ELSE}
    Result := TIdTicks(ANewTickCount - AOldTickCount);
    {$ENDIF}
  end else begin
    {$IFDEF VCL_50}
    d := High(TIdTicks);
    Dec(d, AOldTickCount);
    Inc(d, ANewTickCount);
    Inc(d);
    Result := d;
    {$ELSE}
    Result := TIdTicks(((High(TIdTicks) - AOldTickCount) + ANewTickCount) + 1);
    {$ENDIF}
  end;
end;

Couldn't help but notice this comment you made within IdSSLOpenSSL.pas (starting line 2177). Maybe something similar can be done to fix the other issue?

Ok. I'll apply a similar fix to this case.

megaXD2 commented 2 months ago

Does it still work ok if you use Inc() and Dec() instead?

Can confirm that Inc() and Dec() works on my end 👍

rlebeau commented 2 months ago

I just checked in a fix for this in both master and Delphi5-workarounds branches

megaXD2 commented 2 months ago

Thank you very much for your help. I was able to build it with the new changes (+ one additional change). Apparently IdHTTP.pas has the same issue as well (line 883), but I made a similar change on my end to get a successful build.

And though it isn't the right place to talk about this (since the current issue is now closed), I keep getting an Assertion Failure from IdGlobal.pas (around line 7577) when attempting to use various GET/POST functions with an HTTP component in C++ Builder 5. I'm sure I'm writing something wrong on my end, but I'll open a separate issue if I can't find any solutions.

Thanks again for the assistance.

rlebeau commented 1 month ago

Thank you very much for your help. I was able to build it with the new changes (+ one additional change). Apparently IdHTTP.pas has the same issue as well (line 883), but I made a similar change on my end to get a successful build.

I have checked in another update for that.

And though it isn't the right place to talk about this (since the current issue is now closed), I keep getting an Assertion Failure from IdGlobal.pas (around line 7577) when attempting to use various GET/POST functions with an HTTP component in C++ Builder 5. I'm sure I'm writing something wrong on my end, but I'll open a separate issue if I can't find any solutions.

Please do open a separate ticket for that.