OSDN Git Service

2008-05-27 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / makegpr.adb
index aad0ec4..684cae9 100644 (file)
@@ -6,64 +6,65 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---       Copyright (C) 2004-2005 Free Software Foundation, Inc.             --
+--          Copyright (C) 2004-2008, 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 2,  or (at your option) any later ver- --
+-- 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.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license.          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
-with Ada.Command_Line;  use Ada.Command_Line;
-with Ada.Strings.Fixed; use Ada.Strings.Fixed;
-with Ada.Text_IO;       use Ada.Text_IO;
-with Ada.Unchecked_Deallocation;
-
 with Csets;
 with Gnatvsn;
+with Hostparm; use Hostparm;
+with Makeutl;  use Makeutl;
+with MLib.Tgt; use MLib.Tgt;
+with Namet;    use Namet;
+with Output;   use Output;
+with Opt;      use Opt;
+with Osint;    use Osint;
+with Prj;      use Prj;
+with Prj.Ext;  use Prj.Ext;
+with Prj.Pars;
+with Prj.Util; use Prj.Util;
+with Snames;   use Snames;
+with Table;
+with Types;    use Types;
 
-with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with Ada.Command_Line;           use Ada.Command_Line;
+with Ada.Strings.Fixed;          use Ada.Strings.Fixed;
+with Ada.Text_IO;                use Ada.Text_IO;
+with Ada.Unchecked_Deallocation;
+
+with GNAT.Directory_Operations;  use GNAT.Directory_Operations;
 with GNAT.Dynamic_Tables;
-with GNAT.Expect;               use GNAT.Expect;
+with GNAT.Expect;                use GNAT.Expect;
 with GNAT.HTable;
-with GNAT.OS_Lib;               use GNAT.OS_Lib;
-with GNAT.Regpat;               use GNAT.Regpat;
-
-with Makeutl;          use Makeutl;
-with MLib.Tgt;         use MLib.Tgt;
-with Namet;            use Namet;
-with Output;           use Output;
-with Opt;              use Opt;
-with Osint;            use Osint;
-with Prj;              use Prj;
-with Prj.Pars;
-with Prj.Util;         use Prj.Util;
-with Snames;           use Snames;
+with GNAT.OS_Lib;                use GNAT.OS_Lib;
+with GNAT.Regpat;                use GNAT.Regpat;
+
 with System;
-with System.Case_Util; use System.Case_Util;
-with Table;
-with Types;            use Types;
+with System.Case_Util;           use System.Case_Util;
 
 package body Makegpr is
 
+   On_Windows : constant Boolean := Directory_Separator = '\';
+   --  True when on Windows. Used in Check_Compilation_Needed when processing
+   --  C/C++ dependency files for backslash handling.
+
    Max_In_Archives : constant := 50;
    --  The maximum number of arguments for a single invocation of the
    --  Archive Indexer (ar).
 
-   Cpp_Linker : constant String := "c++linker";
-   --  The name of a linking script, built one the fly, when there are C++
-   --  sources and the C++ compiler is not g++.
-
    No_Argument : aliased Argument_List := (1 .. 0 => null);
    --  Null argument list representing case of no arguments
 
@@ -133,7 +134,7 @@ package body Makegpr is
    --  ar commands.
 
    Archive_Indexer_Path : String_Access := null;
-   --  The path name of the archive indexer (ranlib), if it exists.
+   --  The path name of the archive indexer (ranlib), if it exists
 
    Copyright_Output : Boolean := False;
    Usage_Output     : Boolean := False;
@@ -230,18 +231,18 @@ package body Makegpr is
      (Header_Num => Header_Num,
       Element    => Boolean,
       No_Element => False,
-      Key        => Name_Id,
+      Key        => File_Name_Type,
       Hash       => Hash,
       Equal      => "=");
 
-   package X_Switches is new Table.Table
+   package Saved_Switches is new Table.Table
      (Table_Component_Type => String_Access,
       Table_Index_Type     => Integer,
       Table_Low_Bound      => 1,
-      Table_Initial        => 2,
+      Table_Initial        => 10,
       Table_Increment      => 100,
-      Table_Name           => "Makegpr.X_Switches");
-   --  Table to store the -X switches to be passed to gnatmake
+      Table_Name           => "Makegpr.Saved_Switches");
+   --  Table to store the switches to be passed to gnatmake
 
    Initial_Argument_Count : constant Positive := 20;
    type Boolean_Array is array (Positive range <>) of Boolean;
@@ -266,7 +267,7 @@ package body Makegpr is
       Table_Index_Type     => Integer,
       Table_Low_Bound      => 1,
       Table_Initial        => 200,
-      Table_Increment      => 50,
+      Table_Increment      => 100,
       Table_Name           => "Makegpr.Cache_Args");
    --  A table to cache arguments, to avoid multiple allocation of the same
    --  strings. It is not possible to use a hash table, because String is
@@ -282,6 +283,8 @@ package body Makegpr is
    Dash_cargs        : constant String_Access := Dash_cargs_String'Access;
    Dash_d_String     : aliased  String := "-d";
    Dash_d            : constant String_Access := Dash_d_String'Access;
+   Dash_eL_String    : aliased  String := "-eL";
+   Dash_eL           : constant String_Access := Dash_eL_String'Access;
    Dash_f_String     : aliased  String := "-f";
    Dash_f            : constant String_Access := Dash_f_String'Access;
    Dash_k_String     : aliased  String := "-k";
@@ -345,12 +348,17 @@ package body Makegpr is
    Path_Option : String_Access;
    --  The path option switch, when supported
 
+   Project_Of_Current_Object_Directory : Project_Id := No_Project;
+   --  The object directory of the project for the last compilation. Avoid
+   --  calling Change_Dir if the current working directory is already this
+   --  directory.
+
    package Lib_Path is new Table.Table
      (Table_Component_Type => Character,
       Table_Index_Type     => Integer,
       Table_Low_Bound      => 1,
       Table_Initial        => 200,
-      Table_Increment      => 50,
+      Table_Increment      => 100,
       Table_Name           => "Makegpr.Lib_Path");
    --  A table to compute the path to put in the path option switch, when it
    --  is supported.
@@ -360,7 +368,7 @@ package body Makegpr is
 
    procedure Add_Argument (Arg : String_Access; Display : Boolean);
    procedure Add_Argument (Arg : String; Display : Boolean);
-   --  Add an argument to Arguments. Reallocate if necessary.
+   --  Add an argument to Arguments. Reallocate if necessary
 
    procedure Add_Arguments (Args : Argument_List; Display : Boolean);
    --  Add a list of arguments to Arguments. Reallocate if necessary
@@ -384,7 +392,7 @@ package body Makegpr is
      (Data      : Project_Data;
       Proc      : Processor;
       Language  : Language_Index;
-      File_Name : Name_Id);
+      File_Name : File_Name_Type);
    --  Add to Arguments the switches, if any, for a source (attribute Switches)
    --  or language (attribute Default_Switches), coming from package Compiler
    --  or Linker (depending on Proc) of a specified project file.
@@ -441,37 +449,39 @@ package body Makegpr is
    --  Create the archive dependency file for a library project
 
    procedure Create_Global_Archive_Dependency_File (Name : String);
-   --  Create the archive depenency file for the main project
+   --  Create the archive dependency file for the main project
 
    procedure Display_Command
-     (Name  : String;
-      Path  : String_Access;
-      CPATH : String_Access := null);
-   --  Display the command for a spawned process, if in Verbose_Mode or
-   --  not in Quiet_Output.
+     (Name    : String;
+      Path    : String_Access;
+      CPATH   : String_Access := null;
+      Ellipse : Boolean := False);
+   --  Display the command for a spawned process, if in Verbose_Mode or not in
+   --  Quiet_Output. In non verbose mode, when Ellipse is True, display "..."
+   --  in place of the first argument that has Display set to False.
 
    procedure Get_Compiler (For_Language : First_Language_Indexes);
    --  Find the compiler name and path name for a specified programming
-   --  language, if not already done. Results are in the corresponding
-   --  elements of arrays Compiler_Names and Compiler_Paths. Name of compiler
-   --  is found in package IDE of the main project, or defaulted.
-   --  Fail if compiler cannot be found on the path. For the Ada language,
-   --  gnatmake, rather than the Ada compiler is returned.
+   --  language, if not already done. Results are in the corresponding elements
+   --  of arrays Compiler_Names and Compiler_Paths. Name of compiler is found
+   --  in package IDE of the main project, or defaulted. Fail if compiler
+   --  cannot be found on the path. For the Ada language, gnatmake, rather than
+   --  the Ada compiler is returned.
 
    procedure Get_Imported_Directories
      (Project : Project_Id;
       Data    : in out Project_Data);
-   --  Find the necessary switches -I to be used when compiling sources
-   --  of languages other than Ada, in a specified project file. Cache the
-   --  result in component Imported_Directories_Switches of the project data.
-   --  For gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
+   --  Find the necessary switches -I to be used when compiling sources of
+   --  languages other than Ada, in a specified project file. Cache the result
+   --  in component Imported_Directories_Switches of the project data. For
+   --  gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
 
    procedure Initialize;
    --  Do the necessary package initialization and process the command line
    --  arguments.
 
    function Is_Included_In_Global_Archive
-     (Object_Name : Name_Id;
+     (Object_Name : File_Name_Type;
       Project     : Project_Id) return Boolean;
    --  Return True if the object Object_Name is not overridden by a source
    --  in a project extending project Project.
@@ -480,9 +490,9 @@ package body Makegpr is
    --  Link executables
 
    procedure Report_Error (S1 : String; S2 : String := ""; S3 : String := "");
-   --  Report an error. If Keep_Going is False, just call Osint.Fail.
-   --  If Keep_Going is True, display the error and increase the total number
-   --  of errors.
+   --  Report an error. If Keep_Going is False, just call Osint.Fail. If
+   --  Keep_Going is True, display the error and increase the total number of
+   --  errors.
 
    procedure Report_Total_Errors (Kind : String);
    --  If Total_Number_Of_Errors is not zero, report it, and fail
@@ -502,9 +512,9 @@ package body Makegpr is
 
    procedure Add_Archives (For_Gnatmake : Boolean) is
       Last_Arg : constant Natural := Last_Argument;
-      --  The position of the last argument before adding the archives.
-      --  Used to reverse the order of the arguments added when processing
-      --  the archives.
+      --  The position of the last argument before adding the archives. Used to
+      --  reverse the order of the arguments added when processing the
+      --  archives.
 
       procedure Recursive_Add_Archives (Project : Project_Id);
       --  Recursive procedure to add the archive of a project file, if any,
@@ -534,14 +544,14 @@ package body Makegpr is
          begin
             if Data.Library then
 
-               --  If it is a library project file, nothing to do if
-               --  gnatmake will be invoked, because gnatmake will take
-               --  care of it, even if the library is not an Ada library.
+               --  If it is a library project file, nothing to do if gnatmake
+               --  will be invoked, because gnatmake will take care of it, even
+               --  if the library is not an Ada library.
 
                if not For_Gnatmake then
                   if Data.Library_Kind = Static then
                      Add_Argument
-                       (Get_Name_String (Data.Library_Dir) &
+                       (Get_Name_String (Data.Display_Library_Dir) &
                         Directory_Separator &
                         "lib" & Get_Name_String (Data.Library_Name) &
                         '.' & Archive_Ext,
@@ -555,24 +565,23 @@ package body Makegpr is
                        ("-l" & Get_Name_String (Data.Library_Name),
                         Verbose_Mode);
 
-                     Get_Name_String (Data.Library_Dir);
+                     Get_Name_String (Data.Display_Library_Dir);
 
                      Add_Argument
                        ("-L" & Name_Buffer (1 .. Name_Len),
                         Verbose_Mode);
 
-                     --  If there is a run path option, prepend this
-                     --  directory to the library path. It is probable
-                     --  that the order of the directories in the path
-                     --  option is not important, but just in case
-                     --  put the directories in the same order as the
-                     --  libraries.
+                     --  If there is a run path option, prepend this directory
+                     --  to the library path. It is probable that the order of
+                     --  the directories in the path option is not important,
+                     --  but just in case put the directories in the same order
+                     --  as the libraries.
 
                      if Path_Option /= null then
 
-                        --  If it is not the first directory, make room
-                        --  at the beginning of the table, including
-                        --  for a path separator.
+                        --  If it is not the first directory, make room at the
+                        --  beginning of the table, including for a path
+                        --  separator.
 
                         if Lib_Path.Last > 0 then
                            Increment := Name_Len + 1;
@@ -603,15 +612,15 @@ package body Makegpr is
                   end if;
                end if;
 
-            --  For a non-library project, the only archive needed
-            --  is the one for the main project, if there is one.
+            --  For a non-library project, the only archive needed is the one
+            --  for the main project, if there is one.
 
             elsif Project = Main_Project and then Global_Archive_Exists then
                Add_Argument
-                 (Get_Name_String (Data.Object_Directory) &
+                 (Get_Name_String (Data.Display_Object_Dir) &
                   Directory_Separator &
-                  "lib" & Get_Name_String (Data.Name) &
-                  '.' & Archive_Ext,
+                  "lib" & Get_Name_String (Data.Display_Name)
+                  '.' & Archive_Ext,
                   Verbose_Mode);
             end if;
          end Add_Archive_Path;
@@ -693,11 +702,13 @@ package body Makegpr is
       --  And reverse the order
 
       declare
-         First : Positive := Last_Arg + 1;
-         Last  : Natural  := Last_Argument;
+         First : Positive;
+         Last  : Natural;
          Temp  : String_Access;
 
       begin
+         First := Last_Arg + 1;
+         Last  := Last_Argument;
          while First < Last loop
             Temp := Arguments (First);
             Arguments (First) := Arguments (Last);
@@ -765,6 +776,7 @@ package body Makegpr is
       --  Nothing to do if argument is empty
 
       if Arg'Length > 0 then
+
          --  Check if the argument is already in the Cache_Args table.
          --  If it is already there, reuse the allocated value.
 
@@ -924,7 +936,7 @@ package body Makegpr is
      (Data      : Project_Data;
       Proc      : Processor;
       Language  : Language_Index;
-      File_Name : Name_Id)
+      File_Name : File_Name_Type)
    is
       Switches       : Variable_Value;
       --  The switches, if any, for the file/language
@@ -956,6 +968,7 @@ package body Makegpr is
       end case;
 
       if Pkg /= No_Package then
+
          --  Get the Switches ("file name"), if they exist
 
          Switches_Array := Prj.Util.Value_Of
@@ -966,7 +979,7 @@ package body Makegpr is
 
          Switches :=
            Prj.Util.Value_Of
-             (Index     => File_Name,
+             (Index     => Name_Id (File_Name),
               Src_Index => 0,
               In_Array  => Switches_Array,
               In_Tree   => Project_Tree);
@@ -1020,37 +1033,52 @@ package body Makegpr is
    --------------------------
 
    procedure Build_Global_Archive is
-      Data      : Project_Data :=
-                    Project_Tree.Projects.Table (Main_Project);
+      Data      : Project_Data := Project_Tree.Projects.Table (Main_Project);
       Source_Id : Other_Source_Id;
+      S_Id      : Other_Source_Id;
       Source    : Other_Source;
       Success   : Boolean;
 
       Archive_Name : constant String :=
-        "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
+                       "lib"
+                         & Get_Name_String (Data.Display_Name)
+                         & '.'
+                         & Archive_Ext;
       --  The name of the archive file for this project
 
       Archive_Dep_Name : constant String :=
-        "lib" & Get_Name_String (Data.Name) & ".deps";
+                           "lib"
+                             & Get_Name_String (Data.Display_Name)
+                             & ".deps";
       --  The name of the archive dependency file for this project
 
       Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
       --  When True, archive will be rebuilt
 
-      File : Prj.Util.Text_File;
-
-      Object_Path  : Name_Id;
-      Time_Stamp   : Time_Stamp_Type;
-
+      File                : Prj.Util.Text_File;
+      Object_Path         : Path_Name_Type;
+      Time_Stamp          : Time_Stamp_Type;
       Saved_Last_Argument : Natural;
       First_Object        : Natural;
 
       Discard : Boolean;
+      pragma Warnings (Off, Discard);
 
    begin
       Check_Archive_Builder;
 
-      Change_Dir (Get_Name_String (Data.Object_Directory));
+      if Project_Of_Current_Object_Directory /= Main_Project then
+         Project_Of_Current_Object_Directory := Main_Project;
+         Change_Dir (Get_Name_String (Data.Object_Directory));
+
+         if Verbose_Mode then
+            Write_Str  ("Changing to object directory of """);
+            Write_Name (Data.Display_Name);
+            Write_Str  (""": """);
+            Write_Name (Data.Display_Object_Dir);
+            Write_Line ("""");
+         end if;
+      end if;
 
       if not Need_To_Rebuild then
          if Verbose_Mode then
@@ -1075,7 +1103,7 @@ package body Makegpr is
             Open (File, Archive_Dep_Name);
 
             --  If the archive dependency file does not exist, we need to
-            --  to rebuild the archive and to create its dependency file.
+            --  rebuild the archive and to create its dependency file.
 
             if not Is_Valid (File) then
                Need_To_Rebuild := True;
@@ -1087,25 +1115,29 @@ package body Makegpr is
                end if;
 
             else
-               --  Put all sources of language other than Ada in
-               --  Source_Indexes.
+               --  Put all sources of language other than Ada in Source_Indexes
 
-               for Proj in Project_Table.First ..
-                           Project_Table.Last (Project_Tree.Projects)
-               loop
-                  Data := Project_Tree.Projects.Table (Proj);
+               declare
+                  Local_Data : Project_Data;
 
-                  if not Data.Library then
-                     Last_Source := 0;
-                     Source_Id := Data.First_Other_Source;
+               begin
+                  Last_Source := 0;
 
-                     while Source_Id /= No_Other_Source loop
-                        Add_Source_Id (Proj, Source_Id);
-                        Source_Id := Project_Tree.Other_Sources.Table
-                                       (Source_Id).Next;
-                     end loop;
-                  end if;
-               end loop;
+                  for Proj in Project_Table.First ..
+                    Project_Table.Last (Project_Tree.Projects)
+                  loop
+                     Local_Data := Project_Tree.Projects.Table (Proj);
+
+                     if not Local_Data.Library then
+                        Source_Id := Local_Data.First_Other_Source;
+                        while Source_Id /= No_Other_Source loop
+                           Add_Source_Id (Proj, Source_Id);
+                           Source_Id := Project_Tree.Other_Sources.Table
+                             (Source_Id).Next;
+                        end loop;
+                     end if;
+                  end loop;
+               end;
 
                --  Read the dependency file, line by line
 
@@ -1120,16 +1152,16 @@ package body Makegpr is
                   --  Check if this object file is for a source of this project
 
                   for S in 1 .. Last_Source loop
-                     Source_Id := Source_Indexes (S).Id;
-                     Source := Project_Tree.Other_Sources.Table
-                                 (Source_Id);
+                     S_Id := Source_Indexes (S).Id;
+                     Source := Project_Tree.Other_Sources.Table (S_Id);
 
                      if (not Source_Indexes (S).Found)
                        and then Source.Object_Path = Object_Path
                      then
-                        --  We have found the object file: get the source
-                        --  data, and mark it as found.
+                        --  We have found the object file: get the source data,
+                        --  and mark it as found.
 
+                        Source_Id := S_Id;
                         Source_Indexes (S).Found := True;
                         exit;
                      end if;
@@ -1149,8 +1181,8 @@ package body Makegpr is
                      exit;
                   end if;
 
-                  --  The second line is the time stamp of the object file.
-                  --  If there is no next line, then the dependency file is
+                  --  The second line is the time stamp of the object file. If
+                  --  there is no next line, then the dependency file is
                   --  truncated, and the archive need to be rebuilt.
 
                   if End_Of_File (File) then
@@ -1248,19 +1280,19 @@ package body Makegpr is
 
             if not Data.Library then
                Source_Id := Data.First_Other_Source;
-
                while Source_Id /= No_Other_Source loop
                   Source :=
                     Project_Tree.Other_Sources.Table (Source_Id);
 
                   --  Only include object file name that have not been
-                  --  overriden in extending projects.
+                  --  overridden in extending projects.
 
                   if Is_Included_In_Global_Archive
                        (Source.Object_Name, Proj)
                   then
                      Add_Argument
-                       (Get_Name_String (Source.Object_Path), Verbose_Mode);
+                       (Get_Name_String (Source.Object_Path),
+                        Verbose_Mode or (First_Object = Last_Argument));
                   end if;
 
                   Source_Id := Source.Next;
@@ -1289,16 +1321,18 @@ package body Makegpr is
                   Last_Argument := Saved_Last_Argument;
                end if;
 
-               Display_Command (Archive_Builder, Archive_Builder_Path);
+               Display_Command
+                 (Archive_Builder,
+                  Archive_Builder_Path,
+                  Ellipse => True);
 
                Spawn
                  (Archive_Builder_Path.all,
                   Arguments (1 .. Last_Argument),
                   Success);
 
-               exit when not Success;
-
-               exit when Last_Argument = Saved_Last_Argument;
+               exit when not Success
+                 or else Last_Argument = Saved_Last_Argument;
 
                Arguments (1) := r;
                Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
@@ -1311,9 +1345,6 @@ package body Makegpr is
 
             if Success then
 
-               --  If the archive was built, run the archive indexer (ranlib),
-               --  if there is one.
-
                if Archive_Indexer_Path /= null then
                   Last_Argument := 0;
                   Add_Argument (Archive_Name, True);
@@ -1336,7 +1367,7 @@ package body Makegpr is
 
                      Report_Error
                        ("running" & Archive_Indexer & " for project """,
-                        Get_Name_String (Data.Name),
+                        Get_Name_String (Data.Display_Name),
                         """ failed");
                      return;
                   end if;
@@ -1358,7 +1389,7 @@ package body Makegpr is
 
                Report_Error
                  ("building archive for project """,
-                  Get_Name_String (Data.Name),
+                  Get_Name_String (Data.Display_Name),
                   """ failed");
             end if;
          end if;
@@ -1376,11 +1407,13 @@ package body Makegpr is
       Source    : Other_Source;
 
       Archive_Name : constant String :=
-                       "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
+                       "lib" & Get_Name_String (Data.Library_Name)
+                       & '.' & Archive_Ext;
       --  The name of the archive file for this project
 
       Archive_Dep_Name : constant String :=
-                           "lib" & Get_Name_String (Data.Name) & ".deps";
+                           "lib" & Get_Name_String (Data.Library_Name)
+                           & ".deps";
       --  The name of the archive dependency file for this project
 
       Need_To_Rebuild : Boolean := Unconditionally;
@@ -1388,12 +1421,19 @@ package body Makegpr is
 
       File : Prj.Util.Text_File;
 
-      Object_Name : Name_Id;
+      Object_Name : File_Name_Type;
       Time_Stamp  : Time_Stamp_Type;
       Driver_Name : Name_Id := No_Name;
 
-      Lib_Opts : Argument_List_Access := No_Argument'Access;
+      Lib_Opts    : Argument_List_Access := No_Argument'Access;
+
    begin
+      --  Nothing to do if the project is externally built
+
+      if Data.Externally_Built then
+         return;
+      end if;
+
       Check_Archive_Builder;
 
       --  If Unconditionally is False, check if the archive need to be built
@@ -1421,7 +1461,7 @@ package body Makegpr is
             Open (File, Archive_Dep_Name);
 
             --  If the archive dependency file does not exist, we need to
-            --  to rebuild the archive and to create its dependency file.
+            --  rebuild the archive and to create its dependency file.
 
             if not Is_Valid (File) then
                Need_To_Rebuild := True;
@@ -1436,12 +1476,12 @@ package body Makegpr is
                --  Put all sources of language other than Ada in Source_Indexes
 
                Last_Source := 0;
-               Source_Id := Data.First_Other_Source;
 
+               Source_Id := Data.First_Other_Source;
                while Source_Id /= No_Other_Source loop
                   Add_Source_Id (Project, Source_Id);
-                  Source_Id := Project_Tree.Other_Sources.Table
-                                 (Source_Id).Next;
+                  Source_Id :=
+                    Project_Tree.Other_Sources.Table (Source_Id).Next;
                end loop;
 
                --  Read the dependency file, line by line
@@ -1585,15 +1625,14 @@ package body Makegpr is
 
          Last_Argument := 0;
 
-         --  If there are sources in Ada, then gnatmake will build the
-         --  library, so nothing to do.
+         --  If there are sources in Ada, then gnatmake will build the library,
+         --  so nothing to do.
 
-         if not Data.Languages (Ada_Language_Index) then
+         if not Data.Langs (Ada_Language_Index) then
 
             --  Get all the object files of the project
 
             Source_Id := Data.First_Other_Source;
-
             while Source_Id /= No_Other_Source loop
                Source := Project_Tree.Other_Sources.Table (Source_Id);
                Add_Argument
@@ -1601,15 +1640,14 @@ package body Makegpr is
                Source_Id := Source.Next;
             end loop;
 
-            --  If it is a library, it need to be built it the same way
-            --  Ada libraries are built.
+            --  If it is a library, it need to be built it the same way Ada
+            --  libraries are built.
 
             if Data.Library_Kind = Static then
                MLib.Build_Library
                  (Ofiles      => Arguments (1 .. Last_Argument),
-                  Afiles      => No_Argument,
                   Output_File => Get_Name_String (Data.Library_Name),
-                  Output_Dir  => Get_Name_String (Data.Library_Dir));
+                  Output_Dir  => Get_Name_String (Data.Display_Library_Dir));
 
             else
                --  Link with g++ if C++ is one of the languages, otherwise
@@ -1640,13 +1678,14 @@ package body Makegpr is
                begin
                   if not Library_Options.Default then
                      declare
-                        Current : String_List_Id := Library_Options.Values;
+                        Current : String_List_Id;
                         Element : String_Element;
 
                      begin
+                        Current := Library_Options.Values;
                         while Current /= Nil_String loop
-                           Element := Project_Tree.String_Elements.
-                                        Table (Current);
+                           Element :=
+                             Project_Tree.String_Elements.Table (Current);
                            Get_Name_String (Element.Value);
 
                            if Name_Len /= 0 then
@@ -1667,10 +1706,7 @@ package body Makegpr is
 
                MLib.Tgt.Build_Dynamic_Library
                  (Ofiles       => Arguments (1 .. Last_Argument),
-                  Foreign      => Arguments (1 .. Last_Argument),
-                  Afiles       => No_Argument,
-                  Options      => No_Argument,
-                  Options_2    => Lib_Opts.all,
+                  Options      => Lib_Opts.all,
                   Interfaces   => No_Argument,
                   Lib_Filename => Get_Name_String (Data.Library_Name),
                   Lib_Dir      => Get_Name_String (Data.Library_Dir),
@@ -1685,7 +1721,6 @@ package body Makegpr is
 
          declare
             Archive : Ada.Text_IO.File_Type;
-            use Ada.Text_IO;
          begin
             Create (Archive, Out_File, Archive_Name);
             Close (Archive);
@@ -1784,10 +1819,16 @@ package body Makegpr is
      (Source          : Other_Source;
       Need_To_Compile : out Boolean)
    is
-      Source_Name : constant String := Get_Name_String (Source.File_Name);
-      Source_Path : constant String := Get_Name_String (Source.Path_Name);
-      Object_Name : constant String := Get_Name_String (Source.Object_Name);
-      Dep_Name    : constant String := Get_Name_String (Source.Dep_Name);
+      Source_Name   : constant String := Get_Name_String (Source.File_Name);
+      Source_Path   : constant String := Get_Name_String (Source.Path_Name);
+      Object_Name   : constant String := Get_Name_String (Source.Object_Name);
+      C_Object_Name : String := Object_Name;
+      Dep_Name      : constant String := Get_Name_String (Source.Dep_Name);
+      C_Source_Path : constant String :=
+                        Normalize_Pathname
+                          (Name           => Source_Path,
+                           Resolve_Links  => False,
+                           Case_Sensitive => False);
 
       Source_In_Dependencies : Boolean := False;
       --  Set True if source was found in dependency file of its object file
@@ -1796,7 +1837,12 @@ package body Makegpr is
       Start    : Natural;
       Finish   : Natural;
 
+      Looping : Boolean := False;
+      --  Set to True at the end of the first Big_Loop
+
    begin
+      Canonical_Case_File_Name (C_Object_Name);
+
       --  Assume the worst, so that statement "return;" may be used if there
       --  is any problem.
 
@@ -1874,162 +1920,217 @@ package body Makegpr is
          return;
       end if;
 
-      declare
-         End_Of_File_Reached : Boolean := False;
+      --  Loop Big_Loop is executed several times only when the dependency file
+      --  contains several times
+      --     <object file>: <source1> ...
+      --  When there is only one of such occurrence, Big_Loop is exited
+      --  successfully at the beginning of the second loop.
 
-      begin
-         loop
-            if End_Of_File (Dep_File) then
-               End_Of_File_Reached := True;
-               exit;
+      Big_Loop :
+      loop
+         declare
+            End_Of_File_Reached : Boolean := False;
+
+         begin
+            loop
+               if End_Of_File (Dep_File) then
+                  End_Of_File_Reached := True;
+                  exit;
+               end if;
+
+               Get_Line (Dep_File, Name_Buffer, Name_Len);
+
+               exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
+            end loop;
+
+            --  If dependency file contains only empty lines or comments, then
+            --  dependencies are unknown, and the source needs to be
+            --  recompiled.
+
+            if End_Of_File_Reached then
+               --  If we have reached the end of file after the first loop,
+               --  there is nothing else to do.
+
+               exit Big_Loop when Looping;
+
+               if Verbose_Mode then
+                  Write_Str  ("      -> dependency file ");
+                  Write_Str  (Dep_Name);
+                  Write_Line (" is empty");
+               end if;
+
+               Close (Dep_File);
+               return;
             end if;
+         end;
 
-            Get_Line (Dep_File, Name_Buffer, Name_Len);
+         Start  := 1;
+         Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
 
-            exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
-         end loop;
+         if Finish /= 0 then
+            Canonical_Case_File_Name (Name_Buffer (1 .. Finish - 1));
+         end if;
 
-         --  If dependency file contains only empty lines or comments, then
-         --  dependencies are unknown, and the source needs to be recompiled.
+         --  First line must start with name of object file, followed by colon
 
-         if End_Of_File_Reached then
+         if Finish = 0 or else
+            Name_Buffer (1 .. Finish - 1) /= C_Object_Name
+         then
             if Verbose_Mode then
                Write_Str  ("      -> dependency file ");
                Write_Str  (Dep_Name);
-               Write_Line (" is empty");
+               Write_Line (" has wrong format");
             end if;
 
             Close (Dep_File);
             return;
-         end if;
-      end;
 
-      Start  := 1;
-      Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
+         else
+            Start := Finish + 2;
 
-      --  First line must start with name of object file, followed by colon
+            --  Process each line
 
-      if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
-         if Verbose_Mode then
-            Write_Str  ("      -> dependency file ");
-            Write_Str  (Dep_Name);
-            Write_Line (" has wrong format");
-         end if;
-
-         Close (Dep_File);
-         return;
+            Line_Loop : loop
+               declare
+                  Line : String  := Name_Buffer (1 .. Name_Len);
+                  Last : Natural := Name_Len;
 
-      else
-         Start := Finish + 2;
+               begin
+                  Name_Loop : loop
 
-         --  Process each line
+                     --  Find the beginning of the next source path name
 
-         Line_Loop : loop
-            declare
-               Line : constant String  := Name_Buffer (1 .. Name_Len);
-               Last : constant Natural := Name_Len;
+                     while Start < Last and then Line (Start) = ' ' loop
+                        Start := Start + 1;
+                     end loop;
 
-            begin
-               Name_Loop : loop
+                     --  Go to next line when there is a continuation character
+                     --  \ at the end of the line.
 
-                  --  Find the beginning of the next source path name
+                     exit Name_Loop when Start = Last
+                       and then Line (Start) = '\';
 
-                  while Start < Last and then Line (Start) = ' ' loop
-                     Start := Start + 1;
-                  end loop;
+                     --  We should not be at the end of the line, without
+                     --  a continuation character \.
 
-                  --  Go to next line when there is a continuation character \
-                  --  at the end of the line.
+                     if Start = Last then
+                        if Verbose_Mode then
+                           Write_Str  ("      -> dependency file ");
+                           Write_Str  (Dep_Name);
+                           Write_Line (" has wrong format");
+                        end if;
 
-                  exit Name_Loop when Start = Last
-                                   and then Line (Start) = '\';
+                        Close (Dep_File);
+                        return;
+                     end if;
 
-                  --  We should not be at the end of the line, without
-                  --  a continuation character \.
+                     --  Look for the end of the source path name
+
+                     Finish := Start;
+                     while Finish < Last loop
+                        if Line (Finish) = '\' then
+
+                           --  On Windows, a '\' is part of the path name,
+                           --  except when it is followed by another '\' or by
+                           --  a space. On other platforms, when we are getting
+                           --  a '\' that is not the last character of the
+                           --  line, the next character is part of the path
+                           --  name, even if it is a space.
+
+                           if On_Windows
+                             and then Line (Finish + 1) /= '\'
+                             and then Line (Finish + 1) /= ' '
+                           then
+                              Finish := Finish + 1;
+
+                           else
+                              Line (Finish .. Last - 1) :=
+                                Line (Finish + 1 .. Last);
+                              Last := Last - 1;
+                           end if;
 
-                  if Start = Last then
-                     if Verbose_Mode then
-                        Write_Str  ("      -> dependency file ");
-                        Write_Str  (Dep_Name);
-                        Write_Line (" has wrong format");
-                     end if;
+                        else
+                           --  A space that is not preceded by '\' indicates
+                           --  the end of the path name.
 
-                     Close (Dep_File);
-                     return;
-                  end if;
+                           exit when Line (Finish + 1) = ' ';
 
-                  --  Look for the end of the source path name
+                           Finish := Finish + 1;
+                        end if;
+                     end loop;
 
-                  Finish := Start;
-                  while Finish < Last and then Line (Finish + 1) /= ' ' loop
-                     Finish := Finish + 1;
-                  end loop;
+                     --  Check this source
 
-                  --  Check this source
+                     declare
+                        Src_Name : constant String :=
+                                     Normalize_Pathname
+                                       (Name           =>
+                                                       Line (Start .. Finish),
+                                        Resolve_Links  => False,
+                                        Case_Sensitive => False);
+                        Src_TS   : Time_Stamp_Type;
 
-                  declare
-                     Src_Name : constant String :=
-                                  Normalize_Pathname
-                                    (Name           => Line (Start .. Finish),
-                                     Case_Sensitive => False);
-                     Src_TS   : Time_Stamp_Type;
+                     begin
+                        --  If it is original source, set
+                        --  Source_In_Dependencies.
 
-                  begin
-                     --  If it is original source, set Source_In_Dependencies
+                        if Src_Name = C_Source_Path then
+                           Source_In_Dependencies := True;
+                        end if;
 
-                     if Src_Name = Source_Path then
-                        Source_In_Dependencies := True;
-                     end if;
+                        Name_Len := 0;
+                        Add_Str_To_Name_Buffer (Src_Name);
+                        Src_TS := File_Stamp (File_Name_Type'(Name_Find));
 
-                     Name_Len := 0;
-                     Add_Str_To_Name_Buffer (Src_Name);
-                     Src_TS := File_Stamp (Name_Find);
+                        --  If the source does not exist, we need to recompile
 
-                     --  If the source does not exist, we need to recompile
+                        if Src_TS = Empty_Time_Stamp then
+                           if Verbose_Mode then
+                              Write_Str  ("      -> source ");
+                              Write_Str  (Src_Name);
+                              Write_Line (" does not exist");
+                           end if;
 
-                     if Src_TS = Empty_Time_Stamp then
-                        if Verbose_Mode then
-                           Write_Str  ("      -> source ");
-                           Write_Str  (Src_Name);
-                           Write_Line (" does not exist");
-                        end if;
+                           Close (Dep_File);
+                           return;
 
-                        Close (Dep_File);
-                        return;
+                           --  If the source has been modified after the object
+                           --  file, we need to recompile.
 
-                     --  If the source has been modified after the object file,
-                     --  we need to recompile.
+                        elsif Src_TS > Source.Object_TS then
+                           if Verbose_Mode then
+                              Write_Str  ("      -> source ");
+                              Write_Str  (Src_Name);
+                              Write_Line
+                                (" has time stamp later than object file");
+                           end if;
 
-                     elsif Src_TS > Source.Object_TS then
-                        if Verbose_Mode then
-                           Write_Str  ("      -> source ");
-                           Write_Str  (Src_Name);
-                           Write_Line
-                             (" has time stamp later than object file");
+                           Close (Dep_File);
+                           return;
                         end if;
+                     end;
 
-                        Close (Dep_File);
-                        return;
-                     end if;
-                  end;
+                     --  If the source path name ends the line, we are done
 
-                  --  If the source path name ends the line, we are done.
+                     exit Line_Loop when Finish = Last;
 
-                  exit Line_Loop when Finish = Last;
+                     --  Go get the next source on the line
 
-                  --  Go get the next source on the line
+                     Start := Finish + 1;
+                  end loop Name_Loop;
+               end;
 
-                  Start := Finish + 1;
-               end loop Name_Loop;
-            end;
+               --  If we are here, we had a continuation character \ at the end
+               --  of the line, so we continue with the next line.
 
-            --  If we are here, we had a continuation character \ at the end
-            --  of the line, so we continue with the next line.
+               Get_Line (Dep_File, Name_Buffer, Name_Len);
+               Start := 1;
+            end loop Line_Loop;
+         end if;
 
-            Get_Line (Dep_File, Name_Buffer, Name_Len);
-            Start := 1;
-         end loop Line_Loop;
-      end if;
+         --  Set Looping at the end of the first loop
+         Looping := True;
+      end loop Big_Loop;
 
       Close (Dep_File);
 
@@ -2047,8 +2148,7 @@ package body Makegpr is
          return;
       end if;
 
-      --  If we are here, then everything is OK, and we don't need
-      --  to recompile.
+      --  If we are here, then everything is OK, no need to recompile
 
       if Verbose_Mode then
          Write_Line ("      -> up to date");
@@ -2069,7 +2169,7 @@ package body Makegpr is
                      Project_Table.Last (Project_Tree.Projects)
       loop
          if
-           Project_Tree.Projects.Table (Project).Languages
+           Project_Tree.Projects.Table (Project).Langs
                                            (C_Plus_Plus_Language_Index)
          then
             C_Plus_Plus_Is_Used := True;
@@ -2084,11 +2184,11 @@ package body Makegpr is
 
    procedure Compile
      (Source_Id    : Other_Source_Id;
-      Data         : in Project_Data;
+      Data         : Project_Data;
       Local_Errors : in out Boolean)
    is
       Source  : Other_Source :=
-        Project_Tree.Other_Sources.Table (Source_Id);
+                  Project_Tree.Other_Sources.Table (Source_Id);
       Success : Boolean;
       CPATH   : String_Access := null;
 
@@ -2146,7 +2246,9 @@ package body Makegpr is
             declare
                Dep_File : Ada.Text_IO.File_Type;
                Result   : Expect_Match;
-               Status   : Integer;
+
+               Status : Integer;
+               pragma Warnings (Off, Status);
 
             begin
                --  Create the dependency file
@@ -2181,14 +2283,14 @@ package body Makegpr is
                Delete_File (Get_Name_String (Source.Dep_Name), Success);
 
             exception
-            when Process_Died =>
+               when Process_Died =>
 
                   --  This is the normal outcome. Just close the file
 
                   Close (FD, Status);
                   Close (Dep_File);
 
-            when others =>
+               when others =>
 
                   --  Something wrong happened. It is safer to delete the
                   --  dependency file, otherwise the dependencies may be wrong.
@@ -2227,8 +2329,8 @@ package body Makegpr is
 
       Add_Argument (Dash_c, True);
 
-      --  Add the compiling switches for this source found in
-      --  package Compiler of the project file, if they exist.
+      --  Add the compiling switches for this source found in package Compiler
+      --  of the project file, if they exist.
 
       Add_Switches
         (Data, Compiler, Source.Language, Source.File_Name);
@@ -2238,9 +2340,8 @@ package body Makegpr is
       Add_Argument (Get_Name_String (Source.Path_Name), True);
 
       --  If non static library project, compile with the PIC option if there
-      --  is one (when there is no PIC option, function MLib.Tgt.PIC_Option
-      --  returns an empty string, and Add_Argument with an empty string has
-      --  no effect).
+      --  is one (when there is no PIC option, MLib.Tgt.PIC_Option returns an
+      --  empty string, and Add_Argument with an empty string has no effect).
 
       if Data.Library and then Data.Library_Kind /= Static then
          Add_Argument (PIC_Option, True);
@@ -2251,8 +2352,8 @@ package body Makegpr is
       Add_Argument (Dash_o, True);
       Add_Argument (Get_Name_String (Source.Object_Name), True);
 
-      --  When compiler is GCC, use the magic switch that creates
-      --  the dependency file in the correct format.
+      --  When compiler is GCC, use the magic switch that creates the
+      --  dependency file in the correct format.
 
       if Compiler_Is_Gcc (Source.Language) then
          Add_Argument
@@ -2260,16 +2361,15 @@ package body Makegpr is
             Verbose_Mode);
       end if;
 
-      --  Add the compiling switches for the language specified
-      --  on the command line, if any.
+      --  Add the compiling switches for the language specified on the command
+      --  line, if any.
 
       for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
          Add_Argument (Options (Source.Language).Table (J), True);
       end loop;
 
-      --  Finally, add the imported directory switches for this
-      --  project file (or, for gcc compilers, set up the CPATH env var
-      --  if needed).
+      --  Finally, add the imported directory switches for this project file
+      --  (or, for gcc compilers, set up the CPATH env var if needed).
 
       Add_Search_Directories (Data, Source.Language);
 
@@ -2341,12 +2441,12 @@ package body Makegpr is
                        Project_Tree.Projects.Table (Main_Project);
       Source_Id    : Other_Source_Id;
       Source       : Other_Source;
-      Source_Name  : Name_Id;
+      Source_Name  : File_Name_Type;
       Project_Name : String := Get_Name_String (Data.Name);
       Dummy        : Boolean := False;
 
       Ada_Is_A_Language : constant Boolean :=
-                            Data.Languages (Ada_Language_Index);
+                            Data.Langs (Ada_Language_Index);
 
    begin
       Ada_Mains.Init;
@@ -2358,7 +2458,18 @@ package body Makegpr is
 
       --  Compilation will occur in the object directory
 
-      Change_Dir (Get_Name_String (Data.Object_Directory));
+      if Project_Of_Current_Object_Directory /= Main_Project then
+         Project_Of_Current_Object_Directory := Main_Project;
+         Change_Dir (Get_Name_String (Data.Object_Directory));
+
+         if Verbose_Mode then
+            Write_Str  ("Changing to object directory of """);
+            Write_Name (Data.Name);
+            Write_Str  (""": """);
+            Write_Name (Data.Display_Object_Dir);
+            Write_Line ("""");
+         end if;
+      end if;
 
       if not Data.Other_Sources_Present then
          if Ada_Is_A_Language then
@@ -2375,8 +2486,7 @@ package body Makegpr is
             end loop;
 
          else
-            Osint.Fail
-              ("project ", Project_Name, " contains no source");
+            Osint.Fail ("project ", Project_Name, " contains no source");
          end if;
 
       else
@@ -2394,11 +2504,10 @@ package body Makegpr is
 
                if not Sources_Compiled.Get (Source_Name) then
                   Sources_Compiled.Set (Source_Name, True);
-                  Source_Id := Data.First_Other_Source;
 
+                  Source_Id := Data.First_Other_Source;
                   while Source_Id /= No_Other_Source loop
-                     Source :=
-                       Project_Tree.Other_Sources.Table (Source_Id);
+                     Source := Project_Tree.Other_Sources.Table (Source_Id);
                      exit when Source.File_Name = Source_Name;
                      Source_Id := Source.Next;
                   end loop;
@@ -2458,12 +2567,12 @@ package body Makegpr is
       --  Specify the project file
 
       Add_Argument (Dash_P, True);
-      Add_Argument (Get_Name_String (Data.Path_Name), True);
+      Add_Argument (Get_Name_String (Data.Display_Path_Name), True);
 
-      --  Add the -X switches, if any
+      --  Add the saved switches, if any
 
-      for Index in 1 .. X_Switches.Last loop
-         Add_Argument (X_Switches.Table (Index), True);
+      for Index in 1 .. Saved_Switches.Last loop
+         Add_Argument (Saved_Switches.Table (Index), True);
       end loop;
 
       --  If Mains_Specified is True, find the mains in package Mains
@@ -2502,6 +2611,12 @@ package body Makegpr is
          Add_Argument (Dash_d, True);
       end if;
 
+      --  -eL
+
+      if Follow_Links_For_Files then
+         Add_Argument (Dash_eL, True);
+      end if;
+
       --  -k
 
       if Keep_Going then
@@ -2590,7 +2705,6 @@ package body Makegpr is
             Compiler_Names (Ada_Language_Index).all,
             " failed");
       end if;
-
    end Compile_Link_With_Gnatmake;
 
    ---------------------
@@ -2607,7 +2721,7 @@ package body Makegpr is
       --  Keep_Going is True, to inhibit the building of the archive.
 
       Need_To_Compile : Boolean;
-      --  Set to True when a source needs to be compiled/recompiled.
+      --  Set to True when a source needs to be compiled/recompiled
 
       Need_To_Rebuild_Archive : Boolean := Force_Compilations;
       --  True when the archive needs to be built/rebuilt unconditionally
@@ -2624,7 +2738,7 @@ package body Makegpr is
       loop
          Data := Project_Tree.Projects.Table (Project);
 
-         if (not Data.Virtual) and then Data.Other_Sources_Present then
+         if not Data.Virtual and then Data.Other_Sources_Present then
             Source_Id := Data.First_Other_Source;
             while Source_Id /= No_Other_Source loop
                Source := Project_Tree.Other_Sources.Table (Source_Id);
@@ -2658,14 +2772,23 @@ package body Makegpr is
 
             --  Compilation will occur in the object directory
 
-            Change_Dir (Get_Name_String (Data.Object_Directory));
+            if Project_Of_Current_Object_Directory /= Project then
+               Project_Of_Current_Object_Directory := Project;
+               Change_Dir (Get_Name_String (Data.Object_Directory));
 
-            Source_Id := Data.First_Other_Source;
+               if Verbose_Mode then
+                  Write_Str  ("Changing to object directory of """);
+                  Write_Name (Data.Display_Name);
+                  Write_Str  (""": """);
+                  Write_Name (Data.Display_Object_Dir);
+                  Write_Line ("""");
+               end if;
+            end if;
 
             --  Process each source one by one
 
+            Source_Id := Data.First_Other_Source;
             while Source_Id /= No_Other_Source loop
-
                Source := Project_Tree.Other_Sources.Table (Source_Id);
                Current_Source_Number := Current_Source_Number + 1;
                Need_To_Compile := Force_Compilations;
@@ -2713,7 +2836,7 @@ package body Makegpr is
 
             if not Local_Errors
               and then Data.Library
-              and then not Data.Languages (Ada_Language_Index)
+              and then not Data.Langs (Ada_Language_Index)
               and then not Compile_Only
             then
                Build_Library (Project, Need_To_Rebuild_Archive);
@@ -2735,7 +2858,9 @@ package body Makegpr is
          Write_Eol;
          Write_Str ("GPRMAKE ");
          Write_Str (Gnatvsn.Gnat_Version_String);
-         Write_Str (" Copyright 2004 Free Software Foundation, Inc.");
+         Write_Str (" Copyright 2004-");
+         Write_Str (Gnatvsn.Current_Year);
+         Write_Str (" Free Software Foundation, Inc.");
          Write_Eol;
       end if;
    end Copyright;
@@ -2748,10 +2873,9 @@ package body Makegpr is
      (Name         : String;
       First_Source : Other_Source_Id)
    is
-      Source_Id : Other_Source_Id := First_Source;
+      Source_Id : Other_Source_Id;
       Source    : Other_Source;
       Dep_File  : Ada.Text_IO.File_Type;
-      use Ada.Text_IO;
 
    begin
       --  Create the file in Append mode, to avoid automatic insertion of
@@ -2759,6 +2883,7 @@ package body Makegpr is
 
       Create (Dep_File, Append_File, Name);
 
+      Source_Id := First_Source;
       while Source_Id /= No_Other_Source loop
          Source := Project_Tree.Other_Sources.Table (Source_Id);
          Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
@@ -2784,8 +2909,6 @@ package body Makegpr is
       Source    : Other_Source;
       Dep_File  : Ada.Text_IO.File_Type;
 
-      use Ada.Text_IO;
-
    begin
       --  Create the file in Append mode, to avoid automatic insertion of
       --  an end of line if file is empty.
@@ -2800,7 +2923,6 @@ package body Makegpr is
          if not Project_Tree.Projects.Table (Project).Library then
             Source_Id :=
               Project_Tree.Projects.Table (Project).First_Other_Source;
-
             while Source_Id /= No_Other_Source loop
                Source := Project_Tree.Other_Sources.Table (Source_Id);
 
@@ -2832,10 +2954,13 @@ package body Makegpr is
    ---------------------
 
    procedure Display_Command
-     (Name  : String;
-      Path  : String_Access;
-      CPATH : String_Access := null)
+     (Name    : String;
+      Path    : String_Access;
+      CPATH   : String_Access := null;
+      Ellipse : Boolean := False)
    is
+      Display_Ellipse : Boolean := Ellipse;
+
    begin
       --  Only display the command in Verbose Mode (-v) or when
       --  not in Quiet Output (no -q).
@@ -2863,6 +2988,10 @@ package body Makegpr is
             if Arguments_Displayed (Arg) then
                Write_Char (' ');
                Write_Str (Arguments (Arg).all);
+
+            elsif Display_Ellipse then
+               Write_Str (" ...");
+               Display_Ellipse := False;
             end if;
          end loop;
 
@@ -2909,7 +3038,7 @@ package body Makegpr is
 
             else
                Osint.Fail
-                 ("unknow compiler name for language """,
+                 ("unknown compiler name for language """,
                   Get_Name_String (Language_Names.Table (For_Language)),
                   """");
             end if;
@@ -2983,20 +3112,22 @@ package body Makegpr is
       ---------
 
       procedure Add (Source_Dirs : String_List_Id) is
-         Element_Id : String_List_Id := Source_Dirs;
+         Element_Id : String_List_Id;
          Element    : String_Element;
          Add_Arg    : Boolean := True;
 
       begin
          --  Add each source directory path name, preceded by "-I" to Arguments
 
+         Element_Id := Source_Dirs;
          while Element_Id /= Nil_String loop
             Element := Project_Tree.String_Elements.Table (Element_Id);
 
             if Element.Value /= No_Name then
-               Get_Name_String (Element.Value);
+               Get_Name_String (Element.Display_Value);
 
                if Name_Len > 0 then
+
                   --  Remove a trailing directory separator: this may cause
                   --  problems on Windows.
 
@@ -3010,8 +3141,10 @@ package body Makegpr is
                      Arg : constant String :=
                              "-I" & Name_Buffer (1 .. Name_Len);
                   begin
-                     --  Check if directory is already in the list.
-                     --  If it is, no need to put it again.
+                     --  Check if directory is already in the list. If it is,
+                     --  no need to put it there again.
+
+                     Add_Arg := True;
 
                      for Index in 1 .. Last_Argument loop
                         if Arguments (Index).all = Arg then
@@ -3068,14 +3201,12 @@ package body Makegpr is
 
                Recursive_Get_Dirs (Data.Extends);
 
-               Imported := Data.Imported_Projects;
-
                --  Call itself for all imported projects, if any
 
+               Imported := Data.Imported_Projects;
                while Imported /= Empty_Project_List loop
                   Recursive_Get_Dirs
-                    (Project_Tree.Project_Lists.Table
-                       (Imported).Project);
+                    (Project_Tree.Project_Lists.Table (Imported).Project);
                   Imported :=
                     Project_Tree.Project_Lists.Table (Imported).Next;
                end loop;
@@ -3146,7 +3277,7 @@ package body Makegpr is
 
       if Verbose_Mode then
          Write_Eol;
-         Write_Str ("Parsing Project File """);
+         Write_Str ("Parsing project file """);
          Write_Str (Project_File_Name.all);
          Write_Str (""".");
          Write_Eol;
@@ -3168,7 +3299,7 @@ package body Makegpr is
 
       if Verbose_Mode then
          Write_Eol;
-         Write_Str ("Parsing of Project File """);
+         Write_Str ("Parsing of project file """);
          Write_Str (Project_File_Name.all);
          Write_Str (""" is finished.");
          Write_Eol;
@@ -3218,7 +3349,10 @@ package body Makegpr is
             --  If -c was not specified, link the executables,
             --  if there are any.
 
-            if not Compile_Only and then not Data.Library then
+            if not Compile_Only
+              and then not Data.Library
+              and then Data.Object_Directory /= No_Path
+            then
                Build_Global_Archive;
                Link_Executables;
             end if;
@@ -3237,6 +3371,8 @@ package body Makegpr is
 
    procedure Initialize is
    begin
+      Set_Mode (Ada_Only);
+
       --  Do some necessary package initializations
 
       Csets.Initialize;
@@ -3245,6 +3381,51 @@ package body Makegpr is
       Prj.Initialize (Project_Tree);
       Mains.Delete;
 
+      --  Add the directory where gprmake is invoked in front of the path,
+      --  if gprmake is invoked from a bin directory or with directory
+      --  information. Only do this if the platform is not VMS, where the
+      --  notion of path does not really exist.
+
+      --  Below code shares nasty code duplication with make.adb code???
+
+      if not OpenVMS then
+         declare
+            Prefix  : constant String := Executable_Prefix_Path;
+            Command : constant String := Command_Name;
+
+         begin
+            if Prefix'Length > 0 then
+               declare
+                  PATH : constant String :=
+                           Prefix & Directory_Separator & "bin" &
+                           Path_Separator &
+                           Getenv ("PATH").all;
+               begin
+                  Setenv ("PATH", PATH);
+               end;
+
+            else
+               for Index in reverse Command'Range loop
+                  if Command (Index) = Directory_Separator then
+                     declare
+                        Absolute_Dir : constant String :=
+                                         Normalize_Pathname
+                                           (Command (Command'First .. Index));
+                        PATH         : constant String :=
+                                         Absolute_Dir &
+                                         Path_Separator &
+                                         Getenv ("PATH").all;
+                     begin
+                        Setenv ("PATH", PATH);
+                     end;
+
+                     exit;
+                  end if;
+               end loop;
+            end if;
+         end;
+      end if;
+
       --  Set Name_Ide and Name_Compiler_Command
 
       Name_Len := 0;
@@ -3255,9 +3436,9 @@ package body Makegpr is
       Add_Str_To_Name_Buffer ("compiler_command");
       Name_Compiler_Command := Name_Find;
 
-      --  Make sure the -X switch table is empty
+      --  Make sure the Saved_Switches table is empty
 
-      X_Switches.Set_Last (0);
+      Saved_Switches.Set_Last (0);
 
       --  Get the command line arguments
 
@@ -3294,7 +3475,7 @@ package body Makegpr is
    -----------------------------------
 
    function Is_Included_In_Global_Archive
-     (Object_Name : Name_Id;
+     (Object_Name : File_Name_Type;
       Project     : Project_Id) return Boolean
    is
       Data   : Project_Data := Project_Tree.Projects.Table (Project);
@@ -3331,7 +3512,8 @@ package body Makegpr is
       Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
       --  True if main sources were specified on the command line
 
-      Object_Dir : constant String := Get_Name_String (Data.Object_Directory);
+      Object_Dir : constant String :=
+                     Get_Name_String (Data.Display_Object_Dir);
       --  Path of the object directory of the main project
 
       Source_Id : Other_Source_Id;
@@ -3359,7 +3541,7 @@ package body Makegpr is
 
       procedure Link_Foreign
         (Main    : String;
-         Main_Id : Name_Id;
+         Main_Id : File_Name_Type;
          Source  : Other_Source);
       --  Link a non-Ada main, when there is no Ada code
 
@@ -3369,18 +3551,9 @@ package body Makegpr is
 
       procedure Add_C_Plus_Plus_Link_For_Gnatmake is
       begin
-         if Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
-            Add_Argument
-              ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
-               Verbose_Mode);
-
-         else
-            Add_Argument
-              ("--LINK=" &
-               Object_Dir & Directory_Separator &
-               Cpp_Linker,
-               Verbose_Mode);
-         end if;
+         Add_Argument
+           ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
+            Verbose_Mode);
       end Add_C_Plus_Plus_Link_For_Gnatmake;
 
       -----------------------
@@ -3402,19 +3575,15 @@ package body Makegpr is
 
             if Data.Other_Sources_Present then
                declare
-                  Archive_Path : constant String :=
-                                   Get_Name_String
-                                     (Prj_Data.Object_Directory) &
-                  Directory_Separator &
-                  "lib" &
-                  Get_Name_String (Prj_Data.Name) &
-                    '.' & Archive_Ext;
+                  Archive_Path : constant String := Get_Name_String
+                    (Prj_Data.Display_Object_Dir) & Directory_Separator
+                    & "lib" & Get_Name_String (Prj_Data.Display_Name)
+                    & '.' & Archive_Ext;
                   Archive_TS   : Time_Stamp_Type;
                begin
                   Name_Len := 0;
-                  Add_Str_To_Name_Buffer
-                    (Archive_Path);
-                  Archive_TS := File_Stamp (Name_Find);
+                  Add_Str_To_Name_Buffer (Archive_Path);
+                  Archive_TS := File_Stamp (File_Name_Type'(Name_Find));
 
                   --  If the archive is later than the
                   --  executable, we need to relink.
@@ -3449,29 +3618,6 @@ package body Makegpr is
          if Compiler_Names (C_Plus_Plus_Language_Index) = null then
             Get_Compiler (C_Plus_Plus_Language_Index);
          end if;
-
-         if not Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
-            Change_Dir (Object_Dir);
-
-            declare
-               File : Ada.Text_IO.File_Type;
-               use Ada.Text_IO;
-
-            begin
-               Create (File, Out_File, Cpp_Linker);
-
-               Put_Line (File, "#!/bin/sh");
-
-               Put_Line (File, "LIBGCC=`gcc -print-libgcc-file-name`");
-               Put_Line
-                 (File,
-                  Compiler_Names (C_Plus_Plus_Language_Index).all &
-                  " $* ${LIBGCC}");
-
-               Close (File);
-               Set_Executable (Cpp_Linker);
-            end;
-         end if;
       end Choose_C_Plus_Plus_Link_Process;
 
       ------------------
@@ -3480,7 +3626,7 @@ package body Makegpr is
 
       procedure Link_Foreign
         (Main    : String;
-         Main_Id : Name_Id;
+         Main_Id : File_Name_Type;
          Source  : Other_Source)
       is
          Executable_Name : constant String :=
@@ -3495,9 +3641,8 @@ package body Makegpr is
 
          Executable_Path : constant String :=
                              Get_Name_String
-                               (Data.Exec_Directory) &
-                                Directory_Separator &
-                                Executable_Name;
+                               (Data.Display_Exec_Dir) &
+                                Directory_Separator & Executable_Name;
          --  Path name of the executable
 
          Exec_Time_Stamp : Time_Stamp_Type;
@@ -3513,7 +3658,7 @@ package body Makegpr is
 
             Name_Len := 0;
             Add_Str_To_Name_Buffer (Executable_Path);
-            Exec_Time_Stamp := File_Stamp (Name_Find);
+            Exec_Time_Stamp := File_Stamp (File_Name_Type'(Name_Find));
 
             if Verbose_Mode then
                Write_Str  ("   Checking executable ");
@@ -3554,7 +3699,7 @@ package body Makegpr is
 
             Add_Argument (Dash_o, True);
             Add_Argument
-              (Get_Name_String (Data.Exec_Directory) &
+              (Get_Name_String (Data.Display_Exec_Dir) &
                Directory_Separator &
                Get_Name_String
                  (Executable_Of
@@ -3599,7 +3744,7 @@ package body Makegpr is
             --  Add the linking options specified on the
             --  command line.
 
-            for Arg in 1 ..  Linker_Options.Last loop
+            for Arg in 1 .. Linker_Options.Last loop
                Add_Argument (Linker_Options.Table (Arg), True);
             end loop;
 
@@ -3634,13 +3779,13 @@ package body Makegpr is
 
       if not Mains_Specified then
          declare
-            Element_Id : String_List_Id := Data.Mains;
+            Element_Id : String_List_Id;
             Element    : String_Element;
 
          begin
+            Element_Id := Data.Mains;
             while Element_Id /= Nil_String loop
-               Element := Project_Tree.String_Elements.Table
-                            (Element_Id);
+               Element := Project_Tree.String_Elements.Table (Element_Id);
 
                if Element.Value /= No_Name then
                   Mains.Add_Main (Get_Name_String (Element.Value));
@@ -3674,8 +3819,9 @@ package body Makegpr is
 
          --  Only Ada sources in the main project, and even maybe not
 
-         if not Data.Languages (Ada_Language_Index) then
-
+         if Data.Extends = No_Project and then
+           not Data.Langs (Ada_Language_Index)
+         then
             --  Fail if the main project has no source of any language
 
             Osint.Fail
@@ -3704,13 +3850,13 @@ package body Makegpr is
          --  There are other language sources. First check if there are also
          --  sources in Ada.
 
-         if Data.Languages (Ada_Language_Index) then
+         if Data.Langs (Ada_Language_Index) then
 
             --  There is a mix of Ada and other language sources in the main
             --  project. Any main that is not a source of the other languages
             --  will be deemed to be an Ada main.
 
-            --  Find the mains of the other languages and the Ada mains.
+            --  Find the mains of the other languages and the Ada mains
 
             Mains.Reset;
             Ada_Mains.Set_Last (0);
@@ -3721,7 +3867,7 @@ package body Makegpr is
             loop
                declare
                   Main    : constant String := Mains.Next_Main;
-                  Main_Id : Name_Id;
+                  Main_Id : File_Name_Type;
 
                begin
                   exit when Main'Length = 0;
@@ -3732,10 +3878,10 @@ package body Makegpr is
                   Add_Str_To_Name_Buffer (Main);
                   Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
                   Main_Id := Name_Find;
-                  Source_Id := Data.First_Other_Source;
 
                   --  Check if it is a source of a language other than Ada
 
+                  Source_Id := Data.First_Other_Source;
                   while Source_Id /= No_Other_Source loop
                      Source :=
                        Project_Tree.Other_Sources.Table (Source_Id);
@@ -3832,7 +3978,7 @@ package body Makegpr is
                --  If C++ is one of the languages, add the --LINK switch to
                --  the linking switches.
 
-               if Data.Languages (C_Plus_Plus_Language_Index) then
+               if Data.Langs (C_Plus_Plus_Language_Index) then
                   Add_Argument (Dash_largs, Verbose_Mode);
                   Add_C_Plus_Plus_Link_For_Gnatmake;
                   Add_Argument (Dash_margs, Verbose_Mode);
@@ -3848,7 +3994,7 @@ package body Makegpr is
 
             --  First, get the linker to invoke
 
-            if Data.Languages (C_Plus_Plus_Language_Index) then
+            if Data.Langs (C_Plus_Plus_Language_Index) then
                Get_Compiler (C_Plus_Plus_Language_Index);
                Linker_Name := Compiler_Names (C_Plus_Plus_Language_Index);
                Linker_Path := Compiler_Paths (C_Plus_Plus_Language_Index);
@@ -3868,8 +4014,9 @@ package body Makegpr is
 
             loop
                declare
-                  Main : constant String := Mains.Next_Main;
-                  Main_Id : Name_Id;
+                  Main    : constant String := Mains.Next_Main;
+                  Main_Id : File_Name_Type;
+
                begin
                   exit when Main'Length = 0;
 
@@ -3879,10 +4026,10 @@ package body Makegpr is
                   Add_Str_To_Name_Buffer (Main);
                   Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
                   Main_Id := Name_Find;
-                  Source_Id := Data.First_Other_Source;
 
                   --  Check if it is a source of the main project file
 
+                  Source_Id := Data.First_Other_Source;
                   while Source_Id /= No_Other_Source loop
                      Source :=
                        Project_Tree.Other_Sources.Table (Source_Id);
@@ -3917,7 +4064,7 @@ package body Makegpr is
 
                   declare
                      Main    : constant String := Mains.Next_Main;
-                     Main_Id : Name_Id;
+                     Main_Id : File_Name_Type;
                   begin
                      Name_Len := 0;
                      Add_Str_To_Name_Buffer (Main);
@@ -4071,7 +4218,15 @@ package body Makegpr is
       --  Switches start with '-'
 
       elsif Arg (1) = '-' then
-         if Arg = "-c" then
+         if Arg'Length > 3 and then Arg (1 .. 3) = "-aP" then
+            Add_Search_Project_Directory (Arg (4 .. Arg'Last));
+
+            --  Record the switch, so that it is passed to gnatmake, if
+            --  gnatmake is called.
+
+            Saved_Switches.Append (new String'(Arg));
+
+         elsif Arg = "-c" then
             Compile_Only := True;
 
             --  Make sure that when a main is specified and switch -c is used,
@@ -4084,6 +4239,9 @@ package body Makegpr is
          elsif Arg = "-d" then
             Display_Compilation_Progress := True;
 
+         elsif Arg = "-eL" then
+            Follow_Links_For_Files := True;
+
          elsif Arg = "-f" then
             Force_Compilations := True;
 
@@ -4112,6 +4270,9 @@ package body Makegpr is
                Project_File_Name := new String'(Arg (3 .. Arg'Last));
             end if;
 
+         elsif Arg = "-p" or else Arg = "--create-missing-dirs" then
+            Setup_Projects := True;
+
          elsif Arg = "-q" then
             Quiet_Output := True;
 
@@ -4142,11 +4303,10 @@ package body Makegpr is
          then
             --  Is_External_Assignment has side effects when it returns True
 
-            --  Record the -X switch, so that they can be passed to gnatmake,
+            --  Record the -X switch, so that it will be passed to gnatmake,
             --  if gnatmake is called.
 
-            X_Switches.Increment_Last;
-            X_Switches.Table (X_Switches.Last) := new String'(Arg);
+            Saved_Switches.Append (new String'(Arg));
 
          else
             Osint.Fail ("illegal option """, Arg, """");
@@ -4198,11 +4358,7 @@ package body Makegpr is
          Write_Str ("Usage: ");
          Osint.Write_Program_Name;
          Write_Str (" -P<project file> [opts]  [name] {");
-
-         for Lang in First_Language_Indexes loop
-            Write_Str ("[-cargs:lang opts] ");
-         end loop;
-
+         Write_Str ("[-cargs:lang opts] ");
          Write_Str ("[-largs opts] [-gargs opts]}");
          Write_Eol;
          Write_Eol;
@@ -4215,11 +4371,22 @@ package body Makegpr is
          Write_Str ("gprmake switches:");
          Write_Eol;
 
+         --  Line for -aP
+
+         Write_Str ("  -aPdir   Add directory dir to project search path");
+         Write_Eol;
+
          --  Line for -c
 
          Write_Str ("  -c       Compile only");
          Write_Eol;
 
+         --  Line for -eL
+
+         Write_Str ("  -eL      Follow symbolic links when processing " &
+                    "project files");
+         Write_Eol;
+
          --  Line for -f
 
          Write_Str ("  -f       Force recompilations");
@@ -4235,6 +4402,11 @@ package body Makegpr is
          Write_Str ("  -o name  Choose an alternate executable name");
          Write_Eol;
 
+         --  Line for -p
+
+         Write_Str ("  -p       Create missing obj, lib and exec dirs");
+         Write_Eol;
+
          --  Line for -P
 
          Write_Str ("  -Pproj   Use GNAT Project File proj");