OSDN Git Service

2009-08-17 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / gnatlink.adb
index a099217..eb255d9 100644 (file)
@@ -6,18 +6,17 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1996-2005 Free Software Foundation, Inc.          --
+--          Copyright (C) 1996-2009, 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,  51  Franklin  Street,  Fifth  Floor, --
--- Boston, MA 02110-1301, 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.      --
@@ -44,14 +43,26 @@ with Types;
 
 with Ada.Command_Line;     use Ada.Command_Line;
 with Ada.Exceptions;       use Ada.Exceptions;
-with GNAT.OS_Lib;          use GNAT.OS_Lib;
+
+with System.OS_Lib;        use System.OS_Lib;
+with System.CRTL;
+
 with Interfaces.C_Streams; use Interfaces.C_Streams;
 with Interfaces.C.Strings; use Interfaces.C.Strings;
-with System.CRTL;
 
 procedure Gnatlink is
    pragma Ident (Gnatvsn.Gnat_Static_Version_String);
 
+   Shared_Libgcc_String : constant String := "-shared-libgcc";
+   Shared_Libgcc        : constant String_Access :=
+                            new String'(Shared_Libgcc_String);
+   --  Used to invoke gcc when the binder is invoked with -shared
+
+   Static_Libgcc_String : constant String := "-static-libgcc";
+   Static_Libgcc        : constant String_Access :=
+                            new String'(Static_Libgcc_String);
+   --  Used to invoke gcc when shared libs are not used
+
    package Gcc_Linker_Options is new Table.Table (
      Table_Component_Type => String_Access,
      Table_Index_Type     => Integer,
@@ -66,7 +77,7 @@ procedure Gnatlink is
      Table_Index_Type     => Integer,
      Table_Low_Bound      => 1,
      Table_Initial        => 4096,
-     Table_Increment      => 2,
+     Table_Increment      => 100,
      Table_Name           => "Gnatlink.Libpath");
    --  Comments needed ???
 
@@ -93,7 +104,7 @@ procedure Gnatlink is
    --  important because on the GNU linker command line the -L switch is not
    --  used to look for objects files but -L switch is used to look for
    --  objects listed in the response file. This is not a problem with the
-   --  applications objects as they are specified with a fullname.
+   --  applications objects as they are specified with a full name.
 
    package Response_File_Objects is new Table.Table (
      Table_Component_Type => String_Access,
@@ -126,9 +137,9 @@ procedure Gnatlink is
    --  This table collects the arguments to be passed to compile the binder
    --  generated file.
 
-   Gcc : String_Access := Program_Name ("gcc");
+   Gcc : String_Access := Program_Name ("gcc", "gnatlink");
 
-   Read_Mode  : constant String := "r" & ASCII.Nul;
+   Read_Mode : constant String := "r" & ASCII.NUL;
 
    Begin_Info : String := "--  BEGIN Object file/option list";
    End_Info   : String := "--  END Object file/option list   ";
@@ -136,7 +147,6 @@ procedure Gnatlink is
 
    Gcc_Path             : String_Access;
    Linker_Path          : String_Access;
-
    Output_File_Name     : String_Access;
    Ali_File_Name        : String_Access;
    Binder_Spec_Src_File : String_Access;
@@ -149,6 +159,10 @@ procedure Gnatlink is
    --  Temporary file used by linker to pass list of object files on
    --  certain systems with limitations on size of arguments.
 
+   Lname : String_Access := null;
+   --  File used by linker for CLI target, used to concatenate all .il files
+   --  when the command line passed to ilasm is too long
+
    Debug_Flag_Present : Boolean := False;
    Verbose_Mode       : Boolean := False;
    Very_Verbose_Mode  : Boolean := False;
@@ -156,7 +170,7 @@ procedure Gnatlink is
    Ada_Bind_File : Boolean := True;
    --  Set to True if bind file is generated in Ada
 
-   Standard_Gcc  : Boolean := True;
+   Standard_Gcc : Boolean := True;
 
    Compile_Bind_File : Boolean := True;
    --  Set to False if bind file is not to be compiled
@@ -166,6 +180,7 @@ procedure Gnatlink is
    --  the ALI file name (mainprog.ali => mainprog.map).
 
    Object_List_File_Supported : Boolean;
+   for Object_List_File_Supported'Size use Character'Size;
    pragma Import
      (C, Object_List_File_Supported, "__gnat_objlist_file_supported");
    --  Predicate indicating whether the linker has an option whereby the
@@ -174,24 +189,27 @@ procedure Gnatlink is
    Object_List_File_Required : Boolean := False;
    --  Set to True to force generation of a response file
 
-   function Base_Name (File_Name : in String) return String;
+   function Base_Name (File_Name : String) return String;
    --  Return just the file name part without the extension (if present)
 
-   procedure Delete (Name : in String);
+   procedure Delete (Name : String);
    --  Wrapper to unlink as status is ignored by this application
 
-   procedure Error_Msg (Message : in String);
+   procedure Error_Msg (Message : String);
    --  Output the error or warning Message
 
-   procedure Exit_With_Error (Error : in String);
+   procedure Exit_With_Error (Error : String);
    --  Output Error and exit program with a fatal condition
 
    procedure Process_Args;
    --  Go through all the arguments and build option tables
 
-   procedure Process_Binder_File (Name : in String);
+   procedure Process_Binder_File (Name : String);
    --  Reads the binder file and extracts linker arguments
 
+   procedure Usage;
+   --  Display usage
+
    procedure Write_Header;
    --  Show user the program name, version and copyright
 
@@ -202,7 +220,7 @@ procedure Gnatlink is
    -- Base_Name --
    ---------------
 
-   function Base_Name (File_Name : in String) return String is
+   function Base_Name (File_Name : String) return String is
       Findex1 : Natural;
       Findex2 : Natural;
 
@@ -237,7 +255,7 @@ procedure Gnatlink is
    -- Delete --
    ------------
 
-   procedure Delete (Name : in String) is
+   procedure Delete (Name : String) is
       Status : int;
       pragma Unreferenced (Status);
    begin
@@ -249,7 +267,7 @@ procedure Gnatlink is
    -- Error_Msg --
    ---------------
 
-   procedure Error_Msg (Message : in String) is
+   procedure Error_Msg (Message : String) is
    begin
       Write_Str (Base_Name (Command_Name));
       Write_Str (": ");
@@ -261,7 +279,7 @@ procedure Gnatlink is
    -- Exit_With_Error --
    ---------------------
 
-   procedure Exit_With_Error (Error : in String) is
+   procedure Exit_With_Error (Error : String) is
    begin
       Error_Msg (Error);
       Exit_Program (E_Fatal);
@@ -277,7 +295,15 @@ procedure Gnatlink is
       --  Set to true if the next argument is to be added into the list of
       --  linker's argument without parsing it.
 
+      procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
+
+      --  Start of processing for Process_Args
+
    begin
+      --  First, check for --version and --help
+
+      Check_Version_And_Help ("GNATLINK", "1995");
+
       --  Loop through arguments of gnatlink command
 
       Next_Arg := 1;
@@ -406,9 +432,16 @@ procedure Gnatlink is
                         Compile_Bind_File := False;
 
                      when 'o' =>
-                        Linker_Options.Increment_Last;
-                        Linker_Options.Table (Linker_Options.Last) :=
-                         new String'(Arg);
+                        if VM_Target = CLI_Target then
+                           Linker_Options.Increment_Last;
+                           Linker_Options.Table (Linker_Options.Last) :=
+                              new String'("/QUIET");
+
+                        else
+                           Linker_Options.Increment_Last;
+                           Linker_Options.Table (Linker_Options.Last) :=
+                             new String'(Arg);
+                        end if;
 
                         Next_Arg := Next_Arg + 1;
 
@@ -416,7 +449,13 @@ procedure Gnatlink is
                            Exit_With_Error ("Missing argument for -o");
                         end if;
 
-                        Output_File_Name := new String'(Argument (Next_Arg));
+                        if VM_Target = CLI_Target then
+                           Output_File_Name :=
+                             new String'("/OUTPUT=" & Argument (Next_Arg));
+                        else
+                           Output_File_Name :=
+                             new String'(Argument (Next_Arg));
+                        end if;
 
                         Linker_Options.Increment_Last;
                         Linker_Options.Table (Linker_Options.Last) :=
@@ -468,7 +507,7 @@ procedure Gnatlink is
                   end if;
 
                   Linker_Path :=
-                    GNAT.OS_Lib.Locate_Exec_On_Path (Arg (8 .. Arg'Last));
+                    System.OS_Lib.Locate_Exec_On_Path (Arg (8 .. Arg'Last));
 
                   if Linker_Path = null then
                      Exit_With_Error
@@ -482,8 +521,10 @@ procedure Gnatlink is
                                                  (Arg (7 .. Arg'Last));
 
                   begin
-                     Gcc := new String'(Program_Args.all (1).all);
-                     Standard_Gcc := False;
+                     if Program_Args.all (1).all /= Gcc.all then
+                        Gcc := new String'(Program_Args.all (1).all);
+                        Standard_Gcc := False;
+                     end if;
 
                      --  Set appropriate flags for switches passed
 
@@ -626,7 +667,7 @@ procedure Gnatlink is
    -- Process_Binder_File --
    -------------------------
 
-   procedure Process_Binder_File (Name : in String) is
+   procedure Process_Binder_File (Name : String) is
       Fd : FILEs;
       --  Binder file's descriptor
 
@@ -656,9 +697,11 @@ procedure Gnatlink is
       --  Last object file index in Linker_Objects table
 
       Status : int;
+      pragma Warnings (Off, Status);
       --  Used for various Interfaces.C_Streams calls
 
       Closing_Status : Boolean;
+      pragma Warnings (Off, Closing_Status);
       --  For call to Close
 
       GNAT_Static : Boolean := False;
@@ -713,10 +756,17 @@ procedure Gnatlink is
       --  the response file.
 
       Using_GNU_Linker : Boolean;
+      for Using_GNU_Linker'Size use Character'Size;
       pragma Import (C, Using_GNU_Linker, "__gnat_using_gnu_linker");
       --  Predicate indicating whether this target uses the GNU linker. In
       --  this case we must output a GNU linker compatible response file.
 
+      Separate_Run_Path_Options : Boolean;
+      for Separate_Run_Path_Options'Size use Character'Size;
+      pragma Import
+        (C, Separate_Run_Path_Options, "__gnat_separate_run_path_options");
+      --  Whether separate rpath options should be emitted for each directory
+
       Opening : aliased constant String := """";
       Closing : aliased constant String := '"' & ASCII.LF;
       --  Needed to quote object paths in object list files when GNU linker
@@ -729,7 +779,7 @@ procedure Gnatlink is
       function Index (S, Pattern : String) return Natural;
       --  Return the last occurrence of Pattern in S, or 0 if none
 
-      function Is_Option_Present (Opt : in String) return Boolean;
+      function Is_Option_Present (Opt : String) return Boolean;
       --  Return true if the option Opt is already present in
       --  Linker_Options table.
 
@@ -791,7 +841,7 @@ procedure Gnatlink is
       -- Is_Option_Present --
       -----------------------
 
-      function Is_Option_Present (Opt : in String) return Boolean is
+      function Is_Option_Present (Opt : String) return Boolean is
       begin
          for I in 1 .. Linker_Options.Last loop
 
@@ -893,14 +943,13 @@ procedure Gnatlink is
 
       Objs_End := Linker_Objects.Last;
 
-      --  Let's continue to compute the Link_Bytes, the linker options are
-      --  part of command line length.
+      --  Continue to compute the Link_Bytes, the linker options are part of
+      --  command line length.
 
       Store_File_Context;
 
       while Next_Line (Nfirst .. Nlast) /= End_Info loop
          Link_Bytes := Link_Bytes + Nlast - Nfirst + 2;
-         --  See comment above
          Get_Next_Line;
       end loop;
 
@@ -914,7 +963,42 @@ procedure Gnatlink is
       --  to read from a file instead of the command line is only triggered if
       --  a conservative threshold is passed.
 
-      if Object_List_File_Required
+      if VM_Target = CLI_Target
+        and then Link_Bytes > Link_Max
+      then
+         Lname := new String'("l~" & Base_Name (Ali_File_Name.all) & ".il");
+
+         for J in Objs_Begin .. Objs_End loop
+            Copy_File (Linker_Objects.Table (J).all, Lname.all,
+                       Success => Closing_Status,
+                       Mode    => Append);
+         end loop;
+
+         --  Add the special objects list file option together with the name
+         --  of the temporary file to the objects file table.
+
+         Linker_Objects.Table (Objs_Begin) :=
+           new String'(Value (Object_File_Option_Ptr) & Lname.all);
+
+         --  The slots containing these object file names are then removed
+         --  from the objects table so they do not appear in the link. They
+         --  are removed by moving up the linker options and non-Ada object
+         --  files appearing after the Ada object list in the table.
+
+         declare
+            N : Integer;
+
+         begin
+            N := Objs_End - Objs_Begin + 1;
+
+            for J in Objs_End + 1 .. Linker_Objects.Last loop
+               Linker_Objects.Table (J - N + 1) := Linker_Objects.Table (J);
+            end loop;
+
+            Linker_Objects.Set_Last (Linker_Objects.Last - N + 1);
+         end;
+
+      elsif Object_List_File_Required
         or else (Object_List_File_Supported
                    and then Link_Bytes > Link_Max)
       then
@@ -931,7 +1015,9 @@ procedure Gnatlink is
 
          --  If target is using the GNU linker we must add a special header
          --  and footer in the response file.
+
          --  The syntax is : INPUT (object1.o object2.o ... )
+
          --  Because the GNU linker does not like name with characters such
          --  as '!', we must put the object paths between double quotes.
 
@@ -999,6 +1085,7 @@ procedure Gnatlink is
 
          declare
             N : Integer;
+
          begin
             N := Objs_End - Objs_Begin + 1;
 
@@ -1174,78 +1261,101 @@ procedure Gnatlink is
                                  --  Look for an eventual run_path_option in
                                  --  the linker switches.
 
-                                 for J in reverse 1 .. Linker_Options.Last loop
-                                    if Linker_Options.Table (J) /= null
-                                      and then
-                                        Linker_Options.Table (J)'Length
-                                                  > Run_Path_Opt'Length
-                                      and then
-                                        Linker_Options.Table (J)
-                                          (1 .. Run_Path_Opt'Length) =
-                                                                Run_Path_Opt
-                                    then
-                                       --  We have found a already specified
-                                       --  run_path_option: we will add to this
-                                       --  switch, because only one
-                                       --  run_path_option should be specified.
-
-                                       Run_Path_Opt_Index := J;
-                                       exit;
-                                    end if;
-                                 end loop;
-
-                                 --  If there is no run_path_option, we need
-                                 --  to add one.
-
-                                 if Run_Path_Opt_Index = 0 then
+                                 if Separate_Run_Path_Options then
                                     Linker_Options.Increment_Last;
-                                 end if;
+                                    Linker_Options.Table
+                                      (Linker_Options.Last) :=
+                                      new String'
+                                        (Run_Path_Opt
+                                         & File_Path
+                                           (1 .. File_Path'Length
+                                            - File_Name'Length));
 
-                                 if GCC_Index = 0 then
-                                    if Run_Path_Opt_Index = 0 then
+                                    if GCC_Index /= 0 then
+                                       Linker_Options.Increment_Last;
                                        Linker_Options.Table
                                          (Linker_Options.Last) :=
-                                           new String'
-                                              (Run_Path_Opt
-                                                & File_Path
-                                                  (1 .. File_Path'Length
-                                                         - File_Name'Length));
-
-                                    else
-                                       Linker_Options.Table
-                                         (Run_Path_Opt_Index) :=
-                                           new String'
-                                             (Linker_Options.Table
-                                                 (Run_Path_Opt_Index).all
-                                              & Path_Separator
-                                              & File_Path
-                                                 (1 .. File_Path'Length
-                                                       - File_Name'Length));
+                                         new String'
+                                           (Run_Path_Opt
+                                            & File_Path (1 .. GCC_Index));
                                     end if;
-
                                  else
+                                    for J in reverse
+                                      1 .. Linker_Options.Last
+                                    loop
+                                       if Linker_Options.Table (J) /= null
+                                         and then
+                                           Linker_Options.Table (J)'Length
+                                           > Run_Path_Opt'Length
+                                         and then
+                                           Linker_Options.Table (J)
+                                           (1 .. Run_Path_Opt'Length) =
+                                           Run_Path_Opt
+                                       then
+                                          --  We have found a already specified
+                                          --  run_path_option: we will add to
+                                          --  this switch, because only one
+                                          --  run_path_option should be
+                                          --  specified.
+
+                                          Run_Path_Opt_Index := J;
+                                          exit;
+                                       end if;
+                                    end loop;
+
+                                    --  If there is no run_path_option, we need
+                                    --  to add one.
+
                                     if Run_Path_Opt_Index = 0 then
-                                       Linker_Options.Table
-                                         (Linker_Options.Last) :=
-                                           new String'(Run_Path_Opt
-                                             & File_Path
+                                       Linker_Options.Increment_Last;
+                                    end if;
+
+                                    if GCC_Index = 0 then
+                                       if Run_Path_Opt_Index = 0 then
+                                          Linker_Options.Table
+                                            (Linker_Options.Last) :=
+                                            new String'
+                                              (Run_Path_Opt
+                                               & File_Path
+                                                 (1 .. File_Path'Length
+                                                  - File_Name'Length));
+
+                                       else
+                                          Linker_Options.Table
+                                            (Run_Path_Opt_Index) :=
+                                            new String'
+                                              (Linker_Options.Table
+                                                   (Run_Path_Opt_Index).all
+                                               & Path_Separator
+                                               & File_Path
                                                  (1 .. File_Path'Length
-                                                       - File_Name'Length)
-                                             & Path_Separator
-                                             & File_Path (1 .. GCC_Index));
+                                                  - File_Name'Length));
+                                       end if;
 
                                     else
-                                       Linker_Options.Table
-                                         (Run_Path_Opt_Index) :=
-                                           new String'
-                                            (Linker_Options.Table
-                                                (Run_Path_Opt_Index).all
-                                             & Path_Separator
-                                             & File_Path
+                                       if Run_Path_Opt_Index = 0 then
+                                          Linker_Options.Table
+                                            (Linker_Options.Last) :=
+                                            new String'(Run_Path_Opt
+                                              & File_Path
+                                                (1 .. File_Path'Length
+                                                 - File_Name'Length)
+                                              & Path_Separator
+                                              & File_Path (1 .. GCC_Index));
+
+                                       else
+                                          Linker_Options.Table
+                                            (Run_Path_Opt_Index) :=
+                                            new String'
+                                              (Linker_Options.Table
+                                                   (Run_Path_Opt_Index).all
+                                               & Path_Separator
+                                               & File_Path
                                                  (1 .. File_Path'Length
-                                                       - File_Name'Length)
-                                             & Path_Separator
-                                             & File_Path (1 .. GCC_Index));
+                                                  - File_Name'Length)
+                                               & Path_Separator
+                                               & File_Path (1 .. GCC_Index));
+                                       end if;
                                     end if;
                                  end if;
                               end if;
@@ -1261,7 +1371,7 @@ procedure Gnatlink is
                      else
                         --  If gnatlib library not found, then
                         --  add it anyway in case some other
-                        --  mechanimsm may find it.
+                        --  mechanism may find it.
 
                         Linker_Options.Increment_Last;
                         Linker_Options.Table (Linker_Options.Last) :=
@@ -1288,33 +1398,22 @@ procedure Gnatlink is
          end loop;
       end if;
 
-      Status := fclose (Fd);
-   end Process_Binder_File;
-
-   ------------------
-   -- Write_Header --
-   ------------------
+      --  If -shared was specified, invoke gcc with -shared-libgcc
 
-   procedure Write_Header is
-   begin
-      if Verbose_Mode then
-         Write_Eol;
-         Write_Str ("GNATLINK ");
-         Write_Str (Gnat_Version_String);
-         Write_Eol;
-         Write_Str ("Copyright 1995-2005 Free Software Foundation, Inc");
-         Write_Eol;
+      if GNAT_Shared then
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) := Shared_Libgcc;
       end if;
-   end Write_Header;
 
-   -----------------
-   -- Write_Usage --
-   -----------------
+      Status := fclose (Fd);
+   end Process_Binder_File;
 
-   procedure Write_Usage is
-   begin
-      Write_Header;
+   -----------
+   -- Usage --
+   -----------
 
+   procedure Usage is
+   begin
       Write_Str ("Usage: ");
       Write_Str (Base_Name (Command_Name));
       Write_Str (" switches mainprog.ali [non-Ada-objects] [linker-options]");
@@ -1345,6 +1444,28 @@ procedure Gnatlink is
       Write_Eol;
       Write_Line ("  [non-Ada-objects]  list of non Ada object files");
       Write_Line ("  [linker-options]   other options for the linker");
+   end Usage;
+
+   ------------------
+   -- Write_Header --
+   ------------------
+
+   procedure Write_Header is
+   begin
+      if Verbose_Mode then
+         Write_Eol;
+         Display_Version ("GNATLINK", "1995");
+      end if;
+   end Write_Header;
+
+   -----------------
+   -- Write_Usage --
+   -----------------
+
+   procedure Write_Usage is
+   begin
+      Write_Header;
+      Usage;
    end Write_Usage;
 
 --  Start of processing for Gnatlink
@@ -1392,12 +1513,11 @@ begin
       Exit_Program (E_Fatal);
    end if;
 
-   if Hostparm.Java_VM then
-      Gcc := new String'("jgnat");
-      Ada_Bind_File := True;
-      Begin_Info := "--  BEGIN Object file/option list";
-      End_Info   := "--  END Object file/option list   ";
-   end if;
+   --  Initialize packages to be used
+
+   Namet.Initialize;
+   Csets.Initialize;
+   Snames.Initialize;
 
    --  We always compile with -c
 
@@ -1405,42 +1525,6 @@ begin
    Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
      new String'("-c");
 
-   --  If the main program is in Ada it is compiled with the following
-   --  switches:
-
-   --    -gnatA   stops reading gnat.adc, since we don't know what
-   --             pagmas would work, and we do not need it anyway.
-
-   --    -gnatWb  allows brackets coding for wide characters
-
-   --    -gnatiw  allows wide characters in identifiers. This is needed
-   --             because bindgen uses brackets encoding for all upper
-   --             half and wide characters in identifier names.
-
-   if Ada_Bind_File then
-      Binder_Options_From_ALI.Increment_Last;
-      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
-        new String'("-gnatA");
-      Binder_Options_From_ALI.Increment_Last;
-      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
-        new String'("-gnatWb");
-      Binder_Options_From_ALI.Increment_Last;
-      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
-        new String'("-gnatiw");
-   end if;
-
-   --  Locate all the necessary programs and verify required files are present
-
-   Gcc_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
-
-   if Gcc_Path = null then
-      Exit_With_Error ("Couldn't locate " & Gcc.all);
-   end if;
-
-   if Linker_Path = null then
-      Linker_Path := Gcc_Path;
-   end if;
-
    if Ali_File_Name = null then
       Exit_With_Error ("no ali file given for link");
    end if;
@@ -1449,14 +1533,6 @@ begin
       Exit_With_Error (Ali_File_Name.all & " not found");
    end if;
 
-   --  Get target parameters
-
-   Namet.Initialize;
-   Csets.Initialize;
-   Snames.Initialize;
-   Osint.Add_Default_Search_Dirs;
-   Targparm.Get_Target_Parameters;
-
    --  Read the ALI file of the main subprogram if the binder generated
    --  file needs to be compiled and no --GCC= switch has been specified.
    --  Fetch the back end switches from this ALI file and use these switches
@@ -1496,21 +1572,68 @@ begin
               Index in Units.Table (ALIs.Table (A).First_Unit).First_Arg ..
                        Units.Table (ALIs.Table (A).First_Unit).Last_Arg
             loop
-               --  Do not compile with the front end switches except for --RTS
-               --  if the binder generated file is in Ada.
+               --  Do not compile with the front end switches. However, --RTS
+               --  is to be dealt with specially because it needs to be passed
+               --  if the binder-generated file is in Ada and may also be used
+               --  to drive the linker.
 
                declare
                   Arg : String_Ptr renames Args.Table (Index);
                begin
-                  if not Is_Front_End_Switch (Arg.all)
-                    or else
-                      (Ada_Bind_File
-                        and then Arg'Length > 5
-                        and then Arg (Arg'First + 2 .. Arg'First + 5) = "RTS=")
-                  then
+                  if not Is_Front_End_Switch (Arg.all) then
                      Binder_Options_From_ALI.Increment_Last;
                      Binder_Options_From_ALI.Table
                        (Binder_Options_From_ALI.Last) := String_Access (Arg);
+
+                  elsif Arg'Length > 5
+                    and then Arg (Arg'First + 2 .. Arg'First + 5) = "RTS="
+                  then
+                     if Ada_Bind_File then
+                        Binder_Options_From_ALI.Increment_Last;
+                        Binder_Options_From_ALI.Table
+                          (Binder_Options_From_ALI.Last)
+                            := String_Access (Arg);
+                     end if;
+
+                     --  Set the RTS_*_Path_Name variables, so that the
+                     --  correct directories will be set when
+                     --  Osint.Add_Default_Search_Dirs will be called later.
+
+                     Opt.RTS_Src_Path_Name :=
+                       Get_RTS_Search_Dir
+                         (Arg (Arg'First + 6 .. Arg'Last), Include);
+
+                     Opt.RTS_Lib_Path_Name :=
+                       Get_RTS_Search_Dir
+                         (Arg (Arg'First + 6 .. Arg'Last), Objects);
+
+                     --  GNAT doesn't support the GCC multilib mechanism.
+                     --  This means that, when a multilib switch is used
+                     --  to request a particular compilation mode, the
+                     --  corresponding runtime switch (--RTS) must also be
+                     --  specified. The long-term goal is to fully support the
+                     --  multilib mechanism; however, in the meantime, it is
+                     --  convenient to eliminate the redundancy by keying the
+                     --  compilation mode on a single switch, namely --RTS.
+
+                     --  Pass -mrtp to the linker if --RTS=rtp was passed
+
+                     if Arg'Length > 8
+                       and then Arg (Arg'First + 6 .. Arg'First + 8) = "rtp"
+                     then
+                        Linker_Options.Increment_Last;
+                        Linker_Options.Table (Linker_Options.Last) :=
+                          new String'("-mrtp");
+
+                     --  Pass -fsjlj to the linker if --RTS=sjlj was passed
+
+                     elsif Arg'Length > 9
+                       and then Arg (Arg'First + 6 .. Arg'First + 9) = "sjlj"
+                     then
+                        Linker_Options.Increment_Last;
+                        Linker_Options.Table (Linker_Options.Last) :=
+                          new String'("-fsjlj");
+                     end if;
                   end if;
                end;
             end loop;
@@ -1518,6 +1641,78 @@ begin
       end;
    end if;
 
+   --  Get target parameters
+
+   Osint.Add_Default_Search_Dirs;
+   Targparm.Get_Target_Parameters;
+
+   if VM_Target /= No_VM then
+      case VM_Target is
+         when JVM_Target => Gcc := new String'("jvm-gnatcompile");
+         when CLI_Target => Gcc := new String'("dotnet-gnatcompile");
+         when No_VM      => raise Program_Error;
+      end case;
+
+      Ada_Bind_File := True;
+      Begin_Info := "--  BEGIN Object file/option list";
+      End_Info   := "--  END Object file/option list   ";
+   end if;
+
+   --  If the main program is in Ada it is compiled with the following
+   --  switches:
+
+   --    -gnatA   stops reading gnat.adc, since we don't know what
+   --             pragmas would work, and we do not need it anyway.
+
+   --    -gnatWb  allows brackets coding for wide characters
+
+   --    -gnatiw  allows wide characters in identifiers. This is needed
+   --             because bindgen uses brackets encoding for all upper
+   --             half and wide characters in identifier names.
+
+   if Ada_Bind_File then
+      Binder_Options_From_ALI.Increment_Last;
+      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
+        new String'("-gnatA");
+      Binder_Options_From_ALI.Increment_Last;
+      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
+        new String'("-gnatWb");
+      Binder_Options_From_ALI.Increment_Last;
+      Binder_Options_From_ALI.Table (Binder_Options_From_ALI.Last) :=
+        new String'("-gnatiw");
+   end if;
+
+   --  Locate all the necessary programs and verify required files are present
+
+   Gcc_Path := System.OS_Lib.Locate_Exec_On_Path (Gcc.all);
+
+   if Gcc_Path = null then
+      Exit_With_Error ("Couldn't locate " & Gcc.all);
+   end if;
+
+   if Linker_Path = null then
+      if VM_Target = CLI_Target then
+         Linker_Path := System.OS_Lib.Locate_Exec_On_Path ("ilasm");
+
+         if Linker_Path = null then
+            Exit_With_Error ("Couldn't locate ilasm");
+         end if;
+
+      elsif RTX_RTSS_Kernel_Module_On_Target then
+
+         --  Use Microsoft linker for RTSS modules
+
+         Linker_Path := System.OS_Lib.Locate_Exec_On_Path ("link");
+
+         if Linker_Path = null then
+            Exit_With_Error ("Couldn't locate link");
+         end if;
+
+      else
+         Linker_Path := Gcc_Path;
+      end if;
+   end if;
+
    Write_Header;
 
    --  If no output name specified, then use the base name of .ali file name
@@ -1525,15 +1720,32 @@ begin
    if Output_File_Name = null then
       Output_File_Name :=
         new String'(Base_Name (Ali_File_Name.all)
-                       & Get_Target_Debuggable_Suffix.all);
+                      & Get_Target_Debuggable_Suffix.all);
+
+      if VM_Target = CLI_Target then
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) := new String'("/QUIET");
+
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) := new String'("/DEBUG");
+
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) :=
+           new String'("/OUTPUT=" & Output_File_Name.all);
 
-      Linker_Options.Increment_Last;
-      Linker_Options.Table (Linker_Options.Last) :=
-        new String'("-o");
+      elsif RTX_RTSS_Kernel_Module_On_Target then
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) :=
+           new String'("/OUT:" & Output_File_Name.all);
 
-      Linker_Options.Increment_Last;
-      Linker_Options.Table (Linker_Options.Last) :=
-        new String'(Output_File_Name.all);
+      else
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) := new String'("-o");
+
+         Linker_Options.Increment_Last;
+         Linker_Options.Table (Linker_Options.Last) :=
+           new String'(Output_File_Name.all);
+      end if;
    end if;
 
    --  Warn if main program is called "test", as that may be a built-in command
@@ -1654,7 +1866,12 @@ begin
               Binder_Options.Table (J);
          end loop;
 
-         Args (Args'Last) := Binder_Body_Src_File;
+         --  Use the full path of the binder generated source, so that it is
+         --  guaranteed that the debugger will find this source, even with
+         --  STABS.
+
+         Args (Args'Last) :=
+           new String'(Normalize_Pathname (Binder_Body_Src_File.all));
 
          if Verbose_Mode then
             Write_Str (Base_Name (Gcc_Path.all));
@@ -1667,7 +1884,7 @@ begin
             Write_Eol;
          end if;
 
-         GNAT.OS_Lib.Spawn (Gcc_Path.all, Args, Success);
+         System.OS_Lib.Spawn (Gcc_Path.all, Args, Success);
 
          if not Success then
             Exit_Program (E_Fatal);
@@ -1677,11 +1894,11 @@ begin
 
    --  Now, actually link the program
 
-   --  Skip this step for now on the JVM since the Java interpreter will do
+   --  Skip this step for now on JVM since the Java interpreter will do
    --  the actual link at run time. We might consider packing all class files
    --  in a .zip file during this step.
 
-   if not Hostparm.Java_VM then
+   if VM_Target /= JVM_Target then
       Link_Step : declare
          Num_Args : Natural :=
                      (Linker_Options.Last - Linker_Options.First + 1) +
@@ -1691,6 +1908,141 @@ begin
          IDENT_Op : Boolean := False;
 
       begin
+         if VM_Target = CLI_Target then
+
+            --  Remove extraneous flags not relevant for CIL. Also remove empty
+            --  arguments, since ilasm chokes on them.
+
+            for J in reverse Linker_Options.First .. Linker_Options.Last loop
+               if Linker_Options.Table (J)'Length = 0
+                 or else Linker_Options.Table (J) (1 .. 2) = "-L"
+                 or else Linker_Options.Table (J) (1 .. 2) = "-l"
+                 or else Linker_Options.Table (J) (1 .. 3) = "-Wl"
+                 or else Linker_Options.Table (J) (1 .. 3) = "-sh"
+                 or else Linker_Options.Table (J) (1 .. 2) = "-g"
+               then
+                  Linker_Options.Table (J .. Linker_Options.Last - 1) :=
+                    Linker_Options.Table (J + 1 .. Linker_Options.Last);
+                  Linker_Options.Decrement_Last;
+                  Num_Args := Num_Args - 1;
+               end if;
+            end loop;
+
+         elsif RTX_RTSS_Kernel_Module_On_Target then
+
+            --  Remove flags not relevant for Microsoft linker and adapt some
+            --  others.
+
+            for J in reverse Linker_Options.First .. Linker_Options.Last loop
+
+               --  Remove flags that are not accepted
+               if Linker_Options.Table (J)'Length = 0
+                 or else Linker_Options.Table (J) (1 .. 2) = "-l"
+                 or else Linker_Options.Table (J) (1 .. 3) = "-Wl"
+                 or else Linker_Options.Table (J) (1 .. 3) = "-sh"
+                 or else Linker_Options.Table (J) (1 .. 8) = "-Xlinker"
+                 or else Linker_Options.Table (J) (1 .. 9) = "-mthreads"
+               then
+                  Linker_Options.Table (J .. Linker_Options.Last - 1) :=
+                    Linker_Options.Table (J + 1 .. Linker_Options.Last);
+                  Linker_Options.Decrement_Last;
+                  Num_Args := Num_Args - 1;
+
+               --  Replace "-L" by its counterpart "/LIBPATH:" and UNIX "/" by
+               --  Windows "\".
+               elsif Linker_Options.Table (J) (1 .. 2) = "-L" then
+                  declare
+                     Libpath_Option : constant String_Access := new String'
+                       ("/LIBPATH:" &
+                        Linker_Options.Table (J)
+                          (3 .. Linker_Options.Table (J).all'Last));
+                  begin
+                     for Index in 10 .. Libpath_Option'Last loop
+                        if Libpath_Option (Index) = '/' then
+                           Libpath_Option (Index) := '\';
+                        end if;
+                     end loop;
+
+                     Linker_Options.Table (J) := Libpath_Option;
+                  end;
+
+               --  Replace "-g" by "/DEBUG"
+               elsif Linker_Options.Table (J) (1 .. 2) = "-g" then
+                  Linker_Options.Table (J) := new String'("/DEBUG");
+
+               --  Replace "-o" by "/OUT:"
+               elsif Linker_Options.Table (J) (1 .. 2) = "-o" then
+                  Linker_Options.Table (J + 1) := new String'
+                    ("/OUT:" & Linker_Options.Table (J + 1).all);
+
+                  Linker_Options.Table (J .. Linker_Options.Last - 1) :=
+                    Linker_Options.Table (J + 1 .. Linker_Options.Last);
+                  Linker_Options.Decrement_Last;
+                  Num_Args := Num_Args - 1;
+
+               --  Replace "--stack=" by "/STACK:"
+               elsif Linker_Options.Table (J) (1 .. 8) = "--stack=" then
+                  Linker_Options.Table (J) := new String'
+                    ("/STACK:" &
+                     Linker_Options.Table (J)
+                       (9 .. Linker_Options.Table (J).all'Last));
+
+               --  Replace "-v" by its counterpart "/VERBOSE"
+               elsif Linker_Options.Table (J) (1 .. 2) = "-v" then
+                  Linker_Options.Table (J) := new String'("/VERBOSE");
+               end if;
+            end loop;
+
+            --  Add some required flags to create RTSS modules
+
+            declare
+               Flags_For_Linker : constant array (1 .. 17) of String_Access :=
+                 (new String'("/NODEFAULTLIB"),
+                  new String'("/INCREMENTAL:NO"),
+                  new String'("/NOLOGO"),
+                  new String'("/DRIVER"),
+                  new String'("/ALIGN:0x20"),
+                  new String'("/SUBSYSTEM:NATIVE"),
+                  new String'("/ENTRY:_RtapiProcessEntryCRT@8"),
+                  new String'("/RELEASE"),
+                  new String'("startupCRT.obj"),
+                  new String'("rtxlibcmt.lib"),
+                  new String'("oldnames.lib"),
+                  new String'("rtapi_rtss.lib"),
+                  new String'("Rtx_Rtss.lib"),
+                  new String'("libkernel32.a"),
+                  new String'("libws2_32.a"),
+                  new String'("libmswsock.a"),
+                  new String'("libadvapi32.a"));
+               --  These flags need to be passed to Microsoft linker. They
+               --  come from the RTX documentation.
+
+               Gcc_Lib_Path : constant String_Access := new String'
+                 ("/LIBPATH:" & Include_Dir_Default_Prefix & "\..\");
+               --  Place to look for gcc related libraries, such as libgcc
+
+            begin
+               --  Replace UNIX "/" by Windows "\" in the path
+
+               for Index in 10 .. Gcc_Lib_Path.all'Last loop
+                  if Gcc_Lib_Path (Index) = '/' then
+                     Gcc_Lib_Path (Index) := '\';
+                  end if;
+               end loop;
+
+               Linker_Options.Increment_Last;
+               Linker_Options.Table (Linker_Options.Last) := Gcc_Lib_Path;
+               Num_Args := Num_Args + 1;
+
+               for Index in Flags_For_Linker'Range loop
+                  Linker_Options.Increment_Last;
+                  Linker_Options.Table (Linker_Options.Last) :=
+                    Flags_For_Linker (Index);
+                  Num_Args := Num_Args + 1;
+               end loop;
+            end;
+         end if;
+
          --  Remove duplicate stack size setting from the Linker_Options
          --  table. The stack setting option "-Xlinker --stack=R,C" can be
          --  found in one line when set by a pragma Linker_Options or in two
@@ -1702,7 +2054,7 @@ begin
          --  one. And any subsequent stack setting option will overwrite the
          --  previous one. This is done especially for GNAT/NT where we set
          --  the stack size for tasking programs by a pragma in the NT
-         --  specific tasking package System.Task_Primitives.Oparations.
+         --  specific tasking package System.Task_Primitives.Operations.
 
          --  Note: This is not a FOR loop that runs from Linker_Options.First
          --  to Linker_Options.Last, since operations within the loop can
@@ -1710,6 +2062,7 @@ begin
 
          Clean_Link_Option_Set : declare
             J : Natural := Linker_Options.First;
+            Shared_Libgcc_Seen : Boolean := False;
 
          begin
             while J <= Linker_Options.Last loop
@@ -1731,6 +2084,20 @@ begin
                   end if;
                end if;
 
+               --  Remove duplicate -shared-libgcc switch
+
+               if Linker_Options.Table (J).all = Shared_Libgcc_String then
+                  if Shared_Libgcc_Seen then
+                     Linker_Options.Table (J .. Linker_Options.Last - 1) :=
+                       Linker_Options.Table (J + 1 .. Linker_Options.Last);
+                     Linker_Options.Decrement_Last;
+                     Num_Args := Num_Args - 1;
+
+                  else
+                     Shared_Libgcc_Seen := True;
+                  end if;
+               end if;
+
                --  Here we just check for a canonical form that matches the
                --  pragma Linker_Options set in the NT runtime.
 
@@ -1771,6 +2138,29 @@ begin
 
                J := J + 1;
             end loop;
+
+            if Linker_Path = Gcc_Path and then VM_Target = No_VM then
+
+               --  If gcc is not called with -shared-libgcc, call it with
+               --  -static-libgcc, as there are some platforms where one of
+               --  these two switches is compulsory to link.
+
+               if not Shared_Libgcc_Seen then
+                  Linker_Options.Increment_Last;
+                  Linker_Options.Table (Linker_Options.Last) := Static_Libgcc;
+                  Num_Args := Num_Args + 1;
+               end if;
+
+            elsif RTX_RTSS_Kernel_Module_On_Target then
+
+               --  Force the use of the static libgcc for RTSS modules
+
+               Linker_Options.Increment_Last;
+               Linker_Options.Table (Linker_Options.Last) :=
+                 new String'("libgcc.a");
+               Num_Args := Num_Args + 1;
+            end if;
+
          end Clean_Link_Option_Set;
 
          --  Prepare arguments for call to linker
@@ -1836,17 +2226,21 @@ begin
                end if;
             end if;
 
-            GNAT.OS_Lib.Spawn (Linker_Path.all, Args, Success);
+            System.OS_Lib.Spawn (Linker_Path.all, Args, Success);
 
-            --  Delete the temporary file used in conjuction with linking if
+            --  Delete the temporary file used in conjunction with linking if
             --  one was created. See Process_Bind_File for details.
 
             if Tname_FD /= Invalid_FD then
                Delete (Tname);
             end if;
 
+            if Lname /= null then
+               Delete (Lname.all & ASCII.NUL);
+            end if;
+
             if not Success then
-               Error_Msg ("cannot call " & Linker_Path.all);
+               Error_Msg ("error when calling " & Linker_Path.all);
                Exit_Program (E_Fatal);
             end if;
          end Call_Linker;
@@ -1868,7 +2262,7 @@ begin
 
       Delete (Binder_Body_Src_File.all & ASCII.NUL);
 
-      if not Hostparm.Java_VM then
+      if VM_Target = No_VM then
          Delete (Binder_Obj_File.all & ASCII.NUL);
       end if;
    end if;