OSDN Git Service

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