Jump to content
Incus J

Invalid Compiler Directive: 'MESSAGES'

Recommended Posts

I'm trying to compile an FMX project with ICS 8.64 (installed in Delphi 10.4 via the GetIt Package manager) and getting the following error:

 

[dccosx64 Error] Ics.Posix.Messages.pas(57): E1030 Invalid compiler directive: 'MESSAGES' at the following line:

 

{$IFNDEF MSWINDOWS }
  {$MESSAGES Fatal 'This unit should not be included in a Windows project. Make sure you use Winapi.Messages instead'}
{$ENDIF}

The program is for macOS and uses ICS HTTP and SSL components.  It used to compile and run OK.  However it was last compiled some time ago, for macOS 32-bit.  I'm now recompiling it for macOS 64-bit, since 32-bit programs no longer run on macOS.  I'm wondering if the line above should read {$IFDEF MSWINDOWS} instead of {$IFNDEF MSWINDOWS} - but thought I'd ask before I tinker with it.

Share this post


Link to post

that should be $MESSAGE 

 

{$IFNDEF MSWINDOWS }
  {$MESSAGE Fatal 'This unit should not be included in a Windows project. Make sure you use Winapi.Messages instead'}
{$ENDIF}

 

  • Like 1

Share this post


Link to post

Thanks Vincent - I've corrected it to $MESSAGE, and now when building, the compiler actually displays that error i.e.

"This unit should not be included in a Windows project..."

 

But this is not a Windows project - it's a macOS 64-bit project.  

So I was wondering whether it should actually read { $IFDEF MSWINDOWS } - would make more logical sense?

Edited by Incus J

Share this post


Link to post

OK I've corrected (I think) $IFNDEF to $IFDEF and the compiler gets further.  The sticking point is now in OverbyteIcsUtils:

 

[dccosx64 Error] OverbyteIcsUtils.pas(2391): E1025 Unsupported language feature: 'ASM'

function IcsSwap16(Value: Word): Word;
{$IFDEF PUREPASCAL}
begin
    Result := (Value shr 8) or (Value shl 8);
{$ELSE}
asm
{$IFDEF CPUX64}
    MOV   AX, CX
{$ENDIF}
    XCHG  AL, AH
{$ENDIF}
end;

It doesn't like the line 'asm' which makes sense because (unlike 32-bit) the 64-bit compiler doesn't support inline assembly.  My guess is it needs to use the PUREPASCAL version when compiling for macOS 64-bit.  However I haven't found where PUREPASCAL is defined yet.  Maybe I can add it as a directive in the project options?

Share this post


Link to post

OK, PUREPASCAL added as a Compiler Directive in the project options.  I think this is called winging-it.  Next up:

 

[dccosx64 Error] OverbyteIcsUtils.pas(6956): E2033 Types of actual and formal var parameters must be identical

function TIcsFindList.AddSorted(const Item2: Pointer; Compare: TListSortCompare): Integer;
begin
    if NOT Sorted then
        Result := Count
    else begin
       if Find (Item2, Compare, Result) then exit;
    end ;
    Insert (Result, Item2) ;
end;

Result is an Integer, but Find defines its 3rd 'index' parameter as a LongInt.  

 

Oh! - lightbulb moment.  ICS expects a 32-bit compiler, where Integer and LongInt are likely the same size.  But macOS requires a 64-bit compiler, where one of those (either Integer or LongInt, but not both) will be 64-bits.  Out of my depth - what do you mean you can tell? :)

Share this post


Link to post

I've fixed the $MESSAGE issue, I added that but it is not tested by building FMX packages. 

 

PUREPASCAL was defined OverbyteIcsUtils.pas for CPUX64 but is currently suppressed since we now have the necessary assembler.  I'll set it for MacOS64

 

I've fixed the AddSorted mismatch, does not show up under Win64. 

 

Please let me know of any other MacOS errors you find, I can not test this since I don't have any Mac hardware.  Won't be in SVN for a few days.

 

Angus

Share this post


Link to post

That sounds brilliant - thank you Angus.

 

I'm happy to test Mac stuff (macOS Catalina, VMWare Fusion hosting a Windows 10 guest running Delphi 10.4)

 

Share this post


Link to post

Have you built and installed the three packages for FMX without any more errors.  That is the most important and useful test.   Ideally from the overnight zip, but there will be more changes before the next release.

 

Angus

Share this post


Link to post

At the moment I've got as far as:

 

[dccosx64 Error] Ics.InterlockedApi.inc(3): E1025 Unsupported language feature: 'ASM'

{$IFDEF CPUX64}
function InterlockedIncrement(var Addend: LongInt): LongInt;
asm
       MOV   EAX,1
  LOCK XADD  [RCX].Integer,EAX
       INC   EAX
end;

I don't think there's a PUREPASCAL version of that function.

I will grab the overnight zip now and have another try.  

Share this post


Link to post

Sorry, can not help with InterlockedIncrement, that code was written by a developer that is no longer with us, and appears to be using some CPU feature for a few functions like Posix.Messages,  TIcsThreadTimer and web sessions,  The last assembler I wrote was Z80 for Wang Word Processing, over 30 years ago. 

 

Hopefully some watching here might have a clue what this interlocking is all about?

 

Angus

 

Share this post


Link to post

OK, that error hasn't appeared so far in the overnight zip.  Here's some quick progress notes from the overnight zip:

 

- Opened Install/D104InstallVclFmx.groupproj

- Build IcsCommonD104Run.dproj (bplIcsCommonD104Run.dylib)

- Target Platform set to macOS 64-bit

- With PUREPASCAL added as a project compiler directive:

 

[dccosx64 Error] OverbyteIcsUtils.pas(7015): E2003 Undeclared identifier: 'FileSetAttr'

function IcsDeleteFile(const Fname: string; const ReadOnly: boolean): Integer;
var
    attrs: integer ;
begin
    result := -1 ;    // file not found
    attrs := FileGetAttr (Fname);
    if attrs < 0 then exit;
    if ((attrs and faReadOnly) <> 0) and ReadOnly then begin
        result := FileSetAttr (Fname, 0);
        if result <> 0 then result := 1;
        if result <> 0 then exit;  // 1 could not change file attribute, ignore system error
    end ;
    if DeleteFile (Fname) then
        result := 0   // OK
    else
        result := GetLastError; // system error
end ;

FileSetAttr is Windows only I think.  To continue I surrounded with {$IFDEF MSWINDOWS} to bypass file attribute routines.

 

[dccosx64 Error] OverbyteIcsStreams.pas(263): E2137 Method 'SetSize' not found in base class

In the base class Stream, the SetSize parameter NewSize takes a LongInt or Int64, but not an Integer.

To continue I changed NewSize to a LongInt.

 

[dccosx64 Error] OverbyteIcsStreams.pas(288): E2137 Method ‘Read’ ‘Write’ ‘Seek’ not found in base class

In the base class TStream, parameters and Result for Read, Write, Seek are LongInt (not Integer).

To continue I changed all offending parameters to LongInt.

 

[dccosx64 Error] OverbyteIcsStreams.pas(1362): E2037 Declaration of 'Create' differs from previous declaration

To continue I changed BufferSize to LongInt.

 

[dccosx64 Error] OverbyteIcsStreams.pas(328): E2137 Method 'Create' not found in base class

To continue I changed BufferSize to LongInt.

 

[dccosx64 Error] OverbyteIcsStreams.pas(380): E2137 Method 'Create' not found in base class

To continue I changed BufferSize to LongInt.

 

[dccosx64 Error] OverbyteIcsCRC.pas(237): E1025 Unsupported language feature: 'ASM'

Note: Inline assembly not supported by 64-bit compiler.

 

Got stuck at this point because I don’t know the equivalent pascal for the assembly instruction: bswap eax

Since the function is only a single line of code, I can probably figure out the intension from the function declaration.

 

If it is useful I can zip up the files I've modified?

Share this post


Link to post

Side tracking slightly, what was the last ICS version you successfully built with MacOS32?  I believe V8.62 at least was successful for MacOS from reports here. 

 

While I understand the ASM problems, not sure why all these LongInt problems are happening when Win64 is happy. 

 

In CRC, function Endian can be killed, no longer used, don't think it worked anyway. 

 

Might be better to wait until you have found all the compiler errors before sending anything, but I'm quite happy to update as you report them.

 

Angus

 

Share this post


Link to post

It's a good while back - maybe as far back as XE4, so definitely the previous macOS 32-bit compiler.  But it all worked including SSL.  It helps that macOS includes OpenSSL.  I can try 8.62 and see what happens. 

 

Yes, it does seem odd that the Win64 compiler is happy to consider Integer vs Longint equivalent, but not the macOS compiler, since they target the same CPU.

 

OK, I'll plough on and see how far I can get.

 

Ah the Z80 - lovely instruction set (my misspent childhood with a Sinclair ZX Spectrum 🙂

Share this post


Link to post

Thanks, done most of your changes, don't worry about MacOS32 if it is now dead.  

 

The Wang Z80 development environment was luxury compared to CP/M PCs at the time, it originally had CDC 14in platter disk drives with 75 or 300 megs of storage and used the Intel PL/M language (which CP/M was also written in).  

 

Angus

 

Share this post


Link to post

OK - I've removed the unused Endian function.  Next up is:

 

[dccosx64 Error] OverbyteIcsSSLEAY.pas(2105): E2003 Undeclared identifier: 'size_t'

    f_SSL_bytes_to_cipher_list :               function(s: PSSL; cbytes: PAnsiChar; len: size_t; isv2format: Boolean; var sk: PSTACK_OF_SSL_CIPHER; var scvsvs: PSTACK_OF_SSL_CIPHER): LongInt; cdecl = nil;   { V8.64 }

size_t is defined as a UInt64 or LongWord on line 85 and 87 of OverbyteIcsTypes.pas - but only for MSWINDOWS.  There are quite a few nested IFDEFs here, so I need to be careful making any modification.

 

75 megs does sound like luxury, compared to 48K of RAM and compact cassette for storage.

Share this post


Link to post
3 hours ago, Angus Robertson said:

InterlockedIncrement

Replace that with AtomicIncrement or the Increment method from System.SyncObjs.TInterlocked

Share this post


Link to post

For the missing size_t, try adding this to types:

 

{$IFDEF POSIX}
  {$IFDEF CPUX64}
    size_t                    = UInt64;
  {$ELSE}
    size_t                    = LongWord;
  {$ENDIF}
    Psize_t                   = ^size_t;
{$ENDIF POSIX}
 

Not sure if the 32-bit line is necessary, seems strange MacOS did not give an error if it was missing.

 

Angus

 

Share this post


Link to post

For the InterlockedIncrement asm issue, add this to the top of Ics.InterlockedApi.inc:

 

{$IFDEF COMPILER23_UP}

function InterlockedIncrement(var Addend: LongInt): LongInt;
begin
    Result := TInterlocked.Increment(Addend);
end;

{$ELSE}
(and a closing endif at the end). 

 

OverbyteIcsWSocket and OverbyteIcsUtils both need the suppressed PUREPASCAL define replaced with:

 

  {$IFDEF MACOS}
    {$DEFINE PUREPASCAL}
  {$ENDIF}
 

These should get your compile a little further.

 

Angus

Share this post


Link to post

Thanks Angus, David

 

That solved size_t OK.

 

[dccosx64 Warning] OverbyteIcsUtils.pas(1304): W1073 Combining signed type and unsigned 64-bit type - treated as an unsigned type

Result := Int64(Buf.f_bfree) * Buf.f_frsize

I’ve ignored this warning for now, but I could cast to Int64(Buf.f_frsize) ?

 

[dccosx64 Error] OverbyteIcsZlibHigh.pas(385): E2033 Types of actual and formal var parameters must be identical

strm.next_out  := DMAOfStream(OutStream, strm.avail_out);

DMAOfStream defines parameter out Available as Integer.  However strm.avail_out, part of a record, z_stream, is LongInt.

To continue I redefine DMAOfStream to use a LongInt parameter, rather than mess with the size of the z_stream record structure that might be populated from a disk buffer (?)

 

…but doing that causes:

 

[dccosx64 Error] OverbyteIcsZlibHigh.pas(309): E2033 Types of actual and formal var parameters must be identical

BackObj.InMem := DMAOfStream(InStream, BackObj.InMemSize);

Again, DMAOfStream, but now the situation is reversed, InMemSize is defined as Integer, and the redefined DMAOfStream requires LongInt.  So I might try redefining strm.avail_out from LongInt to Integer instead, and hope that doesn't damage the size of the z_stream record structure.

 

Share this post


Link to post

Lets worry about warnings once all the errors have gone, I changed dozens of integers to longint in streams so there may be more warnings to come. I'll put my changed units in SVN later today.

 

Not touched zlib for many years, keep meaning to update to a newer version.   I'll have a look later.

 

Angus

 

 

 

Share this post


Link to post

Sounds good.  In z_stream I've redefined strm.avail_out (and also strm.avail_in) from LongInt to Integer to get a bit further.

 

Good news is your InterlockedIncrement suggestion worked, with a small adjustment:  

function InterlockedIncrement(var Addend: Integer): LongInt;

I defined Addend as Integer, because routines that call this function pass in an Integer parameter.

Integer seems a better fit here, TInterlocked.Increment has overloaded versions for Integer and Int64, but not LongInt.

 

[dccosx64 Error] OverbyteIcsSuperObject.pas(278): E2100 Data type too large: exceeds 2 GB

 TSuperObjectArray = array[0..(high(PtrInt) div sizeof(TSuperObject))-1] of ISuperObject;

[dccosx64 Fatal Error] OverbyteIcsSuperObject.pas(859): F2613 Unit 'Winapi.Windows' not found.

uses
 {$IFDEF RTL_NAMESPACES}System.SysUtils,{$ELSE}SysUtils,{$ENDIF}
 {$IFDEF UNIX}
   baseunix, unix, DateUtils
 {$ELSE}
   {$IFDEF RTL_NAMESPACES}Winapi.Windows{$ELSE}Windows{$ENDIF}
 {$ENDIF}
 {$IFDEF FPC}
   ,sockets
 {$ELSE}
   ,{$IFDEF RTL_NAMESPACES}Winapi.WinSock{$ELSE}WinSock{$ENDIF}
 {$ENDIF}
  ;

I have bypassed the two Winapi statements using {$IFDEF MSWINDOWS}.  This unit performs calculations with dates and times, and seems to use Winapi to do this:

 

[dccosx64 Error] OverbyteIcsSuperObject.pas(1074): E2003 Undeclared identifier: 'PSystemTime'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1075): E2005 'PSystemTime' is not a type identifier

[dccosx64 Error] OverbyteIcsSuperObject.pas(1080): E2017 Pointer type required

[dccosx64 Error] OverbyteIcsSuperObject.pas(1122): E2003 Undeclared identifier: 'PTimeZoneInformation'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1123): E2003 Undeclared identifier: 'PFileTime'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1128): E2003 Undeclared identifier: 'TSystemTime'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1129): E2003 Undeclared identifier: 'TFileTime'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1146): E2003 Undeclared identifier: 'TIME_ZONE_ID_INVALID'

[dccosx64 Error] OverbyteIcsSuperObject.pas(1158): E2003 Undeclared identifier: 'FileTimeToSystemTime'

 

 

 

Edited by Incus J

Share this post


Link to post

A lot of that SuperObject date handling code, like time zones and system time, duplicates stuff elsewhere in ICS and can be probably be removed to save space and simplicity.  I was adding new functions to SuperObject last month, so may as well remove some as well.  Probably not today, like to test SO properly. 

 

Angus

 

Share this post


Link to post

Just a suggestion from someone who also wrestled with supporting multiple Delphi versions in his library:

Use AtomicXXX throughout the code and declare them for the older Delphi versions that did not have them yet - that way you get the best code generated by the newer compilers that know about these intrinsics rather than putting indirections for everyone in order to be backwards compatible.

Edited by Stefan Glienke
  • Like 1

Share this post


Link to post

That would make sense, except the 10.4 help says System.AtomicIncrement is only in mobile compilers, AtomicIncrement on it's own is not mentioned.  In which version was it added?

 

Angus

 

Share this post


Link to post

They are all available on all platforms and got introduced in XE3 - feel free to copy excerpts from Spring.pas - or some other libraries that have similar implementations

For reference: https://bitbucket.org/sglienke/spring4d/src/ffee3360a2e8cb9ae5311621a745bb9ed809870f/Source/Base/Spring.pas#lines-2729

And let me know if you find any defect 😉

Edited by Stefan Glienke

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×