X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fada%2Fmake.adb;h=0e3c85765d59e584c3e5d37a26a72ba86efd792d;hb=18a49466c972ff6bc70f5da5645eefcde97e1ab8;hp=d1bfec914486d7faaa0d1b292e5e98795ed12f76;hpb=45cedf2ed41b5c0b4c28fb5d8105f38339277c0b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb index d1bfec91448..0e3c85765d5 100644 --- a/gcc/ada/make.adb +++ b/gcc/ada/make.adb @@ -49,10 +49,16 @@ with Prj; use Prj; with Prj.Com; with Prj.Env; with Prj.Pars; +with Prj.Tree; use Prj.Tree; with Prj.Util; with SFN_Scan; with Sinput.P; with Snames; use Snames; + +pragma Warnings (Off); +with System.HTable; +pragma Warnings (On); + with Switch; use Switch; with Switch.M; use Switch.M; with Targparm; use Targparm; @@ -68,8 +74,6 @@ with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables; with GNAT.Case_Util; use GNAT.Case_Util; with GNAT.OS_Lib; use GNAT.OS_Lib; -with System.HTable; - package body Make is use ASCII; @@ -102,13 +106,17 @@ package body Make is Full_Source_File : File_Name_Type; Lib_File : File_Name_Type; Source_Unit : Unit_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : aliased File_Attributes; Mapping_File : Natural := No_Mapping_File; Project : Project_Id := No_Project; - Syntax_Only : Boolean := False; - Output_Is_Object : Boolean := True; end record; -- Data recorded for each compilation process spawned + No_Compilation_Data : constant Compilation_Data := + (Invalid_Pid, No_File, No_File, No_Unit_Name, No_File, Unknown_Attributes, + No_Mapping_File, No_Project); + type Comp_Data_Arr is array (Positive range <>) of Compilation_Data; type Comp_Data_Ptr is access Comp_Data_Arr; Running_Compile : Comp_Data_Ptr; @@ -140,16 +148,16 @@ package body Make is -- Q | | ........ | | | | ....... | | -- +---+--------------+---+---+---+-----------+---+-------- -- ^ ^ ^ - -- Q.First Q_Front Q.Last - 1 + -- Q.First Q_Front Q.Last-1 -- - -- The elements comprised between Q.First and Q_Front - 1 are the elements + -- The elements comprised between Q.First and Q_Front-1 are the elements -- that have been enqueued and then dequeued, while the elements between - -- Q_Front and Q.Last - 1 are the elements currently in the Q. When the Q + -- Q_Front and Q.Last-1 are the elements currently in the Q. When the Q -- is initialized Q_Front = Q.First = Q.Last. After Compile_Sources has -- terminated its execution, Q_Front = Q.Last and the elements contained - -- between Q.Front and Q.Last-1 are those that were explored and thus + -- between Q.First and Q.Last-1 are those that were explored and thus -- marked by Compile_Sources. Whenever the Q is reinitialized, the elements - -- between Q.First and Q.Last - 1 are unmarked. + -- between Q.First and Q.Last-1 are unmarked. procedure Init_Q; -- Must be called to (re)initialize the Q @@ -197,6 +205,9 @@ package body Make is RTS_Specified : String_Access := null; -- Used to detect multiple --RTS= switches + N_M_Switch : Natural := 0; + -- Used to count -mxxx switches that can affect multilib + type Q_Record is record File : File_Name_Type; Unit : Unit_Name_Type; @@ -343,15 +354,13 @@ package body Make is Current_Verbosity : Prj.Verbosity := Prj.Default; -- Verbosity to parse the project files - Project_Tree : constant Project_Tree_Ref := new Project_Tree_Data; - Main_Project : Prj.Project_Id := No_Project; -- The project id of the main project file, if any Project_Of_Current_Object_Directory : Project_Id := No_Project; -- The object directory of the project for the last compilation. Avoid -- calling Change_Dir if the current working directory is already this - -- directory + -- directory. -- Packages of project files where unknown attributes are errors @@ -518,10 +527,6 @@ package body Make is Last_Argument : Natural := 0; -- Last index of arguments in Arguments above - Arguments_Collected : Boolean := False; - -- Set to True when the arguments for the next invocation of the compiler - -- have been collected. - Arguments_Project : Project_Id; -- Project id, if any, of the source to be compiled @@ -557,25 +562,6 @@ package body Make is procedure List_Bad_Compilations; -- Prints out the list of all files for which the compilation failed - procedure Verbose_Msg - (N1 : Name_Id; - S1 : String; - N2 : Name_Id := No_Name; - S2 : String := ""; - Prefix : String := " -> "; - Minimum_Verbosity : Verbosity_Level_Type := Opt.Low); - procedure Verbose_Msg - (N1 : File_Name_Type; - S1 : String; - N2 : File_Name_Type := No_File; - S2 : String := ""; - Prefix : String := " -> "; - Minimum_Verbosity : Verbosity_Level_Type := Opt.Low); - -- If the verbose flag (Verbose_Mode) is set and the verbosity level is - -- at least equal to Minimum_Verbosity, then print Prefix to standard - -- output followed by N1 and S1. If N2 /= No_Name then N2 is printed after - -- S1. S2 is printed last. Both N1 and N2 are printed in quotation marks. - Usage_Needed : Boolean := True; -- Flag used to make sure Makeusg is call at most once @@ -644,7 +630,7 @@ package body Make is (Source_File : File_Name_Type; Source_File_Name : String; Source_Index : Int; - Naming : Naming_Data; + Project : Project_Id; In_Package : Package_Id; Allow_ALI : Boolean) return Variable_Value; -- Return the switches for the source file in the specified package of a @@ -662,6 +648,9 @@ package body Make is -- directory of the ultimate extending project. If it is not, we ignore -- the fact that this ALI file is read-only. + procedure Process_Multilib (Project_Node_Tree : Project_Node_Tree_Ref); + -- Add appropriate --RTS argument to handle multilib + ---------------------------------------------------- -- Compiler, Binder & Linker Data and Subprograms -- ---------------------------------------------------- @@ -729,7 +718,8 @@ package body Make is File_Name : String; Index : Int; Program : Make_Program_Type; - Unknown_Switches_To_The_Compiler : Boolean := True); + Unknown_Switches_To_The_Compiler : Boolean := True; + Project_Node_Tree : Project_Node_Tree_Ref); procedure Add_Switch (S : String_Access; Program : Make_Program_Type; @@ -754,6 +744,8 @@ package body Make is Is_Main_Source : Boolean; The_Args : Argument_List; Lib_File : File_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : access File_Attributes; Read_Only : Boolean; ALI : out ALI_Id; O_File : out File_Name_Type; @@ -764,6 +756,10 @@ package body Make is -- ALI is the ALI_Id corresponding to Lib_File. If Lib_File in not -- up-to-date, then the corresponding source file needs to be recompiled. -- In this case ALI = No_ALI_Id. + -- Full_Lib_File must be the result of calling Osint.Full_Lib_File_Name on + -- Lib_File. Precomputing it saves system calls. Lib_File_Attr is the + -- initialized attributes of that file, which is also used to save on + -- system calls (it can safely be initialized to Unknown_Attributes). procedure Check_Linker_Options (E_Stamp : Time_Stamp_Type; @@ -835,10 +831,6 @@ package body Make is Gnatmake_Mapping_File : String_Access := null; -- The path name of a mapping file specified by switch -C= - procedure Delete_Mapping_Files; - -- Delete all temporary mapping files. Called only in Delete_All_Temp_Files - -- which ensures that Debug_Flag_N is False. - procedure Init_Mapping_File (Project : Project_Id; Data : in out Project_Compilation_Data; @@ -1021,7 +1013,7 @@ package body Make is -- during a compilation are also transitively included in the W section -- of the originally compiled file. - procedure Initialize; + procedure Initialize (Project_Node_Tree : out Project_Node_Tree_Ref); -- Performs default and package initialization. Therefore, -- Compile_Sources can be called by an external unit. @@ -1033,8 +1025,13 @@ package body Make is -- Args must have a lower bound of 1. Success indicates if the link -- succeeded or not. - procedure Scan_Make_Arg (Argv : String; And_Save : Boolean); - -- Scan make arguments. Argv is a single argument to be processed + procedure Scan_Make_Arg + (Project_Node_Tree : Project_Node_Tree_Ref; + Argv : String; + And_Save : Boolean); + -- Scan make arguments. Argv is a single argument to be processed. + -- Project_Node_Tree will be used to initialize external references. It + -- must have been initialized. ------------------- -- Add_Arguments -- @@ -1256,7 +1253,8 @@ package body Make is File_Name : String; Index : Int; Program : Make_Program_Type; - Unknown_Switches_To_The_Compiler : Boolean := True) + Unknown_Switches_To_The_Compiler : Boolean := True; + Project_Node_Tree : Project_Node_Tree_Ref) is Switches : Variable_Value; Switch_List : String_List_Id; @@ -1274,7 +1272,7 @@ package body Make is (Source_File => Name_Find, Source_File_Name => File_Name, Source_Index => Index, - Naming => Main_Project.Naming, + Project => Main_Project, In_Package => The_Package, Allow_ALI => Program = Binder or else Program = Linker); @@ -1297,7 +1295,8 @@ package body Make is Write_Line (Argv); end if; - Scan_Make_Arg (Argv, And_Save => False); + Scan_Make_Arg + (Project_Node_Tree, Argv, And_Save => False); if not Gnatmake_Switch_Found and then not Switch_May_Be_Passed_To_The_Compiler @@ -1378,32 +1377,24 @@ package body Make is -------------------------------- procedure Change_To_Object_Directory (Project : Project_Id) is - Actual_Project : Project_Id; Object_Directory : Path_Name_Type; begin - -- For sources outside of any project, compilation occurs in the object - -- directory of the main project, otherwise we use the project given. - - if Project = No_Project then - Actual_Project := Main_Project; - else - Actual_Project := Project; - end if; + pragma Assert (Project /= No_Project); -- Nothing to do if the current working directory is already the correct -- object directory. - if Project_Of_Current_Object_Directory /= Actual_Project then - Project_Of_Current_Object_Directory := Actual_Project; - Object_Directory := Actual_Project.Object_Directory.Name; + if Project_Of_Current_Object_Directory /= Project then + Project_Of_Current_Object_Directory := Project; + Object_Directory := Project.Object_Directory.Name; -- Set the working directory to the object directory of the actual -- project. if Verbose_Mode then Write_Str ("Changing to object directory of """); - Write_Name (Actual_Project.Display_Name); + Write_Name (Project.Display_Name); Write_Str (""": """); Write_Name (Object_Directory); Write_Line (""""); @@ -1418,9 +1409,9 @@ package body Make is when Directory_Error => Make_Failed ("unable to change to object directory """ & Path_Or_File_Name - (Actual_Project.Object_Directory.Name) & + (Project.Object_Directory.Name) & """ of project " & - Get_Name_String (Actual_Project.Display_Name)); + Get_Name_String (Project.Display_Name)); end Change_To_Object_Directory; ----------- @@ -1433,15 +1424,13 @@ package body Make is Is_Main_Source : Boolean; The_Args : Argument_List; Lib_File : File_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : access File_Attributes; Read_Only : Boolean; ALI : out ALI_Id; O_File : out File_Name_Type; O_Stamp : out Time_Stamp_Type) is - function File_Not_A_Source_Of - (Uname : Name_Id; - Sfile : File_Name_Type) return Boolean; - function First_New_Spec (A : ALI_Id) return File_Name_Type; -- Looks in the with table entries of A and returns the spec file name -- of the first withed unit (subprogram) for which no spec existed when @@ -1456,34 +1445,6 @@ package body Make is -- services, but this causes the whole compiler to be dragged along -- for gnatbind and gnatmake. - -------------------------- - -- File_Not_A_Source_Of -- - -------------------------- - - function File_Not_A_Source_Of - (Uname : Name_Id; - Sfile : File_Name_Type) return Boolean - is - UID : Prj.Unit_Index; - U_Data : Unit_Data; - - begin - UID := Units_Htable.Get (Project_Tree.Units_HT, Uname); - - if UID /= Prj.No_Unit_Index then - U_Data := Project_Tree.Units.Table (UID); - - if U_Data.File_Names (Body_Part).Name /= Sfile - and then U_Data.File_Names (Specification).Name /= Sfile - then - Verbose_Msg (Uname, "sources do not include ", Name_Id (Sfile)); - return True; - end if; - end if; - - return False; - end File_Not_A_Source_Of; - -------------------- -- First_New_Spec -- -------------------- @@ -1574,9 +1535,6 @@ package body Make is -- Data declarations for Check -- --------------------------------- - Full_Lib_File : File_Name_Type; - -- Full name of current library file - Full_Obj_File : File_Name_Type; -- Full name of the object file corresponding to Lib_File @@ -1627,15 +1585,14 @@ package body Make is Check_Object_Consistency; begin Check_Object_Consistency := False; - Text := Read_Library_Info (Lib_File); + Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr); Check_Object_Consistency := Saved_Check_Object_Consistency; end; else - Text := Read_Library_Info (Lib_File); + Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr); end if; - Full_Lib_File := Full_Library_Info_Name; Full_Obj_File := Full_Object_File_Name; Lib_Stamp := Current_Library_File_Stamp; Obj_Stamp := Current_Object_File_Stamp; @@ -1859,72 +1816,10 @@ package body Make is elsif not Read_Only and then Main_Project /= No_Project then - -- Check if a file name does not correspond to the mapping of - -- units to file names. - - declare - SD : Sdep_Record; - WR : With_Record; - Unit_Name : Name_Id; - - begin - U_Chk : - for U in ALIs.Table (ALI).First_Unit .. - ALIs.Table (ALI).Last_Unit - loop - -- Check if the file name is one of the source of the - -- unit. - - Get_Name_String (Units.Table (U).Uname); - Name_Len := Name_Len - 2; - Unit_Name := Name_Find; - - if File_Not_A_Source_Of - (Unit_Name, Units.Table (U).Sfile) - then - ALI := No_ALI_Id; - return; - end if; - - -- Do the same check for each of the withed units - - W_Check : - for W in Units.Table (U).First_With - .. - Units.Table (U).Last_With - loop - WR := Withs.Table (W); - - if WR.Sfile /= No_File then - Get_Name_String (WR.Uname); - Name_Len := Name_Len - 2; - Unit_Name := Name_Find; - - if File_Not_A_Source_Of (Unit_Name, WR.Sfile) then - ALI := No_ALI_Id; - return; - end if; - end if; - end loop W_Check; - end loop U_Chk; - - -- Check also the subunits - - D_Check : - for D in ALIs.Table (ALI).First_Sdep .. - ALIs.Table (ALI).Last_Sdep - loop - SD := Sdep.Table (D); - Unit_Name := SD.Subunit_Name; - - if Unit_Name /= No_Name then - if File_Not_A_Source_Of (Unit_Name, SD.Sfile) then - ALI := No_ALI_Id; - return; - end if; - end if; - end loop D_Check; - end; + if not Check_Source_Info_In_ALI (ALI) then + ALI := No_ALI_Id; + return; + end if; -- Check that the ALI file is in the correct object directory. -- If it is in the object directory of a project that is @@ -1939,23 +1834,25 @@ package body Make is ALI_Project := No_Project; declare - Udata : Prj.Unit_Data; + Udata : Prj.Unit_Index; begin - for U in 1 .. Unit_Table.Last (Project_Tree.Units) loop - Udata := Project_Tree.Units.Table (U); - - if Udata.File_Names (Body_Part).Name = Source_File then - ALI_Project := Udata.File_Names (Body_Part).Project; + Udata := Units_Htable.Get_First (Project_Tree.Units_HT); + while Udata /= No_Unit_Index loop + if Udata.File_Names (Impl) /= null + and then Udata.File_Names (Impl).File = Source_File + then + ALI_Project := Udata.File_Names (Impl).Project; exit; - elsif - Udata.File_Names (Specification).Name = Source_File + elsif Udata.File_Names (Spec) /= null + and then Udata.File_Names (Spec).File = Source_File then - ALI_Project := - Udata.File_Names (Specification).Project; + ALI_Project := Udata.File_Names (Spec).Project; exit; end if; + + Udata := Units_Htable.Get_Next (Project_Tree.Units_HT); end loop; end; @@ -1969,19 +1866,16 @@ package body Make is Normalize_Pathname (Dir_Name (Get_Name_String (Full_Lib_File)), - Resolve_Links => True, + Resolve_Links => + Opt.Follow_Links_For_Dirs, Case_Sensitive => False); begin Name_Len := 0; Add_Str_To_Name_Buffer (Res_Obj_Dir); - if Name_Len > 1 and then - (Name_Buffer (Name_Len) = '/' - or else - Name_Buffer (Name_Len) = Directory_Separator) - then - Name_Len := Name_Len - 1; + if not Is_Directory_Separator (Name_Buffer (Name_Len)) then + Add_Char_To_Name_Buffer (Directory_Separator); end if; Obj_Dir := Name_Find; @@ -2029,6 +1923,7 @@ package body Make is Projects : array (1 .. Num_Ext) of Project_Id; Dep : Sdep_Record; OK : Boolean := True; + UID : Unit_Index; begin Proj := ALI_Project; @@ -2045,24 +1940,20 @@ package body Make is ALIs.Table (ALI).Last_Sdep loop Dep := Sdep.Table (D); - + UID := Units_Htable.Get_First (Project_Tree.Units_HT); Proj := No_Project; Unit_Loop : - for - UID in 1 .. Unit_Table.Last (Project_Tree.Units) - loop - if Project_Tree.Units.Table (UID). - File_Names (Body_Part).Name = Dep.Sfile + while UID /= null loop + if UID.File_Names (Impl) /= null + and then UID.File_Names (Impl).File = Dep.Sfile then - Proj := Project_Tree.Units.Table (UID). - File_Names (Body_Part).Project; + Proj := UID.File_Names (Impl).Project; - elsif Project_Tree.Units.Table (UID). - File_Names (Specification).Name = Dep.Sfile + elsif UID.File_Names (Spec) /= null + and then UID.File_Names (Spec).File = Dep.Sfile then - Proj := Project_Tree.Units.Table (UID). - File_Names (Specification).Project; + Proj := UID.File_Names (Spec).Project; end if; -- If a source is in a project, check if it is one @@ -2078,6 +1969,9 @@ package body Make is exit Unit_Loop; end if; + + UID := + Units_Htable.Get_Next (Project_Tree.Units_HT); end loop Unit_Loop; end loop D_Chk; @@ -2316,7 +2210,6 @@ package body Make is Args : Argument_List) is begin - Arguments_Collected := True; Arguments_Project := No_Project; Last_Argument := 0; Add_Arguments (Args); @@ -2386,7 +2279,7 @@ package body Make is (Source_File => Source_File, Source_File_Name => Source_File_Name, Source_Index => Source_Index, - Naming => Arguments_Project.Naming, + Project => Arguments_Project, In_Package => Compiler_Package, Allow_ALI => False); @@ -2534,62 +2427,22 @@ package body Make is Initialize_ALI_Data : Boolean := True; Max_Process : Positive := 1) is - Source_Unit : Unit_Name_Type; - -- Current source unit - - Source_File : File_Name_Type; - -- Current source file - - Full_Source_File : File_Name_Type; - -- Full name of the current source file - - Lib_File : File_Name_Type; - -- Current library file - - Full_Lib_File : File_Name_Type; - -- Full name of the current library file - - Obj_File : File_Name_Type; - -- Full name of the object file corresponding to Lib_File - - Obj_Stamp : Time_Stamp_Type; - -- Time stamp of the current object file - - Sfile : File_Name_Type; - -- Contains the source file of the units withed by Source_File - - Uname : Unit_Name_Type; - -- Contains the unit name of the units withed by Source_File - - ALI : ALI_Id; - -- ALI Id of the current ALI file - - -- Comment following declarations ??? - - Read_Only : Boolean := False; - - Compilation_OK : Boolean; - Need_To_Compile : Boolean; - - Pid : Process_Id; - Text : Text_Buffer_Ptr; - - Mfile : Natural := No_Mapping_File; + Mfile : Natural := No_Mapping_File; + Mapping_File_Arg : String_Access; + -- Info on the mapping file Need_To_Check_Standard_Library : Boolean := Check_Readonly_Files and not Unique_Compile; - Mapping_File_Arg : String_Access; - - Process_Created : Boolean := False; - procedure Add_Process - (Pid : Process_Id; - Sfile : File_Name_Type; - Afile : File_Name_Type; - Uname : Unit_Name_Type; - Mfile : Natural := No_Mapping_File); + (Pid : Process_Id; + Sfile : File_Name_Type; + Afile : File_Name_Type; + Uname : Unit_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : File_Attributes; + Mfile : Natural := No_Mapping_File); -- Adds process Pid to the current list of outstanding compilation -- processes and record the full name of the source file Sfile that -- we are compiling, the name of its library file Afile and the @@ -2598,18 +2451,14 @@ package body Make is -- array The_Mapping_File_Names. procedure Await_Compile - (Sfile : out File_Name_Type; - Afile : out File_Name_Type; - Uname : out Unit_Name_Type; + (Data : out Compilation_Data; OK : out Boolean); - -- Awaits that an outstanding compilation process terminates. When - -- it does set Sfile to the name of the source file that was compiled - -- Afile to the name of its library file and Uname to the name of its - -- unit. Note that this time stamp can be used to check whether the - -- compilation did generate an object file. OK is set to True if the - -- compilation succeeded. Note that Sfile, Afile and Uname could be - -- resp. No_File, No_File and No_Name if there were no compilations - -- to wait for. + -- Awaits that an outstanding compilation process terminates. When it + -- does set Data to the information registered for the corresponding + -- call to Add_Process. Note that this time stamp can be used to check + -- whether the compilation did generate an object file. OK is set to + -- True if the compilation succeeded. Data could be No_Compilation_Data + -- if there was no compilation to wait for. function Bad_Compilation_Count return Natural; -- Returns the number of compilation failures @@ -2618,12 +2467,18 @@ package body Make is -- Check if s-stalib.adb needs to be compiled procedure Collect_Arguments_And_Compile - (Source_File : File_Name_Type; - Source_Index : Int); - -- Collect arguments from project file (if any) and compile + (Full_Source_File : File_Name_Type; + Lib_File : File_Name_Type; + Source_Index : Int; + Pid : out Process_Id; + Process_Created : out Boolean); + -- Collect arguments from project file (if any) and compile. If no + -- compilation was attempted, Processed_Created is set to False, and the + -- value of Pid is unknown. function Compile - (S : File_Name_Type; + (Project : Project_Id; + S : File_Name_Type; L : File_Name_Type; Source_Index : Int; Args : Argument_List) return Process_Id; @@ -2662,16 +2517,41 @@ package body Make is procedure Record_Good_ALI (A : ALI_Id); -- Records in the previous set the Id of an ALI file + function Must_Exit_Because_Of_Error return Boolean; + -- Return True if there were errors and the user decided to exit in such + -- a case. This waits for any outstanding compilation. + + function Start_Compile_If_Possible (Args : Argument_List) return Boolean; + -- Check if there is more work that we can do (i.e. the Queue is non + -- empty). If there is, do it only if we have not yet used up all the + -- available processes. + -- Returns True if we should exit the main loop + + procedure Wait_For_Available_Slot; + -- Check if we should wait for a compilation to finish. This is the case + -- if all the available processes are busy compiling sources or there is + -- nothing else to do (that is the Q is empty and there are no good ALIs + -- to process). + + procedure Fill_Queue_From_ALI_Files; + -- Check if we recorded good ALI files. If yes process them now in the + -- order in which they have been recorded. There are two occasions in + -- which we record good ali files. The first is in phase 1 when, after + -- scanning an existing ALI file we realize it is up-to-date, the second + -- instance is after a successful compilation. + ----------------- -- Add_Process -- ----------------- procedure Add_Process - (Pid : Process_Id; - Sfile : File_Name_Type; - Afile : File_Name_Type; - Uname : Unit_Name_Type; - Mfile : Natural := No_Mapping_File) + (Pid : Process_Id; + Sfile : File_Name_Type; + Afile : File_Name_Type; + Uname : Unit_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : File_Attributes; + Mfile : Natural := No_Mapping_File) is OC1 : constant Positive := Outstanding_Compiles + 1; @@ -2679,14 +2559,15 @@ package body Make is pragma Assert (OC1 <= Max_Process); pragma Assert (Pid /= Invalid_Pid); - Running_Compile (OC1).Pid := Pid; - Running_Compile (OC1).Full_Source_File := Sfile; - Running_Compile (OC1).Lib_File := Afile; - Running_Compile (OC1).Source_Unit := Uname; - Running_Compile (OC1).Mapping_File := Mfile; - Running_Compile (OC1).Project := Arguments_Project; - Running_Compile (OC1).Syntax_Only := Syntax_Only; - Running_Compile (OC1).Output_Is_Object := Output_Is_Object; + Running_Compile (OC1) := + (Pid => Pid, + Full_Source_File => Sfile, + Lib_File => Afile, + Full_Lib_File => Full_Lib_File, + Lib_File_Attr => Lib_File_Attr, + Source_Unit => Uname, + Mapping_File => Mfile, + Project => Arguments_Project); Outstanding_Compiles := OC1; end Add_Process; @@ -2696,22 +2577,18 @@ package body Make is ------------------- procedure Await_Compile - (Sfile : out File_Name_Type; - Afile : out File_Name_Type; - Uname : out Unit_Name_Type; - OK : out Boolean) + (Data : out Compilation_Data; + OK : out Boolean) is - Pid : Process_Id; - Project : Project_Id; - Data : Project_Compilation_Access; + Pid : Process_Id; + Project : Project_Id; + Comp_Data : Project_Compilation_Access; begin pragma Assert (Outstanding_Compiles > 0); - Sfile := No_File; - Afile := No_File; - Uname := No_Unit_Name; - OK := False; + Data := No_Compilation_Data; + OK := False; -- The loop here is a work-around for a problem on VMS; in some -- circumstances (shared library and several executables, for @@ -2728,22 +2605,21 @@ package body Make is for J in Running_Compile'First .. Outstanding_Compiles loop if Pid = Running_Compile (J).Pid then - Sfile := Running_Compile (J).Full_Source_File; - Afile := Running_Compile (J).Lib_File; - Uname := Running_Compile (J).Source_Unit; - Syntax_Only := Running_Compile (J).Syntax_Only; - Output_Is_Object := Running_Compile (J).Output_Is_Object; + Data := Running_Compile (J); Project := Running_Compile (J).Project; - -- If a mapping file was used by this compilation, - -- get its file name for reuse by a subsequent compilation + -- If a mapping file was used by this compilation, get its + -- file name for reuse by a subsequent compilation. if Running_Compile (J).Mapping_File /= No_Mapping_File then - Data := Project_Compilation_Htable.Get - (Project_Compilation, Project); - Data.Last_Free_Indices := Data.Last_Free_Indices + 1; - Data.Free_Mapping_File_Indices (Data.Last_Free_Indices) := - Running_Compile (J).Mapping_File; + Comp_Data := + Project_Compilation_Htable.Get + (Project_Compilation, Project); + Comp_Data.Last_Free_Indices := + Comp_Data.Last_Free_Indices + 1; + Comp_Data.Free_Mapping_File_Indices + (Comp_Data.Last_Free_Indices) := + Running_Compile (J).Mapping_File; end if; -- To actually remove this Pid and related info from @@ -2752,7 +2628,6 @@ package body Make is if J = Outstanding_Compiles then null; - else Running_Compile (J) := Running_Compile (Outstanding_Compiles); @@ -2766,6 +2641,8 @@ package body Make is -- This child process was not one of our compilation processes; -- just ignore it for now. + -- Why is this commented out code sitting here??? + -- raise Program_Error; end loop; end Await_Compile; @@ -2801,8 +2678,7 @@ package body Make is -- library only if we can find it. if RTS_Switch then - Add_It := - Find_File (Sfile, Osint.Source) /= No_File; + Add_It := Full_Source_Name (Sfile) /= No_File; end if; if Add_It then @@ -2825,22 +2701,14 @@ package body Make is ----------------------------------- procedure Collect_Arguments_And_Compile - (Source_File : File_Name_Type; - Source_Index : Int) - is + (Full_Source_File : File_Name_Type; + Lib_File : File_Name_Type; + Source_Index : Int; + Pid : out Process_Id; + Process_Created : out Boolean) is begin - -- Process_Created will be set True if an attempt is made to compile - -- the source, that is if it is not in an externally built project. - Process_Created := False; - -- If arguments not yet collected (in Check), collect them now - - if not Arguments_Collected then - Collect_Arguments - (Source_File, Source_Index, Source_File = Main_Source, Args); - end if; - -- If we use mapping file (-P or -C switches), then get one if Create_Mapping_File then @@ -2884,16 +2752,13 @@ package body Make is end; end if; - -- Change to object directory of the project file, if necessary - - Change_To_Object_Directory (Arguments_Project); - Pid := Compile - (File_Name_Type (Arguments_Path_Name), - Lib_File, - Source_Index, - Arguments (1 .. Last_Argument)); + (Project => Arguments_Project, + S => File_Name_Type (Arguments_Path_Name), + L => Lib_File, + Source_Index => Source_Index, + Args => Arguments (1 .. Last_Argument)); Process_Created := True; end if; @@ -2901,12 +2766,13 @@ package body Make is -- If this is a source outside of any project file, make sure it -- will be compiled in object directory of the main project file. - if Main_Project /= No_Project then - Change_To_Object_Directory (Arguments_Project); - end if; - - Pid := Compile (Full_Source_File, Lib_File, Source_Index, - Arguments (1 .. Last_Argument)); + Pid := + Compile + (Project => Main_Project, + S => Full_Source_File, + L => Lib_File, + Source_Index => Source_Index, + Args => Arguments (1 .. Last_Argument)); Process_Created := True; end if; end Collect_Arguments_And_Compile; @@ -2916,7 +2782,8 @@ package body Make is ------------- function Compile - (S : File_Name_Type; + (Project : Project_Id; + S : File_Name_Type; L : File_Name_Type; Source_Index : Int; Args : Argument_List) return Process_Id @@ -2985,7 +2852,9 @@ package body Make is Comp_Next := Comp_Next + 1; -- Optimize the simple case where the gcc command line looks like - -- gcc -c -I. ... -I- file.adb --into-> gcc -c ... file.adb + -- gcc -c -I. ... -I- file.adb + -- into + -- gcc -c ... file.adb if Args (Args'First).all = "-I" & Normalized_CWD and then Args (Args'Last).all = "-I-" @@ -3088,9 +2957,9 @@ package body Make is end if; end if; - if Create_Mapping_File then + if Create_Mapping_File and then Mapping_File_Arg /= null then Comp_Last := Comp_Last + 1; - Comp_Args (Comp_Last) := Mapping_File_Arg; + Comp_Args (Comp_Last) := new String'(Mapping_File_Arg.all); end if; Get_Name_String (S); @@ -3098,6 +2967,12 @@ package body Make is Comp_Last := Comp_Last + 1; Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len)); + -- Change to object directory of the project file, if necessary + + if Project /= No_Project then + Change_To_Object_Directory (Project); + end if; + GNAT.OS_Lib.Normalize_Arguments (Comp_Args (Args'First .. Comp_Last)); Comp_Last := Comp_Last + 1; @@ -3114,6 +2989,118 @@ package body Make is (Gcc_Path.all, Comp_Args (Args'First .. Comp_Last)); end Compile; + ------------------------------- + -- Fill_Queue_From_ALI_Files -- + ------------------------------- + + procedure Fill_Queue_From_ALI_Files is + ALI : ALI_Id; + Source_Index : Int; + Sfile : File_Name_Type; + Uname : Unit_Name_Type; + Unit_Name : Name_Id; + Uid : Prj.Unit_Index; + + begin + while Good_ALI_Present loop + ALI := Get_Next_Good_ALI; + Source_Index := Unit_Index_Of (ALIs.Table (ALI).Afile); + + -- If we are processing the library file corresponding to the + -- main source file check if this source can be a main unit. + + if ALIs.Table (ALI).Sfile = Main_Source + and then Source_Index = Main_Index + then + Main_Unit := ALIs.Table (ALI).Main_Program /= None; + end if; + + -- The following adds the standard library (s-stalib) to the list + -- of files to be handled by gnatmake: this file and any files it + -- depends on are always included in every bind, even if they are + -- not in the explicit dependency list. Of course, it is not added + -- if Suppress_Standard_Library is True. + + -- However, to avoid annoying output about s-stalib.ali being read + -- only, when "-v" is used, we add the standard library only when + -- "-a" is used. + + if Need_To_Check_Standard_Library then + Check_Standard_Library; + end if; + + -- Now insert in the Q the unmarked source files (i.e. those which + -- have never been inserted in the Q and hence never considered). + -- Only do that if Unique_Compile is False. + + if not Unique_Compile then + for J in + ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit + loop + for K in + Units.Table (J).First_With .. Units.Table (J).Last_With + loop + Sfile := Withs.Table (K).Sfile; + Uname := Withs.Table (K).Uname; + + -- If project files are used, find the proper source to + -- compile in case Sfile is the spec but there is a body. + + if Main_Project /= No_Project then + Get_Name_String (Uname); + Name_Len := Name_Len - 2; + Unit_Name := Name_Find; + Uid := + Units_Htable.Get (Project_Tree.Units_HT, Unit_Name); + + if Uid /= Prj.No_Unit_Index then + if Uid.File_Names (Impl) /= null + and then not Uid.File_Names (Impl).Locally_Removed + then + Sfile := Uid.File_Names (Impl).File; + Source_Index := Uid.File_Names (Impl).Index; + + 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; + end if; + end if; + end if; + + Dependencies.Append ((ALIs.Table (ALI).Sfile, Sfile)); + + if Is_In_Obsoleted (Sfile) then + Executable_Obsolete := True; + end if; + + if Sfile = No_File then + Debug_Msg ("Skipping generic:", Withs.Table (K).Uname); + + else + Source_Index := Unit_Index_Of (Withs.Table (K).Afile); + + if Is_Marked (Sfile, Source_Index) then + Debug_Msg ("Skipping marked file:", Sfile); + + elsif not Check_Readonly_Files + and then Is_Internal_File_Name (Sfile, False) + then + Debug_Msg ("Skipping internal file:", Sfile); + + else + Insert_Q + (Sfile, Withs.Table (K).Uname, Source_Index); + Mark (Sfile, Source_Index); + end if; + end if; + end loop; + end loop; + end if; + end loop; + end Fill_Queue_From_ALI_Files; + ---------------------- -- Get_Mapping_File -- ---------------------- @@ -3169,6 +3156,30 @@ package body Make is return Good_ALI.First <= Good_ALI.Last; end Good_ALI_Present; + -------------------------------- + -- Must_Exit_Because_Of_Error -- + -------------------------------- + + function Must_Exit_Because_Of_Error return Boolean is + Data : Compilation_Data; + Success : Boolean; + + begin + if Bad_Compilation_Count > 0 and then not Keep_Going then + while Outstanding_Compiles > 0 loop + Await_Compile (Data, Success); + + if not Success then + Record_Failure (Data.Full_Source_File, Data.Source_Unit); + end if; + end loop; + + return True; + end if; + + return False; + end Must_Exit_Because_Of_Error; + -------------------- -- Record_Failure -- -------------------- @@ -3193,279 +3204,332 @@ package body Make is Good_ALI.Table (Good_ALI.Last) := A; end Record_Good_ALI; - -- Start of processing for Compile_Sources - - begin - pragma Assert (Args'First = 1); + ------------------------------- + -- Start_Compile_If_Possible -- + ------------------------------- - Outstanding_Compiles := 0; - Running_Compile := new Comp_Data_Arr (1 .. Max_Process); + function Start_Compile_If_Possible + (Args : Argument_List) return Boolean + is + In_Lib_Dir : Boolean; + Need_To_Compile : Boolean; + Pid : Process_Id; + Process_Created : Boolean; - -- Package and Queue initializations + Source_File : File_Name_Type; + Full_Source_File : File_Name_Type; + Source_File_Attr : aliased File_Attributes; + -- The full name of the source file and its attributes (size, ...) - Good_ALI.Init; + Source_Unit : Unit_Name_Type; + Source_Index : Int; + -- Index of the current unit in the current source file - if First_Q_Initialization then - Init_Q; - end if; + Lib_File : File_Name_Type; + Full_Lib_File : File_Name_Type; + Lib_File_Attr : aliased File_Attributes; + Read_Only : Boolean := False; + ALI : ALI_Id; + -- The ALI file and its attributes (size, stamp, ...) - if Initialize_ALI_Data then - Initialize_ALI; - Initialize_ALI_Source; - end if; + Obj_File : File_Name_Type; + Obj_Stamp : Time_Stamp_Type; + -- The object file - -- The following two flags affect the behavior of ALI.Set_Source_Table. - -- We set Check_Source_Files to True to ensure that source file - -- time stamps are checked, and we set All_Sources to False to - -- avoid checking the presence of the source files listed in the - -- source dependency section of an ali file (which would be a mistake - -- since the ali file may be obsolete). + begin + if not Empty_Q and then Outstanding_Compiles < Max_Process then + Extract_From_Q (Source_File, Source_Unit, Source_Index); - Check_Source_Files := True; - All_Sources := False; + Osint.Full_Source_Name + (Source_File, + Full_File => Full_Source_File, + Attr => Source_File_Attr'Access); - -- Only insert in the Q if it is not already done, to avoid simultaneous - -- compilations if -jnnn is used. + Lib_File := Osint.Lib_File_Name (Source_File, Source_Index); - if not Is_Marked (Main_Source, Main_Index) then - Insert_Q (Main_Source, Index => Main_Index); - Mark (Main_Source, Main_Index); - end if; + -- ??? 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. - First_Compiled_File := No_File; - Most_Recent_Obj_File := No_File; - Most_Recent_Obj_Stamp := Empty_Time_Stamp; - Main_Unit := False; + Osint.Full_Lib_File_Name + (Lib_File, + Lib_File => Full_Lib_File, + Attr => Lib_File_Attr); - -- Keep looping until there is no more work to do (the Q is empty) - -- and all the outstanding compilations have terminated + -- If source has already been compiled, executable is obsolete - Make_Loop : while not Empty_Q or else Outstanding_Compiles > 0 loop + if Is_In_Obsoleted (Source_File) then + Executable_Obsolete := True; + end if; - -- If the user does not want to keep going in case of errors then - -- wait for the remaining outstanding compiles and then exit. + In_Lib_Dir := Full_Lib_File /= No_File + and then In_Ada_Lib_Dir (Full_Lib_File); - if Bad_Compilation_Count > 0 and then not Keep_Going then - while Outstanding_Compiles > 0 loop - Await_Compile - (Full_Source_File, Lib_File, Source_Unit, Compilation_OK); + -- Since the following requires a system call, we precompute it + -- when needed. - if not Compilation_OK then - Record_Failure (Full_Source_File, Source_Unit); + if not In_Lib_Dir then + if Full_Lib_File /= No_File + and then not Check_Readonly_Files + then + Get_Name_String (Full_Lib_File); + Name_Buffer (Name_Len + 1) := ASCII.NUL; + Read_Only := not Is_Writable_File + (Name_Buffer'Address, Lib_File_Attr'Access); + else + Read_Only := False; end if; - end loop; + end if; - exit Make_Loop; - end if; + -- If the library file is an Ada library skip it - -- PHASE 1: Check if there is more work that we can do (i.e. the Q - -- is non empty). If there is, do it only if we have not yet used - -- up all the available processes. + if In_Lib_Dir then + Verbose_Msg + (Lib_File, + "is in an Ada library", + Prefix => " ", + Minimum_Verbosity => Opt.High); - if not Empty_Q and then Outstanding_Compiles < Max_Process then - declare - Source_Index : Int; - -- Index of the current unit in the current source file + -- If the library file is a read-only library skip it, but only + -- if, when using project files, this library file is in the + -- right object directory (a read-only ALI file in the object + -- directory of a project being extended must not be skipped). - begin - Extract_From_Q (Source_File, Source_Unit, Source_Index); - Full_Source_File := Osint.Full_Source_Name (Source_File); - Lib_File := Osint.Lib_File_Name - (Source_File, Source_Index); - Full_Lib_File := Osint.Full_Lib_File_Name (Lib_File); + elsif Read_Only + and then Is_In_Object_Directory (Source_File, Full_Lib_File) + then + Verbose_Msg + (Lib_File, + "is a read-only library", + Prefix => " ", + Minimum_Verbosity => Opt.High); - -- If this source has already been compiled, the executable is - -- obsolete. + -- The source file that we are checking cannot be located - if Is_In_Obsoleted (Source_File) then - Executable_Obsolete := True; - end if; + elsif Full_Source_File = No_File then + Record_Failure (Source_File, Source_Unit, False); - -- If the library file is an Ada library skip it + -- Source and library files can be located but are internal + -- files. - if Full_Lib_File /= No_File - and then In_Ada_Lib_Dir (Full_Lib_File) - then - Verbose_Msg - (Lib_File, - "is in an Ada library", - Prefix => " ", - Minimum_Verbosity => Opt.High); - - -- If the library file is a read-only library skip it, but - -- only if, when using project files, this library file is - -- in the right object directory (a read-only ALI file - -- in the object directory of a project being extended - -- should not be skipped). - - elsif Full_Lib_File /= No_File - and then not Check_Readonly_Files - and then Is_Readonly_Library (Full_Lib_File) - and then Is_In_Object_Directory (Source_File, Full_Lib_File) - then - Verbose_Msg - (Lib_File, - "is a read-only library", - Prefix => " ", - Minimum_Verbosity => Opt.High); + elsif not Check_Readonly_Files + and then Full_Lib_File /= No_File + and then Is_Internal_File_Name (Source_File, False) + then + if Force_Compilations then + Fail + ("not allowed to compile """ & + Get_Name_String (Source_File) & + """; use -a switch, or compile file with " & + """-gnatg"" switch"); + end if; - -- The source file that we are checking cannot be located + Verbose_Msg + (Lib_File, + "is an internal library", + Prefix => " ", + Minimum_Verbosity => Opt.High); - elsif Full_Source_File = No_File then - Record_Failure (Source_File, Source_Unit, False); + -- The source file that we are checking can be located + + else + Collect_Arguments (Source_File, Source_Index, + Source_File = Main_Source, Args); - -- Source and library files can be located but are internal - -- files + -- Do nothing if project of source is externally built - elsif not Check_Readonly_Files - and then Full_Lib_File /= No_File - and then Is_Internal_File_Name (Source_File, False) + if Arguments_Project = No_Project + or else not Arguments_Project.Externally_Built then - if Force_Compilations then - Fail - ("not allowed to compile """ & - Get_Name_String (Source_File) & - """; use -a switch, or compile file with " & - """-gnatg"" switch"); + -- Don't waste any time if we have to recompile anyway + + Obj_Stamp := Empty_Time_Stamp; + Need_To_Compile := Force_Compilations; + + if not Force_Compilations then + Check (Source_File => Source_File, + Source_Index => Source_Index, + Is_Main_Source => Source_File = Main_Source, + The_Args => Args, + Lib_File => Lib_File, + Full_Lib_File => Full_Lib_File, + Lib_File_Attr => Lib_File_Attr'Access, + Read_Only => Read_Only, + ALI => ALI, + O_File => Obj_File, + O_Stamp => Obj_Stamp); + Need_To_Compile := (ALI = No_ALI_Id); end if; - Verbose_Msg - (Lib_File, - "is an internal library", - Prefix => " ", - Minimum_Verbosity => Opt.High); + if not Need_To_Compile then - -- The source file that we are checking can be located - - else - Arguments_Collected := False; + -- The ALI file is up-to-date; record its Id - Collect_Arguments (Source_File, Source_Index, - Source_File = Main_Source, Args); + Record_Good_ALI (ALI); - -- Do nothing if project of source is externally built + -- Record the time stamp of the most recent object + -- file as long as no (re)compilations are needed. - if Arguments_Project = No_Project - or else not Arguments_Project.Externally_Built - then - -- Don't waste any time if we have to recompile anyway - - Obj_Stamp := Empty_Time_Stamp; - Need_To_Compile := Force_Compilations; - - if not Force_Compilations then - Read_Only := - Full_Lib_File /= No_File - and then not Check_Readonly_Files - and then Is_Readonly_Library (Full_Lib_File); - Check (Source_File, Source_Index, - Source_File = Main_Source, Args, Lib_File, - Read_Only, ALI, Obj_File, Obj_Stamp); - Need_To_Compile := (ALI = No_ALI_Id); + if First_Compiled_File = No_File + and then (Most_Recent_Obj_File = No_File + or else Obj_Stamp > Most_Recent_Obj_Stamp) + then + Most_Recent_Obj_File := Obj_File; + Most_Recent_Obj_Stamp := Obj_Stamp; end if; - if not Need_To_Compile then - -- The ALI file is up-to-date. Record its Id - - Record_Good_ALI (ALI); - - -- Record the time stamp of the most recent object - -- file as long as no (re)compilations are needed. + else + -- Check that switch -x has been used if a source outside + -- of project files need to be compiled. - if First_Compiled_File = No_File - and then (Most_Recent_Obj_File = No_File - or else Obj_Stamp > Most_Recent_Obj_Stamp) - then - Most_Recent_Obj_File := Obj_File; - Most_Recent_Obj_Stamp := Obj_Stamp; - end if; + if Main_Project /= No_Project + and then Arguments_Project = No_Project + and then not External_Unit_Compilation_Allowed + then + Make_Failed ("external source (" + & Get_Name_String (Source_File) + & ") is not part of any project;" + & " cannot be compiled without" + & " gnatmake switch -x"); + end if; - else - -- Check that switch -x has been used if a source - -- outside of project files need to be compiled. + -- Is this the first file we have to compile? - if Main_Project /= No_Project - and then Arguments_Project = No_Project - and then not External_Unit_Compilation_Allowed - then - Make_Failed ("external source (" - & Get_Name_String (Source_File) - & ") is not part of any project;" - & " cannot be compiled without" - & " gnatmake switch -x"); - end if; + if First_Compiled_File = No_File then + First_Compiled_File := Full_Source_File; + Most_Recent_Obj_File := No_File; - -- Is this the first file we have to compile? + if Do_Not_Execute then - if First_Compiled_File = No_File then - First_Compiled_File := Full_Source_File; - Most_Recent_Obj_File := No_File; + -- Exit the main loop - if Do_Not_Execute then - exit Make_Loop; - end if; + return True; end if; + end if; + + -- Compute where the ALI file must be generated in + -- In_Place_Mode (this does not require to know the + -- location of the object directory). - if In_Place_Mode then + if In_Place_Mode then + if Full_Lib_File = No_File then -- If the library file was not found, then save -- the library file near the source file. - if Full_Lib_File = No_File then - Lib_File := Osint.Lib_File_Name - (Full_Source_File, Source_Index); + Lib_File := + Osint.Lib_File_Name + (Full_Source_File, Source_Index); + Full_Lib_File := Lib_File; + + else + -- If the library file was found, then save the + -- library file in the same place. + + Lib_File := Full_Lib_File; + end if; + end if; + + -- Start the compilation and record it. We can do this + -- because there is at least one free process. This might + -- change the current directory. + + Collect_Arguments_And_Compile + (Full_Source_File => Full_Source_File, + Lib_File => Lib_File, + Source_Index => Source_Index, + Pid => Pid, + Process_Created => Process_Created); + + -- Compute where the ALI file will be generated (for + -- cases that might require to know the current + -- directory). The current directory might be changed + -- when compiling other files so we cannot rely on it + -- being the same to find the resulting ALI file. + + if not In_Place_Mode then + + -- Compute the expected location of the ALI file. This + -- can be from several places: + -- -i => in place mode. In such a case, + -- Full_Lib_File has already been set above + -- -D => if specified + -- or defaults in current dir + -- We could simply use a call similar to + -- Osint.Full_Lib_File_Name (Lib_File) + -- but that involves system calls and is thus slower + + if Object_Directory_Path /= null then + Name_Len := 0; + Add_Str_To_Name_Buffer (Object_Directory_Path.all); + Add_Str_To_Name_Buffer (Get_Name_String (Lib_File)); + Full_Lib_File := Name_Find; - -- If the library file was found, then save the - -- library file in the same place. + else + if Project_Of_Current_Object_Directory /= + No_Project + then + Get_Name_String + (Project_Of_Current_Object_Directory + .Object_Directory.Name); + Add_Str_To_Name_Buffer + (Get_Name_String (Lib_File)); + Full_Lib_File := Name_Find; else - Lib_File := Full_Lib_File; + Full_Lib_File := Lib_File; end if; - end if; - -- Start the compilation and record it. We can do - -- this because there is at least one free process. + end if; - Collect_Arguments_And_Compile - (Source_File, Source_Index); + Lib_File_Attr := Unknown_Attributes; - -- Make sure we could successfully start - -- the Compilation. + -- Make sure we could successfully start the compilation - if Process_Created then - if Pid = Invalid_Pid then - Record_Failure (Full_Source_File, Source_Unit); - else - Add_Process - (Pid, - Full_Source_File, - Lib_File, - Source_Unit, - Mfile); - end if; + if Process_Created then + if Pid = Invalid_Pid then + Record_Failure (Full_Source_File, Source_Unit); + else + Add_Process + (Pid => Pid, + Sfile => Full_Source_File, + Afile => Lib_File, + Uname => Source_Unit, + Mfile => Mfile, + Full_Lib_File => Full_Lib_File, + Lib_File_Attr => Lib_File_Attr); end if; end if; end if; end if; - end; + end if; end if; + return False; + end Start_Compile_If_Possible; + + ----------------------------- + -- Wait_For_Available_Slot -- + ----------------------------- - -- PHASE 2: Now check if we should wait for a compilation to - -- finish. This is the case if all the available processes are - -- busy compiling sources or there is nothing else to do - -- (that is the Q is empty and there are no good ALIs to process). + procedure Wait_For_Available_Slot is + Compilation_OK : Boolean; + Text : Text_Buffer_Ptr; + ALI : ALI_Id; + Data : Compilation_Data; + begin if Outstanding_Compiles = Max_Process or else (Empty_Q and then not Good_ALI_Present and then Outstanding_Compiles > 0) then - Await_Compile - (Full_Source_File, Lib_File, Source_Unit, Compilation_OK); + Await_Compile (Data, Compilation_OK); if not Compilation_OK then - Record_Failure (Full_Source_File, Source_Unit); + Record_Failure (Data.Full_Source_File, Data.Source_Unit); end if; if Compilation_OK or else Keep_Going then @@ -3477,30 +3541,34 @@ package body Make is Check_Object_Consistency; begin - -- If compilation was not OK, or if output is not an - -- object file and we don't do the bind step, don't check - -- for object consistency. + -- If compilation was not OK, or if output is not an object + -- file and we don't do the bind step, don't check for + -- object consistency. Check_Object_Consistency := Check_Object_Consistency - and Compilation_OK - and (Output_Is_Object or Do_Bind_Step); - Text := Read_Library_Info (Lib_File); + and Compilation_OK + and (Output_Is_Object or Do_Bind_Step); + + Text := + Read_Library_Info_From_Full + (Data.Full_Lib_File, Data.Lib_File_Attr'Access); -- Restore Check_Object_Consistency to its initial value Check_Object_Consistency := Saved_Object_Consistency; end; - -- If an ALI file was generated by this compilation, scan - -- the ALI file and record it. + -- If an ALI file was generated by this compilation, scan the + -- ALI file and record it. -- If the scan fails, a previous ali file is inconsistent with -- the unit just compiled. if Text /= null then ALI := - Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True); + Scan_ALI + (Data.Lib_File, Text, Ignore_ED => False, Err => True); if ALI = No_ALI_Id then @@ -3508,15 +3576,18 @@ package body Make is if Compilation_OK then Inform - (Lib_File, + (Data.Lib_File, "incompatible ALI file, please recompile"); - Record_Failure (Full_Source_File, Source_Unit); + Record_Failure + (Data.Full_Source_File, Data.Source_Unit); end if; + else - Free (Text); Record_Good_ALI (ALI); end if; + Free (Text); + -- If we could not read the ALI file that was just generated -- then there could be a problem reading either the ALI or the -- corresponding object file (if Check_Object_Consistency is @@ -3527,147 +3598,72 @@ package body Make is else if Compilation_OK and not Syntax_Only then Inform - (Lib_File, + (Data.Lib_File, "WARNING: ALI or object file not found after compile"); - Record_Failure (Full_Source_File, Source_Unit); + Record_Failure (Data.Full_Source_File, Data.Source_Unit); end if; end if; end if; end if; + end Wait_For_Available_Slot; - -- PHASE 3: Check if we recorded good ALI files. If yes process - -- them now in the order in which they have been recorded. There - -- are two occasions in which we record good ali files. The first is - -- in phase 1 when, after scanning an existing ALI file we realize - -- it is up-to-date, the second instance is after a successful - -- compilation. - - while Good_ALI_Present loop - ALI := Get_Next_Good_ALI; - - declare - Source_Index : Int := Unit_Index_Of (ALIs.Table (ALI).Afile); - - begin - -- If we are processing the library file corresponding to the - -- main source file check if this source can be a main unit. + -- Start of processing for Compile_Sources - if ALIs.Table (ALI).Sfile = Main_Source and then - Source_Index = Main_Index - then - Main_Unit := ALIs.Table (ALI).Main_Program /= None; - end if; + begin + pragma Assert (Args'First = 1); - -- The following adds the standard library (s-stalib) to the - -- list of files to be handled by gnatmake: this file and any - -- files it depends on are always included in every bind, - -- even if they are not in the explicit dependency list. - -- Of course, it is not added if Suppress_Standard_Library - -- is True. + Outstanding_Compiles := 0; + Running_Compile := new Comp_Data_Arr (1 .. Max_Process); - -- However, to avoid annoying output about s-stalib.ali being - -- read only, when "-v" is used, we add the standard library - -- only when "-a" is used. + -- Package and Queue initializations - if Need_To_Check_Standard_Library then - Check_Standard_Library; - end if; + Good_ALI.Init; - -- Now insert in the Q the unmarked source files (i.e. those - -- which have never been inserted in the Q and hence never - -- considered). Only do that if Unique_Compile is False. + if First_Q_Initialization then + Init_Q; + end if; - if not Unique_Compile then - for J in - ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit - loop - for K in - Units.Table (J).First_With .. Units.Table (J).Last_With - loop - Sfile := Withs.Table (K).Sfile; - Uname := Withs.Table (K).Uname; + if Initialize_ALI_Data then + Initialize_ALI; + Initialize_ALI_Source; + end if; - -- If project files are used, find the proper source - -- to compile, in case Sfile is the spec, but there - -- is a body. + -- The following two flags affect the behavior of ALI.Set_Source_Table. + -- We set Check_Source_Files to True to ensure that source file time + -- stamps are checked, and we set All_Sources to False to avoid checking + -- the presence of the source files listed in the source dependency + -- section of an ali file (which would be a mistake since the ali file + -- may be obsolete). - if Main_Project /= No_Project then - declare - Unit_Name : Name_Id; - Uid : Prj.Unit_Index; - Udata : Unit_Data; + Check_Source_Files := True; + All_Sources := False; - begin - Get_Name_String (Uname); - Name_Len := Name_Len - 2; - Unit_Name := Name_Find; - Uid := - Units_Htable.Get - (Project_Tree.Units_HT, Unit_Name); - - if Uid /= Prj.No_Unit_Index then - Udata := Project_Tree.Units.Table (Uid); - - if - Udata.File_Names (Body_Part).Name /= - No_File - and then - Udata.File_Names (Body_Part).Path.Name /= - Slash - then - Sfile := Udata.File_Names (Body_Part).Name; - Source_Index := - Udata.File_Names (Body_Part).Index; - - elsif - Udata.File_Names (Specification).Name /= - No_File - and then - Udata.File_Names - (Specification).Path.Name /= Slash - then - Sfile := - Udata.File_Names (Specification).Name; - Source_Index := - Udata.File_Names (Specification).Index; - end if; - end if; - end; - end if; + -- Only insert in the Q if it is not already done, to avoid simultaneous + -- compilations if -jnnn is used. - Dependencies.Append ((ALIs.Table (ALI).Sfile, Sfile)); + if not Is_Marked (Main_Source, Main_Index) then + Insert_Q (Main_Source, Index => Main_Index); + Mark (Main_Source, Main_Index); + end if; - if Is_In_Obsoleted (Sfile) then - Executable_Obsolete := True; - end if; + First_Compiled_File := No_File; + Most_Recent_Obj_File := No_File; + Most_Recent_Obj_Stamp := Empty_Time_Stamp; + Main_Unit := False; - if Sfile = No_File then - Debug_Msg - ("Skipping generic:", Withs.Table (K).Uname); + -- Keep looping until there is no more work to do (the Q is empty) + -- and all the outstanding compilations have terminated. - else - Source_Index := - Unit_Index_Of (Withs.Table (K).Afile); + Make_Loop : while not Empty_Q or else Outstanding_Compiles > 0 loop + exit Make_Loop when Must_Exit_Because_Of_Error; + exit Make_Loop when Start_Compile_If_Possible (Args); - if Is_Marked (Sfile, Source_Index) then - Debug_Msg ("Skipping marked file:", Sfile); + Wait_For_Available_Slot; - elsif not Check_Readonly_Files - and then Is_Internal_File_Name (Sfile, False) - then - Debug_Msg ("Skipping internal file:", Sfile); + -- ??? Should be done as soon as we add a Good_ALI, wouldn't it avoid + -- the need for a list of good ALI? - else - Insert_Q - (Sfile, Withs.Table (K).Uname, Source_Index); - Mark (Sfile, Source_Index); - end if; - end if; - end loop; - end loop; - end if; - end; - end loop; + Fill_Queue_From_ALI_Files; if Display_Compilation_Progress then Write_Str ("completed "); @@ -3758,7 +3754,7 @@ package body Make is begin Prj.Env.Create_Config_Pragmas_File - (For_Project, Main_Project, Project_Tree); + (For_Project, Project_Tree); if For_Project.Config_File_Name /= No_Path then Temporary_Config_File := For_Project.Config_File_Temp; @@ -3893,45 +3889,11 @@ package body Make is procedure Delete_All_Temp_Files is begin if not Debug.Debug_Flag_N then - Delete_Mapping_Files; Delete_Temp_Config_Files; - Prj.Env.Delete_All_Path_Files (Project_Tree); + Prj.Delete_All_Temp_Files (Project_Tree); end if; end Delete_All_Temp_Files; - -------------------------- - -- Delete_Mapping_Files -- - -------------------------- - - procedure Delete_Mapping_Files is - Success : Boolean; - pragma Warnings (Off, Success); - - Proj : Project_List; - Data : Project_Compilation_Access; - - begin - -- The caller is responsible for ensuring that Debug_Flag_N is False - - pragma Assert (not Debug.Debug_Flag_N); - - Proj := Project_Tree.Projects; - while Proj /= null loop - Data := Project_Compilation_Htable.Get - (Project_Compilation, Proj.Project); - - if Data /= null and then Data.Mapping_File_Names /= null then - for Index in 1 .. Data.Last_Mapping_File_Names loop - Delete_File - (Name => Get_Name_String (Data.Mapping_File_Names (Index)), - Success => Success); - end loop; - end if; - - Proj := Proj.Next; - end loop; - end Delete_Mapping_Files; - ------------------------------ -- Delete_Temp_Config_Files -- ------------------------------ @@ -3950,22 +3912,15 @@ package body Make is Proj := Project_Tree.Projects; while Proj /= null loop if Proj.Project.Config_File_Temp then - if Verbose_Mode then - Write_Str ("Deleting temp configuration file """); - Write_Str (Get_Name_String (Proj.Project.Config_File_Name)); - Write_Line (""""); - end if; - - Delete_File - (Name => Get_Name_String (Proj.Project.Config_File_Name), - Success => Success); + Delete_Temporary_File + (Project_Tree, Proj.Project.Config_File_Name); -- Make sure that we don't have a config file for this project, -- in case there are several mains. In this case, we will -- recreate another config file: we cannot reuse the one that -- we just deleted! - Proj.Project.Config_Checked := False; + Proj.Project.Config_Checked := False; Proj.Project.Config_File_Name := No_Path; Proj.Project.Config_File_Temp := False; end if; @@ -4016,8 +3971,8 @@ package body Make is then Temporary_Config_File := False; - -- Do not display the -F=mapping_file switch for - -- gnatbind, if -dn is not specified. + -- Do not display the -F=mapping_file switch for gnatbind + -- if -dn is not specified. elsif Debug.Debug_Flag_N or else Args (J)'Length < 4 @@ -4177,8 +4132,7 @@ package body Make is Total_Compilation_Failures : Natural := 0; Is_Main_Unit : Boolean; - -- Set to True by Compile_Sources if the Main_Source_File can be a - -- main unit. + -- Set True by Compile_Sources if Main_Source_File can be a main unit Main_ALI_File : File_Name_Type; -- The ali file corresponding to Main_Source_File @@ -4187,8 +4141,8 @@ package body Make is -- The file name of an executable Non_Std_Executable : Boolean := False; - -- Non_Std_Executable is set to True when there is a possibility - -- that the linker will not choose the correct executable file name. + -- Non_Std_Executable is set to True when there is a possibility that + -- the linker will not choose the correct executable file name. Current_Work_Dir : constant String_Access := new String'(Get_Current_Dir); @@ -4205,6 +4159,8 @@ package body Make is Mapping_Path : Path_Name_Type := No_Path; -- The path name of the mapping file + Project_Node_Tree : Project_Node_Tree_Ref; + Discard : Boolean; pragma Warnings (Off, Discard); @@ -4237,12 +4193,14 @@ package body Make is loop declare Main : constant String := Mains.Next_Main; - -- The name specified on the command line may include - -- directory information. + -- The name specified on the command line may include directory + -- information. File_Name : constant String := Base_Name (Main); -- The simple file name of the current main + Lang : Language_Ptr; + begin exit when Main = ""; @@ -4251,31 +4209,30 @@ package body Make is Proj := Prj.Env.Project_Of (File_Name, Main_Project, Project_Tree); - -- Fail if the current main is not a source of a - -- project. + -- Fail if the current main is not a source of a project if Proj = No_Project then Make_Failed ("""" & Main & """ is not a source of any project"); else - -- If there is directory information, check that - -- the source exists and, if it does, that the path - -- is the actual path of a source of a project. + -- If there is directory information, check that the source + -- exists and, if it does, that the path is the actual path + -- of a source of a project. if Main /= File_Name then + Lang := Get_Language_From_Name (Main_Project, "ada"); + Real_Path := Locate_Regular_File - (Main & - Body_Suffix_Of - (Project_Tree, "ada", Main_Project.Naming), + (Main & Get_Name_String + (Lang.Config.Naming_Data.Body_Suffix), ""); if Real_Path = null then Real_Path := Locate_Regular_File - (Main & - Spec_Suffix_Of - (Project_Tree, "ada", Main_Project.Naming), + (Main & Get_Name_String + (Lang.Config.Naming_Data.Spec_Suffix), ""); end if; @@ -4335,8 +4292,8 @@ package body Make is elsif Proj /= Real_Main_Project then - -- Fail, as the current main is not a source - -- of the same project as the first main. + -- Fail, as the current main is not a source of the + -- same project as the first main. Make_Failed ("""" & Main & @@ -4346,9 +4303,9 @@ package body Make is end if; end if; - -- If -u and -U are not used, we may have mains that - -- are sources of a project that is not the one - -- specified with switch -P. + -- If -u and -U are not used, we may have mains that are + -- sources of a project that is not the one specified with + -- switch -P. if not Unique_Compile then Main_Project := Real_Main_Project; @@ -4378,159 +4335,155 @@ package body Make is Bytes : Integer; OK : Boolean := True; + Unit : Unit_Index; Status : Boolean; -- For call to Close begin Tempdir.Create_Temp_File (Mapping_FD, Mapping_Path); - Record_Temp_File (Mapping_Path); + Record_Temp_File (Project_Tree, Mapping_Path); if Mapping_FD /= Invalid_FD then -- Traverse all units - for J in Unit_Table.First .. - Unit_Table.Last (Project_Tree.Units) - loop - declare - Unit : constant Unit_Data := Project_Tree.Units.Table (J); - begin - if Unit.Name /= No_Name then - - -- If there is a body, put it in the mapping - - if Unit.File_Names (Body_Part).Name /= No_File - and then Unit.File_Names (Body_Part).Project /= - No_Project - then - Get_Name_String (Unit.Name); - Add_Str_To_Name_Buffer ("%b"); - ALI_Unit := Name_Find; - ALI_Name := - Lib_File_Name - (Unit.File_Names (Body_Part).Display_Name); - ALI_Project := Unit.File_Names (Body_Part).Project; - - -- Otherwise, if there is a spec, put it in the - -- mapping. - - elsif Unit.File_Names (Specification).Name /= No_File - and then Unit.File_Names (Specification).Project /= - No_Project - then - Get_Name_String (Unit.Name); - Add_Str_To_Name_Buffer ("%s"); - ALI_Unit := Name_Find; - ALI_Name := - Lib_File_Name - (Unit.File_Names (Specification).Display_Name); - ALI_Project := Unit.File_Names (Specification).Project; - - else - ALI_Name := No_File; - end if; - - -- If we have something to put in the mapping then do it - -- now. However, if the project is extended, we don't put - -- anything in the mapping file, because we do not know - -- where the ALI file is: it might be in the extended - -- project obj dir as well as in the extending project - -- obj dir. + Unit := Units_Htable.Get_First (Project_Tree.Units_HT); - if ALI_Name /= No_File - and then ALI_Project.Extended_By = No_Project - and then ALI_Project.Extends = No_Project - then - -- First check if the ALI file exists. If it does not, - -- do not put the unit in the mapping file. - - declare - ALI : constant String := Get_Name_String (ALI_Name); - - begin - -- For library projects, use the library directory, - -- for other projects, use the object directory. - - if ALI_Project.Library then - Get_Name_String (ALI_Project.Library_Dir.Name); - else - Get_Name_String - (ALI_Project.Object_Directory.Name); - end if; - - if Name_Buffer (Name_Len) /= - Directory_Separator - then - Add_Char_To_Name_Buffer (Directory_Separator); - end if; + while Unit /= No_Unit_Index loop + if Unit.Name /= No_Name then - Add_Str_To_Name_Buffer (ALI); - Add_Char_To_Name_Buffer (ASCII.LF); + -- If there is a body, put it in the mapping - declare - ALI_Path_Name : constant String := - Name_Buffer (1 .. Name_Len); - - begin - if Is_Regular_File - (ALI_Path_Name (1 .. ALI_Path_Name'Last - 1)) - then + if Unit.File_Names (Impl) /= No_Source + and then Unit.File_Names (Impl).Project /= + No_Project + then + Get_Name_String (Unit.Name); + Add_Str_To_Name_Buffer ("%b"); + ALI_Unit := Name_Find; + ALI_Name := + Lib_File_Name + (Unit.File_Names (Impl).Display_File); + ALI_Project := Unit.File_Names (Impl).Project; + + -- Otherwise, if there is a spec, put it in the mapping + + elsif Unit.File_Names (Spec) /= No_Source + and then Unit.File_Names (Spec).Project /= No_Project + then + Get_Name_String (Unit.Name); + Add_Str_To_Name_Buffer ("%s"); + ALI_Unit := Name_Find; + ALI_Name := + Lib_File_Name + (Unit.File_Names (Spec).Display_File); + ALI_Project := Unit.File_Names (Spec).Project; - -- First line is the unit name + else + ALI_Name := No_File; + end if; - Get_Name_String (ALI_Unit); - Add_Char_To_Name_Buffer (ASCII.LF); - Bytes := - Write - (Mapping_FD, - Name_Buffer (1)'Address, - Name_Len); - OK := Bytes = Name_Len; + -- If we have something to put in the mapping then do it + -- now. However, if the project is extended, we don't put + -- anything in the mapping file, because we don't know where + -- the ALI file is: it might be in the extended project + -- object directory as well as in the extending project + -- object directory. - exit when not OK; + if ALI_Name /= No_File + and then ALI_Project.Extended_By = No_Project + and then ALI_Project.Extends = No_Project + then + -- First check if the ALI file exists. If it does not, + -- do not put the unit in the mapping file. - -- Second line it the ALI file name + declare + ALI : constant String := Get_Name_String (ALI_Name); - Get_Name_String (ALI_Name); - Add_Char_To_Name_Buffer (ASCII.LF); - Bytes := - Write - (Mapping_FD, - Name_Buffer (1)'Address, - Name_Len); - OK := Bytes = Name_Len; + begin + -- For library projects, use the library directory, + -- for other projects, use the object directory. - exit when not OK; + if ALI_Project.Library then + Get_Name_String (ALI_Project.Library_Dir.Name); + else + Get_Name_String + (ALI_Project.Object_Directory.Name); + end if; - -- Third line it the ALI path name + if not + Is_Directory_Separator (Name_Buffer (Name_Len)) + then + Add_Char_To_Name_Buffer (Directory_Separator); + end if; - Bytes := - Write - (Mapping_FD, - ALI_Path_Name (1)'Address, - ALI_Path_Name'Length); - OK := Bytes = ALI_Path_Name'Length; + Add_Str_To_Name_Buffer (ALI); + Add_Char_To_Name_Buffer (ASCII.LF); - -- If OK is False, it means we were unable - -- to write a line. No point in continuing - -- with the other units. + declare + ALI_Path_Name : constant String := + Name_Buffer (1 .. Name_Len); - exit when not OK; - end if; - end; + begin + if Is_Regular_File + (ALI_Path_Name (1 .. ALI_Path_Name'Last - 1)) + then + -- First line is the unit name + + Get_Name_String (ALI_Unit); + Add_Char_To_Name_Buffer (ASCII.LF); + Bytes := + Write + (Mapping_FD, + Name_Buffer (1)'Address, + Name_Len); + OK := Bytes = Name_Len; + + exit when not OK; + + -- Second line it the ALI file name + + Get_Name_String (ALI_Name); + Add_Char_To_Name_Buffer (ASCII.LF); + Bytes := + Write + (Mapping_FD, + Name_Buffer (1)'Address, + Name_Len); + OK := (Bytes = Name_Len); + + exit when not OK; + + -- Third line it the ALI path name + + Bytes := + Write + (Mapping_FD, + ALI_Path_Name (1)'Address, + ALI_Path_Name'Length); + OK := (Bytes = ALI_Path_Name'Length); + + -- If OK is False, it means we were unable to + -- write a line. No point in continuing with the + -- other units. + + exit when not OK; + end if; end; - end if; + end; end if; - end; + end if; + + Unit := Units_Htable.Get_Next (Project_Tree.Units_HT); end loop; Close (Mapping_FD, Status); OK := OK and Status; - -- If the creation of the mapping file was successful, - -- we add the switch to the arguments of gnatbind. + -- If the creation of the mapping file was successful, we add the + -- switch to the arguments of gnatbind. if OK then Last_Arg := Last_Arg + 1; @@ -4542,7 +4495,7 @@ package body Make is -- Start of processing for Gnatmake - -- This body is very long, should be broken down ??? + -- This body is very long, should be broken down??? begin Install_Int_Handler (Sigint_Intercepted'Access); @@ -4553,7 +4506,7 @@ package body Make is Obsoleted.Reset; - Make.Initialize; + Make.Initialize (Project_Node_Tree); Bind_Shared := No_Shared_Switch'Access; Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access; @@ -4595,10 +4548,10 @@ package body Make is end if; -- Specify -n for gnatbind and add the ALI files of all the - -- sources, except the one which is a fake main subprogram: - -- this is the one for the binder generated file and it will be - -- transmitted to gnatlink. These sources are those that are - -- in the queue. + -- sources, except the one which is a fake main subprogram: this + -- is the one for the binder generated file and it will be + -- transmitted to gnatlink. These sources are those that are in + -- the queue. Add_Switch ("-n", Binder, And_Save => True); @@ -4615,8 +4568,8 @@ package body Make is elsif Main_Project /= No_Project then - -- If the main project file is a library project file, main(s) - -- cannot be specified on the command line. + -- If the main project file is a library project file, main(s) cannot + -- be specified on the command line. if Osint.Number_Of_Files /= 0 then if Main_Project.Library @@ -4634,10 +4587,10 @@ package body Make is Check_Mains; end if; - -- If no mains have been specified on the command line, - -- and we are using a project file, we either find the main(s) - -- in the attribute Main of the main project, or we put all - -- the sources of the project file as mains. + -- If no mains have been specified on the command line, and we are + -- using a project file, we either find the main(s) in attribute Main + -- of the main project, or we put all the sources of the project file + -- as mains. else if Main_Index /= 0 then @@ -4649,16 +4602,16 @@ package body Make is Value : String_List_Id := Main_Project.Mains; begin - -- The attribute Main is an empty list or not specified, - -- or else gnatmake was invoked with the switch "-u". + -- The attribute Main is an empty list or not specified, or + -- else gnatmake was invoked with the switch "-u". if Value = Prj.Nil_String or else Unique_Compile then if (not Make_Steps) or else Compile_Only or else not Main_Project.Library then - -- First make sure that the binder and the linker - -- will not be invoked. + -- First make sure that the binder and the linker will + -- not be invoked. Do_Bind_Step := False; Do_Link_Step := False; @@ -4685,19 +4638,18 @@ package body Make is end if; else - -- The attribute Main is not an empty list. - -- Put all the main subprograms in the list as if there - -- were specified on the command line. However, if attribute - -- Languages includes a language other than Ada, only - -- include the Ada mains; if there is no Ada main, compile - -- all the sources of the project. + -- The attribute Main is not an empty list. Put all the main + -- subprograms in the list as if they were specified on the + -- command line. However, if attribute Languages includes a + -- language other than Ada, only include the Ada mains; if + -- there is no Ada main, compile all sources of the project. declare Languages : constant Variable_Value := Prj.Util.Value_Of - (Name_Languages, - Main_Project.Decl.Attributes, - Project_Tree); + (Name_Languages, + Main_Project.Decl.Attributes, + Project_Tree); Current : String_List_Id; Element : String_Element; @@ -4711,7 +4663,6 @@ package body Make is if not Languages.Default then Current := Languages.Values; - Look_For_Foreign : while Current /= Nil_String loop Element := Project_Tree.String_Elements. @@ -4828,6 +4779,11 @@ package body Make is Exit_Program (E_Success); else + -- Call Get_Target_Parameters to ensure that VM_Target and + -- AAMP_On_Target get set before calling Usage. + + Targparm.Get_Target_Parameters; + -- Output usage information if no files to compile Usage; @@ -4946,8 +4902,8 @@ package body Make is & """ is not a unit of project " & Project_File_Name.all & "."); else - -- Remove any directory information from the main - -- source file name. + -- Remove any directory information from the main source file + -- file name. declare Pos : Natural := Main_Unit_File_Name'Last; @@ -5027,7 +4983,8 @@ package body Make is end if; Add_Switches - (File_Name => Main_Unit_File_Name, + (Project_Node_Tree => Project_Node_Tree, + File_Name => Main_Unit_File_Name, Index => Main_Index, The_Package => Builder_Package, Program => None, @@ -5082,7 +5039,8 @@ package body Make is end if; Add_Switches - (File_Name => " ", + (Project_Node_Tree => Project_Node_Tree, + File_Name => " ", Index => 0, The_Package => Builder_Package, Program => None, @@ -5098,7 +5056,8 @@ package body Make is end if; Add_Switches - (File_Name => " ", + (Project_Node_Tree => Project_Node_Tree, + File_Name => " ", Index => 0, The_Package => Builder_Package, Program => None); @@ -5181,7 +5140,7 @@ package body Make is -- Add binder switches from the project file for the first main - if Do_Bind_Step and Binder_Package /= No_Package then + if Do_Bind_Step and then Binder_Package /= No_Package then if Verbose_Mode then Write_Str ("Adding binder switches for """); Write_Str (Main_Unit_File_Name); @@ -5189,15 +5148,16 @@ package body Make is end if; Add_Switches - (File_Name => Main_Unit_File_Name, - Index => Main_Index, - The_Package => Binder_Package, - Program => Binder); + (Project_Node_Tree => Project_Node_Tree, + File_Name => Main_Unit_File_Name, + Index => Main_Index, + The_Package => Binder_Package, + Program => Binder); end if; -- Add linker switches from the project file for the first main - if Do_Link_Step and Linker_Package /= No_Package then + if Do_Link_Step and then Linker_Package /= No_Package then if Verbose_Mode then Write_Str ("Adding linker switches for"""); Write_Str (Main_Unit_File_Name); @@ -5205,17 +5165,18 @@ package body Make is end if; Add_Switches - (File_Name => Main_Unit_File_Name, - Index => Main_Index, - The_Package => Linker_Package, - Program => Linker); + (Project_Node_Tree => Project_Node_Tree, + File_Name => Main_Unit_File_Name, + Index => Main_Index, + The_Package => Linker_Package, + Program => Linker); end if; end; end if; -- Get the target parameters, which are only needed for a couple of - -- cases in gnatmake. Protect against an exception, such as the case - -- of system.ads missing from the library, and fail gracefully. + -- cases in gnatmake. Protect against an exception, such as the case of + -- system.ads missing from the library, and fail gracefully. begin Targparm.Get_Target_Parameters; @@ -5308,8 +5269,8 @@ package body Make is end; end if; - -- If a relative path output file has been specified, we add - -- the exec directory. + -- If a relative path output file has been specified, we add the + -- exec directory. for J in reverse 1 .. Saved_Linker_Switches.Last - 1 loop if Saved_Linker_Switches.Table (J).all = Output_Flag.all then @@ -5321,7 +5282,9 @@ package body Make is if not Is_Absolute_Path (Exec_File_Name) then Get_Name_String (Main_Project.Exec_Directory.Name); - if Name_Buffer (Name_Len) /= Directory_Separator then + if not + Is_Directory_Separator (Name_Buffer (Name_Len)) + then Add_Char_To_Name_Buffer (Directory_Separator); end if; @@ -5428,9 +5391,9 @@ package body Make is The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) := No_gnat_adc; end if; - -- If there was a --GCC, --GNATBIND or --GNATLINK switch on - -- the command line, then we have to use it, even if there was - -- another switch in the project file. + -- If there was a --GCC, --GNATBIND or --GNATLINK switch on the command + -- line, then we have to use it, even if there was another switch in + -- the project file. if Saved_Gcc /= null then Gcc := Saved_Gcc; @@ -5649,7 +5612,7 @@ package body Make is and then (Do_Bind_Step or Unique_Compile_All_Projects or not Compile_Only) - and then (Do_Link_Step or N_File = Osint.Number_Of_Files) + and then (Do_Link_Step or else N_File = Osint.Number_Of_Files) then Library_Projs.Init; @@ -6060,9 +6023,10 @@ package body Make is if Main_Project /= No_Project then -- Put all the source directories in ADA_INCLUDE_PATH, - -- and all the object directories in ADA_OBJECTS_PATH. + -- and all the object directories in ADA_OBJECTS_PATH, + -- except those of library projects. - Prj.Env.Set_Ada_Paths (Main_Project, Project_Tree, True); + Prj.Env.Set_Ada_Paths (Main_Project, Project_Tree, False); -- If switch -C was specified, create a binder mapping file @@ -6079,13 +6043,10 @@ package body Make is exception when others => - -- If -dn was not specified, delete the temporary mapping - -- file, if one was created. + -- Delete the temporary mapping file, if one was created. - if not Debug.Debug_Flag_N - and then Mapping_Path /= No_Path - then - Delete_File (Get_Name_String (Mapping_Path), Discard); + if Mapping_Path /= No_Path then + Delete_Temporary_File (Project_Tree, Mapping_Path); end if; -- And reraise the exception @@ -6096,8 +6057,8 @@ package body Make is -- If -dn was not specified, delete the temporary mapping file, -- if one was created. - if not Debug.Debug_Flag_N and then Mapping_Path /= No_Path then - Delete_File (Get_Name_String (Mapping_Path), Discard); + if Mapping_Path /= No_Path then + Delete_Temporary_File (Project_Tree, Mapping_Path); end if; end Bind_Step; end if; @@ -6199,7 +6160,7 @@ package body Make is -- We do that only if Run_Path_Option is True -- (not disabled by -R switch). - if Run_Path_Option and Path_Option /= null then + if Run_Path_Option and then Path_Option /= null then declare Option : String_Access; Length : Natural := Path_Option'Length; @@ -6368,7 +6329,9 @@ package body Make is Successful_Links.Table (Successful_Links.Last) := Main_ALI_File; - elsif Osint.Number_Of_Files = 1 or not Keep_Going then + elsif Osint.Number_Of_Files = 1 + or else not Keep_Going + then Make_Failed ("*** link failed."); else @@ -6482,7 +6445,7 @@ package body Make is -- Add binder switches from the project file for this main, -- if any. - if Do_Bind_Step and Binder_Package /= No_Package then + if Do_Bind_Step and then Binder_Package /= No_Package then if Verbose_Mode then Write_Str ("Adding binder switches for """); Write_Str (Main_Unit_File_Name); @@ -6490,16 +6453,17 @@ package body Make is end if; Add_Switches - (File_Name => Main_Unit_File_Name, - Index => Main_Index, - The_Package => Binder_Package, - Program => Binder); + (Project_Node_Tree => Project_Node_Tree, + File_Name => Main_Unit_File_Name, + Index => Main_Index, + The_Package => Binder_Package, + Program => Binder); end if; -- Add linker switches from the project file for this main, -- if any. - if Do_Link_Step and Linker_Package /= No_Package then + if Do_Link_Step and then Linker_Package /= No_Package then if Verbose_Mode then Write_Str ("Adding linker switches for"""); Write_Str (Main_Unit_File_Name); @@ -6507,10 +6471,11 @@ package body Make is end if; Add_Switches - (File_Name => Main_Unit_File_Name, - Index => Main_Index, - The_Package => Linker_Package, - Program => Linker); + (Project_Node_Tree => Project_Node_Tree, + File_Name => Main_Unit_File_Name, + Index => Main_Index, + The_Package => Linker_Package, + Program => Linker); end if; -- As we are using a project file, for relative paths we add @@ -6654,7 +6619,7 @@ package body Make is Prj.Env.Create_Mapping_File (Project, In_Tree => Project_Tree, - Language => No_Name, + Language => Name_Ada, Name => Data.Mapping_File_Names (Data.Last_Mapping_File_Names)); @@ -6670,7 +6635,8 @@ package body Make is else Record_Temp_File - (Data.Mapping_File_Names (Data.Last_Mapping_File_Names)); + (Project_Tree, + Data.Mapping_File_Names (Data.Last_Mapping_File_Names)); end if; Close (FD, Status); @@ -6700,7 +6666,7 @@ package body Make is -- Initialize -- ---------------- - procedure Initialize is + procedure Initialize (Project_Node_Tree : out Project_Node_Tree_Ref) is procedure Check_Version_And_Help is new Check_Version_And_Help_G (Makeusg); @@ -6708,7 +6674,12 @@ package body Make is -- Start of processing for Initialize begin - Prj.Set_Mode (Ada_Only); + -- Prepare the project's tree, since this is used to hold external + -- references, project path and other attributes that can be impacted by + -- the command line switches + + Project_Node_Tree := new Project_Node_Tree_Data; + Prj.Tree.Initialize (Project_Node_Tree); -- Override default initialization of Check_Object_Consistency since -- this is normally False for GNATBIND, but is True for GNATMAKE since @@ -6735,11 +6706,12 @@ package body Make is Dependencies.Init; RTS_Specified := null; + N_M_Switch := 0; Mains.Delete; - -- Add the directory where gnatmake is invoked in front of the - -- path, if gnatmake is invoked from a bin directory or with directory + -- Add the directory where gnatmake is invoked in front of the path, + -- if gnatmake is invoked from a bin directory or with directory -- information. Only do this if the platform is not VMS, where the -- notion of path does not really exist. @@ -6791,9 +6763,14 @@ package body Make is -- do not include --version or --help. Scan_Args : for Next_Arg in 1 .. Argument_Count loop - Scan_Make_Arg (Argument (Next_Arg), And_Save => True); + Scan_Make_Arg + (Project_Node_Tree, Argument (Next_Arg), And_Save => True); end loop Scan_Args; + if N_M_Switch > 0 and RTS_Specified = null then + Process_Multilib (Project_Node_Tree); + end if; + if Commands_To_Stdout then Set_Standard_Output; end if; @@ -6876,7 +6853,8 @@ package body Make is In_Tree => Project_Tree, Project_File_Name => Project_File_Name.all, Packages_To_Check => Packages_To_Check_By_Gnatmake, - Is_Config_File => False); + Flags => Gnatmake_Flags, + In_Node_Tree => Project_Node_Tree); -- The parsing of project files may have changed the current output @@ -6901,26 +6879,17 @@ package body Make is Write_Eol; end if; - -- We add the source directories and the object directories - -- to the search paths. + -- We add the source directories and the object directories to the + -- search paths. + -- ??? Why do we need these search directories, we already know the + -- locations from parsing the project, except for the runtime which + -- has its own directories anyway Add_Source_Directories (Main_Project, Project_Tree); Add_Object_Directories (Main_Project); Recursive_Compute_Depth (Main_Project); - - -- For each project compute the list of the projects it imports - -- directly or indirectly. - - declare - Proj : Project_List; - begin - Proj := Project_Tree.Projects; - while Proj /= null loop - Compute_All_Imported_Projects (Proj.Project); - Proj := Proj.Next; - end loop; - end; + Compute_All_Imported_Projects (Project_Tree); else @@ -6962,7 +6931,7 @@ package body Make is Into_Q : Boolean) is Put_In_Q : Boolean := Into_Q; - Unit : Unit_Data; + Unit : Unit_Index; Sfile : File_Name_Type; Index : Int; @@ -6977,7 +6946,7 @@ package body Make is function Check_Project (P : Project_Id) return Boolean is begin - if All_Projects or P = The_Project then + if All_Projects or else P = The_Project then return True; elsif Extending then @@ -7004,27 +6973,25 @@ package body Make is begin -- For all the sources in the project files, - for Id in Unit_Table.First .. - Unit_Table.Last (Project_Tree.Units) - loop - Unit := Project_Tree.Units.Table (Id); + Unit := Units_Htable.Get_First (Project_Tree.Units_HT); + while Unit /= null loop Sfile := No_File; Index := 0; -- If there is a source for the body, and the body has not been -- locally removed. - if Unit.File_Names (Body_Part).Name /= No_File - and then Unit.File_Names (Body_Part).Path.Name /= Slash + if Unit.File_Names (Impl) /= null + and then not Unit.File_Names (Impl).Locally_Removed then -- And it is a source for the specified project - if Check_Project (Unit.File_Names (Body_Part).Project) then + if Check_Project (Unit.File_Names (Impl).Project) then -- If we don't have a spec, we cannot consider the source -- if it is a subunit. - if Unit.File_Names (Specification).Name = No_File then + if Unit.File_Names (Spec) = null then declare Src_Ind : Source_File_Index; @@ -7042,7 +7009,7 @@ package body Make is begin Src_Ind := Sinput.P.Load_Project_File (Get_Name_String - (Unit.File_Names (Body_Part).Path.Name)); + (Unit.File_Names (Impl).Path.Name)); -- If it is a subunit, discard it @@ -7050,27 +7017,26 @@ package body Make is Sfile := No_File; Index := 0; else - Sfile := Unit.File_Names (Body_Part).Display_Name; - Index := Unit.File_Names (Body_Part).Index; + Sfile := Unit.File_Names (Impl).Display_File; + Index := Unit.File_Names (Impl).Index; end if; end; else - Sfile := Unit.File_Names (Body_Part).Display_Name; - Index := Unit.File_Names (Body_Part).Index; + Sfile := Unit.File_Names (Impl).Display_File; + Index := Unit.File_Names (Impl).Index; end if; end if; - elsif Unit.File_Names (Specification).Name /= No_File - and then Unit.File_Names (Specification).Path.Name /= Slash - and then Check_Project (Unit.File_Names (Specification).Project) + elsif Unit.File_Names (Spec) /= null + and then not Unit.File_Names (Spec).Locally_Removed + and then Check_Project (Unit.File_Names (Spec).Project) then - -- If there is no source for the body, but there is a source - -- for the spec which has not been locally removed, then we take - -- this one. + -- If there is no source for the body, but there is one for the + -- spec which has not been locally removed, then we take this one. - Sfile := Unit.File_Names (Specification).Display_Name; - Index := Unit.File_Names (Specification).Index; + Sfile := Unit.File_Names (Spec).Display_File; + Index := Unit.File_Names (Spec).Index; end if; -- If Put_In_Q is True, we insert into the Q @@ -7120,6 +7086,8 @@ package body Make is Init_Q; end if; end if; + + Unit := Units_Htable.Get_Next (Project_Tree.Units_HT); end loop; end Insert_Project_Sources; @@ -7409,9 +7377,9 @@ package body Make is B : Byte; function Base_Directory return String; - -- If Dir comes from the command line, empty string (relative paths - -- are resolved with respect to the current directory), else return - -- the main project's directory. + -- If Dir comes from the command line, empty string (relative paths are + -- resolved with respect to the current directory), else return the main + -- project's directory. -------------------- -- Base_Directory -- @@ -7453,6 +7421,118 @@ package body Make is Set_Name_Table_Byte (N, B or Mark); end Mark_Directory; + ---------------------- + -- Process_Multilib -- + ---------------------- + + procedure Process_Multilib + (Project_Node_Tree : Project_Node_Tree_Ref) + is + Output_FD : File_Descriptor; + Output_Name : String_Access; + Arg_Index : Natural := 0; + Success : Boolean := False; + Return_Code : Integer := 0; + Multilib_Gcc_Path : String_Access; + Multilib_Gcc : String_Access; + N_Read : Integer := 0; + Line : String (1 .. 1000); + Args : Argument_List (1 .. N_M_Switch + 1); + + begin + pragma Assert (N_M_Switch > 0 and RTS_Specified = null); + + -- In case we detected a multilib switch and the user has not + -- manually specified a specific RTS we emulate the following command: + -- gnatmake $FLAGS --RTS=$(gcc -print-multi-directory $FLAGS) + + -- First select the flags which might have an impact on multilib + -- processing. Note that this is an heuristic selection and it + -- will need to be maintained over time. The condition has to + -- be kept synchronized with N_M_Switch counting in Scan_Make_Arg. + + for Next_Arg in 1 .. Argument_Count loop + declare + Argv : constant String := Argument (Next_Arg); + begin + if Argv'Length > 2 + and then Argv (1) = '-' + and then Argv (2) = 'm' + and then Argv /= "-margs" + + -- Ignore -mieee to avoid spawning an extra gcc in this case + + and then Argv /= "-mieee" + then + Arg_Index := Arg_Index + 1; + Args (Arg_Index) := new String'(Argv); + end if; + end; + end loop; + + pragma Assert (Arg_Index = N_M_Switch); + + Args (Args'Last) := new String'("-print-multi-directory"); + + -- Call the GCC driver with the collected flags and save its + -- output. Alternate design would be to link in gnatmake the + -- relevant part of the GCC driver. + + if Saved_Gcc /= null then + Multilib_Gcc := Saved_Gcc; + else + Multilib_Gcc := Gcc; + end if; + + Multilib_Gcc_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Multilib_Gcc.all); + + Create_Temp_Output_File (Output_FD, Output_Name); + + if Output_FD = Invalid_FD then + return; + end if; + + GNAT.OS_Lib.Spawn + (Multilib_Gcc_Path.all, Args, Output_FD, Return_Code, False); + Close (Output_FD); + + if Return_Code /= 0 then + return; + end if; + + -- Parse the GCC driver output which is a single line, removing CR/LF + + Output_FD := Open_Read (Output_Name.all, Binary); + + if Output_FD = Invalid_FD then + return; + end if; + + N_Read := Read (Output_FD, Line (1)'Address, Line'Length); + Close (Output_FD); + Delete_File (Output_Name.all, Success); + + for J in reverse 1 .. N_Read loop + if Line (J) = ASCII.CR or else Line (J) = ASCII.LF then + N_Read := N_Read - 1; + else + exit; + end if; + end loop; + + -- In case the standard RTS is selected do nothing + + if N_Read = 0 or else Line (1 .. N_Read) = "." then + return; + end if; + + -- Otherwise add -margs --RTS=output + + Scan_Make_Arg (Project_Node_Tree, "-margs", And_Save => True); + Scan_Make_Arg + (Project_Node_Tree, "--RTS=" & Line (1 .. N_Read), And_Save => True); + end Process_Multilib; + ----------------------------- -- Recursive_Compute_Depth -- ----------------------------- @@ -7462,6 +7542,7 @@ package body Make is Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil; procedure Recurse (Prj : Project_Id; Depth : Natural); + -- Recursive procedure that does the work, keeping track of the depth ------------- -- Recurse -- @@ -7551,7 +7632,11 @@ package body Make is -- Scan_Make_Arg -- ------------------- - procedure Scan_Make_Arg (Argv : String; And_Save : Boolean) is + procedure Scan_Make_Arg + (Project_Node_Tree : Project_Node_Tree_Ref; + Argv : String; + And_Save : Boolean) + is Success : Boolean; begin @@ -7595,7 +7680,7 @@ package body Make is -- If the previous switch has set the Object_Directory_Present flag -- (that is we have seen a -D), then the next argument is the path name - -- of the object directory.. + -- of the object directory. elsif Object_Directory_Present and then not Object_Directory_Seen @@ -7609,22 +7694,27 @@ package body Make is Make_Failed ("cannot find object directory """ & Argv & """"); else - Add_Lib_Search_Dir (Argv); + -- Record the object directory. Make sure it ends with a directory + -- separator. + + declare + Norm : constant String := Normalize_Pathname (Argv); - -- Specify the object directory to the binder + begin + if Norm (Norm'Last) = Directory_Separator then + Object_Directory_Path := new String'(Norm); + else + Object_Directory_Path := + new String'(Norm & Directory_Separator); + end if; - Add_Switch ("-aO" & Argv, Binder, And_Save => And_Save); + Add_Lib_Search_Dir (Norm); - -- Record the object directory. Make sure it ends with a directory - -- separator. + -- Specify the object directory to the binder + + Add_Switch ("-aO" & Norm, Binder, And_Save => And_Save); + end; - if Argv (Argv'Last) = Directory_Separator then - Object_Directory_Path := - new String'(Argv); - else - Object_Directory_Path := - new String'(Argv & Directory_Separator); - end if; end if; -- Then check if we are dealing with -cargs/-bargs/-largs/-margs @@ -7647,9 +7737,8 @@ package body Make is raise Program_Error; end case; - -- A special test is needed for the -o switch within a -largs - -- since that is another way to specify the name of the final - -- executable. + -- A special test is needed for the -o switch within a -largs since that + -- is another way to specify the name of the final executable. elsif Program_Args = Linker and then Argv = "-o" @@ -7657,8 +7746,8 @@ package body Make is Make_Failed ("switch -o not allowed within a -largs. " & "Use -o directly."); - -- Check to see if we are reading switches after a -cargs, - -- -bargs or -largs switch. If yes save it. + -- Check to see if we are reading switches after a -cargs, -bargs or + -- -largs switch. If so, save it. elsif Program_Args /= None then @@ -7701,9 +7790,7 @@ package body Make is for J in 2 .. Program_Args.all'Last loop Add_Switch - (Program_Args.all (J).all, - Compiler, - And_Save => And_Save); + (Program_Args.all (J).all, Compiler, And_Save => And_Save); end loop; end; @@ -7751,7 +7838,7 @@ package body Make is Argv (1 .. 5) = "--RTS" then Add_Switch (Argv, Compiler, And_Save => And_Save); - Add_Switch (Argv, Binder, And_Save => And_Save); + Add_Switch (Argv, Binder, And_Save => And_Save); if Argv'Length <= 6 or else Argv (6) /= '=' then Make_Failed ("missing path for --RTS"); @@ -7793,8 +7880,8 @@ package body Make is RTS_Src_Path_Name := Src_Path_Name; RTS_Lib_Path_Name := Lib_Path_Name; - elsif Src_Path_Name = null - and Lib_Path_Name = null + elsif Src_Path_Name = null + and then Lib_Path_Name = null then Make_Failed ("RTS path not valid: missing " & "adainclude and adalib directories"); @@ -7814,10 +7901,10 @@ package body Make is Argv (1 .. 8) = "--param=" then Add_Switch (Argv, Compiler, And_Save => And_Save); - Add_Switch (Argv, Linker, And_Save => And_Save); + Add_Switch (Argv, Linker, And_Save => And_Save); else - Scan_Make_Switches (Argv, Success); + Scan_Make_Switches (Project_Node_Tree, Argv, Success); end if; -- If we have seen a regular switch process it @@ -7852,18 +7939,17 @@ package body Make is -- -Idir elsif Argv (2) = 'I' then - Add_Source_Search_Dir (Argv (3 .. Argv'Last), And_Save); + Add_Source_Search_Dir (Argv (3 .. Argv'Last), And_Save); Add_Library_Search_Dir (Argv (3 .. Argv'Last), And_Save); Add_Switch (Argv, Compiler, And_Save => And_Save); - Add_Switch (Argv, Binder, And_Save => And_Save); + Add_Switch (Argv, Binder, And_Save => And_Save); -- -aIdir (to gcc this is like a -I switch) elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then Add_Source_Search_Dir (Argv (4 .. Argv'Last), And_Save); - Add_Switch ("-I" & Argv (4 .. Argv'Last), - Compiler, - And_Save => And_Save); + Add_Switch + ("-I" & Argv (4 .. Argv'Last), Compiler, And_Save => And_Save); Add_Switch (Argv, Binder, And_Save => And_Save); -- -aOdir @@ -7877,9 +7963,8 @@ package body Make is elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then Mark_Directory (Argv (4 .. Argv'Last), Ada_Lib_Dir, And_Save); Add_Library_Search_Dir (Argv (4 .. Argv'Last), And_Save); - Add_Switch ("-aO" & Argv (4 .. Argv'Last), - Binder, - And_Save => And_Save); + Add_Switch + ("-aO" & Argv (4 .. Argv'Last), Binder, And_Save => And_Save); -- -aamp_target=... @@ -7897,14 +7982,12 @@ package body Make is elsif Argv (2) = 'A' then Mark_Directory (Argv (3 .. Argv'Last), Ada_Lib_Dir, And_Save); - Add_Source_Search_Dir (Argv (3 .. Argv'Last), And_Save); + Add_Source_Search_Dir (Argv (3 .. Argv'Last), And_Save); Add_Library_Search_Dir (Argv (3 .. Argv'Last), And_Save); - Add_Switch ("-I" & Argv (3 .. Argv'Last), - Compiler, - And_Save => And_Save); - Add_Switch ("-aO" & Argv (3 .. Argv'Last), - Binder, - And_Save => And_Save); + Add_Switch + ("-I" & Argv (3 .. Argv'Last), Compiler, And_Save => And_Save); + Add_Switch + ("-aO" & Argv (3 .. Argv'Last), Binder, And_Save => And_Save); -- -Ldir @@ -7912,11 +7995,11 @@ package body Make is Add_Switch (Argv, Linker, And_Save => And_Save); -- For -gxxxxx, -pg, -mxxx, -fxxx: give the switch to both the - -- compiler and the linker (except for -gnatxxx which is only for - -- the compiler). Some of the -mxxx (for example -m64) and -fxxx - -- (for example -ftest-coverage for gcov) need to be used when - -- compiling the binder generated files, and using all these gcc - -- switches for the binder generated files should not be a problem. + -- compiler and the linker (except for -gnatxxx which is only for the + -- compiler). Some of the -mxxx (for example -m64) and -fxxx (for + -- example -ftest-coverage for gcov) need to be used when compiling + -- the binder generated files, and using all these gcc switches for + -- the binder generated files should not be a problem. elsif (Argv (2) = 'g' and then (Argv'Last < 5 @@ -7926,7 +8009,16 @@ package body Make is or else (Argv (2) = 'f' and then Argv'Last > 2) then Add_Switch (Argv, Compiler, And_Save => And_Save); - Add_Switch (Argv, Linker, And_Save => And_Save); + Add_Switch (Argv, Linker, And_Save => And_Save); + + -- The following condition has to be kept synchronized with + -- the Process_Multilib one. + + if Argv (2) = 'm' + and then Argv /= "-mieee" + then + N_M_Switch := N_M_Switch + 1; + end if; -- -C= @@ -7943,34 +8035,32 @@ package body Make is elsif Argv'Last = 2 and then Argv (2) = 'D' then if Project_File_Name /= null then - Make_Failed ("-D cannot be used in conjunction with a " & - "project file"); + Make_Failed + ("-D cannot be used in conjunction with a project file"); else - Scan_Make_Switches (Argv, Success); + Scan_Make_Switches (Project_Node_Tree, Argv, Success); end if; -- -d - elsif Argv (2) = 'd' - and then Argv'Last = 2 - then + elsif Argv (2) = 'd' and then Argv'Last = 2 then Display_Compilation_Progress := True; -- -i elsif Argv'Last = 2 and then Argv (2) = 'i' then if Project_File_Name /= null then - Make_Failed ("-i cannot be used in conjunction with a " & - "project file"); + Make_Failed + ("-i cannot be used in conjunction with a project file"); else - Scan_Make_Switches (Argv, Success); + Scan_Make_Switches (Project_Node_Tree, Argv, Success); end if; -- -j (need to save the result) elsif Argv (2) = 'j' then - Scan_Make_Switches (Argv, Success); + Scan_Make_Switches (Project_Node_Tree, Argv, Success); if And_Save then Saved_Maximum_Processes := Maximum_Processes; @@ -7978,20 +8068,16 @@ package body Make is -- -m - elsif Argv (2) = 'm' - and then Argv'Last = 2 - then + elsif Argv (2) = 'm' and then Argv'Last = 2 then Minimal_Recompilation := True; -- -u - elsif Argv (2) = 'u' - and then Argv'Last = 2 - then - Unique_Compile := True; - Compile_Only := True; - Do_Bind_Step := False; - Do_Link_Step := False; + elsif Argv (2) = 'u' and then Argv'Last = 2 then + Unique_Compile := True; + Compile_Only := True; + Do_Bind_Step := False; + Do_Link_Step := False; -- -U @@ -7999,10 +8085,10 @@ package body Make is and then Argv'Last = 2 then Unique_Compile_All_Projects := True; - Unique_Compile := True; - Compile_Only := True; - Do_Bind_Step := False; - Do_Link_Step := False; + Unique_Compile := True; + Compile_Only := True; + Do_Bind_Step := False; + Do_Link_Step := False; -- -Pprj or -P prj (only once, and only on the command line) @@ -8011,16 +8097,16 @@ package body Make is Make_Failed ("cannot have several project files specified"); elsif Object_Directory_Path /= null then - Make_Failed ("-D cannot be used in conjunction with a " & - "project file"); + Make_Failed + ("-D cannot be used in conjunction with a project file"); elsif In_Place_Mode then - Make_Failed ("-i cannot be used in conjunction with a " & - "project file"); + Make_Failed + ("-i cannot be used in conjunction with a project file"); elsif not And_Save then - -- It could be a tool other than gnatmake (i.e, gnatdist) + -- It could be a tool other than gnatmake (e.g. gnatdist) -- or a -P switch inside a project file. Fail @@ -8059,33 +8145,32 @@ package body Make is -- -Xext=val (External assignment) elsif Argv (2) = 'X' - and then Is_External_Assignment (Argv) + and then Is_External_Assignment (Project_Node_Tree, Argv) then - -- Is_External_Assignment has side effects - -- when it returns True; + -- Is_External_Assignment has side effects when it returns True null; - -- If -gnath is present, then generate the usage information - -- right now and do not pass this option on to the compiler calls. + -- If -gnath is present, then generate the usage information right + -- now and do not pass this option on to the compiler calls. elsif Argv = "-gnath" then Usage; - -- If -gnatc is specified, make sure the bind step and the link - -- step are not executed. + -- If -gnatc is specified, make sure the bind and link steps are not + -- executed. elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatc" then - -- If -gnatc is specified, make sure the bind step and the link - -- step are not executed. + -- If -gnatc is specified, make sure the bind and link steps are + -- not executed. Add_Switch (Argv, Compiler, And_Save => And_Save); - Operating_Mode := Check_Semantics; + Operating_Mode := Check_Semantics; Check_Object_Consistency := False; Compile_Only := True; - Do_Bind_Step := False; - Do_Link_Step := False; + Do_Bind_Step := False; + Do_Link_Step := False; elsif Argv (2 .. Argv'Last) = "nostdlib" then @@ -8103,14 +8188,15 @@ package body Make is No_Stdinc := True; Add_Switch (Argv, Compiler, And_Save => And_Save); - Add_Switch (Argv, Binder, And_Save => And_Save); + Add_Switch (Argv, Binder, And_Save => And_Save); -- All other switches are processed by Scan_Make_Switches. If the -- call returns with Gnatmake_Switch_Found = False, then the switch -- is passed to the compiler. else - Scan_Make_Switches (Argv, Gnatmake_Switch_Found); + Scan_Make_Switches + (Project_Node_Tree, Argv, Gnatmake_Switch_Found); if not Gnatmake_Switch_Found then Add_Switch (Argv, Compiler, And_Save => And_Save); @@ -8133,10 +8219,12 @@ package body Make is (Source_File : File_Name_Type; Source_File_Name : String; Source_Index : Int; - Naming : Naming_Data; + Project : Project_Id; In_Package : Package_Id; Allow_ALI : Boolean) return Variable_Value is + Lang : constant Language_Ptr := Get_Language_From_Name (Project, "ada"); + Switches : Variable_Value; Defaults : constant Array_Element_Id := @@ -8167,14 +8255,17 @@ package body Make is -- Check also without the suffix - if Switches = Nil_Variable_Value then + if Switches = Nil_Variable_Value + and then Lang /= null + then declare + Naming : Lang_Naming_Data renames Lang.Config.Naming_Data; Name : String (1 .. Source_File_Name'Length + 3); Last : Positive := Source_File_Name'Length; Spec_Suffix : constant String := - Spec_Suffix_Of (Project_Tree, "ada", Naming); + Get_Name_String (Naming.Spec_Suffix); Body_Suffix : constant String := - Body_Suffix_Of (Project_Tree, "ada", Naming); + Get_Name_String (Naming.Body_Suffix); Truncated : Boolean := False; begin @@ -8286,52 +8377,6 @@ package body Make is end if; end Usage; - ----------------- - -- Verbose_Msg -- - ----------------- - - procedure Verbose_Msg - (N1 : Name_Id; - S1 : String; - N2 : Name_Id := No_Name; - S2 : String := ""; - Prefix : String := " -> "; - Minimum_Verbosity : Verbosity_Level_Type := Opt.Low) - is - begin - if (not Verbose_Mode) or else (Minimum_Verbosity > Verbosity_Level) then - return; - end if; - - Write_Str (Prefix); - Write_Str (""""); - Write_Name (N1); - Write_Str (""" "); - Write_Str (S1); - - if N2 /= No_Name then - Write_Str (" """); - Write_Name (N2); - Write_Str (""" "); - end if; - - Write_Str (S2); - Write_Eol; - end Verbose_Msg; - - procedure Verbose_Msg - (N1 : File_Name_Type; - S1 : String; - N2 : File_Name_Type := No_File; - S2 : String := ""; - Prefix : String := " -> "; - Minimum_Verbosity : Verbosity_Level_Type := Opt.Low) - is - begin - Verbose_Msg - (Name_Id (N1), S1, Name_Id (N2), S2, Prefix, Minimum_Verbosity); - end Verbose_Msg; - begin -- Make sure that in case of failure, the temp files will be deleted