One Delphi package is falsely detected as depending from other package - delphi

Recently I developed and installed VlControls Delphi package with own components.
Now when any developer on any machine takes other, one year old, CmGUI package, which existed long before VlControls, and tries to build it, following window pops up:
The following changes are necessary to make this package compatible with other installed packages.
Choose OK to apply these changes and rebuild the package.
Add VlControls.
VlControls contains implicit unit(s) TeeBlockCanvas, TeeMesh, TeeBlockEditor, TeeBlockGallery, TeeBlockClasses, TeeWater, TeeBlocks, TeeMakerConst, TeeLoadError, TeeTarga, TeeGLSLShaders, TeeViewBlock, TeeCamera, TeeMakerControl, TeePlayMP3, TeeTextureSelector, TeeMakerEditor, TeeSelectProperty, TeeClipBlock, TeePointEditor, Tee3DSFormat, TeeFacesBlock, TeeObjFormat, TeeSubdivideMesh, TeePointItemEditor, TeeActionGallery, TeeSoundSelector, TeeMakerLibrary, TeeLoadBlock, TeeExtruded, TeeRoundRect, TeeMoveAnimation, TeeNumberAnimation, TeeExtrudedEditor, TeeActionAnimation, TeeBlockAnimations, TeeBlockReplacer, TeeHelix, TeeRain, TeeBlockFormat, TeePipe, TeeProperties, TeeDraw3DEditor, TeeKinematics, TeeColorPalette, TeeRevolutionEditor, TeeRevolution, TeeAnimationGallery, VCLTee.TeeAnimateEditor, TeeTerrain, TeeEdgeStyle, TeeStairs, TeeChartBlock3DEditor, TeeChartBlock, TeeChart3D.
I do not know why this happens, because both packages are completely independent from each other. There are no files in CmGUI which contain "VlControls" string. What both packages have in common, are Tee chart components.
This happens only to this CmGUI package and other old packages are intact.
What could it be?
I am using Delphi 10.
CmGUI.dpk:
package CmGUI;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS OFF}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS OFF}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO OFF}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl,
vcl,
vclx,
dbrtl,
adortl,
tee923,
designide,
vclactnband,
dclstd,
OurPackageNumber1,
OurPackageNumber2,
vcltouch,
NxCommonRun_d10,
NxGridRun_d10,
TeePro923,
TeeUI923,
TeeImage923,
TeeGL923,
VclSmp,
vclFireDAC,
FireDACIBDriver,
FireDACPgDriver,
IndyProtocols,
NxCollectionRun_d10;
contains
//Here come units from this package only. No external units are included.
end.
VlControls.dpk:
package VlControls;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS OFF}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO OFF}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE RELEASE}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl,
vcl,
vclimg,
vclx,
TeePro923,
TeeUI923,
Tee923,
DesignIDE,
TeeImage923,
TeeGL923,
dbrtl,
FireDAC,
FireDACCommonDriver,
FireDACCommon,
IndySystem,
IndyCore;
contains
//Here come units from this package only. No external units are included.
end.
Update
Ok, I looked closely at my package and handled all warnings it displayed at compile time. Now the contains section has following units:
TeeBlockCanvas,
TeeChart3D,
TeeChartBlock3DEditor,
TeeAnimationGallery,
TeeColorPalette,
TeeDraw3DEditor,
TeeProperties,
TeeBlockReplacer,
TeeEdgeStyle,
TeeLoadBlock,
TeeSoundSelector,
TeeActionGallery,
TeeMakerLibrary,
TeeMakerControl,
TeeCamera,
TeePointItemEditor,
TeeSelectProperty,
TeeTextureSelector,
TeeBlockFormat,
TeeSubdivideMesh,
TeePointEditor,
TeeGLSLShaders,
TeeLoadError,
TeeChartBlock,
TeeMesh,
TeeTerrain,
TeeMakerEditor,
TeeClipBlock,
TeeMoveAnimation,
TeeActionAnimation,
TeeBlockAnimations,
TeeNumberAnimation,
TeeKinematics,
TeeBlockEditor,
TeeBlockGallery,
TeeBlockClasses,
TeeViewBlock,
TeeExtrudedEditor,
TeeHelix,
TeeRevolution,
TeeRevolutionEditor,
TeeStairs,
TeeRain,
TeeWater,
VCLTee.TeeAnimateEditor,
TeePlayMP3,
Tee3DSFormat,
TeeObjFormat,
TeeFacesBlock,
TeePipe,
TeeExtruded,
TeeRoundRect,
TeeBlocks,
TeeMakerConst,
TeeTarga;
As I understand, next step would be to look at each unit and find out which package it belongs to and then add package name to requires section removing unit name from contains section.
How to find out which package the unit belongs to if I have no *.pas files, but only *.bpl and *.dcu?

Obviously your package uses a lot of units from a TeeChart package (or several packages? I don't know TeeChart very well). Do not implicitly import them, just put the packages your explicit units (i.e. the units you explicitly name in the contains section) need in the requires section.
Not only does that make your package a lot slimmer, it also avoids such naming conflicts. Anyone who uses your package will face a naming conflict when using other packages that contain units with the same name. That is why the IDE, recognizing that all or most of the packages the other package uses, are in your package, recommends linking to your package.
If your package did not contain these units, that wouldn't happen. That is why you should always, really always, avoid having implicitly imported units. If that happens, you get a warning (during compilation of the package). Heed it.
Example (package MyControls):
contains
MyUnit;
and in MyUnit:
unit MyUnit;
uses
TeeThis, TeeThat, TeeOther;
Now the TeeThis, TeeThat and TeeOther units are implicitly linked into your package. But if your package references the other package that contains these TeeXXX units (say, TeeChart.bpl), the compiler will not add them to your package, it will use them indirectly (reference them) from the TeeChart package. That makes your package smaller, and allows other packages to use the same TeeXXX units in the same way. There will be no naming conflict between your and other packages regarding the TeeXXX units.
requires
TeeChart,
etcetera;
Of course this puts on you the burden to ensure that everyone who uses your package will have the TeeChart package too, if necessary by distributing that package too (assuming licenses allow that).
UPDATE
Your update shows that you now have the TeeChart packages in your requires. If the message is correct, the compiler also includes the units TeeBlockCanvas, TeeMesh, TeeBlockEditor, TeeBlockGallery, TeeBlockClasses, etc.etc. in your package, so the units you explicitly include (in the containssection) seem to use these units too. Put the packages that contain these units (probably TeePro923, TeeUI923 and Tee923) in the requires section too:
requires
rtl,
vcl,
vclx,
// etc...
TeePro923,
TeeUI923,
Tee923,
TeeImage923,
TeeGL923,
// etc...
Now you should not get the message, that all those units were implicitly included into your package, anymore.

Related

How to avoid insert namespace in Delphi uses

I manage a huge project in Delphi 2007. The target is to upgrade it to Delphi 10.1 Berlin this year. So in the meantime the source is compiled in both versions.
If there is a problem with the new Delphi we want the old version as backup.
My problem in unit dmActions.pas that is a unit inherited from TDataModule.
uses
// VCL
ActnList,
ActnMan,
Classes,
Controls,
Forms,
Graphics,
ImgList,
Menus,
SysUtils,
XPStyleActnCtrls,
Variants,
{$IFDEF BOLD_DELPHI16_OR_LATER}
System.ImageList,
System.Actions,
{$ENDIF}
BusinessClasses;
Delphi IDE don't understand my IFDEF so it automatically insert missing units to this
uses
// VCL
ActnList,
ActnMan,
Classes,
Controls,
Forms,
Graphics,
ImgList,
Menus,
SysUtils,
XPStyleActnCtrls,
Variants,
{$IFDEF BOLD_DELPHI16_OR_LATER}
System.ImageList,
System.Actions,
{$ENDIF}
BusinessClasses, System.ImageList, System.Actions;
But this don't compile in Berlin with this message
[dcc32 Error] dmActions.pas(36): E2004 Identifier redeclared: 'System.ImageList'
[dcc32 Error] dmActions.pas(36): E2004 Identifier redeclared: 'System.Actions'
And of course "System.ImageList, System.Actions" don't compile in D2007.
So what is my best action to solve this ?
You can make use of the Unit Aliases feature of Delphi here - at least as your Delphi 2007 supports dotted unit names in the first place. This allows to use the new unit names like System.SysUtils from Delphi 10.1 Berlin and still compile that project with Delphi 2007.
For this you have to add mappings to the Unit Aliases of the Delphi 2007 project like this:
System.SysUtils=SysUtils
System.Classes=Classes
For units that don't exist in Delphi 2007, like the ones you mention in your post, simply map to an existing unit:
System.Actions=ActnList
System.ImageList=ImgList
As a benefit you end up with uses clauses free of IFDEFs.
As https://stackoverflow.com/users/2916756/nolaspeaker said it works by test compiler version directly. I used an inc-file and that don't work well in this case
But in my case I check Berlin so:
{$IFDEF VER310}
System.ImageList,
System.Actions,
{$ENDIF}

Accessing Delphi method pointers from another unit in another package when compiling with 'dcc32 -JL'

This is a bit complicated scenario - and even more complicated in practice, but I managed to minimize it for this question.
I have defined two Delphi packages: BasePackage.dpk and AnotherPackage.dpk
package BasePackage;
requires
rtl;
contains
Base in 'Base.pas';
end.
and
package AnotherPackage;
requires
BasePackage;
contains
Another in 'Another.pas';
end.
and units
unit Base;
interface
type
TMethod = procedure;
TEncodeableType = record
Method: TMethod;
end;
PEncodeableType = ^TEncodeableType;
procedure Method_Impl;
const
TestMethod_Type: TEncodeableType = (
Method: Method_Impl;
);
implementation
procedure Method_Impl;
begin
end;
end.
and
unit Another;
interface
uses
Base;
implementation
const
ResponseType: PEncodeableType = #TestMethod_Type;
end.
Everything compiles fine basically, and I can even generate the basic C++Builder units with 'dcc32 -JPHNEK --BCB' but when I try to generate the library files for C++Builder using 'dcc32 -JPHNEK --BCB -JL' I get
>dcc32 -JPHNEK --BCB -JL BasePackage.dpk
Embarcadero Delphi for Win32 compiler version 32.0
Copyright (c) 1983,2017 Embarcadero Technologies, Inc.
BasePackage.dpk(10)
11 lines, 0.09 seconds, 3688 bytes code, 176 bytes data.
>dcc32 -JPHNEK --BCB -JL AnotherPackage.dpk
Embarcadero Delphi for Win32 compiler version 32.0
Copyright (c) 1983,2017 Embarcadero Technologies, Inc.
AnotherPackage.dpk(10)
Error: E2201 Need imported data reference ($G) to access 'TestMethod_Type' from unit 'Another'
I have tried to play with different compile options (and of course introduce {$G+} or {$IMPORTEDDATA ON} to the units and packages (although it's the default anyway), but haven't seen them make any difference.
The packages are compiled without any or with these options in .cfg:
-$A+
-$B-
-$C-
-$D-
-$E-
-$F-
-$G+
-$H+
-$I-
-$J-
-$K-
-$L+
-$M-
-$N+
-$O+
-$P+
-$Q-
-$R-
-$S-
-$T+
-$U-
-$V-
-$W-
-$X+
-$Y-
-$Z1
-cg
-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
-H+
-W+
-M
-$M16384,1048576
-K$00300000
-Z
and either without any or with these options in .dpk:
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS ON}
{$RANGECHECKS ON}
{$REFERENCEINFO OFF}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST ON}
{$MINENUMSIZE 1}
{$IMAGEBASE $300000}
{$DESIGNONLY}
{$IMPLICITBUILD OFF}
Any idea if I could make this work (I really need the functionalities in different packages)?
I have been compiling with Delphi 10.2 Tokyo and XE4 with the same result.
I believe this is a compiler issue and therefore it might be impossible to solve for my case exactly like this. But, I can declare the mapping with variables, instead of constants (in practice I have several of these inside structures).
So, this version of Another.pas compiles and works:
unit Another;
interface
uses
Base;
implementation
var
ResponseType: PEncodeableType;
initialization
ResponseType := #TestMethod_Type;
end.

{$WARN SYMBOL_PLATFORM OFF} does not turn off warnings

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.

Error F2063 Could not compile used unit (of dependent package)

I have written 2 packages: MEComps_DXE5 and AMLComps_DXE5. The latter depends on the former. Both should be multi-platform: Win32, Win64, and (in the future) OSX.
When I open the first package MEComps_DXE5, I am able to compile it, build it and install it. I get some warnings, as this library contains code that must also compile on old D5, but the build succeeds and creates the dcu and dcp files where expected.
When I open the second package AMLComps_DXE5, I find this situation:
If I do not declare the dependency on MEComps_DXE5, the package will compile and build correctly (no errors, dcu and dcp files are generated), but Delphi will warn me that it has implicitly imported units from MEComps_DXE5, and ask me to add the package to the dependency list (Requires)
If the dependency is declared, then the compilation will fail with "[dcc32 Fatal Error] MEComps_DXE5.dpk(52): F2063 Could not compile used unit 'MEClasses.pas'", where MEClasses is the first unit of the MEComps_DXE5 package.
I've been trying to solve this for a few days now, but to no avail. I'm working on two fronts:
Why is Delphi even trying to compile the other package? I have just built and installed it, and have all dcus and the dcp.
Why is the compilation failing?
As to the first question I have no clue whatsoever.
As to the second question, the documentation is useless in this case. It explains why not being able to compile a used unit is fatal, and states that the cause is determined by looking at the previous errors. But in this case, there are NO previous errors.
As MEComps_DXE5 actually compiles and builds on its own, I doubt this has anything to do with syntax or code. It would seem to be that the compiler is not able to find something it needs to compile those units.
The two packages reside each in their own directory. I put the MEComps\Win32 dcu directory on the library path and on the browsing path. The IDE actually has no problems looking up the used units.
I also checked the dcc32 command line and it seems that all envolved directories are known to the compiler.
Other info I can add:
Both packages have their own include file (in their source directory). I'm not sure if these are to be included in the package contains list or not, but I've tried both ways and nothing seemed to change.
Both packages have a corresponding Delphi 5 package which includes some of the same units and code (different dpk though). These compile and build correctly. Delphi 5 dcu files are generated in the source directory. Can this create problems with the XE5 compiler?
Here is the complete code for the MEComps_DXE5 package. I see a lot of compiler directives that Delphi inserted when it created the empty package. I didn't touch those:
package MEComps_DXE5;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl,
fmx,
dbrtl,
xmlrtl;
contains
MEClasses in 'MEClasses.pas',
MEConsts in 'MEConsts.pas',
MEDataReader in 'MEDataReader.pas',
MEDateUtils in 'MEDateUtils.pas',
MEEncoding in 'MEEncoding.pas',
MEEncodingISO2022 in 'MEEncodingISO2022.pas',
MEFileUtils in 'MEFileUtils.pas',
MELists in 'MELists.pas',
MEMath in 'MEMath.pas',
MENumUtils in 'MENumUtils.pas',
MESQLUtils in 'MESQLUtils.pas',
MEStrUtils in 'MEStrUtils.pas',
MESysUtils in 'MESysUtils.pas',
METypes in 'METypes.pas',
MEURIUtils in 'MEURIUtils.pas',
MEXMLUtils in 'MEXMLUtils.pas';
end.
Delphi IDE is far from perfect when it comes to editing/compiling packages but you should solve the problem on your side - configure your packages better and Delphi will compile them correctly.
I can only give you general advices addressing the info given:
If you need a common include file for 2 packages create a separate directory for the file and add this directory to the search paths of both packages (in Base build configuration).
Never keep .dcu's in the same folders with source files; always set "unit output directory" option for your packages (also in Base build configuration); I recommend $(BDSCOMMONDIR)\MyPacks\$(Config)\$(Platform) as such directory for your packages; if you already have .dcu's in the source (.pas) folders delete them, does not matter which Delphi version created these .dcu's.
Never add paths to dependent package's sources to the search path, only paths to compiled .dcu's (would be $(BDSCOMMONDIR)\MyPacks\$(Config)\$(Platform) if you follow previous advice).

Can't compile package containing DSUtils in XE2

I am trying to compile a package containing DSUtils.pas (part of DSPack) and it fails because it tries to compile wrong DirectShow9.pas unit - not the one from the DSPack but the one from the Delphi XE2 (Update 3) RTL.
The problem can be repeated with a minimal package:
package Package1;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl;
contains
DSUtils in 'x:\common\pkg\dspack\src\DSPack\DSUtils.pas';
end.
The error occurs in DSUtils line 1058 and the error is Undeclared identifier: FrameRateCode.
Result.FrameRateCode := (x and $00000003) shr 00;
Undeclared is 'FrameRateCode' - CtrlClick on the Result brings us to Winapi.DirectShow9 (in the RTL folder) which doesn't have this field declared.
Interesting part - if I go to the DSUtils uses list, click on DirectShow9 and press Ctrl+Enter, the DSpack version of the unit will open (and this unit has FrameRateCode field defined). So Delphi knows where the unit is. It just tries to compile the package by using the wrong DirectShow9.
Interesting tidbit: If I'm compiling a normal application (non-package) that uses DSUtils, everything works fine.
What I've tried:
Compiling DirectShow9 from the DSPack into its own package (actually I used DirectX9 package from DSPack which contains all files from the DirectX9 folder) and adding it to the 'requires' list. Doesn't work.
Adding the folder with DirectShow9 file (from DSPack) to the beginning of the system path and rebooting. Doesn't work.
Adding the folder with DirectShow9 file to the beginning of the library path. Doesn't work.
Adding the DirectShow9 unit to the package with the explicit path. Doesn't work.
Copying the DirectX9*.pas into the DSPack folder so that the DirectShow9 unit would be in the same folder as the DSUtils unit. Doesn't work.
I see three possible workarounds, but I'm not happy with any of them.
I can comment out the problematic code. Luckily, it is only this one line, everything else compiles with Delphi's DirectShow9.
I can rename DirectShow9 from DSPack but then I may have to fix the 'uses' part in different application.
I can turn off automatic prefixing with 'Winapi.' but that will cause me lots of additional work editing thousands and thousands files.
What I would really like to see is getting XE2 to use the right source file.
I faced the same problem, and I simply commented out all the problem lines (there was 2 or 3 of them). Everything works perfectly fine.
Another option is to use the latest DSPack (which is compatible with XE2): http://code.google.com/p/dspack/
Or you can rename DSPack's DirectShow9 file, as discussed here: http://www.progdigy.com/forums/viewtopic.php?p=16971

Resources