Incus J 10 Posted August 3, 2020 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
Vincent Parrett 763 Posted August 3, 2020 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} 1 Share this post Link to post
Incus J 10 Posted August 3, 2020 (edited) 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 August 3, 2020 by Incus J Share this post Link to post
Incus J 10 Posted August 3, 2020 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
Incus J 10 Posted August 3, 2020 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
Angus Robertson 577 Posted August 3, 2020 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
Incus J 10 Posted August 4, 2020 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
Angus Robertson 577 Posted August 4, 2020 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
Incus J 10 Posted August 4, 2020 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
Angus Robertson 577 Posted August 4, 2020 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
Incus J 10 Posted August 4, 2020 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
Angus Robertson 577 Posted August 4, 2020 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
Incus J 10 Posted August 4, 2020 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
Angus Robertson 577 Posted August 4, 2020 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
Incus J 10 Posted August 4, 2020 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
David Heffernan 2353 Posted August 4, 2020 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
Angus Robertson 577 Posted August 5, 2020 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
Angus Robertson 577 Posted August 5, 2020 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
Incus J 10 Posted August 5, 2020 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
Angus Robertson 577 Posted August 5, 2020 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
Incus J 10 Posted August 5, 2020 (edited) 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 August 5, 2020 by Incus J Share this post Link to post
Angus Robertson 577 Posted August 5, 2020 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
Stefan Glienke 2019 Posted August 5, 2020 (edited) 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 August 5, 2020 by Stefan Glienke 1 Share this post Link to post
Angus Robertson 577 Posted August 5, 2020 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
Stefan Glienke 2019 Posted August 5, 2020 (edited) 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 August 5, 2020 by Stefan Glienke Share this post Link to post