gcc-patches@gcc.gnu.org
[Top] [All Lists]

[PATCH][Ada] Implement multilib support for gnatmake

Subject: [PATCH][Ada] Implement multilib support for gnatmake
From: Laurent GUERBY
Date: Tue, 03 Mar 2009 19:09:48 +0100
Hi,

Even if the Ada build process support multilib, gnatmake users currently
have to provide explicitely --RTS=xxx to select the right runtime, ie:

gnatmake $FLAGS --RTS=$(gcc -print-multi-directory $FLAGS)

The patch does special processing if and only if two conditions are
met: 
1/ there is at least one -mxxx flag passed to gnatmake
2/ no --RTS is passed to gnatmake

If the two conditions are met then the GCC driver is called
with the collected -mxxx flags plus -print-multi-directory
and the resulting output is passed in a generated --RTS=
argument. Otherwise the patch does nothing and normal
gnatmake processing is done.

I tested this patch on x86_64 linux with gnatmake,
gnatmake -m32 and gnatmake -m64, and also
tested --GCC=myscript and checked that myscript was called
by Process_Multilib.

Note: gnat.dg and ACATS need more scripting to handle multilib
gracefully.

That said the gnatmake machinery make.adb has lots of context
so I might have gotten some things wrong, advices and comments
welcomed :).

Otherwise ok to commit to trunk?

Laurent


2009-02-25  Laurent GUERBY  <laurent@xxxxxxxxxx>

        * make.adb: Handle multilib.

Index: make.adb
===================================================================
--- make.adb    (revision 144573)
+++ make.adb    (working copy)
@@ -195,6 +195,9 @@
    RTS_Specified : String_Access := null;
    --  Used to detect multiple --RTS= switches
 
+   N_M_Switch : Natural := 0;
+   --  Used to count -mxxx switches that can affect multilib
+
    type Q_Record is record
       File  : File_Name_Type;
       Unit  : Unit_Name_Type;
@@ -666,6 +669,9 @@
    --  directory of the ultimate extending project. If it is not, we ignore
    --  the fact that this ALI file is read-only.
 
+   procedure Process_Multilib;
+   --  Add appropriate --RTS argument to handle multilib.
+
    ----------------------------------------------------
    -- Compiler, Binder & Linker Data and Subprograms --
    ----------------------------------------------------
@@ -6854,6 +6860,7 @@
       Dependencies.Init;
 
       RTS_Specified := null;
+      N_M_Switch := 0;
 
       Mains.Delete;
 
@@ -6913,6 +6920,10 @@
          Scan_Make_Arg (Argument (Next_Arg), And_Save => True);
       end loop Scan_Args;
 
+      if N_M_Switch > 0 and RTS_Specified = null then
+         Process_Multilib;
+      end if;
+
       if Commands_To_Stdout then
          Set_Standard_Output;
       end if;
@@ -7587,6 +7598,91 @@
       Set_Name_Table_Byte (N, B or Mark);
    end Mark_Directory;
 
+   ----------------------
+   -- Process_Multilib --
+   ----------------------
+
+   procedure Process_Multilib is
+
+      Output_FD         : File_Descriptor;
+      Output_Name       : String_Access;
+      Arg_Index         : Natural := 0;
+      Success           : Boolean := False;
+      Return_Code       : Integer := 0;
+      Multilib_Gcc_Path : String_Access;
+      Multilib_Gcc      : String_Access;
+      N_Read            : Integer := 0;
+      Line              : String (1 .. 1000);
+      Args              : Argument_List (1 .. N_M_Switch + 1);
+
+   begin
+      pragma Assert (N_M_Switch > 0 and RTS_Specified = null);
+
+      for Next_Arg in 1 .. Argument_Count loop
+         declare
+            Argv : constant String := Argument (Next_Arg);
+         begin
+            if Argv'Length > 2
+              and then Argv (1) = '-'
+              and then Argv (2) = 'm'
+              and then Argv /= "-margs"
+            then
+               Arg_Index := Arg_Index + 1;
+               Args (Arg_Index) := new String'(Argv);
+            end if;
+         end;
+      end loop;
+
+      pragma Assert (Arg_Index = N_M_Switch);
+
+      Args (Args'Last) := new String'("-print-multi-directory");
+
+      if Saved_Gcc /= null then
+         Multilib_Gcc := Saved_Gcc;
+      else
+         Multilib_Gcc := Gcc;
+      end if;
+
+      Multilib_Gcc_Path :=
+        GNAT.OS_Lib.Locate_Exec_On_Path (Multilib_Gcc.all);
+
+      Create_Temp_File (Output_FD, Output_Name);
+      if Output_FD = Invalid_FD then
+         return;
+      end if;
+
+      GNAT.OS_Lib.Spawn (Multilib_Gcc_Path.all, Args, Output_FD,
+                         Return_Code, False);
+      if Return_Code /= 0 then
+         return;
+      end if;
+
+      Output_FD := Open_Read (Output_Name.all, Binary);
+      if Output_FD = Invalid_FD then
+         return;
+      end if;
+
+      N_Read := Read (Output_FD, Line (1)'Address, Line'Length);
+      Close (Output_FD);
+      Delete_File (Output_Name.all, Success);
+
+      if N_Read = 0 or else Line (1 .. N_Read) = "." then
+         return;
+      end if;
+
+      for I in reverse 1 .. N_Read loop
+         if Line (I) = ASCII.CR or Line (I) = ASCII.LF then
+            N_Read := N_Read - 1;
+         else
+            exit;
+         end if;
+      end loop;
+
+      Scan_Make_Arg ("--RTS=" & Line (1 .. N_Read),
+                     And_Save => False);
+
+   end Process_Multilib;
+
    -----------------------------
    -- Recursive_Compute_Depth --
    -----------------------------
@@ -8043,6 +8139,10 @@
             Add_Switch (Argv, Compiler, And_Save => And_Save);
             Add_Switch (Argv, Linker, And_Save => And_Save);
 
+            if Argv (2) = 'm' then
+               N_M_Switch := N_M_Switch + 1;
+            end if;
+
          --  -C=<mapping file>
 
          elsif Argv'Last > 2 and then Argv (2) = 'C' then


<Prev in Thread] Current Thread [Next in Thread>