1 {
2 /***************************************************************************
3 packagedefs.pas
4 ---------------
5
6
7 ***************************************************************************/
8
9 ***************************************************************************
10 * *
11 * This source is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This code is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19 * General Public License for more details. *
20 * *
21 * A copy of the GNU General Public License is available on the World *
22 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
23 * obtain it by writing to the Free Software Foundation, *
24 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
25 * *
26 ***************************************************************************
27
28 Author: Mattias Gaertner
29
30 Abstract:
31 Classes for packages and dependencies.
32 }
33 unit PackageDefs;
34
35 {$mode objfpc}{$H+}
36
37 interface
38
39 uses
40 // FCL
41 Classes, SysUtils, contnrs, typinfo, Laz_AVL_Tree,
42 // LCL
43 Forms, ImgList,
44 // Codetools
45 LazConfigStorage, DefineTemplates, CodeToolManager,
46 CodeCache, CodeToolsCfgScript, CodeToolsStructs,
47 // LazUtils
48 FileUtil, LazFileUtils, LazUtilities, LazFileCache, LazUTF8, FileReferenceList,
49 LazTracer, LazLoggerBase, UITypes, Laz2_XMLCfg, AvgLvlTree,
50 // BuildIntf
51 MacroIntf, MacroDefIntf, IDEOptionsIntf, PublishModuleIntf,
52 PackageDependencyIntf, PackageIntf, FppkgIntf,
53 // IDEIntf
54 LazIDEIntf, IDEOptEditorIntf, IDEDialogs, ComponentReg, IDEImagesIntf,
55 // IDE
56 EditDefineTree, CompilerOptions, CompOptsModes, IDEOptionDefs, ProjPackCommon,
57 LazarusIDEStrConsts, IDEProcs, TransferMacros, FppkgHelper;
58
59 type
60 TLazPackage = class;
61 TPkgFile = class;
62 TBasePackageEditor = class;
63 TPkgDependency = class;
64
65 TPackageUpdatePolicy = (
66 pupManually,
67 pupOnRebuildingAll,
68 pupAsNeeded
69 );
70 TPackageUpdatePolicies = set of TPackageUpdatePolicy;
71
72 TGetAllRequiredPackagesEvent =
73 procedure(APackage: TLazPackage; // if not nil then ignore FirstDependency and do not add APackage to Result
74 FirstDependency: TPkgDependency;
75 out List, FPMakeList: TFPList;
76 Flags: TPkgIntfRequiredFlags = [];
77 MinPolicy: TPackageUpdatePolicy = low(TPackageUpdatePolicy)) of object;
78 TGetDependencyOwnerDescription =
79 procedure(Dependency: TPkgDependency; out Description: string) of object;
80 TGetDependencyOwnerDirectory =
81 procedure(Dependency: TPkgDependency; out Directory: string) of object;
82 TGetWritablePkgOutputDirectory =
83 procedure(APackage: TLazPackage; var AnOutDirectory: string) of object;
84
85
86 { TPkgComponent }
87
88 TPkgComponent = class(TRegisteredComponent)
89 private
90 FPkgFile: TPkgFile;
91 procedure SetPkgFile(const AValue: TPkgFile);
92 public
93 constructor Create(ThePkgFile: TPkgFile; TheComponentClass: TComponentClass;
94 const ThePageName: string);
95 destructor Destroy; override;
GetUnitNamenull96 function GetUnitName: string; override;
GetPrioritynull97 function GetPriority: TComponentPriority; override;
98 procedure ConsistencyCheck; override;
ImageIndexnull99 function ImageIndex: TImageIndex;
Imagesnull100 class function Images: TCustomImageList;
HasIconnull101 function HasIcon: boolean;
CanBeCreatedInDesignernull102 function CanBeCreatedInDesigner: boolean; override;
103 public
104 property PkgFile: TPkgFile read FPkgFile write SetPkgFile;
105 end;
106
107 { TPkgFile }
108
109 type
110 TPFComponentBaseClass = (
111 pfcbcNone, // unknown
112 pfcbcForm, // is TForm
113 pfcbcFrame, // is TFrame
114 pfcbcDataModule,// is TDataModule
115 pfcbcCustomForm // is TCustomForm (not TForm)
116 );
117
118 const
119 PFComponentBaseClassNames: array[TPFComponentBaseClass] of string = (
120 'None',
121 'Form',
122 'Frame',
123 'DataModule',
124 'CustomForm'
125 );
126
StrToComponentBaseClassnull127 function StrToComponentBaseClass(const s: string): TPFComponentBaseClass;
GetComponentBaseClassnull128 function GetComponentBaseClass(aClass: TClass): TPFComponentBaseClass;
129
130 type
131 TPkgFileFlag = (
132 pffHasRegisterProc, // file is unit and has a 'register' procedure
133 pffAddToPkgUsesSection,// unit is added to uses section
134 pffReportedAsRemoved // file has been reported as removed
135 );
136 TPkgFileFlags = set of TPkgFileFlag;
137
138 { TPkgFile }
139
140 TPkgFile = class(TLazPackageFile)
141 private
142 FAutoReferenceSourceDir: boolean;
143 FComponentPriority: TComponentPriority;
144 FComponents: TFPList; // list of TPkgComponent
145 FDirectory: string;
146 FFlags: TPkgFileFlags;
147 fFilename: string;
148 fFullFilename: string;
149 fFullFilenameStamp: integer;
150 FPackage: TLazPackage;
151 FResourceBaseClass: TPFComponentBaseClass;
152 FSourceDirectoryReferenced: boolean;
153 FSourceDirNeedReference: boolean;
GetAddToUsesPkgSectionnull154 function GetAddToUsesPkgSection: boolean;
GetComponentsnull155 function GetComponents(Index: integer): TPkgComponent;
GetHasRegisterProcnull156 function GetHasRegisterProc: boolean;
157 procedure SetAddToUsesPkgSection(const AValue: boolean);
158 procedure SetAutoReferenceSourceDir(const AValue: boolean);
159 procedure SetFlags(const AValue: TPkgFileFlags);
160 procedure SetHasRegisterProc(const AValue: boolean);
161 procedure UpdateUnitName;
GetComponentListnull162 function GetComponentList: TFPList;
163 protected
GetInUsesnull164 function GetInUses: boolean; override;
165 procedure SetInUses(AValue: boolean); override;
GetIDEPackagenull166 function GetIDEPackage: TIDEPackage; override;
GetFilenamenull167 function GetFilename: string; override;
168 procedure SetFilename(const AValue: string); override;
169 procedure SetRemoved(const AValue: boolean); override;
170 procedure SetDisableI18NForLFM(AValue: boolean); override;
171 procedure SetFileType(const AValue: TPkgFileType); override;
172 procedure SetUnitName(const AValue: string); override;
173 public
174 constructor Create(ThePackage: TLazPackage);
175 destructor Destroy; override;
176 procedure Clear;
177 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string;
178 FileVersion: integer; AdjustPathDelims: boolean);
179 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string;
180 UsePathDelim: TPathDelimSwitch);
181 procedure ConsistencyCheck;
ComponentCountnull182 function ComponentCount: integer;
183 procedure AddPkgComponent(APkgComponent: TPkgComponent);
184 procedure RemovePkgComponent(APkgComponent: TPkgComponent);
HasRegisteredPluginsnull185 function HasRegisteredPlugins: boolean;
MakeSensenull186 function MakeSense: boolean;
187 procedure UpdateSourceDirectoryReference;
GetFullFilenamenull188 function GetFullFilename: string; override;
GetShortFilenamenull189 function GetShortFilename(UseUp: boolean): string; override;
GetResolvedFilenamenull190 function GetResolvedFilename: string; // GetFullFilename + resolve symlinks
GetFileOwnernull191 function GetFileOwner: TObject; override;
GetFileOwnerNamenull192 function GetFileOwnerName: string; override;
193 public
194 property AddToUsesPkgSection: boolean
195 read GetAddToUsesPkgSection write SetAddToUsesPkgSection;
196 property AutoReferenceSourceDir: boolean read FAutoReferenceSourceDir
197 write SetAutoReferenceSourceDir;
198 property ResourceBaseClass: TPFComponentBaseClass read FResourceBaseClass
199 write FResourceBaseClass;
200 property ComponentPriority: TComponentPriority read FComponentPriority
201 write FComponentPriority;
202 property Components[Index: integer]: TPkgComponent read GetComponents;// registered components
203 property Directory: string read FDirectory;
204 property Flags: TPkgFileFlags read FFlags write SetFlags;
205 property HasRegisterProc: boolean read GetHasRegisterProc write SetHasRegisterProc;
206 property LazPackage: TLazPackage read FPackage;
207 property SourceDirectoryReferenced: boolean read FSourceDirectoryReferenced;
208 end;
209
210
211 { TPkgUnitsTree - Tree of TPkgFile sorted for unitnames }
212
213 TPkgUnitsTree = class(TAVLTree)
214 private
215 FLazPackage: TLazPackage;
216 public
FindNodeWithUnitNamenull217 function FindNodeWithUnitName(const AUnitName: string): TAVLTreeNode;
FindPkgFileWithUnitNamenull218 function FindPkgFileWithUnitName(const AUnitName: string): TPkgFile;
219 constructor Create(ThePackage: TLazPackage);
220 property LazPackage: TLazPackage read FLazPackage write FLazPackage;
221 end;
222
223
224 { TPkgDependency }
225
226 TPkgMarkerFlag = (
227 pmfVisited,
228 pmfMarked
229 );
230 TPkgMarkerFlags = set of TPkgMarkerFlag;
231
232 TPkgDependencyDirection = (
233 pddRequires,
234 pddUsedBy
235 );
236
237 { TPkgDependency }
238
239 TPkgDependency = class(TPkgDependencyID)
240 private
241 FDefaultFilename: string;
242 FHoldPackage: boolean;
243 FMarkerFlags: TPKgMarkerFlags;
244 FOwner: TObject;
245 FPreferDefaultFilename: boolean;
GetRequiredPackagenull246 function GetRequiredPackage: TLazPackage;
247 procedure SetHoldPackage(const AValue: boolean);
248 procedure SetRequiredPackage(AValue: TLazPackage);
249 protected
250 procedure SetPackageName(const AValue: string); override;
251 public
252 NextDependency, PrevDependency: array[TPkgDependencyDirection] of TPkgDependency;
253 constructor Create;
254 destructor Destroy; override;
255 procedure Clear; override;
256 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string;
257 FileVersion: integer);
258 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string;
259 UsePathDelim: TPathDelimSwitch);
260
Comparenull261 function Compare(Dependency2: TPkgDependency): integer;
262 procedure Assign(Source: TPkgDependency);
263 procedure Assign(Source: TLazPackageID);
264 procedure ConsistencyCheck;
IsCompatiblenull265 function IsCompatible(Pkg: TLazPackageID): boolean; overload;
266 procedure MakeCompatible(const PkgName: string; const Version: TPkgVersion);
AsStringnull267 function AsString(WithOwner, WithDefaults: boolean): string; overload;
268 // API for iterating dependencies.
NextUsedByDependencynull269 function NextUsedByDependency: TPkgDependency; override;
PrevUsedByDependencynull270 function PrevUsedByDependency: TPkgDependency; override;
NextRequiresDependencynull271 function NextRequiresDependency: TPkgDependency; override;
PrevRequiresDependencynull272 function PrevRequiresDependency: TPkgDependency; override;
273 // API for adding / removing dependencies, defined in base class.
274 procedure AddUsedByDep(var FirstDependency: TPkgDependencyBase); override;
275 procedure RemoveUsedByDep(var FirstDependency: TPkgDependencyBase); override;
276 procedure AddRequiresDep(var FirstDependency: TPkgDependencyBase); override;
277 procedure RemoveRequiresDep(var FirstDependency: TPkgDependencyBase); override;
278 // API using ListType.
279 procedure AddToList(var FirstDependency: TPkgDependency;
280 ListType: TPkgDependencyDirection);
281 procedure AddToEndOfList(var LastDependency: TPkgDependency;
282 ListType: TPkgDependencyDirection);
283 procedure RemoveFromList(var FirstDependency: TPkgDependency;
284 ListType: TPkgDependencyDirection);
MoveUpInListnull285 function MoveUpInList(var FirstDependency: TPkgDependency;
286 ListType: TPkgDependencyDirection): Boolean;
MoveDownInListnull287 function MoveDownInList(var FirstDependency: TPkgDependency;
288 ListType: TPkgDependencyDirection): Boolean;
MakeFilenameRelativeToOwnernull289 function MakeFilenameRelativeToOwner(const AFilename: string): string;
FindDefaultFilenamenull290 function FindDefaultFilename: string;
291 public
292 property Owner: TObject read FOwner write FOwner;// package or project or IDE
293 property HoldPackage: boolean read FHoldPackage write SetHoldPackage;
294 property MarkerFlags: TPKgMarkerFlags read FMarkerFlags write FMarkerFlags;
295 property DefaultFilename: string read FDefaultFilename write FDefaultFilename;
296 property PreferDefaultFilename: boolean read FPreferDefaultFilename write FPreferDefaultFilename;
297 property RequiredPackage: TLazPackage read GetRequiredPackage write SetRequiredPackage;
298 end;
299 PPkgDependency = ^TPkgDependency;
300
301
302 { TPkgPair }
303
304 TPkgPair = class
305 public
306 Package1: TLazPackage;
307 Package2: TLazPackage;
308 constructor Create(Pkg1, Pkg2: TLazPackage);
ComparePairnull309 function ComparePair(Pkg1, Pkg2: TLazPackage): integer;
Comparenull310 function Compare(PkgPair: TPkgPair): integer;
AsStringnull311 function AsString: string;
312 end;
313
314
315 { TPkgPairTree - Tree of TPkgPair }
316
317 TPkgPairTree = class(TAVLTree)
318 public
319 constructor Create;
320 destructor Destroy; override;
FindPairnull321 function FindPair(Pkg1, Pkg2: TLazPackage; IgnoreOrder: boolean): TPkgPair;
AddPairnull322 function AddPair(Pkg1, Pkg2: TLazPackage): TPkgPair;
AddPairIfNotExistsnull323 function AddPairIfNotExists(Pkg1, Pkg2: TLazPackage): TPkgPair;
324 end;
325
326
327 { TPkgCompilerOptions }
328
329 TPkgCompilerOptions = class(TBaseCompilerOptions)
330 private
331 FLazPackage: TLazPackage;
332 FSkipCompiler: Boolean;
333 procedure InvalidateOptions;
334 protected
335 procedure SetLazPackage(const AValue: TLazPackage);
336 procedure SetCustomOptions(const AValue: string); override;
337 procedure SetIncludePaths(const AValue: string); override;
338 procedure SetLibraryPaths(const AValue: string); override;
339 procedure SetLinkerOptions(const AValue: string); override;
340 procedure SetObjectPath(const AValue: string); override;
341 procedure SetSrcPath(const AValue: string); override;
342 procedure SetUnitPaths(const AValue: string); override;
343 procedure SetUnitOutputDir(const AValue: string); override;
344 procedure SetConditionals(AValue: string); override;
345 public
346 constructor Create(const AOwner: TObject); override;
347 // IDE options
GetGroupCaptionnull348 class function GetGroupCaption: string; override;
GetInstancenull349 class function GetInstance: TAbstractIDEOptions; override;
IsActivenull350 function IsActive: boolean; override;
351 procedure Clear; override;
352 procedure GetInheritedCompilerOptions(var OptionsList: TFPList); override;
GetOwnerNamenull353 function GetOwnerName: string; override;
GetDefaultMainSourceFileNamenull354 function GetDefaultMainSourceFileName: string; override;
CreateTargetFilenamenull355 function CreateTargetFilename: string; override;
HasCompilerCommandnull356 function HasCompilerCommand: boolean; override;
357
358 procedure LoadFromXMLConfig(AXMLConfig: TXMLConfig; const Path: string); override;
359 procedure SaveToXMLConfig(AXMLConfig: TXMLConfig; const Path: string); override;
360 procedure Assign(Source: TPersistent); override;
CreateDiffnull361 function CreateDiff(CompOpts: TBaseCompilerOptions;
362 Tool: TCompilerDiffTool = nil): boolean; override;
363 public
364 property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
365 property SkipCompiler: Boolean read FSkipCompiler write FSkipCompiler;
366 end;
367
368
369 { TPkgAdditionalCompilerOptions }
370
371 TPkgAdditionalCompilerOptions = class(TAdditionalCompilerOptions)
372 private
373 FLazPackage: TLazPackage;
374 procedure SetLazPackage(const AValue: TLazPackage);
375 protected
376 procedure SetCustomOptions(const AValue: string); override;
377 procedure SetIncludePath(const AValue: string); override;
378 procedure SetLibraryPath(const AValue: string); override;
379 procedure SetLinkerOptions(const AValue: string); override;
380 procedure SetObjectPath(const AValue: string); override;
381 procedure SetUnitPath(const AValue: string); override;
382 procedure SetSrcPath(const AValue: string); override;
383 public
384 constructor Create(ThePackage: TLazPackage);
385 procedure AssignOptions(Source: TObject); override;
GetOwnerNamenull386 function GetOwnerName: string; override;
GetBaseCompilerOptionsnull387 function GetBaseCompilerOptions: TBaseCompilerOptions; override;
388 public
389 property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
390 end;
391
392 { TPublishPackageOptions }
393
394 TPublishPackageOptions = class(TPublishModuleOptions)
395 protected
396 procedure DoOnModifyChange; override;
397 public
GetDefaultDestinationDirnull398 function GetDefaultDestinationDir: string; override;
399 end;
400
401
402 { TLazPackageDefineTemplates }
403
404 TLazPackageDefineTemplates = class(TProjPackDefineTemplates)
405 private
406 protected
407 procedure UpdateMain; override;
UpdateSrcDirIfDefnull408 function UpdateSrcDirIfDef: Boolean; override;
409 procedure UpdateSourceDirectories; override;
410 procedure UpdateOutputDirectory; override;
411 procedure UpdateDefinesForCustomDefines; override;
412 procedure ClearFlags; override;
413 public
414 constructor Create(AOwner: IProjPack);
415 destructor Destroy; override;
416 procedure AllChanged(AActivating: boolean); override;
417 end;
418
419
420 { TLazPackage }
421
422 TLazPackageFlag = (
423 lpfAutoIncrementVersionOnBuild, // increment version before
424 lpfModified, // package needs saving
425 lpfNeeded, // Set by PackageGraph, if package is in use
426 // (for example because it is Installed or an Installed
427 // package requires this package)
428 lpfVisited, // Used by the PackageGraph to avoid double checking
429 lpfDestroying, // set during destruction
430 lpfLoading, // set during loading
431 lpfSkipSaving, // Used by PkgBoss to skip saving
432 lpfCycle, // Used by the PackageGraph to mark cycles
433 lpfNeedGroupCompile,// set during group compile, dependent packages need compile too
434 lpfCompatibilityMode// use legacy file format to maximize compatibility with old Lazarus versions
435 );
436 TLazPackageFlags = set of TLazPackageFlag;
437
438 const
439 pupAllAuto = [pupAsNeeded,pupOnRebuildingAll];
440
441 type
442 TPkgOutputDirWritable = (
443 podwUnknown,
444 podwWritable,
445 podwNotWritable
446 );
447 TPkgLastCompileStats = record
448 StateFileLoaded: boolean;
449 StateFileName: string; // the .compiled file
450 StateFileDate: longint;
451 CompilerFilename: string; // path to used compiler
452 CompilerFileDate: integer;
453 Params: string; // compiler parameters
454 Complete: boolean; // compilation was successful
455 MainPPUExists: boolean; // main ppu file was there after compile
456 ViaMakefile: boolean; // compiled via make
457 DirectoryWritable: TPkgOutputDirWritable;
458 end;
459 PPkgLastCompileStats = ^TPkgLastCompileStats;
460 TPkgOutputDir = (
461 podDefault,
462 podFallback // used when podDefault is not writable
463 );
464
465 TIterateComponentClassesEvent = procedure(PkgComponent: TPkgComponent) of object;
466 TPkgChangeNameEvent = procedure(Pkg: TLazPackage; const OldName: string) of object;
467
468 { TPackageIDEOptions }
469
470 TPackageIDEOptions = class(TAbstractPackageIDEOptions)
471 private
472 FPackage: TLazPackage;
473 protected
GetPackagenull474 function GetPackage: TIDEPackage; override;
475 public
476 constructor Create(APackage: TLazPackage);
477 destructor Destroy; override;
GetInstancenull478 class function GetInstance: TAbstractIDEOptions; override;
GetGroupCaptionnull479 class function GetGroupCaption: string; override;
480 property Package: TLazPackage read FPackage;
481 end;
482
483
484 { TLazPackage }
485
486 TLazPackage = class(TIDEPackage, IProjPack)
487 private
488 FAddToProjectUsesSection: boolean;
489 FAuthor: string;
490 FAutoUpdate: TPackageUpdatePolicy;
491 FFPDocPackageName: string;
492 FOnModifySilently: TNotifyEvent;
493 FOptionsBackup: TLazPackage;
494 FComponents: TFPList; // TFPList of TPkgComponent
495 FDefineTemplates: TLazPackageDefineTemplates;
496 FDescription: string;
497 FDirectory: string;
498 FDirectoryExpanded: string;
499 FDirectoryExpandedChangeStamp: integer;
500 FEnableI18N: boolean;
501 FEnableI18NForLFM: boolean;
502 FFileReadOnly: boolean;
503 FFiles: TFPList; // TFPList of TPkgFile
504 FFirstRemovedDependency: TPkgDependency;
505 FFirstRequiredDependency: TPkgDependency;
506 FFirstUsedByDependency: TPkgDependency;
507 FFlags: TLazPackageFlags;
508 FHasDirectory: boolean;
509 FHasStaticDirectory: boolean;
510 FHoldPackageCount: integer;
511 FIconFile: string;
512 FInstalled: TPackageInstallType;
513 FFPDocPaths: string;
514 FLicense: string;
515 FLPKSource: TCodeBuffer;
516 FLPKSourceChangeStep: integer;
517 FMacros: TTransferMacroList;
518 FMainUnit: TPkgFile;
519 FMissing: boolean;
520 FModifiedLock: integer;
521 FOutputStateFile: string;
522 FPackageEditor: TBasePackageEditor;
523 FPOOutputDirectory: string;
524 FProvides: TStrings;
525 fPublishOptions: TPublishPackageOptions;
526 FRegistered: boolean;
527 FRemovedFiles: TFPList; // TFPList of TPkgFile
528 FSourceDirectories: TFileReferenceList;
529 FStorePathDelim: TPathDelimSwitch;
530 FTopologicalLevel: integer;
531 FTranslated: string;
532 FUpdateLock: integer;
533 FUsageOptions: TPkgAdditionalCompilerOptions;
534 FUserIgnoreChangeStamp: integer;
535 FUserReadOnly: boolean;
GetAutoIncrementVersionOnBuildnull536 function GetAutoIncrementVersionOnBuild: boolean;
GetCompilerOptionsnull537 function GetCompilerOptions: TPkgCompilerOptions;
GetBaseCompilerOptionsnull538 function GetBaseCompilerOptions: TBaseCompilerOptions;
GetComponentCountnull539 function GetComponentCount: integer;
GetComponentsnull540 function GetComponents(Index: integer): TPkgComponent;
GetRemovedFilesnull541 function GetRemovedFiles(Index: integer): TPkgFile;
GetFilesnull542 function GetFiles(Index: integer): TPkgFile;
GetIDEOptionsnull543 function GetIDEOptions: TPackageIDEOptions;
GetSourceDirectoriesnull544 function GetSourceDirectories: TFileReferenceList;
GetUseLegacyListsnull545 function GetUseLegacyLists: Boolean;
546 procedure SetAddToProjectUsesSection(const AValue: boolean);
547 procedure SetAuthor(const AValue: string);
548 procedure SetAutoIncrementVersionOnBuild(const AValue: boolean);
549 procedure SetAutoUpdate(const AValue: TPackageUpdatePolicy);
550 procedure SetDescription(const AValue: string);
551 procedure SetEnableI18NForLFM(AValue: boolean);
552 procedure SetFileReadOnly(const AValue: boolean);
553 procedure SetFlags(const AValue: TLazPackageFlags);
554 procedure SetFPDocPackageName(AValue: string);
555 procedure SetIconFile(const AValue: string);
556 procedure SetInstalled(const AValue: TPackageInstallType);
557 procedure SetFPDocPaths(const AValue: string);
558 procedure SetLicense(const AValue: string);
559 procedure SetLPKSource(const AValue: TCodeBuffer);
560 procedure SetOutputStateFile(const AValue: string);
561 procedure SetProvides(const AValue: TStrings);
562 procedure SetPOOutputDirectory(const AValue: string);
563 procedure SetEnableI18N(const AValue: boolean);
564 procedure SetRegistered(const AValue: boolean);
565 procedure SetPackageEditor(const AValue: TBasePackageEditor);
566 procedure SetPackageType(const AValue: TLazPackageType);
567 procedure SetStorePathDelim(const AValue: TPathDelimSwitch);
568 procedure SetUseLegacyLists(const AUseLegacyLists: Boolean);
569 procedure SetUserReadOnly(const AValue: boolean);
570 procedure OnMacroListSubstitution({%H-}TheMacro: TTransferMacro;
571 const MacroName: string; var s: string;
572 const Data: PtrInt; var Handled, {%H-}Abort: boolean; {%H-}Depth: integer);
573 procedure Clear;
574 procedure UpdateSourceDirectories;
575 procedure SourceDirectoriesChanged(Sender: TObject);
576 protected
GetDirectorynull577 function GetDirectory: string; override;
GetDefineTemplatesnull578 function GetDefineTemplates: TProjPackDefineTemplates;
GetFileCountnull579 function GetFileCount: integer; override;
GetPkgFilesnull580 function GetPkgFiles(Index: integer): TLazPackageFile; override;
GetDirectoryExpandednull581 function GetDirectoryExpanded: string; override;
GetModifiednull582 function GetModified: boolean; override;
583 procedure SetFilename(const AValue: string); override;
584 procedure SetModified(const AValue: boolean); override;
585 procedure SetName(const NewName: TComponentName); override;
586 procedure VersionChanged(Sender: TObject); override;
GetRemovedCountnull587 function GetRemovedCount: integer; override;
GetRemovedPkgFilesnull588 function GetRemovedPkgFiles(Index: integer): TLazPackageFile; override;
589 procedure SetAutoInstall(AValue: TPackageInstallType); override;
590 public
591 constructor Create; override;
592 constructor CreateAndClear;
593 destructor Destroy; override;
594 procedure AssignOptions(Source: TPersistent); override;
595 // IDE options
596 procedure BackupOptions;
597 procedure RestoreOptions;
598 // modified
599 procedure BeginUpdate;
600 procedure EndUpdate;
601 procedure LockModified;
602 procedure UnlockModified;
ReadOnlynull603 function ReadOnly: boolean; override;
604 procedure ModifySilently; // Set Modified but do not trigger update of editors.
605 // streaming
606 procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string);
607 procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
608 procedure SaveToString(out s: string);
609 // consistency
610 procedure CheckInnerDependencies;
IsMakingSensenull611 function IsMakingSense: boolean;
612 procedure ConsistencyCheck;
613 // paths, define templates
ExtendUnitSearchPathnull614 function ExtendUnitSearchPath(NewUnitPaths: string): boolean;
ExtendIncSearchPathnull615 function ExtendIncSearchPath(NewIncPaths: string): boolean;
IsVirtualnull616 function IsVirtual: boolean; override;
HasDirectorynull617 function HasDirectory: boolean; override;
HasStaticDirectorynull618 function HasStaticDirectory: boolean;
GetFullFilenamenull619 function GetFullFilename(ResolveMacros: boolean): string;
GetResolvedFilenamenull620 function GetResolvedFilename(ResolveMacros: boolean): string; // GetFullFilename + resolve symlinks
GetSourceDirsnull621 function GetSourceDirs(WithPkgDir, WithoutOutputDir: boolean): string;
622 procedure GetInheritedCompilerOptions(var OptionsList: TFPList);
GetOutputDirectorynull623 function GetOutputDirectory(UseOverride: boolean = true): string; // this can change before building, when default dir is readonly
HasSeparateOutputDirectorynull624 function HasSeparateOutputDirectory: boolean;
GetStateFilenamenull625 function GetStateFilename(UseOverride: boolean = true): string;
GetCompileSourceFilenamenull626 function GetCompileSourceFilename: string;// as GetSrcFilename without directory
GetSrcFilenamenull627 function GetSrcFilename: string;
GetSrcPPUFilenamenull628 function GetSrcPPUFilename: string;
GetCompilerFilenamenull629 function GetCompilerFilename: string;
GetPOOutDirectorynull630 function GetPOOutDirectory: string;
GetUnitPathnull631 function GetUnitPath(RelativeToBaseDir: boolean): string;
GetIncludePathnull632 function GetIncludePath(RelativeToBaseDir: boolean): string;
GetSrcPathnull633 function GetSrcPath(RelativeToBaseDir: boolean): string;
GetFPDocPackageNamenull634 function GetFPDocPackageName: string;
GetLastCompilerParamsnull635 function GetLastCompilerParams(o: TPkgOutputDir): string;
NeedsDefineTemplatesnull636 function NeedsDefineTemplates: boolean;
SubstitutePkgMacrosnull637 function SubstitutePkgMacros(const s: string; PlatformIndependent: boolean): string;
638 procedure WriteInheritedUnparsedOptions;
GetActiveBuildMethodnull639 function GetActiveBuildMethod: TBuildMethod;
640 // files
IndexOfPkgFilenull641 function IndexOfPkgFile(PkgFile: TPkgFile): integer;
SearchShortFilenamenull642 function SearchShortFilename(const ShortFilename: string;
643 SearchFlags: TSearchIDEFileFlags): TPkgFile;
SearchFilenamenull644 function SearchFilename(const AFilename: string;
645 SearchFlags: TSearchIDEFileFlags): TPkgFile;
646 procedure ShortenFilename(var ExpandedFilename: string; UseUp: boolean);
647 procedure LongenFilename(var AFilename: string);
FindPkgFilenull648 function FindPkgFile(const AFilename: string;
649 IgnoreRemoved, FindVirtualFile: boolean): TPkgFile;
FindUnitWithRegisternull650 function FindUnitWithRegister(IgnorePkgFile: TPkgFile = nil): TPkgFile;
FindUnitnull651 function FindUnit(const TheUnitName: string): TPkgFile;
FindUnitnull652 function FindUnit(const TheUnitName: string; IgnoreRemoved: boolean): TPkgFile;
FindUnitnull653 function FindUnit(const TheUnitName: string; IgnoreRemoved: boolean;
654 IgnorePkgFile: TPkgFile): TPkgFile;
FindUsedUnitnull655 function FindUsedUnit(TheUnitName: string; IgnorePkgFile: TPkgFile = nil): TPkgFile;
FindRemovedPkgFilenull656 function FindRemovedPkgFile(const AFilename: string): TPkgFile;
AddFilenull657 function AddFile(const NewFilename, NewUnitName: string;
658 NewFileType: TPkgFileType; NewFlags: TPkgFileFlags;
659 CompPriorityCat: TComponentPriorityCategory): TPkgFile;
AddFileByNamenull660 function AddFileByName(aFilename: string;
661 var NewUnitPaths, NewIncPaths: String): Boolean;
AddRemovedFilenull662 function AddRemovedFile(const NewFilename, NewUnitName: string;
663 NewFileType: TPkgFileType; NewFlags: TPkgFileFlags;
664 CompPriorityCat: TComponentPriorityCategory): TPkgFile;
665 procedure DeleteFile(PkgFile: TPkgFile); // free TPkgFile
666 procedure RemoveFileSilently(PkgFile: TPkgFile);
667 procedure RemoveFile(PkgFile: TPkgFile); // move file to removed file list
668 procedure UnremovePkgFile(PkgFile: TPkgFile); // move file back to file list
669 // True if something changed. Param is ignored here, just to match with interface.
RemoveNonExistingFilesnull670 function RemoveNonExistingFiles({%H-}RemoveFromUsesSection: boolean = true): boolean;
GetFileDialogInitialDirnull671 function GetFileDialogInitialDir(const DefaultDirectory: string): string;
672 procedure MoveFile(CurIndex, NewIndex: integer);
673 procedure SortFiles;
FixFilesCaseSensitivitynull674 function FixFilesCaseSensitivity: boolean;
MainUnitHasPkgNamenull675 function MainUnitHasPkgName: boolean;
676 // required dependencies (plus removed required dependencies)
FindDependencyByNamenull677 function FindDependencyByName(const PackageName: string): TPkgDependency;
FindRemovedDependencyByNamenull678 function FindRemovedDependencyByName(const PkgName: string): TPkgDependency;
RequiredDepByIndexnull679 function RequiredDepByIndex(Index: integer): TPkgDependency;
RemovedDepByIndexnull680 function RemovedDepByIndex(Index: integer): TPkgDependency;
681 procedure AddRequiredDependency(Dependency: TPkgDependency);
682 procedure AddPackageDependency(const PackageName: string);
683 procedure RemoveRequiredDepSilently(Dependency: TPkgDependency);
684 procedure RemoveRequiredDependency(Dependency: TPkgDependency);
685 procedure DeleteRequiredDependency(Dependency: TPkgDependency);
686 procedure DeleteRemovedDependency(Dependency: TPkgDependency);
687 procedure RemoveRemovedDependency(Dependency: TPkgDependency);
MoveRequiredDependencyUpnull688 function MoveRequiredDependencyUp(Dependency: TPkgDependency): Boolean;
MoveRequiredDependencyDownnull689 function MoveRequiredDependencyDown(Dependency: TPkgDependency): Boolean;
CreateDependencyWithOwnernull690 function CreateDependencyWithOwner(NewOwner: TObject;
691 WithMinVersion: boolean = false): TPkgDependency;
Requiresnull692 function Requires(APackage: TLazPackage): boolean;
693 procedure GetAllRequiredPackages(var List, FPMakeList: TFPList; WithSelf: boolean;
694 aFlags: TPkgIntfRequiredFlags = [];
695 MinPolicy: TPackageUpdatePolicy = low(TPackageUpdatePolicy));
696 // components
IndexOfPkgComponentnull697 function IndexOfPkgComponent(PkgComponent: TPkgComponent): integer;
AddComponentnull698 function AddComponent(PkgFile: TPkgFile; const Page: string;
699 TheComponentClass: TComponentClass): TPkgComponent;
700 procedure AddPkgComponent(APkgComponent: TPkgComponent);
701 procedure RemovePkgComponent(APkgComponent: TPkgComponent);
702 procedure IterateComponentClasses(Event: TIterateComponentClassesEvent;
703 WithUsedPackages: boolean);
704 procedure SetAllComponentPriorities(const p: TComponentPriority);
705 // used by dependencies
706 procedure AddUsedByDependency(Dependency: TPkgDependencyBase); override;
707 procedure RemoveUsedByDependency(Dependency: TPkgDependencyBase); override;
UsedByDepByIndexnull708 function UsedByDepByIndex(Index: integer): TPkgDependency;
FindUsedByDepPrefernull709 function FindUsedByDepPrefer(Ignore: TPkgDependency): TPkgDependency;
710 // provides
ProvidesPackagenull711 function ProvidesPackage(const AName: string): boolean;
712 // ID
713 procedure ChangeID(const NewName: string; NewVersion: TPkgVersion);
714 public
715 LastCompile: array[TPkgOutputDir] of TPkgLastCompileStats;
GetOutputDirTypenull716 function GetOutputDirType: TPkgOutputDir;
717 public
718 property AddToProjectUsesSection: boolean read FAddToProjectUsesSection
719 write SetAddToProjectUsesSection;
720 property Author: string read FAuthor write SetAuthor;
721 property AutoIncrementVersionOnBuild: boolean read GetAutoIncrementVersionOnBuild
722 write SetAutoIncrementVersionOnBuild;
723 property AutoUpdate: TPackageUpdatePolicy read FAutoUpdate write SetAutoUpdate;
724 property CompilerOptions: TPkgCompilerOptions read GetCompilerOptions;
725 property ComponentCount: integer read GetComponentCount;
726 property Components[Index: integer]: TPkgComponent read GetComponents;
727 property DefineTemplates: TLazPackageDefineTemplates read FDefineTemplates
728 write FDefineTemplates;
729 property Description: string read FDescription write SetDescription;
730 property Editor: TBasePackageEditor read FPackageEditor write SetPackageEditor;
731 property EnableI18N: Boolean read FEnableI18N write SetEnableI18N;
732 property EnableI18NForLFM: boolean read FEnableI18NForLFM write SetEnableI18NForLFM;
733 property FileReadOnly: boolean read FFileReadOnly write SetFileReadOnly;
734 property Files[Index: integer]: TPkgFile read GetFiles;
735 property FirstRemovedDependency: TPkgDependency read FFirstRemovedDependency;
736 property FirstRequiredDependency: TPkgDependency read FFirstRequiredDependency;
737 property FirstUsedByDependency: TPkgDependency read FFirstUsedByDependency;
738 property Flags: TLazPackageFlags read FFlags write SetFlags;
739 property HoldPackageCount: integer read FHoldPackageCount;
740 property IconFile: string read FIconFile write SetIconFile;
741 property IDEOptions: TPackageIDEOptions read GetIDEOptions;
742 property Installed: TPackageInstallType read FInstalled write SetInstalled;
743 property FPDocPaths: string read FFPDocPaths write SetFPDocPaths;
744 property FPDocPackageName: string read FFPDocPackageName write SetFPDocPackageName;
745 property License: string read FLicense write SetLicense;
746 // see Missing, can be nil when file on disk was removed or point to a different codebuffer during rename
747 property LPKSource: TCodeBuffer read FLPKSource write SetLPKSource;
748 property LPKSourceChangeStep: integer read FLPKSourceChangeStep write FLPKSourceChangeStep;
749 property Macros: TTransferMacroList read FMacros;
750 property MainUnit: TPkgFile read FMainUnit;
751 property Missing: boolean read FMissing write FMissing; // lpk is missing, Note: virtual packages can have Missing=false
752 property OptionsBackup: TLazPackage read FOptionsBackup;
753 property OutputStateFile: string read FOutputStateFile write SetOutputStateFile;
754 property PackageType: TLazPackageType read FPackageType write SetPackageType;
755 property POOutputDirectory: string read FPOOutputDirectory write SetPOOutputDirectory;
756 property Provides: TStrings read FProvides write SetProvides;
757 property PublishOptions: TPublishPackageOptions read fPublishOptions write fPublishOptions;
758 property Registered: boolean read FRegistered write SetRegistered;
759 property RemovedFiles[Index: integer]: TPkgFile read GetRemovedFiles;
760 property SourceDirectories: TFileReferenceList read GetSourceDirectories;
761 property StorePathDelim: TPathDelimSwitch read FStorePathDelim write SetStorePathDelim;
762 property TopologicalLevel: integer read FTopologicalLevel write FTopologicalLevel;
763 property Translated: string read FTranslated write FTranslated;
764 property UsageOptions: TPkgAdditionalCompilerOptions read FUsageOptions;
765 property UseLegacyLists: Boolean read GetUseLegacyLists write SetUseLegacyLists;
766 property UserReadOnly: boolean read FUserReadOnly write SetUserReadOnly;
767 property UserIgnoreChangeStamp: integer read FUserIgnoreChangeStamp
768 write FUserIgnoreChangeStamp;
769 property OnModifySilently: TNotifyEvent read FOnModifySilently write FOnModifySilently;
770 end;
771
772 PLazPackage = ^TLazPackage;
773
774
775 { TBasePackageEditor }
776
777 TBasePackageEditor = class(TForm)
778 protected
GetLazPackagenull779 function GetLazPackage: TLazPackage; virtual;
780 procedure SetLazPackage(const AValue: TLazPackage); virtual; abstract;
781 public
CanCloseEditornull782 function CanCloseEditor: TModalResult; virtual; abstract;
783 procedure UpdateAll(Immediately: boolean = false); virtual; abstract;
784 property LazPackage: TLazPackage read GetLazPackage write SetLazPackage;
785 end;
786
787 const
788 LazPkgXMLFileVersion = 5;
789
790 AutoUpdateNames: array[TPackageUpdatePolicy] of string = (
791 'Manually', 'OnRebuildingAll', 'AsNeeded');
792
793 var
794 // All TPkgDependency are added to this AVL tree (sorted for names, not version!)
795 PackageDependencies: TAVLTree = nil; // tree of TPkgDependency
796
797 OnGetAllRequiredPackages: TGetAllRequiredPackagesEvent = nil;
798 OnGetDependencyOwnerDescription: TGetDependencyOwnerDescription = nil;
799 OnGetDependencyOwnerDirectory: TGetDependencyOwnerDirectory = nil;
800 OnPackageFileLoaded: TNotifyEvent = nil;
801
CompareLazPackageIDnull802 function CompareLazPackageID(Data1, Data2: Pointer): integer;
CompareNameWithPackageIDnull803 function CompareNameWithPackageID(Key, Data: Pointer): integer;
ComparePkgIDMaskWithPackageIDnull804 function ComparePkgIDMaskWithPackageID(Key, Data: Pointer): integer;
CompareLazPackageIDNamesnull805 function CompareLazPackageIDNames(Data1, Data2: Pointer): integer;
CompareLazPackageTopologicallyAndNamenull806 function CompareLazPackageTopologicallyAndName(Data1, Data2: Pointer): integer;
CompareNameWithPkgDependencynull807 function CompareNameWithPkgDependency(Key, Data: Pointer): integer;
ComparePkgDependencyNamesnull808 function ComparePkgDependencyNames(Data1, Data2: Pointer): integer;
CompareUnitsTreenull809 function CompareUnitsTree(UnitTree1, UnitTree2: TPkgUnitsTree): integer;
ComparePackageWithUnitsTreenull810 function ComparePackageWithUnitsTree(Package: TLazPackage;
811 UnitTree: TPkgUnitsTree): integer;
ComparePkgFilesAlphabeticallynull812 function ComparePkgFilesAlphabetically(PkgFile1, PkgFile2: TPkgFile): integer;
813
GetUsageOptionsListnull814 function GetUsageOptionsList(PackageList: TFPList): TFPList;
815
GetPkgFileTypeLocalizedNamenull816 function GetPkgFileTypeLocalizedName(FileType: TPkgFileType): string;
NameToAutoUpdatePolicynull817 function NameToAutoUpdatePolicy(const s: string): TPackageUpdatePolicy;
FileNameToPkgFileTypenull818 function FileNameToPkgFileType(AFilename: string): TPkgFileType;
819
820 procedure SortDependencyListAlphabetically(Dependencies: TFPList);
821 procedure LoadPkgDependencyList(XMLConfig: TXMLConfig; const ThePath: string;
822 var First: TPkgDependency; ListType: TPkgDependencyDirection; Owner: TObject;
823 HoldPackages, SortList: boolean);
824 procedure SavePkgDependencyList(XMLConfig: TXMLConfig; const ThePath: string;
825 First: TPkgDependency; ListType: TPkgDependencyDirection;
826 UsePathDelim: TPathDelimSwitch;LegacyLists:Boolean);
827 procedure ListPkgIDToDependencyList(ListOfTLazPackageID: TObjectList;
828 var First: TPkgDependency; ListType: TPkgDependencyDirection; Owner: TObject;
829 HoldPackages: boolean);
830 procedure DeleteDependencyInList(ADependency: TPkgDependency;
831 var First: TPkgDependency; ListType: TPkgDependencyDirection);
832 procedure FreeDependencyList(var First: TPkgDependency;
833 ListType: TPkgDependencyDirection);
DependencyListAsStringnull834 function DependencyListAsString(First: TPkgDependency;
835 ListType: TPkgDependencyDirection): string;
836
FindDependencyByNameInListnull837 function FindDependencyByNameInList(First: TPkgDependency;
838 ListType: TPkgDependencyDirection; const Name: string): TPkgDependency;
FindCompatibleDependencyInListnull839 function FindCompatibleDependencyInList(First: TPkgDependency;
840 ListType: TPkgDependencyDirection; ComparePackage: TLazPackageID): TPkgDependency;
GetDependencyWithIndexnull841 function GetDependencyWithIndex(First: TPkgDependency;
842 ListType: TPkgDependencyDirection; Index: integer): TPkgDependency;
IndexOfDependencyInListnull843 function IndexOfDependencyInList(First: TPkgDependency;
844 ListType: TPkgDependencyDirection; FindDependency: TPkgDependency): integer;
GetFirstDependencynull845 function GetFirstDependency(ListItem: TPkgDependency;
846 ListType: TPkgDependencyDirection): TPkgDependency;
847
FindLowestPkgDependencyWithNamenull848 function FindLowestPkgDependencyWithName(const PkgName: string): TPkgDependency;
FindLowestPkgDependencyNodeWithNamenull849 function FindLowestPkgDependencyNodeWithName(const PkgName: string): TAVLTreeNode;
FindNextPkgDependencyNodeWithSameNamenull850 function FindNextPkgDependencyNodeWithSameName(Node: TAVLTreeNode): TAVLTreeNode;
851
GetDependencyOwnerAsStringnull852 function GetDependencyOwnerAsString(Dependency: TPkgDependency): string;
GetDependencyOwnerDirectorynull853 function GetDependencyOwnerDirectory(Dependency: TPkgDependency): string;
854
855 procedure PkgVersionLoadFromXMLConfig(Version: TPkgVersion;
856 XMLConfig: TXMLConfig; const Path: string; FileVersion: integer);
857 procedure PkgVersionSaveToXMLConfig(Version: TPkgVersion; XMLConfig: TXMLConfig;
858 const Path: string);
859 procedure PkgVersionLoadFromXMLConfig(Version: TPkgVersion;
860 XMLConfig: TXMLConfig);
861
862 var
863 Package1: TLazPackage; // don't use it - only for options dialog
864
865 function dbgs(p: TPackageUpdatePolicy): string; overload;
866 function dbgs(p: TLazPackageType): string; overload;
867 function PackagePathToStr(PathList: TFPList): string;
868
869
870 implementation
871
872 function GetPkgFileTypeLocalizedName(FileType: TPkgFileType): string;
873 begin
874 case FileType of
875 pftUnit: Result:=lisUnit;
876 pftVirtualUnit: Result:=lisPkgFileTypeVirtualUnit;
877 pftMainUnit: Result:=lisPkgFileTypeMainUnit;
878 pftLFM: Result:=lisPkgFileTypeLFM;
879 pftLRS: Result:=lisPkgFileTypeLRS;
880 pftInclude: Result:=lisPkgFileTypeInclude;
881 pftIssues: Result:=lisPkgFileTypeIssues;
882 pftText: Result:=lisPkgFileTypeText;
883 pftBinary: Result:=lisPkgFileTypeBinary;
884 else
885 Result:='Unknown';
886 end;
887 end;
888
889 function NameToAutoUpdatePolicy(const s: string): TPackageUpdatePolicy;
890 begin
891 for Result:=Low(TPackageUpdatePolicy) to High(TPackageUpdatePolicy) do
892 if SysUtils.CompareText(AutoUpdateNames[Result],s)=0 then exit;
893 Result:=pupAsNeeded;
894 end;
895
896 function FileNameToPkgFileType(AFilename: string): TPkgFileType;
897 var
898 Code: TCodeBuffer;
899 SrcType: String;
900 HasName: Boolean;
901 begin
902 HasName:=ExtractFileNameOnly(AFilename)<>'';
903 if HasName then begin
904 if FilenameExtIs(AFilename,'lfm',true) then
905 exit(pftLFM)
906 else if FilenameExtIs(AFilename,'lrs',true) then
907 exit(pftLRS)
908 else if FilenameExtIs(AFilename,'inc') then
909 exit(pftInclude)
910 else if FilenameExtIs(AFilename,'xml') then
911 exit(pftIssues)
912 else if FilenameHasPascalExt(AFilename) then begin
913 Result:=pftUnit;
914 AFilename:=CleanAndExpandFilename(AFilename);
915 Code:=CodeToolBoss.LoadFile(aFilename,true,false);
916 if Code<>nil then begin
917 SrcType:=CodeToolBoss.GetSourceType(Code,false);
918 if CompareText(SrcType,'unit')<>0 then
919 Result:=pftInclude;
920 end;
921 exit;
922 end;
923 end;
924 if FileIsText(AFilename) then
925 Result:=pftText
926 else
927 Result:=pftBinary;
928 end;
929
930 procedure LoadPkgDependencyList(XMLConfig: TXMLConfig; const ThePath: string;
931 var First: TPkgDependency; ListType: TPkgDependencyDirection; Owner: TObject;
932 HoldPackages, SortList: boolean);
933 var
934 i: Integer;
935 PkgDependency: TPkgDependency;
936 NewCount: Integer;
937 List: TFPList;
938 FileVersion: Integer;
939 Last: TPkgDependency;
940 LegacyList: Boolean;
941 SubPath: string;
942 begin
943 FileVersion:=XMLConfig.GetValue(ThePath+'Version',0);
944 LegacyList:=XMLConfig.IsLegacyList(ThePath);
945 NewCount:=XMLConfig.GetListItemCount(ThePath, 'Item', LegacyList);
946 List:=TFPList.Create;
947 for i:=0 to NewCount-1 do begin
948 PkgDependency:=TPkgDependency.Create;
949 SubPath:=ThePath+XMLConfig.GetListItemXPath('Item', i, LegacyList, True)+'/';
950 PkgDependency.LoadFromXMLConfig(XMLConfig,SubPath,FileVersion);
951 PkgDependency.HoldPackage:=HoldPackages;
952 // IsMakingSense checks if the package-name is a valid identifier. This is
953 // not applicable to FPMake-packages.
954 if (PkgDependency.DependencyType=pdtFPMake) or PkgDependency.IsMakingSense then
955 List.Add(PkgDependency)
956 else
957 PkgDependency.Free;
958 end;
959 if SortList then
960 SortDependencyListAlphabetically(List);
961 Last:=First;
962 if Last<>nil then
963 while Last.NextDependency[ListType]<>nil do
964 Last:=Last.NextDependency[ListType];
965 for i:=0 to List.Count-1 do begin
966 PkgDependency:=TPkgDependency(List[i]);
967 PkgDependency.AddToEndOfList(Last,ListType);
968 if First=nil then
969 First:=Last;
970 PkgDependency.Owner:=Owner;
971 end;
972 List.Free;
973 end;
974
975 procedure SavePkgDependencyList(XMLConfig: TXMLConfig; const ThePath: string;
976 First: TPkgDependency; ListType: TPkgDependencyDirection;
977 UsePathDelim: TPathDelimSwitch; LegacyLists: Boolean);
978 var
979 i: Integer;
980 Dependency: TPkgDependency;
981 SubPath: string;
982 begin
983 i:=0;
984 Dependency:=First;
985 while Dependency<>nil do begin
986 SubPath:=ThePath+XMLConfig.GetListItemXPath('Item', i, LegacyLists, True)+'/';
987 Dependency.SaveToXMLConfig(XMLConfig,SubPath,UsePathDelim);
988 Dependency:=Dependency.NextDependency[ListType];
989 inc(i);
990 end;
991 XMLConfig.SetListItemCount(ThePath, i, LegacyLists);
992 end;
993
994 procedure ListPkgIDToDependencyList(ListOfTLazPackageID: TObjectList;
995 var First: TPkgDependency; ListType: TPkgDependencyDirection; Owner: TObject;
996 HoldPackages: boolean);
997 var
998 NewDependency: TPkgDependency;
999 i: Integer;
1000 PkgID: TLazPackageID;
1001 begin
1002 First:=nil;
1003 for i:=ListOfTLazPackageID.Count-1 downto 0 do begin
1004 PkgID:=TLazPackageID(ListOfTLazPackageID[i]);
1005 NewDependency:=TPkgDependency.Create;
1006 NewDependency.Assign(PkgID);
1007 NewDependency.Owner:=Owner;
1008 NewDependency.HoldPackage:=HoldPackages;
1009 NewDependency.AddToList(First,ListType);
1010 end;
1011 end;
1012
1013 procedure DeleteDependencyInList(ADependency: TPkgDependency;
1014 var First: TPkgDependency; ListType: TPkgDependencyDirection);
1015 var
1016 NextDependency, PrevDependency: TPkgDependency;
1017 begin
1018 NextDependency := ADependency.NextDependency[ListType];
1019 PrevDependency := ADependency.PrevDependency[ListType];
1020 if First = ADependency then First := NextDependency;
1021 if Assigned(NextDependency) then
1022 NextDependency.PrevDependency[ListType] := PrevDependency;
1023 if Assigned(PrevDependency) then
1024 PrevDependency.NextDependency[ListType] := NextDependency;
1025 ADependency.Free;
1026 end;
1027
1028 procedure FreeDependencyList(var First: TPkgDependency;
1029 ListType: TPkgDependencyDirection);
1030 var
1031 NextDependency: TPkgDependency;
1032 begin
1033 while First<>nil do begin
1034 NextDependency:=First.NextDependency[ListType];
1035 First.Free;
1036 First:=NextDependency;
1037 end;
1038 end;
1039
1040 function DependencyListAsString(First: TPkgDependency;
1041 ListType: TPkgDependencyDirection): string;
1042 begin
1043 Result:='';
1044 while First<>nil do begin
1045 Result:=Result+First.AsString+LineEnding;
1046 First:=First.NextDependency[ListType];
1047 end;
1048 end;
1049
1050 procedure SortDependencyListAlphabetically(Dependencies: TFPList);
1051 var
1052 Count: Integer;
1053 i, j: Integer;
1054 Dependency1: TPkgDependency;
1055 Dependency2: TPkgDependency;
1056 Sorted: Boolean;
1057 begin
1058 if (Dependencies=nil) or (Dependencies.Count<2) then exit;
1059 // check if already sorted
1060 Count:=Dependencies.Count;
1061 Sorted:=true;
1062 for i:=0 to Count-2 do begin
1063 Dependency1:=TPkgDependency(Dependencies[i]);
1064 Dependency2:=TPkgDependency(Dependencies[i+1]);
1065 if Dependency1.Compare(Dependency2)>0 then begin
1066 Sorted:=false;
1067 break;
1068 end;
1069 end;
1070 if Sorted then exit;
1071 // bubble sort (slow, but dependency lists are normally sorted)
1072 for i:=0 to Count-2 do begin
1073 Dependency1:=TPkgDependency(Dependencies[i]);
1074 for j:=i+1 to Count-1 do begin
1075 Dependency2:=TPkgDependency(Dependencies[j]);
1076 if Dependency1.Compare(Dependency2)>0 then begin
1077 Dependencies.Exchange(i,j);
1078 Dependency1:=TPkgDependency(Dependencies[i]);
1079 end;
1080 end;
1081 end;
1082 end;
1083
1084 function StrToComponentBaseClass(const s: string): TPFComponentBaseClass;
1085 begin
1086 for Result:=low(TPFComponentBaseClass) to high(TPFComponentBaseClass) do
1087 if SysUtils.CompareText(PFComponentBaseClassNames[Result],s)=0 then exit;
1088 Result:=pfcbcNone;
1089 end;
1090
1091 function GetComponentBaseClass(aClass: TClass): TPFComponentBaseClass;
1092 begin
1093 Result:=pfcbcNone;
1094 if aClass=nil then exit;
1095 if aClass.InheritsFrom(TForm) then
1096 Result:=pfcbcForm
1097 else if aClass.InheritsFrom(TFrame) then
1098 Result:=pfcbcFrame
1099 else if aClass.InheritsFrom(TDataModule) then
1100 Result:=pfcbcDataModule
1101 else if aClass.InheritsFrom(TCustomForm) then
1102 Result:=pfcbcCustomForm;
1103 end;
1104
1105 function CompareLazPackageID(Data1, Data2: Pointer): integer;
1106 var
1107 Pkg1: TLazPackageID absolute Data1;
1108 Pkg2: TLazPackageID absolute Data2;
1109 begin
1110 Result:=Pkg1.Compare(Pkg2);
1111 end;
1112
1113 function CompareNameWithPackageID(Key, Data: Pointer): integer;
1114 var
1115 Name: String;
1116 Pkg: TLazPackageID;
1117 begin
1118 if Key<>nil then begin
1119 Name:=AnsiString(Key);
1120 Pkg:=TLazPackageID(Data);
1121 Result:=SysUtils.CompareText(Name,Pkg.Name);
1122 end else
1123 Result:=-1;
1124 end;
1125
1126 function ComparePkgIDMaskWithPackageID(Key, Data: Pointer): integer;
1127 var
1128 Pkg1: TLazPackageID absolute Key;
1129 Pkg2: TLazPackageID absolute Data;
1130 begin
1131 Result:=Pkg1.CompareMask(Pkg2);
1132 end;
1133
1134 function CompareLazPackageIDNames(Data1, Data2: Pointer): integer;
1135 var
1136 Pkg1: TLazPackageID absolute Data1;
1137 Pkg2: TLazPackageID absolute Data2;
1138 begin
1139 Result:=SysUtils.CompareText(Pkg1.Name,Pkg2.Name);
1140 end;
1141
1142 function CompareLazPackageTopologicallyAndName(Data1, Data2: Pointer): integer;
1143 var
1144 Pkg1: TLazPackage absolute Data1;
1145 Pkg2: TLazPackage absolute Data2;
1146 begin
1147 Result:=Pkg1.TopologicalLevel-Pkg2.TopologicalLevel;
1148 if Result<>0 then exit;
1149 Result:=SysUtils.CompareText(Pkg1.Name,Pkg2.Name);
1150 end;
1151
1152 function CompareNameWithPkgDependency(Key, Data: Pointer): integer;
1153 var
1154 PkgName: String;
1155 Dependency: TPkgDependency absolute Data;
1156 begin
1157 PkgName:=String(Key);
1158 Result:=SysUtils.CompareText(PkgName,Dependency.PackageName);
1159 end;
1160
1161 function ComparePkgDependencyNames(Data1, Data2: Pointer): integer;
1162 var
1163 Dependency1: TPkgDependency absolute Data1;
1164 Dependency2: TPkgDependency absolute Data2;
1165 begin
1166 Result:=SysUtils.CompareText(Dependency1.PackageName,Dependency2.PackageName);
1167 end;
1168
1169 function CompareUnitsTree(UnitTree1, UnitTree2: TPkgUnitsTree): integer;
1170 begin
1171 Result:=UnitTree1.LazPackage.Compare(UnitTree2.LazPackage);
1172 end;
1173
1174 function ComparePackageWithUnitsTree(Package: TLazPackage;
1175 UnitTree: TPkgUnitsTree): integer;
1176 begin
1177 Result:=Package.Compare(UnitTree.LazPackage);
1178 end;
1179
1180 function ComparePkgFilesAlphabetically(PkgFile1, PkgFile2: TPkgFile): integer;
1181 var
1182 ShortFilename1: String;
1183 ShortFilename2: String;
1184 File1IsInMainDir: Boolean;
1185 File2IsInMainDir: Boolean;
1186 begin
1187 ShortFilename1:=PkgFile1.GetShortFilename(true);
1188 ShortFilename2:=PkgFile2.GetShortFilename(true);
1189 // files in the main directory are higher
1190 File1IsInMainDir:=ExtractFilePath(ShortFilename1)='';
1191 File2IsInMainDir:=ExtractFilePath(ShortFilename2)='';
1192 if File1IsInMainDir xor File2IsInMainDir then begin
1193 if File1IsInMainDir then
1194 Result:=-1
1195 else
1196 Result:=1;
1197 exit;
1198 end;
1199 // compare short filenames without extension
1200 Result:=CompareFilenames(ChangeFileExt(ShortFilename1,''),
1201 ChangeFileExt(ShortFilename2,''));
1202 if Result<>0 then exit;
1203 // if one is a unit, then it is higher
1204 if (PkgFile1.Unit_Name<>'') and (PkgFile2.Unit_Name='') then begin
1205 Result:=-1;
1206 exit;
1207 end else if (PkgFile1.Unit_Name='') and (PkgFile2.Unit_Name<>'') then begin
1208 Result:=1;
1209 exit;
1210 end;
1211 // compare short filenames with extension
1212 Result:=CompareFilenames(ShortFilename1,ShortFilename2);
1213 if Result<>0 then exit;
1214 // compare filenames
1215 Result:=CompareFilenames(PkgFile1.FileName,PkgFile2.FileName);
1216 end;
1217
1218 function GetUsageOptionsList(PackageList: TFPList): TFPList;
1219 // returns a list of TPkgAdditionalCompilerOptions
1220 // from the list of TLazPackage
1221 var
1222 Cnt: Integer;
1223 i: Integer;
1224 begin
1225 if PackageList<>nil then begin
1226 Result:=TFPList.Create;
1227 Cnt:=PackageList.Count;
1228 for i:=0 to Cnt-1 do begin
1229 Result.Add(TLazPackage(PackageList[i]).UsageOptions);
1230 end;
1231 end else begin
1232 Result:=nil;
1233 end;
1234 end;
1235
1236 function FindDependencyByNameInList(First: TPkgDependency;
1237 ListType: TPkgDependencyDirection; const Name: string): TPkgDependency;
1238 begin
1239 Result:=First;
1240 while Result<>nil do begin
1241 if SysUtils.CompareText(Result.PackageName,Name)=0 then exit;
1242 Result:=Result.NextDependency[ListType];
1243 end;
1244 end;
1245
1246 function FindCompatibleDependencyInList(First: TPkgDependency;
1247 ListType: TPkgDependencyDirection; ComparePackage: TLazPackageID): TPkgDependency;
1248 begin
1249 Result:=First;
1250 while Result<>nil do begin
1251 if Result.IsCompatible(ComparePackage) then exit;
1252 Result:=Result.NextDependency[ListType];
1253 end;
1254 end;
1255
1256 function GetDependencyWithIndex(First: TPkgDependency;
1257 ListType: TPkgDependencyDirection; Index: integer): TPkgDependency;
1258 begin
1259 if Index<0 then RaiseGDBException('GetDependencyWithIndex');
1260 Result:=First;
1261 while (Result<>nil) and (Index>0) do begin
1262 Result:=Result.NextDependency[ListType];
1263 dec(Index);
1264 end;
1265 end;
1266
1267 function FindLowestPkgDependencyNodeWithName(const PkgName: string): TAVLTreeNode;
1268 begin
1269 Result:=nil;
1270 if PackageDependencies=nil then exit;
1271 Result:=PackageDependencies.FindLeftMostKey(PChar(PkgName),
1272 @CompareNameWithPkgDependency);
1273 end;
1274
1275 function FindNextPkgDependencyNodeWithSameName(
1276 Node: TAVLTreeNode): TAVLTreeNode;
1277 begin
1278 Result:=nil;
1279 if (Node=nil) or (PackageDependencies=nil) then exit;
1280 Result:=PackageDependencies.FindSuccessor(Node);
1281 if (Result<>nil)
1282 and (SysUtils.CompareText(TPkgDependency(Node.Data).PackageName,
1283 TPkgDependency(Result.Data).PackageName)<>0)
1284 then
1285 Result:=nil;
1286 end;
1287
1288 function GetDependencyOwnerAsString(Dependency: TPkgDependency): string;
1289 begin
1290 Result := '';
1291 OnGetDependencyOwnerDescription(Dependency,Result);
1292 end;
1293
1294 function GetDependencyOwnerDirectory(Dependency: TPkgDependency): string;
1295 begin
1296 Result := '';
1297 OnGetDependencyOwnerDirectory(Dependency,Result);
1298 end;
1299
1300 procedure PkgVersionLoadFromXMLConfig(Version: TPkgVersion;
1301 XMLConfig: TXMLConfig; const Path: string; FileVersion: integer);
1302 var
1303 NewMajor: Integer;
1304 NewMinor: Integer;
1305 NewRelease: Integer;
1306 NewBuild: Integer;
1307 begin
1308 if FileVersion=1 then ;
1309 NewMajor:=Version.VersionBound(XMLConfig.GetValue(Path+'Major',0));
1310 NewMinor:=Version.VersionBound(XMLConfig.GetValue(Path+'Minor',0));
1311 NewRelease:=Version.VersionBound(XMLConfig.GetValue(Path+'Release',0));
1312 NewBuild:=Version.VersionBound(XMLConfig.GetValue(Path+'Build',0));
1313 Version.SetValues(NewMajor,NewMinor,NewRelease,NewBuild,pvtBuild);
1314 end;
1315
1316 procedure PkgVersionSaveToXMLConfig(Version: TPkgVersion; XMLConfig: TXMLConfig;
1317 const Path: string);
1318 begin
1319 XMLConfig.SetDeleteValue(Path+'Major',Version.Major,0);
1320 XMLConfig.SetDeleteValue(Path+'Minor',Version.Minor,0);
1321 XMLConfig.SetDeleteValue(Path+'Release',Version.Release,0);
1322 XMLConfig.SetDeleteValue(Path+'Build',Version.Build,0);
1323 end;
1324
1325 procedure PkgVersionLoadFromXMLConfig(Version: TPkgVersion;
1326 XMLConfig: TXMLConfig);
1327 var
1328 Path: String;
1329 FileVersion: LongInt;
1330 begin
1331 Path:='Package/';
1332 FileVersion:=XMLConfig.GetValue(Path+'Version',0);
1333 PkgVersionLoadFromXMLConfig(Version,XMLConfig,Path+'Version/',FileVersion);
1334 end;
1335
1336 function dbgs(p: TPackageUpdatePolicy): string;
1337 begin
1338 Result:=GetEnumName(TypeInfo(p),ord(p));
1339 end;
1340
1341 function dbgs(p: TLazPackageType): string;
1342 begin
1343 Result:=LazPackageTypeIdents[p];
1344 end;
1345
1346 function PackagePathToStr(PathList: TFPList): string;
1347 var
1348 i: Integer;
1349 Item: TObject;
1350 Dep: TPkgDependency;
1351 begin
1352 Result:='';
1353 if PathList=nil then exit;
1354 for i:=0 to PathList.Count-1 do begin
1355 if i>0 then
1356 Result:=Result+' -> ';
1357 Item:=TObject(PathList[i]);
1358 if Item is TPkgDependency then begin
1359 Dep:=TPkgDependency(Item);
1360 Result:=Result+GetDependencyOwnerAsString(Dep);
1361 if i=PathList.Count-1 then
1362 Result:=Result+' -> '+Dep.AsString;
1363 end else if Item is TLazPackage then
1364 Result:=Result+TLazPackage(Item).Name
1365 else
1366 Result:=Result+DbgSName(Item);
1367 end;
1368 end;
1369
1370 function IndexOfDependencyInList(First: TPkgDependency;
1371 ListType: TPkgDependencyDirection; FindDependency: TPkgDependency): integer;
1372 var
1373 Dependency: TPkgDependency;
1374 begin
1375 Result:=-1;
1376 Dependency:=First;
1377 while Dependency<>nil do begin
1378 inc(Result);
1379 if Dependency=FindDependency then exit;
1380 Dependency:=Dependency.NextDependency[ListType];
1381 end;
1382 Result:=-1;
1383 end;
1384
1385 function GetFirstDependency(ListItem: TPkgDependency;
1386 ListType: TPkgDependencyDirection): TPkgDependency;
1387 begin
1388 Result:=ListItem;
1389 if Result=nil then exit;
1390 while Result.PrevDependency[ListType]<>nil do
1391 Result:=Result.PrevDependency[ListType];
1392 end;
1393
1394 function FindLowestPkgDependencyWithName(const PkgName: string): TPkgDependency;
1395 var
1396 ANode: TAVLTreeNode;
1397 begin
1398 ANode:=FindLowestPkgDependencyNodeWithName(PkgName);
1399 if ANode<>nil then
1400 Result:=TPkgDependency(ANode.Data)
1401 else
1402 Result:=nil;
1403 end;
1404
1405 { TPkgFile }
1406
1407 procedure TPkgFile.SetFilename(const AValue: string);
1408 var
1409 NewFilename: String;
1410 OldDirectory: String;
1411 begin
1412 NewFilename:=AValue;
1413 ForcePathDelims(NewFilename);
1414 if Filename=NewFilename then exit;
1415 fFilename:=NewFilename;
1416 fFullFilenameStamp:=LUInvalidChangeStamp;
1417 OldDirectory:=FDirectory;
1418 FDirectory:=ExtractFilePath(Filename);
1419 if OldDirectory<>FDirectory then begin
1420 if FSourceDirNeedReference then begin
1421 LazPackage.SourceDirectories.RemoveFilename(OldDirectory);
1422 LazPackage.SourceDirectories.AddFilename(FDirectory);
1423 end;
1424 end;
1425 UpdateUnitName;
1426 end;
1427
GetHasRegisterProcnull1428 function TPkgFile.GetHasRegisterProc: boolean;
1429 begin
1430 Result:=pffHasRegisterProc in FFlags;
1431 end;
1432
1433 procedure TPkgFile.SetAddToUsesPkgSection(const AValue: boolean);
1434 begin
1435 if AddToUsesPkgSection=AValue then exit;
1436 if AValue then
1437 Include(FFlags,pffAddToPkgUsesSection)
1438 else
1439 Exclude(FFlags,pffAddToPkgUsesSection);
1440 end;
1441
1442 procedure TPkgFile.SetAutoReferenceSourceDir(const AValue: boolean);
1443 begin
1444 if FAutoReferenceSourceDir=AValue then exit;
1445 FAutoReferenceSourceDir:=AValue;
1446 if FSourceDirNeedReference then
1447 UpdateSourceDirectoryReference;
1448 end;
1449
1450 procedure TPkgFile.SetRemoved(const AValue: boolean);
1451 begin
1452 if Removed=AValue then exit;
1453 inherited SetRemoved(AValue);
1454 FSourceDirNeedReference:=(FileType in PkgFileRealUnitTypes) and not Removed;
1455 UpdateSourceDirectoryReference;
1456 end;
1457
1458 procedure TPkgFile.SetDisableI18NForLFM(AValue: boolean);
1459 begin
1460 if DisableI18NForLFM=AValue then exit;
1461 inherited SetDisableI18NForLFM(AValue);
1462 LazPackage.Modified:=true;
1463 end;
1464
GetComponentsnull1465 function TPkgFile.GetComponents(Index: integer): TPkgComponent;
1466 begin
1467 Result:=TPkgComponent(FComponents[Index]);
1468 end;
1469
GetAddToUsesPkgSectionnull1470 function TPkgFile.GetAddToUsesPkgSection: boolean;
1471 begin
1472 Result:=pffAddToPkgUsesSection in FFlags;
1473 end;
1474
1475 procedure TPkgFile.SetFileType(const AValue: TPkgFileType);
1476 begin
1477 if FileType=AValue then exit;
1478 if (LazPackage<>nil) and (LazPackage.MainUnit=Self) then
1479 LazPackage.FMainUnit:=nil;
1480 inherited SetFileType(AValue);
1481 FSourceDirNeedReference:=(FileType in PkgFileRealUnitTypes) and not Removed;
1482 UpdateSourceDirectoryReference;
1483 if (FileType=pftMainUnit) and (LazPackage<>nil)
1484 and (LazPackage.MainUnit<>Self) then begin
1485 if LazPackage.MainUnit<>nil then
1486 LazPackage.MainUnit.FileType:=pftUnit;
1487 LazPackage.FMainUnit:=Self;
1488 end;
1489 end;
1490
1491 procedure TPkgFile.SetFlags(const AValue: TPkgFileFlags);
1492 begin
1493 if FFlags=AValue then exit;
1494 FFlags:=AValue;
1495 end;
1496
1497 procedure TPkgFile.SetHasRegisterProc(const AValue: boolean);
1498 begin
1499 if HasRegisterProc=AValue then exit;
1500 if AValue then
1501 Include(FFlags,pffHasRegisterProc)
1502 else
1503 Exclude(FFlags,pffHasRegisterProc);
1504 end;
1505
1506 procedure TPkgFile.SetUnitName(const AValue: string);
1507 begin
1508 if FUnitName=AValue then Exit;
1509 FUnitName:=AValue;
1510 end;
1511
1512 procedure TPkgFile.UpdateUnitName;
1513 var
1514 NewUnitName: String;
1515 begin
1516 if FilenameHasPascalExt(Filename) then begin
1517 NewUnitName:=ExtractFileNameOnly(Filename);
1518 if SysUtils.CompareText(NewUnitName,FUnitName)<>0 then
1519 FUnitName:=NewUnitName;
1520 end else
1521 FUnitName:='';
1522 end;
1523
GetComponentListnull1524 function TPkgFile.GetComponentList: TFPList;
1525 begin
1526 if FComponents=nil then FComponents:=TFPList.Create;
1527 Result:=FComponents;
1528 end;
1529
GetInUsesnull1530 function TPkgFile.GetInUses: boolean;
1531 begin
1532 Result:=pffAddToPkgUsesSection in FFlags;
1533 end;
1534
1535 procedure TPkgFile.SetInUses(AValue: boolean);
1536 begin
1537 if InUses=AValue then exit;
1538 if AValue then
1539 Include(FFlags,pffAddToPkgUsesSection)
1540 else
1541 Exclude(FFlags,pffAddToPkgUsesSection);
1542 end;
1543
GetIDEPackagenull1544 function TPkgFile.GetIDEPackage: TIDEPackage;
1545 begin
1546 Result:=FPackage;
1547 end;
1548
GetFilenamenull1549 function TPkgFile.GetFilename: string;
1550 begin
1551 Result:=fFilename;
1552 end;
1553
HasRegisteredPluginsnull1554 function TPkgFile.HasRegisteredPlugins: boolean;
1555 begin
1556 Result:=ComponentCount>0;
1557 end;
1558
MakeSensenull1559 function TPkgFile.MakeSense: boolean;
1560 begin
1561 Result:=Filename<>'';
1562 end;
1563
1564 procedure TPkgFile.UpdateSourceDirectoryReference;
1565 begin
1566 if (not AutoReferenceSourceDir) or (FPackage=nil) then exit;
1567 if FSourceDirNeedReference then begin
1568 if not SourceDirectoryReferenced then begin
1569 LazPackage.SourceDirectories.AddFilename(FDirectory);
1570 FSourceDirectoryReferenced:=true;
1571 end;
1572 end else begin
1573 if SourceDirectoryReferenced then begin
1574 LazPackage.SourceDirectories.RemoveFilename(FDirectory);
1575 FSourceDirectoryReferenced:=false;
1576 end;
1577 end;
1578 end;
1579
GetFullFilenamenull1580 function TPkgFile.GetFullFilename: string;
1581 begin
1582 if fFullFilenameStamp<>CompilerParseStamp then begin
1583 fFullFilename:=Filename;
1584 fFullFilenameStamp:=CompilerParseStamp;
1585 if LazPackage<>nil then begin
1586 LazPackage.SubstitutePkgMacros(fFullFilename,false);
1587 fFullFilename:=TrimFilename(fFullFilename);
1588 LazPackage.LongenFilename(fFullFilename);
1589 end
1590 else begin
1591 IDEMacros.SubstituteMacros(fFullFilename);
1592 fFullFilename:=TrimAndExpandFilename(fFullFilename);
1593 end;
1594 end;
1595 Result:=fFullFilename;
1596 end;
1597
1598 constructor TPkgFile.Create(ThePackage: TLazPackage);
1599 begin
1600 inherited Create;
1601 Clear;
1602 FPackage:=ThePackage;
1603 FComponentPriority:=ComponentPriorityNormal;
1604 end;
1605
1606 destructor TPkgFile.Destroy;
1607 begin
1608 FreeThenNil(FComponents);
1609 if (LazPackage<>nil) then begin
1610 if (LazPackage.MainUnit=Self) then
1611 LazPackage.FMainUnit:=nil;
1612 if (not (lpfDestroying in LazPackage.Flags)) then begin
1613 if Removed then
1614 LazPackage.FRemovedFiles.Remove(Self)
1615 else
1616 LazPackage.FFiles.Remove(Self);
1617 end;
1618 end;
1619 inherited Destroy;
1620 end;
1621
1622 procedure TPkgFile.Clear;
1623 begin
1624 AutoReferenceSourceDir:=false;
1625 if (LazPackage=nil) or (not (lpfDestroying in LazPackage.Flags)) then begin
1626 inherited SetRemoved(false);
1627 fFilename:='';
1628 FDirectory:='';
1629 FFlags:=[];
1630 inherited SetFileType(pftUnit);
1631 FSourceDirectoryReferenced:=false;
1632 FSourceDirNeedReference:=true;
1633 end;
1634 FreeThenNil(FComponents);
1635 if (LazPackage<>nil) and (LazPackage.MainUnit=Self) then
1636 LazPackage.FMainUnit:=nil;
1637 end;
1638
1639 procedure TPkgFile.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string;
1640 FileVersion: integer; AdjustPathDelims: boolean);
1641 var
1642 AFilename: String;
1643 CaseInsensitiveUnitName: String;
1644 Config: TXMLOptionsStorage;
1645 begin
1646 if FileVersion=1 then ;
1647 Clear;
1648 AFilename:=SwitchPathDelims(XMLConfig.GetValue(Path+'Filename/Value',''),
1649 AdjustPathDelims);
1650 FPackage.LongenFilename(AFilename);
1651 Filename:=AFilename;
1652 FileType:=PkgFileTypeIdentToType(XMLConfig.GetValue(Path+'Type/Value',''));
1653 HasRegisterProc:=XMLConfig.GetValue(Path+'HasRegisterProc/Value',false);
1654 AddToUsesPkgSection:=XMLConfig.GetValue(Path+'AddToUsesPkgSection/Value',
1655 FileType in PkgFileUnitTypes);
1656 DisableI18NForLFM:=XMLConfig.GetValue(Path+'DisableI18NForLFM/Value',false);
1657 fUnitName:=XMLConfig.GetValue(Path+'UnitName/Value','');
1658 if FileType in PkgFileUnitTypes then begin
1659 // make sure the unitname makes sense
1660 CaseInsensitiveUnitName:=ExtractFileNameOnly(Filename);
1661 if SysUtils.CompareText(fUnitName,CaseInsensitiveUnitName)<>0 then
1662 fUnitName:=CaseInsensitiveUnitName;
1663 end;
1664 FResourceBaseClass:=StrToComponentBaseClass(
1665 XMLConfig.GetValue(Path+'ResourceBaseClass/Value',''));
1666
1667 Config:=TXMLOptionsStorage.Create(XMLConfig);
1668 try
1669 TConfigMemStorage(CustomOptions).LoadFromConfig(Config,Path+'CustomOptions/');
1670 finally
1671 Config.Free;
1672 end;
1673 end;
1674
1675 procedure TPkgFile.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string;
1676 UsePathDelim: TPathDelimSwitch);
1677 var
1678 TmpFilename: String;
1679 Config: TXMLOptionsStorage;
1680 begin
1681 TmpFilename:=Filename;
1682 FPackage.ShortenFilename(TmpFilename,true);
1683 XMLConfig.SetDeleteValue(Path+'Filename/Value',
1684 SwitchPathDelims(TmpFilename,UsePathDelim),'');
1685 XMLConfig.SetDeleteValue(Path+'Type/Value',PkgFileTypeIdents[FileType],
1686 PkgFileTypeIdents[pftUnit]);
1687 XMLConfig.SetDeleteValue(Path+'HasRegisterProc/Value',HasRegisterProc,
1688 false);
1689 XMLConfig.SetDeleteValue(Path+'AddToUsesPkgSection/Value',AddToUsesPkgSection,
1690 FileType in PkgFileUnitTypes);
1691 XMLConfig.SetDeleteValue(Path+'DisableI18NForLFM/Value',DisableI18NForLFM,false);
1692 XMLConfig.SetDeleteValue(Path+'UnitName/Value',FUnitName,'');
1693 XMLConfig.SetDeleteValue(Path+'ResourceBaseClass/Value',
1694 PFComponentBaseClassNames[FResourceBaseClass],
1695 PFComponentBaseClassNames[pfcbcNone]);
1696
1697 Config:=TXMLOptionsStorage.Create(XMLConfig);
1698 try
1699 TConfigMemStorage(CustomOptions).SaveToConfig(Config,Path+'CustomOptions/');
1700 finally
1701 Config.Free;
1702 end;
1703 end;
1704
1705 procedure TPkgFile.ConsistencyCheck;
1706 begin
1707 if FPackage=nil then
1708 RaiseGDBException('TPkgFile.ConsistencyCheck FPackage=nil');
1709 if Filename='' then
1710 RaiseGDBException('TPkgFile.ConsistencyCheck FFilename=""');
1711 end;
1712
GetShortFilenamenull1713 function TPkgFile.GetShortFilename(UseUp: boolean): string;
1714 begin
1715 Result:=GetFullFilename;
1716 LazPackage.ShortenFilename(Result,UseUp);
1717 end;
1718
ComponentCountnull1719 function TPkgFile.ComponentCount: integer;
1720 begin
1721 if FComponents<>nil then
1722 Result:=FComponents.Count
1723 else
1724 Result:=0;
1725 end;
1726
1727 procedure TPkgFile.AddPkgComponent(APkgComponent: TPkgComponent);
1728 begin
1729 if FComponents=nil then FComponents:=TFPList.Create;
1730 FComponents.Add(APkgComponent);
1731 if LazPackage<>nil then
1732 LazPackage.AddPkgComponent(APkgComponent);
1733 end;
1734
1735 procedure TPkgFile.RemovePkgComponent(APkgComponent: TPkgComponent);
1736 begin
1737 if FComponents<>nil then
1738 FComponents.Remove(APkgComponent);
1739 if LazPackage<>nil then
1740 LazPackage.RemovePkgComponent(APkgComponent);
1741 end;
1742
GetResolvedFilenamenull1743 function TPkgFile.GetResolvedFilename: string;
1744 begin
1745 Result:=GetPhysicalFilenameCached(GetFullFilename,false);
1746 end;
1747
GetFileOwnernull1748 function TPkgFile.GetFileOwner: TObject;
1749 begin
1750 Result:=LazPackage;
1751 end;
1752
GetFileOwnerNamenull1753 function TPkgFile.GetFileOwnerName: string;
1754 begin
1755 if LazPackage<>nil then
1756 Result:=LazPackage.Name
1757 else
1758 Result:='';
1759 end;
1760
1761 { TPkgDependency }
1762
1763 procedure TPkgDependency.SetHoldPackage(const AValue: boolean);
1764 begin
1765 if FHoldPackage=AValue then exit;
1766 FHoldPackage:=AValue;
1767 if RequiredPackage<>nil then begin
1768 if FHoldPackage then
1769 inc(RequiredPackage.FHoldPackageCount)
1770 else
1771 dec(RequiredPackage.FHoldPackageCount);
1772 end;
1773 end;
1774
GetRequiredPackagenull1775 function TPkgDependency.GetRequiredPackage: TLazPackage;
1776 begin
1777 Result := TLazPackage(FRequiredPackage);
1778 end;
1779
1780 procedure TPkgDependency.SetRequiredPackage(AValue: TLazPackage);
1781 begin
1782 Assert((DependencyType=pdtLazarus) or not assigned(AValue), 'Not possible to set a reference to a LazPackage into an FPMake-dependency');
1783 RequiredIDEPackage := AValue;
1784 end;
1785
1786 procedure TPkgDependency.SetPackageName(const AValue: string);
1787 begin
1788 if FPackageName=AValue then exit;
1789 if (PackageDependencies<>nil) and (FPackageName<>'') then
1790 AVLRemovePointer(PackageDependencies,Self);
1791 FPackageName:=AValue;
1792 if (PackageDependencies<>nil) and (FPackageName<>'') then
1793 PackageDependencies.Add(Self);
1794 FDefaultFilename:='';
1795 end;
1796
1797 constructor TPkgDependency.Create;
1798 begin
1799 inherited Create;
1800 end;
1801
1802 destructor TPkgDependency.Destroy;
1803 begin
1804 inherited Destroy;
1805 end;
1806
1807 procedure TPkgDependency.Clear;
1808 begin
1809 inherited Clear;
1810 FDefaultFilename:='';
1811 FPreferDefaultFilename:=false;
1812 end;
1813
1814 procedure TPkgDependency.LoadFromXMLConfig(XMLConfig: TXMLConfig;
1815 const Path: string; FileVersion: integer);
1816
1817 function LoadFilename(const SubPath: string): string;
1818 var
1819 BaseDir: String;
1820 begin
1821 Result:=GetForcedPathDelims(XMLConfig.GetValue(Path+SubPath,''));
1822 if (Result<>'') and (Owner<>nil)
1823 and (not FilenameIsAbsolute(Result)) then begin
1824 BaseDir:=GetDependencyOwnerDirectory(Self);
1825 if BaseDir<>'' then
1826 Result:=TrimFilename(AppendPathDelim(BaseDir)+Result);
1827 end;
1828 end;
1829
1830 begin
1831 if FileVersion=1 then ;
1832 Clear;
1833 PackageName:=XMLConfig.GetValue(Path+'PackageName/Value','');
1834 if SameText(XMLConfig.GetValue(Path+'DependencyType/Value',''), PkgDependencyTypeNames[pdtFPMake]) then
1835 DependencyType:=pdtFPMake
1836 else
1837 DependencyType:=pdtLazarus;
1838 PkgVersionLoadFromXMLConfig(MaxVersion,XMLConfig,Path+'MaxVersion/',FileVersion);
1839 PkgVersionLoadFromXMLConfig(MinVersion,XMLConfig,Path+'MinVersion/',FileVersion);
1840 if XMLConfig.GetValue(Path+'MaxVersion/Valid',false) then
1841 Include(FFlags,pdfMaxVersion);
1842 if XMLConfig.GetValue(Path+'MinVersion/Valid',false) then
1843 Include(FFlags,pdfMinVersion);
1844 FDefaultFilename:=LoadFilename('DefaultFilename/Value');
1845 PreferDefaultFilename:=XMLConfig.GetValue(Path+'DefaultFilename/Prefer',false);
1846 end;
1847
1848 procedure TPkgDependency.SaveToXMLConfig(XMLConfig: TXMLConfig;
1849 const Path: string; UsePathDelim: TPathDelimSwitch);
1850
1851 procedure SaveFilename(const aPath: string; AFilename: string);
1852 var
1853 BaseDir: String;
1854 begin
1855 if (AFilename<>'')
1856 and (Owner<>nil) then begin
1857 BaseDir:=GetDependencyOwnerDirectory(Self);
1858 if BaseDir<>'' then
1859 AFilename:=CreateRelativePath(AFilename,BaseDir);
1860 end;
1861 XMLConfig.SetDeleteValue(Path+aPath,SwitchPathDelims(AFilename,UsePathDelim),'');
1862 end;
1863
1864 begin
1865 XMLConfig.SetDeleteValue(Path+'PackageName/Value',PackageName,'');
1866 PkgVersionSaveToXMLConfig(MaxVersion,XMLConfig,Path+'MaxVersion/');
1867 PkgVersionSaveToXMLConfig(MinVersion,XMLConfig,Path+'MinVersion/');
1868 XMLConfig.SetDeleteValue(Path+'MaxVersion/Valid',pdfMaxVersion in FFlags,false);
1869 XMLConfig.SetDeleteValue(Path+'MinVersion/Valid',pdfMinVersion in FFlags,false);
1870 SaveFilename('DefaultFilename/Value',FDefaultFilename);
1871 XMLConfig.SetDeleteValue(Path+'DefaultFilename/Prefer',PreferDefaultFilename,false);
1872 XMLConfig.SetDeleteValue(Path+'DependencyType/Value',PkgDependencyTypeNames[DependencyType],PkgDependencyTypeNames[pdtLazarus]);
1873 end;
1874
Comparenull1875 function TPkgDependency.Compare(Dependency2: TPkgDependency): integer;
1876 begin
1877 Result:=SysUtils.CompareText(PackageName,Dependency2.PackageName);
1878 if Result<>0 then exit;
1879 Result:=MinVersion.Compare(Dependency2.MinVersion);
1880 if Result<>0 then exit;
1881 Result:=CompareBoolean(pdfMinVersion in Flags,
1882 pdfMinVersion in Dependency2.Flags);
1883 if Result<>0 then exit;
1884 Result:=MaxVersion.Compare(Dependency2.MaxVersion);
1885 if Result<>0 then exit;
1886 Result:=CompareBoolean(pdfMaxVersion in Flags,
1887 pdfMaxVersion in Dependency2.Flags);
1888 end;
1889
1890 procedure TPkgDependency.Assign(Source: TPkgDependency);
1891 begin
1892 PackageName:=Source.PackageName;
1893 Flags:=Source.Flags;
1894 MinVersion.Assign(Source.MinVersion);
1895 MaxVersion.Assign(Source.MaxVersion);
1896 end;
1897
1898 procedure TPkgDependency.Assign(Source: TLazPackageID);
1899 begin
1900 PackageName:=Source.Name;
1901 Flags:=[pdfMinVersion];
1902 MinVersion.Assign(Source.Version);
1903 end;
1904
1905 procedure TPkgDependency.ConsistencyCheck;
1906 begin
1907
1908 end;
1909
IsCompatiblenull1910 function TPkgDependency.IsCompatible(Pkg: TLazPackageID): boolean;
1911 begin
1912 Result:=IsCompatible(Pkg.Name,Pkg.Version);
1913 end;
1914
1915 procedure TPkgDependency.MakeCompatible(const PkgName: string;
1916 const Version: TPkgVersion);
1917 begin
1918 PackageName:=PkgName;
1919 if MinVersion.Compare(Version)>0 then MinVersion.Assign(Version);
1920 if MaxVersion.Compare(Version)<0 then MaxVersion.Assign(Version);
1921 end;
1922
AsStringnull1923 function TPkgDependency.AsString(WithOwner, WithDefaults: boolean): string;
1924 var
1925 FN: String;
1926 begin
1927 Result:=inherited AsString;
1928 if WithOwner and (Owner<>nil) then
1929 Result:=GetDependencyOwnerAsString(Self)+' uses '+Result;
1930 if WithDefaults then
1931 begin
1932 if DefaultFilename<>'' then
1933 begin
1934 FN:=MakeFilenameRelativeToOwner(DefaultFilename);
1935 if PreferDefaultFilename then
1936 Result:=Format(lisCEIn, [Result,FN]) // like 'in' keyword in uses section
1937 else
1938 Result:=Format(lisPckEditDefault, [Result,FN]);
1939 end;
1940 if DependencyType=pdtFPMake then
1941 Result:=Result+' '+lisPckEditFPMakePackage;
1942 end;
1943 end;
1944
NextUsedByDependencynull1945 function TPkgDependency.NextUsedByDependency: TPkgDependency;
1946 begin
1947 Result:=NextDependency[pddUsedBy];
1948 end;
1949
PrevUsedByDependencynull1950 function TPkgDependency.PrevUsedByDependency: TPkgDependency;
1951 begin
1952 Result:=PrevDependency[pddUsedBy];
1953 end;
1954
NextRequiresDependencynull1955 function TPkgDependency.NextRequiresDependency: TPkgDependency;
1956 begin
1957 Result:=NextDependency[pddRequires];
1958 end;
1959
PrevRequiresDependencynull1960 function TPkgDependency.PrevRequiresDependency: TPkgDependency;
1961 begin
1962 Result:=PrevDependency[pddRequires];
1963 end;
1964
1965 procedure TPkgDependency.AddUsedByDep(var FirstDependency: TPkgDependencyBase);
1966 begin
1967 AddToList(TPkgDependency(FirstDependency), pddUsedBy);
1968 end;
1969
1970 procedure TPkgDependency.RemoveUsedByDep(var FirstDependency: TPkgDependencyBase);
1971 begin
1972 RemoveFromList(TPkgDependency(FirstDependency), pddUsedBy);
1973 end;
1974
1975 procedure TPkgDependency.AddRequiresDep(var FirstDependency: TPkgDependencyBase);
1976 begin
1977 AddToList(TPkgDependency(FirstDependency), pddRequires);
1978 end;
1979
1980 procedure TPkgDependency.RemoveRequiresDep(var FirstDependency: TPkgDependencyBase);
1981 begin
1982 RemoveFromList(TPkgDependency(FirstDependency), pddRequires);
1983 end;
1984
1985 procedure TPkgDependency.AddToList(var FirstDependency: TPkgDependency;
1986 ListType: TPkgDependencyDirection);
1987 begin
1988 NextDependency[ListType]:=FirstDependency;
1989 FirstDependency:=Self;
1990 PrevDependency[ListType]:=nil;
1991 if NextDependency[ListType]<>nil then
1992 NextDependency[ListType].PrevDependency[ListType]:=Self;
1993 end;
1994
1995 procedure TPkgDependency.AddToEndOfList(var LastDependency: TPkgDependency;
1996 ListType: TPkgDependencyDirection);
1997 begin
1998 PrevDependency[ListType]:=LastDependency;
1999 LastDependency:=Self;
2000 NextDependency[ListType]:=nil;
2001 if PrevDependency[ListType]<>nil then
2002 PrevDependency[ListType].NextDependency[ListType]:=Self;
2003 end;
2004
2005 procedure TPkgDependency.RemoveFromList(var FirstDependency: TPkgDependency;
2006 ListType: TPkgDependencyDirection);
2007 begin
2008 if FirstDependency=Self then FirstDependency:=NextDependency[ListType];
2009 if NextDependency[ListType]<>nil then
2010 NextDependency[ListType].PrevDependency[ListType]:=PrevDependency[ListType];
2011 if PrevDependency[ListType]<>nil then
2012 PrevDependency[ListType].NextDependency[ListType]:=NextDependency[ListType];
2013 NextDependency[ListType]:=nil;
2014 PrevDependency[ListType]:=nil;
2015 end;
2016
MoveUpInListnull2017 function TPkgDependency.MoveUpInList(var FirstDependency: TPkgDependency;
2018 ListType: TPkgDependencyDirection): Boolean;
2019 var
2020 OldPrev: TPkgDependency;
2021 begin
2022 if (FirstDependency=Self) or (PrevDependency[ListType]=nil) then exit(False);
2023 OldPrev:=PrevDependency[ListType];
2024 if OldPrev.PrevDependency[ListType]<>nil then
2025 OldPrev.PrevDependency[ListType].NextDependency[ListType]:=Self;
2026 if NextDependency[ListType]<>nil then
2027 NextDependency[ListType].PrevDependency[ListType]:=OldPrev;
2028 OldPrev.NextDependency[ListType]:=NextDependency[ListType];
2029 PrevDependency[ListType]:=OldPrev.PrevDependency[ListType];
2030 NextDependency[ListType]:=OldPrev;
2031 OldPrev.PrevDependency[ListType]:=Self;
2032 if FirstDependency=OldPrev then FirstDependency:=Self;
2033 Result:=True;
2034 end;
2035
MoveDownInListnull2036 function TPkgDependency.MoveDownInList(var FirstDependency: TPkgDependency;
2037 ListType: TPkgDependencyDirection): Boolean;
2038 var
2039 OldNext: TPkgDependency;
2040 begin
2041 if (NextDependency[ListType]=nil) then exit(False);
2042 OldNext:=NextDependency[ListType];
2043 if OldNext.NextDependency[ListType]<>nil then
2044 OldNext.NextDependency[ListType].PrevDependency[ListType]:=Self;
2045 if PrevDependency[ListType]<>nil then
2046 PrevDependency[ListType].NextDependency[ListType]:=OldNext;
2047 OldNext.PrevDependency[ListType]:=PrevDependency[ListType];
2048 NextDependency[ListType]:=OldNext.NextDependency[ListType];
2049 PrevDependency[ListType]:=OldNext;
2050 OldNext.NextDependency[ListType]:=Self;
2051 if FirstDependency=Self then FirstDependency:=OldNext;
2052 Result:=True;
2053 end;
2054
MakeFilenameRelativeToOwnernull2055 function TPkgDependency.MakeFilenameRelativeToOwner(const AFilename: string): string;
2056 var
2057 BaseDir: String;
2058 begin
2059 Result:=AFilename;
2060 if (Result<>'')
2061 and (Owner<>nil) then begin
2062 BaseDir:=GetDependencyOwnerDirectory(Self);
2063 if BaseDir<>'' then
2064 Result:=CreateRelativePath(Result,BaseDir);
2065 end;
2066 end;
2067
FindDefaultFilenamenull2068 function TPkgDependency.FindDefaultFilename: string;
2069 var
2070 AFilename: String;
2071 CurDir: String;
2072 begin
2073 Result:='';
2074 AFilename:=TrimFilename(DefaultFilename);
2075 if not FilenameExtIs(AFilename,'lpk',true)
2076 or (CompareText(ExtractFileNameOnly(AFilename),PackageName)<>0) then
2077 exit;
2078 if not FilenameIsAbsolute(AFilename) then begin
2079 CurDir:=GetDependencyOwnerDirectory(Self);
2080 if (CurDir<>'') then
2081 AFilename:=AppendPathDelim(CurDir)+AFilename;
2082 end;
2083 if not FilenameIsAbsolute(AFilename) then exit;
2084 AFilename:=CodeToolBoss.DirectoryCachePool.FindDiskFilename(AFilename);
2085 if not FileExistsCached(AFilename) then exit;
2086 Result:=AFilename;
2087 end;
2088
2089 { TPackageIDEOptions }
2090
GetPackagenull2091 function TPackageIDEOptions.GetPackage: TIDEPackage;
2092 begin
2093 Result := FPackage;
2094 end;
2095
2096 constructor TPackageIDEOptions.Create(APackage: TLazPackage);
2097 begin
2098 inherited Create;
2099 FPackage := APackage;
2100 end;
2101
2102 destructor TPackageIDEOptions.Destroy;
2103 begin
2104 inherited Destroy;
2105 end;
2106
2107 class function TPackageIDEOptions.GetInstance: TAbstractIDEOptions;
2108 begin
2109 if Package1<>nil then
2110 Result := Package1.IDEOptions
2111 else
2112 Result := nil;
2113 end;
2114
2115 class function TPackageIDEOptions.GetGroupCaption: string;
2116 begin
2117 Result := lisPckOptsPackageOptions;
2118 end;
2119
2120 { TLazPackage }
2121
2122 procedure TLazPackage.OnMacroListSubstitution(TheMacro: TTransferMacro;
2123 const MacroName: string; var s: string; const Data: PtrInt;
2124 var Handled, Abort: boolean; Depth: integer);
2125 var
2126 Values: TCTCfgScriptVariables;
2127 Macro: PCTCfgScriptVariable;
2128 var
2129 NewValue: String;
2130 begin
2131 if Data=CompilerOptionMacroPlatformIndependent then
2132 begin
2133 NewValue:=GetMakefileMacroValue(MacroName);
2134 if NewValue<>'' then begin
2135 s:=NewValue;
2136 Handled:=true;
2137 exit;
2138 end;
2139 end;
2140
2141 // check build macros
2142 if IsValidIdent(MacroName) then
2143 begin
2144 Values:=GetBuildMacroValues(CompilerOptions,true);
2145 if Values<>nil then begin
2146 Macro:=Values.GetVariable(PChar(MacroName));
2147 if Macro<>nil then
2148 begin
2149 s:=GetCTCSVariableAsString(Macro);
2150 //if MacroName='MyPackageOptions' then
2151 // debugln(['TLazPackage.OnMacroListSubstitution Pkg=',Name,' Macro=',MacroName,' Value="',s,'"']);
2152 Handled:=true;
2153 exit;
2154 end;
2155 end;
2156 end;
2157
2158 if s = '' then
2159 begin
2160 // check local macros
2161 if SysUtils.CompareText(MacroName,'PkgOutDir')=0 then begin
2162 Handled:=true;
2163 if Data=CompilerOptionMacroNormal then
2164 s:=GetOutputDirectory()
2165 else
2166 s:=CompilerOptions.ParsedOpts.GetParsedPIValue(pcosOutputDir);
2167 exit;
2168 end
2169 else if SysUtils.CompareText(MacroName,'PkgDir')=0 then begin
2170 Handled:=true;
2171 s:=FDirectory;
2172 exit;
2173 end
2174 else if SysUtils.CompareText(MacroName,'PkgName')=0 then begin
2175 Handled:=true;
2176 s:=Name;
2177 exit;
2178 end
2179 else if SysUtils.CompareText(MacroName,'PkgIncPath')=0 then begin
2180 Handled:=true;
2181 s:=GetIncludePath(false);
2182 exit;
2183 end
2184 else if SysUtils.CompareText(MacroName,'PkgSrcPath')=0 then begin
2185 Handled:=true;
2186 s:=SourceDirectories.CreateSearchPathFromAllFiles;
2187 exit;
2188 end
2189 else if SysUtils.CompareText(MacroName,'PkgUnitPath')=0 then begin
2190 Handled:=true;
2191 s:=GetUnitPath(false);
2192 exit;
2193 end;
2194 end;
2195
2196 // check global macros
2197 GlobalMacroList.ExecuteMacro(MacroName,s,Data,Handled,Abort,Depth);
2198 end;
2199
2200 procedure TLazPackage.SetUserReadOnly(const AValue: boolean);
2201 begin
2202 if FUserReadOnly=AValue then exit;
2203 FUserReadOnly:=AValue;
2204 end;
2205
SubstitutePkgMacrosnull2206 function TLazPackage.SubstitutePkgMacros(const s: string;
2207 PlatformIndependent: boolean): string;
2208 begin
2209 Result:=s;
2210 if PlatformIndependent then
2211 FMacros.SubstituteStr(Result,CompilerOptionMacroPlatformIndependent)
2212 else
2213 FMacros.SubstituteStr(Result,CompilerOptionMacroNormal);
2214 end;
2215
2216 procedure TLazPackage.WriteInheritedUnparsedOptions;
2217 var
2218 OptionsList: TFPList;
2219 AddOptions: TAdditionalCompilerOptions;
2220 i: Integer;
2221 begin
2222 OptionsList:=nil;
2223 CompilerOptions.GetInheritedCompilerOptions(OptionsList);
2224 if OptionsList<>nil then begin
2225 for i:=0 to OptionsList.Count-1 do begin
2226 AddOptions:=TAdditionalCompilerOptions(OptionsList[i]);
2227 if (not (AddOptions is TAdditionalCompilerOptions)) then continue;
2228 DebugLn('TLazPackage.WriteInheritedUnparsedOptions ',
2229 (AddOptions.Owner as TLazPackage).IDAsString,
2230 ' UnitPath="',AddOptions.GetOption(icoUnitPath),'"');
2231 end;
2232 OptionsList.Free;
2233 end;
2234 end;
2235
GetActiveBuildMethodnull2236 function TLazPackage.GetActiveBuildMethod: TBuildMethod;
2237 begin
2238 Result:=BuildMethod;
2239 if Result=bmBoth then begin
2240 if Assigned(FppkgInterface) and FppkgInterface.UseFPMakeWhenPossible then
2241 Result:=bmFPMake
2242 else
2243 Result:=bmLazarus;
2244 end;
2245 end;
2246
GetAutoIncrementVersionOnBuildnull2247 function TLazPackage.GetAutoIncrementVersionOnBuild: boolean;
2248 begin
2249 Result:=lpfAutoIncrementVersionOnBuild in FFlags;
2250 end;
2251
GetCompilerOptionsnull2252 function TLazPackage.GetCompilerOptions: TPkgCompilerOptions;
2253 begin
2254 Result := TPkgCompilerOptions(FLazCompilerOptions);
2255 end;
2256
GetBaseCompilerOptionsnull2257 function TLazPackage.GetBaseCompilerOptions: TBaseCompilerOptions;
2258 // This satisfies the IProjPack interface requirement.
2259 begin
2260 Result := TBaseCompilerOptions(FLazCompilerOptions);
2261 end;
2262
GetComponentCountnull2263 function TLazPackage.GetComponentCount: integer;
2264 begin
2265 Result:=FComponents.Count;
2266 end;
2267
GetComponentsnull2268 function TLazPackage.GetComponents(Index: integer): TPkgComponent;
2269 begin
2270 Result:=TPkgComponent(FComponents[Index]);
2271 end;
2272
GetDirectoryExpandednull2273 function TLazPackage.GetDirectoryExpanded: string;
2274 begin
2275 if (FDirectoryExpandedChangeStamp<>CompilerParseStamp) then begin
2276 FDirectoryExpanded:=FDirectory;
2277 // use default macros (not package macros)
2278 if IDEMacros<>nil then
2279 IDEMacros.SubstituteMacros(FDirectoryExpanded);
2280 FDirectoryExpanded:=AppendPathDelim(TrimFilename(FDirectoryExpanded));
2281 FDirectoryExpandedChangeStamp:=CompilerParseStamp;
2282 end;
2283 Result:=FDirectoryExpanded;
2284 end;
2285
GetRemovedCountnull2286 function TLazPackage.GetRemovedCount: integer;
2287 begin
2288 Result:=FRemovedFiles.Count;
2289 end;
2290
GetRemovedPkgFilesnull2291 function TLazPackage.GetRemovedPkgFiles(Index: integer): TLazPackageFile;
2292 begin
2293 Result:=GetRemovedFiles(Index);
2294 end;
2295
2296 procedure TLazPackage.AssignOptions(Source: TPersistent);
2297 var
2298 aSource: TLazPackage;
2299 begin
2300 inherited AssignOptions(Source);
2301 if Source is TLazPackage then
2302 begin
2303 aSource:=TLazPackage(Source);
2304 UserReadOnly:=aSource.UserReadOnly;
2305 Translated:=aSource.Translated;
2306 StorePathDelim:=aSource.StorePathDelim;
2307 // ToDo: PublishOptions.AssignOptions(aSource.PublishOptions);
2308 Provides.Assign(aSource.Provides);
2309 POOutputDirectory:=aSource.POOutputDirectory;
2310 PackageType:=aSource.PackageType;
2311 OutputStateFile:=aSource.OutputStateFile;
2312 License:=aSource.License;
2313 FPDocPaths:=aSource.FPDocPaths;
2314 FPDocPackageName:=aSource.FPDocPackageName;
2315 IconFile:=aSource.IconFile;
2316 UsageOptions.AssignOptions(aSource.UsageOptions);
2317 EnableI18N:=aSource.EnableI18N;
2318 EnableI18NForLFM:=aSource.EnableI18NForLFM;
2319 Description:=aSource.Description;
2320 AutoUpdate:=aSource.AutoUpdate;
2321 AutoIncrementVersionOnBuild:=aSource.AutoIncrementVersionOnBuild;
2322 Author:=aSource.Author;
2323 AddToProjectUsesSection:=aSource.AddToProjectUsesSection;
2324 end;
2325 end;
2326
GetRemovedFilesnull2327 function TLazPackage.GetRemovedFiles(Index: integer): TPkgFile;
2328 begin
2329 If (Index >= 0) And (Index < FRemovedFiles.Count) Then
2330 Result:=TPkgFile(FRemovedFiles[Index])
2331 Else
2332 Result := NIL;
2333 end;
2334
GetDefineTemplatesnull2335 function TLazPackage.GetDefineTemplates: TProjPackDefineTemplates;
2336 begin
2337 Result:=FDefineTemplates;
2338 end;
2339
GetFileCountnull2340 function TLazPackage.GetFileCount: integer;
2341 begin
2342 Result:=FFiles.Count;
2343 end;
2344
GetPkgFilesnull2345 function TLazPackage.GetPkgFiles(Index: integer): TLazPackageFile;
2346 begin
2347 Result:=GetFiles(Index);
2348 end;
2349
GetFilesnull2350 function TLazPackage.GetFiles(Index: integer): TPkgFile;
2351 begin
2352 Result:=TPkgFile(FFiles[Index]);
2353 end;
2354
GetIDEOptionsnull2355 function TLazPackage.GetIDEOptions: TPackageIDEOptions;
2356 begin
2357 Result := TPackageIDEOptions(FIDEOptions);
2358 end;
2359
GetSourceDirectoriesnull2360 function TLazPackage.GetSourceDirectories: TFileReferenceList;
2361 begin
2362 Result:=FSourceDirectories;
2363 end;
2364
GetModifiednull2365 function TLazPackage.GetModified: boolean;
2366 begin
2367 Result:=(lpfModified in FFlags) or CompilerOptions.Modified;
2368 end;
2369
2370 procedure TLazPackage.SetAddToProjectUsesSection(const AValue: boolean);
2371 begin
2372 if FAddToProjectUsesSection=AValue then exit;
2373 FAddToProjectUsesSection:=AValue;
2374 Modified:=true;
2375 end;
2376
2377 procedure TLazPackage.SetAuthor(const AValue: string);
2378 begin
2379 if FAuthor=AValue then exit;
2380 FAuthor:=AValue;
2381 Modified:=true;
2382 end;
2383
2384 procedure TLazPackage.SetAutoIncrementVersionOnBuild(const AValue: boolean);
2385 begin
2386 if AutoIncrementVersionOnBuild=AValue then exit;
2387 if AValue then
2388 Include(FFlags,lpfAutoIncrementVersionOnBuild)
2389 else
2390 Exclude(FFlags,lpfAutoIncrementVersionOnBuild);
2391 Modified:=true;
2392 end;
2393
2394 procedure TLazPackage.SetAutoInstall(AValue: TPackageInstallType);
2395 begin
2396 if FAutoInstall=AValue then exit;
2397 FAutoInstall:=AValue;
2398 end;
2399
2400 procedure TLazPackage.SetAutoUpdate(const AValue: TPackageUpdatePolicy);
2401 begin
2402 if AValue=AutoUpdate then exit;
2403 FAutoUpdate:=AValue;
2404 Modified:=true;
2405 end;
2406
2407 procedure TLazPackage.SetDescription(const AValue: string);
2408 begin
2409 if FDescription=AValue then exit;
2410 FDescription:=AValue;
2411 Modified:=true;
2412 end;
2413
2414 procedure TLazPackage.SetEnableI18NForLFM(AValue: boolean);
2415 begin
2416 if FEnableI18NForLFM=AValue then Exit;
2417 FEnableI18NForLFM:=AValue;
2418 Modified:=true;
2419 end;
2420
2421 procedure TLazPackage.SetFileReadOnly(const AValue: boolean);
2422 begin
2423 if FFileReadOnly=AValue then exit;
2424 FFileReadOnly:=AValue;
2425 end;
2426
2427 procedure TLazPackage.SetFilename(const AValue: string);
2428 var
2429 NewFilename: String;
2430 begin
2431 NewFilename:=AValue;
2432 ForcePathDelims(NewFilename);
2433 if FFilename=NewFilename then exit;
2434 FFilename:=NewFilename;
2435 if (FFilename<>'') and (FFilename[length(FFilename)]=PathDelim) then
2436 FDirectory:=FFilename
2437 else
2438 FDirectory:=ExtractFilePath(FFilename);
2439 FDirectoryExpandedChangeStamp:=LUInvalidChangeStamp;
2440 FHasDirectory:=(FDirectory<>'') and (FDirectory[length(FDirectory)]=PathDelim);
2441 FHasStaticDirectory:=FHasDirectory and FilenameIsAbsolute(FDirectory);
2442 FUsageOptions.BaseDirectory:=FDirectory;
2443 CompilerOptions.BaseDirectory:=FDirectory;
2444 Modified:=true;
2445 end;
2446
2447 procedure TLazPackage.SetFlags(const AValue: TLazPackageFlags);
2448 var
2449 ChangedFlags: TLazPackageFlags;
2450 begin
2451 if FFlags=AValue then exit;
2452 ChangedFlags:=(FFlags-AValue)+(AValue-FFlags);
2453 FFlags:=AValue;
2454 if ChangedFlags*[lpfAutoIncrementVersionOnBuild,lpfCompatibilityMode]<>[] then
2455 Modified:=true;
2456 end;
2457
2458 procedure TLazPackage.SetFPDocPackageName(AValue: string);
2459 begin
2460 if FFPDocPackageName=AValue then Exit;
2461 FFPDocPackageName:=AValue;
2462 Modified:=true;
2463 end;
2464
2465 procedure TLazPackage.SetIconFile(const AValue: string);
2466 begin
2467 if FIconFile=AValue then exit;
2468 FIconFile:=AValue;
2469 Modified:=true;
2470 end;
2471
2472 procedure TLazPackage.SetInstalled(const AValue: TPackageInstallType);
2473 begin
2474 if FInstalled=AValue then exit;
2475 FInstalled:=AValue;
2476 end;
2477
2478 procedure TLazPackage.SetFPDocPaths(const AValue: string);
2479 var
2480 NewValue: String;
2481 begin
2482 NewValue:=TrimSearchPath(AValue,'');
2483 if FFPDocPaths=NewValue then exit;
2484 FFPDocPaths:=NewValue;
2485 Modified:=true;
2486 end;
2487
2488 procedure TLazPackage.SetLicense(const AValue: string);
2489 begin
2490 if FLicense=AValue then exit;
2491 FLicense:=AValue;
2492 Modified:=true;
2493 end;
2494
2495 procedure TLazPackage.SetLPKSource(const AValue: TCodeBuffer);
2496 begin
2497 if FLPKSource=AValue then exit;
2498 FLPKSource:=AValue;
2499 if LPKSource<>nil then
2500 FLPKSourceChangeStep:=LPKSource.ChangeStep;
2501 // do not change Filename here.
2502 // See TPkgManager.DoSavePackage and TPkgManager.DoOpenPackageFile
2503 // the LPKSource is the codebuffer last used during load/save, so it is not valid
2504 // for packages that were not yet loaded/saved or during renaming/loading/saving.
2505 end;
2506
2507 procedure TLazPackage.SetOutputStateFile(const AValue: string);
2508 var
2509 NewStateFile: String;
2510 begin
2511 NewStateFile:=TrimFilename(AValue);
2512 if FOutputStateFile=NewStateFile then exit;
2513 FOutputStateFile:=NewStateFile;
2514 end;
2515
2516 procedure TLazPackage.SetProvides(const AValue: TStrings);
2517 begin
2518 if (AValue=FProvides) or (FProvides.Equals(AValue)) then exit;
2519 FProvides.Assign(AValue);
2520 Modified:=true;
2521 end;
2522
2523 procedure TLazPackage.SetPOOutputDirectory(const AValue: string);
2524 var
2525 NewValue: String;
2526 begin
2527 NewValue:=TrimFilename(AValue);
2528 if FPOOutputDirectory=NewValue then exit;
2529 FPOOutputDirectory:=NewValue;
2530 Modified:=true;
2531 end;
2532
2533 procedure TLazPackage.SetEnableI18N(const AValue: boolean);
2534 begin
2535 if FEnableI18N=AValue then exit;
2536 FEnableI18N:=AValue;
2537 Modified:=true;
2538 end;
2539
2540 procedure TLazPackage.SetRegistered(const AValue: boolean);
2541 begin
2542 if FRegistered=AValue then exit;
2543 FRegistered:=AValue;
2544 end;
2545
2546 procedure TLazPackage.ModifySilently;
2547 begin
2548 if FModifiedLock>0 then exit;
2549 Include(FFlags,lpfModified);
2550 Exclude(FFlags,lpfSkipSaving);
2551 if FChangeStamp<High(FChangeStamp) then
2552 inc(FChangeStamp)
2553 else
2554 FChangeStamp:=low(FChangeStamp);
2555 if Assigned(FOnModifySilently) then
2556 FOnModifySilently(Self);
2557 end;
2558
2559 procedure TLazPackage.SetModified(const AValue: boolean);
2560 begin
2561 if AValue then begin
2562 if FModifiedLock>0 then exit;
2563 ModifySilently;
2564 end
2565 else begin
2566 FFlags:=FFlags-[lpfModified,lpfSkipSaving];
2567 PublishOptions.Modified:=false;
2568 CompilerOptions.Modified:=false;
2569 end;
2570 if Modified and (Editor<>nil) then
2571 Editor.UpdateAll(false);
2572 end;
2573
2574 procedure TLazPackage.SetName(const NewName: TComponentName);
2575 begin
2576 if Name=NewName then exit;
2577 inherited SetName(NewName);
2578 FDefineTemplates.IDChanged;
2579 Modified:=true;
2580 end;
2581
2582 procedure TLazPackage.SetPackageEditor(const AValue: TBasePackageEditor);
2583 begin
2584 if FPackageEditor=AValue then exit;
2585 FPackageEditor:=AValue;
2586 end;
2587
2588 procedure TLazPackage.SetPackageType(const AValue: TLazPackageType);
2589 begin
2590 if FPackageType=AValue then exit;
2591 FPackageType:=AValue;
2592 Modified:=true;
2593 end;
2594
2595 procedure TLazPackage.SetStorePathDelim(const AValue: TPathDelimSwitch);
2596 begin
2597 if FStorePathDelim=AValue then exit;
2598 FStorePathDelim:=AValue;
2599 end;
2600
2601 procedure TLazPackage.SetUseLegacyLists(const AUseLegacyLists: Boolean);
2602 begin
2603 if AUseLegacyLists=UseLegacyLists then exit;
2604 if AUseLegacyLists then
2605 Include(FFlags, lpfCompatibilityMode)
2606 else
2607 Exclude(FFlags, lpfCompatibilityMode);
2608 Modified:=true;
2609 end;
2610
2611 constructor TLazPackage.Create;
2612 begin
2613 inherited Create;
2614 FComponents:=TFPList.Create;
2615 FSourceDirectories:=TFileReferenceList.Create;
2616 FSourceDirectories.OnChanged:=@SourceDirectoriesChanged;
2617 FFiles:=TFPList.Create;
2618 FRemovedFiles:=TFPList.Create;
2619 FMacros:=TTransferMacroList.Create;
2620 FMacros.OnSubstitution:=@OnMacroListSubstitution;
2621 FIDEOptions:=TPackageIDEOptions.Create(Self);
2622 FLazCompilerOptions:=TPkgCompilerOptions.Create(Self);
2623 CompilerOptions.ParsedOpts.InvalidateParseOnChange:=true;
2624 CompilerOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacros;
2625 CompilerOptions.DefaultMakeOptionsFlags:=[ccloNoLinkerOpts];
2626 FUsageOptions:=TPkgAdditionalCompilerOptions.Create(Self);
2627 FUsageOptions.ParsedOpts.OnLocalSubstitute:=@SubstitutePkgMacros;
2628 FDefineTemplates:=TLazPackageDefineTemplates.Create(Self);
2629 fPublishOptions:=TPublishPackageOptions.Create(Self);
2630 FProvides:=TStringList.Create;
2631 FUsageOptions.ParsedOpts.InvalidateParseOnChange:=true;
2632 end;
2633
2634 constructor TLazPackage.CreateAndClear;
2635 begin
2636 Create;
2637 Clear;
2638 end;
2639
2640 destructor TLazPackage.Destroy;
2641 begin
2642 Include(FFlags,lpfDestroying);
2643 Clear;
2644 FreeAndNil(FOptionsBackup);
2645 FreeAndNil(fPublishOptions);
2646 FreeAndNil(FProvides);
2647 FreeAndNil(FDefineTemplates);
2648 FreeAndNil(FRemovedFiles);
2649 FreeAndNil(FFiles);
2650 FreeAndNil(FComponents);
2651 FreeAndNil(FLazCompilerOptions);
2652 FreeAndNil(FIDEOptions);
2653 FreeAndNil(FUsageOptions);
2654 FreeAndNil(FMacros);
2655 FreeAndNil(FSourceDirectories);
2656 inherited Destroy;
2657 end;
2658
2659 procedure TLazPackage.BackupOptions;
2660 begin
2661 if FOptionsBackup=nil then
2662 FOptionsBackup:=TLazPackage.Create;
2663 FOptionsBackup.AssignOptions(Self);
2664 FOptionsBackup.FFlags:=FOptionsBackup.FFlags-[lpfModified]+[lpfModified]*FFlags;
2665 FOptionsBackup.CompilerOptions.Modified:=CompilerOptions.Modified;
2666 end;
2667
2668 procedure TLazPackage.RestoreOptions;
2669 begin
2670 if FOptionsBackup=nil then exit;
2671 AssignOptions(FOptionsBackup);
2672 FFlags:=FFlags-[lpfModified]+[lpfModified]*FOptionsBackup.FFlags;
2673 CompilerOptions.Modified:=FOptionsBackup.CompilerOptions.Modified;
2674 end;
2675
2676 procedure TLazPackage.BeginUpdate;
2677 begin
2678 inc(FUpdateLock);
2679 FDefineTemplates.BeginUpdate;
2680 FSourceDirectories.BeginUpdate;
2681 end;
2682
2683 procedure TLazPackage.EndUpdate;
2684 begin
2685 if FUpdateLock=0 then RaiseGDBException('TLazPackage.EndUpdate');
2686 dec(FUpdateLock);
2687 FDefineTemplates.EndUpdate;
2688 FSourceDirectories.EndUpdate;
2689 end;
2690
2691 procedure TLazPackage.Clear;
2692 var
2693 i: Integer;
2694 begin
2695 // break used-by dependencies
2696 while FFirstUsedByDependency<>nil do
2697 FFirstUsedByDependency.RequiredPackage:=nil;
2698 // break and free removed dependencies
2699 while FFirstRemovedDependency<>nil do
2700 DeleteRemovedDependency(FFirstRemovedDependency);
2701 // break and free required dependencies
2702 while FFirstRequiredDependency<>nil do
2703 DeleteRequiredDependency(FFirstRequiredDependency);
2704 if not (lpfDestroying in FFlags) then begin
2705 FAddToProjectUsesSection:=false;
2706 FAuthor:='';
2707 FAutoInstall:=pitNope;
2708 FComponents.Clear;
2709 CompilerOptions.Clear;
2710 FDescription:='';
2711 FDirectory:='';
2712 FDirectoryExpandedChangeStamp:=LUInvalidChangeStamp;
2713 FEnableI18N:=false;
2714 FEnableI18NForLFM:=false;
2715 FPOOutputDirectory:='';
2716 FHasDirectory:=false;
2717 FHasStaticDirectory:=false;
2718 FVersion.Clear;
2719 FFilename:='';
2720 FIconFile:='';
2721 FInstalled:=pitNope;
2722 Name:='';
2723 FPackageType:=lptRunAndDesignTime;
2724 FRegistered:=false;
2725 FFPDocPaths:='';
2726 FFPDocPackageName:='';
2727 ClearCustomOptions;
2728 end;
2729 for i:=FComponents.Count-1 downto 0 do Components[i].Free;
2730 for i:=FRemovedFiles.Count-1 downto 0 do RemovedFiles[i].Free;
2731 FRemovedFiles.Clear;
2732 for i:=FFiles.Count-1 downto 0 do Files[i].Free;
2733 FFiles.Clear;
2734 FUsageOptions.Clear;
2735 fPublishOptions.Clear;
2736 FProvides.Clear;
2737 UpdateSourceDirectories;
2738 // set some nice start values
2739 if not (lpfDestroying in FFlags) then begin
2740 FFlags:=[lpfAutoIncrementVersionOnBuild];
2741 FAutoUpdate:=pupAsNeeded;
2742 FLazCompilerOptions.UnitOutputDirectory:=
2743 'lib'+PathDelim+'$(TargetCPU)-$(TargetOS)'+PathDelim;
2744 FUsageOptions.UnitPath:='$(PkgOutDir)';
2745 end else begin
2746 FFlags:=[lpfDestroying];
2747 end;
2748 FStorePathDelim:=pdsNone;
2749 end;
2750
2751 //function DbgS(PkgFileType: TPkgFileType): string;
2752 //begin
2753 // WriteStr(Result, PkgFileType);
2754 //end;
2755
2756 procedure TLazPackage.UpdateSourceDirectories;
2757 var
2758 Cnt: Integer;
2759 i: Integer;
2760 PkgFile: TPkgFile;
2761 begin
2762 Cnt:=FFiles.Count;
2763 for i:=0 to Cnt-1 do begin
2764 PkgFile:=Files[i];
2765 PkgFile.FSourceDirectoryReferenced:=false;
2766 end;
2767 fSourceDirectories.Clear;
2768 for i:=0 to Cnt-1 do begin
2769 PkgFile:=Files[i];
2770 PkgFile.AutoReferenceSourceDir:=true;
2771 PkgFile.UpdateSourceDirectoryReference;
2772 //debugln('TLazPackage.UpdateSourceDirectories A ',PkgFile.Filename,' ',
2773 // ' ',DbgS(PkgFile.FileType),' ',PkgFile.Removed,
2774 // ' HasPkg=',dbgs(PkgFile.LazPackage=Self),
2775 // ' Need=',PkgFile.FSourceDirNeedReference,
2776 // ' Is=',PkgFile.FSourceDirectoryReferenced);
2777 end;
2778 //debugln('TLazPackage.UpdateSourceDirectories B ',IDAsString,' ',FFiles.Count,' "',fSourceDirectories.CreateSearchPathFromAllFiles,'"');
2779 end;
2780
2781 procedure TLazPackage.VersionChanged(Sender: TObject);
2782 begin
2783 inherited VersionChanged(Sender);
2784 FDefineTemplates.IDChanged;
2785 Modified:=true;
2786 end;
2787
2788 procedure TLazPackage.SourceDirectoriesChanged(Sender: TObject);
2789 begin
2790 FDefineTemplates.SourceDirectoriesChanged;
2791 end;
2792
GetDirectorynull2793 function TLazPackage.GetDirectory: string;
2794 begin
2795 Result:=FDirectory;
2796 end;
2797
2798 procedure TLazPackage.LockModified;
2799 begin
2800 inc(FModifiedLock);
2801 end;
2802
2803 procedure TLazPackage.UnlockModified;
2804 begin
2805 if FModifiedLock<=0 then
2806 RaiseGDBException('TLazPackage.UnlockModified');
2807 dec(FModifiedLock);
2808 end;
2809
ReadOnlynull2810 function TLazPackage.ReadOnly: boolean;
2811 begin
2812 Result:=UserReadOnly or FileReadOnly;
2813 end;
2814
2815 procedure TLazPackage.LoadFromXMLConfig(XMLConfig: TXMLConfig;
2816 const Path: string);
2817 var
2818 FileVersion: integer;
2819 OldFilename: String;
2820 PathDelimChanged: boolean;
2821 Config: TXMLOptionsStorage;
2822
2823 procedure LoadFiles(const ThePath: string; List: TFPList);
2824 var
2825 i: Integer;
2826 NewCount: Integer;
2827 PkgFile: TPkgFile;
2828 LegacyList: Boolean;
2829 SubPath: string;
2830 begin
2831 LegacyList := (FileVersion<=4) or XMLConfig.IsLegacyList(ThePath);
2832 NewCount:=XMLConfig.GetListItemCount(ThePath, 'Item', LegacyList);
2833 for i:=0 to NewCount-1 do begin
2834 PkgFile:=TPkgFile.Create(Self);
2835 SubPath := ThePath+XMLConfig.GetListItemXPath('Item', i, LegacyList, True)+'/';
2836 PkgFile.LoadFromXMLConfig(XMLConfig,SubPath,FileVersion,PathDelimChanged);
2837 if PkgFile.MakeSense then
2838 List.Add(PkgFile)
2839 else
2840 PkgFile.Free;
2841 end;
2842 end;
2843
2844 procedure LoadFlags(const ThePath: string);
2845 begin
2846 if XMLConfig.GetValue(ThePath+'AutoIncrementVersionOnBuild/Value',true) then
2847 Include(FFlags,lpfAutoIncrementVersionOnBuild)
2848 else
2849 Exclude(FFlags,lpfAutoIncrementVersionOnBuild);
2850 if FileVersion<=4 then begin
2851 // set CompatibilityMode flag for legacy projects (this flag was added in FileVersion=5 that changed
2852 // item format so that LPK cannot be opened in legacy Lazarus unless lpfCompatibilityMode is set)
2853 Include(FFlags,lpfCompatibilityMode);
2854 end else
2855 begin
2856 if XMLConfig.GetValue(ThePath+'CompatibilityMode/Value',false) then
2857 Include(FFlags,lpfCompatibilityMode)
2858 else
2859 Exclude(FFlags,lpfCompatibilityMode);
2860 end;
2861 end;
2862
2863 begin
2864 Flags:=Flags+[lpfLoading];
2865 FileVersion:=XMLConfig.GetValue(Path+'Version',0);
2866 OldFilename:=Filename;
2867 BeginUpdate;
2868 Clear;
2869 Filename:=OldFilename;
2870 LockModified;
2871 LoadFlags(Path);
2872 StorePathDelim:=CheckPathDelim(XMLConfig.GetValue(Path+'PathDelim/Value','/'),PathDelimChanged);
2873 Name:=XMLConfig.GetValue(Path+'Name/Value','');
2874 FPackageType:=LazPackageTypeIdentToType(XMLConfig.GetValue(Path+'Type/Value',
2875 LazPackageTypeIdents[lptRunTime]));
2876 FBuildMethod:=StringToBuildMethod(XMLConfig.GetValue(Path+'BuildMethod/Value',
2877 SBuildMethod[bmLazarus]));
2878 FAddToProjectUsesSection:=XMLConfig.GetValue(Path+'AddToProjectUsesSection/Value',
2879 FileVersion<4); // since version 4 the default is false
2880 FAuthor:=XMLConfig.GetValue(Path+'Author/Value','');
2881 FAutoUpdate:=NameToAutoUpdatePolicy(
2882 XMLConfig.GetValue(Path+'AutoUpdate/Value',''));
2883 if FileVersion<2 then
2884 CompilerOptions.LoadFromXMLConfig(XMLConfig,'CompilerOptions/')
2885 else
2886 CompilerOptions.LoadFromXMLConfig(XMLConfig,Path+'CompilerOptions/');
2887 FDescription:=XMLConfig.GetValue(Path+'Description/Value','');
2888 FLicense:=XMLConfig.GetValue(Path+'License/Value','');
2889 PkgVersionLoadFromXMLConfig(FVersion,XMLConfig,Path+'Version/',FileVersion);
2890 FIconFile:=SwitchPathDelims(XMLConfig.GetValue(Path+'IconFile/Value',''),
2891 PathDelimChanged);
2892 OutputStateFile:=SwitchPathDelims(
2893 XMLConfig.GetValue(Path+'OutputStateFile/Value',''),
2894 PathDelimChanged);
2895 FFPDocPaths:=SwitchPathDelims(XMLConfig.GetValue(Path+'LazDoc/Paths',''),
2896 PathDelimChanged);
2897 FFPDocPackageName:=XMLConfig.GetValue(Path+'LazDoc/PackageName','');
2898 // i18n
2899 if FileVersion<3 then begin
2900 FPOOutputDirectory := SwitchPathDelims(
2901 xmlconfig.GetValue(Path+'RST/OutDir', ''),PathDelimChanged);
2902 EnableI18N := FPOOutputDirectory <> '';
2903 end else begin
2904 EnableI18N := xmlconfig.GetValue(Path+'i18n/EnableI18N/Value', False);
2905 FPOOutputDirectory := SwitchPathDelims(
2906 xmlconfig.GetValue(Path+'i18n/OutDir/Value', ''),PathDelimChanged);
2907 end;
2908 EnableI18NForLFM:=xmlconfig.GetValue(Path+'i18n/EnableI18NForLFM/Value', false);
2909
2910 LoadFiles(Path+'Files/',FFiles);
2911 UpdateSourceDirectories;
2912 LoadPkgDependencyList(XMLConfig,Path+'RequiredPkgs/',
2913 FFirstRequiredDependency,pddRequires,Self,false,false);
2914 FUsageOptions.LoadFromXMLConfig(XMLConfig,Path+'UsageOptions/',
2915 PathDelimChanged);
2916 fPublishOptions.LoadFromXMLConfig(XMLConfig,Path+'PublishOptions/',
2917 PathDelimChanged);
2918 LoadStringList(XMLConfig,FProvides,Path+'Provides/');
2919 Config:=TXMLOptionsStorage.Create(XMLConfig);
2920 try
2921 TConfigMemStorage(CustomOptions).LoadFromConfig(Config,Path+'CustomOptions/');
2922 finally
2923 Config.Free;
2924 end;
2925
2926 EndUpdate;
2927 Modified:=false;
2928 UnlockModified;
2929 Flags:=Flags-[lpfLoading];
2930 end;
2931
2932 procedure TLazPackage.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string);
2933 var
2934 UsePathDelim: TPathDelimSwitch;
2935 Config: TXMLOptionsStorage;
2936
2937 function f(const AFilename: string): string;
2938 begin
2939 Result:=SwitchPathDelims(AFilename,UsePathDelim);
2940 end;
2941
2942 procedure SaveFiles(const ThePath: string; List: TFPList);
2943 var
2944 i: Integer;
2945 PkgFile: TPkgFile;
2946 SubPath: string;
2947 begin
2948 XMLConfig.SetListItemCount(ThePath, List.Count, UseLegacyLists);
2949 for i:=0 to List.Count-1 do begin
2950 PkgFile:=TPkgFile(List[i]);
2951 SubPath := ThePath+XMLConfig.GetListItemXPath('Item', i, UseLegacyLists, True)+'/';
2952 PkgFile.SaveToXMLConfig(XMLConfig,SubPath,UsePathDelim);
2953 end;
2954 end;
2955
2956 procedure SaveFlags(const ThePath: string);
2957 begin
2958 XMLConfig.SetDeleteValue(ThePath+'AutoIncrementVersionOnBuild/Value',
2959 AutoIncrementVersionOnBuild,true);
2960 XMLConfig.SetDeleteValue(ThePath+'CompatibilityMode/Value',
2961 UseLegacyLists,false);
2962 end;
2963
2964 begin
2965 UsePathDelim:=StorePathDelim;
2966 XMLConfig.SetValue(Path+'Version',LazPkgXMLFileVersion);
2967 XMLConfig.SetDeleteValue(Path+'PathDelim/Value',PathDelimSwitchToDelim[UsePathDelim],'/');
2968 XMLConfig.SetDeleteValue(Path+'Name/Value',Name,'');
2969 XMLConfig.SetDeleteValue(Path+'Type/Value',LazPackageTypeIdents[FPackageType],
2970 LazPackageTypeIdents[lptRunTime]);
2971 XMLConfig.SetDeleteValue(Path+'BuildMethod/Value',SBuildMethod[FBuildMethod],
2972 SBuildMethod[bmLazarus]);
2973 XMLConfig.SetDeleteValue(Path+'AddToProjectUsesSection/Value',
2974 FAddToProjectUsesSection,false);
2975 XMLConfig.SetDeleteValue(Path+'Author/Value',FAuthor,'');
2976 XMLConfig.SetDeleteValue(Path+'AutoUpdate/Value',AutoUpdateNames[FAutoUpdate],
2977 AutoUpdateNames[pupAsNeeded]);
2978 CompilerOptions.SaveToXMLConfig(XMLConfig,Path+'CompilerOptions/');
2979 XMLConfig.SetDeleteValue(Path+'Description/Value',FDescription,'');
2980 XMLConfig.SetDeleteValue(Path+'License/Value',FLicense,'');
2981 PkgVersionSaveToXMLConfig(FVersion,XMLConfig,Path+'Version/');
2982 SaveFiles(Path+'Files/',FFiles);
2983 SaveFlags(Path);
2984 XMLConfig.SetDeleteValue(Path+'IconFile/Value',f(FIconFile),'');
2985 XMLConfig.SetDeleteValue(Path+'OutputStateFile/Value',f(OutputStateFile),'');
2986 XMLConfig.SetDeleteValue(Path+'LazDoc/Paths',f(FFPDocPaths),'');
2987 XMLConfig.SetDeleteValue(Path+'LazDoc/PackageName',FFPDocPackageName,'');
2988
2989 XMLConfig.SetDeleteValue(Path+'i18n/EnableI18N/Value', EnableI18N, false);
2990 XMLConfig.SetDeleteValue(Path+'i18n/OutDir/Value',f(FPOOutputDirectory), '');
2991 XMLConfig.SetDeleteValue(Path+'i18n/EnableI18NForLFM/Value', EnableI18NForLFM, false);
2992
2993 SavePkgDependencyList(XMLConfig,Path+'RequiredPkgs/',
2994 FFirstRequiredDependency,pddRequires,UsePathDelim,UseLegacyLists);
2995 FUsageOptions.SaveToXMLConfig(XMLConfig,Path+'UsageOptions/',UsePathDelim);
2996 fPublishOptions.SaveToXMLConfig(XMLConfig,Path+'PublishOptions/',UsePathDelim);
2997 SaveStringList(XMLConfig,FProvides,Path+'Provides/');
2998 Config:=TXMLOptionsStorage.Create(XMLConfig);
2999 try
3000 TConfigMemStorage(CustomOptions).SaveToConfig(Config,Path+'CustomOptions/');
3001 finally
3002 Config.Free;
3003 end;
3004 Modified:=false;
3005 end;
3006
3007 procedure TLazPackage.SaveToString(out s: string);
3008 var
3009 XMLConfig: TXMLConfig;
3010 ms: TMemoryStream;
3011 begin
3012 s:='';
3013 XMLConfig:=TXMLConfig.Create(nil);
3014 ms:=TMemoryStream.Create;
3015 try
3016 XMLConfig.Clear;
3017 SaveToXMLConfig(XMLConfig,'Package/');
3018 XMLConfig.WriteToStream(ms);
3019 ms.Position:=0;
3020 SetLength(s,ms.Size);
3021 if s<>'' then
3022 ms.Read(s[1],length(s));
3023 finally
3024 XMLConfig.Free;
3025 ms.Free;
3026 end;
3027 end;
3028
IsVirtualnull3029 function TLazPackage.IsVirtual: boolean;
3030 begin
3031 Result:=not FilenameIsAbsolute(Filename);
3032 end;
3033
HasDirectorynull3034 function TLazPackage.HasDirectory: boolean;
3035 begin
3036 Result:=FHasDirectory;
3037 end;
3038
HasStaticDirectorynull3039 function TLazPackage.HasStaticDirectory: boolean;
3040 begin
3041 Result:=FHasStaticDirectory;
3042 end;
3043
GetFullFilenamenull3044 function TLazPackage.GetFullFilename(ResolveMacros: boolean): string;
3045 begin
3046 Result:=FFilename;
3047 if ResolveMacros then
3048 GlobalMacroList.SubstituteStr(Result);
3049 end;
3050
3051 procedure TLazPackage.CheckInnerDependencies;
3052 begin
3053 // ToDo: make some checks like deactivating double requirements
3054 end;
3055
IsMakingSensenull3056 function TLazPackage.IsMakingSense: boolean;
3057 begin
3058 Result:=IsValidPkgName(Name);
3059 end;
3060
3061 procedure TLazPackage.ShortenFilename(var ExpandedFilename: string; UseUp: boolean);
3062 var
3063 PkgDir: String;
3064 CurPath: String;
3065 begin
3066 if (not HasDirectory) then exit;
3067 PkgDir:=DirectoryExpanded;
3068 if HasStaticDirectory and UseUp then
3069 ExpandedFilename:=CreateRelativePath(ExpandedFilename,PkgDir)
3070 else begin
3071 CurPath:=copy(ExtractFilePath(ExpandedFilename),1,length(PkgDir));
3072 if CompareFilenames(PkgDir,CurPath)=0 then begin
3073 ExpandedFilename:=copy(ExpandedFilename,length(CurPath)+1,
3074 length(ExpandedFilename)-length(CurPath));
3075 end;
3076 end;
3077 end;
3078
3079 procedure TLazPackage.LongenFilename(var AFilename: string);
3080 begin
3081 if not HasDirectory then exit;
3082 if not FilenameIsAbsolute(AFilename) then
3083 AFilename:=TrimFilename(DirectoryExpanded+AFilename);
3084 end;
3085
GetResolvedFilenamenull3086 function TLazPackage.GetResolvedFilename(ResolveMacros: boolean): string;
3087 begin
3088 Result:=GetPhysicalFilenameCached(GetFullFilename(ResolveMacros),false);
3089 end;
3090
GetSourceDirsnull3091 function TLazPackage.GetSourceDirs(WithPkgDir, WithoutOutputDir: boolean): string;
3092 begin
3093 Result:=SourceDirectories.CreateSearchPathFromAllFiles;
3094 if WithPkgDir then
3095 Result:=MergeSearchPaths(Result,Directory);
3096 if WithoutOutputDir then
3097 Result:=RemoveSearchPaths(Result,GetOutputDirectory);
3098 end;
3099
3100 procedure TLazPackage.IterateComponentClasses(Event: TIterateComponentClassesEvent;
3101 WithUsedPackages: boolean);
3102 var
3103 Cnt: Integer;
3104 i: Integer;
3105 Dependency: TPkgDependency;
3106 begin
3107 // iterate through components in this package
3108 Cnt:=ComponentCount;
3109 for i:=0 to Cnt-1 do Event(Components[i]);
3110 // iterate through all used/required packages
3111 if WithUsedPackages then begin
3112 Dependency:=FirstRequiredDependency;
3113 while Dependency<>nil do begin
3114 if Dependency.RequiredPackage<>nil then
3115 Dependency.RequiredPackage.IterateComponentClasses(Event,false);
3116 Dependency:=Dependency.NextRequiresDependency;
3117 end;
3118 end;
3119 end;
3120
3121 procedure TLazPackage.SetAllComponentPriorities(const p: TComponentPriority);
3122 var
3123 i: Integer;
3124 begin
3125 //debugln(['TLazPackage.SetAllComponentPriorities ',Name,' ',dbgs(p), ' FileCount=',FileCount]);
3126 for i:=0 to FileCount-1 do
3127 Files[i].ComponentPriority:=p;
3128 end;
3129
3130 procedure TLazPackage.ConsistencyCheck;
3131 begin
3132 CheckList(FRemovedFiles,true,true,true);
3133 CheckList(FFiles,true,true,true);
3134 CheckList(FComponents,true,true,true);
3135 end;
3136
ExtendUnitSearchPathnull3137 function TLazPackage.ExtendUnitSearchPath(NewUnitPaths: string): boolean;
3138 var
3139 CurUnitPaths: String;
3140 r: TModalResult;
3141 begin
3142 Result:=True;
3143 CurUnitPaths:=CompilerOptions.ParsedOpts.GetParsedValue(pcosUnitPath);
3144 NewUnitPaths:=RemoveSearchPaths(NewUnitPaths,CurUnitPaths);
3145 if NewUnitPaths='' then Exit;
3146 NewUnitPaths:=CreateRelativeSearchPath(NewUnitPaths,Directory);
3147 if NewUnitPaths='.' then Exit;
3148 r:=IDEMessageDialog(lisExtendUnitPath,
3149 Format(lisExtendUnitSearchPathOfPackageWith, [Name, #13, NewUnitPaths]),
3150 mtConfirmation, [mbYes, mbNo, mbCancel]);
3151 case r of
3152 mrYes: CompilerOptions.MergeToUnitPaths(NewUnitPaths);
3153 mrNo: ;
3154 else exit(false);
3155 end;
3156 end;
3157
ExtendIncSearchPathnull3158 function TLazPackage.ExtendIncSearchPath(NewIncPaths: string): boolean;
3159 var
3160 CurIncPaths: String;
3161 r: TModalResult;
3162 begin
3163 Result:=True;
3164 CurIncPaths:=CompilerOptions.ParsedOpts.GetParsedValue(pcosIncludePath);
3165 NewIncPaths:=RemoveSearchPaths(NewIncPaths,CurIncPaths);
3166 if NewIncPaths='' then Exit;
3167 NewIncPaths:=CreateRelativeSearchPath(NewIncPaths,Directory);
3168 if NewIncPaths='.' then Exit;
3169 r:=IDEMessageDialog(lisExtendIncludePath,
3170 Format(lisExtendIncludeFileSearchPathOfPackageWith, [Name, #13, NewIncPaths]),
3171 mtConfirmation, [mbYes, mbNo, mbCancel]);
3172 case r of
3173 mrYes: CompilerOptions.MergeToIncludePaths(NewIncPaths);
3174 mrNo: ;
3175 else exit(false);
3176 end;
3177 end;
3178
IndexOfPkgComponentnull3179 function TLazPackage.IndexOfPkgComponent(PkgComponent: TPkgComponent): integer;
3180 begin
3181 Result:=FComponents.IndexOf(PkgComponent);
3182 end;
3183
FindPkgFilenull3184 function TLazPackage.FindPkgFile(const AFilename: string; IgnoreRemoved,
3185 FindVirtualFile: boolean): TPkgFile;
3186 var
3187 TheFilename: String;
3188 Cnt: Integer;
3189 i: Integer;
3190 begin
3191 Result:=nil;
3192
3193 TheFilename:=AFilename;
3194
3195 Cnt:=FileCount;
3196 for i:=0 to Cnt-1 do begin
3197 Result:=Files[i];
3198 if (not FindVirtualFile) and (not FilenameIsAbsolute(Result.Filename)) then
3199 continue;
3200 if (CompareFilenames(Result.Filename,TheFilename)=0)
3201 or (CompareFilenames(Result.GetFullFilename,TheFilename)=0) then
3202 exit;
3203 end;
3204 if not IgnoreRemoved then begin
3205 Cnt:=RemovedFilesCount;
3206 for i:=0 to Cnt-1 do begin
3207 Result:=RemovedFiles[i];
3208 if (not FindVirtualFile) and (not FilenameIsAbsolute(Result.Filename)) then
3209 continue;
3210 if (CompareFilenames(Result.Filename,TheFilename)=0)
3211 or (CompareFilenames(Result.GetFullFilename,TheFilename)=0) then
3212 exit;
3213 end;
3214 end;
3215 Result:=nil;
3216 end;
3217
FindUnitWithRegisternull3218 function TLazPackage.FindUnitWithRegister(IgnorePkgFile: TPkgFile): TPkgFile;
3219 var
3220 Cnt: LongInt;
3221 i: Integer;
3222 begin
3223 Cnt:=FileCount;
3224 for i:=0 to Cnt-1 do begin
3225 Result:=Files[i];
3226 if IgnorePkgFile=Result then continue;
3227 if not (Result.FileType in PkgFileRealUnitTypes) then continue;
3228 if Result.HasRegisterProc then exit;
3229 end;
3230 Result:=nil;
3231 end;
3232
FindUnitnull3233 function TLazPackage.FindUnit(const TheUnitName: string): TPkgFile;
3234 begin
3235 Result:=FindUnit(TheUnitName,true);
3236 end;
3237
FindUnitnull3238 function TLazPackage.FindUnit(const TheUnitName: string;
3239 IgnoreRemoved: boolean): TPkgFile;
3240 begin
3241 Result:=FindUnit(TheUnitName,IgnoreRemoved,nil);
3242 end;
3243
FindUnitnull3244 function TLazPackage.FindUnit(const TheUnitName: string;
3245 IgnoreRemoved: boolean; IgnorePkgFile: TPkgFile): TPkgFile;
3246 var
3247 Cnt: Integer;
3248 i: Integer;
3249 begin
3250 if TheUnitName='' then exit(nil);
3251 Cnt:=FileCount;
3252 for i:=0 to Cnt-1 do begin
3253 Result:=Files[i];
3254 if IgnorePkgFile=Result then continue;
3255 if SysUtils.CompareText(Result.Unit_Name,TheUnitName)=0 then exit;
3256 end;
3257 if not IgnoreRemoved then begin
3258 Cnt:=RemovedFilesCount;
3259 for i:=0 to Cnt-1 do begin
3260 Result:=RemovedFiles[i];
3261 if IgnorePkgFile=Result then continue;
3262 if SysUtils.CompareText(Result.Unit_Name,TheUnitName)=0 then exit;
3263 end;
3264 end;
3265 Result:=nil;
3266 end;
3267
FindUsedUnitnull3268 function TLazPackage.FindUsedUnit(TheUnitName: string; IgnorePkgFile: TPkgFile
3269 ): TPkgFile;
3270 var
3271 i: Integer;
3272 begin
3273 for i:=0 to FileCount-1 do begin
3274 Result:=Files[i];
3275 if IgnorePkgFile=Result then continue;
3276 if not Result.AddToUsesPkgSection then continue;
3277 if not (Result.FileType in PkgFileRealUnitTypes) then continue;
3278 if SysUtils.CompareText(Result.Unit_Name,TheUnitName)=0 then exit;
3279 end;
3280 Result:=nil;
3281 end;
3282
FindRemovedPkgFilenull3283 function TLazPackage.FindRemovedPkgFile(const AFilename: string): TPkgFile;
3284 var
3285 Cnt: Integer;
3286 i: Integer;
3287 begin
3288 Cnt:=RemovedFilesCount;
3289 for i:=0 to Cnt-1 do begin
3290 Result:=RemovedFiles[i];
3291 if CompareFilenames(Result.Filename,AFilename)=0 then exit;
3292 end;
3293 Result:=nil;
3294 end;
3295
FindDependencyByNamenull3296 function TLazPackage.FindDependencyByName(const PackageName: string): TPkgDependency;
3297 begin
3298 Result:=FindDependencyByNameInList(FFirstRequiredDependency,pddRequires,PackageName);
3299 end;
3300
FindRemovedDependencyByNamenull3301 function TLazPackage.FindRemovedDependencyByName(const PkgName: string): TPkgDependency;
3302 begin
3303 Result:=FindDependencyByNameInList(FFirstRemovedDependency,pddRequires,PkgName);
3304 end;
3305
RequiredDepByIndexnull3306 function TLazPackage.RequiredDepByIndex(Index: integer): TPkgDependency;
3307 begin
3308 Result:=GetDependencyWithIndex(FFirstRequiredDependency,pddRequires,Index);
3309 end;
3310
RemovedDepByIndexnull3311 function TLazPackage.RemovedDepByIndex(Index: integer): TPkgDependency;
3312 begin
3313 Result:=GetDependencyWithIndex(FFirstRemovedDependency,pddRequires,Index);
3314 end;
3315
UsedByDepByIndexnull3316 function TLazPackage.UsedByDepByIndex(Index: integer): TPkgDependency;
3317 begin
3318 Result:=GetDependencyWithIndex(FFirstUsedByDependency,pddUsedBy,Index);
3319 end;
3320
FindUsedByDepPrefernull3321 function TLazPackage.FindUsedByDepPrefer(Ignore: TPkgDependency): TPkgDependency;
3322 begin
3323 Result:=FFirstUsedByDependency;
3324 while (Result<>nil) do begin
3325 if Result.PreferDefaultFilename
3326 and (Result<>Ignore) then
3327 exit;
3328 Result:=Result.NextUsedByDependency;
3329 end;
3330 end;
3331
ProvidesPackagenull3332 function TLazPackage.ProvidesPackage(const AName: string): boolean;
3333 var
3334 i: Integer;
3335 begin
3336 if AName='' then exit(false);
3337 for i:=0 to Provides.Count-1 do
3338 if SysUtils.CompareText(Provides[i],AName)=0 then begin
3339 //DebugLn(['TLazPackage.ProvidesPackage AName=',AName,' Provides[i]="',Provides[i],'"']);
3340 exit(true);
3341 end;
3342 Result:=false;
3343 end;
3344
AddFilenull3345 function TLazPackage.AddFile(const NewFilename, NewUnitName: string;
3346 NewFileType: TPkgFileType; NewFlags: TPkgFileFlags;
3347 CompPriorityCat: TComponentPriorityCategory): TPkgFile;
3348 var
3349 NewComponentPriority: TComponentPriority;
3350 begin
3351 Result:=FindRemovedPkgFile(NewFilename);
3352 if Result=nil then begin
3353 Result:=TPkgFile.Create(Self);
3354 end else begin
3355 Result.AutoReferenceSourceDir:=false;
3356 FRemovedFiles.Remove(Result);
3357 Result.Removed:=false;
3358 end;
3359 with Result do begin
3360 Filename:=NewFilename;
3361 //debugln(['TLazPackage.AddFile Is=',Filename,' Should=',NewFilename]);
3362 Unit_Name:=NewUnitName;
3363 FileType:=NewFileType;
3364 Flags:=NewFlags;
3365 NewComponentPriority:=ComponentPriorityNormal;
3366 NewComponentPriority.Category:=CompPriorityCat;
3367 ComponentPriority:=NewComponentPriority;
3368 Removed:=false;
3369 AutoReferenceSourceDir:=true;
3370 end;
3371 FFiles.Add(Result);
3372 //debugln(['TLazPackage.AddFile Is=',Result.Filename,' Should=',NewFilename]);
3373 Modified:=true;
3374 end;
3375
AddFileByNamenull3376 function TLazPackage.AddFileByName(aFilename: string;
3377 var NewUnitPaths, NewIncPaths: String): Boolean;
3378 var
3379 NewFileType: TPkgFileType;
3380 NewUnitName: String;
3381 NewFlags: TPkgFileFlags;
3382 Code: TCodeBuffer;
3383 CurDir: String;
3384 begin
3385 Result := True;
3386 aFilename:=CleanAndExpandFilename(aFileName);
3387 if not FileExistsUTF8(aFilename) then Exit(False);
3388 if DirPathExists(aFilename) then Exit(False);
3389 if FindPkgFile(aFilename,true,false)<>nil then Exit(False);
3390 NewFileType:=FileNameToPkgFileType(aFilename);
3391 NewFlags:=[];
3392 NewUnitName:='';
3393 if (NewFileType=pftUnit) then begin
3394 Code:=CodeToolBoss.LoadFile(aFilename,true,false);
3395 NewUnitName:=CodeToolBoss.GetSourceName(Code,false);
3396 Assert(NewUnitName<>'', 'TLazPackage.AddFileByName: NewUnitName is empty.');
3397 //if NewUnitName='' then NewUnitName:=ExtractFileNameOnly(aFilename);
3398 if FindUsedUnit(NewUnitName)=nil then
3399 Include(NewFlags,pffAddToPkgUsesSection);
3400 if CodeToolBoss.HasInterfaceRegisterProc(Code) then
3401 Include(NewFlags,pffHasRegisterProc);
3402 end;
3403 AddFile(aFilename,NewUnitName,NewFileType,NewFlags,cpNormal);
3404 CurDir:=ChompPathDelim(ExtractFilePath(aFilename));
3405 if NewFileType=pftUnit then
3406 NewUnitPaths:=MergeSearchPaths(NewUnitPaths,CurDir)
3407 else
3408 NewIncPaths:=MergeSearchPaths(NewIncPaths,CurDir);
3409 end;
3410
AddRemovedFilenull3411 function TLazPackage.AddRemovedFile(const NewFilename, NewUnitName: string;
3412 NewFileType: TPkgFileType; NewFlags: TPkgFileFlags;
3413 CompPriorityCat: TComponentPriorityCategory): TPkgFile;
3414 var
3415 NewComponentPriority: TComponentPriority;
3416 begin
3417 Result:=FindRemovedPkgFile(NewFilename);
3418 if Result=nil then begin
3419 Result:=TPkgFile.Create(Self);
3420 end;
3421 with Result do begin
3422 AutoReferenceSourceDir:=false;
3423 Filename:=NewFilename;
3424 Unit_Name:=NewUnitName;
3425 FileType:=NewFileType;
3426 Flags:=NewFlags;
3427 NewComponentPriority:=ComponentPriorityNormal;
3428 NewComponentPriority.Category:=CompPriorityCat;
3429 ComponentPriority:=NewComponentPriority;
3430 Removed:=false;
3431 AutoReferenceSourceDir:=true;
3432 end;
3433 FRemovedFiles.Add(Result);
3434 end;
3435
3436 procedure TLazPackage.DeleteFile(PkgFile: TPkgFile);
3437 begin
3438 PkgFile.Free;
3439 Modified:=true
3440 end;
3441
3442 procedure TLazPackage.RemoveFileSilently(PkgFile: TPkgFile);
3443 // Remove a file without setting the Modified flag. Caller must take care of it.
3444 begin
3445 FFiles.Remove(PkgFile);
3446 FRemovedFiles.Add(PkgFile);
3447 PkgFile.Removed:=true;
3448 end;
3449
3450 procedure TLazPackage.RemoveFile(PkgFile: TPkgFile);
3451 begin
3452 RemoveFileSilently(PkgFile);
3453 Modified:=true;
3454 end;
3455
3456 procedure TLazPackage.UnremovePkgFile(PkgFile: TPkgFile);
3457 begin
3458 FFiles.Add(PkgFile);
3459 FRemovedFiles.Remove(PkgFile);
3460 PkgFile.Removed:=false;
3461 end;
3462
RemoveNonExistingFilesnull3463 function TLazPackage.RemoveNonExistingFiles(RemoveFromUsesSection: boolean): boolean;
3464 // Param is ignored here, it is just to match with interface.
3465 var
3466 i: Integer;
3467 AFilename: String;
3468 begin
3469 Result:=false;
3470 i:=FileCount-1;
3471 while i>=0 do begin
3472 if i>=FileCount then continue;
3473 AFilename:=Files[i].GetResolvedFilename;
3474 if (AFilename='') or (not FileExistsCached(AFilename)) then
3475 begin
3476 RemoveFile(Files[i]);
3477 Result:=true;
3478 end;
3479 dec(i);
3480 end;
3481 end;
3482
GetFileDialogInitialDirnull3483 function TLazPackage.GetFileDialogInitialDir(const DefaultDirectory: string): string;
3484 begin
3485 Result:=AppendPathDelim(TrimFilename(DefaultDirectory));
3486 if (SourceDirectories.GetFileReference(Result)=nil)
3487 and DirPathExists(Directory) then
3488 Result:=Directory;
3489 end;
3490
3491 procedure TLazPackage.MoveFile(CurIndex, NewIndex: integer);
3492 begin
3493 if CurIndex=NewIndex then exit;
3494 FFiles.Move(CurIndex,NewIndex);
3495 Include(FFlags,lpfModified);
3496 if FChangeStamp<High(FChangeStamp) then
3497 inc(FChangeStamp)
3498 else
3499 FChangeStamp:=low(FChangeStamp);
3500 end;
3501
3502 procedure TLazPackage.SortFiles;
3503 var
3504 NewList: TFPList;
3505 Cnt: Integer;
3506 i: Integer;
3507 begin
3508 if FileCount=0 then exit;
3509 NewList:=TFPList.Create;
3510 try
3511 Cnt:=FileCount;
3512 for i:=0 to Cnt-1 do NewList.Add(FFiles[i]);
3513 NewList.Sort(TListSortCompare(@ComparePkgFilesAlphabetically));
3514 i:=Cnt-1;
3515 while (i>=0) and (NewList[i]=FFiles[i]) do dec(i);
3516 if i<0 then exit;
3517 FFiles.Clear;
3518 for i:= 0 to Cnt-1 do FFiles.Add(NewList[i]);
3519 Modified:=true;
3520 finally
3521 NewList.Free;
3522 end;
3523 end;
3524
FixFilesCaseSensitivitynull3525 function TLazPackage.FixFilesCaseSensitivity: boolean;
3526 var
3527 SrcDirs: TStringList;
3528
3529 function IndexOfFileInStringList(List: TStringList;
3530 const Filename: string; OnlyExact: boolean): integer;
3531 begin
3532 // first search for exact match
3533 Result:=List.Count-1;
3534 while (Result>=0) do begin
3535 if (Filename=List[Result]) then exit;
3536 dec(Result);
3537 end;
3538 if OnlyExact then exit;
3539 // then search for case insensitive match
3540 Result:=List.Count-1;
3541 while (Result>=0) and (SysUtils.CompareText(Filename,List[Result])<>0) do
3542 dec(Result);
3543 end;
3544
3545 function AddDirectoryListing(const ADirectory: string): TStringList;
3546 var
3547 SrcDirID: Integer;
3548 FileInfo: TSearchRec;
3549 begin
3550 if SrcDirs=nil then
3551 SrcDirs:=TStringList.Create;
3552 // search directory listing
3553 SrcDirID:=IndexOfFileInStringList(SrcDirs,ADirectory,true);
3554 if SrcDirID>=0 then begin
3555 Result:=TStringList(SrcDirs.Objects[SrcDirID]);
3556 exit;
3557 end;
3558 // create new directory listing
3559 Result:=TStringList.Create;
3560 if FindFirstUTF8(AppendPathDelim(ADirectory)+GetAllFilesMask,
3561 faAnyFile,FileInfo)=0
3562 then begin
3563 repeat
3564 // check if special file
3565 if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='')
3566 then continue;
3567 Result.Add(FileInfo.Name);
3568 //debugln('AddDirectoryListing ',FileInfo.Name);
3569 until FindNextUTF8(FileInfo)<>0;
3570 end;
3571 FindCloseUTF8(FileInfo);
3572 SrcDirs.AddObject(ADirectory,Result);
3573 end;
3574
3575 var
3576 Cnt: Integer;
3577 i: Integer;
3578 CurFile: TPkgFile;
3579 CurShortFilename: String;
3580 DirListID: LongInt;
3581 DirListing: TStringList;
3582 NewShortFilename: string;
3583 NewFilename: String;
3584 CurDir: String;
3585 AFilename: String;
3586 begin
3587 Result:=false;
3588 Cnt:=FileCount;
3589 SrcDirs:=nil;
3590 try
3591 for i:=0 to Cnt-1 do begin
3592 CurFile:=Files[i];
3593 //debugln('TLazPackage.FixFilesCaseSensitivity A ',dbgs(i),' CurFile.Filename=',CurFile.Filename);
3594 AFilename:=CurFile.GetFullFilename;
3595 CurShortFilename:=ExtractFilename(AFilename);
3596 CurDir:=ExtractFilePath(AFilename);
3597 DirListing:=AddDirectoryListing(CurDir);
3598 DirListID:=IndexOfFileInStringList(DirListing,CurShortFilename,false);
3599 //debugln('TLazPackage.FixFilesCaseSensitivity B ',dbgs(i),' CurShortFilename=',CurShortFilename,' DirListID=',dbgs(DirListID));
3600 if DirListID<0 then continue;
3601 NewShortFilename:=DirListing[DirListID];
3602 //debugln('TLazPackage.FixFilesCaseSensitivity New ',dbgs(i),' NewShortFilename=',NewShortFilename);
3603 if CurShortFilename<>NewShortFilename then begin
3604 // case changes
3605 NewFilename:=AppendPathDelim(ExtractFilePath(CurFile.Filename))+NewShortFilename;
3606 //debugln('TLazPackage.FixFilesCaseSensitivity New ',dbgs(i),' NewFilename=',NewFilename);
3607 CurFile.Filename:=NewFilename;
3608 Result:=true;
3609 end;
3610 end;
3611 if Result then
3612 Modified:=true;
3613 finally
3614 if SrcDirs<>nil then begin
3615 for i:=0 to SrcDirs.Count-1 do
3616 SrcDirs.Objects[i].Free;
3617 SrcDirs.Free;
3618 end;
3619 end;
3620 end;
3621
MainUnitHasPkgNamenull3622 function TLazPackage.MainUnitHasPkgName: boolean;
3623 begin
3624 Result:=(MainUnit=nil) or (SysUtils.CompareText(MainUnit.Unit_Name,Name)=0);
3625 end;
3626
3627 procedure TLazPackage.RemoveRemovedDependency(Dependency: TPkgDependency);
3628 begin
3629 Dependency.RemoveFromList(FFirstRemovedDependency,pddRequires);
3630 Dependency.Removed:=false;
3631 end;
3632
3633 procedure TLazPackage.AddRequiredDependency(Dependency: TPkgDependency);
3634 begin
3635 Dependency.AddToList(FFirstRequiredDependency,pddRequires);
3636 Dependency.Owner:=Self;
3637 Modified:=true;
3638 end;
3639
3640 procedure TLazPackage.AddPackageDependency(const PackageName: string);
3641 var
3642 Dependency: TPkgDependency;
3643 begin
3644 if FindDependencyByName(PackageName)<>nil then exit;
3645 Dependency:=TPkgDependency.Create;
3646 Dependency.PackageName:=PackageName;
3647 AddRequiredDependency(Dependency);
3648 end;
3649
3650 procedure TLazPackage.RemoveRequiredDepSilently(Dependency: TPkgDependency);
3651 // Remove a dependency without setting the Modified flag. Caller must take care of it.
3652 begin
3653 Dependency.RemoveFromList(FFirstRequiredDependency,pddRequires);
3654 Dependency.RequiredPackage:=nil;
3655 Dependency.AddToList(FFirstRemovedDependency,pddRequires);
3656 Dependency.Removed:=true;
3657 end;
3658
3659 procedure TLazPackage.RemoveRequiredDependency(Dependency: TPkgDependency);
3660 begin
3661 RemoveRequiredDepSilently(Dependency);
3662 Modified:=true;
3663 end;
3664
3665 procedure TLazPackage.DeleteRequiredDependency(Dependency: TPkgDependency);
3666 begin
3667 Dependency.RequiredPackage:=nil;
3668 Dependency.RemoveFromList(FFirstRequiredDependency,pddRequires);
3669 Dependency.Free;
3670 end;
3671
3672 procedure TLazPackage.DeleteRemovedDependency(Dependency: TPkgDependency);
3673 begin
3674 Dependency.RequiredPackage:=nil;
3675 Dependency.RemoveFromList(FFirstRemovedDependency,pddRequires);
3676 Dependency.Free;
3677 end;
3678
MoveRequiredDependencyUpnull3679 function TLazPackage.MoveRequiredDependencyUp(Dependency: TPkgDependency): Boolean;
3680 begin
3681 Result := Dependency.MoveUpInList(FFirstRequiredDependency,pddRequires);
3682 end;
3683
MoveRequiredDependencyDownnull3684 function TLazPackage.MoveRequiredDependencyDown(Dependency: TPkgDependency): Boolean;
3685 begin
3686 Result := Dependency.MoveDownInList(FFirstRequiredDependency,pddRequires);
3687 end;
3688
CreateDependencyWithOwnernull3689 function TLazPackage.CreateDependencyWithOwner(NewOwner: TObject;
3690 WithMinVersion: boolean): TPkgDependency;
3691 begin
3692 Result:=TPkgDependency.Create;
3693 with Result do begin
3694 Owner:=NewOwner;
3695 PackageName:=Self.Name;
3696 if WithMinVersion then begin
3697 MinVersion.Assign(Version);
3698 Flags:=[pdfMinVersion];
3699 end;
3700 end;
3701 end;
3702
AddComponentnull3703 function TLazPackage.AddComponent(PkgFile: TPkgFile; const Page: string;
3704 TheComponentClass: TComponentClass): TPkgComponent;
3705 begin
3706 Result:=TPkgComponent.Create(PkgFile,TheComponentClass,Page);
3707 end;
3708
3709 procedure TLazPackage.AddPkgComponent(APkgComponent: TPkgComponent);
3710 begin
3711 FComponents.Add(APkgComponent);
3712 end;
3713
3714 procedure TLazPackage.RemovePkgComponent(APkgComponent: TPkgComponent);
3715 begin
3716 FComponents.Remove(APkgComponent);
3717 end;
3718
Requiresnull3719 function TLazPackage.Requires(APackage: TLazPackage): boolean;
3720 begin
3721 Result:=FindCompatibleDependencyInList(FFirstRequiredDependency,pddRequires,
3722 APackage)<>nil;
3723 end;
3724
3725 procedure TLazPackage.AddUsedByDependency(Dependency: TPkgDependencyBase);
3726 begin
3727 Dependency.AddUsedByDep(TPkgDependencyBase(FFirstUsedByDependency));
3728 if TPkgDependency(Dependency).HoldPackage then
3729 inc(FHoldPackageCount);
3730 end;
3731
3732 procedure TLazPackage.RemoveUsedByDependency(Dependency: TPkgDependencyBase);
3733 begin
3734 Dependency.RemoveUsedByDep(TPkgDependencyBase(FFirstUsedByDependency));
3735 if TPkgDependency(Dependency).HoldPackage then
3736 dec(FHoldPackageCount);
3737 end;
3738
3739 procedure TLazPackage.ChangeID(const NewName: string; NewVersion: TPkgVersion);
3740 begin
3741 Version.Assign(NewVersion);
3742 Name:=NewName;
3743 end;
3744
GetFPDocPackageNamenull3745 function TLazPackage.GetFPDocPackageName: string;
3746 begin
3747 if FPDocPackageName<>'' then
3748 Result:=FPDocPackageName
3749 else
3750 Result:=Name;
3751 end;
3752
GetOutputDirTypenull3753 function TLazPackage.GetOutputDirType: TPkgOutputDir;
3754 begin
3755 if (CompilerOptions<>nil)
3756 and (CompilerOptions.ParsedOpts<>nil)
3757 and (CompilerOptions.ParsedOpts.OutputDirectoryOverride<>'') then
3758 Result:=podFallback
3759 else
3760 Result:=podDefault;
3761 end;
3762
3763 procedure TLazPackage.GetAllRequiredPackages(var List, FPMakeList: TFPList;
3764 WithSelf: boolean; aFlags: TPkgIntfRequiredFlags;
3765 MinPolicy: TPackageUpdatePolicy);
3766 begin
3767 if Assigned(OnGetAllRequiredPackages) then
3768 OnGetAllRequiredPackages(Self,FirstRequiredDependency,List,FPMakeList,aFlags,MinPolicy);
3769 if WithSelf then begin
3770 if List=nil then List:=TFPList.Create;
3771 if List.IndexOf(Self)<0 then
3772 List.Insert(0,Self);
3773 end else if List<>nil then begin
3774 List.Remove(Self);
3775 if List.Count=0 then FreeAndNil(List);
3776 end;
3777 end;
3778
3779 procedure TLazPackage.GetInheritedCompilerOptions(var OptionsList: TFPList);
3780 var
3781 PkgList: TFPList; // list of TLazPackage
3782 FPMakeList: TFPList;
3783 begin
3784 PkgList:=nil;
3785 FPMakeList:=nil;
3786 GetAllRequiredPackages(PkgList,FPMakeList,false,[pirCompileOrder]);
3787 OptionsList:=GetUsageOptionsList(PkgList);
3788 PkgList.Free;
3789 FPMakeList.Free;
3790 end;
3791
GetCompileSourceFilenamenull3792 function TLazPackage.GetCompileSourceFilename: string;
3793 begin
3794 if MainUnit<>nil then
3795 Result:=ExtractFilename(MainUnit.GetFullFilename)
3796 else
3797 Result:=ChangeFileExt(ExtractFilename(Filename),'.pas');
3798 end;
3799
GetOutputDirectorynull3800 function TLazPackage.GetOutputDirectory(UseOverride: boolean = true): string;
3801 begin
3802 if HasDirectory then begin
3803 if GetActiveBuildMethod = bmFPMake then begin
3804 Result :=TFppkgHelper.Instance.GetPackageUnitPath(name);
3805 end else begin
3806 Result:=CompilerOptions.ParsedOpts.GetParsedValue(pcosOutputDir,UseOverride);
3807 end;
3808 end else
3809 Result:='';
3810 end;
3811
HasSeparateOutputDirectorynull3812 function TLazPackage.HasSeparateOutputDirectory: boolean;
3813 var
3814 VisitedPackages: TStringToStringTree;
3815 OutputDir: String;
3816
3817 function CheckDependency(ADependency: TPkgDependency): boolean;
3818 var
3819 aPkg: TLazPackage;
3820 Dir: String;
3821 SrcPaths: String;
3822 begin
3823 Result:=false;
3824 while ADependency<>nil do begin
3825 if ADependency.RequiredPackage<>nil then begin
3826 aPkg:=ADependency.RequiredPackage;
3827 if not VisitedPackages.Contains(aPkg.Name) then begin
3828 VisitedPackages[aPkg.Name]:='1';
3829 // check recursively
3830 if not CheckDependency(aPkg.FirstRequiredDependency) then exit;
3831 // check if required package has the same output directory
3832 Dir:=aPkg.GetOutputDirectory;
3833 if CompareFilenames(Dir,OutputDir)=0 then exit;
3834 // check if output directory is a sour directory of a required package
3835 SrcPaths:=aPkg.SourceDirectories.CreateSearchPathFromAllFiles;
3836 if (SrcPaths<>'')
3837 and (FindPathInSearchPath(PChar(OutputDir),length(OutputDir),
3838 PChar(SrcPaths),length(SrcPaths))<>nil)
3839 then exit;
3840 end;
3841 end;
3842 ADependency:=ADependency.NextRequiresDependency;
3843 end;
3844 Result:=true;
3845 end;
3846
3847 var
3848 SrcPaths: String;
3849 begin
3850 Result:=false;
3851 if CompilerOptions.UnitOutputDirectory='' then exit;
3852 OutputDir:=CompilerOptions.ParsedOpts.GetParsedValue(pcosOutputDir,false);
3853 if OutputDir='' then exit;
3854 SrcPaths:=SourceDirectories.CreateSearchPathFromAllFiles;
3855 if SrcPaths='' then exit(true);
3856 if FindPathInSearchPath(PChar(OutputDir),length(OutputDir),PChar(SrcPaths),length(SrcPaths))<>nil
3857 then exit;
3858 // check used packages
3859 VisitedPackages:=TStringToStringTree.Create(false);
3860 try
3861 if not CheckDependency(FirstRequiredDependency) then exit;
3862 finally
3863 VisitedPackages.Free;
3864 end;
3865 Result:=true;
3866 end;
3867
GetStateFilenamenull3868 function TLazPackage.GetStateFilename(UseOverride: boolean): string;
3869 begin
3870 Result:=AppendPathDelim(GetOutputDirectory(UseOverride))+Name+'.compiled';
3871 end;
3872
GetSrcFilenamenull3873 function TLazPackage.GetSrcFilename: string;
3874 begin
3875 if MainUnit<>nil then
3876 Result:=MainUnit.GetFullFilename
3877 else
3878 Result:=FDirectory+GetCompileSourceFilename;
3879 end;
3880
GetSrcPPUFilenamenull3881 function TLazPackage.GetSrcPPUFilename: string;
3882 begin
3883 Result:=AppendPathDelim(GetOutputDirectory)
3884 +ChangeFileExt(GetCompileSourceFilename,'.ppu');
3885 end;
3886
GetCompilerFilenamenull3887 function TLazPackage.GetCompilerFilename: string;
3888 begin
3889 Result:=CompilerOptions.ParsedOpts.GetParsedValue(pcosCompilerPath);
3890 end;
3891
GetPOOutDirectorynull3892 function TLazPackage.GetPOOutDirectory: string;
3893 begin
3894 Result:=TrimFilename(SubstitutePkgMacros(fPOOutputDirectory,false));
3895 LongenFilename(Result);
3896 IDEMacros.SubstituteMacros(Result);
3897 Result:=TrimFilename(Result);
3898 end;
3899
GetUnitPathnull3900 function TLazPackage.GetUnitPath(RelativeToBaseDir: boolean): string;
3901 begin
3902 Result:=CompilerOptions.GetUnitPath(RelativeToBaseDir);
3903 end;
3904
GetUseLegacyListsnull3905 function TLazPackage.GetUseLegacyLists: Boolean;
3906 begin
3907 Result:=lpfCompatibilityMode in Flags;
3908 end;
3909
GetIncludePathnull3910 function TLazPackage.GetIncludePath(RelativeToBaseDir: boolean): string;
3911 begin
3912 Result:=CompilerOptions.GetIncludePath(RelativeToBaseDir);
3913 end;
3914
GetSrcPathnull3915 function TLazPackage.GetSrcPath(RelativeToBaseDir: boolean): string;
3916 begin
3917 Result:=CompilerOptions.GetSrcPath(RelativeToBaseDir);
3918 end;
3919
GetLastCompilerParamsnull3920 function TLazPackage.GetLastCompilerParams(o: TPkgOutputDir): string;
3921 begin
3922 Result:=LastCompile[o].Params;
3923 if LastCompile[o].ViaMakefile then begin
3924 Result:=StringReplace(Result,'$(CPU_TARGET)','$(TargetCPU)',[rfReplaceAll]);
3925 Result:=StringReplace(Result,'$(OS_TARGET)','$(TargetOS)',[rfReplaceAll]);
3926 Result:=StringReplace(Result,'$(LCL_PLATFORM)','$(LCLWidgetType)',[rfReplaceAll]);
3927 Result:=SubstitutePkgMacros(Result,false);
3928 end;
3929 end;
3930
NeedsDefineTemplatesnull3931 function TLazPackage.NeedsDefineTemplates: boolean;
3932 begin
3933 if IsVirtual or (lpfDestroying in Flags) or (Name='') then
3934 Result:=false
3935 else
3936 Result:=true;
3937 end;
3938
IndexOfPkgFilenull3939 function TLazPackage.IndexOfPkgFile(PkgFile: TPkgFile): integer;
3940 begin
3941 Result := FileCount - 1;
3942 if Result < 0 then
3943 Exit;
3944 while (Files[Result] <> PkgFile) do
3945 begin
3946 dec(Result);
3947 if Result < 0 then
3948 Exit;
3949 end;
3950 end;
3951
SearchShortFilenamenull3952 function TLazPackage.SearchShortFilename(const ShortFilename: string;
3953 SearchFlags: TSearchIDEFileFlags): TPkgFile;
3954 var
3955 SearchedFilename: String;
3956 i: Integer;
3957
3958 function FilenameFits(TheFilename: string): boolean;
3959 begin
3960 if siffIgnoreExtension in SearchFlags then
3961 TheFileName:=ExtractFileNameWithoutExt(TheFileName);
3962 //debugln('TLazPackage.SearchFile A ',SearchedFilename,' ',TheFilename);
3963 if siffCaseSensitive in SearchFlags then
3964 Result:=SearchedFilename=TheFilename
3965 else
3966 Result:=SysUtils.CompareText(SearchedFilename,TheFilename)=0;
3967 end;
3968
3969 begin
3970 SearchedFilename:=ShortFilename;
3971 if siffIgnoreExtension in SearchFlags then
3972 SearchedFilename:=ExtractFileNameWithoutExt(SearchedFilename);
3973
3974 // search in files
3975 for i:=0 to FileCount-1 do begin
3976 Result:=Files[i];
3977 if FilenameFits(Result.GetShortFilename(true)) then exit;
3978 end;
3979 Result:=nil;
3980 end;
3981
SearchFilenamenull3982 function TLazPackage.SearchFilename(const AFilename: string;
3983 SearchFlags: TSearchIDEFileFlags): TPkgFile;
3984 var
3985 SearchedFilename: String;
3986 i: Integer;
3987
3988 function FilenameFits(TheFilename: string): boolean;
3989 begin
3990 if siffIgnoreExtension in SearchFlags then
3991 TheFileName:=ExtractFileNameWithoutExt(TheFileName);
3992 //debugln('TLazPackage.SearchFile A ',SearchedFilename,' ',TheFilename);
3993 if siffCaseSensitive in SearchFlags then
3994 Result:=SearchedFilename=TheFilename
3995 else
3996 Result:=SysUtils.CompareText(SearchedFilename,TheFilename)=0;
3997 end;
3998
3999 begin
4000 SearchedFilename:=AFilename;
4001 if siffIgnoreExtension in SearchFlags then
4002 SearchedFilename:=ExtractFileNameWithoutExt(SearchedFilename);
4003
4004 // search in files
4005 for i:=0 to FileCount-1 do begin
4006 Result:=Files[i];
4007 if FilenameFits(Result.GetFullFilename) then exit;
4008 end;
4009 Result:=nil;
4010 end;
4011
4012 { TPkgComponent }
4013
4014 procedure TPkgComponent.SetPkgFile(const AValue: TPkgFile);
4015 begin
4016 if FPkgFile=AValue then exit;
4017 if (FPkgFile<>nil) then PkgFile.RemovePkgComponent(Self);
4018 FPkgFile:=AValue;
4019 if (FPkgFile<>nil) then PkgFile.AddPkgComponent(Self);
4020 end;
4021
4022 constructor TPkgComponent.Create(ThePkgFile: TPkgFile;
4023 TheComponentClass: TComponentClass; const ThePageName: string);
4024 begin
4025 inherited Create(TheComponentClass,ThePageName);
4026 PkgFile:=ThePkgFile;
4027 end;
4028
4029 destructor TPkgComponent.Destroy;
4030 begin
4031 PkgFile:=nil;
4032 inherited Destroy;
4033 end;
4034
GetUnitNamenull4035 function TPkgComponent.GetUnitName: string;
4036 var
4037 TIUnitName: String;
4038 begin
4039 Result:=PkgFile.Unit_Name;
4040 // compare with RTTI unit name
4041 if ComponentClass<>nil then begin
4042 TIUnitName:=ComponentClass.UnitName;
4043 if SysUtils.CompareText(TIUnitName,Result)<>0 then
4044 Result:=TIUnitName;
4045 end;
4046 end;
4047
GetPrioritynull4048 function TPkgComponent.GetPriority: TComponentPriority;
4049 begin
4050 Result:=PkgFile.ComponentPriority;
4051 end;
4052
4053 procedure TPkgComponent.ConsistencyCheck;
4054 begin
4055 inherited ConsistencyCheck;
4056 if FPkgFile=nil then
4057 RaiseGDBException('TIDEComponent.ConsistencyCheck FPkgFile=nil');
4058 if FPkgFile.LazPackage=nil then
4059 RaiseGDBException('TIDEComponent.ConsistencyCheck FPkgFile.LazPackage=nil');
4060 if FPkgFile.LazPackage.IndexOfPkgComponent(Self)<0 then
4061 RaiseGDBException('TIDEComponent.ConsistencyCheck FPkgFile.LazPackage.IndexOfPkgComponent(Self)<0');
4062 if PkgFile.FComponents=nil then
4063 RaiseGDBException('TIDEComponent.ConsistencyCheck PkgFile.FComponents=nil');
4064 if PkgFile.FComponents.IndexOf(Self)<0 then
4065 RaiseGDBException('TIDEComponent.ConsistencyCheck PkgFile.FComponents.IndexOf(Self)<0');
4066 end;
4067
4068 class function TPkgComponent.Images: TCustomImageList;
4069 begin
4070 Result := IDEImages.Images_24;
4071 end;
4072
HasIconnull4073 function TPkgComponent.HasIcon: boolean;
4074 begin
4075 Result:=RealPage.PageName<>'';
4076 end;
4077
ImageIndexnull4078 function TPkgComponent.ImageIndex: TImageIndex;
4079 begin
4080 Result := IDEImages.GetImageIndex(ComponentClass.ClassName, 24);
4081 if Result=-1 then
4082 Result := IDEImages.GetImageIndex('default', 24);
4083 end;
4084
CanBeCreatedInDesignernull4085 function TPkgComponent.CanBeCreatedInDesigner: boolean;
4086 begin
4087 Result:=(not PkgFile.Removed);
4088 end;
4089
4090 { TPkgCompilerOptions }
4091
4092 procedure TPkgCompilerOptions.LoadFromXMLConfig(AXMLConfig: TXMLConfig;
4093 const Path: string);
4094 begin
4095 inherited LoadFromXMLConfig(AXMLConfig,Path);
4096
4097 FSkipCompiler := AXMLConfig.GetValue(Path+'SkipCompiler/Value', False);
4098 end;
4099
4100 procedure TPkgCompilerOptions.SaveToXMLConfig(AXMLConfig: TXMLConfig; const Path: string);
4101 begin
4102 inherited SaveToXMLConfig(AXMLConfig,Path);
4103
4104 AXMLConfig.SetDeleteValue(Path+'SkipCompiler/Value', FSkipCompiler, False);
4105 end;
4106
4107 procedure TPkgCompilerOptions.SetLazPackage(const AValue: TLazPackage);
4108 begin
4109 if FLazPackage=AValue then exit;
4110 FLazPackage:=AValue;
4111 end;
4112
4113 procedure TPkgCompilerOptions.SetCustomOptions(const AValue: string);
4114 begin
4115 if CustomOptions=AValue then exit;
4116 InvalidateOptions;
4117 inherited SetCustomOptions(AValue);
4118 if LazPackage<>nil then
4119 LazPackage.DefineTemplates.CustomDefinesChanged;
4120 end;
4121
4122 procedure TPkgCompilerOptions.SetIncludePaths(const AValue: string);
4123 begin
4124 if IncludePath=AValue then exit;
4125 InvalidateOptions;
4126 inherited SetIncludePaths(AValue);
4127 end;
4128
4129 procedure TPkgCompilerOptions.SetLibraryPaths(const AValue: string);
4130 begin
4131 if Libraries=AValue then exit;
4132 InvalidateOptions;
4133 inherited SetLibraryPaths(AValue);
4134 end;
4135
4136 procedure TPkgCompilerOptions.SetLinkerOptions(const AValue: string);
4137 begin
4138 if LinkerOptions=AValue then exit;
4139 InvalidateOptions;
4140 inherited SetLinkerOptions(AValue);
4141 end;
4142
4143 procedure TPkgCompilerOptions.SetObjectPath(const AValue: string);
4144 begin
4145 if ObjectPath=AValue then exit;
4146 InvalidateOptions;
4147 inherited SetObjectPath(AValue);
4148 end;
4149
4150 procedure TPkgCompilerOptions.SetSrcPath(const AValue: string);
4151 begin
4152 if SrcPath=AValue then exit;
4153 InvalidateOptions;
4154 inherited SetSrcPath(AValue);
4155 end;
4156
4157 procedure TPkgCompilerOptions.SetUnitPaths(const AValue: string);
4158 begin
4159 if OtherUnitFiles=AValue then exit;
4160 InvalidateOptions;
4161 inherited SetUnitPaths(AValue);
4162 end;
4163
4164 procedure TPkgCompilerOptions.SetUnitOutputDir(const AValue: string);
4165 begin
4166 if UnitOutputDirectory=AValue then exit;
4167 InvalidateOptions;
4168 inherited SetUnitOutputDir(AValue);
4169 if LazPackage<>nil then
4170 LazPackage.DefineTemplates.OutputDirectoryChanged;
4171 end;
4172
4173 procedure TPkgCompilerOptions.SetConditionals(AValue: string);
4174 begin
4175 AValue:=UTF8Trim(AValue,[]);
4176 if Conditionals=AValue then exit;
4177 InvalidateOptions;
4178 inherited SetConditionals(AValue);
4179 end;
4180
4181 constructor TPkgCompilerOptions.Create(const AOwner: TObject);
4182 begin
4183 inherited Create(AOwner);
4184 if AOwner<>nil then
4185 FLazPackage := AOwner as TLazPackage;
4186 ParsedOpts.MacroValues.ProjValuesAvailable:=true;
4187 end;
4188
4189 class function TPkgCompilerOptions.GetGroupCaption: string;
4190 begin
4191 Result := dlgCompilerOptions;
4192 end;
4193
4194 class function TPkgCompilerOptions.GetInstance: TAbstractIDEOptions;
4195 begin
4196 if Package1<>nil then
4197 Result := Package1.CompilerOptions
4198 else
4199 Result := nil;
4200 end;
4201
IsActivenull4202 function TPkgCompilerOptions.IsActive: boolean;
4203 begin
4204 Result:=(LazPackage<>nil) and (LazPackage.CompilerOptions=Self);
4205 end;
4206
4207 procedure TPkgCompilerOptions.Clear;
4208 begin
4209 inherited Clear;
4210 FSkipCompiler:=false;
4211 end;
4212
4213 procedure TPkgCompilerOptions.GetInheritedCompilerOptions(
4214 var OptionsList: TFPList);
4215 begin
4216 if LazPackage<>nil then
4217 LazPackage.GetInheritedCompilerOptions(OptionsList);
4218 end;
4219
GetOwnerNamenull4220 function TPkgCompilerOptions.GetOwnerName: string;
4221 begin
4222 if LazPackage<>nil then
4223 Result:=LazPackage.IDAsString
4224 else
4225 Result:='';
4226 end;
4227
4228 procedure TPkgCompilerOptions.InvalidateOptions;
4229 begin
4230 if (LazPackage=nil) then exit;
4231 if LazPackage.UsageOptions=nil then RaiseGDBException('');
4232 if LazPackage.UsageOptions.ParsedOpts=nil then RaiseGDBException('');
4233 LazPackage.UsageOptions.ParsedOpts.InvalidateAll;
4234 end;
4235
GetDefaultMainSourceFileNamenull4236 function TPkgCompilerOptions.GetDefaultMainSourceFileName: string;
4237 begin
4238 if LazPackage<>nil then
4239 Result:=LazPackage.GetCompileSourceFilename
4240 else
4241 Result:='';
4242 if Result='' then
4243 Result:=inherited GetDefaultMainSourceFileName;
4244 end;
4245
CreateTargetFilenamenull4246 function TPkgCompilerOptions.CreateTargetFilename: string;
4247 begin
4248 Result:='';
4249 end;
4250
HasCompilerCommandnull4251 function TPkgCompilerOptions.HasCompilerCommand: boolean;
4252 begin
4253 Result:=(not SkipCompiler) and (CompilerPath<>'');
4254 end;
4255
4256 procedure TPkgCompilerOptions.Assign(Source: TPersistent);
4257 begin
4258 inherited Assign(Source);
4259 if Source is TPkgCompilerOptions
4260 then begin
4261 FSkipCompiler := TPkgCompilerOptions(Source).FSkipCompiler;
4262 end
4263 else begin
4264 FSkipCompiler := False;
4265 end;
4266 end;
4267
CreateDiffnull4268 function TPkgCompilerOptions.CreateDiff(CompOpts: TBaseCompilerOptions;
4269 Tool: TCompilerDiffTool): boolean;
4270 begin
4271 if (CompOpts is TPkgCompilerOptions) then begin
4272 Result:=Tool.AddDiff('SkipCompiler',FSkipCompiler,
4273 TPkgCompilerOptions(CompOpts).FSkipCompiler);
4274 end else begin
4275 Result:=true;
4276 if Tool<>nil then Tool.Differ:=true;
4277 end;
4278 Result:=Result or inherited CreateDiff(CompOpts, Tool);
4279 end;
4280
4281 { TPkgAdditionalCompilerOptions }
4282
4283 procedure TPkgAdditionalCompilerOptions.SetLazPackage(const AValue: TLazPackage);
4284 begin
4285 if FLazPackage=AValue then exit;
4286 FLazPackage:=AValue;
4287 end;
4288
4289 procedure TPkgAdditionalCompilerOptions.SetCustomOptions(const AValue: string);
4290 begin
4291 if AValue=CustomOptions then exit;
4292 inherited SetCustomOptions(AValue);
4293 LazPackage.Modified:=true;
4294 end;
4295
4296 procedure TPkgAdditionalCompilerOptions.SetIncludePath(const AValue: string);
4297 begin
4298 if AValue=IncludePath then exit;
4299 inherited SetIncludePath(AValue);
4300 LazPackage.Modified:=true;
4301 end;
4302
4303 procedure TPkgAdditionalCompilerOptions.SetLibraryPath(const AValue: string);
4304 begin
4305 if AValue=LibraryPath then exit;
4306 inherited SetLibraryPath(AValue);
4307 LazPackage.Modified:=true;
4308 end;
4309
4310 procedure TPkgAdditionalCompilerOptions.SetLinkerOptions(const AValue: string);
4311 begin
4312 if AValue=LinkerOptions then exit;
4313 inherited SetLinkerOptions(AValue);
4314 LazPackage.Modified:=true;
4315 end;
4316
4317 procedure TPkgAdditionalCompilerOptions.SetObjectPath(const AValue: string);
4318 begin
4319 if AValue=ObjectPath then exit;
4320 inherited SetObjectPath(AValue);
4321 LazPackage.Modified:=true;
4322 end;
4323
4324 procedure TPkgAdditionalCompilerOptions.SetUnitPath(const AValue: string);
4325 begin
4326 if AValue=UnitPath then exit;
4327 inherited SetUnitPath(AValue);
4328 LazPackage.Modified:=true;
4329 end;
4330
4331 procedure TPkgAdditionalCompilerOptions.SetSrcPath(const AValue: string);
4332 begin
4333 if AValue=SrcPath then exit;
4334 inherited SetSrcPath(AValue);
4335 LazPackage.Modified:=true;
4336 end;
4337
4338 constructor TPkgAdditionalCompilerOptions.Create(ThePackage: TLazPackage);
4339 begin
4340 inherited Create(ThePackage);
4341 FLazPackage:=ThePackage;
4342 end;
4343
4344 procedure TPkgAdditionalCompilerOptions.AssignOptions(Source: TObject);
4345 begin
4346 inherited AssignOptions(Source);
4347 if Source is TPkgAdditionalCompilerOptions then begin
4348 //Src:=TPkgAdditionalCompilerOptions(Source);
4349 // nothing to do
4350 end;
4351 end;
4352
GetOwnerNamenull4353 function TPkgAdditionalCompilerOptions.GetOwnerName: string;
4354 begin
4355 Result:=LazPackage.IDAsString;
4356 end;
4357
GetBaseCompilerOptionsnull4358 function TPkgAdditionalCompilerOptions.GetBaseCompilerOptions: TBaseCompilerOptions;
4359 begin
4360 Result:=LazPackage.CompilerOptions;
4361 end;
4362
4363 { TLazPackageDefineTemplates }
4364
4365 constructor TLazPackageDefineTemplates.Create(AOwner: IProjPack);
4366 begin
4367 inherited Create(AOwner);
4368 Include(FFlags, ptfIsPackageTemplate);
4369 fLastSourceDirStamp:=LUInvalidChangeStamp;
4370 end;
4371
4372 destructor TLazPackageDefineTemplates.Destroy;
4373 begin
4374 inherited Destroy;
4375 end;
4376
4377 procedure TLazPackageDefineTemplates.ClearFlags;
4378 begin
4379 FFlags:=FFlags+[ptfIDChanged,ptfOutputDirChanged,ptfSourceDirsChanged,
4380 ptfCustomDefinesChanged];
4381 end;
4382
4383 procedure TLazPackageDefineTemplates.AllChanged(AActivating: boolean);
4384 begin
4385 IDChanged;
4386 if not AActivating then // Create the SrcDirIfDef for IDE add-ons
4387 UpdateSrcDirIfDef; // (Will be called from other methods during activation)
4388 SourceDirectoriesChanged;
4389 OutputDirectoryChanged;
4390 CustomDefinesChanged;
4391 end;
4392
4393 procedure TLazPackageDefineTemplates.UpdateMain;
4394 begin
4395 if (not Owner.NeedsDefineTemplates) or (not Active) then exit;
4396 // update the package block define template (the container for all other
4397 // define templates of the package)
4398 if FMain=nil then begin
4399 FMain:=CreatePackageTemplateWithID(Owner.IDAsWord);
4400 FMain.SetDefineOwner(Owner as TLazPackage,false);
4401 FMain.SetFlags([dtfAutoGenerated],[],false);
4402 end else
4403 FMain.Name:=Owner.IDAsWord;
4404 // ClearCache is here unnessary, because it is only a block
4405 end;
4406
UpdateSrcDirIfDefnull4407 function TLazPackageDefineTemplates.UpdateSrcDirIfDef: Boolean;
4408 var
4409 NewVariable: String;
4410 UnitPathDefTempl: TDefineTemplate;
4411 IncPathDefTempl: TDefineTemplate;
4412 begin
4413 // create custom options
4414 // The custom options are enclosed by an IFDEF #PkgSrcMark<PckId> template.
4415 // Each source directory defines this variable, so that the settings can be
4416 // activated for each source directory by a simple DEFINE.
4417 if (FMain=nil) then UpdateMain;
4418 if FMain=nil then exit;
4419 if FSrcDirectories=nil then begin
4420 FSrcDirectories:=TDefineTemplate.Create('Source Directories',
4421 'Source Directories','','',
4422 da_Block);
4423 FMain.AddChild(FSrcDirectories);
4424 end;
4425 Result:=false;
4426 if FSrcDirIf=nil then begin
4427 FSrcDirIf:=TDefineTemplate.Create('Source Directory Additions',
4428 'Additional defines for package source directories',
4429 '#PkgSrcMark'+Owner.IDAsWord, '', da_IfDef);
4430 FMain.AddChild(FSrcDirIf);
4431
4432 // create unit path template for this directory
4433 UnitPathDefTempl:=TDefineTemplate.Create('UnitPath', lisPkgDefsUnitPath,
4434 '#UnitPath','$(#UnitPath);$PkgUnitPath('+Owner.IDAsString+')',
4435 da_Define);
4436 FSrcDirIf.AddChild(UnitPathDefTempl);
4437 // create include path template for this directory
4438 IncPathDefTempl:=TDefineTemplate.Create('IncPath','Include Path',
4439 '#IncPath','$(#IncPath);$PkgIncPath('+Owner.IDAsString+')',
4440 da_Define);
4441 FSrcDirIf.AddChild(IncPathDefTempl);
4442 Result:=true;
4443 end else begin
4444 NewVariable:='#PkgSrcMark'+Owner.IDAsWord;
4445 if NewVariable<>FSrcDirIf.Variable then begin
4446 FSrcDirIf.Variable:=NewVariable;
4447 // unit path
4448 UnitPathDefTempl:=FSrcDirIf.FindChildByName('UnitPath');
4449 if UnitPathDefTempl<>nil then
4450 UnitPathDefTempl.Value:='$(#UnitPath);$PkgUnitPath('+Owner.IDAsString+')';
4451 // include path
4452 IncPathDefTempl:=FSrcDirIf.FindChildByName('IncPath');
4453 if IncPathDefTempl<>nil then
4454 IncPathDefTempl.Value:='$(#IncPath);$PkgIncPath('+Owner.IDAsString+')';
4455 Result:=true;
4456 end;
4457 end;
4458 end;
4459
4460 procedure TLazPackageDefineTemplates.UpdateOutputDirectory;
4461 var
4462 LazPackage: TLazPackage;
4463 begin
4464 if FMain=nil then UpdateMain;
4465 if FMain=nil then exit;
4466
4467 LazPackage := Owner as TLazPackage;
4468 if FOutputDir=nil then begin
4469 FOutputDir:=TDefineTemplate.Create(PkgOutputDirDefTemplName,
4470 lisPkgDefsOutputDirectory, '', LazPackage.GetOutputDirectory, da_Directory);
4471 FOutputDir.SetDefineOwner(LazPackage,false);
4472 FOutputDir.SetFlags([dtfAutoGenerated],[],false);
4473 DisableDefaultsInDirectories(FOutputDir,false);
4474 FMain.AddChild(FOutputDir);
4475 end else begin
4476 FOutputDir.Value:=LazPackage.GetOutputDirectory;
4477 end;
4478
4479 if (FOutPutSrcPath=nil)
4480 or (fLastOutputDirSrcPathIDAsString<>Owner.IDAsString) then begin
4481 fLastOutputDirSrcPathIDAsString:=Owner.IDAsString;
4482 FOutputSrcPath:=TDefineTemplate.Create('CompiledSrcPath',
4483 lisPkgDefsCompiledSrcPathAddition, CompiledSrcPathMacroName,
4484 '$PkgSrcPath('+fLastOutputDirSrcPathIDAsString+');'+'$('+CompiledSrcPathMacroName+')',
4485 da_Define);
4486 FOutputSrcPath.SetDefineOwner(LazPackage,false);
4487 FOutputSrcPath.SetFlags([dtfAutoGenerated],[],false);
4488 CodeToolBoss.DefineTree.ReplaceChild(FOutputDir,FOutputSrcPath,FOutputSrcPath.Name);
4489 end;
4490 end;
4491
4492 procedure TLazPackageDefineTemplates.UpdateSourceDirectories;
4493 var
4494 i: Integer;
4495 SrcDirDefTempl, SrcDirMarkDefTempl: TDefineTemplate;
4496 IDHasChanged: Boolean;
4497 CurUnitPath, SrcDirs: String;
4498 begin
4499 if (not Owner.NeedsDefineTemplates) or (not Active) then exit;
4500
4501 // quick check if something has changed
4502 IDHasChanged:=fLastSourceDirsIDAsString<>Owner.IDAsString;
4503 CurUnitPath:=Owner.BaseCompilerOptions.ParsedOpts.GetParsedValue(pcosUnitPath);
4504 SrcDirs:=Owner.SourceDirectories.CreateSearchPathFromAllFiles;
4505 CurUnitPath:=TrimSearchPath(SrcDirs+';'+CurUnitPath+';.',
4506 Owner.BaseCompilerOptions.BaseDirectory,true);
4507
4508 if (fLastSourceDirectories<>nil)
4509 and (fLastSourceDirStamp=Owner.SourceDirectories.TimeStamp)
4510 and (not IDHasChanged)
4511 and (CurUnitPath=fLastUnitPath) then
4512 exit;
4513 //debugln(['TLazPackageDefineTemplates.UpdateSourceDirectories ',LazPackage.Name,' CurUnitPath=',CurUnitPath]);
4514 fLastSourceDirStamp:=Owner.SourceDirectories.TimeStamp;
4515 fLastSourceDirsIDAsString:=Owner.IDAsString;
4516 fLastUnitPath:=CurUnitPath;
4517
4518 // clear old define templates
4519 if fLastSourceDirectories<>nil then begin
4520 for i:=0 to fLastSourceDirectories.Count-1 do begin
4521 SrcDirDefTempl:=TDefineTemplate(fLastSourceDirectories.Objects[i]);
4522 SrcDirDefTempl.Unbind;
4523 SrcDirDefTempl.Free;
4524 end;
4525 fLastSourceDirectories.Clear;
4526 end else
4527 fLastSourceDirectories:=TStringList.Create;
4528
4529 // build source directory define templates
4530 FreeAndNil(fLastSourceDirectories);
4531 fLastSourceDirectories:=SearchPathToList(CurUnitPath);
4532 if (fLastSourceDirectories.Count>0) and ((FSrcDirIf=nil) or IDHasChanged) then
4533 UpdateSrcDirIfDef;
4534 for i:=0 to fLastSourceDirectories.Count-1 do begin
4535 // create directory template
4536 SrcDirDefTempl:=TDefineTemplate.Create('Source Directory '+IntToStr(i+1),
4537 fLastSourceDirectories[i],'',fLastSourceDirectories[i],da_Directory);
4538 DisableDefaultsInDirectories(SrcDirDefTempl,false);
4539 fLastSourceDirectories.Objects[i]:=SrcDirDefTempl;
4540 // add package source directory marker
4541 SrcDirMarkDefTempl:=TDefineTemplate.Create('PkgSrcDirMark',
4542 lisPkgDefsSrcDirMark,'#PkgSrcMark'+Owner.IDAsWord,'',da_Define);
4543 SrcDirDefTempl.AddChild(SrcDirMarkDefTempl);
4544
4545 SrcDirDefTempl.SetDefineOwner(Owner as TLazPackage,false);
4546 SrcDirDefTempl.SetFlags([dtfAutoGenerated],[],false);
4547 // add directory
4548 FSrcDirectories.AddChild(SrcDirDefTempl);
4549 end;
4550 CodeToolBoss.DefineTree.ClearCache;
4551 end;
4552
4553 procedure TLazPackageDefineTemplates.UpdateDefinesForCustomDefines;
4554 var
4555 OptionsDefTempl: TDefineTemplate;
4556 NewCustomOptions: String;
4557 begin
4558 if (not Owner.NeedsDefineTemplates) or (not Active) then exit;
4559
4560 // check if something has changed
4561 NewCustomOptions:=Owner.BaseCompilerOptions.GetOptionsForCTDefines;
4562 if FLastCustomOptions=NewCustomOptions then exit;
4563
4564 FLastCustomOptions:=NewCustomOptions;
4565 OptionsDefTempl:=CodeToolBoss.DefinePool.CreateFPCCommandLineDefines(
4566 'Custom Options', FLastCustomOptions, false, Owner as TLazPackage);
4567 if OptionsDefTempl=nil then begin
4568 // no custom options -> delete old template
4569 if (FSrcDirIf<>nil) and FSrcDirIf.DeleteChild('Custom Options') then
4570 CodeToolBoss.DefineTree.ClearCache;
4571 end else begin
4572 UpdateSrcDirIfDef;
4573 FSrcDirIf.ReplaceChild(OptionsDefTempl);
4574 end;
4575 end;
4576
4577 { TBasePackageEditor }
4578
GetLazPackagenull4579 function TBasePackageEditor.GetLazPackage: TLazPackage;
4580 begin
4581 Result:=nil;
4582 end;
4583
4584 { TPublishPackageOptions }
4585
4586 procedure TPublishPackageOptions.DoOnModifyChange;
4587 begin
4588 if Modified then
4589 TLazPackage(Owner).Modified:=true;
4590 end;
4591
GetDefaultDestinationDirnull4592 function TPublishPackageOptions.GetDefaultDestinationDir: string;
4593 begin
4594 Result:='$(TestDir)/publishedpackage/';
4595 end;
4596
4597 { TPkgPairTree }
4598
4599 function ComparePkgPairs(Pair1, Pair2: Pointer): integer;
4600 begin
4601 Result:=TPkgPair(Pair1).Compare(TPkgPair(Pair2));
4602 end;
4603
4604 constructor TPkgPairTree.Create;
4605 begin
4606 inherited Create(@ComparePkgPairs);
4607 end;
4608
4609 destructor TPkgPairTree.Destroy;
4610 begin
4611 FreeAndClear;
4612 inherited Destroy;
4613 end;
4614
FindPairnull4615 function TPkgPairTree.FindPair(Pkg1, Pkg2: TLazPackage; IgnoreOrder: boolean): TPkgPair;
4616 var
4617 Comp: integer;
4618 ANode: TAVLTreeNode;
4619 begin
4620 ANode:=Root;
4621 while (ANode<>nil) do begin
4622 Result:=TPkgPair(ANode.Data);
4623 Comp:=Result.ComparePair(Pkg1,Pkg2);
4624 if Comp=0 then exit;
4625 if Comp>0 then begin
4626 ANode:=ANode.Left
4627 end else begin
4628 ANode:=ANode.Right
4629 end;
4630 end;
4631 if IgnoreOrder and (Pkg1<>Pkg2) then
4632 Result:=FindPair(Pkg2,Pkg1,false)
4633 else
4634 Result:=nil;
4635 end;
4636
AddPairnull4637 function TPkgPairTree.AddPair(Pkg1, Pkg2: TLazPackage): TPkgPair;
4638 begin
4639 Result:=TPkgPair.Create(Pkg1,Pkg2);
4640 Add(Result);
4641 end;
4642
AddPairIfNotExistsnull4643 function TPkgPairTree.AddPairIfNotExists(Pkg1, Pkg2: TLazPackage): TPkgPair;
4644 begin
4645 Result:=FindPair(Pkg1,Pkg2,true);
4646 if Result=nil then
4647 Result:=AddPair(Pkg1,Pkg2);
4648 end;
4649
4650 { TPkgPair }
4651
4652 constructor TPkgPair.Create(Pkg1, Pkg2: TLazPackage);
4653 begin
4654 Package1:=Pkg1;
4655 Package2:=Pkg2;
4656 end;
4657
ComparePairnull4658 function TPkgPair.ComparePair(Pkg1, Pkg2: TLazPackage): integer;
4659 begin
4660 Result:=Package1.Compare(Pkg1);
4661 if Result=0 then
4662 Result:=Package2.Compare(Pkg2);
4663 end;
4664
Comparenull4665 function TPkgPair.Compare(PkgPair: TPkgPair): integer;
4666 begin
4667 Result:=ComparePair(PkgPair.Package1,PkgPair.Package2);
4668 end;
4669
AsStringnull4670 function TPkgPair.AsString: string;
4671 begin
4672 Result:=Package1.IDAsString+' - '+Package2.IDAsString;
4673 end;
4674
4675 { TPkgUnitsTree }
4676
FindNodeWithUnitNamenull4677 function TPkgUnitsTree.FindNodeWithUnitName(const AUnitName: string): TAVLTreeNode;
4678 var
4679 Comp: integer;
4680 PkgFile: TPkgFile;
4681 begin
4682 Result:=Root;
4683 while (Result<>nil) do begin
4684 PkgFile:=TPkgFile(Result.Data);
4685 Comp:=SysUtils.CompareText(AUnitName,PkgFile.Unit_Name);
4686 if Comp=0 then exit;
4687 if Comp<0 then begin
4688 Result:=Result.Left
4689 end else begin
4690 Result:=Result.Right
4691 end;
4692 end;
4693 end;
4694
FindPkgFileWithUnitNamenull4695 function TPkgUnitsTree.FindPkgFileWithUnitName(const AUnitName: string): TPkgFile;
4696 var
4697 ANode: TAVLTreeNode;
4698 begin
4699 ANode:=FindNodeWithUnitName(AUnitName);
4700 if ANode=nil then
4701 Result:=nil
4702 else
4703 Result:=TPkgFile(ANode.Data);
4704 end;
4705
4706 function ComparePkgFilesUnitname(PkgFile1, PkgFile2: Pointer): integer;
4707 begin
4708 Result := SysUtils.CompareText(
4709 TPkgFile(PkgFile1).Unit_Name,
4710 TPkgFile(PkgFile2).Unit_Name);
4711 end;
4712
4713 constructor TPkgUnitsTree.Create(ThePackage: TLazPackage);
4714 begin
4715 fLazPackage:=ThePackage;
4716 inherited Create(@ComparePkgFilesUnitname);
4717 end;
4718
4719 initialization
4720 RegisterIDEOptionsGroup(GroupPackage, TPackageIDEOptions);
4721 RegisterIDEOptionsGroup(GroupPkgCompiler, TPkgCompilerOptions);
4722 PackageDependencies:=TAVLTree.Create(@ComparePkgDependencyNames);
4723
4724 finalization
4725 FreeThenNil(PackageDependencies);
4726
4727 end.
4728
4729