Multiple project conditional compilation Delphi - delphi

I work in a Project Group composed by 3 projects with common units.
in project 1, i wrote in the project source :
program Project1;
{$DEFINE FIRSTPROJECT}
uses
.....
in project 2, i wrote in the project source :
program Project2;
{$DEFINE SECONDPROJECT}
uses
.....
Then in the differents units code i wrote :
...
{$IFDEF FIRSTPROJECT}
do this
{$ELSE}
do that
{$ENDIF}
...
The first project code is never compiled (it's just ignore). But if i put the {$DEFINE FIRSTPROJET} in same unit then it work... (in Delphi2009).
How can i spread my compilation directive threw all the file used ? Just depending on which project i want to compile...

$DEFINE directives are local to the unit in which they are defined. If you place them in a project source file, a .dpr file, then they apply in that .dpr file only.
You need to add the conditional defines to each of your projects by using the Project Options dialog.

Related

The initialization part is not called

I'm maintaining the VirtualTreeView component for Delphi and C++Builder. With Delphi everything is okay but when I compile the packages with the C++Builder the code in the initialization part in the Delphi units is not called. Any ideas?
When a Delphi unit's initialization/finalization sections are not being called in a C++Builder project, it usually means the Delphi unit is not being linked into the final executable, typically because the C++ code is not directly referencing any code in the unit, so it gets optimized out. C++Builder is a bit more aggressive about removing unused code than Delphi is. In Delphi, simply adding a unit to a uses clause forces that unit to be linked to. That is not the case in C++. #includeing a Delphi unit's .hpp file in C++ code is not enough to guarantee the unit is linked to, if the C++ code does not use anything from the .hpp file.
Indy ran into this problem in several of its units, most notably IdAllAuthentications, IdAllFTPListParsers, and IdAllHeaderCoders. These units all contain only initialization/finalization code, no interface code, so their generated .hpp files were basically empty. To force linkage, I had to add {$HPPEMIT} statements to the interface section to output #pragma link statements in the generated .hpp files. For example:
unit IdAllAuthentications;
interface
{
Note that this unit is simply for listing ALL Authentications in Indy.
The user could then add this unit to a uses clause in their program and
have all Authentications linked into their program.
ABSOLUTELY NO CODE is permitted in this unit.
}
{$I IdCompilerDefines.inc}
// RLebeau 2/14/09: this forces C++Builder to link to this unit so
// the units can register themselves correctly at program startup...
{$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
{$HPPEMIT LINKUNIT}
{$ELSE}
{$HPPEMIT '#pragma link "IdAllAuthentications"'}
{$ENDIF}
implementation
// uses units that self-register in their initialization sections ...
end.
{$HPPEMIT LINKUNIT} was introduced in XE5 Update 2, to help with linking units that use unit-scope names:
New: You can now use HPPEMIT Delphi compiler directives for linking and generating C++ namespace declarations.
...
{$HPPEMIT LINKUNIT} replaces #pragma link for the iOS device target platform.
For more information, see HPPEMIT.
For C++ applications, {$HPPEMIT LINKUNIT} replaces #pragma link on mobile platforms.
The Delphi run time has units that must be linked in order to enable some functionality. In C++, auto-linking was previously achieved using the following directive:
{$HPPEMIT '#pragma link "<unitname>"'}
Now you should use the following directive instead:
{$HPPEMIT LINKUNIT}
LINKUNIT generates a #pragma link statement that references the calling unit using the correct decorated/namespaced unit name.

What to NOT do to prevent Delphi from mangling the uses list and {$*.RES} in a .DPR

Every couple of weeks, I bump into this: when doing an IDE operation on the uses units in a Delphi project, it mangles the .dpr file.
What happens is that it rebuilds the uses list, but gets the position wrong.
I'm wondering what usage pattern to avoid so I won't get into this error again.
I've had this error occur in many Delphi versions. I know it exists in at least Delphi XE2 (it happened there again today), XE, 2007, 2006 and 7.
The mangled fragment usually is structured like this:
ususes
Forms,
..
LastUnitInUses in 'LastUnitInUses.pas';
R *.RES}
and should be corrected by removing one us, and adding a {$:
uses
Forms,
..
LastUnitInUses in 'LastUnitInUses.pas';
{R *.RES}
Example file that went wrong:
program SysUtilsFormatTests;
{
Delphi DUnit Test Project
-------------------------
This project contains the DUnit test framework and the GUI/Console test runners.
Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options
to use the console test runner. Otherwise the GUI test runner will be used by
default.
}
{$IFDEF CONSOLE_TESTRUNNER}
{$APPTYPE CONSOLE}
{$ENDIF}
ususes
Forms,
TestFramework,
GUITestRunner,
TextTestRunner,
SysUtilsFormatUnit in 'SysUtilsFormatUnit.pas';
R *.RES}
begin
Application.Initialize;
if IsConsole then
with TextTestRunner.RunRegisteredTests do
Free
else
GUITestRunner.RunRegisteredTests;
end.
Example of corrected .dpr file:
program SysUtilsFormatTests;
{
Delphi DUnit Test Project
-------------------------
This project contains the DUnit test framework and the GUI/Console test runners.
Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options
to use the console test runner. Otherwise the GUI test runner will be used by
default.
}
{$IFDEF CONSOLE_TESTRUNNER}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
Forms,
TestFramework,
GUITestRunner,
TextTestRunner,
SysUtilsFormatUnit in 'SysUtilsFormatUnit.pas';
{$R *.RES}
begin
Application.Initialize;
if IsConsole then
with TextTestRunner.RunRegisteredTests do
Free
else
GUITestRunner.RunRegisteredTests;
end.
The only thing that I know that works is for you to let the IDE manage the .dpr file.
Don't add comments.
Don't use conditionals like $IFDEF.
Don't modify the code in the .dpr file.
if you do any of these things, expect the IDE to bite back.
Personally I do all of these and fight back at commit time. I use my VCS to defend against bogus IDE changes. It's not ideal, but it's the best option.

Is there a conditional define for library projects in Delphi?

I have a utility unit with code shared between a few applications and DLLs. I'd like to selectively compile portions of this unit based upon the current project type: Application, Package, or Library. I couldn't find any conditional definitions for a library or package in the System unit, and Google didn't find anything relevant. So, are there any conditional defines such as IsLibrary or IsPackage set by the compiler? I'm aware of the IsLibrary variable, by the way.
There is no such pre-defined conditional, and there could not be such a conditional. That's because at compilation time it is impossible to know whether the unit will, ultimately, be linked into an executable, a library or a package.
In fact, the same compiled unit could be linked into any or all of the above project types. And indeed you can see this yourself when you link the RTL into your projects. You link the same System unit, the same compiled .dcu file, into all your projects, irrespective of the project type.
IMHO there is absolutly no need for such conditionals because of existing conventions.
Compiling an Application or Library (the same on this compiling aspect) or a Package differs like so:
Application/Library will compile only the used parts from the unit
Package will compile all parts from the unit referenced by the interface part of the unit
Example Unit
unit foo;
interface
procedure foo1;
procedure foo2;
implementation
procedure foo3;
begin
// used by foo2, compile depends on foo2 compilation
end;
procedure foo4;
begin
// will never be compiled, because is never used
end;
procedure foo1;
begin
// Package: will always be compiled
// Application/Library: will be compiled if used
end;
procedure foo2;
begin
// Package: will always be compiled
// Application/Library: will be compiled if used
foo3;
end;
end.
That is also a reason, why using packages may result in bigger exe files, because it can contain unused code parts from precompiled dcu files.

Empty main form in GUI app converted from Delphi to Lazarus

I have converted my 2 GUI apps from Delphi to Lazarus.
Both apps compile for Win32 platform, i386 and with GUI.
Main form were converted using Lazarus tool and can be edited from IDE.
But when I run such application main form does not appear, only blank form without any controls.
I tried to debug this. It runs all code in initialization sections,
and runs code from .lpr project, but something wrong happens in CreateForm() because
it doesn't run code in the main form OnCreate event. In event log I can see all
texts I write to it with '<App.Run' appearing after I close this empty form.
Code in .lpr project:
Application.Initialize;
AddToEventLogInfo('App.CreateForm');
Application.CreateForm(TfrmTst, frmTst);
AddToEventLogInfo('App.Run>');
Application.Run;
AddToEventLogInfo('<App.Run');
I checked that I am able to create simple GUI apps from the Lazarus, but both converted GUI
apps do not work as expected. What can be wrong? Have I missed something?
Maybe one of many warnings and hints Lazarus write is important?
When I run my app Lazarus writes this:
windres: warning: 14: "MAINICON": 1045: duplicate value
windres: warning: 16: 1: 1045: duplicate value
Project "Tst_fpc" successfully built. :)
EDIT:
Lazarus conversion tool converted .dfm -> .lfm, but has some problems with .pas file. I had to manually:
add Lazarus units to uses:
uses
{$IFDEF FPC}
LCLIntf, LResources,
{$ENDIF}
Conditional compile Delphi form {$R *.dfm}:
{$IFNDEF FPC}
{$R *.dfm}
{$ENDIF}
Add .lrs resource in initialization code:
initialization
{$IFDEF FPC} {$i myunit.lrs} {$ENDIF}
I suspect that the mainform unit (I assume it is called utest) doesn't have a {$I utest.lrs} in its initialization section. The .lrs is the lazarus resource file, created from the lfm (dfm) in delphi.
The empty form is the form of for the current project as you used the convert Delphi project from tools which means the current project is active.
Try this:
On the project option close the current project.
On the small main window named as project wizard, use the convert Delphi project option.
I'm sorry I can't give you a straight answer. From what I understand there's a problem a problem with the resource file. In delphi that's the *.res, I don't know what they look like in Lazarus. Use a program like resedit, http://www.resedit.net/, to open the resource file. I tried it and found a "folder" Icon where there was a post MAINICON. I'm guessing you have two. In that case remove one of them.

Delphi 7 make complains about files not found

I've got a BPG file that I've modified to use as a make file for our company's automated build server. In order to get it to work I had to change
Uses * Uses
unit1 in 'unit1.pas' * unit1
unit2 in 'unit2.pas' * unit2
... * ...
in the DPR file to get it to work without the compiler giving me some guff about unit1.pas not found.
This is annoying because I want to use a BPG file to actually see the stuff in my project and every time I add a new unit, it auto-jacks that in 'unitx.pas' into my DPR file.
I'm running make -f [then some options], the DPR's that I'm compiling are not in the same directory as the make file, but I'm not certain that this matters. Everything compiles fine as long as the in 'unit1.pas is removed.
It could come from the fact, that the search path in the IDE and the search path of the command line compiler are not the same. If you change the serach path of the command line compiler you might be able to use the exactely same source code as within the IDE.
One possibility to configure the search path for the command-line compiler is to do it in a file called dcc32.cfg. Take a look at the help, there is a short description of dcc32.cfg in the IDE-help.
Well this work-around worked for me.
//{$define PACKAGE}
{$ifdef PACKAGE}
uses
unit1 in 'unit1.pas'
unit2 in 'unit2.pas'
...
{$else}
uses
unit1
unit2
...
{$endif}
The only problem is whenever you add a new unit, delphi erases your ifdef package at the top.
Every time I have to put conditionals into a project file I do this:
program a;
uses
ACondUnits;
...
unit ACondUnits;
interface
uses
{$IFDEF UseD7MM}
Delphi7MM;
{$ELSE}
FastMM4;
{$ENDIF}
implementation
end.
Maybe this trick works in packages too. Never tried.

Resources