When I compile my application under Delphi 2006 I get the following warning
[Pascal Warning]- W1002 Symbol 'FileSetDate' is specific to a platform
What must I do to suppress this warning?
The code
MyLastError:= FileSetDate( Files[ i ].Handle, DateTimeToFileDate( arcDate ) );
1) In the project options you can choose the compiler messages you want to see.
If you don't care about platform independency you can just switch off the platform warning there.
2) Another way is disabling the warning for a certain part of the code:
{$WARN SYMBOL_PLATFORM OFF}
// Your code
{$WARN SYMBOL_PLATFORM ON}
For a complete list of options look at the Delphi help file at the topic '$WARN'
3) A last way would be adding
{$WARNINGS OFF}
// Your code
{$WARNINGS ON}
but that is dangerous, because all warnings will be suppressed.
4) Additionally, as the other answers have already suggested, you could just switch to the platform independant variant of FileSetDate which works on file names (i.e. Strings), but as far as I understand that was not your question.
Although the answer of DR solves the warning, it is not the correct solution.
You should use the platform independent version of FileSetDate:
function FileSetDate(const FileName: string; Age: Integer): Integer; overload;
Also in SysUtils.
You can turn off the platform unit and platform symbol compiler warnings. They are obsolete (and disabled in Delphi 2009 by default). They were introduced when there was a Delphi for Linux (Kylix). They do not have a meaning anymore. Especially with the replacement of Delphi.NET with Delphi Prism.
You can turn them off for the whole project in the Project Options dialog (Compiler Messages).
Related
I still use Delphi XE4 (newest compiler I use of multiple Delphi compilers) and need a specific workaround for the fact they completely hid FClients in TBasicAction in this version. I connect/disconnect clients runtime while setting enabled/disabled (to avoid flicker with ~100+ actions and ui elements) thus this workaround for XE4:
Here's my naive attempt and simply returning the field.
TmscBasicActionCrack = class(TBasicAction)
end;
{$IFDEF mymsDELPHIXE4}
TmscBasicActionHelper = class helper for TBasicAction
public
function Helper_Get_Private_FClients: TList<System.Classes.TBasicActionLink>;
end;
{$ENDIF}
{$IFDEF mymsDELPHIXE4}
//------------------------------------------------------------------------------
function TmscBasicActionHelper.Helper_Get_Private_FClients: TList<System.Classes.TBasicActionLink>;
begin
Result := Self.FClients;
end;
{$ENDIF}
However, I get error
E2003 Undeclared identifier: TList<>
I must admit I never go around to using generics with Delphi since I initially heard of stability problems + I need to maintain compability with Lazarus/FreePascal.
I am aware the most recent versions Delphi has altered class helpers again, but I am for now mostly interested in getting this to work with Delphi XE4
The error is indicating that the TList<T> type is unknown to the compiler. To use it you must include System.Generics.Collections in your uses clause.
I have this piece of code:
INTERFACE
{$WARN SYMBOL_PLATFORM OFF}
USES
Winapi.Windows, etc, {$IFDEF MSWINDOWS}Vcl.FileCtrl, {$ENDIF} System.IniFiles;
{$WARN SYMBOL_PLATFORM ON}
The compiler shows:
[dcc32 Warning] W1005 Unit 'Vcl.FileCtrl' is
specific to a platform
even though the {$WARN SYMBOL_PLATFORM OFF} is there.
Why?
You are using the wrong directive. SYMBOL_PLATFORM controls warnings for symbols marked platform specific. Your warning relates to a unit marked platform specific.
Control these warnings with UNIT_PLATFORM.
The whole unit is tagged (using the platform hint directive) as one that contains material that might not be available on all platforms. If you are writing multi-device applications, the unit might cause a problem. For example, a unit that uses objects defined in OleAuto might be tagged using the PLATFORM directive.
The $WARN UNIT_PLATFORM ON/OFF compiler directive turns on or off all warnings about the platform directive in units where the platform directive is specified.
There's a really easy way for you to work this out for yourself. Take a look at the two documentation topics I linked to above. Their titles are:
W1002 Symbol '%s' is specific to a platform (Delphi)
W1005 Unit '%s' is specific to a platform (Delphi)
The compiler warning that you received names the warning as W1005. This is all you need to know to determine which directive to use to control it. If you have any trouble finding them simply search for the warning name, W1005 in this instance. Or refer to the documentation that lists them all.
I get the CromisIPC cromis ipc site download and compile/rum successfully the demos and custom project on delphi XE5. Without any error.
But, when I get the same code and put on DELPHI 7 project, I have an error on unit Cromis. AnyValue, an compilation error.
TAnyValue = packed record
private
ValueData: TValueDataType;
{$IFDEF AnyValue_HookingOff}
IntfData : IInterface;
{$ELSE}
{$IFNDEF CPUX64}
Padding : array [0..3] of Byte;
{$ENDIF}
{$ENDIF}
ValueType: TValueType;
function GetAsInt64: Int64; inline;
Exactly on lyne:
ValueData: TValueDataType;
[Error] Cromis.AnyValue.pas(210): ',' or ':' expected but identifier 'ValueData' found
[Error] Cromis.AnyValue.pas(219): 'END' expected but 'FUNCTION' found
I use delphi 7 on a 64 bits windows 7 with a 32 bits VCL project.
The same code compiles on XE5.
What happens here ? any idea ?
tl;dr This code is not designed to work under Delphi 7.
Visibility specifiers are not allowed in Delphi 7 records. The compiler is objecting to the use of private. You can remove that, but then the next problem will be all the methods that are declared on the record. Again, they are not available in Delphi 7.
You might be able to make some headway by switching from packed record to packed object. However, I think it highly unlikely that this will be smooth sailing. Expect a lot of work to make this code compile on Delphi 7. Frankly, you would need to be a Delphi expert to take on this task.
You might try to find an old version of the library that actually supports Delphi 7. You might be able to get one from the library's author. But note that the website says:
All code is Delphi 2006 and upwards compatible. I will not support older Delphi version. If you still use them, then its time to upgrade.
Which leads to the other obvious solution. Upgrade to a modern version of Delphi.
If that is impossible, then you should look for a different library.
Delphi 2007 (and newer) supports enabling DEP and ASLR via any of these three techniques:
add the command-line switch –dynamicbase when compiling with dcc32
add the preprocessor command {$DYNAMICBASE ON} to the source code
manually OR in the bit in the header, with {$SETPEOPTFLAGS $40} in the source code
I'd like to be able to do the same thing with Delphi 2006 and C++ Builder 2006 (aka BDS 2006). Does anyone know how to do this?
Set PE flags
You can use {$SetPEOptFlags $40} to set the DEP flag, and {$SetPEOptFlags $100} to set the ASLR flag. To set both use {$SetPEOptFlags $140}.
If you have a version of Delphi with the necessary definitions in the Windows.pas unit you can use the much more readable:
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_NX_COMPAT or
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE }
Typically you include the $SetPEOptFlags setting in the .dpr file. And so you need to make sure that Windows is in the .dpr file uses clause for these IMAGE_XXX constants to be available.
Set DEP policy at runtime
For versions that don't support PE flag based approaches you can call this function early in your app's initialization:
procedure EnableDEP;
const
PROCESS_DEP_ENABLE: DWORD=$00000001;
var
SetProcessDEPPolicy: function(dwFlags: DWORD): BOOL; stdcall;
begin
SetProcessDEPPolicy := GetProcAddress(GetModuleHandle(kernel32),
'SetProcessDEPPolicy');
if Assigned(SetProcessDEPPolicy) then begin
//don't bother checking for errors since we don't need to know if it fails
SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
end;
end;
This will work for any version of Delphi.
You cannot set the ASLR flag at runtime since it influences how the module is loaded. So ASLR can only be set using PE flags.
Modifying PE flags for very old versions of Delphi
Older versions of Delphi do not support $SetPEFlags and $SetPEOptFlags. For such versions you need to use an external tool to modify the executable post-build. When I originally wrote this answer I assumed that EDITBIN from the MS toolchain would do the job. For DEP it will suffice, using the /NXCOMPAT option. For ASLR you will need to use a different PE flag editor. My websearch revealed peflags from cygwin.
peflags --dynamicbase=true --nxcompat=true MyApp.exe
I'm sure there are other PE flag editing options available.
‘{$DYNAMICBASE ON}’ is new in Delphi2007, ‘{$SETPEOPTFLAGS $40}' was an existing directive: info
{$SetPEOptFlags $40} works in Delphi2006
I am using Delphi 7 IDE. Does Delphi compiler optimize codes, just like what the C++ compiler is doing in this following link?
http://msdn.microsoft.com/en-us/library/aa366877(VS.85).aspx
WCHAR szPassword[MAX_PATH];
// Retrieve the password
if (GetPasswordFromUser(szPassword, MAX_PATH))
UsePassword(szPassword);
// Clear the password from memory
SecureZeroMemory(szPassword, sizeof(szPassword));
If ZeroMemory were called in this example instead of SecureZeroMemory, the compiler could optimize the call because the szPassword buffer is not read from before it goes out of scope. The password would remain on the application stack where it could be captured in a crash dump or probed by a malicious application.
Yes, of course Delphi performs optimizations. However, it does not perform the optimization that the SecureZeroMemory function is meant to circumvent. There is no need to use that function in Delphi; just use plain old ZeroMemory, or even FillChar. They're not macros, and they don't do anything that Delphi recognizes as being unused assignment statements that could get optimized out.
Delphi performs code optimization by default, you can disable it in Project > Options > Compiler.
The Delphi help provide a few tips of what type of optimizations are used:
The $O directive controls code optimization. In the {$O+} state, the compiler performs a number of code optimizations, such as placing variables in CPU registers, eliminating common subexpressions, and generating induction variables.
It also states that "the compiler performs no "unsafe" optimizations", but in the sense that they won't alter the execution path, not from a security point of view.
Delphi certainly optimizes code (it is a modern, and excellent, compiler). Another example of optimization deleting lines is:
SomeFunction(); // Set breakpoint here, then step (F10)
myInt := 7; // Next line will not hit this...
myInt := 13; // ...but will instead skip to here
I like to ensure optimization is in the correct state (and not accidentally left switched on or off) by adding {$I MyProjectOptions.inc} in every .pas file in my project. This goes just below the unit name (right at the top of the file). In "MyProjectOptions.inc" you simply add this code:
// Is this a debug or non-debug build?
{$IF Defined(DEBUG)}
{$O-} // Turn optimization off
{$ELSEIF Defined(NDEBUG)}
{$O+} // Ensure optimisation is on
{$IFEND}
Finally, ensure you have defined "DEBUG" and "NDEBUG" (or your equivalent in older versions of Delphi) in the Conditional defines section of Project > Options > Diectories/Conditionals.
I don't believe the compiler will ever eliminate apparently dead code like this. I have never had trouble setting breakpoints on code that could have been eliminated as redundant.
For some scenarios, the compiler can detect if the code is unreachable and eliminate the code.
For instance, the compiler correctly eliminates the "unreachable" portion of the code below.
It will not generate code for that line so:
So there are no blue bullets indicating there is code
Breakpoints put on that line will be marked visually as 'not reachable'
Just tested in Delphi XE, but older Delphi versions have similar behaviour.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
procedure Test;
begin
if (True = False) then
Writeln('Unreachable')
else
Writeln('Reachable');
end;
begin
try
Test();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
It takes quite some while to learn when (or when not) the optimizer on code level and liker level kicks in.
For instance: When you have optimizations turned on, the compiler will also eliminate variables as soon as they are not used.
Sometimes, it even eliminates global symbols.
Danny Thorpe (former Delphi Compiler engineer and Chief Scientist) once wrote a magic method Touch that prevents this.
Just call this Touch method at the end of your method to fool the optimizer during debugging:
procedure Touch(var arg);
begin
end;
--jeroen