From 3c6f47056229f6810545bb8e40f0f1e81984006d Mon Sep 17 00:00:00 2001 From: mattias Date: Sat, 7 Apr 2012 02:43:56 +0000 Subject: [PATCH] IDE: view / IDE internal / what needs building git-svn-id: trunk@36647 - --- .gitattributes | 2 + ide/idefpcinfo.lfm | 15 +- ide/idefpcinfo.pas | 11 +- ide/ideinfodlg.lfm | 19 +- ide/ideinfodlg.pas | 14 +- ide/ideinfoneedbuild.lfm | 60 ++++++ ide/ideinfoneedbuild.pas | 407 ++++++++++++++++++++++++++++++++++++ ide/inputhistory.pas | 12 ++ ide/lazarus.lpi | 11 +- ide/lazarusidestrconsts.pas | 4 + ide/main.pp | 9 +- ide/mainbar.pas | 1 + ide/mainbase.pas | 1 + packager/packagesystem.pas | 69 ++++-- 14 files changed, 599 insertions(+), 36 deletions(-) create mode 100644 ide/ideinfoneedbuild.lfm create mode 100644 ide/ideinfoneedbuild.pas diff --git a/.gitattributes b/.gitattributes index 769230bbbd..dd8d274b48 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4377,6 +4377,8 @@ ide/idehelpmanager.lfm svneol=native#text/plain ide/idehelpmanager.pas svneol=native#text/pascal ide/ideinfodlg.lfm svneol=native#text/plain ide/ideinfodlg.pas svneol=native#text/plain +ide/ideinfoneedbuild.lfm svneol=native#text/plain +ide/ideinfoneedbuild.pas svneol=native#text/plain ide/ideminilibc.pas svneol=native#text/plain ide/ideoptiondefs.pas svneol=native#text/pascal ide/ideoptionsdlg.lfm svneol=native#text/plain diff --git a/ide/idefpcinfo.lfm b/ide/idefpcinfo.lfm index d592d65807..b9b405e701 100644 --- a/ide/idefpcinfo.lfm +++ b/ide/idefpcinfo.lfm @@ -6,9 +6,10 @@ object IDEFPCInfoDialog: TIDEFPCInfoDialog Caption = 'IDEFPCInfoDialog' ClientHeight = 450 ClientWidth = 704 + OnClose = FormClose OnCreate = FormCreate Position = poScreenCenter - LCLVersion = '0.9.31' + LCLVersion = '1.1' object PageControl1: TPageControl Left = 0 Height = 450 @@ -20,8 +21,8 @@ object IDEFPCInfoDialog: TIDEFPCInfoDialog TabOrder = 0 object ValuesTabSheet: TTabSheet Caption = 'FPC values used by the IDE' - ClientHeight = 422 - ClientWidth = 696 + ClientHeight = 418 + ClientWidth = 698 object ValuesMemo: TMemo Left = 0 Height = 422 @@ -39,13 +40,13 @@ object IDEFPCInfoDialog: TIDEFPCInfoDialog end object OutputTabSheet: TTabSheet Caption = 'FPC output' - ClientHeight = 422 - ClientWidth = 696 + ClientHeight = 418 + ClientWidth = 698 object CmdLineOutputMemo: TMemo Left = 0 - Height = 422 + Height = 418 Top = 0 - Width = 696 + Width = 698 Align = alClient Lines.Strings = ( 'CmdLineOutputMemo' diff --git a/ide/idefpcinfo.pas b/ide/idefpcinfo.pas index 8ab876dc02..c9fa316862 100644 --- a/ide/idefpcinfo.pas +++ b/ide/idefpcinfo.pas @@ -32,7 +32,8 @@ interface uses Classes, SysUtils, AVL_Tree, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, FileProcs, DefineTemplates, CodeToolManager, - BaseBuildManager, Project, EnvironmentOpts, LazarusIDEStrConsts, AboutFrm; + BaseBuildManager, Project, EnvironmentOpts, LazarusIDEStrConsts, AboutFrm, + IDEWindowIntf; type @@ -44,6 +45,7 @@ type PageControl1: TPageControl; ValuesTabSheet: TTabSheet; OutputTabSheet: TTabSheet; + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); private procedure UpdateValuesMemo; @@ -84,6 +86,13 @@ begin UpdateValuesMemo; UpdateCmdLinePage; PageControl1.PageIndex:=0; + IDEDialogLayoutList.ApplyLayout(Self); +end; + +procedure TIDEFPCInfoDialog.FormClose(Sender: TObject; + var CloseAction: TCloseAction); +begin + IDEDialogLayoutList.SaveLayout(Self); end; procedure TIDEFPCInfoDialog.UpdateValuesMemo; diff --git a/ide/ideinfodlg.lfm b/ide/ideinfodlg.lfm index 5e8324492f..c4dfa44fa6 100644 --- a/ide/ideinfodlg.lfm +++ b/ide/ideinfodlg.lfm @@ -6,8 +6,9 @@ object IDEInfoDialog: TIDEInfoDialog Caption = 'IDEInfoDialog' ClientHeight = 397 ClientWidth = 735 + OnClose = FormClose OnCreate = FormCreate - LCLVersion = '0.9.31' + LCLVersion = '1.1' object PageControl1: TPageControl Left = 0 Height = 397 @@ -19,8 +20,8 @@ object IDEInfoDialog: TIDEInfoDialog TabOrder = 0 object GeneralTabSheet: TTabSheet Caption = 'General' - ClientHeight = 361 - ClientWidth = 727 + ClientHeight = 365 + ClientWidth = 729 object GeneralMemo: TMemo Left = 0 Height = 361 @@ -37,8 +38,8 @@ object IDEInfoDialog: TIDEInfoDialog end object ModifiedTabSheet: TTabSheet Caption = 'Modified' - ClientHeight = 361 - ClientWidth = 727 + ClientHeight = 365 + ClientWidth = 729 object ModifiedMemo: TMemo Left = 0 Height = 361 @@ -54,13 +55,13 @@ object IDEInfoDialog: TIDEInfoDialog end object HelpTabSheet: TTabSheet Caption = 'Help' - ClientHeight = 361 - ClientWidth = 727 + ClientHeight = 365 + ClientWidth = 729 object HelpMemo: TMemo Left = 0 - Height = 361 + Height = 365 Top = 0 - Width = 727 + Width = 729 Align = alClient Lines.Strings = ( 'HelpMemo' diff --git a/ide/ideinfodlg.pas b/ide/ideinfodlg.pas index 461bd57495..d208c7ca90 100644 --- a/ide/ideinfodlg.pas +++ b/ide/ideinfodlg.pas @@ -32,8 +32,8 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, LCLProc, LazHelpHTML, LazHelpIntf, DefineTemplates, EnvironmentOpts, - AboutFrm, LazConf, IDEHelpIntf, LazarusIDEStrConsts, Project, SourceEditor, - PackageSystem, PackageDefs; + AboutFrm, LazConf, IDEHelpIntf, IDEWindowIntf, LazarusIDEStrConsts, Project, + SourceEditor, PackageSystem, PackageDefs; type @@ -47,6 +47,7 @@ type GeneralTabSheet: TTabSheet; ModifiedTabSheet: TTabSheet; HelpTabSheet: TTabSheet; + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); private // general @@ -99,7 +100,14 @@ begin UpdateGeneralMemo; UpdateModifiedMemo; UpdateHelpMemo; - PageControl1.ActivePage:=GeneralTabSheet; + PageControl1.PageIndex:=0; + IDEDialogLayoutList.ApplyLayout(Self); +end; + +procedure TIDEInfoDialog.FormClose(Sender: TObject; + var CloseAction: TCloseAction); +begin + IDEDialogLayoutList.SaveLayout(Self); end; procedure TIDEInfoDialog.GatherHelpDB(Prefix: string; diff --git a/ide/ideinfoneedbuild.lfm b/ide/ideinfoneedbuild.lfm new file mode 100644 index 0000000000..00b1128327 --- /dev/null +++ b/ide/ideinfoneedbuild.lfm @@ -0,0 +1,60 @@ +object IDEInfoNeedBuildDlg: TIDEInfoNeedBuildDlg + Left = 275 + Height = 434 + Top = 248 + Width = 555 + Caption = 'IDEInfoNeedBuildDlg' + ClientHeight = 434 + ClientWidth = 555 + OnClose = FormClose + OnCreate = FormCreate + OnDestroy = FormDestroy + Position = poScreenCenter + LCLVersion = '1.1' + object TargetLabel: TLabel + AnchorSideLeft.Control = Owner + AnchorSideTop.Control = TargetComboBox + AnchorSideTop.Side = asrCenter + Left = 6 + Height = 15 + Top = 12 + Width = 65 + BorderSpacing.Around = 6 + Caption = 'TargetLabel' + ParentColor = False + end + object TargetComboBox: TComboBox + AnchorSideLeft.Control = TargetLabel + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = Owner + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Left = 77 + Height = 27 + Top = 6 + Width = 472 + Anchors = [akTop, akLeft, akRight] + BorderSpacing.Around = 6 + ItemHeight = 0 + OnChange = TargetComboBoxChange + TabOrder = 0 + Text = 'TargetComboBox' + end + object MainMemo: TMemo + AnchorSideTop.Control = TargetComboBox + AnchorSideTop.Side = asrBottom + Left = 6 + Height = 389 + Top = 39 + Width = 543 + Align = alBottom + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Around = 6 + Lines.Strings = ( + 'MainMemo' + ) + ReadOnly = True + ScrollBars = ssAutoBoth + TabOrder = 1 + end +end diff --git a/ide/ideinfoneedbuild.pas b/ide/ideinfoneedbuild.pas new file mode 100644 index 0000000000..e4ede8b3ed --- /dev/null +++ b/ide/ideinfoneedbuild.pas @@ -0,0 +1,407 @@ +{ + *************************************************************************** + * * + * 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 . 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 + + Abstract: + IDE dialog showing packages needing rebuild. +} +unit IDEInfoNeedBuild; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, FileUtil, AvgLvlTree, FileProcs, Forms, Controls, Graphics, + Dialogs, StdCtrls, + IDEWindowIntf, LazIDEIntf, ProjectIntf, + LazarusIDEStrConsts, PackageDefs, PackageSystem, Project, InputHistory, + EnvironmentOpts, IDEProcs, BuildManager; + +type + TINeedBuild = ( + inbNone, + inbNo, + inbNormal, + inbClean + ); + + TInfoNeedBuildItem = class + public + Target: TObject; // TProject, TLazPackage, LazarusIDE + Caption: string; + Filename: string; + NeedBuild: TINeedBuild; + Note: string; + end; + + { TIDEInfoNeedBuildDlg } + + TIDEInfoNeedBuildDlg = class(TForm) + MainMemo: TMemo; + TargetComboBox: TComboBox; + TargetLabel: TLabel; + procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure OnIdle(Sender: TObject; var Done: Boolean); + procedure TargetComboBoxChange(Sender: TObject); + private + FIdleConnected: boolean; + FMainTarget: TObject; + FSkipDesignTimePackages: boolean; + FTargetToItem: TAvgLvlTree; // tree of TInfoNeedBuildItem sorted for Target + FTargets: TFPList; // topologically sorted list of TInfoNeedBuildItem, last=main + procedure FillTargets; + function ProjectAsTarget(AProject: TProject): string; + function IDEAsTarget: string; + procedure SetIdleConnected(AValue: boolean); + function CheckNeedBuild(All: boolean): boolean;// true = complete + function GetTargets(Target: string): TFPList; + function HaveSameTargets(BuildItems, Targets: TFPList): boolean; + procedure ClearTargets; + procedure SetMainTarget(AValue: TObject); + public + property IdleConnected: boolean read FIdleConnected write SetIdleConnected; + property MainTarget: TObject read FMainTarget write SetMainTarget; + property SkipDesignTimePackages: boolean read FSkipDesignTimePackages + write FSkipDesignTimePackages; + end; + +procedure ShowNeedBuildDialog; + +function CompareInfoNeedBuildItemWithTargets(Info1, Info2: Pointer): integer; +function CompareTargetWithInfoNeedBuildItem(Target, Info: Pointer): integer; + +implementation + +{$R *.lfm} + +procedure ShowNeedBuildDialog; +var + IDEInfoNeedBuildDlg: TIDEInfoNeedBuildDlg; +begin + IDEInfoNeedBuildDlg:=TIDEInfoNeedBuildDlg.Create(nil); + try + IDEInfoNeedBuildDlg.ShowModal; + finally + IDEInfoNeedBuildDlg.Free; + end; +end; + +function CompareInfoNeedBuildItemWithTargets(Info1, Info2: Pointer): integer; +var + Item1: TInfoNeedBuildItem absolute Info1; + Item2: TInfoNeedBuildItem absolute Info2; +begin + Result:=ComparePointers(Item1.Target,Item2.Target); +end; + +function CompareTargetWithInfoNeedBuildItem(Target, Info: Pointer): integer; +var + Item: TInfoNeedBuildItem absolute Info; +begin + Result:=ComparePointers(Target,Item.Target); +end; + +{ TIDEInfoNeedBuildDlg } + +procedure TIDEInfoNeedBuildDlg.FormCreate(Sender: TObject); +var + Target: String; +begin + FTargetToItem:=TAvgLvlTree.Create(@CompareInfoNeedBuildItemWithTargets); + FTargets:=TFPList.Create; + + Caption:=lisWhatNeedsRebuilding; + + TargetLabel.Caption:=lisTarget; + FillTargets; + Target:=InputHistories.ViewNeedBuildTarget; + if (Target<>'') and (TargetComboBox.Items.IndexOf(Target)>=0) then + TargetComboBox.Text:=Target + else + TargetComboBox.Text:=TargetComboBox.Items[0]; + + IDEDialogLayoutList.ApplyLayout(Self); + IdleConnected:=true; +end; + +procedure TIDEInfoNeedBuildDlg.FormDestroy(Sender: TObject); +begin + IdleConnected:=false; + ClearTargets; + FreeAndNil(FTargetToItem); + FreeAndNil(FTargets); + MainTarget:=nil; +end; + +procedure TIDEInfoNeedBuildDlg.OnIdle(Sender: TObject; var Done: Boolean); +begin + if CheckNeedBuild(false) then + IdleConnected:=false; +end; + +procedure TIDEInfoNeedBuildDlg.TargetComboBoxChange(Sender: TObject); +begin + IdleConnected:=true; +end; + +procedure TIDEInfoNeedBuildDlg.FormClose(Sender: TObject; + var CloseAction: TCloseAction); +var + Target: TCaption; +begin + IdleConnected:=false; + IDEDialogLayoutList.SaveLayout(Self); + Target:=TargetComboBox.Text; + if Target=ProjectAsTarget(Project1) then + Target:=''; + InputHistories.ViewNeedBuildTarget:=Target; +end; + +procedure TIDEInfoNeedBuildDlg.FillTargets; +var + sl: TStringList; + i: Integer; +begin + sl:=TStringList.Create; + try + for i:=0 to PackageGraph.Count-1 do + sl.Add(PackageGraph[i].Name); + sl.Sort; + sl.Insert(0,IDEAsTarget); + if Project1<>nil then + sl.Insert(0,ProjectAsTarget(Project1)); + TargetComboBox.Items.Assign(sl); + finally + sl.Free; + end; +end; + +function TIDEInfoNeedBuildDlg.ProjectAsTarget(AProject: TProject): string; +begin + if AProject=nil then + Result:='' + else + Result:=Format(lisProject, [AProject.Title]); +end; + +function TIDEInfoNeedBuildDlg.IDEAsTarget: string; +begin + Result:=lisLazarusIDE; +end; + +procedure TIDEInfoNeedBuildDlg.SetIdleConnected(AValue: boolean); +begin + if FIdleConnected=AValue then Exit; + if AValue and (ComponentState*[csDestroying,csLoading]<>[]) then exit; + FIdleConnected:=AValue; + if IdleConnected then + Application.AddOnIdleHandler(@OnIdle) + else + Application.RemoveOnIdleHandler(@OnIdle); +end; + +function TIDEInfoNeedBuildDlg.CheckNeedBuild(All: boolean): boolean; +var + NewTargets: TFPList; + i: Integer; + Item: TInfoNeedBuildItem; + s: String; + Pkg: TLazPackage; + AProject: TProject; + NeedBuildAll: boolean; + PGNeedBuild: TModalResult; +begin + NewTargets:=GetTargets(TargetComboBox.Text); + try + if not HaveSameTargets(FTargets,NewTargets) then begin + // targets have changed + ClearTargets; + if NewTargets=nil then exit(true); + SkipDesignTimePackages:=false; + for i:=0 to NewTargets.Count-1 do begin + Item:=TInfoNeedBuildItem.Create; + Item.Target:=TObject(NewTargets[i]); + if Item.Target=LazarusIDE then begin + Item.Caption:=IDEAsTarget; + Item.Filename:=EnvironmentOptions.LazarusDirectory; + end + else if Item.Target is TProject then begin + AProject:=TProject(Item.Target); + Item.Caption:=ProjectAsTarget(AProject); + Item.Filename:=AProject.ProjectInfoFile; + SkipDesignTimePackages:=not (pfUseDesignTimePackages in AProject.Flags); + end + else if Item.Target is TLazPackage then begin + Pkg:=TLazPackage(Item.Target); + Item.Caption:=Pkg.IDAsString; + Item.Filename:=Pkg.Filename; + end; + FTargetToItem.Add(Item); + FTargets.Add(Item); + end; + end; + finally + NewTargets.Free; + end; + Result:=true; + + // check + if (FTargets.Count>0) then + MainTarget:=TObject(FTargets.Last); + + i:=0; + while i'' then + s+='File: '+Item.Filename+LineEnding; + if Item.Note<>'' then + s+='Note: '+Item.Note+LineEnding; + s+=LineEnding; + end; + MainMemo.Lines.Text:=s; +end; + +function TIDEInfoNeedBuildDlg.GetTargets(Target: string): TFPList; + + function GetList(Main: TObject; FirstDependency: TPkgDependency): TFPList; + begin + Result:=nil; + if Main=nil then exit; + PackageGraph.GetAllRequiredPackages(FirstDependency,Result); + if Result<>nil then begin + // PackageGraph.GetAllRequiredPackages starts with the inner nodes + // => reverse order + ReverseList(Result); + end + else + Result:=TFPList.Create; + Result.Add(Main); + end; + +var + Pkg: TLazPackage; +begin + if Target=IDEAsTarget then begin + Result:=GetList(LazarusIDE,PackageGraph.FirstAutoInstallDependency); + end else if Target=ProjectAsTarget(Project1) then begin + Result:=GetList(Project1,Project1.FirstRequiredDependency); + end else begin + Pkg:=PackageGraph.FindPackageWithName(Target,nil); + Result:=GetList(Pkg,Pkg.FirstRequiredDependency); + end; +end; + +function TIDEInfoNeedBuildDlg.HaveSameTargets(BuildItems, Targets: TFPList + ): boolean; +// check if BuildItems and Targets have the same targets +var + Targets1: TFPList; + Targets2: TFPList; + i: Integer; + Target: TObject; +begin + Result:=false; + if (BuildItems=nil)<>(Targets=nil) then exit; + Targets1:=TFPList.Create; + Targets2:=TFPList.Create; + try + // create a list of targets from BuildItems and a second list from Targets + for i:=0 to BuildItems.Count-1 do + Targets1.Add(TInfoNeedBuildItem(BuildItems[i]).Target); + for i:=0 to Targets.Count-1 do begin + Target:=TObject(Targets[i]); + if (Target=LazarusIDE) or (Target is TProject) or (Target is TLazPackage) then + Targets2.Add(Target); + end; + if Targets1.Count<>Targets2.Count then exit; + // sort both lists + Targets1.Sort(@ComparePointers); + Targets2.Sort(@ComparePointers); + // compare each item + for i:=0 to Targets1.Count-1 do + if Targets1[i]<>Targets2[i] then exit; + finally + Targets1.Free; + Targets2.Free; + end; + Result:=true; +end; + +procedure TIDEInfoNeedBuildDlg.ClearTargets; +begin + FTargetToItem.FreeAndClear; + FTargets.Clear; +end; + +procedure TIDEInfoNeedBuildDlg.SetMainTarget(AValue: TObject); +begin + if FMainTarget=AValue then Exit; + FMainTarget:=AValue; + if (FMainTarget=LazarusIDE) then + MainBuildBoss.SetBuildTargetIDE + else + MainBuildBoss.SetBuildTargetProject1(true); +end; + +end. + diff --git a/ide/inputhistory.pas b/ide/inputhistory.pas index 1954b18e82..f7741c5e2b 100644 --- a/ide/inputhistory.pas +++ b/ide/inputhistory.pas @@ -209,6 +209,7 @@ type FLastConvertDelphiPackage: string; FLastConvertDelphiProject: string; FLastConvertDelphiUnit: string; + FViewNeedBuildTarget: string; FNewFileType: string; FNewProjectType: string; FReplaceHistory: TStringList; @@ -313,6 +314,10 @@ type write FLastConvertDelphiPackage; property LastConvertDelphiUnit: string read FLastConvertDelphiUnit write FLastConvertDelphiUnit; + + // View / internals + property ViewNeedBuildTarget: string read FViewNeedBuildTarget + write FViewNeedBuildTarget; // file encodings property FileEncodings: TStringToStringTree read fFileEncodings write fFileEncodings; @@ -558,6 +563,9 @@ begin FLastConvertDelphiPackage:=XMLConfig.GetValue(Path+'Conversion/Delphi/Package',''); FLastConvertDelphiUnit:=XMLConfig.GetValue(Path+'Conversion/Delphi/Unit',''); + // view internals + ViewNeedBuildTarget:=XMLConfig.GetValue(Path+'View/NeedBuild/Target',''); + // encodings LoadStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/'); @@ -632,6 +640,10 @@ begin FLastConvertDelphiPackage,''); XMLConfig.SetDeleteValue(Path+'Conversion/Delphi/Unit', FLastConvertDelphiUnit,''); + + // view internals + XMLConfig.SetDeleteValue(Path+'View/NeedBuild/Target',ViewNeedBuildTarget,''); + // encodings SaveStringToStringTree(XMLConfig,fFileEncodings,Path+'FileEncodings/'); diff --git a/ide/lazarus.lpi b/ide/lazarus.lpi index 4df9255968..535d3a770c 100644 --- a/ide/lazarus.lpi +++ b/ide/lazarus.lpi @@ -63,7 +63,7 @@ - + @@ -552,6 +552,7 @@ + @@ -573,6 +574,7 @@ + @@ -676,6 +678,13 @@ + + + + + + + diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index 26f94e1003..95df67dd36 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -366,6 +366,7 @@ resourcestring lisMenuPackageLinks = 'Package Links ...'; lisMenuAboutFPC = 'About FPC'; lisAboutIDE = 'About IDE'; + lisMenuWhatNeedsBuilding = 'What Needs Building'; lisMenuNewProject = 'New Project ...'; lisMenuNewProjectFromFile = 'New Project from File ...'; @@ -4607,6 +4608,9 @@ resourcestring lisUIClearIncludedByReference = 'Clear include cache'; lisChangeParent = 'Change Parent'; lisLazarusIDE = 'Lazarus IDE'; + lisProject = 'Project %s'; + lisWhatNeedsRebuilding = 'What needs rebuilding'; + lisTarget = 'Target:'; lisDirectives = 'Directives'; //conditional defines dialog diff --git a/ide/main.pp b/ide/main.pp index 0c3732a5c3..d66c987a40 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -145,7 +145,7 @@ uses OutputFilter, JumpHistoryView, ManageExamples, BuildLazDialog, BuildProfileManager, BuildManager, CheckCompOptsForNewUnitDlg, MiscOptions, InputHistory, UnitDependencies, ClipBoardHistory, - IDEFPCInfo, IDEInfoDlg, ProcessList, InitialSetupDlgs, + IDEFPCInfo, IDEInfoDlg, IDEInfoNeedBuild, ProcessList, InitialSetupDlgs, NewDialog, MakeResStrDlg, DialogProcs, FindReplaceDialog, FindInFilesDlg, CodeExplorer, BuildFileDlg, ProcedureList, ExtractProcDlg, FindRenameIdentifier, AbstractsMethodsDlg, EmptyMethodsDlg, UnusedUnitsDlg, @@ -261,6 +261,7 @@ type procedure mnuViewIDESpeedButtonsClicked(Sender: TObject); procedure mnuViewFPCInfoClicked(Sender: TObject); procedure mnuViewIDEInfoClicked(Sender: TObject); + procedure mnuViewNeedBuildClicked(Sender: TObject); // source menu procedure mnuSourceClicked(Sender: TObject); @@ -2599,6 +2600,7 @@ begin itmViewFPCInfo.OnClick:=@mnuViewFPCInfoClicked; itmViewIDEInfo.OnClick:=@mnuViewIDEInfoClicked; + itmViewNeedBuild.OnClick:=@mnuViewNeedBuildClicked; end; end; @@ -2800,6 +2802,11 @@ begin ShowIDEInfo; end; +procedure TMainIDE.mnuViewNeedBuildClicked(Sender: TObject); +begin + ShowNeedBuildDialog; +end; + procedure TMainIDE.SetDesigning(AComponent: TComponent; Value: Boolean); begin SetComponentDesignMode(AComponent, Value); diff --git a/ide/mainbar.pas b/ide/mainbar.pas index 506f700ded..247377754f 100644 --- a/ide/mainbar.pas +++ b/ide/mainbar.pas @@ -196,6 +196,7 @@ type itmViewPackageLinks: TIDEMenuCommand; itmViewFPCInfo: TIDEMenuCommand; itmViewIDEInfo: TIDEMenuCommand; + itmViewNeedBuild: TIDEMenuCommand; itmSearchInFPDocFiles: TIDEMenuCommand; // source menu diff --git a/ide/mainbase.pas b/ide/mainbase.pas index 7c1bcceb2a..ac48470c01 100644 --- a/ide/mainbase.pas +++ b/ide/mainbase.pas @@ -537,6 +537,7 @@ begin CreateMenuItem(itmViewIDEInternalsWindows, itmViewPackageLinks, 'itmViewPackageLinks', lisMenuPackageLinks); CreateMenuItem(itmViewIDEInternalsWindows, itmViewFPCInfo, 'itmViewFPCInfo', lisMenuAboutFPC); CreateMenuItem(itmViewIDEInternalsWindows, itmViewIDEInfo, 'itmViewIDEInfo', lisAboutIDE); + CreateMenuItem(itmViewIDEInternalsWindows, itmViewNeedBuild, 'itmViewNeedBuild', lisMenuWhatNeedsBuilding); {$IFDEF EnableFPDocSearch} CreateMenuItem(itmViewIDEInternalsWindows, itmSearchInFPDocFiles, 'itmSearchInFPDocFiles', 'Search in FPDoc files'); diff --git a/packager/packagesystem.pas b/packager/packagesystem.pas index f15e07f53e..c537034559 100644 --- a/packager/packagesystem.pas +++ b/packager/packagesystem.pas @@ -146,7 +146,8 @@ type function GetPackageCompilerParams(APackage: TLazPackage): string; function CheckIfCurPkgOutDirNeedsCompile(APackage: TLazPackage; CheckDependencies, SkipDesignTimePackages: boolean; - out NeedBuildAllFlag, ConfigChanged, DependenciesChanged: boolean): TModalResult; + out NeedBuildAllFlag, ConfigChanged, DependenciesChanged: boolean; + var Note: string): TModalResult; procedure InvalidateStateFile(APackage: TLazPackage); public constructor Create; @@ -290,7 +291,7 @@ type ): TModalResult; function CheckIfPackageNeedsCompilation(APackage: TLazPackage; SkipDesignTimePackages: boolean; - out NeedBuildAllFlag: boolean): TModalResult; + out NeedBuildAllFlag: boolean; var Note: string): TModalResult; function PreparePackageOutputDirectory(APackage: TLazPackage; CleanUp: boolean): TModalResult; function GetFallbackOutputDir(APackage: TLazPackage): string; @@ -2853,7 +2854,8 @@ begin end; function TLazPackageGraph.CheckIfPackageNeedsCompilation(APackage: TLazPackage; - SkipDesignTimePackages: boolean; out NeedBuildAllFlag: boolean): TModalResult; + SkipDesignTimePackages: boolean; out NeedBuildAllFlag: boolean; var + Note: string): TModalResult; var OutputDir: String; NewOutputDir: String; @@ -2869,12 +2871,13 @@ begin {$ENDIF} NeedBuildAllFlag:=false; - if APackage.AutoUpdate=pupManually then exit(mrNo); + if APackage.AutoUpdate=pupManually then + exit(mrNo); // check the current output directory Result:=CheckIfCurPkgOutDirNeedsCompile(APackage, true,SkipDesignTimePackages, - NeedBuildAllFlag,ConfigChanged,DependenciesChanged); + NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note); if Result=mrNo then exit; // the current output is valid // the current output directory needs compilation @@ -2888,6 +2891,7 @@ begin exit; end; debugln(['TLazPackageGraph.CheckIfPackageNeedsCompilation normal output dir is not writable: ',OutputDir]); + Note+='Normal output directory is not writable.'+LineEnding; // the normal output directory is not writable // => try the fallback directory NewOutputDir:=GetFallbackOutputDir(APackage); @@ -2895,7 +2899,7 @@ begin APackage.CompilerOptions.ParsedOpts.OutputDirectoryOverride:=NewOutputDir; Result:=CheckIfCurPkgOutDirNeedsCompile(APackage, true,SkipDesignTimePackages, - NeedBuildAllFlag,ConfigChanged,DependenciesChanged); + NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note); end else begin // the last compile was put to the fallback output directory if not ConfigChanged then begin @@ -2916,10 +2920,11 @@ begin OldNeedBuildAllFlag:=NeedBuildAllFlag; DefResult:=CheckIfCurPkgOutDirNeedsCompile(APackage, true,SkipDesignTimePackages, - NeedBuildAllFlag,ConfigChanged,DependenciesChanged); + NeedBuildAllFlag,ConfigChanged,DependenciesChanged,Note); if DefResult=mrNo then begin // switching back to the not writable output directory requires no compile debugln(['TLazPackageGraph.CheckIfPackageNeedsCompilation switching back to the normal output directory: ',APackage.GetOutputDirectory]); + Note+='Switching back to not writable output directory.'+LineEnding; exit(mrNo); end; // neither the default nor the fallback is valid @@ -2930,10 +2935,9 @@ begin end; function TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile( - APackage: TLazPackage; - CheckDependencies, SkipDesignTimePackages: boolean; - out NeedBuildAllFlag, - ConfigChanged, DependenciesChanged: boolean): TModalResult; + APackage: TLazPackage; CheckDependencies, SkipDesignTimePackages: boolean; + out NeedBuildAllFlag, ConfigChanged, DependenciesChanged: boolean; + var Note: string): TModalResult; // returns: mrYes, mrNo, mrCancel, mrAbort var StateFilename: String; @@ -2987,6 +2991,7 @@ begin if not Stats^.StateFileLoaded then begin // package was not compiled via Lazarus nor via Makefile DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Missing state file for ',APackage.IDAsString,': ',StateFilename); + Note+='Missing state file "'+StateFilename+'".'+LineEnding; ConfigChanged:=true; exit(mrYes); end; @@ -3010,6 +3015,9 @@ begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler custom params changed for ',APackage.IDAsString); DebugLn(' Old="',OldValue,'"'); DebugLn(' Now="',NewValue,'"'); + Note+='Compiler custom parameters changed:'+LineEnding + +' Old="'+OldValue+'"'+LineEnding + +' Now="'+NewValue+'"'+LineEnding; ConfigChanged:=true; exit(mrYes); end; @@ -3020,6 +3028,9 @@ begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler unit paths changed for ',APackage.IDAsString); DebugLn(' Old="',OldValue,'"'); DebugLn(' Now="',NewValue,'"'); + Note+='Compiler unit paths changed:'+LineEnding + +' Old="'+OldValue+'"'+LineEnding + +' Now="'+NewValue+'"'+LineEnding; ConfigChanged:=true; exit(mrYes); end; @@ -3030,6 +3041,9 @@ begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler include paths changed for ',APackage.IDAsString); DebugLn(' Old="',OldValue,'"'); DebugLn(' Now="',NewValue,'"'); + Note+='Compiler include paths changed:'+LineEnding + +' Old="'+OldValue+'"'+LineEnding + +' Now="'+NewValue+'"'+LineEnding; ConfigChanged:=true; exit(mrYes); end; @@ -3042,6 +3056,9 @@ begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler params changed for ',APackage.IDAsString); DebugLn(' Old="',LastParams,'"'); DebugLn(' Now="',CompilerParams,'"'); + Note+='Compiler parameters changed:'+LineEnding + +' Old="'+OldValue+'"'+LineEnding + +' Now="'+NewValue+'"'+LineEnding; ConfigChanged:=true; exit(mrYes); end; @@ -3050,26 +3067,40 @@ begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler filename changed for ',APackage.IDAsString); DebugLn(' Old="',Stats^.CompilerFilename,'"'); DebugLn(' Now="',CompilerFilename,'"'); + Note+='Compiler filename changed:'+LineEnding + +' Old="'+Stats^.CompilerFilename+'"'+LineEnding + +' Now="'+CompilerFilename+'"'+LineEnding; exit(mrYes); end; if not FileExistsCached(CompilerFilename) then begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler filename not found for ',APackage.IDAsString); DebugLn(' File="',CompilerFilename,'"'); + Note+='Compiler file "'+CompilerFilename+'" not found.'+LineEnding; exit(mrYes); end; if (not Stats^.ViaMakefile) and (FileAgeCached(CompilerFilename)<>Stats^.CompilerFileDate) then begin DebugLn('TLazPackageGraph.CheckIfCurPkgOutDirNeedsCompile Compiler file changed for ',APackage.IDAsString); DebugLn(' File="',CompilerFilename,'"'); + Note+='Compiler file "'+CompilerFilename+'" changed:'+LineEnding + +' Old='+FileAgeToStr(Stats^.CompilerFileDate)+LineEnding + +' Now='+FileAgeToStr(FileAgeCached(CompilerFilename))+LineEnding; exit(mrYes); end; // check main source file if (SrcFilename<>'') then begin - if (not FileExistsCached(SrcFilename)) or (StateFileAge