diff mbox

[ada] gnatlink's order of options interfers with --as-needed

Message ID 51713144.20705@ubuntu.com
State New
Headers show

Commit Message

Matthias Klose April 19, 2013, 11:57 a.m. UTC
The linux version of Build_Dynamic_Library passes all options and libraries in
Options, which end up on the command line before the object files.  So it looks
like the signature of Build_Dynamic_Library should differentiate between options
and libraries.  Until it does, use the same approach as done for on irix,
scanning the options for -l strings and moving them to Options_2, which end up
behind the object files. Just copied from the irix variant (available up to
4.7). Ok for 4.7, 4.8 and the trunk?

  Matthias

	* mlib-tgt-specific-linux.adb (Build_Dynamic_Library): Move -l* strings
	from Options to Options_2.

Comments

Arnaud Charlet April 19, 2013, 12:14 p.m. UTC | #1
Can you clarify what problem you are trying to solve (e.g. by providing
a testcase, explaining what you are doing and you would expect)?

Arno
Matthias Klose April 19, 2013, 12:35 p.m. UTC | #2
Am 19.04.2013 14:14, schrieb Arnaud Charlet:
> Can you clarify what problem you are trying to solve (e.g. by providing
> a testcase, explaining what you are doing and you would expect)?

from http://bugs.debian.org/680292

Gnatmake calls gcc -shared in a way incompatible with
--as-needed. Gprbuild uses a better ordering.

-- bug.ads
package Bug is
end Bug;
-- bug.gpr
project Bug is
  for Library_Name use "bug";
  for Library_Version use "libbug.so.1";
  for Library_Kind use "dynamic";
  for Library_Dir use "lib";
  for Library_Options use ("-lncurses");
end Bug;
$ mkdir lib
$ gnatmake -v -Pbug
...
/usr//bin/gcc-4.6 -shared ... -lncurses ... -lgnat-4.6 -Wl,-soname,libbug.so.1
/tmp/bug/bug.o
...
$ gnatclean -Pbug
...
$ gprbuild -v -Pbug
...
/usr/bin/gcc-4.6 -shared ... -lgnat-4.6 ... -Wl,-soname,libbug.so.1
/tmp/bug/bug.o -lncurses
...

When adding -Wl,--as-needed before -lncurses in Library_Options (or
using GNU gold linker with default options), symbols from -lgnat-4.6
are ignored because they are not used by any object *yet*. In this
minimal example, this is not a problem, but any useful library will
use symbols from -lgnat-4.6.
diff mbox

Patch

--- gcc/ada/mlib-tgt-specific-linux.adb
+++ gcc/ada/mlib-tgt-specific-linux.adb
@@ -81,19 +81,54 @@ 
       Version_Arg          : String_Access;
       Symbolic_Link_Needed : Boolean := False;
 
+      N_Options    : Argument_List := Options;
+      Options_Last : Natural := N_Options'Last;
+      --  After moving -lxxx to Options_2, N_Options up to index Options_Last
+      --  will contain the Options to pass to MLib.Utl.Gcc.
+
+      Real_Options_2 : Argument_List (1 .. Options'Length);
+      Real_Options_2_Last : Natural := 0;
+      --  Real_Options_2 up to index Real_Options_2_Last will contain the
+      --  Options_2 to pass to MLib.Utl.Gcc.
+
    begin
       if Opt.Verbose_Mode then
          Write_Str ("building relocatable shared library ");
          Write_Line (Lib_Path);
       end if;
 
+      --  Move all -lxxx to Options_2
+
+      declare
+         Index : Natural := N_Options'First;
+         Arg   : String_Access;
+
+      begin
+         while Index <= Options_Last loop
+            Arg := N_Options (Index);
+
+            if Arg'Length > 2
+              and then Arg (Arg'First .. Arg'First + 1) = "-l"
+            then
+               Real_Options_2_Last := Real_Options_2_Last + 1;
+               Real_Options_2 (Real_Options_2_Last) := Arg;
+               N_Options (Index .. Options_Last - 1) :=
+                 N_Options (Index + 1 .. Options_Last);
+               Options_Last := Options_Last - 1;
+
+            else
+               Index := Index + 1;
+            end if;
+         end loop;
+      end;
+
       if Lib_Version = "" then
          Utl.Gcc
            (Output_File => Lib_Path,
             Objects     => Ofiles,
-            Options     => Options,
+            Options     => N_Options (N_Options'First .. Options_Last),
             Driver_Name => Driver_Name,
-            Options_2   => No_Argument_List);
+            Options_2   => Real_Options_2 (1 .. Real_Options_2_Last));
 
       else
          declare
@@ -111,18 +146,18 @@ 
                Utl.Gcc
                  (Output_File => Lib_Version,
                   Objects     => Ofiles,
-                  Options     => Options & Version_Arg,
+		  Options     => N_Options (N_Options'First .. Options_Last) & Version_Arg,
                   Driver_Name => Driver_Name,
-                  Options_2   => No_Argument_List);
+                  Options_2   => Real_Options_2 (1 .. Real_Options_2_Last));
                Symbolic_Link_Needed := Lib_Version /= Lib_Path;
 
             else
                Utl.Gcc
                  (Output_File => Lib_Dir & Directory_Separator & Lib_Version,
                   Objects     => Ofiles,
-                  Options     => Options & Version_Arg,
+		  Options     => N_Options (N_Options'First .. Options_Last) & Version_Arg,
                   Driver_Name => Driver_Name,
-                  Options_2   => No_Argument_List);
+                  Options_2   => Real_Options_2 (1 .. Real_Options_2_Last));
                Symbolic_Link_Needed :=
                  Lib_Dir & Directory_Separator & Lib_Version /= Lib_Path;
             end if;