diff --git a/ide/allcompileroptions.lfm b/ide/allcompileroptions.lfm index 52a9d8bb3b..072b77bd1f 100644 --- a/ide/allcompileroptions.lfm +++ b/ide/allcompileroptions.lfm @@ -6,7 +6,7 @@ object frmAllCompilerOptions: TfrmAllCompilerOptions Caption = 'frmAllCompilerOptions' ClientHeight = 497 ClientWidth = 622 - OnShow = FormShow + OnCreate = FormCreate LCLVersion = '1.3' object sbAllOptions: TScrollBox Left = 0 diff --git a/ide/allcompileroptions.pas b/ide/allcompileroptions.pas index c17a872ddf..c3a28424ee 100644 --- a/ide/allcompileroptions.pas +++ b/ide/allcompileroptions.pas @@ -23,7 +23,7 @@ type procedure btnResetOptionsFilterClick(Sender: TObject); procedure cbShowModifiedClick(Sender: TObject); procedure edOptionsFilterChange(Sender: TObject); - procedure FormShow(Sender: TObject); + procedure FormCreate(Sender: TObject); private FIdleConnected: Boolean; FOptionsReader: TCompilerOptReader; @@ -66,6 +66,7 @@ end; destructor TfrmAllCompilerOptions.Destroy; begin + IdleConnected:=false; FGeneratedControls.Clear; FreeAndNil(FGeneratedControls); inherited Destroy; @@ -76,7 +77,7 @@ begin Result := FOptionsReader.ToCustomOptions(aStrings, cbUseComments.Checked); end; -procedure TfrmAllCompilerOptions.FormShow(Sender: TObject); +procedure TfrmAllCompilerOptions.FormCreate(Sender: TObject); begin Caption:=lisAllOptions; edOptionsFilter.Hint := lisFilterTheAvailableOptionsList; @@ -110,6 +111,8 @@ end; procedure TfrmAllCompilerOptions.SetIdleConnected(AValue: Boolean); begin + if csDestroying in ComponentState then + AValue:=false; if FIdleConnected = AValue then exit; FIdleConnected := AValue; if FIdleConnected then @@ -132,9 +135,10 @@ var StartTime: TDateTime; begin IdleConnected := False; + if FOptionsThread=nil then exit; Screen.Cursor := crHourGlass; try - FOptionsThread.WaitFor; // Make sure the options are read. + FOptionsThread.EndParsing; // Make sure the options are read. if FOptionsReader.ErrorMsg <> '' then DebugLn(FOptionsReader.ErrorMsg) else begin diff --git a/ide/compiler.pp b/ide/compiler.pp index 059edc85c2..5a59e2465a 100644 --- a/ide/compiler.pp +++ b/ide/compiler.pp @@ -209,6 +209,8 @@ type procedure Clear; function UpdateTargetParam: Boolean; function ReadAndParseOptions: TModalResult; + function ParseOptions(OutputI, OutputH: TStringList): TModalResult; + procedure ReadCompiler(CompPath, Params: string; out OutputI, OutputH: TStringList); function FilterOptions(aFilter: string; aOnlySelected: Boolean): Boolean; function FindOptionById(aId: integer): TCompilerOpt; function FromCustomOptions(aStrings: TStrings): TModalResult; @@ -228,12 +230,20 @@ type private fReader: TCompilerOptReader; fReadTime: TDateTime; + fCompPath: string; + fCompParams: string; + fOutputI: TStringList; + fOutputH: TStringList; + fStartedOnce: boolean; function GetErrorMsg: string; + procedure Clear; // (main thread) protected procedure Execute; override; public constructor Create(aReader: TCompilerOptReader); destructor Destroy; override; + procedure StartParsing; // (main thread) + procedure EndParsing; // (main thread) public property ReadTime: TDateTime read fReadTime; property ErrorMsg: string read GetErrorMsg; @@ -1166,29 +1176,43 @@ function TCompilerOptReader.ReadAndParseOptions: TModalResult; // fpc -Fr$(FPCMsgFile) -h // fpc -Fr$(FPCMsgFile) -i var - Lines: TStringList; + OutputI: TStringList; + OutputH: TStringList; +begin + if fCompilerExecutable = '' then + fCompilerExecutable := 'fpc'; // Let's hope "fpc" is found in PATH. + try + ReadCompiler(fCompilerExecutable, fParsedTarget, OutputI, OutputH); + Result:=ParseOptions(OutputI, OutputH); + finally + OutputI.Free; + OutputH.Free; + end; +end; + +function TCompilerOptReader.ParseOptions(OutputI, OutputH: TStringList + ): TModalResult; begin OptionIdCounter := 0; fErrorMsg := ''; - if fCompilerExecutable = '' then - fCompilerExecutable := 'fpc'; // Let's hope "fpc" is found in PATH. + if OutputI = Nil then Exit(mrCancel); + Result := ParseI(OutputI); + if Result <> mrOK then Exit; + if OutputH = Nil then Exit(mrCancel); + Result := ParseH(OutputH); +end; + +procedure TCompilerOptReader.ReadCompiler(CompPath, Params: string; out + OutputI, OutputH: TStringList); +begin + OutputH:=nil; + OutputI:=nil; + if CompPath = '' then + CompPath := 'fpc'; // Let's hope "fpc" is found in PATH. // FPC with option -i - Lines:=RunTool(fCompilerExecutable, fParsedTarget + ' -i'); - try - if Lines = Nil then Exit(mrCancel); - Result := ParseI(Lines); - if Result <> mrOK then Exit; - finally - Lines.Free; - end; + OutputI:=RunTool(CompPath, Params + ' -i'); // FPC with option -h - Lines:=RunTool(fCompilerExecutable, fParsedTarget + ' -h'); - try - if Lines = Nil then Exit(mrCancel); - Result := ParseH(Lines); - finally - Lines.Free; - end; + OutputH:=RunTool(CompPath, Params + ' -h'); end; function TCompilerOptReader.FilterOptions(aFilter: string; aOnlySelected: Boolean): Boolean; @@ -1364,12 +1388,15 @@ constructor TCompilerOptThread.Create(aReader: TCompilerOptReader); begin inherited Create(True); //FreeOnTerminate:=True; + fStartedOnce:=false; fReader:=aReader; - fReader.UpdateTargetParam; end; destructor TCompilerOptThread.Destroy; begin + if fStartedOnce then + WaitFor; + Clear; inherited Destroy; end; @@ -1378,17 +1405,51 @@ begin Result := fReader.ErrorMsg; end; +procedure TCompilerOptThread.Clear; +begin + FreeAndNil(fOutputH); + FreeAndNil(fOutputI); +end; + +procedure TCompilerOptThread.StartParsing; +begin + if fStartedOnce then + WaitFor; + fReader.CompilerExecutable:=LazarusIDE.GetFPCompilerFilename;; + fReader.UpdateTargetParam; + fCompPath:=fReader.CompilerExecutable; + fCompParams:=fReader.ParsedTarget; + Start; + fStartedOnce:=true; +end; + +procedure TCompilerOptThread.EndParsing; +begin + if fStartedOnce then + WaitFor; + if (fOutputI<>nil) or (fOutputH<>nil) then begin + try + fReader.ParseOptions(fOutputI,fOutputH); + except + on E: Exception do + fReader.ErrorMsg := 'Error parsing compiler output: '+E.Message; + end; + Clear; + end; +end; + procedure TCompilerOptThread.Execute; var StartTime: TDateTime; begin StartTime := Now; try - fReader.CompilerExecutable := LazarusIDE.GetFPCompilerFilename; - fReader.ReadAndParseOptions; + if fOutputI<>nil then exit; + if fOutputH<>nil then exit; + fReader.ReadCompiler(fCompPath,fCompParams,fOutputI,fOutputH); except on E: Exception do - fReader.ErrorMsg := 'Error parsing options: '+E.Message; + fReader.ErrorMsg := 'Error reading compiler: '+E.Message; end; fReadTime := Now-StartTime; end; diff --git a/ide/customdefines.pas b/ide/customdefines.pas index 7e886961cb..8f1404c6d8 100644 --- a/ide/customdefines.pas +++ b/ide/customdefines.pas @@ -161,7 +161,7 @@ begin IdleConnected := False; Screen.Cursor := crHourGlass; try - FOptionsThread.WaitFor; // Make sure the options are read. + FOptionsThread.EndParsing; // Make sure the options are read. // Parse and separate defines from other options. FOptionsReader.FromCustomOptions(FCustomOptions); // Check the found defines in the GUI. diff --git a/ide/frames/compiler_other_options.pas b/ide/frames/compiler_other_options.pas index 0784aa275d..bedb9d24e8 100644 --- a/ide/frames/compiler_other_options.pas +++ b/ide/frames/compiler_other_options.pas @@ -31,7 +31,7 @@ uses Classes, SysUtils, math, AVL_Tree, LazLogger, Forms, Controls, Graphics, Dialogs, StdCtrls, LCLProc, ComCtrls, LCLType, ExtCtrls, Buttons, CodeToolsCfgScript, KeywordFuncLists, LazarusIDEStrConsts, - IDEOptionsIntf, CompOptsIntf, IDECommands, Project, PackageDefs, + IDEOptionsIntf, CompOptsIntf, IDECommands, LazIDEIntf, Project, PackageDefs, CompilerOptions, Compiler, AllCompilerOptions, CustomDefines, EditorOptions, SynEdit, SynEditKeyCmds, SynCompletion, SourceSynEditor; @@ -366,18 +366,15 @@ begin if Value then begin if Assigned(fOptionsThread) then begin - fOptionsThread.WaitFor; // Make sure the thread has finished running. + fOptionsThread.EndParsing; // Make sure the thread has finished running. if FOptionsReader.UpdateTargetParam then begin - // Does not happen because UpdateTargetParam uses global macros - // which change only after closing the options window. - // This code is here for future refactoring, to react to changed target in GUI. FOptionsReader.Clear; - fOptionsThread.Start; // Read new options. + fOptionsThread.StartParsing; // Read new options. end; end else begin fOptionsThread := TCompilerOptThread.Create(FOptionsReader); - fOptionsThread.Start; + fOptionsThread.StartParsing; end; end; end; @@ -391,6 +388,8 @@ end; procedure TCompilerOtherOptionsFrame.SetIdleConnected(AValue: Boolean); begin + if csDestroying in ComponentState then + AValue:=false; if FIdleConnected=AValue then exit; FIdleConnected:=AValue; if FIdleConnected then @@ -675,6 +674,7 @@ end; destructor TCompilerOtherOptionsFrame.Destroy; begin + IdleConnected:=false; FreeAndNil(fOptionsThread); FreeAndNil(FOptionsReader); FreeAndNil(FCompletionHistory);