Selaa lähdekoodia

instantfpc: version 1.3: compile into temporary directory to avoid clashes in parallel compilations

git-svn-id: trunk@25230 -
Mattias Gaertner 12 vuotta sitten
vanhempi
commit
90d78e775e

+ 2 - 8
utils/instantfpc/instantfpc.lpi

@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
   <ProjectOptions>
     <Version Value="9"/>
@@ -46,7 +46,7 @@
     </Units>
   </ProjectOptions>
   <CompilerOptions>
-    <Version Value="10"/>
+    <Version Value="11"/>
     <Target>
       <Filename Value="instantfpc"/>
     </Target>
@@ -54,12 +54,6 @@
       <IncludeFiles Value="$(ProjOutDir)"/>
       <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
-    <Linking>
-      <Debugging>
-        <GenerateDebugInfo Value="True"/>
-        <DebugInfoType Value="dsAuto"/>
-      </Debugging>
-    </Linking>
     <Other>
       <CompilerMessages>
         <UseMsgFile Value="True"/>

+ 3 - 4
utils/instantfpc/instantfpc.pas

@@ -25,7 +25,8 @@ uses
   Classes, SysUtils, InstantFPTools;
 
 const
-  Version = '1.2';
+  Version = '1.3';
+  // 1.3 compile in a separate directory, so that parallel invocations do not overwrite link.res files
 
 
 Procedure Usage;
@@ -92,7 +93,6 @@ var
   CacheDir: String;
   CacheFilename: String;
   OutputFilename: String;
-  ExeExt: String;
   E : String;
   RunIt: boolean = true;
   
@@ -184,8 +184,7 @@ begin
     E:=LowerCase(ExtractFileExt(CacheFileName));
     if (E<>'.pp') and (E<>'.pas') and (E<>'.lpr') then
       CacheFileName:=CacheFileName+'.pas';
-    ExeExt:='';
-    OutputFilename:=CacheDir+ChangeFileExt(ExtractFileName(Filename),ExeExt);
+    OutputFilename:=CacheDir+ChangeFileExt(ExtractFileName(Filename),'');
     if not IsCacheValid(Src,CacheFilename,OutputFilename) then begin
       // save source in cache to find out next time if something changed
       Src.SaveToFile(CacheFilename);

+ 66 - 6
utils/instantfpc/instantfptools.pas

@@ -47,7 +47,7 @@ procedure Compile(const SrcFilename, CacheFilename, OutputFilename: string);
 procedure WriteCompilerOutput(SrcFilename, CacheFilename, CompilerOutput: string);
 function GetCompiler: string;
 procedure SetCompiler(AValue : string);
-function GetCompilerParameters(const SrcFilename, OutputFilename: string): string;
+function GetCompilerParameters(const SrcFilename, OutputDirectory, OutputFilename: string): string;
 procedure Run(const Filename: string);
 
 implementation
@@ -246,6 +246,31 @@ begin
     end;
 end;
 
+procedure DeleteDirectory(Directory: string);
+var
+  FileInfo: TSearchRec;
+  aFilename: String;
+begin
+  Directory:=ExcludeTrailingPathDelimiter(Directory);
+  if not DirectoryExists(Directory) then exit;
+  if FindFirst(Directory+PathDelim+AllFilesMask,faAnyFile,FileInfo)=0 then begin
+    repeat
+      if (FileInfo.Name='.') or (FileInfo.Name='..') then continue;
+      aFilename:=Directory+PathDelim+FileInfo.Name;
+      if (FileInfo.Attr and faDirectory)>0 then
+        DeleteDirectory(aFilename)
+      else if not DeleteFile(aFilename) then begin
+        writeln('unable to delete file "'+aFilename+'"');
+        Halt(1);
+      end;
+    until FindNext(FileInfo)<>0;
+  end;
+  if not RemoveDir(Directory) then begin
+    writeln('unable to delete directory "'+Directory+'"');
+    Halt(1);
+  end;
+end;
+
 procedure Compile(const SrcFilename, CacheFilename, OutputFilename: string);
 var
   Compiler: String;
@@ -254,14 +279,35 @@ var
   Count: Int64;
   ss: TStringStream;
   buf : Array[1..4096] of byte;
+  pid: SizeUInt;
+  BuildDir: String;
+  BuildOutputFilename: String;
 begin
   Compiler:=GetCompiler;
-  CompParams:=GetCompilerParameters(CacheFilename,OutputFilename);
+  pid:=GetProcessID;
+  BuildDir:='';
+  BuildOutputFilename:=OutputFilename;
+  if pid>0 then begin
+    BuildDir:=ExtractFilePath(OutputFilename)+'__tmp'+IntToStr(pid)+PathDelim;
+    BuildOutputFilename:=BuildDir+ExtractFileName(OutputFilename);
+  end;
   //writeln('Compiler=',Compiler,' Params=',CompParams);
   if FileExists(OutputFilename) and not DeleteFile(OutputFilename) then begin
     writeln('unable to delete ',OutputFilename);
     Halt(1);
   end;
+  if BuildDir<>'' then begin
+    if FileExists(BuildOutputFilename) and not DeleteFile(BuildOutputFilename)
+    then begin
+      writeln('unable to delete ',BuildOutputFilename);
+      Halt(1);
+    end;
+    if not DirectoryExists(BuildDir) and not CreateDir(BuildDir) then begin
+      writeln('unable to mkdir ',BuildDir);
+      Halt(1);
+    end;
+  end;
+  CompParams:=GetCompilerParameters(CacheFilename,BuildDir,BuildOutputFilename);
   Proc:=TProcess.Create(nil);
   Proc.CommandLine:=Compiler+' '+CompParams;
 {$WARNING Unconditional use of pipes breaks for targets not supporting them}
@@ -274,6 +320,15 @@ begin
     if Count>0 then
       ss.write(buf,count);
   until Count=0;
+  if BuildDir<>'' then begin
+    // move from build directory to cache
+    if not RenameFile(BuildOutputFilename,OutputFilename) then begin
+      writeln('unable to move "',BuildOutputFilename,'" to "',OutputFilename,'"');
+      Halt(1);
+    end;
+    // delete build directory
+    DeleteDirectory(BuildDir);
+  end;
   if (not Proc.WaitOnExit) or (Proc.ExitStatus<>0) then begin
     WriteCompilerOutput(SrcFilename,CacheFilename,ss.DataString);
     Halt(1);
@@ -282,7 +337,8 @@ begin
   Proc.Free;
 end;
 
-function GetCompilerParameters(const SrcFilename, OutputFilename: string): string;
+function GetCompilerParameters(const SrcFilename, OutputDirectory,
+  OutputFilename: string): string;
 { For example:
     /usr/bin/instantfpc -MObjFpc -Sh ./envvars.pas param1
   The shebang compile parameters: -MObjFpc -Sh
@@ -300,6 +356,8 @@ begin
       AddParam(P,Result);
     inc(I);
     end;
+  if OutputDirectory<>'' then
+    AddParam('-FU'+OutputDirectory,Result);
   AddParam('-o'+OutputFilename {$IFDEF HASEXEEXT} + '.exe' {$ENDIF},Result);
   AddParam(SrcFilename,Result);
 end;
@@ -307,8 +365,10 @@ end;
 procedure Run(const Filename: string);
 var
   p : PPChar;
+  {$IFNDEF UseFpExecV}
   i : integer;
   args : array of string;
+  {$ENDIF}
 begin
   p:=argv;
   inc(p);
@@ -318,7 +378,9 @@ begin
     end;
     inc(p);
   end;
-  {$IFNDEF UseFpExecV}
+  {$IFDEF UseFpExecV}
+    Halt(FpExecV(Filename,p));
+  {$ELSE}
     if paramcount>1 then
       begin
         setlength(args,paramcount-1);
@@ -326,8 +388,6 @@ begin
           args[i-2]:=paramstr(i);
       end;
     Halt(ExecuteProcess(Filename,args));
-  {$ELSE}
-    Halt(FpExecV(Filename,p));
   {$ENDIF}
 end;