mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-10 12:02:32 +02:00
498 lines
17 KiB
ObjectPascal
498 lines
17 KiB
ObjectPascal
unit compiler_compilation_options;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
// RTL + FCL + LCL
|
|
Classes, sysutils,
|
|
Controls, StdCtrls, Dialogs, ComboEx,
|
|
// CodeTools
|
|
FileProcs, DefineTemplates, CodeToolManager, LinkScanner,
|
|
// LazUtils
|
|
FileUtil, LazFileUtils,
|
|
// IDEIntf
|
|
IDEOptionsIntf, CompOptsIntf, IDEDialogs, IDEUtils, IDEExternToolIntf,
|
|
// IDE
|
|
Project, CompilerOptions, PackageDefs, LazarusIDEStrConsts, EnvironmentOpts,
|
|
LazConf, IDEProcs, DialogProcs, InputHistory, InitialSetupProc;
|
|
|
|
type
|
|
|
|
{ TCompilerCompilationOptionsFrame }
|
|
|
|
TCompilerCompilationOptionsFrame = class(TAbstractIDEOptionsEditor)
|
|
BrowseCompilerButton: TButton;
|
|
ExecAfterParsersCheckComboBox: TCheckComboBox;
|
|
ExecAfterParsersLabel: TLabel;
|
|
ExecAfterParsersSumLabel: TLabel;
|
|
ExecBeforeBrowseButton: TButton;
|
|
chkCompilerBuild: TCheckBox;
|
|
chkCompilerCompile: TCheckBox;
|
|
chkCompilerRun: TCheckBox;
|
|
chkCreateMakefile: TCheckBox;
|
|
chkExecAfterBuild: TCheckBox;
|
|
chkExecAfterCompile: TCheckBox;
|
|
chkExecAfterRun: TCheckBox;
|
|
chkExecBeforeBuild: TCheckBox;
|
|
chkExecBeforeCompile: TCheckBox;
|
|
chkExecBeforeRun: TCheckBox;
|
|
cobCompiler: TComboBox;
|
|
ExecAfterBrowseButton: TButton;
|
|
ExecBeforeParsersSumLabel: TLabel;
|
|
ExecuteAfterCommandComboBox: TComboBox;
|
|
ExecuteAfterCommandLabel: TLabel;
|
|
ExecuteAfterGroupBox: TGroupBox;
|
|
ExecuteBeforeCommandComboBox: TComboBox;
|
|
ExecuteBeforeCommandLabel: TLabel;
|
|
ExecuteBeforeGroupBox: TGroupBox;
|
|
ExecBeforeParsersCheckComboBox: TCheckComboBox;
|
|
ExecBeforeParsersLabel: TLabel;
|
|
grpCompiler: TGroupBox;
|
|
lblCompiler: TLabel;
|
|
lblRunIfCompiler: TLabel;
|
|
lblRunIfExecAfter: TLabel;
|
|
lblRunIfExecBefore: TLabel;
|
|
procedure CompCmdBrowseButtonClick(Sender: TObject);
|
|
procedure ExecAfterParsersCheckComboBoxItemChange(Sender: TObject;
|
|
{%H-}AIndex: Integer);
|
|
procedure ExecBeforeParsersCheckComboBoxItemChange(Sender: TObject;
|
|
{%H-}AIndex: Integer);
|
|
private
|
|
procedure ReadSettingsParsers(ToolOpts: TCompilationToolOptions;
|
|
Cmb: TCheckComboBox; Lbl: TLabel);
|
|
procedure WriteSettingsParsers(ToolOpts: TCompilationToolOptions;
|
|
Cmb: TCheckComboBox);
|
|
procedure UpdateParsersLabel(Lbl: TLabel; Cmb: TCheckComboBox);
|
|
public
|
|
function GetTitle: string; override;
|
|
procedure Setup({%H-}ADialog: TAbstractOptionsEditorDialog); override;
|
|
procedure ReadSettings(AOptions: TAbstractIDEOptions); override;
|
|
procedure WriteSettings(AOptions: TAbstractIDEOptions); override;
|
|
class function SupportedOptionsClass: TAbstractIDEOptionsClass; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
{ TCompilerCompilationOptionsFrame }
|
|
|
|
procedure TCompilerCompilationOptionsFrame.CompCmdBrowseButtonClick(
|
|
Sender: TObject);
|
|
|
|
function ShowQuality(Quality: TSDFilenameQuality;
|
|
const Filename, Note: string): boolean;
|
|
begin
|
|
if Quality<>sddqCompatible then begin
|
|
if IDEMessageDialog(lisCCOWarningCaption, Format(
|
|
lisTheCompilerFileDoesNotLookCorrect, [Filename, #13, Note]),
|
|
mtWarning,[mbIgnore,mbCancel])<>mrIgnore
|
|
then
|
|
exit(false);
|
|
end;
|
|
Result:=true;
|
|
end;
|
|
|
|
var
|
|
OpenDialog: TOpenDialog;
|
|
NewFilename: string;
|
|
Quality: TSDFilenameQuality;
|
|
Note: string;
|
|
s: string;
|
|
OldFilename: string;
|
|
OldParams: string;
|
|
Combo: TComboBox;
|
|
ok: Boolean;
|
|
Kind: TPascalCompiler;
|
|
begin
|
|
OpenDialog:=TOpenDialog.Create(nil);
|
|
try
|
|
InputHistories.ApplyFileDialogSettings(OpenDialog);
|
|
OpenDialog.Options:=OpenDialog.Options+[ofFileMustExist];
|
|
OpenDialog.Filter:=dlgFilterAll+'|'+GetAllFilesMask;
|
|
OldFilename:='';
|
|
OldParams:='';
|
|
// set title
|
|
if Sender=BrowseCompilerButton then begin
|
|
Combo:=cobCompiler;
|
|
OpenDialog.Title:=Format(lisChooseCompilerExecutable,[GetDefaultCompilerFilename])
|
|
end else if (Sender=ExecAfterBrowseButton) then begin
|
|
Combo:=ExecuteAfterCommandComboBox;
|
|
OpenDialog.Title:=lisChooseExecutable;
|
|
SplitCmdLine(Combo.Text,OldFilename,OldParams);
|
|
end else if (Sender=ExecBeforeBrowseButton) then begin
|
|
Combo:=ExecuteBeforeCommandComboBox;
|
|
OpenDialog.Title:=lisChooseExecutable;
|
|
SplitCmdLine(Combo.Text,OldFilename,OldParams);
|
|
end else
|
|
exit;
|
|
|
|
if not OpenDialog.Execute then exit;
|
|
NewFilename:=TrimAndExpandFilename(OpenDialog.Filename);
|
|
// check, even if new file is old filename, so the user see the warnings again
|
|
ok:=false;
|
|
if Sender=BrowseCompilerButton then begin
|
|
// check compiler filename
|
|
case GetPascalCompilerFromExeName(NewFilename) of
|
|
pcPas2js:
|
|
if IsPas2JSExecutable(NewFilename,s) then begin
|
|
// check pas2js
|
|
Quality:=CheckPas2jsQuality(NewFilename,Note,
|
|
CodeToolBoss.CompilerDefinesCache.TestFilename);
|
|
if not ShowQuality(Quality,NewFilename,Note) then exit;
|
|
ok:=true;
|
|
end;
|
|
else
|
|
if IsCompilerExecutable(NewFilename,s,Kind) then begin
|
|
// check compiler
|
|
if Kind=pcPas2js then
|
|
Quality:=CheckPas2jsQuality(NewFilename,Note,
|
|
CodeToolBoss.CompilerDefinesCache.TestFilename)
|
|
else
|
|
Quality:=CheckFPCExeQuality(NewFilename,Note,
|
|
CodeToolBoss.CompilerDefinesCache.TestFilename);
|
|
if not ShowQuality(Quality,NewFilename,Note) then exit;
|
|
ok:=true;
|
|
end;
|
|
end;
|
|
// maybe a script
|
|
if (not ok)
|
|
and not CheckExecutable(OldFilename,NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
|
|
then
|
|
exit;
|
|
ok:=true;
|
|
end else if (Sender=ExecBeforeBrowseButton)
|
|
or (Sender=ExecAfterBrowseButton) then begin
|
|
// check executable
|
|
if not CheckExecutable(OldFilename,NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
|
|
then
|
|
exit;
|
|
ok:=true;
|
|
end;
|
|
SetComboBoxText(Combo,NewFilename,cstFilename);
|
|
finally
|
|
InputHistories.StoreFileDialogSettings(OpenDialog);
|
|
OpenDialog.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.
|
|
ExecAfterParsersCheckComboBoxItemChange(Sender: TObject; AIndex: Integer);
|
|
begin
|
|
UpdateParsersLabel(ExecAfterParsersSumLabel,ExecAfterParsersCheckComboBox);
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.
|
|
ExecBeforeParsersCheckComboBoxItemChange(Sender: TObject; AIndex: Integer);
|
|
begin
|
|
UpdateParsersLabel(ExecBeforeParsersSumLabel,ExecBeforeParsersCheckComboBox);
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.ReadSettingsParsers(
|
|
ToolOpts: TCompilationToolOptions; Cmb: TCheckComboBox; Lbl: TLabel);
|
|
const
|
|
BoolToChecked: array[boolean] of TCheckBoxState = (cbUnchecked,cbChecked);
|
|
var
|
|
l: TFPList;
|
|
i, j: Integer;
|
|
ParserClass: TExtToolParserClass;
|
|
s: String;
|
|
begin
|
|
l:=TFPList.Create;
|
|
try
|
|
// add registered parsers
|
|
for i:=0 to ExternalToolList.ParserCount-1 do
|
|
begin
|
|
ParserClass:=ExternalToolList.Parsers[i];
|
|
j:=0;
|
|
while (j<l.Count)
|
|
and (TExtToolParserClass(l[j]).Priority>=ParserClass.Priority) do
|
|
inc(j);
|
|
l.Insert(j,ParserClass);
|
|
end;
|
|
Cmb.Clear;
|
|
for i:=0 to l.Count-1 do
|
|
begin
|
|
ParserClass:=TExtToolParserClass(l[i]);
|
|
s:=ParserClass.GetLocalizedParserName;
|
|
Cmb.AddItem(s,BoolToChecked[ToolOpts.HasParser[ParserClass.GetParserName]]);
|
|
end;
|
|
// add not registered parsers
|
|
// Note: this happens when opening a project, which needs a designtime-package
|
|
for i:=0 to ToolOpts.Parsers.Count-1 do
|
|
begin
|
|
s:=ToolOpts.Parsers[i];
|
|
if ExternalToolList.FindParserWithName(s)=nil then
|
|
Cmb.AddItem(s,cbChecked);
|
|
end;
|
|
UpdateParsersLabel(Lbl,Cmb);
|
|
finally
|
|
l.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.WriteSettingsParsers(
|
|
ToolOpts: TCompilationToolOptions; Cmb: TCheckComboBox);
|
|
var
|
|
sl: TStringList;
|
|
i, j: Integer;
|
|
begin
|
|
sl:=TStringList.Create;
|
|
try
|
|
for i:=0 to Cmb.Items.Count-1 do
|
|
if Cmb.Checked[i] then begin
|
|
j:=ExternalToolList.ParserCount-1;
|
|
while (j>=0)
|
|
and (Cmb.Items[i]<>ExternalToolList.Parsers[i].GetLocalizedParserName) do
|
|
dec(j);
|
|
if j>=0 then
|
|
sl.Add(ExternalToolList.Parsers[i].GetParserName)
|
|
else
|
|
sl.Add(Cmb.Items[i]); // not registered parser
|
|
end;
|
|
ToolOpts.Parsers:=sl;
|
|
finally
|
|
sl.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.UpdateParsersLabel(Lbl: TLabel;
|
|
Cmb: TCheckComboBox);
|
|
var
|
|
s: String;
|
|
i: Integer;
|
|
begin
|
|
s:='';
|
|
for i:=0 to Cmb.Items.Count-1 do
|
|
begin
|
|
if Cmb.Checked[i] then
|
|
begin
|
|
if s<>'' then s:=s+', ';
|
|
s:=s+Cmb.Items[i];
|
|
end;
|
|
end;
|
|
Lbl.Caption:=s;
|
|
end;
|
|
|
|
function TCompilerCompilationOptionsFrame.GetTitle: string;
|
|
begin
|
|
Result := dlgCOCompilerCommands;
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.Setup(ADialog: TAbstractOptionsEditorDialog);
|
|
begin
|
|
chkCreateMakefile.Caption := dlgCOCreateMakefile;
|
|
chkCreateMakefile.Hint := lisEnabledOnlyForPackages;
|
|
|
|
ExecuteBeforeGroupBox.Caption := lisCOExecuteBefore;
|
|
lblRunIfExecBefore.Caption := lisCOCallOn;
|
|
chkExecBeforeBuild.Caption := lisBuildStage;
|
|
chkExecBeforeCompile.Caption := lisCompileStage;
|
|
chkExecBeforeRun.Caption := lisRunStage;
|
|
ExecuteBeforeCommandComboBox.Text := '';
|
|
ExecuteBeforeCommandLabel.Caption := lisCOCommand;
|
|
ExecBeforeParsersLabel.Caption:=lisParsers;
|
|
|
|
grpCompiler.Caption := lisCompiler;
|
|
lblRunIfCompiler.Caption := lisCOCallOn;
|
|
chkCompilerBuild.Caption := lisBuildStage;
|
|
chkCompilerBuild.Checked := True;
|
|
chkCompilerCompile.Caption := lisCompileStage;
|
|
chkCompilerCompile.Checked := True;
|
|
chkCompilerRun.Caption := lisRunStage;
|
|
chkCompilerRun.Checked := True;
|
|
lblCompiler.Caption := lisCOCommand;
|
|
cobCompiler.Text := '';
|
|
BrowseCompilerButton.Hint:=lisBrowseAndSelectACompiler+ExeExt+')';
|
|
|
|
ExecuteAfterGroupBox.Caption := lisCOExecuteAfter;
|
|
chkExecAfterBuild.Caption := lisBuildStage;
|
|
chkExecAfterCompile.Caption := lisCompileStage;
|
|
chkExecAfterRun.Caption := lisRunStage;
|
|
ExecuteAfterCommandComboBox.Text := '';
|
|
ExecuteAfterCommandLabel.Caption := lisCOCommand;
|
|
ExecAfterParsersLabel.Caption:=lisParsers;
|
|
lblRunIfExecAfter.Caption := lisCOCallOn;
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.ReadSettings(AOptions: TAbstractIDEOptions);
|
|
var
|
|
Options: TBaseCompilerOptions absolute AOptions;
|
|
begin
|
|
chkCreateMakefile.Checked := Options.CreateMakefileOnBuild;
|
|
|
|
// execute before
|
|
with ExecuteBeforeCommandComboBox do begin
|
|
Items.BeginUpdate;
|
|
Items.Assign(InputHistories.HistoryLists.GetList('BuildExecBefore',true,rltFile));
|
|
SetComboBoxText(ExecuteBeforeCommandComboBox,Options.ExecuteBefore.Command,cstCaseSensitive);
|
|
Items.EndUpdate;
|
|
end;
|
|
if Options.ExecuteBefore is TProjectCompilationToolOptions then
|
|
with TProjectCompilationToolOptions(Options.ExecuteBefore) do
|
|
begin
|
|
chkExecBeforeCompile.Checked := crCompile in CompileReasons;
|
|
chkExecBeforeBuild.Checked := crBuild in CompileReasons;
|
|
chkExecBeforeRun.Checked := crRun in CompileReasons;
|
|
lblRunIfExecBefore.Visible := True;
|
|
chkExecBeforeCompile.Visible := True;
|
|
chkExecBeforeBuild.Visible := True;
|
|
chkExecBeforeRun.Visible := True;
|
|
end
|
|
else
|
|
begin
|
|
lblRunIfExecBefore.Visible := False;
|
|
chkExecBeforeCompile.Visible := False;
|
|
chkExecBeforeBuild.Visible := False;
|
|
chkExecBeforeRun.Visible := False;
|
|
end;
|
|
ReadSettingsParsers(Options.ExecuteBefore,ExecBeforeParsersCheckComboBox,
|
|
ExecBeforeParsersSumLabel);
|
|
|
|
// compiler path
|
|
with cobCompiler do begin
|
|
Items.BeginUpdate;
|
|
Items.Assign(EnvironmentOptions.CompilerFileHistory);
|
|
AddFilenameToList(Items,DefaultCompilerPath);
|
|
SetComboBoxText(cobCompiler,Options.CompilerPath,cstFilename);
|
|
Items.EndUpdate;
|
|
end;
|
|
if Options is TProjectCompilerOptions then
|
|
with TProjectCompilerOptions(Options) do
|
|
begin
|
|
chkCreateMakefile.Enabled:=false;
|
|
lblRunIfCompiler.Visible := True;
|
|
chkCompilerCompile.AnchorToNeighbour(akLeft, 30, lblRunIfCompiler);
|
|
chkCompilerCompile.Checked := crCompile in CompileReasons;
|
|
chkCompilerBuild.Checked := crBuild in CompileReasons;
|
|
chkCompilerRun.Checked := crRun in CompileReasons;
|
|
chkCompilerCompile.Caption := lisCompileStage;
|
|
chkCompilerCompile.Visible := True;
|
|
chkCompilerBuild.Visible := True;
|
|
chkCompilerRun.Visible := True;
|
|
cobCompiler.AnchorToNeighbour(akTop, 0, chkCompilerCompile);
|
|
end
|
|
else if Options is TPkgCompilerOptions then
|
|
begin
|
|
chkCreateMakefile.Enabled:=true;
|
|
lblRunIfCompiler.Visible := False;
|
|
chkCompilerCompile.AnchorParallel(akTop, 6, chkCompilerCompile.Parent);
|
|
chkCompilerCompile.AnchorParallel(akLeft, 6, chkCompilerCompile.Parent);
|
|
chkCompilerCompile.Visible := True;
|
|
chkCompilerCompile.Caption := lisCOSkipCallingCompiler;
|
|
chkCompilerCompile.Checked := TPkgCompilerOptions(Options).SkipCompiler;
|
|
chkCompilerBuild.Visible := False;
|
|
chkCompilerRun.Visible := False;
|
|
cobCompiler.AnchorToNeighbour(akTop, 0, chkCompilerCompile);
|
|
end
|
|
else
|
|
begin
|
|
lblRunIfCompiler.Visible := False;
|
|
chkCompilerCompile.Visible := False;
|
|
chkCompilerBuild.Visible := False;
|
|
chkCompilerRun.Visible := False;
|
|
cobCompiler.AnchorParallel(akTop, 0, lblCompiler.Parent);
|
|
end;
|
|
|
|
// execute after
|
|
with ExecuteAfterCommandComboBox do begin
|
|
Items.BeginUpdate;
|
|
Items.Assign(InputHistories.HistoryLists.GetList('BuildExecAfter',true,rltFile));
|
|
SetComboBoxText(ExecuteAfterCommandComboBox,Options.ExecuteAfter.Command,cstCaseSensitive);
|
|
Items.EndUpdate;
|
|
end;
|
|
if Options.ExecuteAfter is TProjectCompilationToolOptions then
|
|
with TProjectCompilationToolOptions(Options.ExecuteAfter) do
|
|
begin
|
|
chkExecAfterCompile.Checked := crCompile in CompileReasons;
|
|
chkExecAfterBuild.Checked := crBuild in CompileReasons;
|
|
chkExecAfterRun.Checked := crRun in CompileReasons;
|
|
lblRunIfExecAfter.Visible := True;
|
|
chkExecAfterCompile.Visible := True;
|
|
chkExecAfterBuild.Visible := True;
|
|
chkExecAfterRun.Visible := True;
|
|
end
|
|
else
|
|
begin
|
|
lblRunIfExecAfter.Visible := False;
|
|
chkExecAfterCompile.Visible := False;
|
|
chkExecAfterBuild.Visible := False;
|
|
chkExecAfterRun.Visible := False;
|
|
end;
|
|
ReadSettingsParsers(Options.ExecuteAfter,ExecAfterParsersCheckComboBox,
|
|
ExecAfterParsersSumLabel);
|
|
end;
|
|
|
|
procedure TCompilerCompilationOptionsFrame.WriteSettings(AOptions: TAbstractIDEOptions);
|
|
|
|
function MakeCompileReasons(const ACompile, ABuild, ARun: TCheckBox): TCompileReasons;
|
|
begin
|
|
Result := [];
|
|
if ACompile.Checked then Include(Result, crCompile);
|
|
if ABuild.Checked then Include(Result, crBuild);
|
|
if ARun.Checked then Include(Result, crRun);
|
|
end;
|
|
|
|
var
|
|
Options: TBaseCompilerOptions absolute AOptions;
|
|
begin
|
|
Options.CreateMakefileOnBuild := chkCreateMakefile.Checked;
|
|
|
|
// execute before
|
|
Options.ExecuteBefore.Command := ExecuteBeforeCommandComboBox.Text;
|
|
with InputHistories.HistoryLists.GetList('BuildExecBefore',true,rltCaseSensitive) do begin
|
|
Assign(ExecuteBeforeCommandComboBox.Items);
|
|
Push(Options.ExecuteBefore.Command);
|
|
end;
|
|
|
|
WriteSettingsParsers(Options.ExecuteBefore,ExecBeforeParsersCheckComboBox);
|
|
|
|
if Options.ExecuteBefore is TProjectCompilationToolOptions then
|
|
begin
|
|
TProjectCompilationToolOptions(Options.ExecuteBefore).CompileReasons :=
|
|
MakeCompileReasons(chkExecBeforeCompile, chkExecBeforeBuild, chkExecBeforeRun);
|
|
end;
|
|
|
|
// compiler path
|
|
Options.CompilerPath := cobCompiler.Text;
|
|
EnvironmentOptions.CompilerFileHistory.Assign(cobCompiler.Items);
|
|
AddToRecentList(Options.CompilerPath,EnvironmentOptions.CompilerFileHistory,30,rltFile);
|
|
|
|
if Options is TProjectCompilerOptions then
|
|
begin
|
|
TProjectCompilerOptions(Options).CompileReasons :=
|
|
MakeCompileReasons(chkCompilerCompile, chkCompilerBuild, chkCompilerRun);
|
|
end
|
|
else if Options is TPkgCompilerOptions then
|
|
TPkgCompilerOptions(Options).SkipCompiler := chkCompilerCompile.Checked;
|
|
|
|
// execute after
|
|
Options.ExecuteAfter.Command := ExecuteAfterCommandComboBox.Text;
|
|
with InputHistories.HistoryLists.GetList('BuildExecAfter',true,rltCaseSensitive) do begin
|
|
Assign(ExecuteAfterCommandComboBox.Items);
|
|
Push(Options.ExecuteAfter.Command);
|
|
end;
|
|
WriteSettingsParsers(Options.ExecuteAfter,ExecAfterParsersCheckComboBox);
|
|
if Options.ExecuteAfter is TProjectCompilationToolOptions then
|
|
begin
|
|
TProjectCompilationToolOptions(Options.ExecuteAfter).CompileReasons :=
|
|
MakeCompileReasons(chkExecAfterCompile, chkExecAfterBuild, chkExecAfterRun);
|
|
end;
|
|
end;
|
|
|
|
class function TCompilerCompilationOptionsFrame.SupportedOptionsClass: TAbstractIDEOptionsClass;
|
|
begin
|
|
Result := TBaseCompilerOptions;
|
|
end;
|
|
|
|
initialization
|
|
RegisterIDEOptionsEditor(GroupCompiler, TCompilerCompilationOptionsFrame,
|
|
CompilerOptionsCompilation);
|
|
RegisterIDEOptionsEditor(GroupPkgCompiler, TCompilerCompilationOptionsFrame,
|
|
CompilerOptionsCompilation);
|
|
|
|
end.
|
|
|