mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 05:39:34 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1249 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			1249 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
 ***************************************************************************
 | 
						|
 *                                                                         *
 | 
						|
 *   This source is free software; you can redistribute it and/or modify   *
 | 
						|
 *   it under the terms of the GNU General Public License as published by  *
 | 
						|
 *   the Free Software Foundation; either version 2 of the License, or     *
 | 
						|
 *   (at your option) any later version.                                   *
 | 
						|
 *                                                                         *
 | 
						|
 *   This code is distributed in the hope that it will be useful, but      *
 | 
						|
 *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 | 
						|
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 | 
						|
 *   General Public License for more details.                              *
 | 
						|
 *                                                                         *
 | 
						|
 *   A copy of the GNU General Public License is available on the World    *
 | 
						|
 *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
 | 
						|
 *   obtain it by writing to the Free Software Foundation,                 *
 | 
						|
 *   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        *
 | 
						|
 *                                                                         *
 | 
						|
 ***************************************************************************
 | 
						|
 | 
						|
  Author: Mattias Gaertner
 | 
						|
  Converted to lfm by: Matthijs Willemstein
 | 
						|
  Quickoptions added by: Giuliano Colla
 | 
						|
  Then extensively modified by: Juha Manninen
 | 
						|
   - added support for Build Profiles which extend the idea of Quick Options.
 | 
						|
   - changed UI to be less weird and comply better with UI design norms.
 | 
						|
   - changed object structure to keep it logical and to avoid duplicate data.
 | 
						|
 | 
						|
  Abstract:
 | 
						|
    Defines settings for the "Build Lazarus" function of the IDE.
 | 
						|
    TConfigureBuildLazarusDlg is used to edit the build options.
 | 
						|
 | 
						|
    The BuildLazarus function will build the lazarus parts.
 | 
						|
 | 
						|
    Building occurs only with options defined in the Detail Page.
 | 
						|
    Profiles are just used to set options there. Therefore beginners can
 | 
						|
    use default profiles and don't need to touch the Detail Page.
 | 
						|
    Advanced users can define their own profiles for example for cross compiling.
 | 
						|
}
 | 
						|
unit BuildLazDialog;
 | 
						|
 | 
						|
{$mode objfpc}{$H+}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  Classes, SysUtils, LCLProc, LConvEncoding, Forms, Controls, LCLType, LCLIntf,
 | 
						|
  Graphics, GraphType, StdCtrls, ExtCtrls, Buttons, FileUtil, LazUTF8,
 | 
						|
  LazLogger, lazutf8classes, Dialogs, InterfaceBase, Themes, CheckLst, Menus,
 | 
						|
  ComCtrls, DividerBevel, DefineTemplates,
 | 
						|
  // IDEIntf
 | 
						|
  LazIDEIntf, IDEMsgIntf, IDEHelpIntf, IDEImagesIntf, IDEWindowIntf, IDEDialogs,
 | 
						|
  PackageIntf,
 | 
						|
  // IDE
 | 
						|
  LazarusIDEStrConsts, TransferMacros, LazConf, IDEProcs, DialogProcs, MainBar,
 | 
						|
  InputHistory, ExtToolDialog, ExtToolEditDlg, EnvironmentOpts,
 | 
						|
  {$IFDEF win32}
 | 
						|
  CodeToolManager, // added for windres workaround
 | 
						|
  {$ENDIF}
 | 
						|
  ApplicationBundle, CompilerOptions, BuildProfileManager,
 | 
						|
  GenericListEditor, GenericCheckList, PackageSystem, PackageDefs;
 | 
						|
 | 
						|
type
 | 
						|
 | 
						|
  TBuildLazarusFlag = (
 | 
						|
    blfDontBuild,           // skip all building, only cleaning
 | 
						|
    blfOnlyIDE,             // skip all but IDE (for example build IDE, but not packages, not lazbuild, ...)
 | 
						|
    blfDontClean,           // ignore clean up option in profile
 | 
						|
    blfUseMakeIDECfg,       // append @idemake.cfg
 | 
						|
    blfReplaceExe,          // ignore OSLocksExecutables and do not create lazarus.new.exe
 | 
						|
    blfBackupOldExe         // rename existing lazarus exe to lazarus.old
 | 
						|
    );
 | 
						|
  TBuildLazarusFlags = set of TBuildLazarusFlag;
 | 
						|
 | 
						|
  { TConfigureBuildLazarusDlg }
 | 
						|
 | 
						|
  TConfigureBuildLazarusDlg = class(TForm)
 | 
						|
    CleanAllRadioButton: TRadioButton;
 | 
						|
    CleanAutoRadioButton: TRadioButton;
 | 
						|
    CleanCommonRadioButton: TRadioButton;
 | 
						|
    CleanOnceCheckBox: TCheckBox;
 | 
						|
    CommonsDividerBevel: TDividerBevel;
 | 
						|
    ConfirmBuildCheckBox: TCheckBox;
 | 
						|
    DefinesButton: TButton;
 | 
						|
    DefinesLabel: TLabel;
 | 
						|
    DefinesListBox: TCheckListBox;
 | 
						|
    CancelButton: TBitBtn;
 | 
						|
    CBLDBtnPanel: TPanel;
 | 
						|
    BuildProfileComboBox: TComboBox;
 | 
						|
    CompileButton: TBitBtn;
 | 
						|
    CompileAdvancedButton: TBitBtn;
 | 
						|
    InhTreeView: TTreeView;
 | 
						|
    InhNoteLabel: TLabel;
 | 
						|
    LCLWidgetTypeLabel: TLabel;
 | 
						|
    LCLWidgetTypeComboBox: TComboBox;
 | 
						|
    OptionsLabel: TLabel;
 | 
						|
    OptionsMemo: TMemo;
 | 
						|
    CleanUpGroupBox: TGroupBox;
 | 
						|
    PageControl1: TPageControl;
 | 
						|
    RestartAfterBuildCheckBox: TCheckBox;
 | 
						|
    ShowOptsMenuItem: TMenuItem;
 | 
						|
    DetailsPanel: TPanel;
 | 
						|
    HelpButton: TBitBtn;
 | 
						|
    BuildProfileLabel: TLabel;
 | 
						|
    OptionsPopupMenu: TPopupMenu;
 | 
						|
    Panel2: TPanel;
 | 
						|
    SaveSettingsButton: TBitBtn;
 | 
						|
    BuildProfileButton: TButton;
 | 
						|
    BuildTabSheet: TTabSheet;
 | 
						|
    InfoTabSheet: TTabSheet;
 | 
						|
    TargetCPUComboBox: TComboBox;
 | 
						|
    TargetCPULabel: TLabel;
 | 
						|
    TargetDirectoryButton: TButton;
 | 
						|
    TargetDirectoryComboBox: TComboBox;
 | 
						|
    TargetDirectoryLabel: TLabel;
 | 
						|
    TargetOSComboBox: TComboBox;
 | 
						|
    TargetOSLabel: TLabel;
 | 
						|
    UpdateRevisionIncCheckBox: TCheckBox;
 | 
						|
    procedure BuildProfileButtonClick(Sender: TObject);
 | 
						|
    procedure BuildProfileComboBoxSelect(Sender: TObject);
 | 
						|
    procedure CompileAdvancedButtonClick(Sender: TObject);
 | 
						|
    procedure CompileButtonClick(Sender: TObject);
 | 
						|
    procedure DefinesButtonClick(Sender: TObject);
 | 
						|
    procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
 | 
						|
    procedure FormCreate(Sender: TObject);
 | 
						|
    procedure FormResize(Sender: TObject);
 | 
						|
    procedure FormShow(Sender: TObject);
 | 
						|
    procedure HelpButtonClick(Sender: TObject);
 | 
						|
    procedure ShowOptsMenuItemClick(Sender: TObject);
 | 
						|
    procedure SaveSettingsButtonClick(Sender: TObject);
 | 
						|
    procedure TargetDirectoryButtonClick(Sender: TObject);
 | 
						|
  private
 | 
						|
    // Data is copied by caller before and after opening this dialog.
 | 
						|
    fProfiles: TBuildLazarusProfiles;
 | 
						|
    fUpdatingProfileCombo: Boolean;
 | 
						|
    fImageIndexPackage: Integer;
 | 
						|
    fImageIndexRequired: Integer;
 | 
						|
    fImageIndexInherited: Integer;
 | 
						|
    procedure PrepareClose;
 | 
						|
    procedure SetupInfoPage;
 | 
						|
    procedure UpdateInheritedTree;
 | 
						|
  public
 | 
						|
    constructor Create(TheOwner: TComponent); overload; reintroduce;
 | 
						|
    destructor Destroy; override;
 | 
						|
    procedure CopyProfileToUI(AProfile: TBuildLazarusProfile);
 | 
						|
    procedure CopyUIToProfile(AProfile: TBuildLazarusProfile);
 | 
						|
    procedure UpdateProfileNamesUI;
 | 
						|
  end;
 | 
						|
 | 
						|
function ShowConfigureBuildLazarusDlg(AProfiles: TBuildLazarusProfiles): TModalResult;
 | 
						|
 | 
						|
function MakeLazarus(Profile: TBuildLazarusProfile;
 | 
						|
  ExternalTools: TBaseExternalToolList; Macros: TTransferMacroList;
 | 
						|
  const PackageOptions, CompilerPath, MakePath: string;
 | 
						|
  Flags: TBuildLazarusFlags; var ProfileChanged: boolean): TModalResult;
 | 
						|
 | 
						|
function CreateIDEMakeOptions(Profile: TBuildLazarusProfile;
 | 
						|
  Macros: TTransferMacroList; const PackageOptions: string;
 | 
						|
  Flags: TBuildLazarusFlags; var ExtraOptions: string;
 | 
						|
  out UpdateRevisionInc: boolean; out OutputDirRedirected: boolean;
 | 
						|
  out TargetFilename: string): TModalResult;
 | 
						|
 | 
						|
function SaveIDEMakeOptions(Profile: TBuildLazarusProfile;
 | 
						|
  Macros: TTransferMacroList;
 | 
						|
  const PackageOptions: string; Flags: TBuildLazarusFlags): TModalResult;
 | 
						|
 | 
						|
function GetMakeIDEConfigFilename: string;
 | 
						|
function GetBackupExeFilename(Filename: string): string;
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
{$R *.lfm}
 | 
						|
 | 
						|
const
 | 
						|
  DefaultIDEMakeOptionFilename = 'idemake.cfg';
 | 
						|
 | 
						|
function ShowConfigureBuildLazarusDlg(AProfiles: TBuildLazarusProfiles): TModalResult;
 | 
						|
// mrOk=save
 | 
						|
// mrYes=save and compile
 | 
						|
// mrAll=save and compile all selected profiles
 | 
						|
var
 | 
						|
  ConfigBuildLazDlg: TConfigureBuildLazarusDlg;
 | 
						|
begin
 | 
						|
  Result := mrCancel;
 | 
						|
  ConfigBuildLazDlg := TConfigureBuildLazarusDlg.Create(nil);
 | 
						|
  try
 | 
						|
    ConfigBuildLazDlg.fProfiles.Assign(AProfiles); // Copy profiles to dialog.
 | 
						|
    Result := ConfigBuildLazDlg.ShowModal;
 | 
						|
    if Result in [mrOk,mrYes,mrAll] then
 | 
						|
      AProfiles.Assign(ConfigBuildLazDlg.fProfiles); // Copy profiles back from dialog.
 | 
						|
  finally
 | 
						|
    ConfigBuildLazDlg.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function MakeLazarus(Profile: TBuildLazarusProfile;
 | 
						|
  ExternalTools: TBaseExternalToolList; Macros: TTransferMacroList;
 | 
						|
  const PackageOptions, CompilerPath, MakePath: string;
 | 
						|
  Flags: TBuildLazarusFlags; var ProfileChanged: boolean): TModalResult;
 | 
						|
 | 
						|
  procedure ApplyCleanOnce;
 | 
						|
  begin
 | 
						|
    if not Profile.CleanOnce then exit;
 | 
						|
    if Profile.IdeBuildMode=bmBuild then exit;
 | 
						|
    Profile.IdeBuildMode:=bmBuild;
 | 
						|
    ProfileChanged:=true;
 | 
						|
  end;
 | 
						|
 | 
						|
  function CheckDirectoryWritable(Dir: string): boolean;
 | 
						|
  begin
 | 
						|
    if DirectoryIsWritableCached(Dir) then exit(true);
 | 
						|
    Result:=false;
 | 
						|
    IDEMessageDialog(lisBuildingLazarusFailed,
 | 
						|
               Format(lisThisSetOfOptionsToBuildLazarusIsNotSupportedByThis,
 | 
						|
                      [LineEnding, '"', Dir, '"', LineEnding]),
 | 
						|
               mtError,[mbCancel]);
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure CleanLazarusSrcDir(Dir: string; Recursive: boolean = true);
 | 
						|
  var
 | 
						|
    FileInfo: TSearchRec;
 | 
						|
    Ext: String;
 | 
						|
    Filename: TFilename;
 | 
						|
  begin
 | 
						|
    Dir:=AppendPathDelim(TrimFilename(Dir));
 | 
						|
    if FindFirstUTF8(Dir+AllFilesMask,faAnyFile,FileInfo)=0 then begin
 | 
						|
      repeat
 | 
						|
        if (FileInfo.Name='') or (FileInfo.Name='.') or (FileInfo.Name='..')
 | 
						|
        or (FileInfo.Name='.svn') or (FileInfo.Name='.git')
 | 
						|
        then
 | 
						|
          continue;
 | 
						|
        Filename:=Dir+FileInfo.Name;
 | 
						|
        if faDirectory and FileInfo.Attr>0 then
 | 
						|
        begin
 | 
						|
          if Recursive then
 | 
						|
            CleanLazarusSrcDir(Filename)
 | 
						|
        end
 | 
						|
        else begin
 | 
						|
          Ext:=LowerCase(ExtractFileExt(FileInfo.Name));
 | 
						|
          if (Ext='.ppu') or (Ext='.o') or (Ext='.rst') then begin
 | 
						|
            if not DeleteFileUTF8(Filename) then
 | 
						|
              debugln(['CleanLazarusSrcDir failed to delete file "',Filename,'"']);
 | 
						|
          end;
 | 
						|
        end;
 | 
						|
      until FindNextUTF8(FileInfo)<>0;
 | 
						|
    end;
 | 
						|
    FindCloseUTF8(FileInfo);
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure CheckRevisionInc;
 | 
						|
  var
 | 
						|
    RevisionIncFile: String;
 | 
						|
    sl: TStringList;
 | 
						|
  begin
 | 
						|
    RevisionIncFile:=AppendPathDelim(EnvironmentOptions.GetParsedLazarusDirectory)+'ide'+PathDelim+'revision.inc';
 | 
						|
    if not FileExistsUTF8(RevisionIncFile) then begin
 | 
						|
      debugln(['Note: revision.inc file missing: ',RevisionIncFile]);
 | 
						|
      sl:=TStringList.Create;
 | 
						|
      sl.Add('// Created by lazbuild');
 | 
						|
      sl.Add('const RevisionStr = '''+LazarusVersionStr+''';');
 | 
						|
      try
 | 
						|
        sl.SaveToFile(RevisionIncFile);
 | 
						|
      except
 | 
						|
        on E: Exception do begin
 | 
						|
          debugln(['Note: can not write ',RevisionIncFile,': ',E.Message]);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
      sl.Free;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure RestoreBackup(LazExeFilename: string);
 | 
						|
  var
 | 
						|
    BackupFilename: String;
 | 
						|
  begin
 | 
						|
    if FileExistsUTF8(LazExeFilename) then begin
 | 
						|
      if not DeleteFileUTF8(LazExeFilename) then begin
 | 
						|
        debugln(['Building IDE failed. Can not delete "',LazExeFilename,'"']);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    BackupFilename:=GetBackupExeFilename(LazExeFilename);
 | 
						|
    if FileExistsUTF8(BackupFilename) then begin
 | 
						|
      if not RenameFileUTF8(BackupFilename,LazExeFilename) then begin
 | 
						|
        debugln(['Building IDE failed. Can not restore backup file "',BackupFilename,'" to "',LazExeFilename,'"']);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
var
 | 
						|
  Tool: TExternalToolOptions;
 | 
						|
  ExtraOptions: String;
 | 
						|
  WorkingDirectory: String;
 | 
						|
  OutputDirRedirected, UpdateRevisionInc: boolean;
 | 
						|
  IdeBuildMode: TIdeBuildMode;
 | 
						|
  CmdLineParams: String;
 | 
						|
  Dir: String;
 | 
						|
  LazExeFilename: string;
 | 
						|
begin
 | 
						|
  Result:=mrCancel;
 | 
						|
 | 
						|
  if LazarusIDE<>nil then
 | 
						|
    LazarusIDE.MainBarSubTitle:=Profile.Name;
 | 
						|
  IdeBuildMode:=Profile.IdeBuildMode;
 | 
						|
 | 
						|
  Tool:=TExternalToolOptions.Create;
 | 
						|
  try
 | 
						|
    // setup external tool
 | 
						|
    Tool.Filename:=MakePath;
 | 
						|
    Tool.EnvironmentOverrides.Values['LCL_PLATFORM']:=
 | 
						|
      LCLPlatformDirNames[Profile.TargetPlatform];
 | 
						|
    Tool.EnvironmentOverrides.Values['LANG']:= 'en_US';
 | 
						|
    if CompilerPath<>'' then
 | 
						|
      Tool.EnvironmentOverrides.Values['PP']:=CompilerPath;
 | 
						|
    if (Tool.Filename<>'') and (not FileExistsUTF8(Tool.Filename)) then
 | 
						|
      Tool.Filename:=FindDefaultExecutablePath(Tool.Filename);
 | 
						|
    if (Tool.Filename='') or (not FileExistsUTF8(Tool.Filename)) then begin
 | 
						|
      Tool.Filename:=FindDefaultMakePath;
 | 
						|
      if (Tool.Filename='') or (not FileExistsUTF8(Tool.Filename)) then begin
 | 
						|
        IDEMessageDialog(lisMakeNotFound,
 | 
						|
                   Format(lisTheProgramMakeWasNotFoundThisToolIsNeededToBuildLa,
 | 
						|
                          ['"', '"', LineEnding, LineEnding]),
 | 
						|
                   mtError,[mbCancel]);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    // add -w option to print leaving/entering messages of "make"
 | 
						|
    CmdLineParams:=' -w';
 | 
						|
    // append target OS
 | 
						|
    if Profile.TargetOS<>'' then
 | 
						|
      CmdLineParams+=' OS_TARGET='+Profile.FPCTargetOS;
 | 
						|
    // append target CPU
 | 
						|
    if Profile.TargetCPU<>'' then
 | 
						|
      CmdLineParams+=' CPU_TARGET='+Profile.FPCTargetCPU;
 | 
						|
 | 
						|
    Tool.ScanOutputForFPCMessages:=true;
 | 
						|
    Tool.ScanOutputForMakeMessages:=true;
 | 
						|
 | 
						|
    // clean up
 | 
						|
    if (IdeBuildMode<>bmBuild) and (not (blfDontClean in Flags)) then begin
 | 
						|
      WorkingDirectory:=EnvironmentOptions.GetParsedLazarusDirectory;
 | 
						|
      if not CheckDirectoryWritable(WorkingDirectory) then exit(mrCancel);
 | 
						|
 | 
						|
      if (IdeBuildMode=bmCleanAllBuild) and (not (blfOnlyIDE in Flags)) then begin
 | 
						|
        // clean all lazarus source directories
 | 
						|
        // Note: Some installations put the fpc units into the lazarus directory
 | 
						|
        //       => clean only the known directories
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory,false);
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'examples');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'components');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'units');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'ide');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'packager');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'lcl');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'ideintf');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'tools');
 | 
						|
        CleanLazarusSrcDir(WorkingDirectory+PathDelim+'test');
 | 
						|
 | 
						|
        // clean config directory
 | 
						|
        CleanLazarusSrcDir(GetPrimaryConfigPath+PathDelim+'units');
 | 
						|
 | 
						|
        // clean custom target directory
 | 
						|
        if Profile.TargetDirectory<>'' then begin
 | 
						|
          Dir:=Profile.GetParsedTargetDirectory(Macros);
 | 
						|
          if (Dir<>'') and DirPathExists(Dir) then
 | 
						|
            CleanLazarusSrcDir(Dir);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
 | 
						|
      // call make to clean up
 | 
						|
      Tool.Title:=lisCleanLazarusSource;
 | 
						|
      Tool.WorkingDirectory:=WorkingDirectory;
 | 
						|
      if (IdeBuildMode=bmCleanBuild) or (blfOnlyIDE in Flags) then
 | 
						|
        Tool.CmdLineParams:='cleanide'
 | 
						|
      else
 | 
						|
        Tool.CmdLineParams:='cleanlaz';
 | 
						|
      Tool.CmdLineParams:=Tool.CmdLineParams+CmdLineParams;
 | 
						|
      Result:=ExternalTools.Run(Tool,Macros,false);
 | 
						|
      if Result<>mrOk then exit;
 | 
						|
 | 
						|
      ApplyCleanOnce;
 | 
						|
    end;
 | 
						|
 | 
						|
    // build IDE
 | 
						|
    if not (blfDontBuild in Flags) then begin
 | 
						|
      WorkingDirectory:=EnvironmentOptions.GetParsedLazarusDirectory;
 | 
						|
      if blfDontClean in Flags then
 | 
						|
        IdeBuildMode:=bmBuild;
 | 
						|
      Tool.Title:=lisIDE;
 | 
						|
      Tool.WorkingDirectory:=WorkingDirectory;
 | 
						|
      if IdeBuildMode=bmBuild then
 | 
						|
        Tool.CmdLineParams:='idepkg'
 | 
						|
      else
 | 
						|
        Tool.CmdLineParams:='cleanide ide';
 | 
						|
      // append extra Profile
 | 
						|
      ExtraOptions:='';
 | 
						|
      Result:=CreateIDEMakeOptions(Profile,Macros,PackageOptions,Flags,
 | 
						|
                               ExtraOptions,UpdateRevisionInc,OutputDirRedirected,
 | 
						|
                               LazExeFilename);
 | 
						|
      if Result<>mrOk then exit;
 | 
						|
 | 
						|
      if (not OutputDirRedirected)
 | 
						|
      and (not CheckDirectoryWritable(WorkingDirectory)) then
 | 
						|
        exit(mrCancel);
 | 
						|
 | 
						|
      if ExtraOptions<>'' then
 | 
						|
        Tool.EnvironmentOverrides.Values['OPT'] := ExtraOptions;
 | 
						|
      if not UpdateRevisionInc then begin
 | 
						|
        CheckRevisionInc;
 | 
						|
        Tool.EnvironmentOverrides.Values['USESVN2REVISIONINC'] := '0';
 | 
						|
      end;
 | 
						|
      Tool.CmdLineParams:=Tool.CmdLineParams+CmdLineParams;
 | 
						|
      // run
 | 
						|
      Result:=ExternalTools.Run(Tool,Macros,false);
 | 
						|
      // clean only once. If building failed the user must first fix the error
 | 
						|
      // before a clean build is needed.
 | 
						|
      ApplyCleanOnce;
 | 
						|
      if Result<>mrOk then begin
 | 
						|
        // build failed: restore backup of lazarus.exe
 | 
						|
        RestoreBackup(LazExeFilename);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    Result:=mrOk;
 | 
						|
  finally
 | 
						|
    Tool.Free;
 | 
						|
    if LazarusIDE<>nil then
 | 
						|
      LazarusIDE.MainBarSubTitle:='';
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
function CreateIDEMakeOptions(Profile: TBuildLazarusProfile;
 | 
						|
  Macros: TTransferMacroList; const PackageOptions: string;
 | 
						|
  Flags: TBuildLazarusFlags; var ExtraOptions: string;
 | 
						|
  out UpdateRevisionInc: boolean; out OutputDirRedirected: boolean;
 | 
						|
  out TargetFilename: string): TModalResult;
 | 
						|
 | 
						|
  procedure BackupExe(var ExeFilename: string);
 | 
						|
  var
 | 
						|
    Ext: String;
 | 
						|
    BackupFilename: String;
 | 
						|
    Backup2Filename: String;
 | 
						|
    AltFilename: String;
 | 
						|
  begin
 | 
						|
    if not FileExistsUTF8(ExeFilename) then exit;
 | 
						|
    // the exe already exists
 | 
						|
    Ext:=ExtractFileExt(ExeFilename);
 | 
						|
    AltFilename:=LeftStr(ExeFilename,length(ExeFilename)-length(Ext))+'.new'+Ext;
 | 
						|
    if blfBackupOldExe in Flags then begin
 | 
						|
      // always delete the lazarus.new exe, so that users/startlazarus are not
 | 
						|
      // confused which one is the newest
 | 
						|
      if FileExistsUTF8(AltFilename) then begin
 | 
						|
        if DeleteFileUTF8(AltFilename) then
 | 
						|
          debugln(['Note: deleted file "',AltFilename,'"'])
 | 
						|
        else
 | 
						|
          debugln(['WARNING: unable to delete file "',AltFilename,'"']);
 | 
						|
      end;
 | 
						|
 | 
						|
      // try to rename the old exe
 | 
						|
      BackupFilename:=GetBackupExeFilename(ExeFilename);
 | 
						|
      if FileExistsUTF8(BackupFilename) then
 | 
						|
        if DeleteFileUTF8(BackupFilename) then begin
 | 
						|
          debugln(['Note: deleted backup "',BackupFilename,'"']);
 | 
						|
        end else begin
 | 
						|
          // unable to delete old backup file, maybe an old IDE is still running
 | 
						|
          // => try to backup the backup
 | 
						|
          Backup2Filename:=LeftStr(ExeFilename,length(ExeFilename)-length(Ext))+'.old2'+Ext;
 | 
						|
          if FileExistsUTF8(Backup2Filename) then begin
 | 
						|
            if DeleteFileUTF8(Backup2Filename) then
 | 
						|
              debugln(['Note: deleted backup "',Backup2Filename,'"'])
 | 
						|
            else
 | 
						|
              debugln(['WARNING: unable to delete old backup file "'+Backup2Filename+'"']);
 | 
						|
          end;
 | 
						|
          if not FileExistsUTF8(Backup2Filename) then begin
 | 
						|
            if RenameFileUTF8(BackupFilename,Backup2Filename) then
 | 
						|
              debugln(['Note: renamed old backup file "'+BackupFilename+'" to "',Backup2Filename,'"'])
 | 
						|
            else
 | 
						|
              debugln(['WARNING: unable to rename old backup file "'+BackupFilename+'" to "',Backup2Filename,'"']);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
      if not FileExistsUTF8(BackupFilename) then begin
 | 
						|
        if RenameFileUTF8(ExeFilename,BackupFilename) then
 | 
						|
          debugln(['Note: renamed file "'+ExeFilename+'" to "',BackupFilename,'"'])
 | 
						|
        else
 | 
						|
          debugln(['WARNING: unable to rename file "'+ExeFilename+'" to "',BackupFilename,'"']);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    if (not (blfReplaceExe in Flags)) and FileExistsUTF8(ExeFilename) then begin
 | 
						|
      // backup didn't work => use another file name
 | 
						|
      ExeFilename:=AltFilename;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure AppendExtraOption(const AddOption: string; EncloseIfSpace: boolean);
 | 
						|
  begin
 | 
						|
    if AddOption='' then exit;
 | 
						|
    if ExtraOptions<>'' then
 | 
						|
      ExtraOptions:=ExtraOptions+' ';
 | 
						|
    if EncloseIfSpace and (Pos(' ',AddOption)>0) then
 | 
						|
      ExtraOptions:=ExtraOptions+'"'+AddOption+'"'
 | 
						|
    else
 | 
						|
      ExtraOptions:=ExtraOptions+AddOption;
 | 
						|
    //DebugLn(['AppendExtraOption ',ExtraOptions]);
 | 
						|
  end;
 | 
						|
 | 
						|
  procedure AppendExtraOption(const AddOption: string);
 | 
						|
  begin
 | 
						|
    AppendExtraOption(AddOption,true);
 | 
						|
  end;
 | 
						|
 | 
						|
var
 | 
						|
  MakeIDECfgFilename: string;
 | 
						|
  TargetDirectory: string;
 | 
						|
  UnitOutDir: string;
 | 
						|
  DefaultTargetOS: string;
 | 
						|
  DefaultTargetCPU: string;
 | 
						|
  TargetOS: string;
 | 
						|
  TargetCPU: string;
 | 
						|
  CrossCompiling: Boolean;
 | 
						|
  CurTargetFilename: string;
 | 
						|
  BundleDir: string;
 | 
						|
  NewTargetDirectoryIsDefault: Boolean;
 | 
						|
  DefaultTargetFilename: string;
 | 
						|
  NewTargetFilenameIsDefault: Boolean;
 | 
						|
  TargetLCLPlatform: String;
 | 
						|
begin
 | 
						|
  Result:=mrOk;
 | 
						|
  OutputDirRedirected:=false;
 | 
						|
  UpdateRevisionInc:=Profile.UpdateRevisionInc;
 | 
						|
 | 
						|
  // create extra Profile
 | 
						|
  ExtraOptions:=Profile.ExtraOptions;
 | 
						|
 | 
						|
  // check for special IDE config file
 | 
						|
  if (blfUseMakeIDECfg in Flags) then begin
 | 
						|
    MakeIDECfgFilename:=GetMakeIDEConfigFilename;
 | 
						|
    //DebugLn(['CreateBuildLazarusOptions MAKE MakeIDECfgFilename=',MakeIDECfgFilename,' ',FileExistsUTF8(MakeIDECfgFilename)]);
 | 
						|
    if (FileExistsUTF8(MakeIDECfgFilename)) then begin
 | 
						|
      // If a file name contains spaces, a file name whould need to be quoted.
 | 
						|
      // Using a single quote is not possible, it is used already in the
 | 
						|
      // makefile to group all Profile in OPT='bla bla'.
 | 
						|
      // using " implicates that make uses a shell to execute the command of
 | 
						|
      // that line. But using shells (i.e. command.com, cmd.exe, etc) is so
 | 
						|
      // fragile (see bug 11362), that is better to avoid this.
 | 
						|
      // Therefore we use a short 8.3 file and path name, so we don't need to
 | 
						|
      // use quotes at all.
 | 
						|
      // On platforms other than windows, ExtractShortPathName is implemented
 | 
						|
      // too and simply returns the passed file name, so there is no need
 | 
						|
      // for $IFDEF.
 | 
						|
      if pos(' ',MakeIDECfgFilename)>0 then
 | 
						|
        MakeIDECfgFilename:=ExtractShortPathNameUTF8(MakeIDECfgFilename);
 | 
						|
      AppendExtraOption('@'+MakeIDECfgFilename);
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
  // set target filename and target directory:
 | 
						|
  // 1. the user has set a target directory
 | 
						|
  // 2. For crosscompiling the IDE needs a different directory
 | 
						|
  // 3. If lazarus is installed as root/administrator, the lazarus directory
 | 
						|
  //    is readonly and needs a different name and directory
 | 
						|
  //    (e.g. ~/.lazarus/bin/lazarus).
 | 
						|
  // 4. Platforms like windows locks executables, so lazarus can not replace
 | 
						|
  //    itself. The IDE will try to rename the file or fallback to another name
 | 
						|
  //    (e.g. lazarus.new.exe).
 | 
						|
  //    The target directory is writable, the lazarus.o file can be created.
 | 
						|
  // Otherwise: Don't touch the target filename.
 | 
						|
 | 
						|
  TargetFilename:='';
 | 
						|
  UnitOutDir:='';
 | 
						|
  TargetDirectory:='';
 | 
						|
  DefaultTargetOS:=GetDefaultTargetOS;
 | 
						|
  DefaultTargetCPU:=GetDefaultTargetCPU;
 | 
						|
  TargetOS:=Profile.FPCTargetOS;
 | 
						|
  TargetCPU:=Profile.FPCTargetCPU;
 | 
						|
  TargetLCLPlatform:=LCLPlatformDirNames[Profile.TargetPlatform];
 | 
						|
  if TargetOS='' then TargetOS:=DefaultTargetOS;
 | 
						|
  if TargetCPU='' then TargetCPU:=DefaultTargetCPU;
 | 
						|
  DefaultTargetFilename:='lazarus'+GetExecutableExt(TargetOS);
 | 
						|
  CrossCompiling:=(CompareText(TargetOS,DefaultTargetOS)<>0) or (CompareText(TargetCPU,DefaultTargetCPU)<>0);
 | 
						|
 | 
						|
  //DebugLn(['CreateBuildLazarusOptions NewTargetOS=',TargetOS,' NewTargetCPU=',TargetCPU]);
 | 
						|
  if (Profile.TargetDirectory<>'') then begin
 | 
						|
    // Case 1. the user has set a target directory
 | 
						|
    TargetDirectory:=Profile.GetParsedTargetDirectory(Macros);
 | 
						|
    if TargetDirectory='' then begin
 | 
						|
      debugln('CreateBuildLazarusOptions macro aborted Options.TargetDirectory=',Profile.TargetDirectory);
 | 
						|
      Result:=mrAbort;
 | 
						|
      exit;
 | 
						|
    end;
 | 
						|
    UnitOutDir:=AppendPathDelim(TargetDirectory)+'units';
 | 
						|
    debugln('CreateBuildLazarusOptions TargetDirectory=',TargetDirectory);
 | 
						|
    debugln('CreateBuildLazarusOptions UnitsTargetDirectory=',UnitOutDir);
 | 
						|
  end else begin
 | 
						|
    // no user defined target directory
 | 
						|
    // => find it automatically
 | 
						|
 | 
						|
    if CrossCompiling then
 | 
						|
    begin
 | 
						|
      // Case 2. crosscompiling the IDE
 | 
						|
      // lazarus.exe to <primary config dir>/bin/<TargetCPU>-<TargetOS>
 | 
						|
      TargetDirectory:=AppendPathDelim(GetPrimaryConfigPath)+'bin'
 | 
						|
                          +PathDelim+TargetCPU+'-'+TargetOS;
 | 
						|
      // ppu files to <primary config dir>/units/<TargetCPU>-<TargetOS>/<LCLWidgetType>
 | 
						|
      UnitOutDir:=AppendPathDelim(GetPrimaryConfigPath)+'units'
 | 
						|
                  +PathDelim+TargetCPU+'-'+TargetOS+PathDelim+TargetLCLPlatform;
 | 
						|
      debugln('CreateBuildLazarusOptions Options.TargetOS=',Profile.FPCTargetOS,' Options.TargetCPU=',
 | 
						|
              Profile.FPCTargetCPU,' DefaultOS=',DefaultTargetOS,' DefaultCPU=',DefaultTargetCPU);
 | 
						|
    end else begin
 | 
						|
      // -> normal compile for this platform
 | 
						|
 | 
						|
      // get lazarus directory
 | 
						|
      TargetDirectory:=EnvironmentOptions.GetParsedLazarusDirectory;
 | 
						|
      if (TargetDirectory<>'') and DirPathExists(TargetDirectory) then
 | 
						|
      begin
 | 
						|
        if not DirectoryIsWritableCached(TargetDirectory) then begin
 | 
						|
          // Case 3. the lazarus directory is not writable
 | 
						|
          // lazarus.exe to <primary config dir>/bin/
 | 
						|
          // ppu files to <primary config dir>/units/<TargetCPU>-<TargetOS>/<LCLWidgetType>
 | 
						|
          UpdateRevisionInc:=false;
 | 
						|
          TargetDirectory:=AppendPathDelim(GetPrimaryConfigPath)+'bin';
 | 
						|
          debugln('CreateBuildLazarusOptions LazDir readonly NewTargetDirectory=',TargetDirectory);
 | 
						|
          UnitOutDir:=AppendPathDelim(GetPrimaryConfigPath)+'units'
 | 
						|
                  +PathDelim+TargetCPU+'-'+TargetOS+PathDelim+TargetLCLPlatform;
 | 
						|
        end else begin
 | 
						|
          // Case 4. the lazarus directory is writable
 | 
						|
          // ppu files to <lazarusdir>/units/<TargetCPU>-<TargetOS>/<LCLWidgetType>
 | 
						|
          UnitOutDir:=AppendPathDelim(TargetDirectory)+'units'
 | 
						|
                  +PathDelim+TargetCPU+'-'+TargetOS+PathDelim+TargetLCLPlatform;
 | 
						|
        end;
 | 
						|
      end else begin
 | 
						|
        // lazarus dir is not valid (probably someone is experimenting)
 | 
						|
        // -> just compile to current directory
 | 
						|
        TargetDirectory:='';
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
  // compute targetfilename
 | 
						|
  if not FilenameIsAbsolute(TargetDirectory) then
 | 
						|
    TargetDirectory:=
 | 
						|
      TrimFilename(AppendPathDelim(EnvironmentOptions.GetParsedLazarusDirectory)+TargetDirectory);
 | 
						|
  if TargetFilename='' then
 | 
						|
    TargetFilename:='lazarus'+GetExecutableExt(TargetOS);
 | 
						|
  if not FilenameIsAbsolute(TargetFilename) then
 | 
						|
    TargetFilename:=TrimFilename(AppendPathDelim(TargetDirectory)+TargetFilename);
 | 
						|
 | 
						|
  // backup old exe
 | 
						|
  BackupExe(TargetFilename);
 | 
						|
 | 
						|
  // check if target file is default
 | 
						|
  NewTargetDirectoryIsDefault:=
 | 
						|
    CompareFilenames(ChompPathDelim(EnvironmentOptions.GetParsedLazarusDirectory),
 | 
						|
                     ChompPathDelim(TargetDirectory))=0;
 | 
						|
  NewTargetFilenameIsDefault:=NewTargetDirectoryIsDefault;
 | 
						|
  if NewTargetFilenameIsDefault then begin
 | 
						|
    CurTargetFilename:=CreateRelativePath(TargetFilename,TargetDirectory);
 | 
						|
    NewTargetFilenameIsDefault:=CurTargetFilename=DefaultTargetFilename;
 | 
						|
  end;
 | 
						|
 | 
						|
  // create output directories
 | 
						|
  if not NewTargetDirectoryIsDefault then begin
 | 
						|
    Result:=ForceDirectoryInteractive(TargetDirectory,[]);
 | 
						|
    if Result<>mrOk then exit;
 | 
						|
  end;
 | 
						|
  if UnitOutDir<>'' then begin
 | 
						|
    Result:=ForceDirectoryInteractive(UnitOutDir,[]);
 | 
						|
    if Result<>mrOk then exit;
 | 
						|
  end;
 | 
						|
 | 
						|
  OutputDirRedirected:=not NewTargetDirectoryIsDefault;
 | 
						|
 | 
						|
  // create apple bundle if needed
 | 
						|
  //debugln(['CreateBuildLazarusOptions NewTargetDirectory=',TargetDirectory]);
 | 
						|
  if (Profile.TargetPlatform in [lpCarbon,lpCocoa])
 | 
						|
  and (not NewTargetDirectoryIsDefault)
 | 
						|
  and (DirectoryIsWritableCached(TargetDirectory)) then begin
 | 
						|
    CurTargetFilename:=TargetFilename;
 | 
						|
    BundleDir:=ChangeFileExt(CurTargetFilename,'.app');
 | 
						|
    //debugln(['CreateBuildLazarusOptions checking bundle ',BundleDir]);
 | 
						|
    if not FileExistsCached(BundleDir) then begin
 | 
						|
      //debugln(['CreateBuildLazarusOptions CurTargetFilename=',CurTargetFilename]);
 | 
						|
      Result:=CreateApplicationBundle(CurTargetFilename, 'Lazarus');
 | 
						|
      if not (Result in [mrOk,mrIgnore]) then begin
 | 
						|
        debugln(['CreateBuildLazarusOptions CreateApplicationBundle failed']);
 | 
						|
        if IDEMessagesWindow<>nil then
 | 
						|
          IDEMessagesWindow.AddMsg('Error: failed to create application bundle '+BundleDir,TargetDirectory,-1);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
      Result:=CreateAppBundleSymbolicLink(CurTargetFilename);
 | 
						|
      if not (Result in [mrOk,mrIgnore]) then begin
 | 
						|
        debugln(['CreateBuildLazarusOptions CreateAppBundleSymbolicLink failed']);
 | 
						|
        if IDEMessagesWindow<>nil then
 | 
						|
          IDEMessagesWindow.AddMsg('Error: failed to create application bundle symlink to '+CurTargetFilename,TargetDirectory,-1);
 | 
						|
        exit;
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
 | 
						|
  if UnitOutDir<>'' then
 | 
						|
    // FPC interpretes '\ ' as an escape for a space in a path on Windows,
 | 
						|
    // so make sure the directory doesn't end with the path delimiter.
 | 
						|
    AppendExtraOption('-FU'+ChompPathDelim(UnitOutDir));
 | 
						|
 | 
						|
  if TargetDirectory<>'' then
 | 
						|
    // FPC interpretes '\ ' as an escape for a space in a path on Windows,
 | 
						|
    // so make sure the directory doesn't end with the path delimiter.
 | 
						|
    AppendExtraOption('-FE'+ChompPathDelim(TargetDirectory));
 | 
						|
 | 
						|
  if not NewTargetFilenameIsDefault then begin
 | 
						|
    // Note: FPC automatically changes the last extension (append or replace)
 | 
						|
    // For example under linux, where executables don't need any extension
 | 
						|
    // fpc removes the last extension of the -o option.
 | 
						|
    AppendExtraOption('-o'+TargetFilename);
 | 
						|
  end;
 | 
						|
 | 
						|
  // add package Profile for IDE
 | 
						|
  //DebugLn(['CreateBuildLazarusOptions blfUseMakeIDECfg=',blfUseMakeIDECfg in FLags,' ExtraOptions="',ExtraOptions,'" ',PackageOptions]);
 | 
						|
  if not (blfUseMakeIDECfg in Flags) then
 | 
						|
    AppendExtraOption(PackageOptions,false);
 | 
						|
  //DebugLn(['CreateBuildLazarusOptions ',MMDef.Name,' ',ExtraOptions]);
 | 
						|
end;
 | 
						|
 | 
						|
function SaveIDEMakeOptions(Profile: TBuildLazarusProfile;
 | 
						|
  Macros: TTransferMacroList;
 | 
						|
  const PackageOptions: string; Flags: TBuildLazarusFlags): TModalResult;
 | 
						|
 | 
						|
  function BreakOptions(const OptionString: string): string;
 | 
						|
  var
 | 
						|
    StartPos: Integer;
 | 
						|
    EndPos: Integer;
 | 
						|
    c: Char;
 | 
						|
    CurLine: String;
 | 
						|
  begin
 | 
						|
    Result:='';
 | 
						|
    // write each option into a line of its own
 | 
						|
    StartPos:=1;
 | 
						|
    repeat
 | 
						|
      while (StartPos<=length(OptionString)) and (OptionString[StartPos]=' ') do
 | 
						|
        inc(StartPos);
 | 
						|
      EndPos:=StartPos;
 | 
						|
      while EndPos<=length(OptionString) do begin
 | 
						|
        c:=OptionString[EndPos];
 | 
						|
        case c of
 | 
						|
        ' ': break;
 | 
						|
 | 
						|
        '''','"','`':
 | 
						|
          begin
 | 
						|
            repeat
 | 
						|
              inc(EndPos);
 | 
						|
              if (OptionString[EndPos]=c) then begin
 | 
						|
                inc(EndPos);
 | 
						|
                break;
 | 
						|
              end;
 | 
						|
            until (EndPos>length(OptionString));
 | 
						|
          end;
 | 
						|
 | 
						|
        else
 | 
						|
          inc(EndPos);
 | 
						|
        end;
 | 
						|
      end;
 | 
						|
      if (EndPos>StartPos) then begin
 | 
						|
        CurLine:=Trim(copy(OptionString,StartPos,EndPos-StartPos));
 | 
						|
        if (length(CurLine)>2) and (CurLine[1] in ['''','"','`'])
 | 
						|
        and (CurLine[1]=CurLine[length(CurLine)]) then begin
 | 
						|
          // whole line enclosed in quotation marks
 | 
						|
          // in fpc config this is forbidden and gladfully unncessary
 | 
						|
          CurLine:=copy(CurLine,2,length(CurLine)-2);
 | 
						|
        end;
 | 
						|
        Result:=Result+CurLine+LineEnding;
 | 
						|
      end;
 | 
						|
      StartPos:=EndPos;
 | 
						|
    until StartPos>length(OptionString);
 | 
						|
  end;
 | 
						|
 | 
						|
var
 | 
						|
  ExOptions: String;
 | 
						|
  Filename: String;
 | 
						|
  fs: TFileStreamUTF8;
 | 
						|
  OptionsAsText: String;
 | 
						|
  UpdateRevisionInc: boolean;
 | 
						|
  OutputDirRedirected: boolean;
 | 
						|
  LazExeFilename: string;
 | 
						|
begin
 | 
						|
  ExOptions:='';
 | 
						|
  Result:=CreateIDEMakeOptions(Profile, Macros, PackageOptions,
 | 
						|
      Flags, ExOptions, UpdateRevisionInc, OutputDirRedirected, LazExeFilename);
 | 
						|
  if Result<>mrOk then exit;
 | 
						|
  Filename:=GetMakeIDEConfigFilename;
 | 
						|
  try
 | 
						|
    InvalidateFileStateCache;
 | 
						|
    fs:=TFileStreamUTF8.Create(Filename,fmCreate);
 | 
						|
    try
 | 
						|
      if ExOptions<>'' then begin
 | 
						|
        OptionsAsText:=BreakOptions(ExOptions);
 | 
						|
        fs.Write(OptionsAsText[1],length(OptionsAsText));
 | 
						|
      end;
 | 
						|
    finally
 | 
						|
      fs.Free;
 | 
						|
    end;
 | 
						|
  except
 | 
						|
    on E: Exception do begin
 | 
						|
      Result:=IDEMessageDialog(lisLazBuildErrorWritingFile,
 | 
						|
        Format(lisLazBuildUnableToWriteFile, [Filename, LineEnding])
 | 
						|
        +E.Message,
 | 
						|
        mtError,[mbCancel,mbAbort]);
 | 
						|
      exit;
 | 
						|
    end;
 | 
						|
  end;
 | 
						|
  Result:=mrOk;
 | 
						|
end;
 | 
						|
 | 
						|
function GetMakeIDEConfigFilename: string;
 | 
						|
begin
 | 
						|
  Result:=AppendPathDelim(GetPrimaryConfigPath)+DefaultIDEMakeOptionFilename;
 | 
						|
end;
 | 
						|
 | 
						|
function GetBackupExeFilename(Filename: string): string;
 | 
						|
var
 | 
						|
  Ext: String;
 | 
						|
begin
 | 
						|
  Ext:=ExtractFileExt(Filename);
 | 
						|
  Result:=LeftStr(Filename,length(Filename)-length(Ext))+'.old'+Ext;
 | 
						|
end;
 | 
						|
 | 
						|
{ TConfigureBuildLazarusDlg }
 | 
						|
 | 
						|
constructor TConfigureBuildLazarusDlg.Create(TheOwner: TComponent);
 | 
						|
begin
 | 
						|
  inherited Create(TheOwner);
 | 
						|
  fProfiles:=TBuildLazarusProfiles.Create;
 | 
						|
  fUpdatingProfileCombo:=False;
 | 
						|
end;
 | 
						|
 | 
						|
destructor TConfigureBuildLazarusDlg.Destroy;
 | 
						|
begin
 | 
						|
  fProfiles.Free;
 | 
						|
  inherited Destroy;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.FormCreate(Sender: TObject);
 | 
						|
var
 | 
						|
  LCLInterface: TLCLPlatform;
 | 
						|
begin
 | 
						|
  IDEDialogLayoutList.ApplyLayout(Self,700,480);
 | 
						|
 | 
						|
  Caption := Format(lisConfigureBuildLazarus, ['"', '"']);
 | 
						|
  PageControl1.ActivePage:=BuildTabSheet;
 | 
						|
  BuildTabSheet.Caption:=lisBuildCaption;
 | 
						|
 | 
						|
  // Show Build target names in combobox.
 | 
						|
  LCLWidgetTypeLabel.Caption := lisLCLWidgetType;
 | 
						|
  for LCLInterface:=Low(TLCLPlatform) to High(TLCLPlatform) do
 | 
						|
    LCLWidgetTypeComboBox.Items.Add(LCLPlatformDisplayNames[LCLInterface]);
 | 
						|
 | 
						|
  BuildProfileLabel.Caption:=lisLazBuildProfile;
 | 
						|
  BuildProfileButton.Hint := lisLazBuildManageProfiles2;
 | 
						|
  BuildProfileComboBox.Hint := lisLazBuildNameOfTheActiveProfile;
 | 
						|
  OptionsLabel.Caption := lisLazBuildOptions;
 | 
						|
  TargetOSLabel.Caption := lisLazBuildTargetOS;
 | 
						|
  TargetCPULabel.Caption := lisLazBuildTargetCPU;
 | 
						|
  TargetDirectoryLabel.Caption := lisLazBuildTargetDirectory;
 | 
						|
 | 
						|
  DefinesListBox.Hint := lisLazBuildDefinesWithoutD;
 | 
						|
  DefinesLabel.Caption := lisLazBuildDefines;
 | 
						|
  DefinesButton.Caption := lisLazBuildEditDefines;
 | 
						|
  DefinesButton.Hint := lisLazBuildEditListOfDefinesWhichCanBeUsedByAnyProfile;
 | 
						|
 | 
						|
  CleanUpGroupBox.Caption:=lisCleanUp;
 | 
						|
  CleanAutoRadioButton.Caption:=lisAutomatically;
 | 
						|
  CleanCommonRadioButton.Caption:=lisCleanCommonFiles;
 | 
						|
  CleanAllRadioButton.Caption:=lisCleanAll;
 | 
						|
  CleanOnceCheckBox.Caption:=lisCleanOnlyOnce;
 | 
						|
  CleanOnceCheckBox.Hint:=lisAfterCleaningUpSwitchToAutomaticClean;
 | 
						|
 | 
						|
  UpdateRevisionIncCheckBox.Caption := lisLazBuildUpdateRevInc;
 | 
						|
  UpdateRevisionIncCheckBox.Hint := lisLazBuildUpdateRevisionInfoInAboutLazarusDialog;
 | 
						|
 | 
						|
  CommonsDividerBevel.Caption := lisLazBuildCommonSettings;
 | 
						|
  RestartAfterBuildCheckBox.Caption := lisLazBuildRestartAfterBuild;
 | 
						|
  RestartAfterBuildCheckBox.Hint := lisLazBuildRestartLazarusAutomatically;
 | 
						|
  ConfirmBuildCheckBox.Caption := lisLazBuildConfirmBuild;
 | 
						|
  ConfirmBuildCheckBox.Hint := lisLazBuildShowConfirmationDialogWhenBuilding;
 | 
						|
 | 
						|
  CompileButton.Caption := lisBuild;
 | 
						|
  CompileButton.LoadGlyphFromLazarusResource('menu_build');
 | 
						|
  CompileAdvancedButton.Caption := lisLazBuildBuildMany;
 | 
						|
  CompileAdvancedButton.LoadGlyphFromLazarusResource('menu_build_all');
 | 
						|
  SaveSettingsButton.Caption := lisSaveSettings;
 | 
						|
  SaveSettingsButton.LoadGlyphFromStock(idButtonSave);
 | 
						|
  if SaveSettingsButton.Glyph.Empty then
 | 
						|
    SaveSettingsButton.LoadGlyphFromLazarusResource('laz_save');
 | 
						|
  CancelButton.Caption := lisCancel;
 | 
						|
  HelpButton.Caption := lisMenuHelp;
 | 
						|
 | 
						|
  OptionsMemo.Hint := lisLazBuildOptionsPassedToCompiler;
 | 
						|
  ShowOptsMenuItem.Caption := lisLazBuildShowOptionsAndDefinesForCommandLine;
 | 
						|
 | 
						|
  with TargetOSComboBox do
 | 
						|
  begin
 | 
						|
    with Items do begin
 | 
						|
      Add(''); //('+rsiwpDefault+')');
 | 
						|
      Add('Darwin');
 | 
						|
      Add('FreeBSD');
 | 
						|
      Add('Linux');
 | 
						|
      Add('NetBSD');
 | 
						|
      Add('OpenBSD');
 | 
						|
      Add('Solaris');
 | 
						|
      Add('Win32');
 | 
						|
      Add('Win64');
 | 
						|
      Add('WinCE');
 | 
						|
      Add('go32v2');
 | 
						|
      Add('os2');
 | 
						|
      Add('beos');
 | 
						|
      Add('haiku');
 | 
						|
      Add('qnx');
 | 
						|
      Add('netware');
 | 
						|
      Add('wdosx');
 | 
						|
      Add('emx');
 | 
						|
      Add('watcom');
 | 
						|
      Add('netwlibc');
 | 
						|
      Add('amiga');
 | 
						|
      Add('atari');
 | 
						|
      Add('palmos');
 | 
						|
      Add('gba');
 | 
						|
      Add('nds');
 | 
						|
      Add('macos');
 | 
						|
      Add('morphos');
 | 
						|
      Add('embedded');
 | 
						|
      Add('symbian');
 | 
						|
    end;
 | 
						|
    ItemIndex:=0;
 | 
						|
  end;
 | 
						|
 | 
						|
  with TargetCPUComboBox do begin
 | 
						|
    with Items do begin
 | 
						|
      Add(''); //('+rsiwpDefault+')');
 | 
						|
      Add('arm');
 | 
						|
      Add('i386');
 | 
						|
      Add('m68k');
 | 
						|
      Add('powerpc');
 | 
						|
      Add('sparc');
 | 
						|
      Add('x86_64');
 | 
						|
    end;
 | 
						|
    ItemIndex:=0;
 | 
						|
  end;
 | 
						|
 | 
						|
  SetupInfoPage;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.FormResize(Sender: TObject);
 | 
						|
begin
 | 
						|
  LCLWidgetTypeComboBox.Width:=(OptionsMemo.Width - 12) div 3;
 | 
						|
  TargetOSComboBox.Width:=LCLWidgetTypeComboBox.Width;
 | 
						|
  DefinesListBox.Width:=(OptionsMemo.Width - 6) div 2;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.FormShow(Sender: TObject);
 | 
						|
begin
 | 
						|
  UpdateProfileNamesUI;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.HelpButtonClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  LazarusHelp.ShowHelpForIDEControl(Self);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.ShowOptsMenuItemClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  CopyUIToProfile(fProfiles.Current);
 | 
						|
  ShowMessage(fProfiles.Current.ExtraOptions);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.TargetDirectoryButtonClick(Sender: TObject);
 | 
						|
var
 | 
						|
  AFilename: String;
 | 
						|
  DirDialog: TSelectDirectoryDialog;
 | 
						|
begin
 | 
						|
  DirDialog:=TSelectDirectoryDialog.Create(nil);
 | 
						|
  try
 | 
						|
    DirDialog.Options:=DirDialog.Options+[ofPathMustExist];
 | 
						|
    DirDialog.Title:=lisLazBuildABOChooseOutputDir+'(lazarus'+
 | 
						|
                      GetExecutableExt(fProfiles.Current.FPCTargetOS)+')';
 | 
						|
    if DirDialog.Execute then begin
 | 
						|
      AFilename:=CleanAndExpandDirectory(DirDialog.Filename);
 | 
						|
      TargetDirectoryComboBox.AddHistoryItem(AFilename,10,true,true);
 | 
						|
    end;
 | 
						|
  finally
 | 
						|
    DirDialog.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.CopyProfileToUI(AProfile: TBuildLazarusProfile);
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  LCLWidgetTypeComboBox.ItemIndex   :=ord(AProfile.TargetPlatform);
 | 
						|
  UpdateRevisionIncCheckBox.Checked :=AProfile.UpdateRevisionInc;
 | 
						|
  TargetOSComboBox.Text             :=AProfile.TargetOS;
 | 
						|
  TargetDirectoryComboBox.Text      :=AProfile.TargetDirectory;
 | 
						|
  TargetCPUComboBox.Text            :=AProfile.TargetCPU;
 | 
						|
  case AProfile.IdeBuildMode of
 | 
						|
  bmBuild: CleanAutoRadioButton.Checked:=true;
 | 
						|
  bmCleanBuild: CleanCommonRadioButton.Checked:=true;
 | 
						|
  bmCleanAllBuild: CleanAllRadioButton.Checked:=true;
 | 
						|
  end;
 | 
						|
  CleanOnceCheckBox.Checked:=AProfile.CleanOnce;
 | 
						|
  OptionsMemo.Lines.Assign(AProfile.OptionsLines);
 | 
						|
  for i:=0 to DefinesListBox.Items.Count-1 do
 | 
						|
    DefinesListBox.Checked[i]:=AProfile.Defines.IndexOf(DefinesListBox.Items[i]) > -1;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.CopyUIToProfile(AProfile: TBuildLazarusProfile);
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  AProfile.TargetPlatform    :=TLCLPlatform(LCLWidgetTypeComboBox.ItemIndex);
 | 
						|
  AProfile.UpdateRevisionInc :=UpdateRevisionIncCheckBox.Checked;
 | 
						|
  AProfile.TargetOS          :=TargetOSComboBox.Text;
 | 
						|
  AProfile.TargetDirectory   :=TargetDirectoryComboBox.Text;
 | 
						|
  AProfile.TargetCPU         :=TargetCPUComboBox.Text;
 | 
						|
  if CleanAllRadioButton.Checked then
 | 
						|
    AProfile.IdeBuildMode := bmCleanAllBuild
 | 
						|
  else if CleanCommonRadioButton.Checked then
 | 
						|
    AProfile.IdeBuildMode := bmCleanBuild
 | 
						|
  else
 | 
						|
    AProfile.IdeBuildMode := bmBuild;
 | 
						|
  AProfile.CleanOnce:=CleanOnceCheckBox.Checked;
 | 
						|
  AProfile.OptionsLines.Assign(OptionsMemo.Lines);
 | 
						|
  AProfile.Defines.Clear;
 | 
						|
  for i:=0 to DefinesListBox.Items.Count-1 do
 | 
						|
    if DefinesListBox.Checked[i] then
 | 
						|
      AProfile.Defines.Add(DefinesListBox.Items[i]);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.UpdateProfileNamesUI;
 | 
						|
var
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  // List of defines to checklistbox.
 | 
						|
  DefinesListBox.Items.Clear;
 | 
						|
  for i:=0 to fProfiles.AllDefines.Count-1 do
 | 
						|
    DefinesListBox.Items.Add(fProfiles.AllDefines[i]);
 | 
						|
  // Update the Profiles ComboBox.
 | 
						|
  fUpdatingProfileCombo:=True;
 | 
						|
  BuildProfileComboBox.Items.BeginUpdate;
 | 
						|
  BuildProfileComboBox.Items.Clear;
 | 
						|
  for i:=0 to fProfiles.Count-1 do
 | 
						|
    BuildProfileComboBox.Items.Add(fProfiles[i].Name);
 | 
						|
  BuildProfileCombobox.ItemIndex:=fProfiles.CurrentIndex;
 | 
						|
  CopyProfileToUI(fProfiles.Current); // Copy current selection to UI.
 | 
						|
  BuildProfileComboBox.Items.EndUpdate;
 | 
						|
  fUpdatingProfileCombo:=False;
 | 
						|
  RestartAfterBuildCheckBox.Checked:=fProfiles.RestartAfterBuild;
 | 
						|
  ConfirmBuildCheckBox.Checked     :=fProfiles.ConfirmBuild;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.SetupInfoPage;
 | 
						|
begin
 | 
						|
  InfoTabSheet.Caption:=lisInformation;
 | 
						|
 | 
						|
  fImageIndexPackage := IDEImages.LoadImage(16, 'item_package');
 | 
						|
  fImageIndexRequired := IDEImages.LoadImage(16, 'pkg_required');
 | 
						|
  fImageIndexInherited := IDEImages.LoadImage(16, 'pkg_inherited');
 | 
						|
  InhNoteLabel.Caption := lisAdditionalCompilerOptionsInheritedFromPackages;
 | 
						|
  InhTreeView.Images := IDEImages.Images_16;
 | 
						|
 | 
						|
  UpdateInheritedTree;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.UpdateInheritedTree;
 | 
						|
var
 | 
						|
  AncestorNode: TTreeNode;
 | 
						|
 | 
						|
  procedure AddChildNode(const NewNodeName, Value: string);
 | 
						|
  var
 | 
						|
    VisibleValue: string;
 | 
						|
    ChildNode: TTreeNode;
 | 
						|
  begin
 | 
						|
    VisibleValue := UTF8Trim(Value);
 | 
						|
    if VisibleValue = '' then
 | 
						|
      exit;
 | 
						|
    ChildNode := InhTreeView.Items.AddChild(AncestorNode,
 | 
						|
      NewNodeName + ' = "' + VisibleValue + '"');
 | 
						|
    ChildNode.ImageIndex := fImageIndexRequired;
 | 
						|
    ChildNode.SelectedIndex := ChildNode.ImageIndex;
 | 
						|
  end;
 | 
						|
 | 
						|
var
 | 
						|
  PkgList: TFPList;
 | 
						|
  i: Integer;
 | 
						|
  Pkg: TLazPackage;
 | 
						|
  AncestorOptions: TPkgAdditionalCompilerOptions;
 | 
						|
  LazDir: String;
 | 
						|
begin
 | 
						|
  PkgList:=nil;
 | 
						|
  InhTreeView.BeginUpdate;
 | 
						|
  LazDir:=EnvironmentOptions.GetParsedLazarusDirectory;
 | 
						|
  try
 | 
						|
    PackageGraph.GetAllRequiredPackages(nil,
 | 
						|
      PackageGraph.FirstAutoInstallDependency,PkgList,[pirSkipDesignTimeOnly]);
 | 
						|
 | 
						|
    // add detail nodes
 | 
						|
    if PkgList<>nil then
 | 
						|
      for i := 0 to PkgList.Count - 1 do
 | 
						|
      begin
 | 
						|
        Pkg:=TLazPackage(PkgList[i]);
 | 
						|
        AncestorOptions := Pkg.UsageOptions;
 | 
						|
        AncestorNode := InhTreeView.Items.Add(nil, '');
 | 
						|
        AncestorNode.Text := AncestorOptions.GetOwnerName;
 | 
						|
        AncestorNode.ImageIndex := fImageIndexPackage;
 | 
						|
        AncestorNode.SelectedIndex := AncestorNode.ImageIndex;
 | 
						|
        with AncestorOptions.ParsedOpts do
 | 
						|
        begin
 | 
						|
          AddChildNode(lisunitPath,
 | 
						|
            CreateRelativeSearchPath(GetParsedValue(pcosUnitPath),LazDir));
 | 
						|
          AddChildNode(lisincludePath,
 | 
						|
            CreateRelativeSearchPath(GetParsedValue(pcosIncludePath),LazDir));
 | 
						|
          AddChildNode(lisobjectPath,
 | 
						|
            CreateRelativeSearchPath(GetParsedValue(pcosObjectPath),LazDir));
 | 
						|
          AddChildNode(lislibraryPath,
 | 
						|
            CreateRelativeSearchPath(GetParsedValue(pcosLibraryPath),LazDir));
 | 
						|
          AddChildNode(lislinkerOptions, GetParsedValue(pcosLinkerOptions));
 | 
						|
          AddChildNode(liscustomOptions, GetParsedValue(pcosCustomOptions));
 | 
						|
        end;
 | 
						|
        AncestorNode.Expanded := True;
 | 
						|
      end;
 | 
						|
  finally
 | 
						|
    InhTreeView.EndUpdate;
 | 
						|
    PkgList.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.PrepareClose;
 | 
						|
begin
 | 
						|
  CopyUIToProfile(fProfiles.Current);
 | 
						|
  fProfiles.RestartAfterBuild :=RestartAfterBuildCheckBox.Checked;
 | 
						|
  fProfiles.ConfirmBuild      :=ConfirmBuildCheckBox.Checked;
 | 
						|
  MainIDEBar.itmToolBuildLazarus.Caption:=
 | 
						|
    Format(lisMenuBuildLazarusProf, [fProfiles.Current.Name]);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.CompileAdvancedButtonClick(Sender: TObject);
 | 
						|
// mrOk=change selected profiles. Selected profiels will be saved or discarded
 | 
						|
// depending on the calling dialog
 | 
						|
// mrYes=save and compile
 | 
						|
// mrCancel=do nothing
 | 
						|
var
 | 
						|
  EditForm: TGenericCheckListForm;
 | 
						|
  i, ind: Integer;
 | 
						|
begin
 | 
						|
  PrepareClose;
 | 
						|
  EditForm:=TGenericCheckListForm.Create(Nil);
 | 
						|
  try
 | 
						|
    EditForm.Caption:=lisLazBuildSelectProfilesToBuild;
 | 
						|
    // Copy profile names to checkboxlist and check the previously selected ones.
 | 
						|
    for i:=0 to fProfiles.Count-1 do begin
 | 
						|
      ind:=EditForm.CheckListBox1.Items.Add(fProfiles[i].Name);
 | 
						|
      if fProfiles.Selected.IndexOf(fProfiles[i].Name)>-1 then
 | 
						|
        EditForm.CheckListBox1.Checked[ind]:=True;
 | 
						|
    end;
 | 
						|
    // Show the form.
 | 
						|
    EditForm.ShowModal;
 | 
						|
    if EditForm.ModalResult in [mrOK, mrYes] then begin
 | 
						|
      // Copy checked profile names to Selected.
 | 
						|
      fProfiles.Selected.Clear;
 | 
						|
      for i:=0 to fProfiles.Count-1 do begin      // fProfiles and CheckListBox1
 | 
						|
        if EditForm.CheckListBox1.Checked[i] then // indexes match now.
 | 
						|
          fProfiles.Selected.Add(fProfiles[i].Name);
 | 
						|
      end;
 | 
						|
    end;
 | 
						|
    if EditForm.ModalResult=mrYes then
 | 
						|
      ModalResult:=mrAll;
 | 
						|
  finally
 | 
						|
    EditForm.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.CompileButtonClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  PrepareClose;
 | 
						|
  ModalResult:=mrYes;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.SaveSettingsButtonClick(Sender: TObject);
 | 
						|
begin
 | 
						|
  PrepareClose;
 | 
						|
  ModalResult:=mrOk;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.DefinesButtonClick(Sender: TObject);
 | 
						|
var
 | 
						|
  EditForm: TGenericListEditForm;
 | 
						|
  i: Integer;
 | 
						|
begin
 | 
						|
  EditForm:=TGenericListEditForm.Create(Nil);
 | 
						|
  try
 | 
						|
    EditForm.Caption:=lisLazBuildEditDefinesDialogCaption;
 | 
						|
    EditForm.Memo1.Lines.Assign(fProfiles.AllDefines);
 | 
						|
    if EditForm.ShowModal=mrOK then begin
 | 
						|
      CopyUIToProfile(fProfiles.Current); // Make sure changed fields don't get lost.
 | 
						|
      fProfiles.AllDefines.Assign(EditForm.Memo1.Lines);
 | 
						|
      DefinesListBox.Items.Clear;
 | 
						|
      for i:=0 to fProfiles.AllDefines.Count-1 do
 | 
						|
        DefinesListBox.Items.Add(fProfiles.AllDefines[i]);
 | 
						|
      for i:=0 to DefinesListBox.Items.Count-1 do // Check the right boxes again.
 | 
						|
        DefinesListBox.Checked[i]:=fProfiles.Current.Defines.IndexOf(DefinesListBox.Items[i]) > -1;
 | 
						|
    end;
 | 
						|
  finally
 | 
						|
    EditForm.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.FormClose(Sender: TObject; var CloseAction:
 | 
						|
  TCloseAction);
 | 
						|
begin
 | 
						|
  IDEDialogLayoutList.SaveLayout(Self);
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.BuildProfileButtonClick(Sender: TObject);
 | 
						|
var
 | 
						|
  Frm: TBuildProfileManagerForm;
 | 
						|
begin
 | 
						|
  Frm:=TBuildProfileManagerForm.Create(nil);
 | 
						|
  try
 | 
						|
    CopyUIToProfile(fProfiles.Current);    // Make sure changed fields get included.
 | 
						|
    Frm.Prepare(fProfiles);                // Copy profiles to dialog.
 | 
						|
    if Frm.ShowModal = mrOk then begin
 | 
						|
      fProfiles.Assign(Frm.ProfsToManage); // Copy profiles back from dialog.
 | 
						|
      UpdateProfileNamesUI;
 | 
						|
    end;
 | 
						|
  finally
 | 
						|
    Frm.Free;
 | 
						|
  end;
 | 
						|
end;
 | 
						|
 | 
						|
procedure TConfigureBuildLazarusDlg.BuildProfileComboBoxSelect(Sender: TObject);
 | 
						|
begin
 | 
						|
  // QT binding calls this also when items are added to list. It shouldn't.
 | 
						|
  if (fProfiles.Count>0) and not fUpdatingProfileCombo then
 | 
						|
    if (Sender as TComboBox).ItemIndex<>-1 then begin
 | 
						|
      CopyUIToProfile(fProfiles.Current);    // Save old selection from UI.
 | 
						|
      fProfiles.CurrentIndex:=(Sender as TComboBox).ItemIndex;
 | 
						|
      CopyProfileToUI(fProfiles.Current);    // Copy new selection to UI.
 | 
						|
    end;
 | 
						|
end;
 | 
						|
 | 
						|
end.
 | 
						|
 |