• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 418
  • Last Modified:

conditionally include files in a project

Is there a method to conditionally include files in a project?
0
boardtc
Asked:
boardtc
  • 7
  • 6
  • 2
  • +2
2 Solutions
 
Ivanov_GCommented:
{$DEFINE DEBUG_VERSION}

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs
  {$IFDEF DEBUG_VERSION}
  , ADODB
  {$ENDIF}
  ;
0
 
boardtcAuthor Commented:
Thanks for the comment. What I meant was file added ot the dpr, if you try the above in the dpr the compiler ovewrites it on the next build. Thanks, Tom.
0
 
Ivanov_GCommented:
Sorry, I forgot to mentions:

instead of {$DEFINE TEST} go to Project / Options / Directories/Conditionals/ Conditionals
and add TEST there.

Thus conditionals are saved in the .DOF file, so next build will be OK
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
andrewjbCommented:
No!

(Easy answer!)

You could sort of do it by using {$Include ...} (I think that's the directive!) in a file, then protecting this via {$IfDef..}, but that's pretty awful.

0
 
boardtcAuthor Commented:
Sorry should have been more specific, not wanting to do this via the project options page...i am trying for a way to do it via code.

The way you do an include is {%File 'my file name'}
All includes in the uses of a project are overwritten at the next build.

Anyone know of a way to do this ?

Thanks, Tom.
0
 
andrewjbCommented:
You can't do it directly that way at all.

The best you can do is something like:

1) Have a unit called 'Includer.pas'
2) Have this always in your project
3) Have it do something like:

{$IfDef IWantIt}
 {$Include RealFile.pas}
{$else}
  interface;
  implementation;
{$endif}

Ugh!

0
 
boardtcAuthor Commented:
OK! So my undertandiong is we have to have a .pas file (Includer.pas) so as it will not be overwritten in the dpr.

This pascal file is essentially a wrapper for my other pascal units ( RealFile.pas, etc).

Trying the above gives the message interface expected  but unit found, which is expected really. removing the unit declaration and basically disguising an include file as a pascal file gives a unit name mismatch error. Not seeing a solution...

anyone?

Cheers, Tom.

ps. searching usenet people were talking about using .mak files. never done that and don't know how but not sure I want to get into that :-)
0
 
andrewjbCommented:
This isn't really a good practice way of doing things, even if you can get it working..

What are you actually trying to achieve?
0
 
boardtcAuthor Commented:
In the dpr I can do

program MyProgram

{%File 'myfilename.pas'}

uses
 ....

and myfilename appears in the project manager. However when another usit uses myfilename in the the uses clause it will recognize it. However if myfilename is added to the prject (ie appears  in the uses : above myfilename in myfilename.pas) then it compiles fine.

My goal here is that there is some functionality that I only want to conditionaly include in the program using the sme code base if that makes sense...cheers mate.

0
 
DeerBearCommented:
Hi!

Your best bet, imho, is to use Packages. Googling a bit, you should find a few artiicles explaining how to use them in order to add functionalities to an application.

HTH,

Andrew
0
 
andrewjbCommented:
Delphi doesn't really have the support at all to do this. You're probably better off having two or three project files and only including the units you need in each one. It isn't happy otherwise.

0
 
boardtcAuthor Commented:
Thanks for that. Having 2 or 3 project files kind of defeats the purpose of using conditionals in this way as one would use a different project file dpening on wheter a condition was defined or not...

Had seen pakages mentiioned in googling, guess I don't know enough about them to undertand how they could be used with conditional defines. Will do some research.

tom.
0
 
DeerBearCommented:
Hi Tom( hope you don't mind if I call you tom ),

I wasn't actually hinting at using conditional defines but to use of plug-ins, which are the most elegant way to solve your problem - imho.

Another way you could go after is using conditional defines *inside* the desired units, leaving them empty if not needed. Something like this:

unit MyDefineDrivenUnit;

interface
 
  {$IFDEF MyDefine}
      uses MyOtherUnit;
     
      procedure DoX;
  {$ENDIF}

implementation

  {$IFDEF MyDefine}
     procedure DoX;
     begin
        // Code here
     end;
  {$ENDIF}
 
end.

HTH,

Andrew
0
 
andrewjbCommented:
Could you give a concrete example of what you might want to conditionally include? We might be able to suggest a better solution.
0
 
boardtcAuthor Commented:
Thanks guys. I'm not undertanding the confusion so i'm obviously not explaining well at all.  

It's not as simple as wrapping functions in conditional defines, I'm tallking about whole units here. Say I have one class which contains another class conditionally, if the condition is defined then there needs to be x number of units included in the project, if it isn't I don't want those units included.  Are packages / plugin's the way to do this? I've no experience of doing it with either. This any clearer?

Thanks, Tom,
0
 
andrewjbCommented:
I understand what you're trying to do, but don't understand why you might want to do that. Delphi doesn't have the capabilities to conditionally include complete units. You might be able to hack something in using some odd technique such as I was attempting to explain. But you're asking for trouble.

What I was trying to ask for was an example of exactly _why_ you need to do this? It's kind of an odd thing to want to do. Having separate project files with the correct units included does seem much more like the way to go..

0
 
Wim ten BrinkSelf-employed developerCommented:
So you want to create two versions of your application? One being for example a demo version with limited functionality and the other is the real version?

Well, the {$IFDEF} way can be used to include/exclude units after you do a rebuild. (Not recompile!) The {$INCLUDE} can add a piece of Pascal source in your project.

But if you want to exclude some unit from your project, you will have to exclude it everywhere, where you're using it in your uses clause. Not only in your main dpr file but perhaps also from your mainform and other units.

This example has been provided already but has one additional feature. It also provides an additional file extention.

{$IFDEF Test}
{$E 'exe'}
uses
  Forms,
  SysUtils,
  Windows,
  frmMain in 'frmMain.pas' {FormMain};
{$ELSE}
{$E 'mod'}
uses
  Forms,
  frmMain in 'frmMain.pas' {FormMain};
{$ENDIF}

If Test is defined in your project options, your executable will use SysUtils and Windows and be called Project1.exe. Otherwise, those units will still be included since frmMain and Forms are using them too and thus you either have to add those conditions there too or just accept it that they cannot be removed. But the binary will now be called Project1.mod instead of .exe, which is reasonable usable.

Finally, if you have a class that contains another class, then there's nothing conditional about it. Unless you've used {$IFDEF} to make it conditional. But if you did that, you can use the same {$IFDEF} all over your code to include/exclude the units.

But a nicer way to use these kinds of conditional stuff is by splitting your project into a main executable and several DLL's. If you load those DLL's dynamically then it just depends if the DLL can be found to determine if your system has a certain capability or not. You try to load the DLL and if it fails, you don't have this capability.
0
 
boardtcAuthor Commented:
Andrewjb - thanks for your perseverance with me man...i guess I could not see the wood from the trees at all, of course I should just include the files in one dpr and not the other....i think!

But what my motivation was is that we bespoke from a set base and my idea was in the bespoke I'd have the conditional define and that would turn on/off the functionality without having to worry about adding certain files to the project.

hmmm... there must be a way to set conditions in code rather than going through the project options dialog, that would be better...more research beckons.

Workshop-alex : ok..trying to see how a dll solution would work. If something was turned on we'd need the class to be contained  in another (hence the conditional defines)...but a dll could not affect the conditional define as that would have top be done at compile time...how would it work?

Thanks guys, Tom.
0
 
Wim ten BrinkSelf-employed developerCommented:
For some project of mine I needed to be able to create debug information in certain situations. To do this I created a separate DLL (source at http://www.workshop-alex.org/Sources/Debug/Debug.zip) that I would compile which would allow me what I just said above. If the DLL is there, I would get two files with comments that were written to them. If the DLL isn't there then those log files would not be created. The advantage is that when I needed to find a problem, I would copy the DLL in the same folder as the executable, thus enabling the debug functionality. Then some testing and once I was done I removed the DLL and log files again so the user would not be bothered by these files.

The idea behind this was that I needed an object in the DLL that would be accessible from the main executable. And it does contain an object. However, within Delphi you can't mix objects between the executables and DLL's without confusing your memory management. So I created an interface too that would export the object methods that I need to the executable. (Interface is defined in intTextfile.pas if you're interested.) This interface would be known by both the executable and the DLL. The DLL would also have a function that gets exported that returns an object/interface to whomever calls it. (Functions GetLogFile and GetDebugFile in debug.dpr.)
My main application would just try to load the DLL (unit cp_Debug) and if it could load it, it would create two logfiles that communicate with the DLL. (One log file with and the other without timestamps.) If it would fail to load then no problem. The unit itself contains a dummy interface that just does nothing, so any writes to the logfiles would just be ignored.

So since this solution doesn't use any conditional defines, you would get one executable and one DLL. The DLL would provide any additional functionality and this could be accessed through the interface that is defined in both the DLL and the EXE.
There are some limitations to this technique, though. But those are normal for any application that uses DLL's. The most important ones are that you can't (easily) use strings and dynamic arrays between DLL and EXE and you can't share objects between them either, unless you share them through interfaces. Forms usage is therefore also a bit limited.
The technique is also a bit complicated to learn at first since you have to get used to how interfaces work. You could compare them to classes with only abstract methods and no data. But with experience you could use this technique for some very powerful solutions.
And this technique is a step closer to developing ActiveX controls...

Also, splitting up your project in one EXE and one or more DLL's does make it easier to alter things your projects. It divides functionality over multiple binaries.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 7
  • 6
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now