[Ada] Recompile when a dependency has been replaced with another file name
Arnaud Charlet
charlet@adacore.com
Thu Oct 7 09:26:00 GMT 2010
When a source in a project being extended has been replaced by a source
with a different file name in the extending project, other sources that
depend on the replaced source file need to be recompiled. This patch
ensures that they are.
No simple test.
Tested on x86_64-pc-linux-gnu, committed on trunk
2010-10-07 Vincent Celier <celier@adacore.com>
* make.adb (Check): Call Check_Source_Info_In_ALI with Project_Tree
* makeutl.adb (Check_Source_Info_In_ALI): If there is at least one
replaced source, check that none of the replaced sources are in the
dependencies.
* makeutl.ads (Check_Source_Info_In_ALI): New parameter Tree
* prj-nmsc.adb (Remove_Source): New parameter Tree. If the source is
replaced with a source with a different file name, put it in the hash
table Replaced_Sources.
(Add_Source): Call Remove_Source with Data.Tree. If there is at least
one replaced source, check if it has the same file name as the current
source; if it has, remove it from the hash table Replaced_Sources.
* prj.adb (Reset): Reset hash table Tree.Replaced_Sources
* prj.ads (Replaced_Source_HTable): New hash table
(Project_Tree_Data): New components Replaced_Sources and
Replaced_Source_Number.
-------------- next part --------------
Index: make.adb
===================================================================
--- make.adb (revision 165080)
+++ make.adb (working copy)
@@ -1843,7 +1843,7 @@ package body Make is
elsif not Read_Only and then Main_Project /= No_Project then
- if not Check_Source_Info_In_ALI (ALI) then
+ if not Check_Source_Info_In_ALI (ALI, Project_Tree) then
ALI := No_ALI_Id;
return;
end if;
Index: prj.adb
===================================================================
--- prj.adb (revision 165080)
+++ prj.adb (working copy)
@@ -898,6 +898,9 @@ package body Prj is
Array_Table.Init (Tree.Arrays);
Package_Table.Init (Tree.Packages);
Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
+ Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
+
+ Tree.Replaced_Source_Number := 0;
Free_List (Tree.Projects, Free_Project => True);
Free_Units (Tree.Units_HT);
Index: prj.ads
===================================================================
--- prj.ads (revision 165080)
+++ prj.ads (working copy)
@@ -1333,6 +1333,14 @@ package Prj is
-- Project_Tree_Data --
-----------------------
+ package Replaced_Source_HTable is new Simple_HTable
+ (Header_Num => Header_Num,
+ Element => File_Name_Type,
+ No_Element => No_File,
+ Key => File_Name_Type,
+ Hash => Hash,
+ Equal => "=");
+
type Private_Project_Tree_Data is private;
-- Data for a project tree that is used only by the Project Manager
@@ -1347,6 +1355,13 @@ package Prj is
Packages : Package_Table.Instance;
Projects : Project_List;
+ Replaced_Sources : Replaced_Source_HTable.Instance;
+ -- The list of sources that have been replaced by sources with
+ -- different file names.
+
+ Replaced_Source_Number : Natural := 0;
+ -- The number of entries in Replaced_Sources
+
Units_HT : Units_Htable.Instance;
-- Unit name to Unit_Index (and from there so Source_Id)
Index: makeutl.adb
===================================================================
--- makeutl.adb (revision 165080)
+++ makeutl.adb (working copy)
@@ -203,7 +203,10 @@ package body Makeutl is
-- Check_Source_Info_In_ALI --
------------------------------
- function Check_Source_Info_In_ALI (The_ALI : ALI_Id) return Boolean is
+ function Check_Source_Info_In_ALI
+ (The_ALI : ALI_Id;
+ Tree : Project_Tree_Ref) return Boolean
+ is
Unit_Name : Name_Id;
begin
@@ -242,7 +245,7 @@ package body Makeutl is
end loop;
end loop;
- -- Loop to check subunits
+ -- Loop to check subunits and replaced sources
for D in ALIs.Table (The_ALI).First_Sdep ..
ALIs.Table (The_ALI).Last_Sdep
@@ -253,8 +256,32 @@ package body Makeutl is
begin
Unit_Name := SD.Subunit_Name;
- if Unit_Name /= No_Name then
+ if Unit_Name = No_Name then
+ -- Check if this source file has been replaced by a source with
+ -- a different file name.
+
+ if Tree /= null and then Tree.Replaced_Source_Number > 0 then
+ declare
+ Replacement : constant File_Name_Type :=
+ Replaced_Source_HTable.Get
+ (Tree.Replaced_Sources, SD.Sfile);
+
+ begin
+ if Replacement /= No_File then
+ if Verbose_Mode then
+ Write_Line
+ ("source file" &
+ Get_Name_String (SD.Sfile) &
+ " has been replaced by " &
+ Get_Name_String (Replacement));
+ end if;
+ return False;
+ end if;
+ end;
+ end if;
+
+ else
-- For separates, the file is no longer associated with the
-- unit ("proc-sep.adb" is not associated with unit "proc.sep")
-- so we need to check whether the source file still exists in
Index: makeutl.ads
===================================================================
--- makeutl.ads (revision 165080)
+++ makeutl.ads (working copy)
@@ -105,7 +105,9 @@ package Makeutl is
-- True if the unit is in one of the project file, but the file name is not
-- one of its source. Returns False otherwise.
- function Check_Source_Info_In_ALI (The_ALI : ALI.ALI_Id) return Boolean;
+ function Check_Source_Info_In_ALI
+ (The_ALI : ALI.ALI_Id;
+ Tree : Project_Tree_Ref) return Boolean;
-- Check whether all file references in ALI are still valid (i.e. the
-- source files are still associated with the same units). Return True
-- if everything is still valid.
Index: prj-nmsc.adb
===================================================================
--- prj-nmsc.adb (revision 165080)
+++ prj-nmsc.adb (working copy)
@@ -482,7 +482,8 @@ package body Prj.Nmsc is
-- if file cannot be found.
procedure Remove_Source
- (Id : Source_Id;
+ (Tree : Project_Tree_Ref;
+ Id : Source_Id;
Replaced_By : Source_Id);
-- Remove a file from the list of sources of a project. This might be
-- because the file is replaced by another one in an extending project,
@@ -872,7 +873,16 @@ package body Prj.Nmsc is
Lang_Id.First_Source := Id;
if Source_To_Replace /= No_Source then
- Remove_Source (Source_To_Replace, Id);
+ Remove_Source (Data.Tree, Source_To_Replace, Id);
+ end if;
+
+ if Data.Tree.Replaced_Source_Number > 0 and then
+ Replaced_Source_HTable.Get (Data.Tree.Replaced_Sources, Id.File) /=
+ No_File
+ then
+ Replaced_Source_HTable.Remove (Data.Tree.Replaced_Sources, Id.File);
+ Data.Tree.Replaced_Source_Number :=
+ Data.Tree.Replaced_Source_Number - 1;
end if;
Files_Htable.Set (Data.File_To_Source, File_Name, Id);
@@ -6193,7 +6203,7 @@ package body Prj.Nmsc is
(Project.Source_Names,
Source.File,
No_Name_Location);
- Remove_Source (Source, No_Source);
+ Remove_Source (Data.Tree, Source, No_Source);
Error_Msg_Name_1 := Name_Id (Source.File);
Error_Msg
@@ -6277,7 +6287,7 @@ package body Prj.Nmsc is
end if;
if Source.Path = No_Path_Information then
- Remove_Source (Source, No_Source);
+ Remove_Source (Data.Tree, Source, No_Source);
end if;
end if;
@@ -7589,7 +7599,8 @@ package body Prj.Nmsc is
-------------------
procedure Remove_Source
- (Id : Source_Id;
+ (Tree : Project_Tree_Ref;
+ Id : Source_Id;
Replaced_By : Source_Id)
is
Source : Source_Id;
@@ -7609,6 +7620,21 @@ package body Prj.Nmsc is
if Replaced_By /= No_Source then
Id.Replaced_By := Replaced_By;
Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
+
+ if Id.File /= Replaced_By.File then
+ declare
+ Replacement : constant File_Name_Type :=
+ Replaced_Source_HTable.Get (Tree.Replaced_Sources, Id.File);
+ begin
+ Replaced_Source_HTable.Set
+ (Tree.Replaced_Sources, Id.File, Replaced_By.File);
+
+ if Replacement = No_File then
+ Tree.Replaced_Source_Number :=
+ Tree.Replaced_Source_Number + 1;
+ end if;
+ end;
+ end if;
end if;
Id.In_Interfaces := False;
More information about the Gcc-patches
mailing list