Delphi {$INCLUDE filename} in uses part of dpr file - delphi

I have many Delphi 10 projects that are using the same units, let's call them "commons".
When I add anew unit to commons, I have to manually add it to each project. I have tried adding a {$INCLUDE commons.inc} line into the uses part of each .dpr file:
uses
Forms,
{$INCLUDE commons.inc}
projectUnit1,
...;
commons.inc has this content:
common1,
common2,
I can compile a project but cannot manage the units from commons.inc. By manage, I mean Ctrl-F12, remove from project, etc.
This is from Delphi's help:
There is one restriction to the use of include files: an include file can't be specified in the middle of a statement part. In fact, all statements between the begin and end of a statement part must exist in the same source file.
I suppose that is why my idea does not work?
Am I doing something wrong, or is there another solution?

This workaround might suit. The only downside I have found so far is that the included files do not appear in the Project Manager.
Add the folder(s) containing the files to be included to the search path of every project.
Create Include.pas, a normal .pas file, and include it in the normal way in every project.
Add the files to be included in multiple projects to the uses clause of Include.pas. $IFDEFS can be used if required.

Related

How to use templates defined in other package without adding source file to the project?

I've created a package which contains several templates (TFrame descendants).
These templates has been added to the palette.
In other packages, I'm trying to use these templates but each time I add one of them, a message appear:
The following unit: %s, is needed in your project to create the
template. Do you wish to add it?
mrYes:
Source file is added to the project.
Furthermore, it causes the following error on compiling:
E2200 Package '%s' already contains unit '%s'
mrNo:
It's ok, but the question is asked each time I place one of my
templates. Me and my collegues will use these templates alot of times and I really would like to avoid that message.
Update 1:
Here are steps to observe the described behavior:
Create a package project named Package1.
Add a TFrame descendant named MyTest.
Add TMyTest to palette (Structure window, right click, add to
palette).
Set project output directories to .\out
Build the project.
Add \out to library path.
In the same projectgroup, create a package project named Package2.
Add Package1, to "requires" (in Package2.dpk).
Add a form.
Add a TMyTestTemplate to the form.
Update 2:
I'm looking for a solution which works with Delphi 2007 and Delphi XE7.
A bit more work but one that should fit your needs:
Create Package FooRuntime(Mark RuntimeOnly), add your TMyFrame
Create Package FooDesignTime(Mark DesigntimeOnly), requires FooRuntime, Registers your frame
Install FooDesignTime
Link your other project to FooRuntime
Without the packages the IDE seems to fail to recognize the units.

How to define and use precompiled variable in delphi directives

I want to define a precompile string variable and use it in {$include} directive in delphi, for example:
{$define FILE_NAME "lockfile"}
{$include FILE_NAME'.txt.1'}
{$include FILE_NAME'.txt.2'}
...
For security reasons (this is part of our licensing system), we don't want to use normal strings and file reading functions. Is there any capability for this purpose in Delphi?
The $INCLUDE directive does not support indirection on the file name. So, the following code:
const
someconst = 'foo';
{$INCLUDE someconst}
leads to the following error:
F1026 File not found: 'someconst.pas'
If you must use an include file, you must apply the indirection by some other means. One way could be to use the fact that the compiler will search for the included file by looking on the search path. So, if you place each client specific include file in a different directory, then you can add the client specific directory to the search path as part of your build process.
FWIW, I find it hard to believe that this will make your program more immune to hacking. I think that a more likely outcome is that your program will be just as susceptible to hacking, but that it will become much more difficult and error prone for you to build and distribute the program.
You requirement may be better satisfied by the proper use of a VCS system. You need "branches" for every customer where customer-specific files contains customer-specific data. This will avoid to litter your code with complex directive to manage each customer - file names stays the same, just their content is different in each branch. Adding a new customer just requires to create a new branch and update files there.
Then you just need get each branch and compile it for each customer to get the final executable(s) with customer specific data built in.

conditional include in FSharp

I would like to convert a bunch of fs files to fsx files.
Each of those fs file reference class defined in, say, base.fs
So instead of being compiled in the project and relying on the compiler resolution, all would be file based.
That means if I have all those file to include base.fsx, and that one file references another, base.fsx would be included twice.
Does anyone know how to make a conditional include with fsx files ?
The preprocessor documentation states
There is no #define preprocessor directive in F#. You must use the
compiler option or project settings to define the symbols used by the
#if directive.
If you're loading all the files from a single fsx script, then you can load the individual files from the project in the right order and the individual library files do not need to load base.fs directly - the code will be defined, because it has been loaded before.
For example, if you have base.fs:
module Base
let test() = 10
and you have more.fs which does not load base.fs but uses the functions defined there:
module More
let more () =
Base.test() + 1
then you can load all files in F# interactive (in, say, script.fsx) and it will work fine:
#load "base.fs"
#load "more.fs"
More.more()
The only disadvantage is that you won't get IntelliSense when editting more.fs (because the editor does not know about base.fs). To workaround that, it is probably a good idea to keep the files in a project in Visual Studio. But you can still load them in F# interactive for experimentation & testing.

Is it possible to find out position of a unit in project's uses clause?

I have two units (SuperPuper.pas and SuperPuper777.pas) in a project (.exe or .dll)
Is it possible to find out at runtime from my code in SuperPuper777.pas that
SuperPuper.pas is listed in project's uses clause;
SuperPuper.pas is first unit in project's uses clause.
The question was heavily edited. I guess that it's practical purpose is to find out if ShareMem.pas unit was declared in right position in project's uses clause.
If you want to enforce the correct declaration of a unit in a project's uses clause I would add a pre-build event to run a regex based Perl/Python/Ruby script. The script would do a simple regex based check of the .dpr file and return an error if it was not as intended. Not fool-proof, but probably the best balance of utility for a small amount of effort.
I realise that your question asks for runtime detection but this is a compile time property and so best attacked at compile time.
You can get a list of all units linked to the executable (i.e. at runtime) from the resources. There is a resource named PACKAGEINFO which contains a list of all units. You can find some reverse information from here. Perhaps you can get this information from enhanced RTTI (available since Delphi 2010).
About how to detect that an unit is first in the .dpr uses clause, I do not see any way of doing it at runtime easily. The list in PACKAGEINFO is not in this order. You can do that at compile time, by parsing the .dpr content and checking its uses clause.
The only way I see to guess which unit was first set is to use a global variable in a common unit:
var LatestUnitSet: (oneUnit, anotherUnit);
Then in the initialization section of each unit:
initialization
LatestUnitSet := OneUnit;
...
initialization
LatestUnitSet := anotherUnit;
...
Then check for LatestUnitSet to see which one was initialized the latest.

Including client files for shared file

Okay, so I have 2 projects for a game. One is the server and one is the client. I keep the shared units into a shared folder that I use to include in my client/server project. There is a problem however: I have a shared file that needs a different file for client / server. Example: mySharedLib needs to print to the console, however the client/server console is different. What are my options? Thanks
In your shared file you could use define compiler directive
For example
{$IFDEF MYSERVER}
Writeln('Server'); // this code executes
{$ELSE}
Writeln('Client'); // this code does not execute
{$ENDIF}
Then in your server project define a MYSERVER define and in your client define a MYCLIENT one, then when the shared code seperates use an {$IFDEF) statement.
From the Delphi help on conditional definitions:
The conditional directives $IFDEF, $IFNDEF, $IF, $ELSEIF, $ELSE, $ENDIF, and $IFEND allow you to compile or suppress code based on the status of a conditional symbol. $IF and $ELSEIF allow you to base conditional compilation on declared Delphi identifiers. $IFOPT compiles or suppresses code depending on whether a specified compiler switch is enabled.
This will not however work if the shared code is in a DLL or any other sort of complied shared resource such as a package.
From the Delphi help on conditional definitions:
Conditional definitions are evaluated only when source code is recompiled. If you change a conditional symbol's status and then rebuild a project, source code in unchanged units may not be recompiled. Use Project|Build All Projects to ensure everything in your project reflects the current status of conditional symbols.
If they're different, they're not really a shared file anymore.

Resources