{**************************************************************************************************} { } { Project JEDI Code Library (JCL) extension } { } { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); } { you may not use this file except in compliance with the License. You may obtain a copy of the } { License at http://www.mozilla.org/MPL/ } { } { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF } { ANY KIND, either express or implied. See the License for the specific language governing rights } { and limitations under the License. } { } { The Original Code is JclInstall.pas. } { } { The Initial Developer of the Original Code is Petr Vones. Portions created by Petr Vones are } { Copyright (C) of Petr Vones. All Rights Reserved. } { } { Contributor(s): Robert Rossmair (crossplatform & BCB support, refactoring) } { } { Last modified: $Date: 2006/02/09 13:57:33 $ } { } {**************************************************************************************************} unit JclInstall; interface {$I jcl.inc} {$I crossplatform.inc} uses SysUtils, Classes, IniFiles, Contnrs, JclSysUtils, JclBorlandTools, JediInstall; type TJclDistribution = class; TJclInstallation = class private FDistribution: TJclDistribution; FTarget: TJclBorRADToolInstallation; FDebugDcuDir: string; FLibDir: string; FLibObjDir: string; FDefines: TStringList; FUnits: TStringList; FDemos: TStringList; FDemoExclusionList: TStringList; FOnWriteLog: TTextHandler; FRelativeDemoPath: string; FDemoSectionName: string; procedure AddDemo(const Directory: string; const FileInfo: TSearchRec); procedure AddDemos(const Directory: string); procedure AddDialogToRepository(const DialogName: string; const DialogFileName: string; const DialogIconFileName: string; const Designer: string; const Ancestor: string = ''); function GetDemoList: TStringList; procedure BuildUnitList(const SubDir: string; Units: TStrings); function GetDemoExclusionList: TStrings; function GetProgressTotal: Integer; function GetTool: IJediInstallTool; function GetUnits(const SourceDir: string): TStrings; function InitOptions: Boolean; procedure InstallationStarted; procedure InstallationFinished; procedure InstallFailedOn(const InstallObj: string); procedure ConfigureBpr2Mak(const PackageFileName: string); {$IFDEF MSWINDOWS} function CompileExpert(const Name: string; InstallExpert: Boolean): Boolean; {$ENDIF MSWINDOWS} function CompilePackage(const Name: string; InstallPackage: Boolean): Boolean; function CompilePackages: Boolean; function InstallOption(Option: TJediInstallOption): Boolean; procedure RemoveDialogFromRepository(const DialogName, DialogFileName: string); function UninstallPackage(const Name: string): Boolean; function UninstallPackages: Boolean; function UninstallOption(Option: TJediInstallOption): Boolean; function LogFileName: string; procedure MakeDemo(Index: Integer); function MakeDemos: Boolean; overload; function MakeUnits(Debug: Boolean): Boolean; function MakePath(const FormatStr: string): string; function Description(Option: TJediInstallOption): string; procedure SaveDemoOption(Index: Integer); procedure SaveOption(Option: TJediInstallOption); procedure SaveOptions; procedure Progress(Steps: Integer); function StoredOption(Option: TJediInstallOption; Default: Boolean = True): Boolean; function TotalUnitCount: Integer; procedure WriteLog(const Msg: string); function GetJclDcpPath: string; {$IFDEF MSWINDOWS} function InstallExpert(const Option: TJediInstallOption): Boolean; function UninstallExpert(const Option: TJediInstallOption): Boolean; {$ENDIF MSWINDOWS} protected constructor Create(JclDistribution: TJclDistribution; InstallTarget: TJclBorRADToolInstallation); function CompileLibraryUnits(const SubDir: string; Debug: Boolean): Boolean; {$IFDEF MSWINDOWS} procedure AddHelpToIdeTools; procedure AddHelpToOpenHelp; procedure RemoveHelpFromIdeTools; procedure RemoveHelpFromOpenHelp; procedure CopyFakeXmlRtlPackage; {$ENDIF MSWINDOWS} function BplPath: string; function DcpPath: string; function CheckDirectories: Boolean; procedure CleanupRepository; function DemoOption(DemoIndex: Integer): TJediInstallOption; function DemoOptionSelected(Index: Integer): Boolean; function ExcludeEdition(ExcludeList: TStrings; Index: Integer; out Name: string): Boolean; function InstallSelectedOptions: Boolean; function UninstallSelectedOptions: Boolean; function OptionSelected(Option: TJediInstallOption): Boolean; function ProgressWeight(Option: TJediInstallOption): Integer; function Run: Boolean; function Undo: Boolean; function StoredBplPath: string; function StoredDcpPath: string; property Defines: TStringList read FDefines; property Demos: TStringList read GetDemoList; property DemoSectionName: string read FDemoSectionName; property DemoExclusionList: TStrings read GetDemoExclusionList; property Tool: IJediInstallTool read GetTool; property DebugDcuDir: string read FDebugDcuDir; property LibDir: string read FLibDir; property LibObjDir: string read FLibObjDir; property ProgressTotal: Integer read GetProgressTotal; property RelativeDemoPath: string read FRelativeDemoPath; property Target: TJclBorRADToolInstallation read FTarget; property Units[const SourceDir: string]: TStrings read GetUnits; property JclDcpPath: string read GetJclDcpPath; public destructor Destroy; override; property OnWriteLog: TTextHandler read FOnWriteLog write FOnWriteLog; property Distribution: TJclDistribution read FDistribution; end; TJclDistribution = class (TInterfacedObject, IJediInstall) private FJclPath: string; FJclBinDir: string; FLibDirMask: string; FLibDebugDirMask: string; FLibObjDirMask: string; FJclSourceDir: string; FJclSourcePath: string; FClxDialogFileName: string; FClxDialogIconFileName: string; {$IFDEF MSWINDOWS} FVclDialogFileName: string; FVclDialogSendFileName: string; FVclDialogIconFileName: string; FVclDialogSendIconFileName: string; {$ENDIF MSWINDOWS} FJclChmHelpFileName: string; FJclHlpHelpFileName: string; FJclReadmeFileName: string; FTool: IJediInstallTool; FTargetInstalls: TObjectList; FIniFile: TMemIniFile; FProgress: Integer; FProgressTotal: Integer; FProgressPercent: Integer; FOnStarting: TInstallationEvent; FOnEnding: TInstallationEvent; FOnProgress: TInstallationProgressEvent; FInstalling: Boolean; function CreateInstall(Target: TJclBorRADToolInstallation): Boolean; function GetTargetInstall(Installation: TJclBorRADToolInstallation): TJclInstallation; procedure InitInstallationTargets; procedure InitProgress; function GetExamplesDir: string; function GetDemosPath: string; protected constructor Create; function DocFileName(const BaseFileName: string): string; procedure InstallProgress(Steps: Integer); procedure SetTool(const Value: IJediInstallTool); procedure ShowProgress; property TargetInstall[Target: TJclBorRADToolInstallation]: TJclInstallation read GetTargetInstall; public destructor Destroy; override; function FeatureInfoFileName(FeatureID: Cardinal): string; function GetHint(Option: TJediInstallOption): string; function InitInformation(const ApplicationFileName: string): Boolean; function Install: Boolean; function Uninstall: Boolean; function ReadmeFileName: string; procedure SetOnWriteLog(Installation: TJclBorRADToolInstallation; Value: TTextHandler); procedure SetOnEnding(Value: TInstallationEvent); procedure SetOnProgress(Value: TInstallationProgressEvent); procedure SetOnStarting(Value: TInstallationEvent); function Supports(Target: TJclBorRADToolInstallation): Boolean; property BinDir: string read FJclBinDir; property ExamplesDir: string read GetExamplesDir; property DemosPath: string read GetDemosPath; property ChmHelpFileName: string read FJclChmHelpFileName; property HlpHelpFileName: string read FJclHlpHelpFileName; property Installing: Boolean read FInstalling; property Path: string read FJclPath; property SourceDir: string read FJclSourceDir; property SourcePath: string read FJclSourcePath; property Tool: IJediInstallTool read FTool write SetTool; end; function CreateJclInstall: IJediInstall; function LogFileName(Target: TJclBorRADToolInstallation): string; implementation uses {$IFDEF VCL} Dialogs, Controls, {$ELSE VCL} QDialogs, QControls, {$ENDIF VCL} JclBase, JclResources, JclSysInfo, {$IFDEF MSWINDOWS} JclPeImage, {$ENDIF MSWINDOWS} JclFileUtils, JclStrings; { Install option data } resourcestring // Captions // Products RsJCL = 'JEDI Code Library'; // Common features RsDefThreadSafe = 'Thread safe container classes'; RsDefDropObsoleteCode = 'Drop obsolete code'; RsDefMathPrecSingle = 'Single float precision'; RsDefMathPrecDouble = 'Double float precision'; RsDefMathPrecExtended = 'Extended float precision'; RsMapCreate = 'Create MAP files'; RsMapLink = 'Link MAP files'; RsMapDelete = 'Delete MAP files after the link'; RsEnvironment = 'Environment'; RsEnvLibPath = 'Add JCL to IDE Library Path'; RsEnvBrowsingPath = 'Add JCL to IDE Browsing Path'; RsEnvDebugDCUPath = 'Add JCL to Debug DCU Path'; RsMake = 'Make library units'; RsMakeRelease = 'Release'; RsMakeDebug = 'Debug'; RsMakeVClx = 'Visual CLX'; RsMakeDemos = 'Make demos'; RsHelpFiles = 'Help files'; RsIdeExperts = 'IDE experts'; RsJCLPackages = 'Packages'; RsIdeHelpHlp = 'Add help file to IDE help system'; RsIdeHelpChm = 'Add HTML help to the Tools menu'; RsCopyHppFiles = 'Copy HPP files to %s'; RsDualPackages = 'Dual packages'; RsCopyPackagesHppFiles = 'Output HPP files to %s'; // Product specific features RsJCLExceptDlg = 'Sample Exception Dialogs in the Object Reporitory'; RsJCLDialogVCL = 'VCL Exception Dialog'; RsJCLDialogVCLSnd = 'VCL Exception Dialog with Send button'; RsJCLDialogCLX = 'CLX Exception Dialog'; RsExpertsDsgnPackages = 'Design packages'; RsExpertsDLL = 'DLL experts'; RsJCLIdeDebug = 'Debug Extension'; RsJCLIdeAnalyzer = 'Project Analyzer'; RsJCLIdeFavorite = 'Favorite combobox in Open/Save dialogs'; RsJCLIdeThreadNames = 'Displaying thread names in Thread Status window'; RsJCLIdeUses = 'Uses Wizard'; RsJCLSimdView = 'Debug window for XMM registers'; RsJCLVersionControl = 'Version control'; // Hints RsHintTarget = 'Installation target'; RsHintJCL = 'Select to install JCL for this target.'; RsHintJclDefThreadSafe = 'Conditionally compile container classes to be thread safe'; RsHintJclDefDropObsoleteCode = 'Do not compile deprecated code'; RsHintJclDefMathPrecSingle = 'type Float = Single'; RsHintJclDefMathPrecDouble = 'type Float = Double'; RsHintJclDefMathPrecExtended = 'type Float = Extended'; RsHintJclMapCreate = 'Create detailled MAP files for each libraries'; RsHintJclMapLink = 'Link MAP files as a resource in the output library or executable, the stack can be traced on exceptions'; RsHintJclMapDelete = 'Once linked in the binary, delete the original MAP file'; RsHintJclEnv = 'Set selected environment items'; RsHintJclEnvLibPath = 'Add JCL precompiled unit directories to library path'; RsHintJclEnvBrowsingPath = 'Add JCL source directories to browsing path'; RsHintJclEnvDebugDCUPath = 'This is a prerequisite for using the precompiled JCL debug units ' + 'by means of the respective'#13#10'Project Options|Compiler switch. See "Make library ' + 'units/Debug" option below.'; RsHintJclMake = 'Generate .dcu and .dpu (Kylix only) files.'#13#10'Recommended.'; RsHintJclMakeRelease = 'Make precompiled units for release, i.e. optimized, w/o debug information.'; RsHintJclMakeReleaseVcl = 'Make precompiled VCL units for release'; RsHintJclMakeReleaseVClx = 'Make precompiled Visual CLX units for release'; RsHintJclMakeDebug = 'Make precompiled units for debugging, i.e.optimization off, debug ' + 'information included.'#13#10'When installed, available through Project Options|Compiler|Use ' + 'Debug DCUs.'; RsHintJclMakeDebugVcl = 'Make precompiled VCL units for debugging'; RsHintJclMakeDebugVClx = 'Make precompiled Visual CLX units for debugging'; RsHintJclCopyHppFiles = 'Copy .hhp files into C++Builder''s include path.'; RsHintJclDualPackages = 'The same package introduce component for Delphi Win32 and C++Builder Win32'; RsHintJclPackages = 'Build and eventually install JCL runtime packages (RTL, VCL and Visual ' + 'CLX) and optional IDE experts.'; RsHintJclExperts = 'Build and install selected IDE experts.'; RsHintJclExpertsDsgnPackages = 'Design packages containing JCL experts'; RsHintJclExpertsDLL = 'DLLs containing JCL experts'; RsHintJclExpertDebug = 'Install IDE expert which assists to insert JCL Debug information into ' + 'executable files.'; RsHintJclExpertAnalyzer = 'Install IDE Project Analyzer.'; RsHintJclExpertFavorite = 'Install "Favorites" combobox in IDE Open/Save dialogs.'; RsHintJclExpertsThreadNames = 'Display thread names in Thread Status window IDE extension.'; RsHintJclExpertUses = 'Install IDE Uses Wizard.'; RsHintJclExpertSimdView = 'Install a debug window of XMM registers (used by SSE instructions)'; RsHintJclExpertVersionControl = 'Integration of TortoiseCVS and TortoiseSVN in the IDE'; RsHintJclCopyPackagesHppFiles = 'Output .hhp files into C++Builder''s include path instead of ' + 'the source paths.'; RsHintJclExcDialog = 'Add selected Exception dialogs to the Object Repository.'; RsHintJclExcDialogVCL = 'Add VCL exception dialog to the Object Repository.'; RsHintJclExcDialogVCLSnd = 'Add VCL exception dialog with "Send Button" to the Object Repository.'; RsHintJclExcDialogCLX = 'Add CLX exception dialog (Windows only) to the Object Repository.'; RsHintJclHelp = 'Install JCL help files.'; RsHintJclHelpHlp = 'Customize Borland Open Help to include JCL help files.'; RsHintJclHelpChm = ''; RsHintJclMakeDemos = 'Make JCL demo applications'; // warning messages RsPackageNodeNotSelected = 'The "Packages" node is not selected.' + sLineBreak + 'Various libraries (including the JVCL) require JCL packages to be compiled' + sLineBreak + 'Do you want to continue without compiling JCL packages?'; const Invalid = -1; LineBreak = AnsiLineBreak; ioUndef = TJediInstallOption(Invalid); InitData: array[TJediInstallOption] of TInstallOptionData = ( (Parent: ioUndef; // ioTarget Caption: ''; Hint: RsHintTarget), (Parent: ioTarget; // ioJCL Caption: RsJCL; Hint: RsHintJcl), (Parent: ioJCL; // ioJclDefThreadSafe Caption: RsDefThreadSafe; Hint: RsHintJclDefThreadSafe), (Parent: ioJCL; // ioJclDefDropObsoleteCode Caption: RsDefDropObsoleteCode; Hint: RsHintJclDefDropObsoleteCode), (Parent: ioJCL; // ioJclDefMathPrecSingle Caption: RsDefMathPrecSingle; Hint: RsHintJclDefMathPrecSingle), (Parent: ioJCL; // ioJclDefMathPrecDouble Caption: RsDefMathPrecDouble; Hint: RsHintJclDefMathPrecDouble), (Parent: ioJCL; // ioJclDefMathPrecExtended Caption: RsDefMathPrecExtended; Hint: RsHintJclDefMathPrecExtended), (Parent: ioJCL; // ioJclMapCreate Caption: RsMapCreate; Hint: RsHintJclMapCreate), (Parent: ioJclMapCreate; // ioJclMapLink Caption: RsMapLink; Hint: RsHintJclMapLink), (Parent: ioJclMapLink; // ioJclMapDelete Caption: RsMapDelete; Hint: RsHintJclMapDelete), (Parent: ioJCL; // ioJclEnv Caption: RsEnvironment; Hint: RsHintJclEnv), (Parent: ioJclEnv; // ioJclEnvLibPath Caption: RsEnvLibPath; Hint: RsHintJclEnvLibPath), (Parent: ioJclEnv; // ioJclEnvBrowsingPath Caption: RsEnvBrowsingPath; Hint: RsHintJclEnvBrowsingPath), (Parent: ioJclEnv; // ioJclEnvDebugDCUPath Caption: RsEnvDebugDCUPath; Hint: RsHintJclEnvDebugDCUPath), (Parent: ioJCL; // ioJclMake Caption: RsMake; Hint: RsHintJclMake), (Parent: ioJclMake; // ioJclMakeRelease Caption: RsMakeRelease; Hint: RsHintJclMakeRelease), (Parent: ioJclMake; // ioJclMakeReleaseVClx Caption: RsMakeVClx; Hint: RsHintJclMakeReleaseVClx), (Parent: ioJclMake; // ioJclMakeDebug Caption: RsMakeDebug; Hint: RsHintJclMakeDebug), (Parent: ioJclMake; // ioJclMakeDebugVClx Caption: RsMakeVClx; Hint: RsHintJclMakeDebugVClx), (Parent: ioJclMake; // ioJclCopyHppFiles Caption: RsCopyHppFiles; Hint: RsHintJclCopyHppFiles), (Parent: ioJclPackages; // ioJclDualPackages Caption: RsDualPackages; Hint: RsHintJclDualPackages), (Parent: ioJCL; // ioJclPackages Caption: RsJCLPackages; Hint: RsHintJclPackages), (Parent: ioJclExperts; // ioJclExpertsDesignPackages Caption: RsExpertsDsgnPackages; Hint: RsHintJclExpertsDsgnPackages), (Parent: ioJclExperts; // ioJclExpertsDLL Caption: RsExpertsDLL; Hint: RsHintJclExpertsDLL), (Parent: ioJclPackages; // ioJclExperts Caption: RsIdeExperts; Hint: RsHintJclExperts), (Parent: ioJclExperts; // ioJclExpertDebug Caption: RsJCLIdeDebug; Hint: RsHintJclExpertDebug), (Parent: ioJclExperts; // ioJclExpertAnalyzer Caption: RsJCLIdeAnalyzer; Hint: RsHintJclExpertAnalyzer), (Parent: ioJclExperts; // ioJclExpertFavorite Caption: RsJCLIdeFavorite; Hint: RsHintJclExpertFavorite), (Parent: ioJclExperts; // ioJclExpertThreadNames Caption: RsJCLIdeThreadNames; Hint: RsHintJclExpertsThreadNames), (Parent: ioJclExperts; // ioJclExpertUses Caption: RsJCLIdeUses; Hint: RsHintJclExpertUses), (Parent: ioJclExperts; // ioJclExpertSimdView Caption: RsJCLSimdView; Hint: RsHintJclExpertSimdView), (Parent: ioJclExperts; // ioJclExpertVersionControl Caption: RsJclVersionControl; Hint: RsHintJclExpertVersionControl), (Parent: ioJclPackages; // ioJclCopyPackagesHppFiles Caption: RsCopyPackagesHppFiles; Hint: RsHintJclCopyPackagesHppFiles), (Parent: ioJCL; // ioJclExcDialog Caption: RsJCLExceptDlg; Hint: RsHintJclExcDialog), (Parent: ioJclExcDialog; // ioJclExcDialogVCL Caption: RsJCLDialogVCL; Hint: RsHintJclExcDialogVCL), (Parent: ioJclExcDialog; // ioJclExcDialogVCLSnd Caption: RsJCLDialogVCLSnd; Hint: RsHintJclExcDialogVCLSnd), (Parent: ioJclExcDialog; // ioJclExcDialogCLX Caption: RsJCLDialogCLX; Hint: RsHintJclExcDialogCLX), (Parent: ioJCL; // ioJclHelp Caption: RsHelpFiles; Hint: RsHintJclHelp), (Parent: ioJclHelp; // ioJclHelpHlp Caption: RsIdeHelpHlp; Hint: RsHintJclHelpHlp), (Parent: ioJclHelp; // ioJclHelpChm Caption: RsIdeHelpChm; Hint: RsHintJclHelpChm), (Parent: ioJCL; // ioJclMakeDemos Caption: RsMakeDemos; Hint: RsHintJclMakeDemos) ); const {$IFDEF KYLIX} VersionDir = '/k%d'; VersionDirExp = '/k%%d'; {$ELSE} VersionDir = '\%s'; VersionDirExp = '\%%s'; {$ENDIF} JclSrcDirCommon = 'common'; JclSrcDirVisClx = 'visclx'; {$IFDEF MSWINDOWS} {$IFNDEF RTL140_UP} PathSep = ';'; {$ENDIF RTL140_UP} VclDialogFileName = 'ExceptDlg.pas'; VclDlgSndFileName = 'ExceptDlgMail.pas'; VclDialogName = 'Exception Dialog'; VclDialogNameSend = 'Exception Dialog with Send'; JclDpk = 'Jcl'; JclVclDpk = 'JclVcl'; JclVClxDpk = 'JclVClx'; JclIdeBaseDpk = 'JclBaseExpert'; JclIdeDebugDpk = 'JclDebugExpert'; JclIdeAnalyzerDpk = 'JclProjectAnalysisExpert'; JclIdeFavoriteDpk = 'JclFavoriteFoldersExpert'; JclIdeThrNamesDpk = 'JclThreadNameExpert'; JclIdeUsesDpk = 'JclUsesExpert'; JclIdeSimdViewDpk = 'JclSIMDViewExpert'; JclIdeVersionControlDpk = 'JclVersionControlExpert'; JclBdsExpertDpr = 'JclBdsExpert'; ExpertPaths: array[ioJclExperts..ioJclExpertVersionControl] of string = ( JclIdeBaseDpk, JclIdeDebugDpk, JclIdeAnalyzerDpk, JclIdeFavoriteDpk, JclIdeThrNamesDpk, JclIdeUsesDpk, JclIdeSimdViewDpk, JclIdeVersionControlDpk ); JclSrcDirOS = 'windows'; JclSrcDirVcl = 'vcl'; JclSourceDirs: array[0..3] of string = (JclSrcDirCommon, JclSrcDirOS, JclSrcDirVcl, JclSrcDirVisClx); JclSourcePath = '%0:s\' + JclSrcDirOS + ';%0:s\' + JclSrcDirCommon + ';%0:s\' + JclSrcDirVcl + ';%0:s\' + JclSrcDirVisClx; BCBIncludePath = '%s;%s;$(BCB)\include;$(BCB)\include\vcl'; BCBObjectPath = '%s;%s;$(BCB)\Lib\Obj'; {$ENDIF MSWINDOWS} {$IFDEF UNIX} JclSrcDirOS = 'unix'; JclSourceDirs: array[0..2] of string = (JclSrcDirCommon, JclSrcDirOS, JclSrcDirVisClx); JclSourcePath = '%0:s\' + JclSrcDirOS + ':%0:s\' + JclSrcDirCommon + ':%0:s\' + JclSrcDirVisClx; BCBIncludePath = '%s:%s:$(BCB)/include:$(BCB)/include/vcl'; BCBObjectPath = BCBIncludePath; {$ENDIF UNIX} DialogsPath = 'experts' + PathSeparator + 'debug' + PathSeparator + 'dialog' + PathSeparator; ClxDialogFileName = 'ClxExceptDlg.pas'; ClxDialogName = 'CLX Exception Dialog'; DialogDescription = 'JCL Application exception dialog'; DialogAuthor = 'Project JEDI'; DialogPage = 'Dialogs'; JclChmHelpFile = 'help' + PathSeparator + 'JCLHelp.chm'; JclHlpHelpFile = 'help' + PathSeparator + 'JCLHelp.hlp'; JclHelpTitle = 'JCL %d.%d Help'; JclHelpIndexName = 'Jedi Code Library Reference'; HHFileName = 'HH.EXE'; {$IFDEF MSWINDOWS} Bcb2MakTemplate = 'packages\BCB.bmk'; {$ENDIF MSWINDOWS} {$IFDEF KYLIX} Bcb2MakTemplate = 'packages/bcb.gmk'; {$ENDIF KYLIX} resourcestring RsStatusMessage = 'Installing %s...'; RsStatusDetailMessage = 'Installing %s for %s...'; RsUninstallMessage = 'Removing %s...'; RsBuildingMessage = 'Building %s...'; RsBuildingDemosMessage = 'Building demo projects...'; RsBuildingDemosByTargetMessage = 'Building demo projects by %s...'; RsCompilingMessage = 'Compiling %s...'; RsInstallFailed = 'Installation of %s failed, see %s for details.'; RsInvalidBplPath = LineBreak + 'Invalid BPL path "%s"'; RsInvalidDcpPath = LineBreak + 'Invalid DCP path "%s"'; RsLibDescriptor = '%s library %sunits for %s'; {$IFDEF VisualCLX} RsReadmeFileName = 'Readme.html'; {$ELSE} RsReadmeFileName = 'Readme.txt'; {$ENDIF} RsIniFileName = 'JCL-install.ini'; function CreateJclInstall: IJediInstall; begin Result := TJclDistribution.Create as IJediInstall; end; function CopyFiles(Files: TStrings; const TargetDir: string; Overwrite: Boolean = True): Boolean; var I: Integer; FileName: string; begin Result := True; for I := 0 to Files.Count - 1 do begin FileName := Files[I]; Result := Result and FileCopy(FileName, PathAddSeparator(TargetDir) + ExtractFileName(FileName), Overwrite); end; end; procedure CopyResFiles(TargetDir: string); var FileList: TStringList; begin FileList := TStringList.Create; try if BuildFileList('*.res', faAnyFile, FileList) then CopyFiles(FileList, TargetDir); finally FileList.Free; end; end; function CopyHppFiles(Units: TStrings; const TargetDir: string): Boolean; var I: Integer; FileName: string; begin Result := True; for I := 0 to Units.Count - 1 do begin FileName := Units[I] + '.hpp'; if FileExists(FileName) then Result := Result and FileCopy(FileName, TargetDir + FileName, True); end; end; function FullPackageFileName(Target: TJclBorRADToolInstallation; const BaseName: string): string; const S = 'packages' + VersionDir + PathSeparator + '%s'; begin with Target do begin {$IFDEF KYLIX} Result := Format(S + '%s', [VersionNumber, BaseName, PackageSourceFileExtension]); {$ELSE KYLIX} if SupportsLibSuffix then Result := Format(S + '%s', [VersionNumberStr, BaseName, PackageSourceFileExtension]) else Result := Format(S + '%s0%3:s', [VersionNumberStr, BaseName, VersionNumberStr, PackageSourceFileExtension]); {$ENDIF KYLIX} end; end; {$IFDEF MSWINDOWS} function FullLibraryFileName(Target: TJclBorRADToolInstallation; const BaseName: string): string; const S = 'packages' + VersionDir + PathSeparator + '%s'; begin with Target do if SupportsLibSuffix then Result := Format(S + 'DLL%s', [VersionNumberStr, BaseName, ProjectSourceFileExtension]) else Result := Format(S + 'DLL%s0%3:s', [VersionNumberStr, BaseName, VersionNumberStr, ProjectSourceFileExtension]); end; {$ENDIF MSWINDOWS} function LogFileName(Target: TJclBorRADToolInstallation): string; begin with Target do Result := Format('%s%s.log', [PathAddSeparator(ExtractFileDir(ParamStr(0))), Target.Name]); end; { TJclInstallation } constructor TJclInstallation.Create(JclDistribution: TJclDistribution; InstallTarget: TJclBorRADToolInstallation); begin inherited Create; FDistribution := JclDistribution; FTarget := InstallTarget; InstallTarget.OutputCallback := WriteLog; FDebugDcuDir := MakePath(Distribution.FLibDebugDirMask); FLibDir := MakePath(Distribution.FLibDirMask); if InstallTarget is TJclBCBInstallation then FLibObjDir := MakePath(Distribution.FLibObjDirMask); FDefines := TStringList.Create; FUnits := TStringList.Create; FDemoSectionName := Target.Name + ' demos'; end; destructor TJclInstallation.Destroy; var I: Integer; begin FDemoExclusionList.Free; FDemos.Free; if Assigned(FUnits) then for I := 0 to FUnits.Count - 1 do FUnits.Objects[I].Free; FUnits.Free; FDefines.Free; inherited Destroy; end; procedure TJclInstallation.AddDemo(const Directory: string; const FileInfo: TSearchRec); var FileName: string; begin FileName := FRelativeDemoPath + FileInfo.Name; if not DemoExclusionList.IndexOf(FileName) >= 0 then Demos.Append(FileName); end; procedure TJclInstallation.AddDemos(const Directory: string); begin FRelativeDemoPath := PathAddSeparator(PathGetRelativePath(Distribution.DemosPath, Directory)); EnumFiles(Directory + '*.dpr', AddDemo); end; procedure TJclInstallation.AddDialogToRepository(const DialogName: string; const DialogFileName: string; const DialogIconFileName: string; const Designer: string; const Ancestor: string = ''); begin WriteLog(Format(LineBreak + 'Installing %s...', [DialogName])); with Target.Repository do AddObject( DialogFileName, BorRADToolRepositoryFormTemplate, FindPage(DialogPage, 1), DialogName, DialogIconFileName, DialogDescription, DialogAuthor, BorRADToolRepositoryDesignerDfm); WriteLog(Format('-> %s' + LineBreak + '-> %s' + LineBreak + '...done.', [DialogFileName, DialogIconFileName])); end; {$IFDEF MSWINDOWS} procedure TJclInstallation.AddHelpToIdeTools; var ToolsIndex: Integer; HelpTitle: string; begin HelpTitle := Format(JclHelpTitle, [JclVersionMajor, JclVersionMinor]); with Target.IdeTools do if IndexOfTitle(HelpTitle) = Invalid then begin ToolsIndex := Count; Count := ToolsIndex + 1; Title[ToolsIndex] := HelpTitle; Path[ToolsIndex] := HHFileName; Parameters[ToolsIndex] := StrDoubleQuote(FDistribution.FJclChmHelpFileName); WorkingDir[ToolsIndex] := Distribution.Path; end; end; procedure TJclInstallation.AddHelpToOpenHelp; begin if Target.OpenHelp.AddHelpFile(Distribution.FJclHlpHelpFileName, JclHelpIndexName) then WriteLog(Format(LineBreak + 'Added %s to %s Online Help', [Distribution.FJclHlpHelpFileName, Target.RADToolName])); end; {$ENDIF MSWINDOWS} function TJclInstallation.BplPath: string; begin Result := Tool.BPLPath[Target]; {$IFDEF MSWINDOWS} Result := PathGetShortName(Result); {$ENDIF MSWINDOWS} end; function TJclInstallation.DcpPath: string; begin Result := Tool.DCPPath[Target]; {$IFDEF MSWINDOWS} Result := PathGetShortName(Result); {$ENDIF MSWINDOWS} end; function TJclInstallation.CheckDirectories: Boolean; begin Result := not OptionSelected(ioJclPackages); if not Result then begin Result := True; if not DirectoryExists(BplPath) then begin WriteLog(Format(RsInvalidBplPath, [BplPath])); Result := False; end; if not DirectoryExists(DcpPath) then begin WriteLog(Format(RsInvalidDcpPath, [DcpPath])); Result := False; end; end; end; procedure TJclInstallation.CleanupRepository; begin if OptionSelected(ioJCL) then with Target.Repository do begin RemoveObjects(DialogsPath, ClxDialogFileName, BorRADToolRepositoryFormTemplate); {$IFDEF MSWINDOWS} RemoveObjects(DialogsPath, VclDialogFileName, BorRADToolRepositoryFormTemplate); RemoveObjects(DialogsPath, VclDlgSndFileName, BorRADToolRepositoryFormTemplate); {$ENDIF MSWINDOWS} end; end; function TJclInstallation.CompileLibraryUnits(const SubDir: string; Debug: Boolean): Boolean; var UnitList: TStrings; UnitType: string; LibDescriptor: string; SaveDir, UnitOutputDir: string; Path: string; function CompilationOptions: string; begin if FTarget.RADToolKind = brCppBuilder then begin Result := StringsToStr(Target.DCC32.Options, ' ') + ' '; Result := StringReplace(Result, '$(BCB)', Target.RootDir, [rfReplaceAll]); end else Result := ''; end; function CompileUnits: Boolean; {$IFDEF COMPILE_UNITS_SEPARATELY // gives better progress resolution } var I: Integer; begin Result := True; for I := 0 to UnitList.Count - 1 do begin Result := Target.DCC32.Execute({$IFNDEF KYLIX}CompilationOptions + {$ENDIF}UnitList[I]); Progress(1); if not Result then Break; end; end; {$ELSE} begin Result := Target.DCC32.Execute({$IFNDEF KYLIX}CompilationOptions + {$ENDIF}StringsToStr(UnitList, ' ')); Progress(UnitList.Count); end; {$ENDIF} begin if Debug then UnitType := 'debug '; LibDescriptor := Format(RsLibDescriptor, [SubDir, UnitType, Target.Name]); WriteLog(Format(LineBreak + 'Making %s', [LibDescriptor])); Tool.UpdateStatus(Format(RsCompilingMessage, [LibDescriptor])); Path := Format('%s' + PathSeparator + '%s', [Distribution.SourceDir, SubDir]); UnitList := Units[SubDir]; with Target.DCC32 do begin SetDefaultOptions; Options.Add('-D' + StringsToStr(Defines, ';')); Options.Add('-M'); if Target.RADToolKind = brCppBuilder then begin Options.Add('-D_RTLDLL;NO_STRICT;USEPACKAGES'); // $(SYSDEFINES) if Debug then begin Options.Add('-$Y+'); Options.Add('-$W'); Options.Add('-$O-'); Options.Add('-v'); UnitOutputDir := MakePath(Distribution.FLibDebugDirMask); AddPathOption('N2', MakePath(Distribution.FLibDirMask + PathSeparator + 'obj')); // .obj files end else begin Options.Add('-$YD'); Options.Add('-$W+'); Options.Add('-$O+'); UnitOutputDir := MakePath(Distribution.FLibDirMask); AddPathOption('N2', UnitOutputDir + PathSeparator + 'obj'); // .obj files end; Options.Add('-v'); Options.Add('-JPHNE'); Options.Add('--BCB'); AddPathOption('N0', UnitOutputDir); // .dcu files AddPathOption('O', Format(BCBIncludePath, [Distribution.SourceDir, Distribution.SourcePath])); AddPathOption('U', Format(BCBObjectPath, [Distribution.SourceDir, Distribution.SourcePath])); end else // Delphi begin if Debug then begin Options.Add('-$O-'); Options.Add('-$W+'); Options.Add('-$R+'); Options.Add('-$Q+'); Options.Add('-$D+'); Options.Add('-$L+'); Options.Add('-$Y+'); UnitOutputDir := MakePath(Distribution.FLibDebugDirMask); end else begin Options.Add('-$O+'); Options.Add('-$R-'); Options.Add('-$Q-'); Options.Add('-$C-'); Options.Add('-$D-'); UnitOutputDir := MakePath(Distribution.FLibDirMask); end; AddPathOption('N', UnitOutputDir); AddPathOption('U', Distribution.SourcePath); AddPathOption('R', Distribution.SourcePath); end; AddPathOption('I', Distribution.SourceDir); SaveDir := GetCurrentDir; Result := SetCurrentDir(Path); {$IFDEF WIN32} Win32Check(Result); {$ELSE} if Result then {$ENDIF} try WriteLog(''); WriteLog('Compiling .dcu files...'); Result := Result and CompileUnits; CopyResFiles(UnitOutputDir); if OptionSelected(ioJclCopyHppFiles) then begin Result := Result and CopyHppFiles(UnitList, Target.VclIncludeDir); WriteLog('Copying .hpp files...'); end; {$IFDEF KYLIX} Options.Add('-P'); // generate position independent code (PIC) WriteLog(''); WriteLog('Compiling dpu files...'); Result := Result and CompileUnits; {$ENDIF KYLIX} finally SetCurrentDir(SaveDir); end; end; if not Result then InstallFailedOn(LibDescriptor); end; procedure TJclInstallation.ConfigureBpr2Mak(const PackageFileName: string); var PackageDirectory: string; begin PackageDirectory := PathAddSeparator(ExtractFileDir(PackageFileName)); if clProj2Mak in Target.CommandLineTools then begin Target.Bpr2Mak.Options.Clear; Target.Bpr2Mak.Options.Add('-t' + ExtractRelativePath(PackageDirectory,Distribution.Path + Bcb2MakTemplate)); end; {$IFDEF KYLIX} SetEnvironmentVar('OBJDIR', LibObjDir); SetEnvironmentVar('BPILIBDIR', DcpPath); SetEnvironmentVar('BPLDIR', BplPath); {$ELSE KYLIX} if clMake in Target.CommandLineTools then begin Target.Make.Options.Clear; Target.Make.AddPathOption('DBPILIBDIR=', DcpPath); Target.Make.AddPathOption('DBPLDIR=', BplPath); if OptionSelected(ioJclCopyPackagesHppFiles) then Target.Make.AddPathOption('DHPPDIR=', Target.VclIncludeDir); end; {$ENDIF KYLIX} end; function TJclInstallation.Description(Option: TJediInstallOption): string; begin Result := InitData[Option].Caption; case Option of ioTarget: Result := Target.Description; ioJclCopyHppFiles: Result := Format(Result, [Target.VclIncludeDir]); ioJclCopyPackagesHppFiles: Result := Format(Result, [Target.VclIncludeDir]); end; end; {$IFDEF MSWINDOWS} procedure TJclInstallation.CopyFakeXmlRtlPackage; // replace missing xmlrtl.dcp in Delphi 2005 Personal by dummy package to allow expert installation begin { TODO : implement copying of fake xmlrtl.dcp to $(BDS)\Lib } end; {$ENDIF MSWINDOWS} function TJclInstallation.ExcludeEdition(ExcludeList: TStrings; Index: Integer; out Name: string): Boolean; var Editions: string; begin Name := ExcludeList[Index]; if Pos('=', Name) > 0 then Name := ExcludeList.Names[Index]; Editions := ExcludeList.Values[Name]; Result := (Editions = '') or (StrIPos(BorRADToolEditionIDs[Target.Edition], Editions) > 0); end; function TJclDistribution.GetExamplesDir: string; begin Result := Path + 'examples'; end; function DemoNameCompare(List: TStringList; Index1, Index2: Integer): Integer; var Name1, Name2: string; begin Name1 := ExtractFileName(List[Index1]); Name2 := ExtractFileName(List[Index2]); Result := CompareText(Name1, Name2); end; function TJclInstallation.GetDemoList: TStringList; begin if not Assigned(FDemos) then begin FDemos := TStringList.Create; EnumDirectories(Distribution.ExamplesDir, AddDemos); Demos.CustomSort(DemoNameCompare); end; Result := FDemos; end; function TJclDistribution.GetDemosPath: string; begin Result := PathAddSeparator(Path + 'examples'); end; function TJclDistribution.GetHint(Option: TJediInstallOption): string; begin if Ord(Option) < Ord(ioJclLast) then Result := InitData[Option].Hint; end; function TJclInstallation.GetProgressTotal: Integer; var Option: TJediInstallOption; begin Result := 0; if OptionSelected(ioJCL) then for Option := Succ(ioJCL) to ioJclLast do if OptionSelected(Option) then Inc(Result, ProgressWeight(Option)); end; function TJclInstallation.GetTool: IJediInstallTool; begin Result := Distribution.Tool; end; procedure TJclInstallation.BuildUnitList(const SubDir: string; Units: TStrings); var I, J: Integer; ExcludeList: TStringList; ExcludeListFileName: string; UnitName: string; FileMask: string; begin FileMask := Format('%s' + PathSeparator + '%s' + PathSeparator + '*.pas', [Distribution.SourceDir, SubDir]); BuildFileList(FileMask, faAnyFile, Units); // check for units not to compile ExcludeListFileName := MakePath(Format('%s' + PathSeparator + '%s.exc', [Distribution.FLibDirMask, SubDir])); if FileExists(ExcludeListFileName) then begin ExcludeList := TStringList.Create; try ExcludeList.LoadFromFile(ExcludeListFileName); for I := 0 to ExcludeList.Count - 1 do if ExcludeEdition(ExcludeList, I, UnitName) then begin J := Units.IndexOf(UnitName); if J <> Invalid then Units.Delete(J); end; finally ExcludeList.Free; end; end; for I := 0 to Units.Count -1 do Units[I] := Copy(Units[I], 1, Length(Units[I]) - Length('.pas')); end; function TJclInstallation.DemoOption(DemoIndex: Integer): TJediInstallOption; begin Result := TJediInstallOption(Ord(ioJclLast) + 1 + DemoIndex); end; function TJclInstallation.DemoOptionSelected(Index: Integer): Boolean; begin Result := OptionSelected(DemoOption(Index)); end; function TJclInstallation.GetDemoExclusionList: TStrings; var I: Integer; Strings: TStrings; FileName: string; begin if not Assigned(FDemoExclusionList) then begin FDemoExclusionList := TStringList.Create; {$IFDEF KYLIX} FileName := MakePath(Distribution.DemosPath + 'k%d.exc'); {$ELSE} FileName := MakePath(Distribution.DemosPath + '%s.exc'); {$ENDIF KYLIX} if FileExists(FileName) then begin FDemoExclusionList.LoadFromFile(FileName); Strings := TStringList.Create; try I := 0; while I < FDemoExclusionList.Count do begin if ExcludeEdition(FDemoExclusionList, I, FileName) then if ExtractFileExt(FileName) = '.exc' then begin Strings.LoadFromFile(Distribution.DemosPath + FileName); FDemoExclusionList.AddStrings(Strings); FDemoExclusionList.Delete(I); end else begin FDemoExclusionList[I] := FileName; Inc(I); end else FDemoExclusionList.Delete(I); end; finally Strings.Free; end; end; end; Result := FDemoExclusionList; end; function TJclInstallation.GetJclDcpPath: string; begin Result := Format('%slib\%s', [Distribution.Path, Target.VersionNumberStr]); end; function TJclInstallation.GetUnits(const SourceDir: string): TStrings; var I: Integer; begin I := FUnits.IndexOf(SourceDir); if I = Invalid then begin Result := TStringList.Create; try BuildUnitList(SourceDir, Result); except Result.Free; end; FUnits.AddObject(SourceDir, Result); end else Result := FUnits.Objects[I] as TStrings; end; function TJclInstallation.InitOptions: Boolean; var GUI: TObject; {$IFDEF MSWINDOWS} ExpertOptions: TJediInstallGUIOptions; {$ENDIF MSWINDOWS} InstallationNode, ProductNode, PackagesNode, ExpertsNode, DemosNode, MakeNode, EnvNode, HelpNode, RepositoryNode, MapCreateNode, MapLinkNode, BCBNode: TObject; RunTimeInstallation: Boolean; function AddNode(Parent: TObject; Option: TJediInstallOption; GUIOptions: TJediInstallGUIOptions = [goChecked]): TObject; begin if StoredOption(Option, goChecked in GUIOptions) then Include(GUIOptions, goChecked) else Exclude(GUIOptions, goChecked); Result := Tool.GUIAddOption(GUI, Parent, Option, Description(Option), GUIOptions); end; function AddDemoNode(Parent: TObject; Index: Integer; GUIOptions: TJediInstallGUIOptions = []): TObject; var Checked: Boolean; begin Checked := Distribution.FIniFile.ReadInteger(DemoSectionName, Demos[Index], 0) > 0; if Checked then Include(GUIOptions, goChecked) else Exclude(GUIOptions, goChecked); Result := Tool.GUIAddOption(GUI, Parent, DemoOption(Index), ExtractFileName(Demos[Index]), GUIOptions); end; procedure AddDemoNodes; var I: Integer; begin DemosNode := AddNode(ProductNode, ioJclMakeDemos, [goExpandable, goNoAutoCheck]); for I := 0 to Demos.Count - 1 do AddDemoNode(DemosNode, I); end; procedure AddMakeNodes(Parent: TObject; DebugSettings: Boolean); const Option: array[Boolean, Boolean] of TJediInstallOption = ( (ioJclMakeRelease, ioJclMakeReleaseVClx), (ioJclMakeDebug, ioJclMakeDebugVClx)); var Node: TObject; begin Node := AddNode(Parent, Option[DebugSettings, False], [goStandAloneParent, goChecked]); if Target.SupportsVisualCLX then AddNode(Node, Option[DebugSettings, True]); end; begin Result := Assigned(Target) and Target.Valid; if not Result then Exit; RunTimeInstallation := (Target.RadToolKind <> brBorlandDevStudio) or ((Target.VersionNumber >= 3) and (bpDelphi32 in Target.Personalities)); GUI := Tool.OptionGUI(Target); InstallationNode := AddNode(nil, ioTarget); //InstallationNode.StateIndex := 0; ProductNode := AddNode(InstallationNode, ioJCL); if RunTimeInstallation then begin AddNode(ProductNode, ioJclDefThreadSafe); AddNode(ProductNode, ioJclDefDropObsoleteCode); AddNode(ProductNode, ioJclDefMathPrecSingle, [goRadioButton]); AddNode(ProductNode, ioJclDefMathPrecDouble, [goRadioButton]); AddNode(ProductNode, ioJclDefMathPrecExtended, [goRadioButton, goChecked]); EnvNode := AddNode(ProductNode, ioJclEnv); AddNode(EnvNode, ioJclEnvLibPath); AddNode(EnvNode, ioJclEnvBrowsingPath); AddNode(EnvNode, ioJclEnvDebugDCUPath); end; if RunTimeInstallation then begin MakeNode := AddNode(ProductNode, ioJclMake, [goExpandable, goChecked]); AddMakeNodes(MakeNode, False); AddMakeNodes(MakeNode, True); if bpBCBuilder32 in Target.Personalities then AddNode(MakeNode, ioJclCopyHppFiles); {$IFDEF MSWINDOWS} { TODO : Help integration for BDS } if Target.RadToolKind <> brBorlandDevStudio then with Distribution do if (HlpHelpFileName <> '') or (ChmHelpFileName <> '') then begin HelpNode := AddNode(ProductNode, ioJclHelp); if HlpHelpFileName <> '' then AddNode(HelpNode, ioJclHelpHlp); if ChmHelpFileName <> '' then AddNode(HelpNode, ioJclHelpChm); end; { TODO : Object Repository access for BDS } if Target.RadToolKind <> brBorlandDevStudio then {$ENDIF MSWINDOWS} begin RepositoryNode := AddNode(ProductNode, ioJclExcDialog); {$IFDEF MSWINDOWS} AddNode(RepositoryNode, ioJclExcDialogVCL); AddNode(RepositoryNode, ioJclExcDialogVCLSnd); if Target.SupportsVisualCLX then {$ENDIF MSWINDOWS} AddNode(RepositoryNode, ioJclExcDialogCLX); end; end; PackagesNode := AddNode(ProductNode, ioJclPackages, [goStandAloneParent, goChecked]); if (bpBCBuilder32 in Target.Personalities) and RunTimeInstallation then begin if (Target.RadToolKind = brBorlandDevStudio) and (Target.VersionNumber >= 4) then begin BCBNode := AddNode(PackagesNode, ioJclDualPackages, [goStandAloneParent, goChecked]); AddNode(BCBNode, ioJclCopyPackagesHppFiles); end else AddNode(PackagesNode, ioJclCopyPackagesHppFiles); end; MapCreateNode := AddNode(PackagesNode, ioJclMapCreate, [goExpandable, goStandaloneParent, goNoAutoCheck]); {$IFDEF MSWINDOWS} MapLinkNode := AddNode(MapCreateNode, ioJclMapLink, [goExpandable, goStandaloneParent, goNoAutoCheck]); AddNode(MapLinkNode,ioJclMapDelete, [goNoAutoCheck]); if (Target.RadToolKind = brBorlandDevStudio) and (Target.VersionNumber = 3) and (Target.Edition = deStd) then CopyFakeXmlRtlPackage; { TODO : It has been reported that IDE experts don't work under Win98. Leave these options unchecked for Win9x/WinME until that has been examined. } if IsWinNT then ExpertOptions := [goChecked] else ExpertOptions := []; ExpertsNode := AddNode(PackagesNode, ioJclExperts, [goExpandable, goChecked]); if (Target.RadToolKind = brBorlandDevStudio) and (Target.VersionNumber <= 2) then // design packages are not loaded by C#Builder 1 and Delphi 8 AddNode(ExpertsNode, ioJclExpertsDLL, [goRadioButton, goChecked]) else if (Target.RadToolKind = brBorlandDevStudio) and (Target.VersionNumber >= 3) then // expert DLLs are unstable on Delphi 2005 and BDS 2006 // (problems while adding menu items in menu not yet loaded) AddNode(ExpertsNode, ioJclExpertsDesignPackages, [goRadioButton, goChecked]) else begin AddNode(ExpertsNode, ioJclExpertsDesignPackages, [goRadioButton, goChecked]); AddNode(ExpertsNode, ioJclExpertsDLL, [goRadioButton]); end; if RunTimeInstallation then begin AddNode(ExpertsNode, ioJclExpertDebug, ExpertOptions); AddNode(ExpertsNode, ioJclExpertAnalyzer, ExpertOptions); AddNode(ExpertsNode, ioJclExpertUses, ExpertOptions); AddNode(ExpertsNode, ioJclExpertSimdView, ExpertOptions); end; AddNode(ExpertsNode, ioJclExpertFavorite, ExpertOptions); AddNode(ExpertsNode, ioJclExpertVersionControl, [goNoAutoCheck]); if (Target.RadToolKind <> brBorlandDevStudio) and (Target.VersionNumber <= 6) then AddNode(ExpertsNode, ioJclExpertThreadNames, ExpertOptions); {$ENDIF MSWINDOWS} if RunTimeInstallation then AddDemoNodes; Tool.BPLPath[Target] := StoredBplPath; Tool.DCPPath[Target] := StoredDcpPath; end; function TJclInstallation.InstallSelectedOptions: Boolean; function BorRADToolVersionStr: string; begin Result := Format('%s Build %s ', [Target.Name, Target.IdeExeBuildNumber]); end; var Option: TJediInstallOption; begin Tool.UpdateStatus(Format(RsStatusMessage, [Target.Name])); WriteLog(StrPadRight(BorRADToolVersionStr, 44, '=')); Result := CheckDirectories; if Result then begin CleanupRepository; Defines.Clear; Target.MapCreate := False; Target.MapLink := False; Target.MapDelete := False; {$IFDEF MSWINDOWS} if Target is TJclBDSInstallation then TJclBDSInstallation(Target).DualPackageInstallation := False; {$ENDIF MSWINDOWS} for Option := ioJCL to ioJclLast do if OptionSelected(Option) then Result := Result and InstallOption(Option); end; WriteLog(''); end; function TJclInstallation.InstallOption(Option: TJediInstallOption): Boolean; begin Result := True; case Option of ioJclDefThreadSafe: Defines.Add('THREAD_SAFE'); ioJclDefDropObsoleteCode: Defines.Add('DROP_OBSOLETE_CODE'); ioJclDefMathPrecSingle: Defines.Add('MATH_SINGLE_PRECISION'); ioJclDefMathPrecDouble: Defines.Add('MATH_DOUBLE_PRECISION'); ioJclDefMathPrecExtended: Defines.Add('MATH_EXTENDED_PRECISION'); ioJclMapCreate: Target.MapCreate := True; ioJclMapLink: Target.MapLink := True; ioJclMapDelete: Target.MapDelete := True; ioJclEnvLibPath: if Target.AddToLibrarySearchPath(LibDir) and Target.AddToLibrarySearchPath(Distribution.SourceDir) then WriteLog(Format(LineBreak + 'Added "%s;%s" to library path.', [LibDir, Distribution.SourceDir])); ioJclEnvBrowsingPath: if Target.AddToLibraryBrowsingPath(Distribution.SourcePath) then WriteLog(Format(LineBreak + 'Added "%s" to library browsing path.', [Distribution.SourcePath])); ioJclEnvDebugDCUPath: if Target.AddToDebugDCUPath(DebugDcuDir) then WriteLog(Format(LineBreak + 'Added "%s" to Debug DCU Path.', [DebugDcuDir])); // ioJclMake: ioJclMakeRelease: Result := MakeUnits(False); // ioJclMakeReleaseVClx: handled with ioJclMakeRelease ioJclMakeDebug: Result := MakeUnits(True); // ioJclMakeDebugVClx: handled with ioJclMakeDebug // ioJclCopyHppFiles: handled by CompileLibraryUnits //{$IFDEF MSWINDOWS} //ioJclDualPackages: handled by CompilePackages and InstallExpert //{$ENDIF MSWINDOWS} ioJclPackages: Result := CompilePackages; {$IFDEF MSWINDOWS} // ioJclExperts: ioJclExperts..ioJclExpertVersionControl: Result := InstallExpert(Option); // ioJclCopyPackagesHppFiles: handled by InstallPackageSourceFile // ioJclExcDialog: ioJclExcDialogVCL: with Distribution do AddDialogToRepository(VclDialogName, FVclDialogFileName, FVclDialogIconFileName, BorRADToolRepositoryDesignerDfm); ioJclExcDialogVCLSnd: with Distribution do AddDialogToRepository(VclDialogNameSend, FVclDialogSendFileName, FVclDialogSendIconFileName, BorRADToolRepositoryDesignerDfm, FVclDialogFileName); {$ENDIF MSWINDOWS} ioJclExcDialogCLX: with Distribution do AddDialogToRepository(ClxDialogName, FClxDialogFileName, FClxDialogIconFileName, BorRADToolRepositoryDesignerXfm); {$IFDEF MSWINDOWS} // ioJclHelp: ioJclHelpHlp: AddHelpToOpenHelp; ioJclHelpChm: AddHelpToIdeTools; {$ENDIF MSWINDOWS} ioJclMakeDemos: MakeDemos; end; if not (Option in [ioJclMakeRelease, ioJclMakeDebug]) then Progress(ProgressWeight(Option)); end; function TJclInstallation.UninstallOption(Option: TJediInstallOption): Boolean; begin Result := True; case Option of ioJclEnvLibPath: if Target.RemoveFromLibrarySearchPath(LibDir) and Target.RemoveFromLibrarySearchPath(Distribution.SourceDir) then WriteLog(Format(LineBreak + 'Removed "%s;%s" from library path.', [LibDir, Distribution.SourceDir])); ioJclEnvBrowsingPath: if Target.RemoveFromLibraryBrowsingPath(Distribution.SourcePath) then WriteLog(Format(LineBreak + 'Removed "%s" from library browsing path.', [Distribution.SourcePath])); ioJclEnvDebugDCUPath: if Target.RemoveFromDebugDCUPath(DebugDcuDir) then WriteLog(Format(LineBreak + 'Removed "%s" from Debug DCU Path.', [DebugDcuDir])); // ioJclMake: ioJclMakeRelease: { TODO : Delete generated files }; ioJclMakeDebug: { TODO : Delete generated files }; ioJclCopyHppFiles: { TODO : Delete copied files }; ioJclPackages: Result := UninstallPackages; {$IFDEF MSWINDOWS} ioJclExperts..ioJclExpertVersionControl: Result := UninstallExpert(Option); // ioJclCopyPackagesHppFiles: // ioJclExcDialog: ioJclExcDialogVCL: with Distribution do RemoveDialogFromRepository(VclDialogName, VclDialogFileName); ioJclExcDialogVCLSnd: with Distribution do RemoveDialogFromRepository(VclDialogNameSend, VclDlgSndFileName); {$ENDIF MSWINDOWS} ioJclExcDialogCLX: with Distribution do RemoveDialogFromRepository(ClxDialogName, ClxDialogFileName); {$IFDEF MSWINDOWS} // ioJclHelp: ioJclHelpHlp: RemoveHelpFromOpenHelp; ioJclHelpChm: RemoveHelpFromIdeTools; ioJclMakeDemos: ; {$ENDIF MSWINDOWS} end; if not Distribution.Installing then if not (Option in [ioJclMakeRelease, ioJclMakeDebug]) then Progress(ProgressWeight(Option)); end; procedure TJclInstallation.InstallationStarted; begin with FDistribution do if Assigned(FOnStarting) then FOnStarting(Target); end; function TJclInstallation.InstallExpert( const Option: TJediInstallOption): Boolean; begin if Option in [Low(ExpertPaths)..High(ExpertPaths)] then begin if (Option = ioJclExperts) or OptionSelected(ioJclExpertsDesignPackages) then begin // dual packages installation is useless for design time packages {$IFDEF MSWINDOWS} if Target.RadToolKind = brBorlandDevStudio then TJclBDSInstallation(Target).DualPackageInstallation := False; {$ENDIF MSWINDOWS} Result := CompilePackage(FullPackageFileName(Target,ExpertPaths[Option]), True); end else Result := CompileExpert(FullLibraryFileName(Target, ExpertPaths[Option]), True); end else Result := False; end; procedure TJclInstallation.InstallationFinished; begin with FDistribution do if Assigned(FOnEnding) then FOnEnding(Target); end; procedure TJclInstallation.InstallFailedOn(const InstallObj: string); begin Tool.Dialog(Format(RsInstallFailed, [InstallObj, LogFileName]), dtError); end; {$IFDEF MSWINDOWS} function TJclInstallation.CompileExpert(const Name: string; InstallExpert: Boolean): Boolean; var ProjectFileName, ProjectBinaryFileName, ProjectDEFFileName, ProjectDescription: string; LibraryPeImage: TJclPeImage; ExportFuncList: TJclPeExportFuncList; Index: Integer; DEFFile: TStrings; FirstCompilationOk: Boolean; const WizardEntryPoint = 'INITWIZARD0001'; // note (outchy) : I don't know if the parameter signature is constant // if constant, the complete signature would be // @*@JCLWizardInit$qqsx56System@%DelphiInterface$t28Toolsapi@IBorlandIDEServices%pqqrx47System@%DelphiInterface$t19Toolsapi@IOTAWizard%$orpqqrv$v InternalEntryPoint = '@JCLWizardInit$'; begin ProjectFileName := PathAddSeparator(Distribution.Path) + Name; if InstallExpert then WriteLog(Format(LineBreak + 'Installing expert %s...', [ProjectFileName])) else WriteLog(Format(LineBreak + 'Compiling expert %s...', [ProjectFileName])); Tool.UpdateStatus(Format(RsStatusDetailMessage, [ExtractFileName(ProjectFileName), Target.Name])); if IsDelphiProject(ProjectFileName) and (bpDelphi32 in Target.Personalities) then begin if InstallExpert then Result := Target.InstallExpert(ProjectFileName, BplPath, JclDcpPath) else Result := Target.CompileProject(ProjectFileName, BplPath, JclDcpPath); end else if IsBCBProject(ProjectFileName) and (bpBCBuilder32 in Target.Personalities) then begin ConfigureBpr2Mak(ProjectFileName); // the compilation is done in 2 steps: // - first compilation without changes, we try to find the internal export name // for the wizard entry point function // - second compilation with creation of an alias between the internal export name // and the excepted export name ProjectDEFFileName := ChangeFileExt(ProjectFileName, CompilerExtensionDEF); // first compilation DEFFile := TStringList.Create; try // the linker doesn't like empty def files DEFFile.Add('EXPORTS'); DEFFile.SaveToFile(ProjectDEFFileName); finally DEFFile.Free; end; Result := Target.CompileProject(ProjectFileName, BplPath, JclDcpPath); if Result then begin WriteLog(LineBreak + 'First compilation ok'); LibraryPeImage := TJclPeImage.Create; try GetBPRFileInfo(ProjectFileName, ProjectBinaryFileName, @ProjectDescription); ProjectBinaryFileName := PathAddSeparator(BplPath) + ProjectBinaryFileName; WriteLog(Format(LineBreak + 'Analysing expert %s for entry point %s...', [ProjectBinaryFileName, WizardEntryPoint])); LibraryPeImage.FileName := ProjectBinaryFileName; ExportFuncList := LibraryPeImage.ExportList; FirstCompilationOk := Assigned(ExportFuncList.ItemFromName[WizardEntryPoint]); // the expected export name doesn't exist if not FirstCompilationOk then begin Result := False; WriteLog(LineBreak + 'Entry point not found'); // try to find the decorated entry point // export names for pascal functions are: // @UnitName@FunctionName$ParameterSignature for Index := 0 to ExportFuncList.Count - 1 do if Pos(StrUpper(InternalEntryPoint), StrUpper(ExportFuncList.Items[Index].Name)) > 0 then begin WriteLog(Format(LineBreak + 'Internal entry point found %s', [ExportFuncList.Items[Index].Name])); DEFFile := TStringList.Create; try DEFFile.Add('EXPORTS'); DEFFile.Add(Format('%s=%s', [WizardEntryPoint, ExportFuncList.Items[Index].Name])); DEFFile.SaveToFile(ProjectDEFFileName); finally DEFFile.Free; end; Result := True; Break; end; end else begin WriteLog(LineBreak + 'Entry point found, registering expert...'); Target.RegisterExpert(ProjectBinaryFileName, ProjectDescription); end; finally LibraryPeImage.Free; end; if Result and (not FirstCompilationOk) then begin // second compilation if InstallExpert then Result := Target.InstallExpert(ProjectFileName, BplPath, JclDcpPath) else Result := Target.CompileProject(ProjectFileName, BplPath, JclDcpPath); end else if not Result then WriteLog(LineBreak + 'Internal entry point not found'); end else WriteLog(LineBreak + 'First compilation failed'); end else Result := False; if Result then WriteLog('...done.') else InstallFailedOn(ProjectFileName); end; {$ENDIF MSWINDOWS} function TJclInstallation.CompilePackage(const Name: string; InstallPackage: Boolean): Boolean; var PackageFileName: string; {$IFNDEF KYLIX} DpkPackageFileName: string; {$ENDIF} begin PackageFileName := PathAddSeparator(Distribution.Path) + Name; if InstallPackage then WriteLog(Format(LineBreak + 'Installing package %s...', [PackageFileName])) else WriteLog(Format(LineBreak + 'Compiling package %s...', [PackageFileName])); Tool.UpdateStatus(Format(RsStatusDetailMessage, [ExtractFileName(PackageFileName), Target.Name])); if IsDelphiPackage(PackageFileName) and (bpDelphi32 in Target.Personalities) then begin if InstallPackage then Result := Target.InstallPackage(PackageFileName, BplPath, DcpPath) else begin {$IFNDEF KYLIX} if Target.RadToolKind = brBorlandDevStudio then (Target as TJclBDSInstallation).CleanPackageCache(BinaryFileName(BplPath, PackageFileName)); {$ENDIF KYLIX} Result := Target.CompilePackage(PackageFileName, BplPath, DcpPath); end; end else if IsBCBPackage(PackageFileName) and (bpBCBuilder32 in Target.Personalities) then begin ConfigureBpr2Mak(PackageFileName); {$IFDEF KYLIX} if InstallPackage then Result := Target.InstallPackage(PackageFileName, BplPath, DcpPath) else Result := Target.CompilePackage(PackageFileName, BplPath, DcpPath); {$ELSE} if Target.RadToolKind = brBorlandDevStudio then (Target as TJclBDSInstallation).CleanPackageCache(BinaryFileName(BplPath, PackageFileName)); // to satisfy JVCL (and eventually other libraries), create a .dcp file; // Note: it is put out to .bpl path to make life easier for JVCL DpkPackageFileName := ChangeFileExt(PackageFileName, SourceExtensionDelphiPackage); if InstallPackage then Result := ((not FileExists(DpkPackageFileName)) or Target.InstallPackage(DpkPackageFileName, BplPath, DcpPath)) and Target.InstallPackage(PackageFileName, BplPath, DcpPath) else Result := ((not FileExists(DpkPackageFileName)) or Target.CompilePackage(DpkPackageFileName, BplPath, DcpPath)) and Target.CompilePackage(PackageFileName, BplPath, DcpPath); {$ENDIF} end else begin Result := False; WriteLog(Format(LineBreak + 'No personality supports the extension %s', [ExtractFileExt(PackageFileName)])); end; if Result then WriteLog('...done.') else InstallFailedOn(PackageFileName); end; function TJclInstallation.CompilePackages: Boolean; begin {$IFDEF MSWINDOWS} if Target.RadToolKind = brBorlandDevStudio then TJclBDSInstallation(Target).DualPackageInstallation := OptionSelected(ioJclDualPackages); {$ENDIF MSWINDOWS} Result := CompilePackage(FullPackageFileName(Target, JclDpk), False); if Target.SupportsVisualCLX then Result := Result and CompilePackage(FullPackageFileName(Target, JclVClxDpk), False); if (Target.VersionNumber >= 6) or ((Target.RadToolKind = brBorlandDevStudio) and (Target.VersionNumber >= 3)) then Result := Result and CompilePackage(FullPackageFileName(Target, JclVclDpk), False); end; function TJclInstallation.LogFileName: string; begin Result := JclInstall.LogFileName(Target); end; function TJclInstallation.MakePath(const FormatStr: string): string; begin {$IFDEF KYLIX} Result := Format(FormatStr, [Target.VersionNumber]); {$ELSE ~KYLIX} Result := PathGetShortName(Format(FormatStr, [Target.VersionNumberStr])); {$ENDIF ~KYLIX} end; procedure TJclInstallation.MakeDemo(Index: Integer); var FileName: string; CfgFileName: string; Directory: string; begin FileName := Demos[Index]; Directory := Distribution.DemosPath + ExtractFileDir(FileName); FileName := ExtractFileName(FileName); WriteLog(Format(LineBreak + RsBuildingMessage, [FileName])); SetCurrentDir(Directory); CfgFileName := ChangeFileExt(FileName, '.cfg'); StringToFile(CfgFileName, Format( '-e%s' + AnsiLineBreak + // Exe output dir '-u%s' + AnsiLineBreak + // Unit directories '-i%s', // Include path [Distribution.BinDir, LibDir, Distribution.SourceDir])); Target.DCC32.Execute(FileName); FileDelete(CfgFileName); end; function TJclInstallation.MakeDemos: Boolean; var I: Integer; SaveDir: string; begin Tool.UpdateStatus(Format(RsBuildingDemosByTargetMessage, [Target.Name])); WriteLog(LineBreak + RsBuildingDemosMessage + LineBreak); Result := True; SaveDir := GetCurrentDir; for I := 0 to Demos.Count - 1 do if DemoOptionSelected(I) then MakeDemo(I); SetCurrentDir(SaveDir); end; function TJclInstallation.MakeUnits(Debug: Boolean): Boolean; var I: Integer; begin Result := True; for I := Low(JclSourceDirs) to High(JclSourceDirs) do begin {$IFDEF MSWINDOWS} if (JclSourceDirs[I] = 'visclx') and not (OptionSelected(ioJclMakeReleaseVClx) or OptionSelected(ioJclMakeDebugVClx)) then Continue; {$ENDIF MSWINDOWS} Result := Result and CompileLibraryUnits(JclSourceDirs[I], Debug); end; end; function TJclInstallation.OptionSelected(Option: TJediInstallOption): Boolean; begin Result := Tool.FeatureChecked(Ord(Option), Target); end; procedure TJclInstallation.Progress(Steps: Integer); begin Distribution.InstallProgress(Steps); end; function TJclInstallation.ProgressWeight(Option: TJediInstallOption): Integer; begin case Option of ioJclEnvLibPath, ioJclEnvBrowsingPath, ioJclEnvDebugDCUPath: Result := 1; ioJclMakeRelease, ioJclMakeDebug: begin Result := TotalUnitCount; {$IFDEF KYLIX} Result := Result * 2; // .dcu + .dpu {$ENDIF KYLIX} end; ioJclMakeReleaseVClx, ioJclMakeDebugVClx: Result := 0; ioJclCopyHppFiles: Result := 2; ioJclPackages: Result := 10; ioJclExpertDebug, ioJclExpertAnalyzer, ioJclExpertFavorite, ioJclExpertThreadNames, ioJclExpertUses, ioJclExpertSimdView, ioJclExpertVersionControl: Result := 5; ioJclCopyPackagesHppFiles: Result := 2; ioJclExcDialog, ioJclExcDialogVCL, ioJclExcDialogVCLSnd, ioJclExcDialogCLX, ioJclHelpHlp, ioJclHelpChm: Result := 1; ioJclMakeDemos: Result := 50; else Result := 0; end; end; procedure TJclInstallation.RemoveDialogFromRepository(const DialogName, DialogFileName: string); begin Target.Repository.RemoveObjects(DialogsPath, DialogFileName, BorRADToolRepositoryFormTemplate); WriteLog(Format(LineBreak + 'Removed %s.', [DialogName])); end; {$IFDEF MSWINDOWS} procedure TJclInstallation.RemoveHelpFromIdeTools; begin { TODO : Implement } end; procedure TJclInstallation.RemoveHelpFromOpenHelp; begin if Target.OpenHelp.RemoveHelpFile(Distribution.FJclHlpHelpFileName, JclHelpIndexName) then WriteLog(Format(LineBreak + 'Removed %s from %s Online Help', [Distribution.FJclHlpHelpFileName, Target.RADToolName])); end; {$ENDIF MSWINDOWS} function TJclInstallation.Run: Boolean; begin Result := True; if OptionSelected(ioJCL) then begin InstallationStarted; try Result := InstallSelectedOptions; finally InstallationFinished; end; end; SaveOptions; end; function TJclInstallation.Undo: Boolean; begin Result := True; if OptionSelected(ioJCL) then Result := UninstallSelectedOptions; SaveOptions; end; function TJclInstallation.UninstallPackage(const Name: string): Boolean; var PackageFileName: string; begin PackageFileName := Distribution.Path + Format(Name, [Target.VersionNumberStr]); {$IFNDEF KYLIX} if Target.RadToolKind = brBorlandDevStudio then (Target as TJclBDSInstallation).CleanPackageCache(BinaryFileName(StoredBPLPath, PackageFileName)); {$ENDIF KYLIX} Result := Target.UninstallPackage(PackageFileName, StoredBPLPath, StoredDCPPath); // delete DCP files that were created to bpl path (old behavior) FileDelete(PathAddSeparator(StoredBPLPath) + PathExtractFileNameNoExt(Name) + CompilerExtensionDCP); // delete DCP files that were created to target dcp path (old behavior) FileDelete(PathAddSeparator(Target.DCPOutputPath) + PathExtractFileNameNoExt(Name) + CompilerExtensionDCP); // delete BPI files that were created to target dcp path (old behavior) FileDelete(PathAddSeparator(Target.DCPOutputPath) + PathExtractFileNameNoExt(Name) + CompilerExtensionBPI); // delete LIB files that were created to target dcp path (old behaviour) FileDelete(PathAddSeparator(Target.DCPOutputPath) + PathExtractFileNameNoExt(Name) + CompilerExtensionLIB); { TODO : evtl. remove .HPP Files } if Result then WriteLog(Format(LineBreak + 'Removed package %s.', [Name])); end; function TJclInstallation.UninstallPackages: Boolean; begin Result := UninstallPackage(FullPackageFileName(Target, JclDpk)); if Target.SupportsVisualCLX then Result := Result and UninstallPackage(FullPackageFileName(Target, JclVClxDpk)); if Target.VersionNumber >= 6 then Result := Result and UninstallPackage(FullPackageFileName(Target, JclVclDpk)); end; {$IFDEF MSWINDOWS} function TJclInstallation.UninstallExpert(const Option: TJediInstallOption): Boolean; function OldExpertBPLFileName(const BaseName: string): string; const OldExperts: array[ioJclExpertDebug..ioJclExpertVersionControl] of string = ( 'JclDebugIde%s0.bpl', 'ProjectAnalyzer%s0.bpl', 'IdeOpenDlgFavorite%s0.bpl', 'ThreadNameExpert%s0.bpl', 'JediUses%s0.bpl', 'JclSIMDView%s.bpl', 'JclVersionControl'); var I: TJediInstallOption; begin with Target do for I := Low(OldExperts) to High(OldExperts) do if BaseName = ExpertPaths[I] then begin Result := PathAddSeparator(StoredBPLPath) + Format(OldExperts[I], [VersionNumberStr]); Break; end; end; var BaseName: string; BPLFileName: string; PackageFileName: string; LibraryFileName: string; begin Result := False; BaseName := ExpertPaths[Option]; // uninstall package if it exists PackageFileName := FullPackageFileName(Target, BaseName); LibraryFileName := FullLibraryFileName(Target, BaseName); if FileExists(Distribution.Path + PackageFileName) then begin Result := UninstallPackage(PackageFileName); // eventually remove old expert packages to avoid annoying package conflicts during IDE startup; // for simplicity, .dcp files are not handled BaseName := ExtractFileName(BaseName); BPLFileName := OldExpertBPLFileName(BaseName); FileDelete(BPLFileName); Target.IdePackages.RemovePackage(BPLFileName); end; if FileExists(Distribution.Path + LibraryFileName) then begin // delete DLL experts Result := Target.UninstallExpert(Distribution.Path + LibraryFileName, StoredBPLPath); end; end; {$ENDIF MSWINDOWS} function TJclInstallation.UninstallSelectedOptions: Boolean; function BorRADToolVersionStr: string; begin Result := Format('%s Build %s ', [Target.Name, Target.IdeExeBuildNumber]); end; var Option: TJediInstallOption; Success: Boolean; begin Result := True; Tool.UpdateStatus(Format(RsUninstallMessage, [Target.Name])); WriteLog(StrPadRight('Starting Uninstall process', 44, '.')); for Option := ioJCL to ioJclLast do if OptionSelected(Option) then begin // Don't stop uninstall process when one step fails Success := UninstallOption(Option); Result := Result and Success; end; WriteLog(''); end; procedure TJclInstallation.SaveDemoOption(Index: Integer); var Value: Integer; begin Value := Invalid; if OptionSelected(DemoOption(Index)) then Value := JclBase.JclVersionBuild; Distribution.FIniFile.WriteInteger(DemoSectionName, Demos[Index], Value); end; procedure TJclInstallation.SaveOption(Option: TJediInstallOption); var Value: Integer; begin Value := Invalid; if OptionSelected(Option) then Value := JclBase.JclVersionBuild; Distribution.FIniFile.WriteInteger(Target.Name, OptionToStr(Option), Value); end; procedure TJclInstallation.SaveOptions; var I: Integer; Option: TJediInstallOption; begin SaveOption(ioTarget); for Option := ioJCL to ioJclLast do SaveOption(Option); for I := 0 to Demos.Count - 1 do SaveDemoOption(I); Distribution.FIniFile.WriteString(Target.Name, 'BPL-Path', Tool.BPLPath[Target]); Distribution.FIniFile.WriteString(Target.Name, 'DCP-Path', Tool.DCPPath[Target]); end; function TJclInstallation.StoredBplPath: string; begin Result := Distribution.FIniFile.ReadString(Target.Name, 'BPL-Path', Target.BPLOutputPath); end; function TJclInstallation.StoredDcpPath: string; begin Result := Distribution.FIniFile.ReadString(Target.Name, 'DCP-Path', JclDcpPath); end; function TJclInstallation.StoredOption(Option: TJediInstallOption; Default: Boolean = True): Boolean; begin case Distribution.FIniFile.ReadInteger(Target.Name, OptionToStr(Option), 0) of Invalid: Result := False; 0: Result := Default; else Result := True; end; end; function TJclInstallation.TotalUnitCount: Integer; var I: Integer; begin Result := 0; for I := Low(JclSourceDirs) to High(JclSourceDirs) do begin {$IFDEF MSWINDOWS} if (JclSourceDirs[I] = 'visclx') and not (OptionSelected(ioJclMakeReleaseVClx) or OptionSelected(ioJclMakeDebugVClx)) then Continue; {$ENDIF MSWINDOWS} with Units[JclSourceDirs[I]] do Inc(Result, Count); end; end; procedure TJclInstallation.WriteLog(const Msg: string); begin if Assigned(FOnWriteLog) then FOnWriteLog(Msg); end; { TJclDistribution } constructor TJclDistribution.Create; begin inherited; FTargetInstalls := TObjectList.Create; FTargetInstalls.OwnsObjects := True; FIniFile := TMemIniFile.Create(ExtractFilePath(ParamStr(0)) + RsIniFileName); end; destructor TJclDistribution.Destroy; begin FTargetInstalls.Free; if Assigned(FIniFile) then begin FIniFile.UpdateFile; FreeAndNil(FIniFile); end; inherited; end; function TJclDistribution.CreateInstall(Target: TJclBorRADToolInstallation): Boolean; var Inst: TJclInstallation; begin if Supports(Target) then try Inst := TJclInstallation.Create(Self, Target); FTargetInstalls.Add(Inst); Inst.InitOptions; except end; Result := True; end; function TJclDistribution.DocFileName(const BaseFileName: string): string; const SDocFileMask = '%sdocs' + PathSeparator + '%s'; begin Result := Format(SDocFileMask, [FJclPath, BaseFileName]); end; function TJclDistribution.FeatureInfoFileName(FeatureID: Cardinal): string; begin Result := DocFileName(Format('%.7x.info', [FeatureID])); end; function TJclDistribution.GetTargetInstall(Installation: TJclBorRADToolInstallation): TJclInstallation; var I: Integer; begin for I := 0 to FTargetInstalls.Count - 1 do begin Result := TJclInstallation(FTargetInstalls[I]); if Result.Target = Installation then Exit; end; Result := nil; end; procedure TJclDistribution.InitInstallationTargets; begin if not Tool.GetBorRADToolInstallations.Iterate(CreateInstall) then raise EJediInstallInitFailure.CreateRes(@RsNoInstall); end; function TJclDistribution.InitInformation(const ApplicationFileName: string): Boolean; var I: Integer; ExceptDialogsPath: string; begin FJclPath := PathAddSeparator(ExpandFileName(PathExtractFileDirFixed(ApplicationFileName) + '..')); {$IFDEF MSWINDOWS} FJclPath := PathGetShortName(FJclPath); {$ENDIF MSWINDOWS} FLibDirMask := Format('%slib' + VersionDirExp, [FJclPath]); FLibDebugDirMask := FLibDirMask + PathSeparator + 'debug'; FLibObjDirMask := FLibDirMask + PathSeparator + 'obj'; FJclBinDir := FJclPath + 'bin'; FJclSourceDir := FJclPath + 'source'; FJclSourcePath := ''; for I := Low(JclSourceDirs) to High(JclSourceDirs) do FJclSourcePath := FJclSourcePath + Format('%s' + PathSeparator + '%s' + PathSep, [FJclSourceDir, JclSourceDirs[I]]); {$IFDEF MSWINDOWS} ExceptDialogsPath := PathGetShortName(FJclPath + DialogsPath); FClxDialogFileName := AnsiUpperCase(ExceptDialogsPath + ClxDialogFileName); {$ENDIF MSWINDOWS} {$IFDEF UNIX} ExceptDialogsPath := FJclPath + DialogsPath; FClxDialogFileName := ExceptDialogsPath + ClxDialogFileName; {$ENDIF UNIX} FClxDialogIconFileName := ChangeFileExt(FClxDialogFileName, '.ico'); {$IFDEF MSWINDOWS} FVclDialogFileName := AnsiUpperCase(ExceptDialogsPath + VclDialogFileName); FVclDialogSendFileName := AnsiUpperCase(ExceptDialogsPath + VclDlgSndFileName); FVclDialogIconFileName := ChangeFileExt(FVclDialogFileName, '.ico'); FVclDialogSendIconFileName := ChangeFileExt(FVclDialogSendFileName, '.ico'); {$ENDIF MSWINDOWS} FJclChmHelpFileName := FJclPath + JclChmHelpFile; FJclHlpHelpFileName := FJclPath + JclHlpHelpFile; if not FileExists(FJclChmHelpFileName) then FJclChmHelpFileName := ''; if not FileExists(FJclHlpHelpFileName) then FJclHlpHelpFileName := ''; {$IFDEF MSWINDOWS} // Reset ReadOnly flag for dialog forms FileSetAttr(FClxDialogFileName, faArchive); FileSetAttr(ChangeFileExt(FClxDialogFileName, '.xfm'), faArchive); FileSetAttr(FVclDialogFileName, faArchive); FileSetAttr(ChangeFileExt(FVclDialogFileName, '.dfm'), faArchive); FileSetAttr(FVclDialogSendFileName, faArchive); FileSetAttr(ChangeFileExt(FVclDialogSendFileName, '.dfm'), faArchive); Result := FileExists(FClxDialogFileName) and FileExists(FClxDialogIconFileName) and FileExists(FVclDialogFileName) and FileExists(FVclDialogIconFileName) {$ELSE ~MSWINDOWS} Result := True; {$ENDIF ~MSWINDOWS}; FJclReadmeFileName := DocFileName(RsReadmeFileName); if FileExists(FJclReadmeFileName) then Tool.Readme := FJclReadmeFileName; if not Result then raise EJediInstallInitFailure.CreateRes(@RsCantFindFiles); end; procedure TJclDistribution.InitProgress; var I: Integer; begin FProgress := 0; FProgressTotal := 0; for I := 0 to FTargetInstalls.Count - 1 do Inc(FProgressTotal, TJclInstallation(FTargetInstalls[I]).ProgressTotal); end; function TJclDistribution.Install: Boolean; var I: Integer; begin // installation validation Result := False; for I := 0 to FTargetInstalls.Count - 1 do if TJclInstallation(FTargetInstalls[I]).OptionSelected(ioJCL) and not TJclInstallation(FTargetInstalls[I]).OptionSelected(ioJclPackages) and (MessageDlg(RsPackageNodeNotSelected, mtWarning, [mbYes, mbNo], 0) <> mrYes) then Exit; FInstalling := True; // tell UninstallOption not to call Progress() Result := True; try InitProgress; for I := 0 to FTargetInstalls.Count - 1 do begin TJclInstallation(FTargetInstalls[I]).Undo; Result := Result and TJclInstallation(FTargetInstalls[I]).Run; end; finally Tool.UpdateStatus(''); FInstalling := False; end; end; function TJclDistribution.Uninstall: Boolean; var I: Integer; Success: Boolean; begin Result := True; try InitProgress; for I := 0 to FTargetInstalls.Count - 1 do begin Success := TJclInstallation(FTargetInstalls[I]).Undo; Result := Result and Success; end; finally Tool.UpdateStatus(''); end; end; procedure TJclDistribution.InstallProgress(Steps: Integer); begin if Steps > 0 then begin Inc(FProgress, Steps); ShowProgress; end; end; function TJclDistribution.ReadmeFileName: string; begin Result := FJclReadmeFileName; end; procedure TJclDistribution.SetOnWriteLog(Installation: TJclBorRADToolInstallation; Value: TTextHandler); begin TargetInstall[Installation].OnWriteLog := Value; end; procedure TJclDistribution.SetOnEnding(Value: TInstallationEvent); begin FOnEnding := Value; end; procedure TJclDistribution.SetOnProgress(Value: TInstallationProgressEvent); begin FOnProgress := Value; end; procedure TJclDistribution.SetOnStarting(Value: TInstallationEvent); begin FOnStarting := Value; end; procedure TJclDistribution.SetTool(const Value: IJediInstallTool); begin FTool := Value; InitInformation(ParamStr(0)); InitInstallationTargets; end; procedure TJclDistribution.ShowProgress; var Percent: Integer; begin if (FProgressTotal > 0) and Assigned(FOnProgress) then begin Percent := (FProgress * 100) div FProgressTotal; if Percent <> FProgressPercent then begin FProgressPercent := Percent; FOnProgress(Percent); end; end; end; function TJclDistribution.Supports(Target: TJclBorRADToolInstallation): Boolean; begin {$IFDEF KYLIX} Result := Target.VersionNumber = 3; {$ELSE ~KYLIX} case Target.RadToolKind of brDelphi : Result := Target.VersionNumber in [5, 6, 7]; brCppBuilder : Result := Target.VersionNumber in [5, 6]; brBorlandDevStudio : Result := Target.VersionNumber in [1, 2, 3, 4]; else Result := False; end; {$ENDIF ~KYLIX} end; // History: // $Log: JclInstall.pas,v $ // Revision 1.90 2006/02/09 13:57:33 outchy // Delete old compiler files // // Revision 1.89 2006/02/05 13:26:14 outchy // dcp, bpi and lib files are created in \lib\ver // // Revision 1.88 2006/02/02 20:33:39 outchy // Package cache cleaned // // Revision 1.87 2006/01/15 00:51:22 outchy // cvs support in version control expert // version control expert integration in the installer // // Revision 1.86 2006/01/13 16:52:00 outchy // Warning of packages are not installed. // // Revision 1.85 2006/01/06 18:15:15 outchy // hpp node moved as a child of the dual package node when supported // // Revision 1.84 2005/12/26 18:03:41 outchy // Enhanced bds support (including C#1 and D8) // Introduction of dll experts // Project types in templates // // Revision 1.83 2005/12/04 10:10:57 obones // Borland Developer Studio 2006 support // // Revision 1.82 2005/11/13 17:05:01 uschuster // some fixes for Kylix // // Revision 1.81 2005/11/12 19:00:32 outchy // map-files node moved inside the packages node. // // Revision 1.80 2005/11/10 23:59:50 outchy // Map-file operations not added when not runned on Windows. // // Revision 1.79 2005/11/10 22:16:31 outchy // Added creation/link/deletion of MAP files for packages. // // Revision 1.78 2005/11/08 00:18:32 outchy // Fixed AV when DCC32.exe is missing. // // Revision 1.77 2005/10/28 04:38:53 rrossmair // - fixes related to package uninstallation, and more // // Revision 1.76 2005/10/27 01:50:28 rrossmair // - sort demo list alphabethically // // Revision 1.75 2005/10/26 06:30:38 rrossmair // - TJclInstallation.UninstallExpert now also handles old expert package names // // Revision 1.74 2005/10/22 00:39:34 outchy // JclBaseExpert is now correctly uninstalled. // // Revision 1.73 2005/10/20 23:13:32 outchy // Experts are now generated by the package generator. // No WEAKPACKAGEUNIT in design-time packages. // // Revision 1.72 2005/10/18 23:09:56 rrossmair // - updated Installer for new package naming rules // // Revision 1.70 2005/09/23 22:46:31 rrossmair // - changed to ensure that TInstallation.Demos is assigned when needed; likewise DemoExclusionList // - some refactoring // // Revision 1.69 2005/09/18 20:13:10 rrossmair // - several additions/minor fixes // // Revision 1.68 2005/08/22 19:30:58 rrossmair // - TJclInstallation.BuildUnitList fault tolerance improved // // Revision 1.67 2005/08/22 02:08:40 rrossmair // - implemented ability to specify which demos are to be built // // Revision 1.66 2005/08/06 11:19:34 rrossmair // - demo building improved: handles exclusion files etc. // // Revision 1.65 2005/08/01 04:52:02 rrossmair // - (basic) support for compilation of examples // // Revision 1.64 2005/07/28 21:57:49 outchy // JEDI Installer can now install design-time packages for C++Builder 5 and 6 // // Revision 1.63 2005/03/24 20:41:32 rrossmair // - fixed installation progress computation. // // Revision 1.62 2005/03/23 04:28:49 rrossmair // - removed make -fBCB5-dcc32.cfg.mak (handled by build.exe now) // // Revision 1.61 2005/03/22 03:23:18 rrossmair // - fixed recent changes // // Revision 1.60 2005/03/21 11:09:49 obones // Now calls BCB5-dcc32.cfg.mak if required // // Revision 1.59 2005/03/21 04:03:58 rrossmair // - workarounds for DCC32 126 character path limit // // Revision 1.57 2005/03/16 18:11:33 rrossmair // - "Copy HPP files to ..." options now checked by default. // // Revision 1.56 2005/03/14 16:10:43 rrossmair // - compiler hints resolved // // Revision 1.55 2005/03/14 08:46:47 rrossmair // - check-in in preparation for release 1.95 // // Revision 1.54 2005/03/14 02:21:34 rrossmair // - changed Expert naming convention to include Delphi/BCB infix (D|C) // // Revision 1.53 2005/03/05 06:33:17 rrossmair // - support for some conditional defines added. // // Revision 1.52 2005/02/28 20:19:05 uschuster // changes for Uses wizard // // Revision 1.51 2005/02/23 08:32:30 rrossmair // - TJclInstallation: replaced Target.DCC.Options.Clear by Target.DCC.SetDefaultOptions. // Some cleanup. // // Revision 1.50 2005/02/05 05:16:18 rrossmair // - check-in for release 1.94.1.1802 // // Revision 1.49 2005/02/04 05:19:41 rrossmair // - some uninstall support finally functional // // Revision 1.48 2005/02/03 06:15:41 rrossmair // - fixed for Kylix // // Revision 1.47 2005/02/03 05:22:17 rrossmair // - more uninstall support (still unfinished) // // Revision 1.46 2004/12/23 05:32:28 rrossmair // - fixed for Kylix // // Revision 1.45 2004/12/23 05:09:26 rrossmair // - except dialog and help integration disabled for D 2005 // // Revision 1.44 2004/12/15 21:49:35 rrossmair // - denotes D2005 as supported now // // Revision 1.43 2004/12/08 18:25:07 rrossmair // - fixed TJclInstallation.StoredOption so that Default parameter gets evaluated // // Revision 1.42 2004/12/08 18:14:49 rrossmair // - all install options now selected by default // - minor fixes // // Revision 1.41 2004/11/18 10:14:54 rrossmair // - changes for release 1.93 // // Revision 1.40 2004/11/17 06:34:01 marquardt // suppress warning about unused UninstallOption // // Revision 1.39 2004/11/14 12:08:05 rrossmair // - some precautions & minor fixes // // Revision 1.38 2004/11/14 05:55:55 rrossmair // - installer refactoring (continued) // // Revision 1.37 2004/11/10 05:18:11 rrossmair // - fixed for Kylix // // Revision 1.36 2004/11/09 07:51:37 rrossmair // - installer refactoring (incomplete) // end.