IDE: fixed checking type of compiler (fpc/pas2js), fixed quoting compiler filename, improved error handling

git-svn-id: trunk@60535 -
This commit is contained in:
mattias 2019-02-28 16:18:36 +00:00
parent acf40b5480
commit ad2827a4e5
13 changed files with 368 additions and 246 deletions

View File

@ -809,11 +809,11 @@ type
// values
Kind: TPascalCompiler;
CompilerDate: longint;
RealCompiler: string; // when Compiler is fpc, this is the real compiler (e.g. ppc386)
RealCompiler: string; // when Compiler is fpc.exe, this is the real compiler (e.g. ppc386.exe)
RealCompilerDate: longint;
RealTargetOS: string;
RealTargetCPU: string;
RealCompilerInPath: string; // the ppc<target> in PATH
RealTargetCPUCompiler: string; // the ppc<target>.exe in PATH for TargetCPU
FullVersion: string; // Version.Release.Patch
ConfigFiles: TPCConfigFileStateList;
UnitPaths: TStrings;
@ -843,7 +843,7 @@ type
function GetFPCInfoCmdLineOptions(ExtraOptions: string): string;
function Update(TestFilename: string; ExtraOptions: string = '';
const OnProgress: TDefinePoolProgress = nil): boolean;
function FindRealCompilerInPath(aTargetCPU: string; ResolveLinks: boolean): string;
function FindDefaultTargetCPUCompiler(aTargetCPU: string; ResolveLinks: boolean): string;
function GetUnitPaths: string;
function GetFPCVerNumbers(out FPCVersion, FPCRelease, FPCPatch: integer): boolean;
function GetFPCVer: string; // e.g. 2.7.1
@ -1066,11 +1066,14 @@ function GetDefaultCompilerFilename(const TargetCPU: string = ''; Cross: boolean
procedure GetTargetProcessors(const TargetCPU: string; aList: TStrings);
function GetFPCTargetOS(TargetOS: string): string; // normalize
function GetFPCTargetCPU(TargetCPU: string): string; // normalize
function GetPascalCompilerFromExeName(Filename: string): TPascalCompiler;
function IsCTExecutable(AFilename: string; out ErrorMsg: string): boolean; // not thread-safe
function IsCompilerExecutable(AFilename: string; out ErrorMsg: string; out Kind: TPascalCompiler): boolean; // not thread-safe
function IsFPCExecutable(AFilename: string; out ErrorMsg: string): boolean; // not thread-safe
function IsPas2JSExecutable(AFilename: string; out ErrorMsg: string): boolean; // not thread-safe
function GuessPascalCompilerFromExeName(Filename: string): TPascalCompiler;
function IsCompilerExecutable(AFilename: string; out ErrorMsg: string;
out Kind: TPascalCompiler; Run: boolean): boolean; // not thread-safe
function IsFPCExecutable(AFilename: string; out ErrorMsg: string; Run: boolean): boolean; // not thread-safe
function IsPas2JSExecutable(AFilename: string; out ErrorMsg: string; Run: boolean): boolean; // not thread-safe
// functions to quickly setup some defines
function CreateDefinesInDirectories(const SourcePaths, FlagName: string
@ -1100,14 +1103,13 @@ type
const
AllFPCFrontEndParams = [low(TFPCFrontEndParam)..high(TFPCFrontEndParam)];
function GuessCompilerType(Filename: string): TPascalCompiler;
function ParseFPCInfo(FPCInfo: string; InfoTypes: TFPCInfoTypes;
out Infos: TFPCInfoStrings): boolean;
function RunFPCInfo(const CompilerFilename: string;
InfoTypes: TFPCInfoTypes; const Options: string =''): string;
function FPCVersionToNumber(const FPCVersionString: string): integer;
function FPCVersionToNumber(const FPCVersionString: string): integer; // 2.7.1 -> 20701
function SplitFPCVersion(const FPCVersionString: string;
out FPCVersion, FPCRelease, FPCPatch: integer): boolean;
out FPCVersion, FPCRelease, FPCPatch: integer): boolean; // 2.7.1 -> 2,7,1
function ParseFPCVerbose(List: TStrings; // fpc -va output
const WorkDir: string;
out ConfigFiles: TStrings; // prefix '-' for file not found, '+' for found and read
@ -1136,24 +1138,24 @@ procedure GatherUnitsInFPMSources(Units: TStringToStringTree; // unit names to f
function GatherUnitSourcesInDirectory(Directory: string;
MaxLevel: integer = 1): TStringToStringTree; // unit names to full file name
procedure AdjustFPCSrcRulesForPPUPaths(Units: TStringToStringTree;
Rules: TFPCSourceRules);
Rules: TFPCSourceRules); // not for pas2js
function GatherUnitsInFPCSources(Files: TStringList;
TargetOS: string = ''; TargetCPU: string = '';
Duplicates: TStringToStringTree = nil; // unit to semicolon separated list of files
Rules: TFPCSourceRules = nil;
const DebugUnitName: string = ''): TStringToStringTree;
const DebugUnitName: string = ''): TStringToStringTree; // not for pas2js
function CreateFPCTemplate(Config: TPCTargetConfigCache;
Owner: TObject): TDefineTemplate; overload;
function CreateFPCTemplate(Config: TFPCUnitSetCache;
Owner: TObject): TDefineTemplate; overload;
function CreateFPCSourceTemplate(Config: TFPCUnitSetCache;
Owner: TObject): TDefineTemplate; overload;
Owner: TObject): TDefineTemplate; overload; // not for pas2js
function CreateFPCSourceTemplate(FPCSrcDir: string;
Owner: TObject): TDefineTemplate; overload;
Owner: TObject): TDefineTemplate; overload; // not for pas2js
procedure CheckPPUSources(PPUFiles, // unitname to filename
UnitToSource, // unitname to file name
UnitToDuplicates: TStringToStringTree; // unitname to semicolon separated list of files
var Duplicates, Missing: TStringToStringTree);
var Duplicates, Missing: TStringToStringTree); // not for pas2js
procedure LoadFPCCacheFromFile(Filename: string;
var Configs: TPCTargetConfigCaches; var Sources: TFPCSourceCaches);
procedure SaveFPCCacheToFile(Filename: string;
@ -1521,14 +1523,6 @@ begin
end;
end;
function GuessCompilerType(Filename: string): TPascalCompiler;
begin
Filename:=ExtractFileNameOnly(Filename);
if Pos('pas2js',lowercase(Filename))>0 then
exit(pcPas2js);
Result:=pcFPC;
end;
function ParseFPCInfo(FPCInfo: string; InfoTypes: TFPCInfoTypes;
out Infos: TFPCInfoStrings): boolean;
var
@ -1557,29 +1551,32 @@ end;
function RunFPCInfo(const CompilerFilename: string;
InfoTypes: TFPCInfoTypes; const Options: string): string;
var
Params: String;
Param: String;
List: TStringList;
Params: TStringListUTF8;
begin
Result:='';
Params:='';
if fpciCompilerDate in InfoTypes then Params:=Params+'D';
if fpciShortVersion in InfoTypes then Params:=Params+'V';
if fpciFullVersion in InfoTypes then Params:=Params+'W';
if fpciCompilerOS in InfoTypes then Params:=Params+'SO';
if fpciCompilerProcessor in InfoTypes then Params:=Params+'SP';
if fpciTargetOS in InfoTypes then Params:=Params+'TO';
if fpciTargetProcessor in InfoTypes then Params:=Params+'TP';
if Params='' then exit;
Params:='-i'+Params;
if Options<>'' then
Params:=Params+' '+Options;
Param:='';
if fpciCompilerDate in InfoTypes then Param:=Param+'D';
if fpciShortVersion in InfoTypes then Param:=Param+'V';
if fpciFullVersion in InfoTypes then Param:=Param+'W';
if fpciCompilerOS in InfoTypes then Param:=Param+'SO';
if fpciCompilerProcessor in InfoTypes then Param:=Param+'SP';
if fpciTargetOS in InfoTypes then Param:=Param+'TO';
if fpciTargetProcessor in InfoTypes then Param:=Param+'TP';
if Param='' then exit;
Param:='-i'+Param;
List:=nil;
Params:=TStringListUTF8.Create;
try
Params.Add(Param);
SplitCmdLineParams(Options,Params);
List:=RunTool(CompilerFilename,Params);
if (List=nil) or (List.Count<1) then exit;
Result:=List[0];
if copy(Result,1,6)='Error:' then Result:='';
finally
Params.Free;
List.free;
end;
end;
@ -1840,7 +1837,7 @@ function RunFPCVerbose(const CompilerFilename, TestFilename: string; out
UnitPaths: TStrings; out IncludePaths: TStrings; out UnitScopes: TStrings;
out Defines, Undefines: TStringToStringTree; const Options: string): boolean;
var
Params: String;
Params: TStringListUTF8;
Filename: String;
WorkDir: String;
List: TStringList;
@ -1855,23 +1852,28 @@ begin
Defines:=nil;
Undefines:=nil;
// create empty file
try
fs:=TFileStreamUTF8.Create(TestFilename,fmCreate);
fs.Free;
except
debugln(['Warning: [RunFPCVerbose] unable to create test file "'+TestFilename+'"']);
exit;
end;
Params:='-va';
if Options<>'' then
Params:=Params+' '+Options;
Filename:=ExtractFileName(TestFilename);
WorkDir:=ExtractFilePath(TestFilename);
Params:=Params+' '+Filename;
Params:=TStringListUTF8.Create;
List:=nil;
try
Params.Add('-va');
if TestFilename<>'' then begin
// create empty file
try
fs:=TFileStreamUTF8.Create(TestFilename,fmCreate);
fs.Free;
except
debugln(['Warning: [RunFPCVerbose] unable to create test file "'+TestFilename+'"']);
exit;
end;
Filename:=ExtractFileName(TestFilename);
WorkDir:=ExtractFilePath(TestFilename);
Params.Add(Filename);
end else
WorkDir:='';
SplitCmdLineParams(Options,Params);
//DebugLn(['RunFPCVerbose ',CompilerFilename,' ',Params,' ',WorkDir]);
List:=RunTool(CompilerFilename,Params,WorkDir);
if (List=nil) or (List.Count=0) then begin
@ -1881,8 +1883,10 @@ begin
Result:=ParseFPCVerbose(List,WorkDir,ConfigFiles,RealCompilerFilename,
UnitPaths,IncludePaths,UnitScopes,Defines,Undefines);
finally
Params.Free;
List.Free;
DeleteFileUTF8(TestFilename);
if TestFilename<>'' then
DeleteFileUTF8(TestFilename);
end;
end;
@ -3844,25 +3848,6 @@ begin
Result:=LowerCase(TargetCPU);
end;
function GetPascalCompilerFromExeName(Filename: string): TPascalCompiler;
var
ShortFilename: String;
begin
ShortFilename:=ExtractFileNameOnly(Filename);
// pas2js*
if CompareText(LeftStr(ShortFilename,6),'pas2js')=0 then
exit(pcPas2js);
// dcc*.exe
if (CompareFilenames(LeftStr(ShortFilename,3),'dcc')=0)
and ((ExeExt='') or (CompareFileExt(Filename,ExeExt)=0))
then
exit(pcDelphi);
Result:=pcFPC;
end;
function IsCTExecutable(AFilename: string; out ErrorMsg: string): boolean;
begin
Result:=false;
@ -3893,10 +3878,32 @@ begin
Result:=true;
end;
function IsCompilerExecutable(AFilename: string; out ErrorMsg: string; out
Kind: TPascalCompiler): boolean;
function GuessPascalCompilerFromExeName(Filename: string): TPascalCompiler;
var
ShortFilename: String;
begin
ShortFilename:=ExtractFileNameOnly(Filename);
// pas2js*
if CompareText(LeftStr(ShortFilename,6),'pas2js')=0 then
exit(pcPas2js);
// dcc*.exe
if (CompareFilenames(LeftStr(ShortFilename,3),'dcc')=0)
and ((ExeExt='') or (CompareFileExt(Filename,ExeExt)=0))
then
exit(pcDelphi);
Result:=pcFPC;
end;
function IsCompilerExecutable(AFilename: string; out ErrorMsg: string; out
Kind: TPascalCompiler; Run: boolean): boolean;
var
ShortFilename, Line: String;
Params: TStringListUTF8;
Lines: TStringList;
i: Integer;
begin
Result:=IsCTExecutable(AFilename,ErrorMsg);
if not Result then exit;
@ -3905,27 +3912,74 @@ begin
// allow scripts like fpc.sh and fpc.bat
ShortFilename:=ExtractFileNameOnly(AFilename);
//debugln(['IsFPCompiler Short=',ShortFilename]);
if CompareFilenames(ShortFilename,'fpc')=0 then
exit(true);
// allow ppcxxx.exe
// check ppc*.exe
if (CompareFilenames(LeftStr(ShortFilename,3),'ppc')=0)
and ((ExeExt='') or (CompareFileExt(AFilename,ExeExt)=0))
then
exit(true);
// check pas2js*
if CompareText(LeftStr(ShortFilename,6),'pas2js')=0 then begin
Kind:=pcPas2js;
exit(true);
end;
// dcc*.exe
if (CompareFilenames(LeftStr(ShortFilename,3),'dcc')=0)
and ((ExeExt='') or (CompareFileExt(ShortFilename,ExeExt)=0))
then begin
Kind:=pcDelphi;
exit(true);
end;
if Run then begin
// run it and check for magics
Params:=TStringListUTF8.Create;
Lines:=nil;
try
Params.Add('-va');
Lines:=RunTool(AFilename,Params);
if Lines<>nil then begin
for i:=0 to Lines.Count-1 do
begin
Line:=Lines[i];
if Pos('fpc.cfg',Line)>0 then
begin
Kind:=pcFPC;
exit(true);
end;
if Pos('pas2js.cfg',Line)>0 then
begin
Kind:=pcPas2js;
exit(true);
end;
end;
end;
finally
Params.Free;
Lines.Free;
end;
end;
// check fpc<something>
// Note: fpc.exe is just a wrapper, it can call pas2js
if CompareFilenames(ShortFilename,'fpc')=0 then
exit(true);
ErrorMsg:='fpc executable should start with fpc or ppc';
end;
function IsFPCExecutable(AFilename: string; out ErrorMsg: string): boolean;
function IsFPCExecutable(AFilename: string; out ErrorMsg: string; Run: boolean
): boolean;
var
ShortFilename: String;
Kind: TPascalCompiler;
begin
if Run then begin
Result:=IsCompilerExecutable(AFilename,ErrorMsg,Kind,true) and (Kind=pcFPC);
exit;
end;
Result:=IsCTExecutable(AFilename,ErrorMsg);
if not Result then exit;
@ -3944,10 +3998,17 @@ begin
ErrorMsg:='fpc executable should start with fpc or ppc';
end;
function IsPas2JSExecutable(AFilename: string; out ErrorMsg: string): boolean;
function IsPas2JSExecutable(AFilename: string; out ErrorMsg: string;
Run: boolean): boolean;
var
ShortFilename: String;
Kind: TPascalCompiler;
begin
if Run then begin
Result:=IsCompilerExecutable(AFilename,ErrorMsg,Kind,true) and (Kind=pcPas2js);
exit;
end;
Result:=IsCTExecutable(AFilename,ErrorMsg);
if not Result then exit;
@ -6200,7 +6261,7 @@ var
end;
end;
var CmdLine: string;
var
i, OutLen, LineStart: integer;
TheProcess: TProcessUTF8;
OutputLine, Buf: String;
@ -6208,6 +6269,7 @@ var CmdLine: string;
SrcOS: string;
SrcOS2: String;
Step: String;
Params: TStringListUTF8;
begin
Result:=nil;
//DebugLn('TDefinePool.CreateFPCTemplate PPC386Path="',CompilerPath,'" FPCOptions="',CompilerOptions,'"');
@ -6225,21 +6287,22 @@ begin
SetLength(Buf,1024);
Step:='Init';
try
CmdLine:=CompilerPath+' -va ';
if (Pos('pas2js',lowercase(ExtractFileName(CompilerPath)))<1)
and FileExistsCached(EnglishErrorMsgFilename) then
CmdLine:=CmdLine+'-Fr'+EnglishErrorMsgFilename+' ';
if CompilerOptions<>'' then
CmdLine:=CmdLine+CompilerOptions+' ';
CmdLine:=CmdLine+TestPascalFile;
//DebugLn('TDefinePool.CreateFPCTemplate CmdLine="',CmdLine,'"');
Params:=TStringListUTF8.Create;
TheProcess := TProcessUTF8.Create(nil);
TheProcess.ParseCmdLine(CmdLine);
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+CmdLine;
try
TheProcess.Executable:=CompilerPath;
Params.Add('-va');
if (Pos('pas2js',lowercase(ExtractFileName(CompilerPath)))<1)
and FileExistsCached(EnglishErrorMsgFilename) then
Params.Add('-Fr'+EnglishErrorMsgFilename);
if CompilerOptions<>'' then
SplitCmdLineParams(CompilerOptions,Params,true);
Params.Add(TestPascalFile);
//DebugLn('TDefinePool.CreateFPCTemplate Params="',MergeCmdLineParams(Params),'"');
TheProcess.Parameters:=Params;
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+MergeCmdLineParams(Params);
TheProcess.Execute;
OutputLine:='';
repeat
@ -6267,23 +6330,24 @@ begin
finally
//DebugLn('TDefinePool.CreateFPCTemplate Run with -va: OutputLine="',OutputLine,'"');
TheProcess.Free;
Params.Free;
end;
DefineSymbol(FPCUnitPathMacroName,UnitSearchPath,'FPC default unit search path');
//DebugLn('TDefinePool.CreateFPCTemplate First done UnitSearchPath="',UnitSearchPath,'"');
// ask for target operating system -> ask compiler with switch -iTO
CmdLine:=CompilerPath;
if CompilerOptions<>'' then
CmdLine:=CmdLine+' '+CompilerOptions;
CmdLine:=CmdLine+' -iTO';
Params:=TStringListUTF8.Create;
TheProcess := TProcessUTF8.Create(nil);
TheProcess.ParseCmdLine(CmdLine);
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+CmdLine;
try
TheProcess.Executable:=CompilerPath;
if CompilerOptions<>'' then
SplitCmdLineParams(CompilerOptions,Params,true);
Params.Add('-iTO');
TheProcess.Parameters:=Params;
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+MergeCmdLineParams(Params);
TheProcess.Execute;
if (TheProcess.Output<>nil) then
OutLen:=TheProcess.Output.Read(Buf[1],length(Buf))
@ -6321,19 +6385,21 @@ begin
finally
//DebugLn('TDefinePool.CreateFPCTemplate Run with -iTO: OutputLine="',OutputLine,'"');
TheProcess.Free;
Params.Free;
end;
// ask for target processor -> ask compiler with switch -iTP
Params:=TStringListUTF8.Create;
TheProcess := TProcessUTF8.Create(nil);
CmdLine:=CompilerPath;
if CompilerOptions<>'' then
CmdLine:=CmdLine+' '+CompilerOptions;
CmdLine:=CmdLine+' -iTP';
TheProcess.ParseCmdLine(CmdLine);
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+CmdLine;
try
TheProcess.Executable:=CompilerPath;
if CompilerOptions<>'' then
SplitCmdLineParams(CompilerOptions,Params,true);
Params.Add('-iTP');
TheProcess.Parameters:=Params;
TheProcess.Options:= [poUsePipes, poStdErrToOutPut];
TheProcess.ShowWindow := swoHide;
Step:='Running '+MergeCmdLineParams(Params);
TheProcess.Execute;
if TheProcess.Output<>nil then
OutLen:=TheProcess.Output.Read(Buf[1],length(Buf))
@ -7631,7 +7697,7 @@ begin
UnitPath:='';
IncPath:='';
Namespaces:='';
Params:=TStringList.Create;
Params:=TStringListUTF8.Create;
try
SplitCmdLineParams(CmdLine,Params);
for i:=0 to Params.Count-1 do begin
@ -8039,7 +8105,7 @@ begin
RealCompilerDate:=0;
RealTargetCPU:='';
RealTargetOS:='';
RealCompilerInPath:='';
RealTargetCPUCompiler:='';
FullVersion:='';
HasPPUs:=false;
ConfigFiles.Clear;
@ -8104,7 +8170,7 @@ begin
or (RealCompilerDate<>Item.RealCompilerDate)
or (RealTargetOS<>Item.RealTargetOS)
or (RealTargetCPU<>Item.RealTargetCPU)
or (RealCompilerInPath<>Item.RealCompilerInPath)
or (RealTargetCPUCompiler<>Item.RealTargetCPUCompiler)
or (FullVersion<>Item.FullVersion)
or (HasPPUs<>Item.HasPPUs)
or (not ConfigFiles.Equals(Item.ConfigFiles,true))
@ -8197,7 +8263,7 @@ begin
RealCompilerDate:=Item.RealCompilerDate;
RealTargetOS:=Item.RealTargetOS;
RealTargetCPU:=Item.RealTargetCPU;
RealCompilerInPath:=Item.RealCompilerInPath;
RealTargetCPUCompiler:=Item.RealTargetCPUCompiler;
FullVersion:=Item.FullVersion;
HasPPUs:=Item.HasPPUs;
ConfigFiles.Assign(Item.ConfigFiles);
@ -8346,7 +8412,7 @@ begin
RealCompilerDate:=XMLConfig.GetValue(Path+'RealCompiler/Date',0);
RealTargetOS:=XMLConfig.GetValue(Path+'RealCompiler/OS','');
RealTargetCPU:=XMLConfig.GetValue(Path+'RealCompiler/CPU','');
RealCompilerInPath:=XMLConfig.GetValue(Path+'RealCompiler/InPath','');
RealTargetCPUCompiler:=XMLConfig.GetValue(Path+'RealCompiler/InPath','');
FullVersion:=XMLConfig.GetValue(Path+'RealCompiler/FullVersion','');
HasPPUs:=XMLConfig.GetValue(Path+'HasPPUs',true);
ConfigFiles.LoadFromXMLConfig(XMLConfig,Path+'Configs/');
@ -8531,7 +8597,7 @@ begin
XMLConfig.SetDeleteValue(Path+'RealCompiler/Date',RealCompilerDate,0);
XMLConfig.SetDeleteValue(Path+'RealCompiler/OS',RealTargetOS,'');
XMLConfig.SetDeleteValue(Path+'RealCompiler/CPU',RealTargetCPU,'');
XMLConfig.SetDeleteValue(Path+'RealCompiler/InPath',RealCompilerInPath,'');
XMLConfig.SetDeleteValue(Path+'RealCompiler/InPath',RealTargetCPUCompiler,'');
XMLConfig.SetDeleteValue(Path+'RealCompiler/FullVersion',FullVersion,'');
XMLConfig.SetDeleteValue(Path+'HasPPUs',HasPPUs,true);
ConfigFiles.SaveToXMLConfig(XMLConfig,Path+'Configs/');
@ -8666,10 +8732,10 @@ begin
end;
// fpc searches via PATH for the real compiler, resolves any symlink
// and that is the RealCompiler
AFilename:=FindRealCompilerInPath(TargetCPU,true);
if RealCompilerInPath<>AFilename then begin
AFilename:=FindDefaultTargetCPUCompiler(TargetCPU,true);
if RealTargetCPUCompiler<>AFilename then begin
if CTConsoleVerbosity>0 then
debugln(['Hint: [TPCTargetConfigCache.NeedsUpdate] TargetOS="',TargetOS,'" TargetCPU="',TargetCPU,'" Options="',CompilerOptions,'" real compiler in PATH changed from "',RealCompilerInPath,'" to "',AFilename,'"']);
debugln(['Hint: [TPCTargetConfigCache.NeedsUpdate] TargetOS="',TargetOS,'" TargetCPU="',TargetCPU,'" Options="',CompilerOptions,'" real compiler in PATH changed from "',RealTargetCPUCompiler,'" to "',AFilename,'"']);
exit;
end;
for i:=0 to ConfigFiles.Count-1 do begin
@ -8732,7 +8798,7 @@ var
Infos: TFPCInfoStrings;
InfoTypes: TFPCInfoTypes;
BaseDir: String;
FullFilename: String;
FullFilename, KindErrorMsg: String;
begin
OldOptions:=TPCTargetConfigCache.Create(nil);
CfgFiles:=nil;
@ -8743,18 +8809,17 @@ begin
if CTConsoleVerbosity>0 then
debugln(['Hint: [TPCTargetConfigCache.NeedsUpdate] ',Compiler,' TargetOS=',TargetOS,' TargetCPU=',TargetCPU,' CompilerOptions=',CompilerOptions,' ExtraOptions=',ExtraOptions,' PATH=',GetEnvironmentVariableUTF8('PATH')]);
CompilerDate:=FileAgeCached(Compiler);
CompilerDate:=-1;
if FileExistsCached(Compiler) then begin
ExtraOptions:=GetFPCInfoCmdLineOptions(ExtraOptions);
CompilerDate:=FileAgeCached(Compiler);
ExtraOptions:=GetFPCInfoCmdLineOptions(ExtraOptions);// contains TargetOS and TargetCPU
BaseDir:='';
// kind
Kind:=GuessCompilerType(Compiler);
// get version and real OS and CPU
// get version, OS and CPU
InfoTypes:=[fpciTargetOS,fpciTargetProcessor,fpciFullVersion];
Info:=RunFPCInfo(Compiler,InfoTypes,ExtraOptions);
if ParseFPCInfo(Info,InfoTypes,Infos) then begin
// fpc or pas2js
RealTargetOS:=Infos[fpciTargetOS];
RealTargetCPU:=Infos[fpciTargetProcessor];
FullVersion:=Infos[fpciFullVersion];
@ -8766,9 +8831,6 @@ begin
if RealTargetCPU='' then
RealTargetCPU:=GetCompiledTargetCPU;
end;
if Kind=pcFPC then
RealCompilerInPath:=FindRealCompilerInPath(TargetCPU,true);
// run fpc/pas2js and parse output
HasPPUs:=false;
RunFPCVerbose(Compiler,TestFilename,CfgFiles,RealCompiler,UnitPaths,
@ -8780,8 +8842,15 @@ begin
if Defines.Contains('PAS2JS') and Defines.Contains('PAS2JS_FULLVERSION') then
Kind:=pcPas2js
else
Kind:=pcFPC;
else if Defines.Contains('FPC') and Defines.Contains('FPC_FULLVERSION') then
Kind:=pcFPC
else begin
IsCompilerExecutable(Compiler,KindErrorMsg,Kind,false);
if KindErrorMsg<>'' then
debugln(['Warning: [TPCTargetConfigCache.Update] cannot determine type of compiler: Compiler="'+Compiler+'" Options="'+ExtraOptions+'"']);
end;
if Kind=pcFPC then
RealTargetCPUCompiler:=FindDefaultTargetCPUCompiler(TargetCPU,true);
PreparePaths(UnitPaths);
PreparePaths(IncludePaths);
// store the real compiler file and date
@ -8847,7 +8916,7 @@ begin
end;
end;
function TPCTargetConfigCache.FindRealCompilerInPath(aTargetCPU: string;
function TPCTargetConfigCache.FindDefaultTargetCPUCompiler(aTargetCPU: string;
ResolveLinks: boolean): string;
function Search(const ShortFileName: string): string;
@ -9740,7 +9809,7 @@ begin
Result:={$I %FPCVersion%}
else
Result:='';
if not IsFPCExecutable(CompilerFilename,ErrorMsg) then
if not IsCTExecutable(CompilerFilename,ErrorMsg) then
exit;
CfgCache:=ConfigCaches.Find(CompilerFilename,ExtraOptions,TargetOS,TargetCPU,true);
if CfgCache.NeedsUpdate

View File

@ -571,7 +571,7 @@ procedure THeapTrcInfo.ParseTraceLine(s: string; var line: TStackLine);
var
AnId, SrcX, SrcY, SrcTopLine: Integer;
AnIsCurrent, Complete: Boolean;
AFuncName, AFile, AReminder, TheErrorMsg: String;
AFuncName, AReminder, TheErrorMsg: String;
AnArgs: TStringList;
SrcCode: TCodeBuffer;
begin

View File

@ -191,7 +191,7 @@ type
// Methods used by CreateIDEMakeOptions :
procedure BackupExe(Flags: TBuildLazarusFlags);
function CreateAppleBundle: TModalResult;
procedure AppendExtraOption(const aOption: string; EncloseIfSpace: boolean = True);
procedure AppendExtraOption(const aOption: string; AutoQuote: boolean = True);
// This is used by MakeLazarus and SaveIDEMakeOptions
function PrepareTargetDir(Flags: TBuildLazarusFlags): TModalResult;
public
@ -376,20 +376,22 @@ function TLazarusBuilder.MakeLazarus(Profile: TBuildLazarusProfile;
Flags: TBuildLazarusFlags): TModalResult;
var
Tool: TAbstractExternalTool;
Executable, CmdLineParams, Cmd: String;
Executable, Cmd: String;
CmdLineParams: TStrings;
EnvironmentOverrides: TStringList;
function Run(CurTitle: string): TModalResult;
var
Params: String;
procedure AddCmdLineParam(Param: string; ExecMacros: boolean);
begin
Params:=UTF8Trim(CmdLineParams,[]);
if fMacros<>nil then
fMacros.SubstituteStr(Params);
if Params<>'' then
Params:=Cmd+' '+Params
else
Params:=Cmd;
if Param='' then exit;
if ExecMacros and (fMacros<>nil) then
fMacros.SubstituteStr(Param);
if Param<>'' then
CmdLineParams.Add(Param);
end;
function Run(CurTitle: string): TModalResult;
begin
AddCmdLineParam(Cmd,false);
Tool:=ExternalToolList.Add(CurTitle);
Tool.Reference(Self,ClassName);
try
@ -401,7 +403,7 @@ var
Tool.AddParsers(SubToolMake);
Tool.Process.CurrentDirectory:=fWorkingDir;
Tool.EnvironmentOverrides:=EnvironmentOverrides;
Tool.CmdLineParams:=Params;
Tool.CmdLineParams:=MergeCmdLineParams(CmdLineParams);
Tool.Execute;
Tool.WaitForExit;
if Tool.ErrorMessage='' then
@ -428,6 +430,7 @@ begin
IdeBuildMode:=Profile.IdeBuildMode;
EnvironmentOverrides:=TStringList.Create;
CmdLineParams:=TStringListUTF8.Create;
Tool:=nil;
try
// setup external tool
@ -451,13 +454,17 @@ begin
end;
// add -w option to print leaving/entering messages of "make"
CmdLineParams:=' -w';
AddCmdLineParam('-w',false);
// append target OS
if fTargetOS<>fCompilerTargetOS then
CmdLineParams+=' OS_TARGET='+fTargetOS+' OS_SOURCE='+fTargetOS;
if fTargetOS<>fCompilerTargetOS then begin
AddCmdLineParam('OS_TARGET='+fTargetOS,true);
AddCmdLineParam('OS_SOURCE='+fTargetOS,true);
end;
// append target CPU
if fTargetCPU<>fCompilerTargetCPU then
CmdLineParams+=' CPU_TARGET='+fTargetCPU+' CPU_SOURCE='+fTargetCPU;
if fTargetCPU<>fCompilerTargetCPU then begin
AddCmdLineParam('CPU_TARGET='+fTargetCPU,true);
AddCmdLineParam('CPU_SOURCE='+fTargetCPU,true);
end;
// create target directory and bundle
Result:=PrepareTargetDir(Flags);
@ -535,6 +542,7 @@ begin
end;
Result:=mrOk;
finally
CmdLineParams.Free;
EnvironmentOverrides.Free;
if LazarusIDE<>nil then
LazarusIDE.MainBarSubTitle:='';
@ -841,13 +849,13 @@ begin
end;
end;
procedure TLazarusBuilder.AppendExtraOption(const aOption: string; EncloseIfSpace: boolean);
procedure TLazarusBuilder.AppendExtraOption(const aOption: string; AutoQuote: boolean);
begin
if aOption='' then exit;
if fExtraOptions<>'' then
fExtraOptions:=fExtraOptions+' ';
if EncloseIfSpace and (Pos(' ',aOption)>0) then
fExtraOptions:=fExtraOptions+'"'+aOption+'"'
if AutoQuote then
fExtraOptions:=fExtraOptions+AnsiQuotedStr(aOption,'"')
else
fExtraOptions:=fExtraOptions+aOption;
//DebugLn(['AppendExtraOption ',fExtraOptions]);
@ -870,7 +878,7 @@ begin
// create apple bundle if needed
//debugln(['CreateIDEMakeOptions NewTargetDirectory=',fTargetDir]);
if (compareText(fTargetOS,'darwin')=0)
if (CompareText(fTargetOS,'darwin')=0)
and fOutputDirRedirected and DirectoryIsWritableCached(fTargetDir) then
begin
Result:=CreateAppleBundle;

View File

@ -80,6 +80,9 @@ type
fTargetOS: string;
fTargetCPU: string;
fLCLWidgetType: string;
// cache
FFPCompilerFilename: string;
FFPCompilerFilenameStamp: Integer;
procedure DoOnRescanFPCDirectoryCache(Sender: TObject);
function GetTargetFilename: String;
procedure OnMacroSubstitution(TheMacro: TTransferMacro;
@ -335,6 +338,7 @@ begin
DefaultCfgVars:=TCTCfgScriptVariables.Create;
DefaultCfgVarsBuildMacroStamp:=CTInvalidChangeStamp;
FFPCVerChangeStamp:=CTInvalidChangeStamp;
FFPCompilerFilenameStamp:=CTInvalidChangeStamp;
MainBuildBoss:=Self;
inherited Create(AOwner);
fTargetOS:=GetCompiledTargetOS;
@ -640,9 +644,7 @@ end;
function TBuildManager.GetCompilerFilename: string;
var
s: string;
Opts: TProjectCompilerOptions;
Kind: TPascalCompiler;
begin
Result:='';
//debugln(['TBuildManager.GetCompilerFilename START FBuildTarget=',DbgSName(FBuildTarget)]);
@ -658,27 +660,35 @@ begin
// the compiler filename is resolved twice, once for getting the default
// compiler target OS/CPU and once with the real values.
// For easier debugging macros, avoid this double resolve.
if Result='$(CompPath)' then
if Result='' then
// see below
else if Result='$(CompPath)' then
Result:=''
else if (Pos('$',Result)<1) and (FilenameIsAbsolute(Result)) then
Result:=TrimFilename(Result)
else
Result:=FBuildTarget.GetCompilerFilename;
//debugln(['TBuildManager.GetFPCompilerFilename project compiler="',Result,'"']);
//debugln(['TBuildManager.GetCompilerFilename project compiler="',Result,'"']);
end;
end;
if not IsCompilerExecutable(Result,s,Kind) then begin
//debugln(['TBuildManager.GetFPCompilerFilename project compiler IS NOT a pascal compiler: "',Result,'"']);
if Result='' then
Result:=EnvironmentOptions.GetParsedCompilerFilename;
if Kind=pcFPC then ;
end;
//debugln(['TBuildManager.GetCompilerFilename END Result="',Result,'"']);
end;
function TBuildManager.GetFPCompilerFilename: string;
var
ErrMsg: string;
Kind: TPascalCompiler;
begin
Result:=GetCompilerFilename;
if GuessCompilerType(Result)<>pcFPC then
Result:=EnvironmentOptions.GetParsedCompilerFilename;
if FFPCompilerFilenameStamp<>CompilerParseStamp then begin
FFPCompilerFilename:=GetCompilerFilename;
if (not IsCompilerExecutable(FFPCompilerFilename,ErrMsg,Kind,false)) or (ErrMsg<>'')
or (Kind<>pcFPC) then
FFPCompilerFilename:=EnvironmentOptions.GetParsedCompilerFilename;
FFPCompilerFilenameStamp:=CompilerParseStamp;
end;
Result:=FFPCompilerFilename;
end;
function TBuildManager.GetFPCFrontEndOptions: string;
@ -829,7 +839,7 @@ procedure TBuildManager.RescanCompilerDefines(ResetBuildTarget,
if Cfg.Kind=pcFPC then begin
if Cfg.RealCompiler='' then begin
if ConsoleVerbosity>=0 then
debugln(['Error: (lazarus) [PPUFilesAndCompilerMatch] Compiler=',Cfg.Compiler,' RealComp=',Cfg.RealCompiler,' InPath=',Cfg.RealCompilerInPath]);
debugln(['Error: (lazarus) [PPUFilesAndCompilerMatch] Compiler=',Cfg.Compiler,' RealComp=',Cfg.RealCompiler,' InPath=',Cfg.RealTargetCPUCompiler]);
IDEMessageDialog(lisCCOErrorCaption, Format(
lisCompilerDoesNotSupportTarget, [Cfg.Compiler, Cfg.TargetCPU, Cfg.TargetOS]),
mtError,[mbOk]);
@ -858,8 +868,8 @@ var
UnitSetChanged: Boolean;
HasTemplate: Boolean;
CompilerErrorMsg: string;
Msg: String;
Kind: TPascalCompiler;
Msg, DefCompilerFilename: String;
CompilerKind: TPascalCompiler;
begin
if ClearCaches then begin
{$IFDEF VerboseFPCSrcScan}
@ -881,13 +891,15 @@ begin
{$IFDEF VerboseFPCSrcScan}
debugln(['TBuildManager.RescanCompilerDefines GetParsedFPCSourceDirectory needs FPCVer...']);
{$ENDIF}
FPCSrcDir:=EnvironmentOptions.GetParsedFPCSourceDirectory; // needs FPCVer macro
CompilerFilename:=GetCompilerFilename;
IsCompilerExecutable(CompilerFilename,CompilerErrorMsg,CompilerKind,true);
FPCSrcDir:=EnvironmentOptions.GetParsedFPCSourceDirectory; // needs FPCVer macro
FPCOptions:=GetFPCFrontEndOptions;
{$IFDEF VerboseFPCSrcScan}
debugln(['TMainIDE.RescanCompilerDefines START ',
' CompilerFilename=',CompilerFilename,
' Kind=',PascalCompilerNames[CompilerKind],
' TargetOS=',TargetOS,
' TargetCPU=',TargetCPU,
' FPCOptions="',FPCOptions,'"',
@ -911,29 +923,31 @@ begin
end;
// then check the project's compiler
if not IsCompilerExecutable(CompilerFilename,CompilerErrorMsg,Kind) then begin
if (CompilerErrorMsg<>'') then begin
Msg:='';
if (FBuildTarget<>nil)
and ([crCompile,crBuild]*FBuildTarget.CompilerOptions.CompileReasons<>[])
and (FBuildTarget.CompilerOptions.CompilerPath<>'')
then begin
CompilerFilename:=FBuildTarget.GetCompilerFilename;
if not IsCompilerExecutable(CompilerFilename,CompilerErrorMsg,Kind) then begin
if not IsCompilerExecutable(CompilerFilename,CompilerErrorMsg,CompilerKind,true)
then begin
Msg+='Project''s compiler: "'+CompilerFilename+'": '+CompilerErrorMsg+#13;
end;
end;
CompilerFilename:=EnvironmentOptions.GetParsedCompilerFilename;
if not IsFPCExecutable(CompilerFilename,CompilerErrorMsg) then begin
Msg+='Environment compiler: "'+CompilerFilename+'": '+CompilerErrorMsg+#13;
DefCompilerFilename:=EnvironmentOptions.GetParsedCompilerFilename;
if not IsCompilerExecutable(DefCompilerFilename,CompilerErrorMsg,CompilerKind,true)
then begin
Msg+='Environment compiler: "'+DefCompilerFilename+'": '+CompilerErrorMsg+#13;
end;
debugln('Warning: (lazarus) [TBuildManager.RescanCompilerDefines]: invalid compiler:');
debugln(Msg);
if not Quiet then begin
IDEMessageDialog('Error','There is no Free Pascal Compiler'
+' (e.g. fpc'+ExeExt+' or ppc<cpu>'+ExeExt+') configured in the'
+' environment options. Codetools will not work properly.'#13
+Msg,mtError,[mbCancel]);
+' project options. Codetools will not work properly.'#13
+Msg,mtError,[mbOk]);
end;
UnitSetCache:=nil;
exit;
@ -2111,14 +2125,17 @@ function TBuildManager.MacroFuncFPCVer(const Param: string; const Data: PtrInt;
s: string;
begin
FFPC_FULLVERSION:=0;
if OverrideFPCVer<>'' then
if OverrideFPCVer<>'' then begin
FFPCVer:=OverrideFPCVer;
FFPC_FULLVERSION:=FPCVersionToNumber(FFPCVer);
exit;
end;
FFPCVer:={$I %FPCVERSION%}; // Version.Release.Patch
if CodeToolBoss<>nil then begin
// fetch the FPC version from the current compiler
// Not from the fpc.exe, but from the real compiler
CompilerFilename:=GetFPCompilerFilename;
if not IsFPCExecutable(CompilerFilename,s) then exit;
if not IsCTExecutable(CompilerFilename,s) then exit;
TargetOS:=GetTargetOS;
TargetCPU:=GetTargetCPU;
ConfigCache:=CodeToolBoss.CompilerDefinesCache.ConfigCaches.Find(
@ -2133,7 +2150,8 @@ function TBuildManager.MacroFuncFPCVer(const Param: string; const Data: PtrInt;
end;
FFPCVer:=ConfigCache.GetFPCVer;
FFPC_FULLVERSION:=ConfigCache.GetFPC_FULLVERSION;
end;
end else
FFPC_FULLVERSION:=FPCVersionToNumber(FFPCVer);
end;
begin

View File

@ -301,8 +301,9 @@ function TCheckCompilerOptsDlg.CheckCompileBogusFile(
var
TestDir: String;
BogusFilename: String;
CmdLineParams: String;
CmdLineParams, ErrMsg: String;
CompileTool: TAbstractExternalTool;
Kind: TPascalCompiler;
begin
// compile bogus file
FTest:=cotCompileBogusFiles;
@ -334,7 +335,7 @@ begin
CompileTool:=ExternalToolList.Add(dlgCCOTestToolCompilingEmptyFile);
CompileTool.Reference(Self,ClassName);
try
if GuessCompilerType(CompilerFilename)=pcPas2js then
if IsCompilerExecutable(CompilerFilename,ErrMsg,Kind,true) and (Kind=pcPas2js) then
CompileTool.AddParsers(SubToolPas2js)
else
CompileTool.AddParsers(SubToolFPC);

View File

@ -44,7 +44,7 @@ uses
// LCL
Forms, Controls,
// Codetools
DefineTemplates, LinkScanner, TransferMacros,
DefineTemplates, LinkScanner, CodeToolManager, TransferMacros,
// IdeIntf
IDEExternToolIntf, IDEMsgIntf, LazIDEIntf,
// IDE
@ -282,6 +282,7 @@ var
TargetOS: String;
TargetCPU: String;
TargetFilename, SubTool: String;
CompilerKind: TPascalCompiler;
begin
Result:=mrCancel;
if ConsoleVerbosity>=1 then
@ -344,7 +345,8 @@ begin
Tool.Process.CurrentDirectory:=WorkingDir;
Tool.CurrentDirectoryIsTestDir:=CurrentDirectoryIsTestDir;
SubTool:=SubToolFPC;
if GuessCompilerType(CompilerFilename)=pcPas2js then
CompilerKind:=CodeToolBoss.GetPascalCompilerForDirectory(WorkingDir);
if CompilerKind=pcPas2js then
SubTool:=SubToolPas2js;
FPCParser:=TFPCParser(Tool.AddParsers(SubTool));
FPCParser.ShowLinesCompiled:=EnvironmentOptions.MsgViewShowFPCMsgLinesCompiled;

View File

@ -2582,7 +2582,7 @@ var
DefaultTargetOS: string;
DefaultTargetCPU: string;
RealCompilerFilename: String;
s, CurNamespaces: string;
CurNamespaces: string;
CurFPCMsgFile: TFPCMsgFilePoolItem;
Quiet: Boolean;
Kind: TPascalCompiler;
@ -2859,9 +2859,10 @@ begin
Quiet:=ConsoleVerbosity<=-3; // lazbuild -q -q, lazarus -q -q -q
CompilerFilename:=ParsedOpts.GetParsedValue(pcosCompilerPath);
if IsCompilerExecutable(CompilerFilename,s,Kind) then
if CompilerFilename<>'' then
RealCompilerFilename:=CompilerFilename
else begin
// use default compiler
RealCompilerFilename:=EnvironmentOptions.GetParsedCompilerFilename;
Kind:=pcFPC;
end;
@ -4093,6 +4094,7 @@ begin
else if Option in ParsedCompilerFilenames then
begin
// make filename absolute
//debugln(['TParsedCompilerOptions.DoParseOption ',ParsedCompilerOptsVars[Option],' s="',s,'"']);
if ExtractFilePath(s)='' then begin
h:=FileUtil.FindDefaultExecutablePath(s,GetBaseDir);
if h<>'' then s:=h;

View File

@ -1009,7 +1009,6 @@ var
FPCVer: String;
FPCSrcDir: String;
aFilename: String;
ErrMsg: string;
begin
if fMsgFileStamp<>CompilerParseStamp then begin
fCurrentEnglishFile:=DefaultEnglishFile;
@ -1017,10 +1016,7 @@ begin
// English msg file
// => use fpcsrcdir/compiler/msg/errore.msg
// the fpcsrcdir might depend on the FPC version
if IsFPCExecutable(CompilerFilename,ErrMsg) then
FPCVer:=CodeToolBoss.CompilerDefinesCache.GetFPCVersion(CompilerFilename,TargetOS,TargetCPU,false)
else
FPCVer:='';
FPCVer:=CodeToolBoss.CompilerDefinesCache.GetFPCVersion(CompilerFilename,TargetOS,TargetCPU,false);
FPCSrcDir:=EnvironmentOptions.GetParsedFPCSourceDirectory(FPCVer);
if FilenameIsAbsolute(FPCSrcDir) then begin
// FPCSrcDir exists => use the errore.msg

View File

@ -12,7 +12,7 @@ uses
// CodeTools
FileProcs, DefineTemplates, CodeToolManager, LinkScanner,
// LazUtils
FileUtil, LazFileUtils,
FileUtil, LazFileUtils, LazUTF8,
// IDEIntf
IDEOptionsIntf, IDEOptEditorIntf, CompOptsIntf, IDEExternToolIntf,
IDEDialogs, IDEUtils,
@ -126,42 +126,43 @@ begin
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
// check, even if new file is old filename, so the user sees 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;
if Pos('pas2js',UTF8LowerCase(ExtractFileNameOnly(NewFilename)))>0 then begin
// check pas2js
Quality:=CheckPas2jsQuality(NewFilename,Note,
CodeToolBoss.CompilerDefinesCache.TestFilename);
if not ShowQuality(Quality,NewFilename,Note) then exit;
ok:=true;
end;
// maybe a script
if (not ok)
and not CheckExecutable(OldFilename,NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
then
exit;
ok:=true;
and (SameText('ppc',LeftStr(ExtractFileNameOnly(NewFilename),3))
or (Pos('fpc',UTF8LowerCase(ExtractFileNameOnly(NewFilename)))>0)) then begin
// check fpc
Quality:=CheckFPCExeQuality(NewFilename,Note,
CodeToolBoss.CompilerDefinesCache.TestFilename);
if not ShowQuality(Quality,NewFilename,Note) then exit;
ok:=true;
end;
if not ok then begin
// maybe a wrapper script
if IsCompilerExecutable(NewFilename,s,Kind,true) then begin
if (s<>'') and not ShowQuality(sddqInvalid,NewFilename,s) then exit;
ok:=true;
end;
// maybe a script
if (not ok)
and not CheckExecutable('',NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
then
exit;
ok:=true;
end;
end else if (Sender=ExecBeforeBrowseButton)
or (Sender=ExecAfterBrowseButton) then begin
// check executable
if not CheckExecutable(OldFilename,NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
if not CheckExecutable('',NewFilename,lisInvalidExecutable,lisInvalidExecutableMessageText)
then
exit;
ok:=true;

View File

@ -315,7 +315,7 @@ begin
sl.Add('RealCompilerDate='+DateTimeToStr(FileDateToDateTimeDef(CfgCache.RealCompilerDate)));
sl.Add('RealTargetOS='+CfgCache.RealTargetOS);
sl.Add('RealTargetCPU='+CfgCache.RealTargetCPU);
sl.Add('RealCompilerInPath='+CfgCache.RealCompilerInPath);
sl.Add('RealCompilerInPath='+CfgCache.RealTargetCPUCompiler);
sl.Add('Version='+CfgCache.FullVersion);
HasCfgs:=false;
if CfgCache.ConfigFiles<>nil then begin

View File

@ -280,6 +280,7 @@ procedure TIDEInfoDialog.GatherGlobalOptions(sl: TStrings);
var
CfgCache: TPCTargetConfigCache;
Note, aFilename: string;
CompilerKind: TPascalCompiler;
begin
sl.add('Global IDE options:');
sl.Add('Primary config directory='+GetPrimaryConfigPath);
@ -302,12 +303,13 @@ begin
sl.Add('Project CompilerFilename='+Project1.CompilerOptions.CompilerPath);
aFilename:=LazarusIDE.GetCompilerFilename;
sl.Add('Real Project CompilerFilename='+aFilename);
if GuessCompilerType(aFilename)=pcPas2js then begin
IsCompilerExecutable(aFilename,Note,CompilerKind,true);
if CompilerKind=pcPas2js then begin
if CheckPas2jsQuality(aFilename,Note,
CodeToolBoss.CompilerDefinesCache.TestFilename)<>sddqCompatible
then
sl.Add('WARNING: '+Note);
end else begin;
end else begin
if CheckFPCExeQuality(aFilename,Note,
CodeToolBoss.CompilerDefinesCache.TestFilename)<>sddqCompatible
then

View File

@ -95,7 +95,7 @@ uses
// LCL
Forms, Controls, Dialogs,
// LazUtils
UTF8Process, FileUtil, LazFileUtils, LazUtilities, LazUTF8,
UTF8Process, FileUtil, LazFileUtils, LazUtilities, LazUTF8, LazUTF8Classes,
// CodeTools
FileProcs,
// IdeIntf
@ -421,12 +421,18 @@ end;
constructor TLazarusProcess.Create(const LazarusPath: string;
const CommandLine: string; EnvOverrides: TStringList);
var
Params: TStringListUTF8;
begin
FProcess := TProcessUTF8.Create(nil);
FProcess.InheritHandles := false;
FProcess.Options := [];
FProcess.ShowWindow := swoShow;
FProcess.CommandLine := LazarusPath + CommandLine;
Params:=TStringListUTF8.Create;
Params.Add(LazarusPath);
SplitCmdLineParams(CommandLine,Params);
FProcess.Parameters:=Params;
Params.Free;
if (EnvOverrides<>nil) and (EnvOverrides.Count>0) then
AssignEnvironmentTo(FProcess.Environment,EnvOverrides);
end;

View File

@ -7180,7 +7180,8 @@ end;
function TMainIDE.DoRunProjectWithoutDebug: TModalResult;
var
Process: TProcessUTF8;
ExeCmdLine, ExeWorkingDirectory, ExeFile, Params: string;
RunCmdLine, RunWorkingDirectory, ExeFile: string;
Params: TStringListUTF8;
RunAppBundle, Handled: Boolean;
ARunMode: TRunParamsOptionsMode;
begin
@ -7199,29 +7200,39 @@ begin
Result:=DoCallRunWithoutDebugInit(Handled);
if Handled then exit;
ExeCmdLine := MainBuildBoss.GetRunCommandLine;
debugln(['Hint: (lazarus) [TMainIDE.DoRunProjectWithoutDebug] ExeCmdLine="',ExeCmdLine,'"']);
if ExeCmdLine='' then
RunCmdLine := MainBuildBoss.GetRunCommandLine;
debugln(['Hint: (lazarus) [TMainIDE.DoRunProjectWithoutDebug] ExeCmdLine="',RunCmdLine,'"']);
if RunCmdLine='' then
begin
IDEMessageDialog(lisUnableToRun, lisLaunchingApplicationInvalid,
mtError,[mbCancel]);
Exit(mrNone);
end;
Params:=TStringListUTF8.Create;
Process := TProcessUTF8.Create(nil);
try
RunAppBundle:={$IFDEF Darwin}true{$ELSE}false{$ENDIF};
RunAppBundle:=RunAppBundle and Project1.UseAppBundle;
SplitCmdLine(ExeCmdLine,ExeFile,Params);
SplitCmdLineParams(RunCmdLine,Params);
if Params.Count=0 then begin
IDEMessageDialog(lisUnableToRun,
Format(lisUnableToRun2, ['<project has no target file>']),
mtError, [mbOK]);
exit(mrCancel);
end else begin
ExeFile:=Params[0];
Params.Delete(0);
end;
Process.Executable := ExeFile;
if Params<>'' then
CommandToList(Params, Process.Parameters);
ARunMode := Project1.RunParameterOptions.GetActiveMode;
if RunAppBundle and FileExistsUTF8(Process.Executable)
and FileExistsUTF8('/usr/bin/open') then
if RunAppBundle
and FileExistsUTF8(Process.Executable)
and FileExistsUTF8('/usr/bin/open') then
begin
// run bundle via open
Process.Parameters.Insert(0,Process.Executable);
Process.Executable := '/usr/bin/open';
end else if not FileIsExecutable(Process.Executable) then
@ -7235,19 +7246,19 @@ begin
IDEMessageDialog(lisUnableToRun,
Format(lisUnableToRun2, [Process.Executable]),
mtError, [mbOK]);
Exit(mrNone);
Exit(mrCancel);
end;
if ARunMode<>nil then
ExeWorkingDirectory := ARunMode.WorkingDirectory
RunWorkingDirectory := ARunMode.WorkingDirectory
else
ExeWorkingDirectory := '';
if not GlobalMacroList.SubstituteStr(ExeWorkingDirectory) then
ExeWorkingDirectory := '';
RunWorkingDirectory := '';
if not GlobalMacroList.SubstituteStr(RunWorkingDirectory) then
RunWorkingDirectory := '';
if ExeWorkingDirectory = '' then
ExeWorkingDirectory := ExtractFilePath(Process.Executable);
Process.CurrentDirectory := ExeWorkingDirectory;
if RunWorkingDirectory = '' then
RunWorkingDirectory := ExtractFilePath(Process.Executable);
Process.CurrentDirectory := RunWorkingDirectory;
if not DirectoryExists(Process.CurrentDirectory) then
begin
@ -7259,9 +7270,15 @@ begin
end;
Project1.RunParameterOptions.AssignEnvironmentTo(Process.Environment);
TNotifyProcessEnd.Create(Process, @DoCallRunFinishedHandler);
except
try
TNotifyProcessEnd.Create(Process, @DoCallRunFinishedHandler);
except
on E: Exception do
debugln(['Error: (lazarus) [TMainIDE.DoRunProjectWithoutDebug] ',E.Message]);
end;
finally
Process.Free;
Params.Free;
end;
end;