OSDN Git Service

2006-10-31 Javier Miranda <miranda@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / mlib-tgt-vms-ia64.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             M L I B . T G T                              --
6 --                         (Integrity VMS Version)                          --
7 --                                                                          --
8 --                                 B o d y                                  --
9 --                                                                          --
10 --            Copyright (C) 2004-2005 Free Software Foundation, Inc.        --
11 --                                                                          --
12 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
13 -- terms of the  GNU General Public License as published  by the Free Soft- --
14 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
15 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
16 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
17 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
18 -- for  more details.  You should have  received  a copy of the GNU General --
19 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
20 -- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
21 -- Boston, MA 02110-1301, USA.                                              --
22 --                                                                          --
23 -- GNAT was originally developed  by the GNAT team at  New York University. --
24 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
25 --                                                                          --
26 ------------------------------------------------------------------------------
27
28 --  This is the Integrity VMS version of the body
29
30 with Ada.Characters.Handling; use Ada.Characters.Handling;
31
32 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
33
34 with MLib.Fil;
35 with MLib.Utl;
36 with Namet;    use Namet;
37 with Opt;      use Opt;
38 with Output;   use Output;
39 with Prj.Com;
40
41 with System;           use System;
42 with System.Case_Util; use System.Case_Util;
43 with System.CRTL;      use System.CRTL;
44
45 package body MLib.Tgt is
46
47    use GNAT;
48
49    Empty_Argument_List : aliased Argument_List := (1 .. 0 => null);
50    Additional_Objects  : Argument_List_Access := Empty_Argument_List'Access;
51    --  Used to add the generated auto-init object files for auto-initializing
52    --  stand-alone libraries.
53
54    Macro_Name   : constant String := "mcr gnu:[bin]gcc -c -x assembler";
55    --  The name of the command to invoke the macro-assembler
56
57    VMS_Options : Argument_List := (1 .. 1 => null);
58
59    Gnatsym_Name : constant String := "gnatsym";
60
61    Gnatsym_Path : String_Access;
62
63    Arguments : Argument_List_Access := null;
64    Last_Argument : Natural := 0;
65
66    Success : Boolean := False;
67
68    Shared_Libgcc : aliased String := "-shared-libgcc";
69
70    No_Shared_Libgcc_Switch : aliased Argument_List := (1 .. 0 => null);
71    Shared_Libgcc_Switch    : aliased Argument_List :=
72                                (1 => Shared_Libgcc'Access);
73    Link_With_Shared_Libgcc : Argument_List_Access :=
74                                No_Shared_Libgcc_Switch'Access;
75
76    ---------------------
77    -- Archive_Builder --
78    ---------------------
79
80    function Archive_Builder return String is
81    begin
82       return "ar";
83    end Archive_Builder;
84
85    -----------------------------
86    -- Archive_Builder_Options --
87    -----------------------------
88
89    function Archive_Builder_Options return String_List_Access is
90    begin
91       return new String_List'(1 => new String'("cr"));
92    end Archive_Builder_Options;
93
94    -----------------
95    -- Archive_Ext --
96    -----------------
97
98    function Archive_Ext return String is
99    begin
100       return "olb";
101    end Archive_Ext;
102
103    ---------------------
104    -- Archive_Indexer --
105    ---------------------
106
107    function Archive_Indexer return String is
108    begin
109       return "ranlib";
110    end Archive_Indexer;
111
112    -----------------------------
113    -- Archive_Indexer_Options --
114    -----------------------------
115
116    function Archive_Indexer_Options return String_List_Access is
117    begin
118       return new String_List (1 .. 0);
119    end Archive_Indexer_Options;
120
121    ---------------------------
122    -- Build_Dynamic_Library --
123    ---------------------------
124
125    procedure Build_Dynamic_Library
126      (Ofiles       : Argument_List;
127       Foreign      : Argument_List;
128       Afiles       : Argument_List;
129       Options      : Argument_List;
130       Options_2    : Argument_List;
131       Interfaces   : Argument_List;
132       Lib_Filename : String;
133       Lib_Dir      : String;
134       Symbol_Data  : Symbol_Record;
135       Driver_Name  : Name_Id := No_Name;
136       Lib_Version  : String  := "";
137       Auto_Init    : Boolean := False)
138    is
139       pragma Unreferenced (Foreign);
140       pragma Unreferenced (Afiles);
141
142       Lib_File : constant String :=
143                    Lib_Dir & Directory_Separator & "lib" &
144                    Fil.Ext_To (Lib_Filename, DLL_Ext);
145
146       Opts      : Argument_List := Options;
147       Last_Opt  : Natural       := Opts'Last;
148       Opts2     : Argument_List (Options'Range);
149       Last_Opt2 : Natural       := Opts2'First - 1;
150
151       Inter : constant Argument_List := Interfaces;
152
153       function Is_Interface (Obj_File : String) return Boolean;
154       --  For a Stand-Alone Library, returns True if Obj_File is the object
155       --  file name of an interface of the SAL. For other libraries, always
156       --  return True.
157
158       function Option_File_Name return String;
159       --  Returns Symbol_File, if not empty. Otherwise, returns "symvec.opt"
160
161       function Version_String return String;
162       --  Returns Lib_Version if not empty and if Symbol_Data.Symbol_Policy is
163       --  not Autonomous, otherwise returns "".
164       --  When Symbol_Data.Symbol_Policy is Autonomous, fails gnatmake if
165       --  Lib_Version is not the image of a positive number.
166
167       ------------------
168       -- Is_Interface --
169       ------------------
170
171       function Is_Interface (Obj_File : String) return Boolean is
172          ALI : constant String :=
173                  Fil.Ext_To
174                   (Filename => To_Lower (Base_Name (Obj_File)),
175                    New_Ext  => "ali");
176
177       begin
178          if Inter'Length = 0 then
179             return True;
180
181          elsif ALI'Length > 2 and then
182                ALI (ALI'First .. ALI'First + 2) = "b__"
183          then
184             return True;
185
186          else
187             for J in Inter'Range loop
188                if Inter (J).all = ALI then
189                   return True;
190                end if;
191             end loop;
192
193             return False;
194          end if;
195       end Is_Interface;
196
197       ----------------------
198       -- Option_File_Name --
199       ----------------------
200
201       function Option_File_Name return String is
202       begin
203          if Symbol_Data.Symbol_File = No_Name then
204             return "symvec.opt";
205          else
206             Get_Name_String (Symbol_Data.Symbol_File);
207             To_Lower (Name_Buffer (1 .. Name_Len));
208             return Name_Buffer (1 .. Name_Len);
209          end if;
210       end Option_File_Name;
211
212       --------------------
213       -- Version_String --
214       --------------------
215
216       function Version_String return String is
217          Version : Integer := 0;
218       begin
219          if Lib_Version = ""
220            or else Symbol_Data.Symbol_Policy /= Autonomous
221          then
222             return "";
223
224          else
225             begin
226                Version := Integer'Value (Lib_Version);
227
228                if Version <= 0 then
229                   raise Constraint_Error;
230                end if;
231
232                return Lib_Version;
233
234             exception
235                when Constraint_Error =>
236                   Fail ("illegal version """, Lib_Version,
237                         """ (on VMS version must be a positive number)");
238                   return "";
239             end;
240          end if;
241       end Version_String;
242
243       Opt_File_Name  : constant String := Option_File_Name;
244       Version        : constant String := Version_String;
245       For_Linker_Opt : String_Access;
246
247    --  Start of processing for Build_Dynamic_Library
248
249    begin
250       --  Invoke gcc with -shared-libgcc, but only for GCC 3 or higher
251
252       if GCC_Version >= 3 then
253          Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access;
254       else
255          Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access;
256       end if;
257
258       --  Option file must end with ".opt"
259
260       if Opt_File_Name'Length > 4
261         and then
262           Opt_File_Name (Opt_File_Name'Last - 3 .. Opt_File_Name'Last) = ".opt"
263       then
264          For_Linker_Opt := new String'("--for-linker=" & Opt_File_Name);
265       else
266          Fail ("Options File """, Opt_File_Name, """ must end with .opt");
267       end if;
268
269       VMS_Options (VMS_Options'First) := For_Linker_Opt;
270
271       for J in Inter'Range loop
272          To_Lower (Inter (J).all);
273       end loop;
274
275       --  "gnatsym" is necessary for building the option file
276
277       if Gnatsym_Path = null then
278          Gnatsym_Path := OS_Lib.Locate_Exec_On_Path (Gnatsym_Name);
279
280          if Gnatsym_Path = null then
281             Fail (Gnatsym_Name, " not found in path");
282          end if;
283       end if;
284
285       --  For auto-initialization of a stand-alone library, we create
286       --  a macro-assembly file and we invoke the macro-assembler.
287
288       if Auto_Init then
289          declare
290             Macro_File_Name : constant String := Lib_Filename & "__init.asm";
291             Macro_File      : File_Descriptor;
292             Init_Proc       : String := Lib_Filename & "INIT";
293             Popen_Result    : System.Address;
294             Pclose_Result   : Integer;
295             Len             : Natural;
296             OK              : Boolean := True;
297
298             command  : constant String :=
299                          Macro_Name & " " & Macro_File_Name & ASCII.NUL;
300             --  The command to invoke the assembler on the generated auto-init
301             --  assembly file.
302
303             mode : constant String := "r" & ASCII.NUL;
304             --  The mode for the invocation of Popen
305
306          begin
307             To_Upper (Init_Proc);
308
309             if Verbose_Mode then
310                Write_Str ("Creating auto-init assembly file """);
311                Write_Str (Macro_File_Name);
312                Write_Line ("""");
313             end if;
314
315             --  Create and write the auto-init assembly file
316
317             declare
318                First_Line : constant String :=
319                  ASCII.HT &
320                  ".type " & Init_Proc & "#, @function" &
321                  ASCII.LF;
322                Second_Line : constant String :=
323                  ASCII.HT &
324                  ".global " & Init_Proc & "#" &
325                  ASCII.LF;
326                Third_Line : constant String :=
327                  ASCII.HT &
328                  ".global LIB$INITIALIZE#" &
329                  ASCII.LF;
330                Fourth_Line : constant String :=
331                  ASCII.HT &
332                  ".section LIB$INITIALIZE#,""a"",@progbits" &
333                  ASCII.LF;
334                Fifth_Line : constant String :=
335                  ASCII.HT &
336                  "data4 @fptr(" & Init_Proc & "#)" &
337                   ASCII.LF;
338
339             begin
340                Macro_File := Create_File (Macro_File_Name, Text);
341                OK := Macro_File /= Invalid_FD;
342
343                if OK then
344                   Len := Write
345                     (Macro_File, First_Line (First_Line'First)'Address,
346                      First_Line'Length);
347                   OK := Len = First_Line'Length;
348                end if;
349
350                if OK then
351                   Len := Write
352                     (Macro_File, Second_Line (Second_Line'First)'Address,
353                      Second_Line'Length);
354                   OK := Len = Second_Line'Length;
355                end if;
356
357                if OK then
358                   Len := Write
359                     (Macro_File, Third_Line (Third_Line'First)'Address,
360                      Third_Line'Length);
361                   OK := Len = Third_Line'Length;
362                end if;
363
364                if OK then
365                   Len := Write
366                     (Macro_File, Fourth_Line (Fourth_Line'First)'Address,
367                      Fourth_Line'Length);
368                   OK := Len = Fourth_Line'Length;
369                end if;
370
371                if OK then
372                   Len := Write
373                     (Macro_File, Fifth_Line (Fifth_Line'First)'Address,
374                      Fifth_Line'Length);
375                   OK := Len = Fifth_Line'Length;
376                end if;
377
378                if OK then
379                   Close (Macro_File, OK);
380                end if;
381
382                if not OK then
383                   Fail ("creation of auto-init assembly file """,
384                         Macro_File_Name, """ failed");
385                end if;
386             end;
387
388             --  Invoke the macro-assembler
389
390             if Verbose_Mode then
391                Write_Str ("Assembling auto-init assembly file """);
392                Write_Str (Macro_File_Name);
393                Write_Line ("""");
394             end if;
395
396             Popen_Result := popen (command (command'First)'Address,
397                                    mode (mode'First)'Address);
398
399             if Popen_Result = Null_Address then
400                Fail ("assembly of auto-init assembly file """,
401                      Macro_File_Name, """ failed");
402             end if;
403
404             --  Wait for the end of execution of the macro-assembler
405
406             Pclose_Result := pclose (Popen_Result);
407
408             if Pclose_Result < 0 then
409                Fail ("assembly of auto init assembly file """,
410                      Macro_File_Name, """ failed");
411             end if;
412
413             --  Add the generated object file to the list of objects to be
414             --  included in the library.
415
416             Additional_Objects :=
417               new Argument_List'
418                 (1 => new String'(Lib_Filename & "__init.obj"));
419          end;
420       end if;
421
422       --  Allocate the argument list and put the symbol file name, the
423       --  reference (if any) and the policy (if not autonomous).
424
425       Arguments := new Argument_List (1 .. Ofiles'Length + 8);
426
427       Last_Argument := 0;
428
429       --  Verbosity
430
431       if Verbose_Mode then
432          Last_Argument := Last_Argument + 1;
433          Arguments (Last_Argument) := new String'("-v");
434       end if;
435
436       --  Version number (major ID)
437
438       if Lib_Version /= "" then
439          Last_Argument := Last_Argument + 1;
440          Arguments (Last_Argument) := new String'("-V");
441          Last_Argument := Last_Argument + 1;
442          Arguments (Last_Argument) := new String'(Version);
443       end if;
444
445       --  Symbol file
446
447       Last_Argument := Last_Argument + 1;
448       Arguments (Last_Argument) := new String'("-s");
449       Last_Argument := Last_Argument + 1;
450       Arguments (Last_Argument) := new String'(Opt_File_Name);
451
452       --  Reference Symbol File
453
454       if Symbol_Data.Reference /= No_Name then
455          Last_Argument := Last_Argument + 1;
456          Arguments (Last_Argument) := new String'("-r");
457          Last_Argument := Last_Argument + 1;
458          Arguments (Last_Argument) :=
459            new String'(Get_Name_String (Symbol_Data.Reference));
460       end if;
461
462       --  Policy
463
464       case Symbol_Data.Symbol_Policy is
465          when Autonomous =>
466             null;
467
468          when Compliant =>
469             Last_Argument := Last_Argument + 1;
470             Arguments (Last_Argument) := new String'("-c");
471
472          when Controlled =>
473             Last_Argument := Last_Argument + 1;
474             Arguments (Last_Argument) := new String'("-C");
475
476          when Restricted =>
477             Last_Argument := Last_Argument + 1;
478             Arguments (Last_Argument) := new String'("-R");
479       end case;
480
481       --  Add each relevant object file
482
483       for Index in Ofiles'Range loop
484          if Is_Interface (Ofiles (Index).all) then
485             Last_Argument := Last_Argument + 1;
486             Arguments (Last_Argument) := new String'(Ofiles (Index).all);
487          end if;
488       end loop;
489
490       --  Spawn gnatsym
491
492       Spawn (Program_Name => Gnatsym_Path.all,
493              Args         => Arguments (1 .. Last_Argument),
494              Success      => Success);
495
496       if not Success then
497          Fail ("unable to create symbol file for library """,
498                Lib_Filename, """");
499       end if;
500
501       Free (Arguments);
502
503       --  Move all the -l switches from Opts to Opts2
504
505       declare
506          Index : Natural := Opts'First;
507          Opt   : String_Access;
508
509       begin
510          while Index <= Last_Opt loop
511             Opt := Opts (Index);
512
513             if Opt'Length > 2 and then
514               Opt (Opt'First .. Opt'First + 1) = "-l"
515             then
516                if Index < Last_Opt then
517                   Opts (Index .. Last_Opt - 1) :=
518                     Opts (Index + 1 .. Last_Opt);
519                end if;
520
521                Last_Opt := Last_Opt - 1;
522
523                Last_Opt2 := Last_Opt2 + 1;
524                Opts2 (Last_Opt2) := Opt;
525
526             else
527                Index := Index + 1;
528             end if;
529          end loop;
530       end;
531
532       --  Invoke gcc to build the library
533
534       Utl.Gcc
535         (Output_File => Lib_File,
536          Objects     => Ofiles & Additional_Objects.all,
537          Options     => VMS_Options,
538          Options_2   => Link_With_Shared_Libgcc.all &
539                         Opts (Opts'First .. Last_Opt) &
540                         Opts2 (Opts2'First .. Last_Opt2) & Options_2,
541          Driver_Name => Driver_Name);
542
543       --  The auto-init object file need to be deleted, so that it will not
544       --  be included in the library as a regular object file, otherwise
545       --  it will be included twice when the library will be built next
546       --  time, which may lead to errors.
547
548       if Auto_Init then
549          declare
550             Auto_Init_Object_File_Name : constant String :=
551                                            Lib_Filename & "__init.obj";
552             Disregard : Boolean;
553
554          begin
555             if Verbose_Mode then
556                Write_Str ("deleting auto-init object file """);
557                Write_Str (Auto_Init_Object_File_Name);
558                Write_Line ("""");
559             end if;
560
561             Delete_File (Auto_Init_Object_File_Name, Success => Disregard);
562          end;
563       end if;
564    end Build_Dynamic_Library;
565
566    -------------
567    -- DLL_Ext --
568    -------------
569
570    function DLL_Ext return String is
571    begin
572       return "exe";
573    end DLL_Ext;
574
575    ----------------
576    -- DLL_Prefix --
577    ----------------
578
579    function DLL_Prefix return String is
580    begin
581       return "lib";
582    end DLL_Prefix;
583
584    --------------------
585    -- Dynamic_Option --
586    --------------------
587
588    function Dynamic_Option return String is
589    begin
590       return "-shared";
591    end Dynamic_Option;
592
593    -------------------
594    -- Is_Object_Ext --
595    -------------------
596
597    function Is_Object_Ext (Ext : String) return Boolean is
598    begin
599       return Ext = ".obj";
600    end Is_Object_Ext;
601
602    --------------
603    -- Is_C_Ext --
604    --------------
605
606    function Is_C_Ext (Ext : String) return Boolean is
607    begin
608       return Ext = ".c";
609    end Is_C_Ext;
610
611    --------------------
612    -- Is_Archive_Ext --
613    --------------------
614
615    function Is_Archive_Ext (Ext : String) return Boolean is
616    begin
617       return Ext = ".olb" or else Ext = ".exe";
618    end Is_Archive_Ext;
619
620    -------------
621    -- Libgnat --
622    -------------
623
624    function Libgnat return String is
625       Libgnat_A : constant String := "libgnat.a";
626       Libgnat_Olb : constant String := "libgnat.olb";
627
628    begin
629       Name_Len := Libgnat_A'Length;
630       Name_Buffer (1 .. Name_Len) := Libgnat_A;
631
632       if Osint.Find_File (Name_Enter, Osint.Library) /= No_File then
633          return Libgnat_A;
634
635       else
636          return Libgnat_Olb;
637       end if;
638    end Libgnat;
639
640    ------------------------
641    -- Library_Exists_For --
642    ------------------------
643
644    function Library_Exists_For
645      (Project : Project_Id; In_Tree : Project_Tree_Ref) return Boolean
646    is
647    begin
648       if not In_Tree.Projects.Table (Project).Library then
649          Fail ("INTERNAL ERROR: Library_Exists_For called " &
650                "for non library project");
651          return False;
652
653       else
654          declare
655             Lib_Dir : constant String :=
656               Get_Name_String
657                 (In_Tree.Projects.Table (Project).Library_Dir);
658             Lib_Name : constant String :=
659               Get_Name_String
660                 (In_Tree.Projects.Table (Project).Library_Name);
661
662          begin
663             if In_Tree.Projects.Table (Project).Library_Kind =
664               Static
665             then
666                return Is_Regular_File
667                  (Lib_Dir & Directory_Separator & "lib" &
668                   Fil.Ext_To (Lib_Name, Archive_Ext));
669
670             else
671                return Is_Regular_File
672                  (Lib_Dir & Directory_Separator & "lib" &
673                   Fil.Ext_To (Lib_Name, DLL_Ext));
674             end if;
675          end;
676       end if;
677    end Library_Exists_For;
678
679    ---------------------------
680    -- Library_File_Name_For --
681    ---------------------------
682
683    function Library_File_Name_For
684      (Project : Project_Id;
685       In_Tree : Project_Tree_Ref) return Name_Id
686    is
687    begin
688       if not In_Tree.Projects.Table (Project).Library then
689          Prj.Com.Fail ("INTERNAL ERROR: Library_File_Name_For called " &
690                        "for non library project");
691          return No_Name;
692
693       else
694          declare
695             Lib_Name : constant String :=
696               Get_Name_String
697                 (In_Tree.Projects.Table (Project).Library_Name);
698
699          begin
700             Name_Len := 3;
701             Name_Buffer (1 .. Name_Len) := "lib";
702
703             if In_Tree.Projects.Table (Project).Library_Kind =
704               Static then
705                Add_Str_To_Name_Buffer (Fil.Ext_To (Lib_Name, Archive_Ext));
706
707             else
708                Add_Str_To_Name_Buffer (Fil.Ext_To (Lib_Name, DLL_Ext));
709             end if;
710
711             return Name_Find;
712          end;
713       end if;
714    end Library_File_Name_For;
715
716    ----------------
717    -- Object_Ext --
718    ----------------
719
720    function Object_Ext return String is
721    begin
722       return "obj";
723    end Object_Ext;
724
725    ----------------
726    -- PIC_Option --
727    ----------------
728
729    function PIC_Option return String is
730    begin
731       return "";
732    end PIC_Option;
733
734    -----------------------------------------------
735    -- Standalone_Library_Auto_Init_Is_Supported --
736    -----------------------------------------------
737
738    function Standalone_Library_Auto_Init_Is_Supported return Boolean is
739    begin
740       return True;
741    end Standalone_Library_Auto_Init_Is_Supported;
742
743    ---------------------------
744    -- Support_For_Libraries --
745    ---------------------------
746
747    function Support_For_Libraries return Library_Support is
748    begin
749       return Full;
750    end Support_For_Libraries;
751
752 end MLib.Tgt;