OSDN Git Service

2011-08-04 Emmanuel Briot <briot@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Aug 2011 12:14:06 +0000 (12:14 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 4 Aug 2011 12:14:06 +0000 (12:14 +0000)
* make.adb, makeutl.adb, makeutl.ads (Make): major refactoring.
Create several new subprograms to move code out of Make. This makes the
code more readable, removes code duplication, and is a preparation work
for adding support for aggregate projects.

2011-08-04  Tristan Gingold  <gingold@adacore.com>

* s-po32gl.ads, s-po32gl.adb: New files.
* exp_ch7.ads (Get_Global_Pool_For_Access_Type): New function.
* exp_ch7.adb (Get_Global_Pool_For_Access_Type): New function.
(Build_Finalization_Collection): Use it.
* exp_ch4.adb (Complete_Controlled_Allocation): Ditto.
* rtsfind.ads: System_Pool_32_Global, Re_Global_Pool_32_Object: New
literals.
* gcc-interface/Makefile.in: Use s-po32gl.o on VMS.
* gcc-interface/Make-lang.in: Update dependencies.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177364 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/ada/ChangeLog
gcc/ada/exp_ch4.adb
gcc/ada/exp_ch7.adb
gcc/ada/exp_ch7.ads
gcc/ada/gcc-interface/Make-lang.in
gcc/ada/gcc-interface/Makefile.in
gcc/ada/make.adb
gcc/ada/makeutl.adb
gcc/ada/makeutl.ads
gcc/ada/rtsfind.ads
gcc/ada/s-po32gl.adb [new file with mode: 0644]
gcc/ada/s-po32gl.ads [new file with mode: 0644]

index eea90ca..542f4a6 100644 (file)
@@ -1,5 +1,24 @@
 2011-08-04  Emmanuel Briot  <briot@adacore.com>
 
+       * make.adb, makeutl.adb, makeutl.ads (Make): major refactoring.
+       Create several new subprograms to move code out of Make. This makes the
+       code more readable, removes code duplication, and is a preparation work
+       for adding support for aggregate projects.
+
+2011-08-04  Tristan Gingold  <gingold@adacore.com>
+
+       * s-po32gl.ads, s-po32gl.adb: New files.
+       * exp_ch7.ads (Get_Global_Pool_For_Access_Type): New function.
+       * exp_ch7.adb (Get_Global_Pool_For_Access_Type): New function.
+       (Build_Finalization_Collection): Use it.
+       * exp_ch4.adb (Complete_Controlled_Allocation): Ditto.
+       * rtsfind.ads: System_Pool_32_Global, Re_Global_Pool_32_Object: New
+       literals.
+       * gcc-interface/Makefile.in: Use s-po32gl.o on VMS.
+       * gcc-interface/Make-lang.in: Update dependencies.
+
+2011-08-04  Emmanuel Briot  <briot@adacore.com>
+
        * makeutl.adb (Complete_Mains): add support for specs with no suffix on
        the command line.
 
index a5b3bdc..5377960 100644 (file)
@@ -455,7 +455,8 @@ package body Exp_Ch4 is
              or else Is_Library_Level_Entity (Ptr_Typ))
       then
          declare
-            Pool_Id : constant Entity_Id := RTE (RE_Global_Pool_Object);
+            Pool_Id : constant Entity_Id :=
+              Get_Global_Pool_For_Access_Type (Ptr_Typ);
             Scop    : Node_Id := Cunit_Entity (Current_Sem_Unit);
 
          begin
index 3891b03..5ecf752 100644 (file)
@@ -949,7 +949,7 @@ package body Exp_Ch7 is
 
                begin
                   if No (Associated_Storage_Pool (Base_Typ)) then
-                     Pool_Id := RTE (RE_Global_Pool_Object);
+                     Pool_Id := Get_Global_Pool_For_Access_Type (Base_Typ);
                      Set_Associated_Storage_Pool (Base_Typ, Pool_Id);
                   else
                      Pool_Id := Associated_Storage_Pool (Base_Typ);
@@ -959,7 +959,7 @@ package body Exp_Ch7 is
             --  The default choice is the global pool
 
             else
-               Pool_Id := RTE (RE_Global_Pool_Object);
+               Pool_Id := Get_Global_Pool_For_Access_Type (Typ);
                Set_Associated_Storage_Pool (Typ, Pool_Id);
             end if;
 
@@ -4072,6 +4072,21 @@ package body Exp_Ch7 is
       end loop;
    end Find_Node_To_Be_Wrapped;
 
+   -------------------------------------
+   -- Get_Global_Pool_For_Access_Type --
+   -------------------------------------
+
+   function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id is
+   begin
+      if Opt.True_VMS_Target
+        and then Esize (T) = 32
+      then
+         return RTE (RE_Global_Pool_32_Object);
+      else
+         return RTE (RE_Global_Pool_Object);
+      end if;
+   end Get_Global_Pool_For_Access_Type;
+
    ----------------------------------
    -- Has_New_Controlled_Component --
    ----------------------------------
index 08c3734..7a7f874 100644 (file)
@@ -98,6 +98,11 @@ package Exp_Ch7 is
    --  applies, in which case we know that class-wide objects do not contain
    --  controlled parts.
 
+   function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id;
+   --  Return the pool id for access type T.  This is generally the node
+   --  corresponding to System.Global_Pool.Global_Pool_Object except on
+   --  VMS if the access size is 32.
+
    function Has_New_Controlled_Component (E : Entity_Id) return Boolean;
    --  E is a type entity. Give the same result as Has_Controlled_Component
    --  except for tagged extensions where the result is True only if the
index d7af952..f7273a0 100644 (file)
@@ -1301,17 +1301,16 @@ ada/alfa.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
    ada/aspects.ads ada/atree.ads ada/atree.adb ada/casing.ads \
    ada/debug.ads ada/einfo.ads ada/gnat.ads ada/g-htable.ads \
    ada/g-table.ads ada/g-table.adb ada/hostparm.ads ada/interfac.ads \
-   ada/namet.ads ada/namet.adb ada/nlists.ads ada/nlists.adb \
-   ada/nmake.ads ada/opt.ads ada/output.ads ada/output.adb \
-   ada/put_alfa.ads ada/put_alfa.adb ada/sem_util.ads \
-   ada/sinfo.ads ada/sinfo.adb ada/sinput.ads ada/snames.ads \
-   ada/system.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
-   ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-secsta.ads \
-   ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads ada/s-stoele.ads \
-   ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
-   ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
-   ada/types.ads ada/uintp.ads ada/uintp.adb ada/unchconv.ads \
-   ada/unchdeal.ads ada/urealp.ads ada/widechar.ads 
+   ada/namet.ads ada/namet.adb ada/nlists.ads ada/nlists.adb ada/nmake.ads \
+   ada/opt.ads ada/output.ads ada/output.adb ada/put_alfa.ads \
+   ada/put_alfa.adb ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb \
+   ada/sinput.ads ada/snames.ads ada/system.ads ada/s-exctab.ads \
+   ada/s-htable.ads ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads \
+   ada/s-parame.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
+   ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
+   ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
+   ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads ada/uintp.adb \
+   ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads 
 
 ada/ali-util.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
    ada/a-uncdea.ads ada/ali.ads ada/ali.adb ada/ali-util.ads \
@@ -2753,13 +2752,14 @@ ada/get_alfa.o : ada/ada.ads ada/a-except.ads ada/a-ioexce.ads \
    ada/a-unccon.ads ada/a-uncdea.ads ada/alfa.ads ada/alfa.adb \
    ada/alloc.ads ada/atree.ads ada/debug.ads ada/einfo.ads \
    ada/get_alfa.ads ada/get_alfa.adb ada/gnat.ads ada/g-table.ads \
-   ada/g-table.adb ada/hostparm.ads ada/namet.ads ada/opt.ads \
-   ada/output.ads ada/put_alfa.ads ada/sinfo.ads ada/snames.ads \
-   ada/system.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
-   ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
-   ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
-   ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
-   ada/unchdeal.ads ada/urealp.ads 
+   ada/g-table.adb ada/hostparm.ads ada/namet.ads ada/nlists.ads \
+   ada/nmake.ads ada/opt.ads ada/output.ads ada/put_alfa.ads \
+   ada/sem_util.ads ada/sinfo.ads ada/snames.ads ada/system.ads \
+   ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
+   ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads ada/s-unstyp.ads \
+   ada/s-wchcon.ads ada/table.ads ada/table.adb ada/tree_io.ads \
+   ada/types.ads ada/uintp.ads ada/unchconv.ads ada/unchdeal.ads \
+   ada/urealp.ads 
 
 ada/get_scos.o : ada/ada.ads ada/a-ioexce.ads ada/a-unccon.ads \
    ada/get_scos.ads ada/get_scos.adb ada/gnat.ads ada/g-table.ads \
@@ -3314,13 +3314,14 @@ ada/prepcomp.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
 ada/put_alfa.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
    ada/a-uncdea.ads ada/alfa.ads ada/alfa.adb ada/alloc.ads ada/atree.ads \
    ada/debug.ads ada/einfo.ads ada/gnat.ads ada/g-table.ads \
-   ada/g-table.adb ada/hostparm.ads ada/namet.ads ada/opt.ads \
-   ada/output.ads ada/put_alfa.ads ada/put_alfa.adb ada/sinfo.ads \
-   ada/snames.ads ada/system.ads ada/s-exctab.ads ada/s-memory.ads \
-   ada/s-os_lib.ads ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads \
-   ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
-   ada/table.adb ada/tree_io.ads ada/types.ads ada/uintp.ads \
-   ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads 
+   ada/g-table.adb ada/hostparm.ads ada/namet.ads ada/nlists.ads \
+   ada/nmake.ads ada/opt.ads ada/output.ads ada/put_alfa.ads \
+   ada/put_alfa.adb ada/sem_util.ads ada/sinfo.ads ada/snames.ads \
+   ada/system.ads ada/s-exctab.ads ada/s-memory.ads ada/s-os_lib.ads \
+   ada/s-parame.ads ada/s-stalib.ads ada/s-string.ads ada/s-traent.ads \
+   ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
+   ada/tree_io.ads ada/types.ads ada/uintp.ads ada/unchconv.ads \
+   ada/unchdeal.ads ada/urealp.ads 
 
 ada/put_scos.o : ada/ada.ads ada/a-unccon.ads ada/gnat.ads ada/g-table.ads \
    ada/g-table.adb ada/par_sco.ads ada/put_scos.ads ada/put_scos.adb \
@@ -3951,23 +3952,22 @@ ada/sem_ch13.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
 ada/sem_ch2.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
    ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
    ada/atree.adb ada/casing.ads ada/csets.ads ada/debug.ads ada/einfo.ads \
-   ada/einfo.adb ada/err_vars.ads ada/errout.ads ada/errout.adb \
-   ada/erroutc.ads ada/erroutc.adb ada/fname.ads ada/fname-uf.ads \
-   ada/gnat.ads ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads \
-   ada/interfac.ads ada/lib.ads ada/namet.ads ada/namet.adb ada/nlists.ads \
-   ada/nlists.adb ada/nmake.ads ada/opt.ads ada/output.ads \
-   ada/restrict.ads ada/restrict.adb ada/rident.ads ada/scans.ads \
-   ada/sem_aux.ads ada/sem_ch2.ads ada/sem_ch2.adb ada/sem_ch8.ads \
-   ada/sem_util.ads ada/sinfo.ads ada/sinfo.adb ada/sinput.ads \
-   ada/snames.ads ada/stand.ads ada/stylesw.ads ada/system.ads \
-   ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads ada/s-imenne.ads \
-   ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads ada/s-rident.ads \
-   ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads ada/s-stalib.ads \
-   ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads ada/s-traent.ads \
-   ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads ada/table.adb \
-   ada/targparm.ads ada/tree_io.ads ada/types.ads ada/types.adb \
-   ada/uintp.ads ada/uintp.adb ada/uname.ads ada/unchconv.ads \
-   ada/unchdeal.ads ada/urealp.ads ada/widechar.ads 
+   ada/err_vars.ads ada/errout.ads ada/errout.adb ada/erroutc.ads \
+   ada/erroutc.adb ada/fname.ads ada/fname-uf.ads ada/gnat.ads \
+   ada/g-htable.ads ada/gnatvsn.ads ada/hostparm.ads ada/interfac.ads \
+   ada/lib.ads ada/namet.ads ada/namet.adb ada/nlists.ads ada/nlists.adb \
+   ada/opt.ads ada/output.ads ada/restrict.ads ada/restrict.adb \
+   ada/rident.ads ada/scans.ads ada/sem_aux.ads ada/sem_ch2.ads \
+   ada/sem_ch2.adb ada/sem_ch8.ads ada/sinfo.ads ada/sinfo.adb \
+   ada/sinput.ads ada/snames.ads ada/stand.ads ada/stylesw.ads \
+   ada/system.ads ada/s-carun8.ads ada/s-exctab.ads ada/s-htable.ads \
+   ada/s-imenne.ads ada/s-memory.ads ada/s-os_lib.ads ada/s-parame.ads \
+   ada/s-rident.ads ada/s-secsta.ads ada/s-soflin.ads ada/s-stache.ads \
+   ada/s-stalib.ads ada/s-stoele.ads ada/s-stoele.adb ada/s-string.ads \
+   ada/s-traent.ads ada/s-unstyp.ads ada/s-wchcon.ads ada/table.ads \
+   ada/table.adb ada/targparm.ads ada/tree_io.ads ada/types.ads \
+   ada/types.adb ada/uintp.ads ada/uintp.adb ada/uname.ads \
+   ada/unchconv.ads ada/unchdeal.ads ada/urealp.ads ada/widechar.ads 
 
 ada/sem_ch3.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
    ada/a-uncdea.ads ada/alloc.ads ada/aspects.ads ada/atree.ads \
index 386c05f..2ceb3a0 100644 (file)
@@ -1574,6 +1574,7 @@ adamsg.o: adamsg.msg
   GNATLIB_SHARED=gnatlib-shared-vms
   EXTRA_LIBGNAT_SRCS+=adamsg.msg
   EXTRA_LIBGNAT_OBJS+=adamsg.o
+  EXTRA_GNATRTL_NONTASKING_OBJS+-s-po32gl.o
   EXTRA_GNATRTL_TASKING_OBJS=s-tpopde.o
   EXTRA_GNATTOOLS = \
      ../../gnatsym$(exeext)
index 6b485f0..7372996 100644 (file)
@@ -466,9 +466,6 @@ package body Make is
    --  A table to keep dependencies, to be able to decide if an executable
    --  is obsolete. More explanation needed ???
 
---     procedure Add_Dependency (S : File_Name_Type; On : File_Name_Type);
---     --  Add one entry in table Dependencies
-
    ----------------------------
    -- Arguments and Switches --
    ----------------------------
@@ -601,6 +598,83 @@ package body Make is
    procedure Process_Multilib (Env : in out Prj.Tree.Environment);
    --  Add appropriate --RTS argument to handle multilib
 
+   procedure Compute_Builder_Switches
+     (Project_Node_Tree   : Project_Node_Tree_Ref;
+      Root_Environment    : in out Prj.Tree.Environment;
+      Main_Unit_File_Name : String;
+      Main_Index          : Int := 0);
+   --  Analyze the root project to find the builder switches and the global
+   --  compilation switches (the latter are ignored if there were multiple main
+   --  on the command line.
+
+   procedure Resolve_Relative_Names_In_Switches (Current_Work_Dir : String);
+   --  Resolve all relative paths found in the linker and binder switches,
+   --  when using project files.
+
+   procedure Queue_Library_Project_Sources;
+   --  For all library project, if the library file does not exist,
+   --  put all the project sources in the queue, and flag the project
+   --  so that the library is generated.
+
+   procedure Compute_Switches_For_Main
+     (Main_Source_File  : in out File_Name_Type;
+      Main_Index        : Int;
+      Project_Node_Tree : Project_Node_Tree_Ref;
+      Root_Environment  : in out Prj.Tree.Environment;
+      Compute_Builder   : Boolean;
+      Current_Work_Dir  : String);
+   --  Find compiler, binder and linker switches to use for the given main
+
+   procedure Compute_Executable
+     (Main_Source_File   : File_Name_Type;
+      Executable         : out File_Name_Type;
+      Non_Std_Executable : out Boolean);
+   --  Parse the linker switches and project file to compute the name of the
+   --  executable to generate.
+   --  ??? What is the meaning of Non_Std_Executable
+
+   procedure Compilation_Phase
+     (Main_Source_File           : File_Name_Type;
+      Current_Main_Index         : Int := 0;
+      Total_Compilation_Failures : in out Natural;
+      Stand_Alone_Libraries      : in out Boolean;
+      Executable                 : File_Name_Type := No_File;
+      Is_Last_Main               : Boolean;
+      Stop_Compile               : out Boolean);
+   --  Build all source files for a given main file.
+   --  Current_Main_Index, if not zero, the index of the current main unit in
+   --  its source file.
+   --  Stand_Alone_Libraries is set to True when there are Stand-Alone
+   --  Libraries, so that gnatbind is invoked with the -F switch to force
+   --  checking of elaboration flags.
+   --  Stop_Compile is set to true if we should not try to compile any more
+   --  of the main units
+
+   procedure Binding_Phase
+     (Stand_Alone_Libraries : Boolean := False;
+      Main_ALI_File : File_Name_Type);
+   --  Stand_Alone_Libraries should be set to True when there are Stand-Alone
+   --  Libraries, so that gnatbind is invoked with the -F switch to force
+   --  checking of elaboration flags.
+
+   procedure Library_Phase
+      (Stand_Alone_Libraries : in out Boolean;
+       Library_Rebuilt : in out Boolean);
+   --  Build libraries.
+   --  Stand_Alone_Libraries is set to True when there are Stand-Alone
+   --  Libraries, so that gnatbind is invoked with the -F switch to force
+   --  checking of elaboration flags.
+
+   procedure Linking_Phase
+     (Non_Std_Executable : Boolean := False;
+      Executable         : File_Name_Type := No_File;
+      Main_ALI_File      : File_Name_Type);
+   --  Perform the link of a single executable.
+   --  The ali file corresponding to Main_Source_File.
+   --  Executable is the file name of an executable.
+   --  Non_Std_Executable is set to True when there is a possibility that
+   --  the linker will not choose the correct executable file name.
+
    ----------------------------------------------------
    -- Compiler, Binder & Linker Data and Subprograms --
    ----------------------------------------------------
@@ -4087,2194 +4161,2181 @@ package body Make is
       end if;
    end Globalize;
 
-   --------------
-   -- Gnatmake --
-   --------------
-
-   procedure Gnatmake is
-      Main_Source_File : File_Name_Type;
-      --  The source file containing the main compilation unit
-
-      Compilation_Failures : Natural;
+   -------------------
+   -- Linking_Phase --
+   -------------------
 
-      Total_Compilation_Failures : Natural := 0;
+   procedure Linking_Phase
+     (Non_Std_Executable : Boolean := False;
+      Executable         : File_Name_Type := No_File;
+      Main_ALI_File      : File_Name_Type)
+   is
+      Linker_Switches_Last : constant Integer := Linker_Switches.Last;
+      Path_Option          : constant String_Access :=
+        MLib.Linker_Library_Path_Option;
+      Libraries_Present    : Boolean := False;
+      Current              : Natural;
+      Proj2                : Project_Id;
+      Depth                : Natural;
+      Proj1                : Project_List;
+   begin
+      if not Run_Path_Option then
+         Linker_Switches.Increment_Last;
+         Linker_Switches.Table (Linker_Switches.Last) :=
+           new String'("-R");
+      end if;
 
-      Is_Main_Unit : Boolean;
-      --  Set True by Compile_Sources if Main_Source_File can be a main unit
+      if Main_Project /= No_Project then
+         Library_Paths.Set_Last (0);
+         Library_Projs.Init;
 
-      Main_ALI_File : File_Name_Type;
-      --  The ali file corresponding to Main_Source_File
+         if MLib.Tgt.Support_For_Libraries /= Prj.None then
 
-      Executable : File_Name_Type := No_File;
-      --  The file name of an executable
+            --  Check for library projects
 
-      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.
+            Proj1 := Project_Tree.Projects;
+            while Proj1 /= null loop
+               if Proj1.Project /= Main_Project
+                 and then Proj1.Project.Library
+               then
+                  --  Add this project to table Library_Projs
 
-      Current_Work_Dir : constant String_Access :=
-                                    new String'(Get_Current_Dir);
-      --  The current working directory, used to modify some relative path
-      --  switches on the command line when a project file is used.
+                  Libraries_Present := True;
+                  Depth := Proj1.Project.Depth;
+                  Library_Projs.Increment_Last;
+                  Current := Library_Projs.Last;
 
-      Current_Main_Index : Int := 0;
-      --  If not zero, the index of the current main unit in its source file
+                  --  Any project with a greater depth should be
+                  --  after this project in the list.
 
-      Stand_Alone_Libraries : Boolean := False;
-      --  Set to True when there are Stand-Alone Libraries, so that gnatbind
-      --  is invoked with the -F switch to force checking of elaboration flags.
+                  while Current > 1 loop
+                     Proj2 := Library_Projs.Table (Current - 1);
+                     exit when Proj2.Depth <= Depth;
+                     Library_Projs.Table (Current) := Proj2;
+                     Current := Current - 1;
+                  end loop;
 
-      Mapping_Path : Path_Name_Type := No_Path;
-      --  The path name of the mapping file
+                  Library_Projs.Table (Current) := Proj1.Project;
 
-      Project_Node_Tree : Project_Node_Tree_Ref;
-      Root_Environment  : Prj.Tree.Environment;
+                  --  If it is not a static library and path option
+                  --  is set, add it to the Library_Paths table.
 
-      Discard : Boolean;
-      pragma Warnings (Off, Discard);
+                  if Proj1.Project.Library_Kind /= Static
+                    and then Proj1.Project.Extended_By = No_Project
+                    and then Path_Option /= null
+                  then
+                     Library_Paths.Increment_Last;
+                     Library_Paths.Table (Library_Paths.Last) :=
+                       new String'
+                         (Get_Name_String
+                              (Proj1.Project.Library_Dir.Display_Name));
+                  end if;
+               end if;
 
-      procedure Check_Mains;
-      --  Check that the main subprograms do exist and that they all
-      --  belong to the same project file.
+               Proj1 := Proj1.Next;
+            end loop;
 
-      -----------------
-      -- Check_Mains --
-      -----------------
+            for Index in 1 .. Library_Projs.Last loop
+               if
+                 Library_Projs.Table (Index).Extended_By = No_Project
+               then
+                  if Library_Projs.Table (Index).Library_Kind = Static
+                    and then not Targparm.OpenVMS_On_Target
+                  then
+                     Linker_Switches.Increment_Last;
+                     Linker_Switches.Table (Linker_Switches.Last) :=
+                       new String'
+                         (Get_Name_String
+                              (Library_Projs.Table
+                                   (Index).Library_Dir.Display_Name) &
+                          "lib" &
+                          Get_Name_String
+                            (Library_Projs.Table
+                               (Index).Library_Name) &
+                          "." &
+                          MLib.Tgt.Archive_Ext);
 
-      procedure Check_Mains is
-      begin
-         if Mains.Number_Of_Mains (Project_Tree) = 0
-           and then not Unique_Compile
-         then
-            Mains.Fill_From_Project (Main_Project, Project_Tree);
+                  else
+                     --  Add the -L switch
+
+                     Linker_Switches.Increment_Last;
+                     Linker_Switches.Table (Linker_Switches.Last) :=
+                       new String'("-L" &
+                         Get_Name_String
+                           (Library_Projs.Table (Index).
+                              Library_Dir.Display_Name));
+
+                     --  Add the -l switch
+
+                     Linker_Switches.Increment_Last;
+                     Linker_Switches.Table (Linker_Switches.Last) :=
+                       new String'("-l" &
+                         Get_Name_String
+                           (Library_Projs.Table (Index).
+                              Library_Name));
+                  end if;
+               end if;
+            end loop;
          end if;
 
-         Mains.Complete_Mains
-           (Root_Environment.Flags, Main_Project, Project_Tree);
-      end Check_Mains;
+         if Libraries_Present then
 
-   --  Start of processing for Gnatmake
+            --  If Path_Option is not null, create the switch
+            --  ("-Wl,-rpath," or equivalent) with all the non-static
+            --  library dirs plus the standard GNAT library dir.
+            --  We do that only if Run_Path_Option is True
+            --  (not disabled by -R switch).
 
-   --  This body is very long, should be broken down???
+            if Run_Path_Option and then Path_Option /= null then
+               declare
+                  Option  : String_Access;
+                  Length  : Natural := Path_Option'Length;
+                  Current : Natural;
 
-   begin
-      Install_Int_Handler (Sigint_Intercepted'Access);
+               begin
+                  if MLib.Separate_Run_Path_Options then
 
-      Do_Compile_Step := True;
-      Do_Bind_Step    := True;
-      Do_Link_Step    := True;
+                     --  We are going to create one switch of the form
+                     --  "-Wl,-rpath,dir_N" for each directory to
+                     --  consider.
 
-      Obsoleted.Reset;
+                     --  One switch for each library directory
 
-      Make.Initialize (Project_Node_Tree, Root_Environment);
+                     for Index in
+                       Library_Paths.First .. Library_Paths.Last
+                     loop
+                        Linker_Switches.Increment_Last;
+                        Linker_Switches.Table
+                          (Linker_Switches.Last) :=
+                          new String'
+                            (Path_Option.all &
+                             Library_Paths.Table (Index).all);
+                     end loop;
 
-      Bind_Shared := No_Shared_Switch'Access;
-      Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access;
+                     --  One switch for the standard GNAT library dir
 
-      Failed_Links.Set_Last (0);
-      Successful_Links.Set_Last (0);
+                     Linker_Switches.Increment_Last;
+                     Linker_Switches.Table
+                       (Linker_Switches.Last) :=
+                       new String'
+                         (Path_Option.all & MLib.Utl.Lib_Directory);
 
-      --  Special case when switch -B was specified
+                  else
+                     --  We are going to create one switch of the form
+                     --  "-Wl,-rpath,dir_1:dir_2:dir_3"
 
-      if Build_Bind_And_Link_Full_Project then
+                     for Index in
+                       Library_Paths.First .. Library_Paths.Last
+                     loop
+                        --  Add the length of the library dir plus one
+                        --  for the directory separator.
 
-         --  When switch -B is specified, there must be a project file
+                        Length :=
+                          Length +
+                            Library_Paths.Table (Index)'Length + 1;
+                     end loop;
 
-         if Main_Project = No_Project then
-            Make_Failed ("-B cannot be used without a project file");
+                     --  Finally, add the length of the standard GNAT
+                     --  library dir.
 
-         --  No main program may be specified on the command line
+                     Length := Length + MLib.Utl.Lib_Directory'Length;
+                     Option := new String (1 .. Length);
+                     Option (1 .. Path_Option'Length) :=
+                       Path_Option.all;
+                     Current := Path_Option'Length;
 
-         elsif Osint.Number_Of_Files /= 0 then
-            Make_Failed ("-B cannot be used with a main specified on " &
-                         "the command line");
+                     --  Put each library dir followed by a dir
+                     --  separator.
 
-         --  And the project file cannot be a library project file
+                     for Index in
+                       Library_Paths.First .. Library_Paths.Last
+                     loop
+                        Option
+                          (Current + 1 ..
+                             Current +
+                               Library_Paths.Table (Index)'Length) :=
+                          Library_Paths.Table (Index).all;
+                        Current :=
+                          Current +
+                            Library_Paths.Table (Index)'Length + 1;
+                        Option (Current) := Path_Separator;
+                     end loop;
 
-         elsif Main_Project.Library then
-            Make_Failed ("-B cannot be used for a library project file");
+                     --  Finally put the standard GNAT library dir
 
-         else
-            No_Main_Subprogram := True;
-            Insert_Project_Sources
-              (The_Project  => Main_Project,
-               All_Projects => Unique_Compile_All_Projects,
-               Into_Q       => False);
+                     Option
+                       (Current + 1 ..
+                          Current + MLib.Utl.Lib_Directory'Length) :=
+                         MLib.Utl.Lib_Directory;
 
-            --  If there are no sources to compile, we fail
+                     --  And add the switch to the linker switches
 
-            if Osint.Number_Of_Files = 0 then
-               Make_Failed ("no sources to compile");
+                     Linker_Switches.Increment_Last;
+                     Linker_Switches.Table (Linker_Switches.Last) :=
+                       Option;
+                  end if;
+               end;
             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.
+         end if;
 
-            Add_Switch ("-n", Binder, And_Save => True);
+         --  Put the object directories in ADA_OBJECTS_PATH
 
-            for J in 1 .. Queue.Size loop
-               Add_Switch
-                 (Get_Name_String
-                    (Lib_File_Name (Queue.Element (J))),
-                  Binder, And_Save => True);
+         Prj.Env.Set_Ada_Paths
+           (Main_Project,
+            Project_Tree,
+            Including_Libraries => False,
+            Include_Path        => False);
+
+         --  Check for attributes Linker'Linker_Options in projects
+         --  other than the main project
+
+         declare
+            Linker_Options : constant String_List :=
+              Linker_Options_Switches
+                (Main_Project,
+                 Do_Fail => Make_Failed'Access,
+                 In_Tree => Project_Tree);
+         begin
+            for Option in Linker_Options'Range loop
+               Linker_Switches.Increment_Last;
+               Linker_Switches.Table (Linker_Switches.Last) :=
+                 Linker_Options (Option);
             end loop;
-         end if;
+         end;
+      end if;
 
-      elsif Main_Index /= 0 and then Osint.Number_Of_Files > 1 then
-         Make_Failed ("cannot specify several mains with a multi-unit index");
+      --  Add switch -M to gnatlink if buider switch --create-map-file
+      --  has been specified.
 
-      elsif Main_Project /= No_Project then
+      if Map_File /= null then
+         Linker_Switches.Increment_Last;
+         Linker_Switches.Table (Linker_Switches.Last) :=
+           new String'("-M" & Map_File.all);
+      end if;
 
-         --  If the main project file is a library project file, main(s) cannot
-         --  be specified on the command line.
+      declare
+         Args : Argument_List
+           (Linker_Switches.First .. Linker_Switches.Last + 2);
 
-         if Osint.Number_Of_Files /= 0 then
-            if Main_Project.Library
-              and then not Unique_Compile
-              and then ((not Make_Steps) or else Bind_Only or else Link_Only)
+         Last_Arg : Integer := Linker_Switches.First - 1;
+         Skip     : Boolean := False;
+
+      begin
+         --  Get all the linker switches
+
+         for J in Linker_Switches.First .. Linker_Switches.Last loop
+            if Skip then
+               Skip := False;
+
+            elsif Non_Std_Executable
+              and then Linker_Switches.Table (J).all = "-o"
             then
-               Make_Failed ("cannot specify a main program " &
-                            "on the command line for a library project file");
+               Skip := True;
 
-            else
-               --  Check that each main on the command line is a source of a
-               --  project file and, if there are several mains, each of them
-               --  is a source of the same project file.
+               --  Here we capture and duplicate the linker argument. We
+               --  need to do the duplication since the arguments will
+               --  get normalized. Not doing so will result in calling
+               --  normalized two times for the same set of arguments if
+               --  gnatmake is passed multiple mains. This can result in
+               --  the wrong argument being passed to the linker.
 
-               Check_Mains;
+            else
+               Last_Arg := Last_Arg + 1;
+               Args (Last_Arg) :=
+                 new String'(Linker_Switches.Table (J).all);
             end if;
+         end loop;
 
-         --  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.
+         --  If need be, add the -o switch
 
-         else
-            if Main_Index /= 0 then
-               Make_Failed ("cannot specify a multi-unit index but no main " &
-                            "on the command line");
-            end if;
+         if Non_Std_Executable then
+            Last_Arg := Last_Arg + 1;
+            Args (Last_Arg) := new String'("-o");
+            Last_Arg := Last_Arg + 1;
+            Args (Last_Arg) := new String'(Get_Name_String (Executable));
+         end if;
 
-            declare
-               Value : String_List_Id := Main_Project.Mains;
+         --  And invoke the linker
 
-            begin
-               --  The attribute Main is an empty list or not specified, or
-               --  else gnatmake was invoked with the switch "-u".
+         declare
+            Success : Boolean := False;
+         begin
+            Link (Main_ALI_File,
+                  Link_With_Shared_Libgcc.all &
+                  Args (Args'First .. Last_Arg),
+                  Success);
+
+            if Success then
+               Successful_Links.Increment_Last;
+               Successful_Links.Table (Successful_Links.Last) :=
+                 Main_ALI_File;
+
+            elsif Osint.Number_Of_Files = 1
+              or else not Keep_Going
+            then
+               Make_Failed ("*** link failed.");
 
-               if Value = Prj.Nil_String or else Unique_Compile then
+            else
+               Set_Standard_Error;
+               Write_Line ("*** link failed");
 
-                  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.
+               if Commands_To_Stdout then
+                  Set_Standard_Output;
+               end if;
 
-                     Do_Bind_Step := False;
-                     Do_Link_Step := False;
+               Failed_Links.Increment_Last;
+               Failed_Links.Table (Failed_Links.Last) :=
+                 Main_ALI_File;
+            end if;
+         end;
+      end;
 
-                     --  Put all the sources in the queue
+      Linker_Switches.Set_Last (Linker_Switches_Last);
+   end Linking_Phase;
 
-                     No_Main_Subprogram := True;
-                     Insert_Project_Sources
-                       (The_Project  => Main_Project,
-                        All_Projects => Unique_Compile_All_Projects,
-                        Into_Q       => False);
+   -------------------
+   -- Binding_Phase --
+   -------------------
 
-                     --  If no sources to compile, then there is nothing to do
+   procedure Binding_Phase
+     (Stand_Alone_Libraries : Boolean := False;
+      Main_ALI_File : File_Name_Type)
+   is
+      Args : Argument_List
+        (Binder_Switches.First .. Binder_Switches.Last + 2);
+      --  The arguments for the invocation of gnatbind
 
-                     if Osint.Number_Of_Files = 0 then
-                        if not Quiet_Output then
-                           Osint.Write_Program_Name;
-                           Write_Line (": no sources to compile");
-                        end if;
+      Last_Arg : Natural := Binder_Switches.Last;
+      --  Index of the last argument in Args
 
-                        Finish_Program (Project_Tree, E_Success);
-                     end if;
-                  end if;
+      Shared_Libs : Boolean := False;
+      --  Set to True when there are shared library project files or
+      --  when gnatbind is invoked with -shared.
 
-               else
-                  --  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.
+      Proj : Project_List;
 
-                  declare
-                     Languages : constant Variable_Value :=
-                                   Prj.Util.Value_Of
-                                     (Name_Languages,
-                                      Main_Project.Decl.Attributes,
-                                      Project_Tree.Shared);
+      Mapping_Path : Path_Name_Type := No_Path;
+      --  The path name of the mapping file
 
-                     Current : String_List_Id;
-                     Element : String_Element;
+   begin
+      --  Check if there are shared libraries, so that gnatbind is
+      --  called with -shared. Check also if gnatbind is called with
+      --  -shared, so that gnatlink is called with -shared-libgcc
+      --  ensuring that the shared version of libgcc will be used.
 
-                     Foreign_Language  : Boolean := False;
-                     At_Least_One_Main : Boolean := False;
+      if Main_Project /= No_Project
+        and then MLib.Tgt.Support_For_Libraries /= Prj.None
+      then
+         Proj := Project_Tree.Projects;
+         while Proj /= null loop
+            if Proj.Project.Library
+              and then Proj.Project.Library_Kind /= Static
+            then
+               Shared_Libs := True;
+               Bind_Shared := Shared_Switch'Access;
+               exit;
+            end if;
+            Proj := Proj.Next;
+         end loop;
+      end if;
 
-                  begin
-                     --  First, determine if there is a foreign language in
-                     --  attribute Languages.
+      --  Check now for switch -shared
 
-                     if not Languages.Default then
-                        Current := Languages.Values;
-                        Look_For_Foreign :
-                        while Current /= Nil_String loop
-                           Element := Project_Tree.Shared.String_Elements.
-                                        Table (Current);
-                           Get_Name_String (Element.Value);
-                           To_Lower (Name_Buffer (1 .. Name_Len));
+      if not Shared_Libs then
+         for J in Binder_Switches.First .. Last_Arg loop
+            if Binder_Switches.Table (J).all = "-shared" then
+               Shared_Libs := True;
+               exit;
+            end if;
+         end loop;
+      end if;
 
-                           if Name_Buffer (1 .. Name_Len) /= "ada" then
-                              Foreign_Language := True;
-                              exit Look_For_Foreign;
-                           end if;
+      --  If shared libraries present, invoke gnatlink with
+      --  -shared-libgcc.
 
-                           Current := Element.Next;
-                        end loop Look_For_Foreign;
-                     end if;
-
-                     --  Then, find all mains, or if there is a foreign
-                     --  language, all the Ada mains.
-
-                     while Value /= Prj.Nil_String loop
-                        --  To know if a main is an Ada main, get its project.
-                        --  It should be the project specified on the command
-                        --  line.
+      if Shared_Libs then
+         Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access;
+      end if;
 
-                        Get_Name_String
-                          (Project_Tree.Shared.String_Elements.Table
-                             (Value).Value);
+      --  Get all the binder switches
 
-                        declare
-                           Main_Name : constant String :=
-                              Get_Name_String
-                               (Project_Tree.Shared.String_Elements.Table
-                                    (Value).Value);
-                           Proj : constant Project_Id :=
-                             Prj.Env.Project_Of
-                              (Main_Name, Main_Project, Project_Tree);
-                        begin
+      for J in Binder_Switches.First .. Last_Arg loop
+         Args (J) := Binder_Switches.Table (J);
+      end loop;
 
-                           if Proj = Main_Project then
+      if Stand_Alone_Libraries then
+         Last_Arg := Last_Arg + 1;
+         Args (Last_Arg) := Force_Elab_Flags_String'Access;
+      end if;
 
-                              At_Least_One_Main := True;
-                              Osint.Add_File
-                                (Get_Name_String
-                                   (Project_Tree.Shared.String_Elements.Table
-                                      (Value).Value),
-                                 Index =>
-                                   Project_Tree.Shared.String_Elements.Table
-                                     (Value).Index);
+      if Main_Project /= No_Project then
 
-                           elsif not Foreign_Language then
-                              Make_Failed
-                                ("""" & Main_Name &
-                                 """ is not a source of project " &
-                                 Get_Name_String (Main_Project.Display_Name));
-                           end if;
-                        end;
+         --  Put all the source directories in ADA_INCLUDE_PATH,
+         --  and all the object directories in ADA_OBJECTS_PATH,
+         --  except those of library projects.
 
-                        Value := Project_Tree.Shared.String_Elements.Table
-                                   (Value).Next;
-                     end loop;
+         Prj.Env.Set_Ada_Paths
+           (Project             => Main_Project,
+            In_Tree             => Project_Tree,
+            Including_Libraries => False,
+            Include_Path        => Use_Include_Path_File);
 
-                     --  If we did not get any main, it means that all mains
-                     --  in attribute Mains are in a foreign language and -B
-                     --  was not specified to gnatmake; so, we fail.
+         --  If switch -C was specified, create a binder mapping file
 
-                     if not At_Least_One_Main then
-                        Make_Failed
-                          ("no Ada mains, use -B to build foreign main");
-                     end if;
-                  end;
+         if Create_Mapping_File then
+            Mapping_Path := Create_Binder_Mapping_File (Project_Tree);
 
-               end if;
-            end;
+            if Mapping_Path /= No_Path then
+               Last_Arg := Last_Arg + 1;
+               Args (Last_Arg) :=
+                 new String'("-F=" & Get_Name_String (Mapping_Path));
+            end if;
          end if;
-      end if;
 
-      if Verbose_Mode then
-         Write_Eol;
-         Display_Version ("GNATMAKE", "1995");
       end if;
 
-      if Osint.Number_Of_Files = 0 then
-         if Main_Project /= No_Project
-           and then Main_Project.Library
-         then
-            if Do_Bind_Step
-              and then not Main_Project.Standalone_Library
-            then
-               Make_Failed ("only stand-alone libraries may be bound");
-            end if;
-
-            --  Add the default search directories to be able to find libgnat
-
-            Osint.Add_Default_Search_Dirs;
+      begin
+         Bind (Main_ALI_File,
+               Bind_Shared.all & Args (Args'First .. Last_Arg));
 
-            --  Get the target parameters, so that the correct binder generated
-            --  files are generated if OpenVMS is the target.
+      exception
+         when others =>
 
-            begin
-               Targparm.Get_Target_Parameters;
+            --  Delete the temporary mapping file if one was created
 
-            exception
-               when Unrecoverable_Error =>
-                  Make_Failed ("*** make failed.");
-            end;
+            if Mapping_Path /= No_Path then
+               Delete_Temporary_File
+                 (Project_Tree.Shared, Mapping_Path);
+            end if;
 
-            --  And bind and or link the library
+            --  And reraise the exception
 
-            MLib.Prj.Build_Library
-              (For_Project   => Main_Project,
-               In_Tree       => Project_Tree,
-               Gnatbind      => Gnatbind.all,
-               Gnatbind_Path => Gnatbind_Path,
-               Gcc           => Gcc.all,
-               Gcc_Path      => Gcc_Path,
-               Bind          => Bind_Only,
-               Link          => Link_Only);
+            raise;
+      end;
 
-            Finish_Program (Project_Tree, E_Success);
+      --  If -dn was not specified, delete the temporary mapping file
+      --  if one was created.
 
-         else
-            --  Call Get_Target_Parameters to ensure that VM_Target and
-            --  AAMP_On_Target get set before calling Usage.
+      if Mapping_Path /= No_Path then
+         Delete_Temporary_File (Project_Tree.Shared, Mapping_Path);
+      end if;
+   end Binding_Phase;
 
-            Targparm.Get_Target_Parameters;
+   -------------------
+   -- Library_Phase --
+   -------------------
 
-            --  Output usage information if no files to compile
+   procedure Library_Phase
+     (Stand_Alone_Libraries : in out Boolean;
+      Library_Rebuilt : in out Boolean)
+   is
+      Depth   : Natural;
+      Current : Natural;
+      Proj1   : Project_List;
 
-            Usage;
-            Finish_Program (Project_Tree, E_Success);
-         end if;
-      end if;
+      procedure Add_To_Library_Projs (Proj : Project_Id);
+      --  Add project Project to table Library_Projs in
+      --  decreasing depth order.
 
-      --  If -M was specified, behave as if -n was specified
+      --------------------------
+      -- Add_To_Library_Projs --
+      --------------------------
 
-      if List_Dependencies then
-         Do_Not_Execute := True;
-      end if;
+      procedure Add_To_Library_Projs (Proj : Project_Id) is
+         Prj : Project_Id;
 
-      --  Note that Osint.M.Next_Main_Source will always return the (possibly
-      --  abbreviated file) without any directory information.
+      begin
+         Library_Projs.Increment_Last;
+         Depth := Proj.Depth;
+
+         --  Put the projects in decreasing depth order, so that
+         --  if libA depends on libB, libB is first in order.
+
+         Current := Library_Projs.Last;
+         while Current > 1 loop
+            Prj := Library_Projs.Table (Current - 1);
+            exit when Prj.Depth >= Depth;
+            Library_Projs.Table (Current) := Prj;
+            Current := Current - 1;
+         end loop;
 
-      Main_Source_File := Next_Main_Source;
+         Library_Projs.Table (Current) := Proj;
+      end Add_To_Library_Projs;
 
-      if Current_File_Index /= No_Index then
-         Main_Index := Current_File_Index;
-      end if;
+   begin
+      Library_Projs.Init;
 
-      Add_Switch ("-I-", Compiler, And_Save => True);
+      --  Put in Library_Projs table all library project file
+      --  ids when the library need to be rebuilt.
 
-      if Main_Project = No_Project then
-         if Look_In_Primary_Dir then
+      Proj1 := Project_Tree.Projects;
+      while Proj1 /= null loop
+         if Proj1.Project.Extended_By = No_Project then
+            if Proj1.Project.Standalone_Library then
+               Stand_Alone_Libraries := True;
+            end if;
 
-            Add_Switch
-              ("-I" &
-               Normalize_Directory_Name
-               (Get_Primary_Src_Search_Directory.all).all,
-               Compiler, Append_Switch => False,
-               And_Save => False);
+            if Proj1.Project.Library then
+               MLib.Prj.Check_Library
+                 (Proj1.Project, Project_Tree);
+            end if;
 
+            if Proj1.Project.Need_To_Build_Lib then
+               Add_To_Library_Projs (Proj1.Project);
+            end if;
          end if;
 
-      else
-         --  If we use a project file, we have already checked that a main
-         --  specified on the command line with directory information has the
-         --  path name corresponding to a correct source in the project tree.
-         --  So, we don't need the directory information to be taken into
-         --  account by Find_File, and in fact it may lead to take the wrong
-         --  sources for other compilation units, when there are extending
-         --  projects.
-
-         Look_In_Primary_Dir := False;
-         Add_Switch ("-I-", Binder, And_Save => True);
-      end if;
+         Proj1 := Proj1.Next;
+      end loop;
 
-      --  If the user wants a program without a main subprogram, add the
-      --  appropriate switch to the binder.
+      --  Check if importing libraries should be regenerated
+      --  because at least an imported library will be
+      --  regenerated or is more recent.
+
+      Proj1 := Project_Tree.Projects;
+      while Proj1 /= null loop
+         if Proj1.Project.Library
+           and then Proj1.Project.Extended_By = No_Project
+           and then Proj1.Project.Library_Kind /= Static
+           and then not Proj1.Project.Need_To_Build_Lib
+           and then not Proj1.Project.Externally_Built
+         then
+            declare
+               List    : Project_List;
+               Proj2   : Project_Id;
+               Rebuild : Boolean := False;
 
-      if No_Main_Subprogram then
-         Add_Switch ("-z", Binder, And_Save => True);
-      end if;
+               Lib_Timestamp1 : constant Time_Stamp_Type :=
+                 Proj1.Project.Library_TS;
 
-      if Main_Project /= No_Project then
+            begin
+               List := Proj1.Project.All_Imported_Projects;
+               while List /= null loop
+                  Proj2 := List.Project;
+
+                  if Proj2.Library then
+                     if Proj2.Need_To_Build_Lib
+                       or else
+                         (Lib_Timestamp1 < Proj2.Library_TS)
+                     then
+                        Rebuild := True;
+                        exit;
+                     end if;
+                  end if;
 
-         if Main_Project.Object_Directory /= No_Path_Information then
-            --  Change current directory to object directory of main project
+                  List := List.Next;
+               end loop;
 
-            Project_Of_Current_Object_Directory := No_Project;
-            Change_To_Object_Directory (Main_Project);
+               if Rebuild then
+                  Proj1.Project.Need_To_Build_Lib := True;
+                  Add_To_Library_Projs (Proj1.Project);
+               end if;
+            end;
          end if;
 
-         --  Source file lookups should be cached for efficiency.
-         --  Source files are not supposed to change.
-
-         Osint.Source_File_Data (Cache => True);
+         Proj1 := Proj1.Next;
+      end loop;
 
-         --  Find the file name of the (first) main unit
+      --  Reset the flags Need_To_Build_Lib for the next main,
+      --  to avoid rebuilding libraries uselessly.
 
-         declare
-            Main_Source_File_Name : constant String :=
-                                      Get_Name_String (Main_Source_File);
-            Main_Unit_File_Name   : constant String :=
-                                      Prj.Env.File_Name_Of_Library_Unit_Body
-                                        (Name    => Main_Source_File_Name,
-                                         Project => Main_Project,
-                                         In_Tree => Project_Tree,
-                                         Main_Project_Only =>
-                                           not Unique_Compile);
-
-            The_Packages : constant Package_Id :=
-                             Main_Project.Decl.Packages;
-
-            Builder_Package : constant Prj.Package_Id :=
-                                Prj.Util.Value_Of
-                                  (Name        => Name_Builder,
-                                   In_Packages => The_Packages,
-                                   Shared      => Project_Tree.Shared);
+      Proj1 := Project_Tree.Projects;
+      while Proj1 /= null loop
+         Proj1.Project.Need_To_Build_Lib := False;
+         Proj1 := Proj1.Next;
+      end loop;
 
-            Binder_Package : constant Prj.Package_Id :=
-                               Prj.Util.Value_Of
-                                 (Name        => Name_Binder,
-                                  In_Packages => The_Packages,
-                                  Shared      => Project_Tree.Shared);
+      --  Build the libraries, if any need to be built
 
-            Linker_Package : constant Prj.Package_Id :=
-                               Prj.Util.Value_Of
-                                 (Name        => Name_Linker,
-                                  In_Packages => The_Packages,
-                                  Shared      => Project_Tree.Shared);
+      for J in 1 .. Library_Projs.Last loop
+         Library_Rebuilt := True;
 
-            Default_Switches_Array : Array_Id;
+         --  If a library is rebuilt, then executables are obsolete
 
-            Global_Compilation_Array    : Array_Element_Id;
-            Global_Compilation_Elem     : Array_Element;
-            Global_Compilation_Switches : Variable_Value;
+         Executable_Obsolete := True;
 
-         begin
-            --  We fail if we cannot find the main source file
+         MLib.Prj.Build_Library
+           (For_Project   => Library_Projs.Table (J),
+            In_Tree       => Project_Tree,
+            Gnatbind      => Gnatbind.all,
+            Gnatbind_Path => Gnatbind_Path,
+            Gcc           => Gcc.all,
+            Gcc_Path      => Gcc_Path);
+      end loop;
+   end Library_Phase;
 
-            if Main_Unit_File_Name = "" then
-               Make_Failed ('"' & Main_Source_File_Name
-                            & """ is not a unit of project "
-                            & Project_File_Name.all & ".");
-            else
-               --  Remove any directory information from the main source file
-               --  file name.
+   -----------------------
+   -- Compilation_Phase --
+   -----------------------
 
-               declare
-                  Pos : Natural := Main_Unit_File_Name'Last;
+   procedure Compilation_Phase
+     (Main_Source_File           : File_Name_Type;
+      Current_Main_Index         : Int := 0;
+      Total_Compilation_Failures : in out Natural;
+      Stand_Alone_Libraries      : in out Boolean;
+      Executable                 : File_Name_Type := No_File;
+      Is_Last_Main               : Boolean;
+      Stop_Compile               : out Boolean)
+   is
+      Args                : Argument_List (1 .. Gcc_Switches.Last);
 
-               begin
-                  loop
-                     exit when Pos < Main_Unit_File_Name'First or else
-                       Main_Unit_File_Name (Pos) = Directory_Separator;
-                     Pos := Pos - 1;
-                  end loop;
+      First_Compiled_File : File_Name_Type;
+      Youngest_Obj_File   : File_Name_Type;
+      Youngest_Obj_Stamp  : Time_Stamp_Type;
 
-                  Name_Len := Main_Unit_File_Name'Last - Pos;
+      Is_Main_Unit : Boolean;
+      --  Set True by Compile_Sources if Main_Source_File can be a main unit
 
-                  Name_Buffer (1 .. Name_Len) :=
-                    Main_Unit_File_Name
-                    (Pos + 1 .. Main_Unit_File_Name'Last);
+      Compilation_Failures : Natural;
 
-                  Main_Source_File := Name_Find;
+      Executable_Stamp : Time_Stamp_Type;
 
-                  --  We only output the main source file if there is only one
+      Library_Rebuilt : Boolean := False;
 
-                  if Verbose_Mode and then Osint.Number_Of_Files = 1 then
-                     Write_Str ("Main source file: """);
-                     Write_Str (Main_Unit_File_Name
-                                (Pos + 1 .. Main_Unit_File_Name'Last));
-                     Write_Line (""".");
-                  end if;
-               end;
-            end if;
+   begin
+      Stop_Compile := False;
 
-            --  If there is a package Builder in the main project file, add
-            --  the switches from it.
+      for J in 1 .. Gcc_Switches.Last loop
+         Args (J) := Gcc_Switches.Table (J);
+      end loop;
 
-            if Builder_Package /= No_Package then
+      --  Now we invoke Compile_Sources for the current main
+
+      Compile_Sources
+        (Main_Source           => Main_Source_File,
+         Args                  => Args,
+         First_Compiled_File   => First_Compiled_File,
+         Most_Recent_Obj_File  => Youngest_Obj_File,
+         Most_Recent_Obj_Stamp => Youngest_Obj_Stamp,
+         Main_Unit             => Is_Main_Unit,
+         Main_Index            => Current_Main_Index,
+         Compilation_Failures  => Compilation_Failures,
+         Check_Readonly_Files  => Check_Readonly_Files,
+         Do_Not_Execute        => Do_Not_Execute,
+         Force_Compilations    => Force_Compilations,
+         In_Place_Mode         => In_Place_Mode,
+         Keep_Going            => Keep_Going,
+         Initialize_ALI_Data   => True,
+         Max_Process           => Saved_Maximum_Processes);
 
-               Global_Compilation_Array := Prj.Util.Value_Of
-                 (Name      => Name_Global_Compilation_Switches,
-                  In_Arrays => Project_Tree.Shared.Packages.Table
-                    (Builder_Package).Decl.Arrays,
-                  Shared    => Project_Tree.Shared);
+      if Verbose_Mode then
+         Write_Str ("End of compilation");
+         Write_Eol;
+      end if;
 
-               Default_Switches_Array :=
-                 Project_Tree.Shared.Packages.Table
-                   (Builder_Package).Decl.Arrays;
+      Total_Compilation_Failures :=
+        Total_Compilation_Failures + Compilation_Failures;
 
-               while Default_Switches_Array /= No_Array and then
-                 Project_Tree.Shared.Arrays.Table (Default_Switches_Array).Name
-                 /= Name_Default_Switches
-               loop
-                  Default_Switches_Array := Project_Tree.Shared.Arrays.Table
-                    (Default_Switches_Array).Next;
-               end loop;
+      if Total_Compilation_Failures /= 0 then
+         Stop_Compile := True;
+         return;
+      end if;
 
-               if Global_Compilation_Array /= No_Array_Element and then
-                  Default_Switches_Array /= No_Array
-               then
-                  Errutil.Error_Msg
-                    ("Default_Switches forbidden in presence of " &
-                     "Global_Compilation_Switches. Use Switches instead.",
-                     Project_Tree.Shared.Arrays.Table
-                       (Default_Switches_Array).Location);
-                  Make_Failed
-                    ("*** illegal combination of Builder attributes");
-               end if;
+      --  Regenerate libraries, if there are any and if object files
+      --  have been regenerated.
 
-               --  If there is only one main, we attempt to get the gnatmake
-               --  switches for this main (if any). If there are no specific
-               --  switch for this particular main, get the general gnatmake
-               --  switches (if any).
+      if Main_Project /= No_Project
+        and then MLib.Tgt.Support_For_Libraries /= Prj.None
+        and then (Do_Bind_Step
+                  or Unique_Compile_All_Projects
+                  or not Compile_Only)
+        and then (Do_Link_Step or else Is_Last_Main)
+      then
+         Library_Phase
+           (Stand_Alone_Libraries => Stand_Alone_Libraries,
+            Library_Rebuilt       => Library_Rebuilt);
+      end if;
 
-               if Osint.Number_Of_Files = 1 then
-                  if Verbose_Mode then
-                     Write_Str ("Adding gnatmake switches for """);
-                     Write_Str (Main_Unit_File_Name);
-                     Write_Line (""".");
-                  end if;
+      if List_Dependencies then
+         if First_Compiled_File /= No_File then
+            Inform
+              (First_Compiled_File,
+               "must be recompiled. Can't generate dependence list.");
+         else
+            List_Depend;
+         end if;
 
-                  Add_Switches
-                    (Project_Node_Tree                => Project_Node_Tree,
-                     Env                              => Root_Environment,
-                     File_Name                        => Main_Unit_File_Name,
-                     Index                            => Main_Index,
-                     The_Package                      => Builder_Package,
-                     Program                          => None,
-                     Unknown_Switches_To_The_Compiler =>
-                       Global_Compilation_Array = No_Array_Element);
+      elsif First_Compiled_File = No_File
+        and then not Do_Bind_Step
+        and then not Quiet_Output
+        and then not Library_Rebuilt
+        and then Osint.Number_Of_Files = 1
+      then
+         Inform (Msg => "objects up to date.");
 
-               else
-                  --  If there are several mains, we always get the general
-                  --  gnatmake switches (if any).
+      elsif Do_Not_Execute
+        and then First_Compiled_File /= No_File
+      then
+         Write_Name (First_Compiled_File);
+         Write_Eol;
+      end if;
 
-                  --  Warn the user, if necessary, so that he is not surprised
-                  --  that specific switches are not taken into account.
+      --  Stop after compile step if any of:
 
-                  declare
-                     Defaults : constant Variable_Value :=
-                                  Prj.Util.Value_Of
-                                    (Name                    => Name_Ada,
-                                     Index                   => 0,
-                                     Attribute_Or_Array_Name =>
-                                       Name_Default_Switches,
-                                     In_Package              =>
-                                       Builder_Package,
-                                     Shared            => Project_Tree.Shared);
-
-                     Switches : constant Array_Element_Id :=
-                                  Prj.Util.Value_Of
-                                    (Name      => Name_Switches,
-                                     In_Arrays =>
-                                       Project_Tree.Shared.Packages.Table
-                                         (Builder_Package).Decl.Arrays,
-                                     Shared    => Project_Tree.Shared);
-
-                     Other_Switches : constant Variable_Value :=
-                                        Prj.Util.Value_Of
-                                          (Name        => All_Other_Names,
-                                           Index       => 0,
-                                           Attribute_Or_Array_Name
-                                                       => Name_Switches,
-                                           In_Package  => Builder_Package,
-                                           Shared      => Project_Tree.Shared);
+      --    1) -n (Do_Not_Execute) specified
 
-                  begin
-                     if Other_Switches /= Nil_Variable_Value then
-                        if not Quiet_Output
-                          and then Switches /= No_Array_Element
-                          and then Project_Tree.Shared.Array_Elements.Table
-                                     (Switches).Next /= No_Array_Element
-                        then
-                           Write_Line
-                             ("Warning: using Builder'Switches(others), "
-                              & "as there are several mains");
-                        end if;
+      --    2) -M (List_Dependencies) specified (also sets
+      --       Do_Not_Execute above, so this is probably superfluous).
 
-                        Add_Switches
-                          (Project_Node_Tree              => Project_Node_Tree,
-                           Env                            => Root_Environment,
-                           File_Name                        => " ",
-                           Index                            => 0,
-                           The_Package                      => Builder_Package,
-                           Program                          => None,
-                           Unknown_Switches_To_The_Compiler => False);
-
-                     elsif Defaults /= Nil_Variable_Value then
-                        if not Quiet_Output
-                          and then Switches /= No_Array_Element
-                        then
-                           Write_Line
-                             ("Warning: using Builder'Default_Switches"
-                              & "(""Ada""), as there are several mains");
-                        end if;
+      --    3) -c (Compile_Only) specified, but not -b (Bind_Only)
 
-                        Add_Switches
-                          (Project_Node_Tree => Project_Node_Tree,
-                           Env               => Root_Environment,
-                           File_Name   => " ",
-                           Index       => 0,
-                           The_Package => Builder_Package,
-                           Program     => None);
+      --    4) Made unit cannot be a main unit
 
-                     elsif not Quiet_Output
-                       and then Switches /= No_Array_Element
-                     then
-                        Write_Line
-                          ("Warning: using no switches from package "
-                           & "Builder, as there are several mains");
-                     end if;
-                  end;
-               end if;
+      if ((Do_Not_Execute
+           or List_Dependencies
+           or not Do_Bind_Step
+           or not Is_Main_Unit)
+          and then not No_Main_Subprogram
+          and then not Build_Bind_And_Link_Full_Project)
+        or else Unique_Compile
+      then
+         Stop_Compile := True;
+         return;
+      end if;
 
-               --  Take into account attribute Global_Compilation_Switches
-               --  ("Ada").
+      --  If the objects were up-to-date check if the executable file
+      --  is also up-to-date. For now always bind and link on the JVM
+      --  since there is currently no simple way to check whether
+      --  objects are up-to-date.
 
-               declare
-                  Index : Name_Id;
-                  List  : String_List_Id;
-                  Elem  : String_Element;
+      if Targparm.VM_Target /= JVM_Target
+        and then First_Compiled_File = No_File
+      then
+         Executable_Stamp := File_Stamp (Executable);
 
-               begin
-                  while Global_Compilation_Array /= No_Array_Element loop
-                     Global_Compilation_Elem :=
-                       Project_Tree.Shared.Array_Elements.Table
-                         (Global_Compilation_Array);
+         if not Executable_Obsolete then
+            Executable_Obsolete :=
+              Youngest_Obj_Stamp > Executable_Stamp;
+         end if;
 
-                     Get_Name_String (Global_Compilation_Elem.Index);
-                     To_Lower (Name_Buffer (1 .. Name_Len));
-                     Index := Name_Find;
+         if not Executable_Obsolete then
+            for Index in reverse 1 .. Dependencies.Last loop
+               if Is_In_Obsoleted
+                 (Dependencies.Table (Index).Depends_On)
+               then
+                  Enter_Into_Obsoleted
+                    (Dependencies.Table (Index).This);
+               end if;
+            end loop;
 
-                     if Index = Name_Ada then
-                        Global_Compilation_Switches :=
-                          Global_Compilation_Elem.Value;
+            Executable_Obsolete := Is_In_Obsoleted (Main_Source_File);
+            Dependencies.Init;
+         end if;
 
-                        if Global_Compilation_Switches /= Nil_Variable_Value
-                          and then not Global_Compilation_Switches.Default
-                        then
-                           --  We have found attribute
-                           --  Global_Compilation_Switches ("Ada"): put the
-                           --  switches in the appropriate table.
-
-                           List := Global_Compilation_Switches.Values;
-
-                           while List /= Nil_String loop
-                              Elem :=
-                                Project_Tree.Shared.String_Elements.Table
-                                  (List);
-
-                              if Elem.Value /= No_Name then
-                                 Add_Switch
-                                   (Get_Name_String (Elem.Value),
-                                    Compiler,
-                                    And_Save => False);
-                              end if;
+         if not Executable_Obsolete then
 
-                              List := Elem.Next;
-                           end loop;
+            --  If no Ada object files obsolete the executable, check
+            --  for younger or missing linker files.
 
-                           exit;
-                        end if;
-                     end if;
+            Check_Linker_Options
+              (Executable_Stamp,
+               Youngest_Obj_File,
+               Youngest_Obj_Stamp);
 
-                     Global_Compilation_Array := Global_Compilation_Elem.Next;
-                  end loop;
-               end;
-            end if;
+            Executable_Obsolete := Youngest_Obj_File /= No_File;
+         end if;
 
-            Osint.Add_Default_Search_Dirs;
+         --  Check if any library file is more recent than the
+         --  executable: there may be an externally built library
+         --  file that has been modified.
 
-            --  Record the current last switch index for table Binder_Switches
-            --  and Linker_Switches, so that these tables may be reset before
-            --  for each main, before adding switches from the project file
-            --  and from the command line.
+         if not Executable_Obsolete
+           and then Main_Project /= No_Project
+         then
+            declare
+               Proj1 : Project_List;
 
-            Last_Binder_Switch := Binder_Switches.Last;
-            Last_Linker_Switch := Linker_Switches.Last;
-
-            Check_Steps;
+            begin
+               Proj1 := Project_Tree.Projects;
+               while Proj1 /= null loop
+                  if Proj1.Project.Library
+                    and then
+                      Proj1.Project.Library_TS > Executable_Stamp
+                  then
+                     Executable_Obsolete := True;
+                     Youngest_Obj_Stamp := Proj1.Project.Library_TS;
+                     Name_Len := 0;
+                     Add_Str_To_Name_Buffer ("library ");
+                     Add_Str_To_Name_Buffer
+                       (Get_Name_String (Proj1.Project.Library_Name));
+                     Youngest_Obj_File := Name_Find;
+                     exit;
+                  end if;
 
-            --  Add binder switches from the project file for the first main
+                  Proj1 := Proj1.Next;
+               end loop;
+            end;
+         end if;
 
-            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);
-                  Write_Line (""".");
-               end if;
+         --  Return if the executable is up to date and otherwise
+         --  motivate the relink/rebind.
 
-               Add_Switches
-                 (Project_Node_Tree => Project_Node_Tree,
-                  Env               => Root_Environment,
-                  File_Name         => Main_Unit_File_Name,
-                  Index             => Main_Index,
-                  The_Package       => Binder_Package,
-                  Program           => Binder);
+         if not Executable_Obsolete then
+            if not Quiet_Output then
+               Inform (Executable, "up to date.");
             end if;
 
-            --  Add linker switches from the project file for the first main
-
-            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);
-                  Write_Line (""".");
-               end if;
+            Stop_Compile := True;
+            return;
+         end if;
 
-               Add_Switches
-                 (Project_Node_Tree => Project_Node_Tree,
-                  Env               => Root_Environment,
-                  File_Name         => Main_Unit_File_Name,
-                  Index             => Main_Index,
-                  The_Package       => Linker_Package,
-                  Program           => Linker);
+         if Executable_Stamp (1) = ' ' then
+            if not No_Main_Subprogram then
+               Verbose_Msg (Executable, "missing.", Prefix => "  ");
             end if;
-         end;
-      end if;
 
-      --  The combination of -f -u and one or several mains on the command line
-      --  implies -a.
+         elsif Youngest_Obj_Stamp (1) = ' ' then
+            Verbose_Msg
+              (Youngest_Obj_File, "missing.",  Prefix => "  ");
 
-      if Force_Compilations
-        and then Unique_Compile
-        and then not Unique_Compile_All_Projects
-        and then Main_On_Command_Line
-      then
-         Must_Compile := True;
-      end if;
+         elsif Youngest_Obj_Stamp > Executable_Stamp then
+            Verbose_Msg
+              (Youngest_Obj_File,
+               "(" & String (Youngest_Obj_Stamp) & ") newer than",
+               Executable,
+               "(" & String (Executable_Stamp) & ")");
 
-      if Main_Project /= No_Project
-        and then not Must_Compile
-        and then Main_Project.Externally_Built
-      then
-         Make_Failed
-           ("nothing to do for a main project that is externally built");
-      end if;
+         else
+            Verbose_Msg
+              (Executable, "needs to be rebuilt", Prefix => "  ");
 
-      --  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.
+         end if;
+      end if;
+   end Compilation_Phase;
 
-      begin
-         Targparm.Get_Target_Parameters;
-      exception
-         when Unrecoverable_Error =>
-            Make_Failed ("*** make failed.");
-      end;
+   ------------------------------
+   -- Compute_Builder_Switches --
+   ------------------------------
 
-      --  Special processing for VM targets
+   procedure Compute_Builder_Switches
+     (Project_Node_Tree   : Project_Node_Tree_Ref;
+      Root_Environment    : in out Prj.Tree.Environment;
+      Main_Unit_File_Name : String;
+      Main_Index          : Int := 0)
+   is
+      Builder_Package : constant Prj.Package_Id :=
+                           Prj.Util.Value_Of
+                             (Name        => Name_Builder,
+                              In_Packages => Main_Project.Decl.Packages,
+                              Shared      => Project_Tree.Shared);
 
-      if Targparm.VM_Target /= No_VM then
+      Global_Compilation_Array    : Array_Element_Id;
+      Global_Compilation_Elem     : Array_Element;
+      Global_Compilation_Switches : Variable_Value;
 
-         --  Set proper processing commands
+      Default_Switches_Array : Array_Id;
 
-         case Targparm.VM_Target is
-            when Targparm.JVM_Target =>
+   begin
 
-               --  Do not check for an object file (".o") when compiling to
-               --  JVM machine since ".class" files are generated instead.
+      --  If there is a package Builder in the main project file, add
+      --  the switches from it.
 
-               Check_Object_Consistency := False;
-               Gcc := new String'("jvm-gnatcompile");
+      if Builder_Package /= No_Package then
+         Global_Compilation_Array := Prj.Util.Value_Of
+           (Name      => Name_Global_Compilation_Switches,
+            In_Arrays => Project_Tree.Shared.Packages.Table
+              (Builder_Package).Decl.Arrays,
+            Shared    => Project_Tree.Shared);
 
-            when Targparm.CLI_Target =>
-               Gcc := new String'("dotnet-gnatcompile");
+         Default_Switches_Array :=
+           Project_Tree.Shared.Packages.Table (Builder_Package).Decl.Arrays;
 
-            when Targparm.No_VM =>
-               raise Program_Error;
-         end case;
-      end if;
+         while Default_Switches_Array /= No_Array and then
+           Project_Tree.Shared.Arrays.Table (Default_Switches_Array).Name
+           /= Name_Default_Switches
+         loop
+            Default_Switches_Array := Project_Tree.Shared.Arrays.Table
+              (Default_Switches_Array).Next;
+         end loop;
 
-      Display_Commands (not Quiet_Output);
+         if Global_Compilation_Array /= No_Array_Element and then
+           Default_Switches_Array /= No_Array
+         then
+            Errutil.Error_Msg
+              ("Default_Switches forbidden in presence of " &
+               "Global_Compilation_Switches. Use Switches instead.",
+               Project_Tree.Shared.Arrays.Table
+                 (Default_Switches_Array).Location);
+            Make_Failed ("*** illegal combination of Builder attributes");
+         end if;
 
-      Check_Steps;
+         --  If there is only one main, we attempt to get the gnatmake
+         --  switches for this main (if any). If there are no specific
+         --  switch for this particular main, get the general gnatmake
+         --  switches (if any).
 
-      if Main_Project /= No_Project then
+         if Osint.Number_Of_Files = 1 then
+            if Verbose_Mode then
+               Write_Str ("Adding gnatmake switches for """);
+               Write_Str (Main_Unit_File_Name);
+               Write_Line (""".");
+            end if;
 
-         --  For all library project, if the library file does not exist, put
-         --  all the project sources in the queue, and flag the project so that
-         --  the library is generated.
+            Add_Switches
+              (Project_Node_Tree                => Project_Node_Tree,
+               Env                              => Root_Environment,
+               File_Name                        => Main_Unit_File_Name,
+               Index                            => Main_Index,
+               The_Package                      => Builder_Package,
+               Program                          => None,
+               Unknown_Switches_To_The_Compiler =>
+                 Global_Compilation_Array = No_Array_Element);
 
-         if not Unique_Compile
-           and then MLib.Tgt.Support_For_Libraries /= Prj.None
-         then
-            declare
-               Proj : Project_List;
+         else
+            --  If there are several mains, we always get the general
+            --  gnatmake switches (if any).
 
-            begin
-               Proj := Project_Tree.Projects;
-               while Proj /= null loop
-                  if Proj.Project.Library then
-                     Proj.Project.Need_To_Build_Lib :=
-                       not MLib.Tgt.Library_Exists_For
-                         (Proj.Project, Project_Tree)
-                       and then not Proj.Project.Externally_Built;
+            --  Warn the user, if necessary, so that he is not surprised
+            --  that specific switches are not taken into account.
 
-                     if Proj.Project.Need_To_Build_Lib then
+            declare
+               Defaults : constant Variable_Value :=
+                 Prj.Util.Value_Of
+                   (Name                    => Name_Ada,
+                    Index                   => 0,
+                    Attribute_Or_Array_Name =>
+                      Name_Default_Switches,
+                    In_Package              =>
+                      Builder_Package,
+                    Shared            => Project_Tree.Shared);
+
+               Switches : constant Array_Element_Id :=
+                 Prj.Util.Value_Of
+                   (Name      => Name_Switches,
+                    In_Arrays =>
+                      Project_Tree.Shared.Packages.Table
+                        (Builder_Package).Decl.Arrays,
+                    Shared    => Project_Tree.Shared);
 
-                        --  If there is no object directory, then it will be
-                        --  impossible to build the library. So fail
-                        --  immediately.
+               Other_Switches : constant Variable_Value :=
+                 Prj.Util.Value_Of
+                   (Name        => All_Other_Names,
+                    Index       => 0,
+                    Attribute_Or_Array_Name
+                    => Name_Switches,
+                    In_Package  => Builder_Package,
+                    Shared      => Project_Tree.Shared);
 
-                        if
-                          Proj.Project.Object_Directory = No_Path_Information
-                        then
-                           Make_Failed
-                             ("no object files to build library for project """
-                              & Get_Name_String (Proj.Project.Name)
-                              & """");
-                           Proj.Project.Need_To_Build_Lib := False;
+            begin
+               if Other_Switches /= Nil_Variable_Value then
+                  if not Quiet_Output
+                    and then Switches /= No_Array_Element
+                    and then Project_Tree.Shared.Array_Elements.Table
+                      (Switches).Next /= No_Array_Element
+                  then
+                     Write_Line
+                       ("Warning: using Builder'Switches(others), "
+                        & "as there are several mains");
+                  end if;
 
-                        else
-                           if Verbose_Mode then
-                              Write_Str
-                                ("Library file does not exist for project """);
-                              Write_Str (Get_Name_String (Proj.Project.Name));
-                              Write_Line ("""");
-                           end if;
+                  Add_Switches
+                    (Project_Node_Tree              => Project_Node_Tree,
+                     Env                            => Root_Environment,
+                     File_Name                        => " ",
+                     Index                            => 0,
+                     The_Package                      => Builder_Package,
+                     Program                          => None,
+                     Unknown_Switches_To_The_Compiler => False);
 
-                           Insert_Project_Sources
-                             (The_Project  => Proj.Project,
-                              All_Projects => False,
-                              Into_Q       => True);
-                        end if;
-                     end if;
+               elsif Defaults /= Nil_Variable_Value then
+                  if not Quiet_Output
+                    and then Switches /= No_Array_Element
+                  then
+                     Write_Line
+                       ("Warning: using Builder'Default_Switches"
+                        & "(""Ada""), as there are several mains");
                   end if;
 
-                  Proj := Proj.Next;
-               end loop;
+                  Add_Switches
+                    (Project_Node_Tree => Project_Node_Tree,
+                     Env               => Root_Environment,
+                     File_Name   => " ",
+                     Index       => 0,
+                     The_Package => Builder_Package,
+                     Program     => None);
+
+               elsif not Quiet_Output
+                 and then Switches /= No_Array_Element
+               then
+                  Write_Line
+                    ("Warning: using no switches from package "
+                     & "Builder, as there are several mains");
+               end if;
             end;
          end if;
 
-         --  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
-               declare
-                  Exec_File_Name : constant String :=
-                                     Saved_Linker_Switches.Table (J + 1).all;
-
-               begin
-                  if not Is_Absolute_Path (Exec_File_Name) then
-                     Get_Name_String
-                       (Main_Project.Exec_Directory.Display_Name);
-                     Add_Str_To_Name_Buffer (Exec_File_Name);
-                     Saved_Linker_Switches.Table (J + 1) :=
-                       new String'(Name_Buffer (1 .. Name_Len));
-                  end if;
-               end;
-
-               exit;
-            end if;
-         end loop;
-
-         --  If we are using a project file, for relative paths we add the
-         --  current working directory for any relative path on the command
-         --  line and the project directory, for any relative path in the
-         --  project file.
+         --  Take into account attribute Global_Compilation_Switches
+         --  ("Ada").
 
          declare
-            Dir_Path : constant String :=
-                         Get_Name_String (Main_Project.Directory.Display_Name);
+            Index : Name_Id;
+            List  : String_List_Id;
+            Elem  : String_Element;
+
          begin
-            for J in 1 .. Binder_Switches.Last loop
-               Test_If_Relative_Path
-                 (Binder_Switches.Table (J),
-                  Do_Fail => Make_Failed'Access,
-                  Parent => Dir_Path, Including_L_Switch => False);
-            end loop;
+            while Global_Compilation_Array /= No_Array_Element loop
+               Global_Compilation_Elem :=
+                 Project_Tree.Shared.Array_Elements.Table
+                   (Global_Compilation_Array);
 
-            for J in 1 .. Saved_Binder_Switches.Last loop
-               Test_If_Relative_Path
-                 (Saved_Binder_Switches.Table (J),
-                  Do_Fail => Make_Failed'Access,
-                  Parent => Current_Work_Dir.all, Including_L_Switch => False);
-            end loop;
+               Get_Name_String (Global_Compilation_Elem.Index);
+               To_Lower (Name_Buffer (1 .. Name_Len));
+               Index := Name_Find;
 
-            for J in 1 .. Linker_Switches.Last loop
-               Test_If_Relative_Path
-                 (Linker_Switches.Table (J), Parent => Dir_Path,
-                  Do_Fail => Make_Failed'Access);
-            end loop;
+               if Index = Name_Ada then
+                  Global_Compilation_Switches := Global_Compilation_Elem.Value;
 
-            for J in 1 .. Saved_Linker_Switches.Last loop
-               Test_If_Relative_Path
-                 (Saved_Linker_Switches.Table (J),
-                  Do_Fail => Make_Failed'Access,
-                  Parent => Current_Work_Dir.all);
-            end loop;
+                  if Global_Compilation_Switches /= Nil_Variable_Value
+                    and then not Global_Compilation_Switches.Default
+                  then
+                     --  We have found attribute
+                     --  Global_Compilation_Switches ("Ada"): put the
+                     --  switches in the appropriate table.
+
+                     List := Global_Compilation_Switches.Values;
+
+                     while List /= Nil_String loop
+                        Elem :=
+                          Project_Tree.Shared.String_Elements.Table
+                            (List);
+
+                        if Elem.Value /= No_Name then
+                           Add_Switch
+                             (Get_Name_String (Elem.Value),
+                              Compiler,
+                              And_Save => False);
+                        end if;
 
-            for J in 1 .. Gcc_Switches.Last loop
-               Test_If_Relative_Path
-                 (Gcc_Switches.Table (J),
-                  Do_Fail => Make_Failed'Access,
-                  Parent               => Dir_Path,
-                  Including_Non_Switch => False);
-            end loop;
+                        List := Elem.Next;
+                     end loop;
+
+                     exit;
+                  end if;
+               end if;
 
-            for J in 1 .. Saved_Gcc_Switches.Last loop
-               Test_If_Relative_Path
-                 (Saved_Gcc_Switches.Table (J),
-                  Parent               => Current_Work_Dir.all,
-                  Do_Fail => Make_Failed'Access,
-                  Including_Non_Switch => False);
+               Global_Compilation_Array := Global_Compilation_Elem.Next;
             end loop;
          end;
       end if;
+   end Compute_Builder_Switches;
 
-      --  We now put in the Binder_Switches and Linker_Switches tables, the
-      --  binder and linker switches of the command line that have been put in
-      --  the Saved_ tables. If a project file was used, then the command line
-      --  switches will follow the project file switches.
+   ----------------------------------------
+   -- Resolve_Relative_Names_In_Switches --
+   ----------------------------------------
 
-      for J in 1 .. Saved_Binder_Switches.Last loop
-         Add_Switch
-           (Saved_Binder_Switches.Table (J),
-            Binder,
-            And_Save => False);
-      end loop;
+   procedure Resolve_Relative_Names_In_Switches (Current_Work_Dir : String) is
+   begin
+      --  If a relative path output file has been specified, we add the
+      --  exec directory.
 
-      for J in 1 .. Saved_Linker_Switches.Last loop
-         Add_Switch
-           (Saved_Linker_Switches.Table (J),
-            Linker,
-            And_Save => False);
+      for J in reverse 1 .. Saved_Linker_Switches.Last - 1 loop
+         if Saved_Linker_Switches.Table (J).all = Output_Flag.all then
+            declare
+               Exec_File_Name : constant String :=
+                 Saved_Linker_Switches.Table (J + 1).all;
+
+            begin
+               if not Is_Absolute_Path (Exec_File_Name) then
+                  Get_Name_String
+                    (Main_Project.Exec_Directory.Display_Name);
+                  Add_Str_To_Name_Buffer (Exec_File_Name);
+                  Saved_Linker_Switches.Table (J + 1) :=
+                    new String'(Name_Buffer (1 .. Name_Len));
+               end if;
+            end;
+
+            exit;
+         end if;
       end loop;
 
-      --  If no project file is used, we just put the gcc switches
-      --  from the command line in the Gcc_Switches table.
+      --  If we are using a project file, for relative paths we add the
+      --  current working directory for any relative path on the command
+      --  line and the project directory, for any relative path in the
+      --  project file.
 
-      if Main_Project = No_Project then
-         for J in 1 .. Saved_Gcc_Switches.Last loop
-            Add_Switch
-              (Saved_Gcc_Switches.Table (J), Compiler, And_Save => False);
+      declare
+         Dir_Path : constant String :=
+           Get_Name_String (Main_Project.Directory.Display_Name);
+      begin
+         for J in 1 .. Binder_Switches.Last loop
+            Test_If_Relative_Path
+              (Binder_Switches.Table (J),
+               Do_Fail => Make_Failed'Access,
+               Parent => Dir_Path, Including_L_Switch => False);
          end loop;
 
-      else
-         --  If there is a project, put the command line gcc switches in the
-         --  variable The_Saved_Gcc_Switches. They are going to be used later
-         --  in procedure Compile_Sources.
+         for J in 1 .. Saved_Binder_Switches.Last loop
+            Test_If_Relative_Path
+              (Saved_Binder_Switches.Table (J),
+               Do_Fail => Make_Failed'Access,
+               Parent => Current_Work_Dir,
+               Including_L_Switch => False);
+         end loop;
 
-         The_Saved_Gcc_Switches :=
-           new Argument_List (1 .. Saved_Gcc_Switches.Last + 1);
+         for J in 1 .. Linker_Switches.Last loop
+            Test_If_Relative_Path
+              (Linker_Switches.Table (J), Parent => Dir_Path,
+               Do_Fail => Make_Failed'Access);
+         end loop;
+
+         for J in 1 .. Saved_Linker_Switches.Last loop
+            Test_If_Relative_Path
+              (Saved_Linker_Switches.Table (J),
+               Do_Fail => Make_Failed'Access,
+               Parent => Current_Work_Dir);
+         end loop;
+
+         for J in 1 .. Gcc_Switches.Last loop
+            Test_If_Relative_Path
+              (Gcc_Switches.Table (J),
+               Do_Fail => Make_Failed'Access,
+               Parent               => Dir_Path,
+               Including_Non_Switch => False);
+         end loop;
 
          for J in 1 .. Saved_Gcc_Switches.Last loop
-            The_Saved_Gcc_Switches (J) := Saved_Gcc_Switches.Table (J);
+            Test_If_Relative_Path
+              (Saved_Gcc_Switches.Table (J),
+               Parent               => Current_Work_Dir,
+               Do_Fail => Make_Failed'Access,
+               Including_Non_Switch => False);
          end loop;
+      end;
+   end Resolve_Relative_Names_In_Switches;
 
-         --  We never use gnat.adc when a project file is used
+   -----------------------------------
+   -- Queue_Library_Project_Sources --
+   -----------------------------------
 
-         The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) := No_gnat_adc;
-      end if;
+   procedure Queue_Library_Project_Sources is
+   begin
+      if not Unique_Compile
+        and then MLib.Tgt.Support_For_Libraries /= Prj.None
+      then
+         declare
+            Proj : Project_List;
 
-      --  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.
+         begin
+            Proj := Project_Tree.Projects;
+            while Proj /= null loop
+               if Proj.Project.Library then
+                  Proj.Project.Need_To_Build_Lib :=
+                    not MLib.Tgt.Library_Exists_For
+                      (Proj.Project, Project_Tree)
+                    and then not Proj.Project.Externally_Built;
+
+                  if Proj.Project.Need_To_Build_Lib then
+
+                     --  If there is no object directory, then it will be
+                     --  impossible to build the library. So fail
+                     --  immediately.
+
+                     if Proj.Project.Object_Directory =
+                       No_Path_Information
+                     then
+                        Make_Failed
+                          ("no object files to build library for"
+                           & " project """
+                           & Get_Name_String (Proj.Project.Name)
+                           & """");
+                        Proj.Project.Need_To_Build_Lib := False;
 
-      if Saved_Gcc /= null then
-         Gcc := Saved_Gcc;
-      end if;
+                     else
+                        if Verbose_Mode then
+                           Write_Str
+                             ("Library file does not exist for "
+                              & "project """);
+                           Write_Str
+                             (Get_Name_String (Proj.Project.Name));
+                           Write_Line ("""");
+                        end if;
 
-      if Saved_Gnatbind /= null then
-         Gnatbind := Saved_Gnatbind;
-      end if;
+                        Insert_Project_Sources
+                          (The_Project  => Proj.Project,
+                           All_Projects => False,
+                           Into_Q       => True);
+                     end if;
+                  end if;
+               end if;
 
-      if Saved_Gnatlink /= null then
-         Gnatlink := Saved_Gnatlink;
+               Proj := Proj.Next;
+            end loop;
+         end;
       end if;
+   end Queue_Library_Project_Sources;
 
-      Gcc_Path       := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
-      Gnatbind_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
-      Gnatlink_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
+   ------------------------
+   -- Compute_Executable --
+   ------------------------
 
-      --  If we have specified -j switch both from the project file
-      --  and on the command line, the one from the command line takes
-      --  precedence.
+   procedure Compute_Executable
+     (Main_Source_File   : File_Name_Type;
+      Executable         : out File_Name_Type;
+      Non_Std_Executable : out Boolean)
+   is
+   begin
+      Executable          := No_File;
+      Non_Std_Executable  :=
+        Targparm.Executable_Extension_On_Target /= No_Name;
 
-      if Saved_Maximum_Processes = 0 then
-         Saved_Maximum_Processes := Maximum_Processes;
-      end if;
+      --  Look inside the linker switches to see if the name of the final
+      --  executable program was specified.
 
-      if Debug.Debug_Flag_M then
-         Write_Line ("Maximum number of simultaneous compilations =" &
-                     Saved_Maximum_Processes'Img);
-      end if;
+      for J in reverse Linker_Switches.First .. Linker_Switches.Last loop
+         if Linker_Switches.Table (J).all = Output_Flag.all then
+            pragma Assert (J < Linker_Switches.Last);
 
-      --  Allocate as many temporary mapping file names as the maximum number
-      --  of compilations processed, for each possible project.
+            --  We cannot specify a single executable for several main
+            --  subprograms
 
-      declare
-         Data : Project_Compilation_Access;
-         Proj : Project_List := Project_Tree.Projects;
-      begin
-         while Proj /= null loop
-            Data := new Project_Compilation_Data'
-              (Mapping_File_Names        => new Temp_Path_Names
-                                              (1 .. Saved_Maximum_Processes),
-               Last_Mapping_File_Names   => 0,
-               Free_Mapping_File_Indexes => new Free_File_Indexes
-                                              (1 .. Saved_Maximum_Processes),
-               Last_Free_Indexes         => 0);
+            if Osint.Number_Of_Files > 1 then
+               Fail ("cannot specify a single executable for several mains");
+            end if;
 
-            Project_Compilation_Htable.Set
-              (Project_Compilation, Proj.Project, Data);
-            Proj := Proj.Next;
-         end loop;
-
-         Data := new Project_Compilation_Data'
-           (Mapping_File_Names        => new Temp_Path_Names
-                                           (1 .. Saved_Maximum_Processes),
-            Last_Mapping_File_Names   => 0,
-            Free_Mapping_File_Indexes => new Free_File_Indexes
-                                           (1 .. Saved_Maximum_Processes),
-            Last_Free_Indexes         => 0);
+            Name_Len := 0;
+            Add_Str_To_Name_Buffer (Linker_Switches.Table (J + 1).all);
+            Executable := Name_Enter;
 
-         Project_Compilation_Htable.Set
-           (Project_Compilation, No_Project, Data);
-      end;
+            Verbose_Msg (Executable, "final executable");
+         end if;
+      end loop;
 
-      Bad_Compilation.Init;
+      --  If the name of the final executable program was not specified then
+      --  construct it from the main input file.
 
-      --  If project files are used, create the mapping of all the sources, so
-      --  that the correct paths will be found. Otherwise, if there is a file
-      --  which is not a source with the same name in a source directory this
-      --  file may be incorrectly found.
+      if Executable = No_File then
+         if Main_Project = No_Project then
+            Executable := Executable_Name (Strip_Suffix (Main_Source_File));
 
-      if Main_Project /= No_Project then
-         Prj.Env.Create_Mapping (Project_Tree);
+         else
+            --  If we are using a project file, we attempt to remove the
+            --  body (or spec) termination of the main subprogram. We find
+            --  it the naming scheme of the project file. This avoids
+            --  generating an executable "main.2" for a main subprogram
+            --  "main.2.ada", when the body termination is ".2.ada".
+
+            Executable :=
+              Prj.Util.Executable_Of
+                (Main_Project, Project_Tree.Shared,
+                 Main_Source_File, Main_Index);
+         end if;
       end if;
 
-      Current_Main_Index := Main_Index;
+      if Main_Project /= No_Project
+        and then Main_Project.Exec_Directory /= No_Path_Information
+      then
+         declare
+            Exec_File_Name : constant String := Get_Name_String (Executable);
+         begin
+            if not Is_Absolute_Path (Exec_File_Name) then
+               Get_Name_String (Main_Project.Exec_Directory.Display_Name);
+               Add_Str_To_Name_Buffer (Exec_File_Name);
+               Executable := Name_Find;
+            end if;
+
+            Non_Std_Executable := True;
+         end;
+      end if;
+   end Compute_Executable;
 
-      --  Here is where the make process is started
+   -------------------------------
+   -- Compute_Switches_For_Main --
+   -------------------------------
 
-      --  We do the same process for each main
+   procedure Compute_Switches_For_Main
+     (Main_Source_File  : in out File_Name_Type;
+      Main_Index        : Int;
+      Project_Node_Tree : Project_Node_Tree_Ref;
+      Root_Environment  : in out Prj.Tree.Environment;
+      Compute_Builder   : Boolean;
+      Current_Work_Dir  : String)
+   is
+   begin
+      if Main_Project /= No_Project then
+         declare
+            Main_Source_File_Name : constant String :=
+              Get_Name_String (Main_Source_File);
 
-      Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop
+            Main_Unit_File_Name   : constant String :=
+              Prj.Env.File_Name_Of_Library_Unit_Body
+                (Name    => Main_Source_File_Name,
+                 Project => Main_Project,
+                 In_Tree => Project_Tree,
+                 Main_Project_Only =>
+                 not Unique_Compile);
 
-         --  First, find the executable name and path
+            The_Packages : constant Package_Id := Main_Project.Decl.Packages;
 
-         Executable          := No_File;
-         Executable_Obsolete := False;
-         Non_Std_Executable  :=
-           Targparm.Executable_Extension_On_Target /= No_Name;
+            Binder_Package : constant Prj.Package_Id :=
+              Prj.Util.Value_Of
+                (Name        => Name_Binder,
+                 In_Packages => The_Packages,
+                 Shared      => Project_Tree.Shared);
 
-         --  Look inside the linker switches to see if the name of the final
-         --  executable program was specified.
+            Linker_Package : constant Prj.Package_Id :=
+              Prj.Util.Value_Of
+                (Name        => Name_Linker,
+                 In_Packages => The_Packages,
+                 Shared      => Project_Tree.Shared);
 
-         for J in reverse Linker_Switches.First .. Linker_Switches.Last loop
-            if Linker_Switches.Table (J).all = Output_Flag.all then
-               pragma Assert (J < Linker_Switches.Last);
+         begin
+            --  We fail if we cannot find the main source file
 
-               --  We cannot specify a single executable for several main
-               --  subprograms
+            if Main_Unit_File_Name = "" then
+               Make_Failed ('"' & Main_Source_File_Name
+                            & """ is not a unit of project "
+                            & Project_File_Name.all & ".");
+            end if;
 
-               if Osint.Number_Of_Files > 1 then
-                  Fail
-                    ("cannot specify a single executable for several mains");
-               end if;
+            --  Remove any directory information from the main source file
+            --  file name.
 
-               Name_Len := 0;
-               Add_Str_To_Name_Buffer (Linker_Switches.Table (J + 1).all);
-               Executable := Name_Enter;
+            declare
+               Pos : Natural := Main_Unit_File_Name'Last;
 
-               Verbose_Msg (Executable, "final executable");
-            end if;
-         end loop;
+            begin
+               loop
+                  exit when Pos < Main_Unit_File_Name'First
+                    or else Main_Unit_File_Name (Pos) = Directory_Separator;
+                  Pos := Pos - 1;
+               end loop;
 
-         --  If the name of the final executable program was not specified then
-         --  construct it from the main input file.
+               Name_Len := Main_Unit_File_Name'Last - Pos;
 
-         if Executable = No_File then
-            if Main_Project = No_Project then
-               Executable := Executable_Name (Strip_Suffix (Main_Source_File));
+               Name_Buffer (1 .. Name_Len) :=
+                 Main_Unit_File_Name (Pos + 1 .. Main_Unit_File_Name'Last);
 
-            else
-               --  If we are using a project file, we attempt to remove the
-               --  body (or spec) termination of the main subprogram. We find
-               --  it the naming scheme of the project file. This avoids
-               --  generating an executable "main.2" for a main subprogram
-               --  "main.2.ada", when the body termination is ".2.ada".
-
-               Executable :=
-                 Prj.Util.Executable_Of
-                   (Main_Project, Project_Tree.Shared,
-                    Main_Source_File, Main_Index);
-            end if;
-         end if;
+               Main_Source_File := Name_Find;
 
-         if Main_Project /= No_Project
-           and then Main_Project.Exec_Directory /= No_Path_Information
-         then
-            declare
-               Exec_File_Name : constant String :=
-                                  Get_Name_String (Executable);
+               --  We only output the main source file if there is only one
 
-            begin
-               if not Is_Absolute_Path (Exec_File_Name) then
-                  Get_Name_String (Main_Project.Exec_Directory.Display_Name);
-                  Add_Str_To_Name_Buffer (Exec_File_Name);
-                  Executable := Name_Find;
+               if Verbose_Mode and then Osint.Number_Of_Files = 1 then
+                  Write_Str ("Main source file: """);
+                  Write_Str (Main_Unit_File_Name
+                             (Pos + 1 .. Main_Unit_File_Name'Last));
+                  Write_Line (""".");
                end if;
-
-               Non_Std_Executable := True;
             end;
-         end if;
 
-         if Do_Compile_Step then
-            Recursive_Compilation_Step : declare
-               Args                : Argument_List (1 .. Gcc_Switches.Last);
+            if Compute_Builder then
+               Compute_Builder_Switches
+                 (Project_Node_Tree   => Project_Node_Tree,
+                  Root_Environment    => Root_Environment,
+                  Main_Unit_File_Name => Main_Unit_File_Name,
+                  Main_Index          => Main_Index);
 
-               First_Compiled_File : File_Name_Type;
-               Youngest_Obj_File   : File_Name_Type;
-               Youngest_Obj_Stamp  : Time_Stamp_Type;
+               Resolve_Relative_Names_In_Switches
+                 (Current_Work_Dir => Current_Work_Dir);
 
-               Executable_Stamp : Time_Stamp_Type;
-               --  Executable is the final executable program
-               --  ??? comment seems unrelated to declaration
+               --  Record the current last switch index for table
+               --  Binder_Switches and Linker_Switches, so that these tables
+               --  may be reset before each main, before adding switches from
+               --  the project file and from the command line.
 
-               Library_Rebuilt : Boolean := False;
+               Last_Binder_Switch := Binder_Switches.Last;
+               Last_Linker_Switch := Linker_Switches.Last;
 
-            begin
-               for J in 1 .. Gcc_Switches.Last loop
-                  Args (J) := Gcc_Switches.Table (J);
-               end loop;
+            else
+               --  Reset the tables Binder_Switches and Linker_Switches
+               Binder_Switches.Set_Last (Last_Binder_Switch);
+               Linker_Switches.Set_Last (Last_Linker_Switch);
+            end if;
 
-               Queue.Initialize
-                       (Main_Project /= No_Project and then
-                        One_Compilation_Per_Obj_Dir);
-
-               --  Now we invoke Compile_Sources for the current main
-
-               Compile_Sources
-                 (Main_Source           => Main_Source_File,
-                  Args                  => Args,
-                  First_Compiled_File   => First_Compiled_File,
-                  Most_Recent_Obj_File  => Youngest_Obj_File,
-                  Most_Recent_Obj_Stamp => Youngest_Obj_Stamp,
-                  Main_Unit             => Is_Main_Unit,
-                  Main_Index            => Current_Main_Index,
-                  Compilation_Failures  => Compilation_Failures,
-                  Check_Readonly_Files  => Check_Readonly_Files,
-                  Do_Not_Execute        => Do_Not_Execute,
-                  Force_Compilations    => Force_Compilations,
-                  In_Place_Mode         => In_Place_Mode,
-                  Keep_Going            => Keep_Going,
-                  Initialize_ALI_Data   => True,
-                  Max_Process           => Saved_Maximum_Processes);
+            --  We now deal with the binder and linker switches.
+            --  If no project file is used, there is nothing to do
+            --  because the binder and linker switches are the same
+            --  for all mains.
 
+            --  Add binder switches from the project file for the first main
+
+            if Do_Bind_Step and then Binder_Package /= No_Package then
                if Verbose_Mode then
-                  Write_Str ("End of compilation");
-                  Write_Eol;
+                  Write_Str ("Adding binder switches for """);
+                  Write_Str (Main_Unit_File_Name);
+                  Write_Line (""".");
                end if;
 
-               Total_Compilation_Failures :=
-                 Total_Compilation_Failures + Compilation_Failures;
+               Add_Switches
+                 (Project_Node_Tree => Project_Node_Tree,
+                  Env               => Root_Environment,
+                  File_Name         => Main_Unit_File_Name,
+                  Index             => Main_Index,
+                  The_Package       => Binder_Package,
+                  Program           => Binder);
+            end if;
 
-               if Total_Compilation_Failures /= 0 then
-                  if Keep_Going then
-                     goto Next_Main;
+            --  Add linker switches from the project file for the first main
 
-                  else
-                     List_Bad_Compilations;
-                     Report_Compilation_Failed;
-                  end if;
+            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);
+                  Write_Line (""".");
                end if;
 
-               --  Regenerate libraries, if there are any and if object files
-               --  have been regenerated.
-
-               if Main_Project /= No_Project
-                 and then MLib.Tgt.Support_For_Libraries /= Prj.None
-                 and then (Do_Bind_Step
-                             or Unique_Compile_All_Projects
-                             or not Compile_Only)
-                 and then (Do_Link_Step or else N_File = Osint.Number_Of_Files)
-               then
-                  Library_Projs.Init;
-
-                  declare
-                     Depth   : Natural;
-                     Current : Natural;
-                     Proj1   : Project_List;
-
-                     procedure Add_To_Library_Projs (Proj : Project_Id);
-                     --  Add project Project to table Library_Projs in
-                     --  decreasing depth order.
+               Add_Switches
+                 (Project_Node_Tree => Project_Node_Tree,
+                  Env               => Root_Environment,
+                  File_Name         => Main_Unit_File_Name,
+                  Index             => Main_Index,
+                  The_Package       => Linker_Package,
+                  Program           => Linker);
+            end if;
 
-                     --------------------------
-                     -- Add_To_Library_Projs --
-                     --------------------------
+            --  As we are using a project file, for relative paths we add
+            --  the current working directory for any relative path on
+            --  the command line and the project directory, for any
+            --  relative path in the project file.
 
-                     procedure Add_To_Library_Projs (Proj : Project_Id) is
-                        Prj : Project_Id;
+            declare
+               Dir_Path : constant String :=
+                 Get_Name_String (Main_Project.Directory.Display_Name);
+            begin
+               for J in Last_Binder_Switch + 1 .. Binder_Switches.Last loop
+                  Test_If_Relative_Path
+                    (Binder_Switches.Table (J),
+                     Do_Fail => Make_Failed'Access,
+                     Parent  => Dir_Path, Including_L_Switch => False);
+               end loop;
 
-                     begin
-                        Library_Projs.Increment_Last;
-                        Depth := Proj.Depth;
-
-                        --  Put the projects in decreasing depth order, so that
-                        --  if libA depends on libB, libB is first in order.
-
-                        Current := Library_Projs.Last;
-                        while Current > 1 loop
-                           Prj := Library_Projs.Table (Current - 1);
-                           exit when Prj.Depth >= Depth;
-                           Library_Projs.Table (Current) := Prj;
-                           Current := Current - 1;
-                        end loop;
+               for J in Last_Linker_Switch + 1 .. Linker_Switches.Last loop
+                  Test_If_Relative_Path
+                    (Linker_Switches.Table (J),
+                     Parent  => Dir_Path,
+                     Do_Fail => Make_Failed'Access);
+               end loop;
+            end;
+         end;
 
-                        Library_Projs.Table (Current) := Proj;
-                     end Add_To_Library_Projs;
+      else
+         if not Compute_Builder then
+            --  Reset the tables Binder_Switches and Linker_Switches
+            Binder_Switches.Set_Last (Last_Binder_Switch);
+            Linker_Switches.Set_Last (Last_Linker_Switch);
+         end if;
+      end if;
 
-                  --  Start of processing for ??? (should name declare block
-                  --  or probably better, break this out as a nested proc).
+      Check_Steps;
 
-                  begin
-                     --  Put in Library_Projs table all library project file
-                     --  ids when the library need to be rebuilt.
-
-                     Proj1 := Project_Tree.Projects;
-                     while Proj1 /= null loop
-                        if Proj1.Project.Extended_By = No_Project then
-                           if Proj1.Project.Standalone_Library then
-                              Stand_Alone_Libraries := True;
-                           end if;
+      if Compute_Builder then
+         Display_Commands (not Quiet_Output);
+      end if;
 
-                           if Proj1.Project.Library then
-                              MLib.Prj.Check_Library
-                                (Proj1.Project, Project_Tree);
-                           end if;
+      --  We now put in the Binder_Switches and Linker_Switches tables,
+      --  the binder and linker switches of the command line that have
+      --  been put in the Saved_ tables. If a project file was used, then
+      --  the command line switches will follow the project file
+      --  switches.
 
-                           if Proj1.Project.Need_To_Build_Lib then
-                              Add_To_Library_Projs (Proj1.Project);
-                           end if;
-                        end if;
+      for J in 1 .. Saved_Binder_Switches.Last loop
+         Add_Switch
+           (Saved_Binder_Switches.Table (J),
+            Binder,
+            And_Save => False);
+      end loop;
 
-                        Proj1 := Proj1.Next;
-                     end loop;
+      for J in 1 .. Saved_Linker_Switches.Last loop
+         Add_Switch
+           (Saved_Linker_Switches.Table (J),
+            Linker,
+            And_Save => False);
+      end loop;
+   end Compute_Switches_For_Main;
 
-                     --  Check if importing libraries should be regenerated
-                     --  because at least an imported library will be
-                     --  regenerated or is more recent.
-
-                     Proj1 := Project_Tree.Projects;
-                     while Proj1 /= null loop
-                        if Proj1.Project.Library
-                          and then Proj1.Project.Extended_By = No_Project
-                          and then Proj1.Project.Library_Kind /= Static
-                          and then not Proj1.Project.Need_To_Build_Lib
-                          and then not Proj1.Project.Externally_Built
-                        then
-                           declare
-                              List    : Project_List;
-                              Proj2   : Project_Id;
-                              Rebuild : Boolean := False;
-
-                              Lib_Timestamp1 : constant Time_Stamp_Type :=
-                                                 Proj1.Project.Library_TS;
-
-                           begin
-                              List := Proj1.Project.All_Imported_Projects;
-                              while List /= null loop
-                                 Proj2 := List.Project;
-
-                                 if Proj2.Library then
-                                    if Proj2.Need_To_Build_Lib
-                                      or else
-                                        (Lib_Timestamp1 < Proj2.Library_TS)
-                                    then
-                                       Rebuild := True;
-                                       exit;
-                                    end if;
-                                 end if;
+   --------------
+   -- Gnatmake --
+   --------------
 
-                                 List := List.Next;
-                              end loop;
+   procedure Gnatmake is
+      Main_Source_File : File_Name_Type;
+      --  The source file containing the main compilation unit
 
-                              if Rebuild then
-                                 Proj1.Project.Need_To_Build_Lib := True;
-                                 Add_To_Library_Projs (Proj1.Project);
-                              end if;
-                           end;
-                        end if;
+      Total_Compilation_Failures : Natural := 0;
 
-                        Proj1 := Proj1.Next;
-                     end loop;
+      Main_ALI_File : File_Name_Type;
+      --  The ali file corresponding to Main_Source_File
 
-                     --  Reset the flags Need_To_Build_Lib for the next main,
-                     --  to avoid rebuilding libraries uselessly.
+      Executable : File_Name_Type := No_File;
+      --  The file name of an executable
 
-                     Proj1 := Project_Tree.Projects;
-                     while Proj1 /= null loop
-                        Proj1.Project.Need_To_Build_Lib := False;
-                        Proj1 := Proj1.Next;
-                     end loop;
-                  end;
+      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.
 
-                  --  Build the libraries, if any need to be built
+      Current_Work_Dir : constant String_Access :=
+                                    new String'(Get_Current_Dir);
+      --  The current working directory, used to modify some relative path
+      --  switches on the command line when a project file is used.
 
-                  for J in 1 .. Library_Projs.Last loop
-                     Library_Rebuilt := True;
+      Current_Main_Index : Int := 0;
+      --  If not zero, the index of the current main unit in its source file
 
-                     --  If a library is rebuilt, then executables are obsolete
+      Stand_Alone_Libraries : Boolean := False;
+      --  Set to True when there are Stand-Alone Libraries, so that gnatbind
+      --  is invoked with the -F switch to force checking of elaboration flags.
 
-                     Executable_Obsolete := True;
+      Project_Node_Tree : Project_Node_Tree_Ref;
+      Root_Environment  : Prj.Tree.Environment;
 
-                     MLib.Prj.Build_Library
-                       (For_Project   => Library_Projs.Table (J),
-                        In_Tree       => Project_Tree,
-                        Gnatbind      => Gnatbind.all,
-                        Gnatbind_Path => Gnatbind_Path,
-                        Gcc           => Gcc.all,
-                        Gcc_Path      => Gcc_Path);
-                  end loop;
-               end if;
+      Stop_Compile : Boolean;
 
-               if List_Dependencies then
-                  if First_Compiled_File /= No_File then
-                     Inform
-                       (First_Compiled_File,
-                        "must be recompiled. Can't generate dependence list.");
-                  else
-                     List_Depend;
-                  end if;
+      Discard : Boolean;
+      pragma Warnings (Off, Discard);
 
-               elsif First_Compiled_File = No_File
-                 and then not Do_Bind_Step
-                 and then not Quiet_Output
-                 and then not Library_Rebuilt
-                 and then Osint.Number_Of_Files = 1
-               then
-                  Inform (Msg => "objects up to date.");
+      procedure Check_Mains;
+      --  Check that the main subprograms do exist and that they all
+      --  belong to the same project file.
 
-               elsif Do_Not_Execute
-                 and then First_Compiled_File /= No_File
-               then
-                  Write_Name (First_Compiled_File);
-                  Write_Eol;
-               end if;
+      -----------------
+      -- Check_Mains --
+      -----------------
 
-               --  Stop after compile step if any of:
+      procedure Check_Mains is
+      begin
+         if Mains.Number_Of_Mains (Project_Tree) = 0
+           and then not Unique_Compile
+         then
+            Mains.Fill_From_Project (Main_Project, Project_Tree);
+         end if;
 
-               --    1) -n (Do_Not_Execute) specified
+         Mains.Complete_Mains
+           (Root_Environment.Flags, Main_Project, Project_Tree);
+      end Check_Mains;
 
-               --    2) -M (List_Dependencies) specified (also sets
-               --       Do_Not_Execute above, so this is probably superfluous).
+   --  Start of processing for Gnatmake
 
-               --    3) -c (Compile_Only) specified, but not -b (Bind_Only)
+   --  This body is very long, should be broken down???
 
-               --    4) Made unit cannot be a main unit
+   begin
+      Install_Int_Handler (Sigint_Intercepted'Access);
 
-               if ((Do_Not_Execute
-                    or List_Dependencies
-                    or not Do_Bind_Step
-                    or not Is_Main_Unit)
-                  and then not No_Main_Subprogram
-                  and then not Build_Bind_And_Link_Full_Project)
-                 or else Unique_Compile
-               then
-                  if Osint.Number_Of_Files = 1 then
-                     exit Multiple_Main_Loop;
+      Do_Compile_Step := True;
+      Do_Bind_Step    := True;
+      Do_Link_Step    := True;
 
-                  else
-                     goto Next_Main;
-                  end if;
-               end if;
+      Obsoleted.Reset;
 
-               --  If the objects were up-to-date check if the executable file
-               --  is also up-to-date. For now always bind and link on the JVM
-               --  since there is currently no simple way to check whether
-               --  objects are up-to-date.
+      Make.Initialize (Project_Node_Tree, Root_Environment);
 
-               if Targparm.VM_Target /= JVM_Target
-                 and then First_Compiled_File = No_File
-               then
-                  Executable_Stamp := File_Stamp (Executable);
+      Bind_Shared := No_Shared_Switch'Access;
+      Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access;
 
-                  if not Executable_Obsolete then
-                     Executable_Obsolete :=
-                       Youngest_Obj_Stamp > Executable_Stamp;
-                  end if;
+      Failed_Links.Set_Last (0);
+      Successful_Links.Set_Last (0);
 
-                  if not Executable_Obsolete then
-                     for Index in reverse 1 .. Dependencies.Last loop
-                        if Is_In_Obsoleted
-                             (Dependencies.Table (Index).Depends_On)
-                        then
-                           Enter_Into_Obsoleted
-                             (Dependencies.Table (Index).This);
-                        end if;
-                     end loop;
+      --  Special case when switch -B was specified
 
-                     Executable_Obsolete := Is_In_Obsoleted (Main_Source_File);
-                     Dependencies.Init;
-                  end if;
+      if Build_Bind_And_Link_Full_Project then
+         --  When switch -B is specified, there must be a project file
 
-                  if not Executable_Obsolete then
+         if Main_Project = No_Project then
+            Make_Failed ("-B cannot be used without a project file");
 
-                     --  If no Ada object files obsolete the executable, check
-                     --  for younger or missing linker files.
+         --  No main program may be specified on the command line
 
-                     Check_Linker_Options
-                       (Executable_Stamp,
-                        Youngest_Obj_File,
-                        Youngest_Obj_Stamp);
+         elsif Osint.Number_Of_Files /= 0 then
+            Make_Failed ("-B cannot be used with a main specified on " &
+                         "the command line");
 
-                     Executable_Obsolete := Youngest_Obj_File /= No_File;
-                  end if;
+         --  And the project file cannot be a library project file
 
-                  --  Check if any library file is more recent than the
-                  --  executable: there may be an externally built library
-                  --  file that has been modified.
+         elsif Main_Project.Library then
+            Make_Failed ("-B cannot be used for a library project file");
 
-                  if not Executable_Obsolete
-                    and then Main_Project /= No_Project
-                  then
-                     declare
-                        Proj1 : Project_List;
+         else
+            No_Main_Subprogram := True;
+            Insert_Project_Sources
+              (The_Project  => Main_Project,
+               All_Projects => Unique_Compile_All_Projects,
+               Into_Q       => False);
 
-                     begin
-                        Proj1 := Project_Tree.Projects;
-                        while Proj1 /= null loop
-                           if Proj1.Project.Library
-                             and then
-                               Proj1.Project.Library_TS > Executable_Stamp
-                           then
-                              Executable_Obsolete := True;
-                              Youngest_Obj_Stamp := Proj1.Project.Library_TS;
-                              Name_Len := 0;
-                              Add_Str_To_Name_Buffer ("library ");
-                              Add_Str_To_Name_Buffer
-                                (Get_Name_String (Proj1.Project.Library_Name));
-                              Youngest_Obj_File := Name_Find;
-                              exit;
-                           end if;
+            --  If there are no sources to compile, we fail
 
-                           Proj1 := Proj1.Next;
-                        end loop;
-                     end;
-                  end if;
+            if Osint.Number_Of_Files = 0 then
+               Make_Failed ("no sources to compile");
+            end if;
 
-                  --  Return if the executable is up to date and otherwise
-                  --  motivate the relink/rebind.
+            --  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.
 
-                  if not Executable_Obsolete then
-                     if not Quiet_Output then
-                        Inform (Executable, "up to date.");
-                     end if;
+            Add_Switch ("-n", Binder, And_Save => True);
 
-                     if Osint.Number_Of_Files = 1 then
-                        exit Multiple_Main_Loop;
+            for J in 1 .. Queue.Size loop
+               Add_Switch
+                 (Get_Name_String (Lib_File_Name (Queue.Element (J))),
+                  Binder, And_Save => True);
+            end loop;
+         end if;
 
-                     else
-                        goto Next_Main;
-                     end if;
-                  end if;
+      elsif Main_Index /= 0 and then Osint.Number_Of_Files > 1 then
+         Make_Failed ("cannot specify several mains with a multi-unit index");
 
-                  if Executable_Stamp (1) = ' ' then
-                     if not No_Main_Subprogram then
-                        Verbose_Msg (Executable, "missing.", Prefix => "  ");
-                     end if;
+      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.
 
-                  elsif Youngest_Obj_Stamp (1) = ' ' then
-                     Verbose_Msg
-                       (Youngest_Obj_File, "missing.",  Prefix => "  ");
+         if Osint.Number_Of_Files /= 0 then
+            if Main_Project.Library
+              and then not Unique_Compile
+              and then ((not Make_Steps) or else Bind_Only or else Link_Only)
+            then
+               Make_Failed ("cannot specify a main program " &
+                            "on the command line for a library project file");
+            end if;
 
-                  elsif Youngest_Obj_Stamp > Executable_Stamp then
-                     Verbose_Msg
-                       (Youngest_Obj_File,
-                        "(" & String (Youngest_Obj_Stamp) & ") newer than",
-                        Executable,
-                        "(" & String (Executable_Stamp) & ")");
+         --  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
-                     Verbose_Msg
-                       (Executable, "needs to be rebuilt", Prefix => "  ");
+         else
+            if Main_Index /= 0 then
+               Make_Failed ("cannot specify a multi-unit index but no main " &
+                            "on the command line");
+            end if;
 
-                  end if;
-               end if;
-            end Recursive_Compilation_Step;
-         end if;
+            declare
+               Value : String_List_Id := Main_Project.Mains;
 
-         --  For binding and linking, we need to be in the object directory of
-         --  the main project.
+            begin
+               --  The attribute Main is an empty list or not specified, or
+               --  else gnatmake was invoked with the switch "-u".
 
-         if Main_Project /= No_Project then
-            Change_To_Object_Directory (Main_Project);
-         end if;
+               if Value = Prj.Nil_String or else Unique_Compile then
 
-         --  If we are here, it means that we need to rebuilt the current main,
-         --  so we set Executable_Obsolete to True to make sure that subsequent
-         --  mains will be rebuilt.
+                  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.
 
-         Main_ALI_In_Place_Mode_Step : declare
-            ALI_File : File_Name_Type;
-            Src_File : File_Name_Type;
+                     Do_Bind_Step := False;
+                     Do_Link_Step := False;
 
-         begin
-            Src_File      := Strip_Directory (Main_Source_File);
-            ALI_File      := Lib_File_Name (Src_File, Current_Main_Index);
-            Main_ALI_File := Full_Lib_File_Name (ALI_File);
+                     --  Put all the sources in the queue
 
-            --  When In_Place_Mode, the library file can be located in the
-            --  Main_Source_File directory which may not be present in the
-            --  library path. If it is not present then use the corresponding
-            --  library file name.
+                     No_Main_Subprogram := True;
+                     Insert_Project_Sources
+                       (The_Project  => Main_Project,
+                        All_Projects => Unique_Compile_All_Projects,
+                        Into_Q       => False);
 
-            if Main_ALI_File = No_File and then In_Place_Mode then
-               Get_Name_String (Get_Directory (Full_Source_Name (Src_File)));
-               Get_Name_String_And_Append (ALI_File);
-               Main_ALI_File := Name_Find;
-               Main_ALI_File := Full_Lib_File_Name (Main_ALI_File);
-            end if;
+                     --  If no sources to compile, then there is nothing to do
 
-            if Main_ALI_File = No_File then
-               Make_Failed ("could not find the main ALI file");
-            end if;
-         end Main_ALI_In_Place_Mode_Step;
+                     if Osint.Number_Of_Files = 0 then
+                        if not Quiet_Output then
+                           Osint.Write_Program_Name;
+                           Write_Line (": no sources to compile");
+                        end if;
 
-         if Do_Bind_Step then
-            Bind_Step : declare
-               Args : Argument_List
-                        (Binder_Switches.First .. Binder_Switches.Last + 2);
-               --  The arguments for the invocation of gnatbind
+                        Finish_Program (Project_Tree, E_Success);
+                     end if;
+                  end if;
 
-               Last_Arg : Natural := Binder_Switches.Last;
-               --  Index of the last argument in Args
+               else
+                  --  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.
 
-               Shared_Libs : Boolean := False;
-               --  Set to True when there are shared library project files or
-               --  when gnatbind is invoked with -shared.
+                  declare
+                     Languages : constant Variable_Value :=
+                                   Prj.Util.Value_Of
+                                     (Name_Languages,
+                                      Main_Project.Decl.Attributes,
+                                      Project_Tree.Shared);
 
-               Proj : Project_List;
+                     Current : String_List_Id;
+                     Element : String_Element;
 
-            begin
-               --  Check if there are shared libraries, so that gnatbind is
-               --  called with -shared. Check also if gnatbind is called with
-               --  -shared, so that gnatlink is called with -shared-libgcc
-               --  ensuring that the shared version of libgcc will be used.
+                     Foreign_Language  : Boolean := False;
+                     At_Least_One_Main : Boolean := False;
 
-               if Main_Project /= No_Project
-                 and then MLib.Tgt.Support_For_Libraries /= Prj.None
-               then
-                  Proj := Project_Tree.Projects;
-                  while Proj /= null loop
-                     if Proj.Project.Library
-                       and then Proj.Project.Library_Kind /= Static
-                     then
-                        Shared_Libs := True;
-                        Bind_Shared := Shared_Switch'Access;
-                        exit;
-                     end if;
-                     Proj := Proj.Next;
-                  end loop;
-               end if;
+                  begin
+                     --  First, determine if there is a foreign language in
+                     --  attribute Languages.
 
-               --  Check now for switch -shared
+                     if not Languages.Default then
+                        Current := Languages.Values;
+                        Look_For_Foreign :
+                        while Current /= Nil_String loop
+                           Element := Project_Tree.Shared.String_Elements.
+                                        Table (Current);
+                           Get_Name_String (Element.Value);
+                           To_Lower (Name_Buffer (1 .. Name_Len));
 
-               if not Shared_Libs then
-                  for J in Binder_Switches.First .. Last_Arg loop
-                     if Binder_Switches.Table (J).all = "-shared" then
-                        Shared_Libs := True;
-                        exit;
-                     end if;
-                  end loop;
-               end if;
+                           if Name_Buffer (1 .. Name_Len) /= "ada" then
+                              Foreign_Language := True;
+                              exit Look_For_Foreign;
+                           end if;
 
-               --  If shared libraries present, invoke gnatlink with
-               --  -shared-libgcc.
+                           Current := Element.Next;
+                        end loop Look_For_Foreign;
+                     end if;
 
-               if Shared_Libs then
-                  Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access;
-               end if;
+                     --  Then, find all mains, or if there is a foreign
+                     --  language, all the Ada mains.
 
-               --  Get all the binder switches
+                     while Value /= Prj.Nil_String loop
+                        --  To know if a main is an Ada main, get its project.
+                        --  It should be the project specified on the command
+                        --  line.
 
-               for J in Binder_Switches.First .. Last_Arg loop
-                  Args (J) := Binder_Switches.Table (J);
-               end loop;
+                        Get_Name_String
+                          (Project_Tree.Shared.String_Elements.Table
+                             (Value).Value);
 
-               if Stand_Alone_Libraries then
-                  Last_Arg := Last_Arg + 1;
-                  Args (Last_Arg) := Force_Elab_Flags_String'Access;
-               end if;
+                        declare
+                           Main_Name : constant String :=
+                              Get_Name_String
+                               (Project_Tree.Shared.String_Elements.Table
+                                    (Value).Value);
+                           Proj : constant Project_Id :=
+                             Prj.Env.Project_Of
+                              (Main_Name, Main_Project, Project_Tree);
+                        begin
 
-               if Main_Project /= No_Project then
+                           if Proj = Main_Project then
 
-                  --  Put all the source directories in ADA_INCLUDE_PATH,
-                  --  and all the object directories in ADA_OBJECTS_PATH,
-                  --  except those of library projects.
+                              At_Least_One_Main := True;
+                              Osint.Add_File
+                                (Get_Name_String
+                                   (Project_Tree.Shared.String_Elements.Table
+                                      (Value).Value),
+                                 Index =>
+                                   Project_Tree.Shared.String_Elements.Table
+                                     (Value).Index);
 
-                  Prj.Env.Set_Ada_Paths
-                    (Project             => Main_Project,
-                     In_Tree             => Project_Tree,
-                     Including_Libraries => False,
-                     Include_Path        => Use_Include_Path_File);
+                           elsif not Foreign_Language then
+                              Make_Failed
+                                ("""" & Main_Name &
+                                 """ is not a source of project " &
+                                 Get_Name_String (Main_Project.Display_Name));
+                           end if;
+                        end;
 
-                  --  If switch -C was specified, create a binder mapping file
+                        Value := Project_Tree.Shared.String_Elements.Table
+                                   (Value).Next;
+                     end loop;
 
-                  if Create_Mapping_File then
-                     Mapping_Path := Create_Binder_Mapping_File (Project_Tree);
+                     --  If we did not get any main, it means that all mains
+                     --  in attribute Mains are in a foreign language and -B
+                     --  was not specified to gnatmake; so, we fail.
 
-                     if Mapping_Path /= No_Path then
-                        Last_Arg := Last_Arg + 1;
-                        Args (Last_Arg) :=
-                          new String'("-F=" & Get_Name_String (Mapping_Path));
+                     if not At_Least_One_Main then
+                        Make_Failed
+                          ("no Ada mains, use -B to build foreign main");
                      end if;
-                  end if;
+                  end;
 
                end if;
+            end;
+         end if;
 
-               begin
-                  Bind (Main_ALI_File,
-                        Bind_Shared.all & Args (Args'First .. Last_Arg));
+         --  Check that each main on the command line is a source of a
+         --  project file and, if there are several mains, each of them
+         --  is a source of the same project file.
 
-               exception
-                  when others =>
+         Check_Mains;
+      end if;
 
-                     --  Delete the temporary mapping file if one was created
+      if Verbose_Mode then
+         Write_Eol;
+         Display_Version ("GNATMAKE", "1995");
+      end if;
 
-                     if Mapping_Path /= No_Path then
-                        Delete_Temporary_File
-                           (Project_Tree.Shared, Mapping_Path);
-                     end if;
+      if Osint.Number_Of_Files = 0 then
+         if Main_Project /= No_Project
+           and then Main_Project.Library
+         then
+            if Do_Bind_Step
+              and then not Main_Project.Standalone_Library
+            then
+               Make_Failed ("only stand-alone libraries may be bound");
+            end if;
 
-                     --  And reraise the exception
+            --  Add the default search directories to be able to find libgnat
 
-                     raise;
-               end;
+            Osint.Add_Default_Search_Dirs;
 
-               --  If -dn was not specified, delete the temporary mapping file
-               --  if one was created.
+            --  Get the target parameters, so that the correct binder generated
+            --  files are generated if OpenVMS is the target.
 
-               if Mapping_Path /= No_Path then
-                  Delete_Temporary_File (Project_Tree.Shared, Mapping_Path);
-               end if;
-            end Bind_Step;
-         end if;
+            begin
+               Targparm.Get_Target_Parameters;
 
-         if Do_Link_Step then
-            Link_Step : declare
-               Linker_Switches_Last : constant Integer := Linker_Switches.Last;
-               Path_Option          : constant String_Access :=
-                                        MLib.Linker_Library_Path_Option;
-               Libraries_Present    : Boolean := False;
-               Current              : Natural;
-               Proj2                : Project_Id;
-               Depth                : Natural;
-               Proj1                : Project_List;
+            exception
+               when Unrecoverable_Error =>
+                  Make_Failed ("*** make failed.");
+            end;
 
-            begin
-               if not Run_Path_Option then
-                  Linker_Switches.Increment_Last;
-                  Linker_Switches.Table (Linker_Switches.Last) :=
-                    new String'("-R");
-               end if;
+            --  And bind and or link the library
 
-               if Main_Project /= No_Project then
-                  Library_Paths.Set_Last (0);
-                  Library_Projs.Init;
+            MLib.Prj.Build_Library
+              (For_Project   => Main_Project,
+               In_Tree       => Project_Tree,
+               Gnatbind      => Gnatbind.all,
+               Gnatbind_Path => Gnatbind_Path,
+               Gcc           => Gcc.all,
+               Gcc_Path      => Gcc_Path,
+               Bind          => Bind_Only,
+               Link          => Link_Only);
 
-                  if MLib.Tgt.Support_For_Libraries /= Prj.None then
+            Finish_Program (Project_Tree, E_Success);
 
-                     --  Check for library projects
+         else
+            --  Call Get_Target_Parameters to ensure that VM_Target and
+            --  AAMP_On_Target get set before calling Usage.
 
-                     Proj1 := Project_Tree.Projects;
-                     while Proj1 /= null loop
-                        if Proj1.Project /= Main_Project
-                          and then Proj1.Project.Library
-                        then
-                           --  Add this project to table Library_Projs
+            Targparm.Get_Target_Parameters;
 
-                           Libraries_Present := True;
-                           Depth := Proj1.Project.Depth;
-                           Library_Projs.Increment_Last;
-                           Current := Library_Projs.Last;
+            --  Output usage information if no files to compile
 
-                           --  Any project with a greater depth should be
-                           --  after this project in the list.
+            Usage;
+            Finish_Program (Project_Tree, E_Success);
+         end if;
+      end if;
 
-                           while Current > 1 loop
-                              Proj2 := Library_Projs.Table (Current - 1);
-                              exit when Proj2.Depth <= Depth;
-                              Library_Projs.Table (Current) := Proj2;
-                              Current := Current - 1;
-                           end loop;
+      --  Get the first executable.
+      --  ??? This needs to be done early, because Osint.Next_Main_File also
+      --  initializes the primary search directory, used below to initiliaze
+      --  the "-I" parameter
 
-                           Library_Projs.Table (Current) := Proj1.Project;
+      Main_Source_File := Next_Main_Source;  --  No directory information
 
-                           --  If it is not a static library and path option
-                           --  is set, add it to the Library_Paths table.
+      --  If -M was specified, behave as if -n was specified
 
-                           if Proj1.Project.Library_Kind /= Static
-                             and then Proj1.Project.Extended_By = No_Project
-                             and then Path_Option /= null
-                           then
-                              Library_Paths.Increment_Last;
-                              Library_Paths.Table (Library_Paths.Last) :=
-                                new String'
-                                  (Get_Name_String
-                                     (Proj1.Project.Library_Dir.Display_Name));
-                           end if;
-                        end if;
+      if List_Dependencies then
+         Do_Not_Execute := True;
+      end if;
 
-                        Proj1 := Proj1.Next;
-                     end loop;
+      Add_Switch ("-I-", Compiler, And_Save => True);
 
-                     for Index in 1 .. Library_Projs.Last loop
-                        if
-                          Library_Projs.Table (Index).Extended_By = No_Project
-                        then
-                           if Library_Projs.Table (Index).Library_Kind = Static
-                             and then not Targparm.OpenVMS_On_Target
-                           then
-                              Linker_Switches.Increment_Last;
-                              Linker_Switches.Table (Linker_Switches.Last) :=
-                                new String'
-                                  (Get_Name_String
-                                       (Library_Projs.Table
-                                            (Index).Library_Dir.Display_Name) &
-                                   "lib" &
-                                   Get_Name_String
-                                     (Library_Projs.Table
-                                        (Index).Library_Name) &
-                                   "." &
-                                   MLib.Tgt.Archive_Ext);
+      if Main_Project = No_Project then
+         if Look_In_Primary_Dir then
+            Add_Switch
+              ("-I" &
+               Normalize_Directory_Name
+               (Get_Primary_Src_Search_Directory.all).all,
+               Compiler, Append_Switch => False,
+               And_Save => False);
 
-                           else
-                              --  Add the -L switch
-
-                              Linker_Switches.Increment_Last;
-                              Linker_Switches.Table (Linker_Switches.Last) :=
-                                new String'("-L" &
-                                  Get_Name_String
-                                    (Library_Projs.Table (Index).
-                                       Library_Dir.Display_Name));
-
-                              --  Add the -l switch
-
-                              Linker_Switches.Increment_Last;
-                              Linker_Switches.Table (Linker_Switches.Last) :=
-                                new String'("-l" &
-                                            Get_Name_String
-                                              (Library_Projs.Table (Index).
-                                                Library_Name));
-                           end if;
-                        end if;
-                     end loop;
-                  end if;
+         end if;
 
-                  if Libraries_Present then
+      else
+         --  If we use a project file, we have already checked that a main
+         --  specified on the command line with directory information has the
+         --  path name corresponding to a correct source in the project tree.
+         --  So, we don't need the directory information to be taken into
+         --  account by Find_File, and in fact it may lead to take the wrong
+         --  sources for other compilation units, when there are extending
+         --  projects.
 
-                     --  If Path_Option is not null, create the switch
-                     --  ("-Wl,-rpath," or equivalent) with all the non-static
-                     --  library dirs plus the standard GNAT library dir.
-                     --  We do that only if Run_Path_Option is True
-                     --  (not disabled by -R switch).
+         Look_In_Primary_Dir := False;
+         Add_Switch ("-I-", Binder, And_Save => True);
+      end if;
 
-                     if Run_Path_Option and then Path_Option /= null then
-                        declare
-                           Option  : String_Access;
-                           Length  : Natural := Path_Option'Length;
-                           Current : Natural;
+      --  If the user wants a program without a main subprogram, add the
+      --  appropriate switch to the binder.
 
-                        begin
-                           if MLib.Separate_Run_Path_Options then
-
-                              --  We are going to create one switch of the form
-                              --  "-Wl,-rpath,dir_N" for each directory to
-                              --  consider.
-
-                              --  One switch for each library directory
-
-                              for Index in
-                                Library_Paths.First .. Library_Paths.Last
-                              loop
-                                 Linker_Switches.Increment_Last;
-                                 Linker_Switches.Table
-                                   (Linker_Switches.Last) :=
-                                   new String'
-                                     (Path_Option.all &
-                                      Library_Paths.Table (Index).all);
-                              end loop;
+      if No_Main_Subprogram then
+         Add_Switch ("-z", Binder, And_Save => True);
+      end if;
 
-                              --  One switch for the standard GNAT library dir
+      if Main_Project /= No_Project then
 
-                              Linker_Switches.Increment_Last;
-                              Linker_Switches.Table
-                                (Linker_Switches.Last) :=
-                                  new String'
-                                    (Path_Option.all & MLib.Utl.Lib_Directory);
+         if Main_Project.Object_Directory /= No_Path_Information then
+            --  Change current directory to object directory of main project
 
-                           else
-                              --  We are going to create one switch of the form
-                              --  "-Wl,-rpath,dir_1:dir_2:dir_3"
-
-                              for Index in
-                                Library_Paths.First .. Library_Paths.Last
-                              loop
-                                 --  Add the length of the library dir plus one
-                                 --  for the directory separator.
-
-                                 Length :=
-                                   Length +
-                                     Library_Paths.Table (Index)'Length + 1;
-                              end loop;
+            Project_Of_Current_Object_Directory := No_Project;
+            Change_To_Object_Directory (Main_Project);
+         end if;
 
-                              --  Finally, add the length of the standard GNAT
-                              --  library dir.
-
-                              Length := Length + MLib.Utl.Lib_Directory'Length;
-                              Option := new String (1 .. Length);
-                              Option (1 .. Path_Option'Length) :=
-                                Path_Option.all;
-                              Current := Path_Option'Length;
-
-                              --  Put each library dir followed by a dir
-                              --  separator.
-
-                              for Index in
-                                Library_Paths.First .. Library_Paths.Last
-                              loop
-                                 Option
-                                   (Current + 1 ..
-                                     Current +
-                                       Library_Paths.Table (Index)'Length) :=
-                                   Library_Paths.Table (Index).all;
-                                 Current :=
-                                   Current +
-                                     Library_Paths.Table (Index)'Length + 1;
-                                 Option (Current) := Path_Separator;
-                              end loop;
+         --  Source file lookups should be cached for efficiency.
+         --  Source files are not supposed to change.
 
-                              --  Finally put the standard GNAT library dir
+         Osint.Source_File_Data (Cache => True);
 
-                              Option
-                                (Current + 1 ..
-                                   Current + MLib.Utl.Lib_Directory'Length) :=
-                                  MLib.Utl.Lib_Directory;
+         Osint.Add_Default_Search_Dirs;
 
-                              --  And add the switch to the linker switches
+         Queue_Library_Project_Sources;
+      end if;
 
-                              Linker_Switches.Increment_Last;
-                              Linker_Switches.Table (Linker_Switches.Last) :=
-                                Option;
-                           end if;
-                        end;
-                     end if;
+      --  The combination of -f -u and one or several mains on the command line
+      --  implies -a.
 
-                  end if;
+      if Force_Compilations
+        and then Unique_Compile
+        and then not Unique_Compile_All_Projects
+        and then Main_On_Command_Line
+      then
+         Must_Compile := True;
+      end if;
 
-                  --  Put the object directories in ADA_OBJECTS_PATH
+      if Main_Project /= No_Project
+        and then not Must_Compile
+        and then Main_Project.Externally_Built
+      then
+         Make_Failed
+           ("nothing to do for a main project that is externally built");
+      end if;
 
-                  Prj.Env.Set_Ada_Paths
-                    (Main_Project,
-                     Project_Tree,
-                     Including_Libraries => False,
-                     Include_Path        => False);
+      --  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.
 
-                  --  Check for attributes Linker'Linker_Options in projects
-                  --  other than the main project
+      begin
+         Targparm.Get_Target_Parameters;
+      exception
+         when Unrecoverable_Error =>
+            Make_Failed ("*** make failed.");
+      end;
 
-                  declare
-                     Linker_Options : constant String_List :=
-                                        Linker_Options_Switches
-                                          (Main_Project,
-                                           Do_Fail => Make_Failed'Access,
-                                           In_Tree => Project_Tree);
-                  begin
-                     for Option in Linker_Options'Range loop
-                        Linker_Switches.Increment_Last;
-                        Linker_Switches.Table (Linker_Switches.Last) :=
-                          Linker_Options (Option);
-                     end loop;
-                  end;
-               end if;
+      --  Special processing for VM targets
 
-               --  Add switch -M to gnatlink if builder switch
-               --  --create-map-file has been specified.
+      if Targparm.VM_Target /= No_VM then
 
-               if Map_File /= null then
-                  Linker_Switches.Increment_Last;
-                  Linker_Switches.Table (Linker_Switches.Last) :=
-                    new String'("-M" & Map_File.all);
-               end if;
+         --  Set proper processing commands
 
-               declare
-                  Args : Argument_List
-                           (Linker_Switches.First .. Linker_Switches.Last + 2);
+         case Targparm.VM_Target is
+            when Targparm.JVM_Target =>
 
-                  Last_Arg : Integer := Linker_Switches.First - 1;
-                  Skip     : Boolean := False;
+               --  Do not check for an object file (".o") when compiling to
+               --  JVM machine since ".class" files are generated instead.
 
-               begin
-                  --  Get all the linker switches
+               Check_Object_Consistency := False;
+               Gcc := new String'("jvm-gnatcompile");
 
-                  for J in Linker_Switches.First .. Linker_Switches.Last loop
-                     if Skip then
-                        Skip := False;
+            when Targparm.CLI_Target =>
+               Gcc := new String'("dotnet-gnatcompile");
 
-                     elsif Non_Std_Executable
-                       and then Linker_Switches.Table (J).all = "-o"
-                     then
-                        Skip := True;
+            when Targparm.No_VM =>
+               raise Program_Error;
+         end case;
+      end if;
 
-                     --  Here we capture and duplicate the linker argument. We
-                     --  need to do the duplication since the arguments will
-                     --  get normalized. Not doing so will result in calling
-                     --  normalized two times for the same set of arguments if
-                     --  gnatmake is passed multiple mains. This can result in
-                     --  the wrong argument being passed to the linker.
+      --  If no project file is used, we just put the gcc switches
+      --  from the command line in the Gcc_Switches table.
 
-                     else
-                        Last_Arg := Last_Arg + 1;
-                        Args (Last_Arg) :=
-                          new String'(Linker_Switches.Table (J).all);
-                     end if;
-                  end loop;
+      if Main_Project = No_Project then
+         for J in 1 .. Saved_Gcc_Switches.Last loop
+            Add_Switch
+              (Saved_Gcc_Switches.Table (J), Compiler, And_Save => False);
+         end loop;
 
-                  --  If need be, add the -o switch
+      else
+         --  If there is a project, put the command line gcc switches in the
+         --  variable The_Saved_Gcc_Switches. They are going to be used later
+         --  in procedure Compile_Sources.
 
-                  if Non_Std_Executable then
-                     Last_Arg := Last_Arg + 1;
-                     Args (Last_Arg) := new String'("-o");
-                     Last_Arg := Last_Arg + 1;
-                     Args (Last_Arg) :=
-                       new String'(Get_Name_String (Executable));
-                  end if;
+         The_Saved_Gcc_Switches :=
+           new Argument_List (1 .. Saved_Gcc_Switches.Last + 1);
 
-                  --  And invoke the linker
+         for J in 1 .. Saved_Gcc_Switches.Last loop
+            The_Saved_Gcc_Switches (J) := Saved_Gcc_Switches.Table (J);
+         end loop;
 
-                  declare
-                     Success : Boolean := False;
-                  begin
-                     Link (Main_ALI_File,
-                           Link_With_Shared_Libgcc.all &
-                           Args (Args'First .. Last_Arg),
-                           Success);
-
-                     if Success then
-                        Successful_Links.Increment_Last;
-                        Successful_Links.Table (Successful_Links.Last) :=
-                          Main_ALI_File;
-
-                     elsif Osint.Number_Of_Files = 1
-                       or else not Keep_Going
-                     then
-                        Make_Failed ("*** link failed.");
+         --  We never use gnat.adc when a project file is used
 
-                     else
-                        Set_Standard_Error;
-                        Write_Line ("*** link failed");
+         The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) := No_gnat_adc;
+      end if;
 
-                        if Commands_To_Stdout then
-                           Set_Standard_Output;
-                        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.
 
-                        Failed_Links.Increment_Last;
-                        Failed_Links.Table (Failed_Links.Last) :=
-                          Main_ALI_File;
-                     end if;
-                  end;
-               end;
+      if Saved_Gcc /= null then
+         Gcc := Saved_Gcc;
+      end if;
 
-               Linker_Switches.Set_Last (Linker_Switches_Last);
-            end Link_Step;
-         end if;
+      if Saved_Gnatbind /= null then
+         Gnatbind := Saved_Gnatbind;
+      end if;
 
-         --  We go to here when we skip the bind and link steps
+      if Saved_Gnatlink /= null then
+         Gnatlink := Saved_Gnatlink;
+      end if;
 
-         <<Next_Main>>
+      Gcc_Path       := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
+      Gnatbind_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
+      Gnatlink_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
 
-         --  We go to the next main, if we did not process the last one
+      --  If we have specified -j switch both from the project file
+      --  and on the command line, the one from the command line takes
+      --  precedence.
 
-         if N_File < Osint.Number_Of_Files then
-            Main_Source_File := Next_Main_Source;
+      if Saved_Maximum_Processes = 0 then
+         Saved_Maximum_Processes := Maximum_Processes;
+      end if;
 
-            if Current_File_Index /= No_Index then
-               Main_Index := Current_File_Index;
-            end if;
+      if Debug.Debug_Flag_M then
+         Write_Line ("Maximum number of simultaneous compilations =" &
+                     Saved_Maximum_Processes'Img);
+      end if;
 
-            if Main_Project /= No_Project then
+      --  Allocate as many temporary mapping file names as the maximum number
+      --  of compilations processed, for each possible project.
 
-               --  Find the file name of the main unit
+      declare
+         Data : Project_Compilation_Access;
+         Proj : Project_List := Project_Tree.Projects;
+      begin
+         while Proj /= null loop
+            Data := new Project_Compilation_Data'
+              (Mapping_File_Names        => new Temp_Path_Names
+                                              (1 .. Saved_Maximum_Processes),
+               Last_Mapping_File_Names   => 0,
+               Free_Mapping_File_Indexes => new Free_File_Indexes
+                                              (1 .. Saved_Maximum_Processes),
+               Last_Free_Indexes         => 0);
 
-               declare
-                  Main_Source_File_Name : constant String :=
-                                            Get_Name_String (Main_Source_File);
-
-                  Main_Unit_File_Name : constant String :=
-                                          Prj.Env.
-                                            File_Name_Of_Library_Unit_Body
-                                              (Name => Main_Source_File_Name,
-                                               Project => Main_Project,
-                                               In_Tree => Project_Tree,
-                                               Main_Project_Only =>
-                                                 not Unique_Compile);
-
-                  The_Packages : constant Package_Id :=
-                                   Main_Project.Decl.Packages;
-
-                  Binder_Package : constant Prj.Package_Id :=
-                                     Prj.Util.Value_Of
-                                       (Name        => Name_Binder,
-                                        In_Packages => The_Packages,
-                                        Shared      => Project_Tree.Shared);
-
-                  Linker_Package : constant Prj.Package_Id :=
-                                     Prj.Util.Value_Of
-                                       (Name        => Name_Linker,
-                                        In_Packages => The_Packages,
-                                        Shared      => Project_Tree.Shared);
+            Project_Compilation_Htable.Set
+              (Project_Compilation, Proj.Project, Data);
+            Proj := Proj.Next;
+         end loop;
 
-               begin
-                  --  We fail if we cannot find the main source file
-                  --  as an immediate source of the main project file.
+         Data := new Project_Compilation_Data'
+           (Mapping_File_Names        => new Temp_Path_Names
+                                           (1 .. Saved_Maximum_Processes),
+            Last_Mapping_File_Names   => 0,
+            Free_Mapping_File_Indexes => new Free_File_Indexes
+                                           (1 .. Saved_Maximum_Processes),
+            Last_Free_Indexes         => 0);
 
-                  if Main_Unit_File_Name = "" then
-                     Make_Failed ('"' & Main_Source_File_Name
-                                  & """ is not a unit of project "
-                                  & Project_File_Name.all & ".");
+         Project_Compilation_Htable.Set
+           (Project_Compilation, No_Project, Data);
+      end;
 
-                  else
-                     --  Remove any directory information from the main
-                     --  source file name.
+      Bad_Compilation.Init;
 
-                     declare
-                        Pos : Natural := Main_Unit_File_Name'Last;
+      --  If project files are used, create the mapping of all the sources, so
+      --  that the correct paths will be found. Otherwise, if there is a file
+      --  which is not a source with the same name in a source directory this
+      --  file may be incorrectly found.
 
-                     begin
-                        loop
-                           exit when Pos < Main_Unit_File_Name'First
-                             or else
-                             Main_Unit_File_Name (Pos) = Directory_Separator;
-                           Pos := Pos - 1;
-                        end loop;
+      if Main_Project /= No_Project then
+         Prj.Env.Create_Mapping (Project_Tree);
+      end if;
 
-                        Name_Len := Main_Unit_File_Name'Last - Pos;
+      --  Here is where the make process is started
 
-                        Name_Buffer (1 .. Name_Len) :=
-                          Main_Unit_File_Name
-                          (Pos + 1 .. Main_Unit_File_Name'Last);
+      Queue.Initialize
+        (Main_Project /= No_Project and then One_Compilation_Per_Obj_Dir);
 
-                        Main_Source_File := Name_Find;
-                     end;
-                  end if;
+      Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop
+         if Current_File_Index /= No_Index then
+            Main_Index := Current_File_Index;
+         end if;
 
-                  --  We now deal with the binder and linker switches.
-                  --  If no project file is used, there is nothing to do
-                  --  because the binder and linker switches are the same
-                  --  for all mains.
+         Current_Main_Index := Main_Index;
 
-                  --  Reset the tables Binder_Switches and Linker_Switches
+         Compute_Switches_For_Main
+           (Main_Source_File,
+            Main_Index,
+            Project_Node_Tree,
+            Root_Environment,
+            Compute_Builder  => N_File = 1,
+            Current_Work_Dir => Current_Work_Dir.all);
 
-                  Binder_Switches.Set_Last (Last_Binder_Switch);
-                  Linker_Switches.Set_Last (Last_Linker_Switch);
+         Executable_Obsolete := False;
 
-                  --  Add binder switches from the project file for this main,
-                  --  if any.
+         Compute_Executable
+           (Main_Source_File   => Main_Source_File,
+            Executable         => Executable,
+            Non_Std_Executable => Non_Std_Executable);
 
-                  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);
-                        Write_Line (""".");
-                     end if;
+         if Do_Compile_Step then
+            Compilation_Phase
+              (Main_Source_File           => Main_Source_File,
+               Current_Main_Index         => Current_Main_Index,
+               Total_Compilation_Failures => Total_Compilation_Failures,
+               Stand_Alone_Libraries      => Stand_Alone_Libraries,
+               Executable                 => Executable,
+               Is_Last_Main               => N_File = Osint.Number_Of_Files,
+               Stop_Compile               => Stop_Compile);
+
+            if Stop_Compile then
+               if Total_Compilation_Failures /= 0 then
+                  if Keep_Going then
+                     goto Next_Main;
 
-                     Add_Switches
-                       (Project_Node_Tree => Project_Node_Tree,
-                        Env               => Root_Environment,
-                        File_Name         => Main_Unit_File_Name,
-                        Index             => Main_Index,
-                        The_Package       => Binder_Package,
-                        Program           => Binder);
+                  else
+                     List_Bad_Compilations;
+                     Report_Compilation_Failed;
                   end if;
 
-                  --  Add linker switches from the project file for this main,
-                  --  if any.
-
-                  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);
-                        Write_Line (""".");
-                     end if;
+               elsif Osint.Number_Of_Files = 1 then
+                  exit Multiple_Main_Loop;
+               else
+                  goto Next_Main;
+               end if;
+            end if;
+         end if;
 
-                     Add_Switches
-                       (Project_Node_Tree => Project_Node_Tree,
-                        Env               => Root_Environment,
-                        File_Name         => Main_Unit_File_Name,
-                        Index             => Main_Index,
-                        The_Package       => Linker_Package,
-                        Program           => Linker);
-                  end if;
+         --  For binding and linking, we need to be in the object directory of
+         --  the main project.
 
-                  --  As we are using a project file, for relative paths we add
-                  --  the current working directory for any relative path on
-                  --  the command line and the project directory, for any
-                  --  relative path in the project file.
+         if Main_Project /= No_Project then
+            Change_To_Object_Directory (Main_Project);
+         end if;
 
-                  declare
-                     Dir_Path : constant String :=
-                                  Get_Name_String
-                                    (Main_Project.Directory.Display_Name);
+         --  If we are here, it means that we need to rebuilt the current main,
+         --  so we set Executable_Obsolete to True to make sure that subsequent
+         --  mains will be rebuilt.
 
-                  begin
-                     for
-                       J in Last_Binder_Switch + 1 .. Binder_Switches.Last
-                     loop
-                        Test_If_Relative_Path
-                          (Binder_Switches.Table (J),
-                           Do_Fail => Make_Failed'Access,
-                           Parent  => Dir_Path, Including_L_Switch => False);
-                     end loop;
+         Main_ALI_In_Place_Mode_Step : declare
+            ALI_File : File_Name_Type;
+            Src_File : File_Name_Type;
 
-                     for
-                       J in Last_Linker_Switch + 1 .. Linker_Switches.Last
-                     loop
-                        Test_If_Relative_Path
-                          (Linker_Switches.Table (J),
-                           Parent  => Dir_Path,
-                           Do_Fail => Make_Failed'Access);
-                     end loop;
-                  end;
+         begin
+            Src_File      := Strip_Directory (Main_Source_File);
+            ALI_File      := Lib_File_Name (Src_File, Current_Main_Index);
+            Main_ALI_File := Full_Lib_File_Name (ALI_File);
 
-                  --  We now put in the Binder_Switches and Linker_Switches
-                  --  tables, the binder and linker switches of the command
-                  --  line that have been put in the Saved_ tables. These
-                  --  switches will follow the project file switches.
+            --  When In_Place_Mode, the library file can be located in the
+            --  Main_Source_File directory which may not be present in the
+            --  library path. If it is not present then use the corresponding
+            --  library file name.
 
-                  for J in 1 .. Saved_Binder_Switches.Last loop
-                     Add_Switch
-                       (Saved_Binder_Switches.Table (J),
-                        Binder,
-                        And_Save => False);
-                  end loop;
+            if Main_ALI_File = No_File and then In_Place_Mode then
+               Get_Name_String (Get_Directory (Full_Source_Name (Src_File)));
+               Get_Name_String_And_Append (ALI_File);
+               Main_ALI_File := Name_Find;
+               Main_ALI_File := Full_Lib_File_Name (Main_ALI_File);
+            end if;
 
-                  for J in 1 .. Saved_Linker_Switches.Last loop
-                     Add_Switch
-                       (Saved_Linker_Switches.Table (J),
-                        Linker,
-                        And_Save => False);
-                  end loop;
-               end;
+            if Main_ALI_File = No_File then
+               Make_Failed ("could not find the main ALI file");
             end if;
+         end Main_ALI_In_Place_Mode_Step;
+
+         if Do_Bind_Step then
+            Binding_Phase
+              (Stand_Alone_Libraries => Stand_Alone_Libraries,
+               Main_ALI_File         => Main_ALI_File);
+         end if;
+
+         if Do_Link_Step then
+            Linking_Phase
+              (Non_Std_Executable => Non_Std_Executable,
+               Executable         => Executable,
+               Main_ALI_File      => Main_ALI_File);
          end if;
 
+         --  We go to here when we skip the bind and link steps
+
+         <<Next_Main>>
+
          Queue.Remove_Marks;
+
+         if N_File < Osint.Number_Of_Files then
+            Main_Source_File := Next_Main_Source;  --  No directory information
+         end if;
       end loop Multiple_Main_Loop;
 
       if Do_Codepeer_Globalize_Step then
index 5efd6e4..76156d9 100644 (file)
@@ -1696,6 +1696,38 @@ package body Makeutl is
             return No_Main_Info;
          else
             Current := Current + 1;
+
+            --  If not using projects, and in the gnatmake case, the main file
+            --  may have not have the extension. Try ".adb" first then ".ads"
+
+            if Names.Table (Current).Project = No_Project then
+               declare
+                  Orig_Main : constant File_Name_Type :=
+                    Names.Table (Current).File;
+                  Current_Main : File_Name_Type;
+
+               begin
+                  if Strip_Suffix (Orig_Main) = Orig_Main then
+                     Get_Name_String (Orig_Main);
+                     Add_Str_To_Name_Buffer (".adb");
+                     Current_Main := Name_Find;
+
+                     if Full_Source_Name (Current_Main) = No_File then
+                        Get_Name_String (Orig_Main);
+                        Add_Str_To_Name_Buffer (".ads");
+                        Current_Main := Name_Find;
+
+                        if Full_Source_Name (Current_Main) /= No_File then
+                           Names.Table (Current).File := Current_Main;
+                        end if;
+
+                     else
+                        Names.Table (Current).File := Current_Main;
+                     end if;
+                  end if;
+               end;
+            end if;
+
             return Names.Table (Current);
          end if;
       end Next_Main;
index 7660749..91e0769 100644 (file)
@@ -352,7 +352,7 @@ package Makeutl is
       function Next_Main return String;
       function Next_Main return Main_Info;
       --  Moves the cursor forward and returns the new current entry. Returns
-      --  No_File_And_Loc if there are no more mains in the table.
+      --  No_Main_Info there are no more mains in the table.
 
       function Number_Of_Mains (Tree : Project_Tree_Ref) return Natural;
       --  Returns the number of mains in this project tree (if Tree is null, it
index 985022c..9ccb5d3 100644 (file)
@@ -324,6 +324,7 @@ package Rtsfind is
       System_Pack_63,
       System_Parameters,
       System_Partition_Interface,
+      System_Pool_32_Global,
       System_Pool_Global,
       System_Pool_Empty,
       System_Pool_Local,
@@ -1154,6 +1155,8 @@ package Rtsfind is
 
      RE_Global_Pool_Object,              -- System.Pool_Global
 
+     RE_Global_Pool_32_Object,           -- System.Pool_32_Global
+
      RE_Stack_Bounded_Pool,              -- System.Pool_Size
 
      RE_Do_Apc,                          -- System.RPC
@@ -2452,6 +2455,8 @@ package Rtsfind is
 
      RE_Global_Pool_Object               => System_Pool_Global,
 
+     RE_Global_Pool_32_Object            => System_Pool_32_Global,
+
      RE_Stack_Bounded_Pool               => System_Pool_Size,
 
      RE_Do_Apc                           => System_RPC,
diff --git a/gcc/ada/s-po32gl.adb b/gcc/ada/s-po32gl.adb
new file mode 100644 (file)
index 0000000..54acf26
--- /dev/null
@@ -0,0 +1,98 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                 S Y S T E M . P O O L _ 3 2 _ G L O B A L                --
+--                                                                          --
+--                                 B o d y                                  --
+--                                                                          --
+--          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+with System.Storage_Pools; use System.Storage_Pools;
+with System.Memory;
+
+package body System.Pool_32_Global is
+
+   package SSE renames System.Storage_Elements;
+
+   --------------
+   -- Allocate --
+   --------------
+
+   overriding procedure Allocate
+     (Pool         : in out Unbounded_No_Reclaim_Pool_32;
+      Address      : out System.Address;
+      Storage_Size : SSE.Storage_Count;
+      Alignment    : SSE.Storage_Count)
+   is
+      pragma Warnings (Off, Pool);
+      pragma Warnings (Off, Alignment);
+
+   begin
+      Address := Memory.Alloc32 (Memory.size_t (Storage_Size));
+
+      --  The call to Alloc returns an address whose alignment is compatible
+      --  with the worst case alignment requirement for the machine; thus the
+      --  Alignment argument can be safely ignored.
+
+      if Address = Null_Address then
+         raise Storage_Error;
+      end if;
+   end Allocate;
+
+   ----------------
+   -- Deallocate --
+   ----------------
+
+   overriding procedure Deallocate
+     (Pool         : in out Unbounded_No_Reclaim_Pool_32;
+      Address      : System.Address;
+      Storage_Size : SSE.Storage_Count;
+      Alignment    : SSE.Storage_Count)
+   is
+      pragma Warnings (Off, Pool);
+      pragma Warnings (Off, Storage_Size);
+      pragma Warnings (Off, Alignment);
+
+   begin
+      Memory.Free (Address);
+   end Deallocate;
+
+   ------------------
+   -- Storage_Size --
+   ------------------
+
+   overriding function Storage_Size
+     (Pool  : Unbounded_No_Reclaim_Pool_32)
+      return  SSE.Storage_Count
+   is
+      pragma Warnings (Off, Pool);
+
+   begin
+      --  The 32 bit heap is limited to 2 GB of memory
+
+      return SSE.Storage_Count (2 ** 31);
+   end Storage_Size;
+
+end System.Pool_32_Global;
diff --git a/gcc/ada/s-po32gl.ads b/gcc/ada/s-po32gl.ads
new file mode 100644 (file)
index 0000000..578fbec
--- /dev/null
@@ -0,0 +1,80 @@
+------------------------------------------------------------------------------
+--                                                                          --
+--                         GNAT COMPILER COMPONENTS                         --
+--                                                                          --
+--                 S Y S T E M . P O O L _ 3 2 _ G L O B A L                --
+--                                                                          --
+--                                 S p e c                                  --
+--                                                                          --
+--          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--                                                                          --
+-- GNAT is free software;  you can  redistribute it  and/or modify it under --
+-- terms of the  GNU General Public License as published  by the Free Soft- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
+-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
+-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
+-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
+--                                                                          --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception,   --
+-- version 3.1, as published by the Free Software Foundation.               --
+--                                                                          --
+-- You should have received a copy of the GNU General Public License and    --
+-- a copy of the GCC Runtime Library Exception along with this program;     --
+-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
+-- <http://www.gnu.org/licenses/>.                                          --
+--                                                                          --
+-- GNAT was originally developed  by the GNAT team at  New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
+--                                                                          --
+------------------------------------------------------------------------------
+
+--  Storage pool corresponding to default global storage pool used for types
+--  designated by a 32 bits access type for which no storage pool is specified.
+--  This is specific to VMS.
+
+with System;
+with System.Storage_Pools;
+with System.Storage_Elements;
+
+package System.Pool_32_Global is
+   pragma Elaborate_Body;
+   --  Needed to ensure that library routines can execute allocators
+
+   --  Allocation strategy:
+
+   --    Call to malloc/free for each Allocate/Deallocate
+   --    No user specifiable size
+   --    No automatic reclaim
+   --    Minimal overhead
+
+   --  Pool simulating the allocation/deallocation strategy used by the
+   --  compiler for access types globally declared.
+
+   type Unbounded_No_Reclaim_Pool_32 is new
+     System.Storage_Pools.Root_Storage_Pool with null record;
+
+   overriding function Storage_Size
+     (Pool : Unbounded_No_Reclaim_Pool_32)
+      return System.Storage_Elements.Storage_Count;
+
+   overriding procedure Allocate
+     (Pool         : in out Unbounded_No_Reclaim_Pool_32;
+      Address      : out System.Address;
+      Storage_Size : System.Storage_Elements.Storage_Count;
+      Alignment    : System.Storage_Elements.Storage_Count);
+
+   overriding procedure Deallocate
+     (Pool         : in out Unbounded_No_Reclaim_Pool_32;
+      Address      : System.Address;
+      Storage_Size : System.Storage_Elements.Storage_Count;
+      Alignment    : System.Storage_Elements.Storage_Count);
+
+   --  Pool object used by the compiler when implicit Storage Pool objects are
+   --  explicitly referred to. For instance when writing something like:
+   --     for T'Storage_Pool use Q'Storage_Pool;
+   --  and Q'Storage_Pool hasn't been defined explicitly.
+
+   Global_Pool_32_Object : Unbounded_No_Reclaim_Pool_32;
+
+end System.Pool_32_Global;