diff mbox

[Ada] gnatmake find old ALI files in wrong object directory

Message ID 20130129140742.GA24692@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 29, 2013, 2:07 p.m. UTC
When gnatmake is invoked with project files and a source has been moved
from one project A to another project B in the project tree, but the ALI
and object files has not be removed from the object directory of A,
gnatmake may always recompile the source moved to project B, even when it
is up to date. This patch is fixing this.

The test is to have 3 projects: Prj that withs A that withs B.
The object directories of the 3 projects are different.
A package Pkg in project A is used by the main in Prj. Invoke gnatmake to
build the main in Prj. Move package Pkg from project A to project B,
without removing the ALI and object files in the object directory of A.
Invoke gnatmake to build the main in Prj. Invoke again gnatmake to build
the main in Prj: gnatmake should report that everything is up to date.

Tested on x86_64-pc-linux-gnu, committed on trunk

2013-01-29  Vincent Celier  <celier@adacore.com>

	* clean.adb (Clean_Executables): Add Sid component when calling
	Queue.Insert.
	* make.adb: When inserting in the Queue, add the Source_Id
	(Sid) when it is known (Start_Compile_If_Possible): When the
	Source_Id is known (Sid), get the path name of the ALI file
	(Full_Lib_File) from it, to avoid finding old ALI files in other
	object directories.
	* makeutl.ads (Source_Info): New Source_Id component Sid in
	Format_Gnatmake variant.
diff mbox

Patch

Index: make.adb
===================================================================
--- make.adb	(revision 195533)
+++ make.adb	(working copy)
@@ -2746,7 +2746,8 @@ 
                              File    => Sfile,
                              Unit    => No_Unit_Name,
                              Project => No_Project,
-                             Index   => 0))
+                             Index   => 0,
+                             Sid     => No_Source))
                   then
                      if Is_In_Obsoleted (Sfile) then
                         Executable_Obsolete := True;
@@ -3091,6 +3092,7 @@ 
          ALI          : ALI_Id;
          Source_Index : Int;
          Sfile        : File_Name_Type;
+         Sid          : Prj.Source_Id;
          Uname        : Unit_Name_Type;
          Unit_Name    : Name_Id;
          Uid          : Prj.Unit_Index;
@@ -3137,6 +3139,7 @@ 
                   loop
                      Sfile := Withs.Table (K).Sfile;
                      Uname := Withs.Table (K).Uname;
+                     Sid   := No_Source;
 
                      --  If project files are used, find the proper source to
                      --  compile in case Sfile is the spec but there is a body.
@@ -3154,12 +3157,14 @@ 
                            then
                               Sfile        := Uid.File_Names (Impl).File;
                               Source_Index := Uid.File_Names (Impl).Index;
+                              Sid          := Uid.File_Names (Impl);
 
                            elsif Uid.File_Names (Spec) /= null
                              and then not Uid.File_Names (Spec).Locally_Removed
                            then
                               Sfile        := Uid.File_Names (Spec).File;
                               Source_Index := Uid.File_Names (Spec).Index;
+                              Sid          := Uid.File_Names (Spec);
                            end if;
                         end if;
                      end if;
@@ -3187,7 +3192,8 @@ 
                                File    => Sfile,
                                Project => ALI_P.Project,
                                Unit    => Withs.Table (K).Uname,
-                               Index   => Source_Index));
+                               Index   => Source_Index,
+                               Sid     => Sid));
                         end if;
                      end if;
                   end loop;
@@ -3308,16 +3314,16 @@ 
       is
          In_Lib_Dir      : Boolean;
          Need_To_Compile : Boolean;
-         Pid             : Process_Id;
+         Pid             : Process_Id := Invalid_Pid;
          Process_Created : Boolean;
 
          Source           : Queue.Source_Info;
-         Full_Source_File : File_Name_Type;
+         Full_Source_File : File_Name_Type := No_File;
          Source_File_Attr : aliased File_Attributes;
          --  The full name of the source file and its attributes (size, ...)
 
          Lib_File      : File_Name_Type;
-         Full_Lib_File : File_Name_Type;
+         Full_Lib_File : File_Name_Type := No_File;
          Lib_File_Attr : aliased File_Attributes;
          Read_Only     : Boolean := False;
          ALI           : ALI_Id;
@@ -3335,24 +3341,50 @@ 
          then
             Queue.Extract (Found, Source);
 
-            Osint.Full_Source_Name
-              (Source.File,
-               Full_File => Full_Source_File,
-               Attr      => Source_File_Attr'Access);
+            --  If it is a source in a project, first look for the ALI file
+            --  in the object directory. When the project is extending another
+            --  the ALI file may not be found, but the source does not
+            --  necessarily need to be compiled, as it may already be up to
+            --  date in the project being extended. In this case, look for an
+            --  ALI file in all the object directories, as is done when
+            --  gnatmake is not invoked with a project file.
 
-            Lib_File := Osint.Lib_File_Name (Source.File, Source.Index);
+            if Source.Sid /= No_Source then
+               Initialize_Source_Record (Source.Sid);
+               Full_Source_File :=
+                 File_Name_Type (Source.Sid.Path.Display_Name);
+               Lib_File      := Source.Sid.Dep_Name;
+               Full_Lib_File := File_Name_Type (Source.Sid.Dep_Path);
+               Lib_File_Attr := Unknown_Attributes;
 
-            --  ??? This call could be avoided when using projects, since we
-            --  know where the ALI file is supposed to be. That would avoid
-            --  searches in the object directories, including in the runtime
-            --  dir. However, that would require getting access to the
-            --  Source_Id.
+               if Full_Lib_File /= No_File then
+                  declare
+                     FLF : constant String :=
+                       Get_Name_String (Full_Lib_File) & ASCII.NUL;
+                  begin
+                     if not Is_Regular_File
+                       (FLF'Address, Lib_File_Attr'Access)
+                     then
+                        Full_Lib_File := No_File;
+                     end if;
+                  end;
+               end if;
+            end if;
 
-            Osint.Full_Lib_File_Name
-              (Lib_File,
-               Lib_File => Full_Lib_File,
-               Attr     => Lib_File_Attr);
+            if Full_Lib_File = No_File then
+               Osint.Full_Source_Name
+                 (Source.File,
+                  Full_File => Full_Source_File,
+                  Attr      => Source_File_Attr'Access);
 
+               Lib_File := Osint.Lib_File_Name (Source.File, Source.Index);
+
+               Osint.Full_Lib_File_Name
+                 (Lib_File,
+                  Lib_File => Full_Lib_File,
+                  Attr     => Lib_File_Attr);
+            end if;
+
             --  If source has already been compiled, executable is obsolete
 
             if Is_In_Obsoleted (Source.File) then
@@ -3734,7 +3766,8 @@ 
           File    => Main_Source,
           Project => Main_Project,
           Unit    => No_Unit_Name,
-          Index   => Main_Index));
+          Index   => Main_Index,
+          Sid     => No_Source));
 
       First_Compiled_File   := No_File;
       Most_Recent_Obj_File  := No_File;
@@ -6650,6 +6683,7 @@ 
       Put_In_Q : Boolean := Into_Q;
       Unit     : Unit_Index;
       Sfile    : File_Name_Type;
+      Sid      : Prj.Source_Id;
       Index    : Int;
       Project  : Project_Id;
 
@@ -6659,6 +6693,7 @@ 
       Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
       while Unit /= null loop
          Sfile   := No_File;
+         Sid     := No_Source;
          Index   := 0;
          Project := No_Project;
 
@@ -6704,15 +6739,18 @@ 
                      if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
                         Sfile := No_File;
                         Index := 0;
+                        Sid   := No_Source;
                      else
                         Sfile := Unit.File_Names (Impl).Display_File;
                         Index := Unit.File_Names (Impl).Index;
+                        Sid   := Unit.File_Names (Impl);
                      end if;
                   end;
 
                else
                   Sfile := Unit.File_Names (Impl).Display_File;
                   Index := Unit.File_Names (Impl).Index;
+                  Sid   := Unit.File_Names (Impl);
                end if;
             end if;
 
@@ -6728,6 +6766,7 @@ 
 
             Sfile := Unit.File_Names (Spec).Display_File;
             Index := Unit.File_Names (Spec).Index;
+            Sid   := Unit.File_Names (Spec);
             Project := Unit.File_Names (Spec).Project;
          end if;
 
@@ -6744,7 +6783,8 @@ 
                 File     => Sfile,
                 Project  => Project,
                 Unit     => No_Unit_Name,
-                Index    => Index));
+                Index    => Index,
+                Sid      => Sid));
          end if;
 
          if not Put_In_Q and then Sfile /= No_File then
Index: makeutl.ads
===================================================================
--- makeutl.ads	(revision 195533)
+++ makeutl.ads	(working copy)
@@ -485,14 +485,15 @@ 
          record
             case Format is
                when Format_Gprbuild =>
-                  Tree : Project_Tree_Ref := null;
-                  Id   : Source_Id        := null;
+                  Tree : Project_Tree_Ref := No_Project_Tree;
+                  Id   : Source_Id        := No_Source;
 
                when Format_Gnatmake =>
                   File    : File_Name_Type := No_File;
                   Unit    : Unit_Name_Type := No_Unit_Name;
                   Index   : Int            := 0;
                   Project : Project_Id     := No_Project;
+                  Sid     : Source_Id      := No_Source;
             end case;
          end record;
       --  Information about files stored in the queue. The exact information
Index: clean.adb
===================================================================
--- clean.adb	(revision 195533)
+++ clean.adb	(working copy)
@@ -397,7 +397,8 @@ 
                 File    => Main_Lib_File,
                 Unit    => No_Unit_Name,
                 Index   => 0,
-                Project => No_Project));
+                Project => No_Project,
+                Sid     => No_Source));
          end if;
 
          while not Queue.Is_Empty loop
@@ -440,7 +441,8 @@ 
                                   File    => Withs.Table (K).Afile,
                                   Unit    => No_Unit_Name,
                                   Index   => 0,
-                                  Project => No_Project));
+                                  Project => No_Project,
+                                  Sid     => No_Source));
                            end if;
                         end loop;
                      end loop;