OSDN Git Service

2005-03-08 Geert Bosch <bosch@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / mlib-tgt-vms-alpha.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             M L I B . T G T                              --
6 --                           (Alpha VMS Version)                            --
7 --                                                                          --
8 --                                 B o d y                                  --
9 --                                                                          --
10 --          Copyright (C) 2003-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 Alpha 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, otherwise returns "1".
164       --  Fails gnatmake if Lib_Version is not the image of a positive number.
165
166       ------------------
167       -- Is_Interface --
168       ------------------
169
170       function Is_Interface (Obj_File : String) return Boolean is
171          ALI : constant String :=
172                  Fil.Ext_To
173                   (Filename => To_Lower (Base_Name (Obj_File)),
174                    New_Ext  => "ali");
175
176       begin
177          if Inter'Length = 0 then
178             return True;
179
180          elsif ALI'Length > 2 and then
181                ALI (ALI'First .. ALI'First + 1) = "b$"
182          then
183             return True;
184
185          else
186             for J in Inter'Range loop
187                if Inter (J).all = ALI then
188                   return True;
189                end if;
190             end loop;
191
192             return False;
193          end if;
194       end Is_Interface;
195
196       ----------------------
197       -- Option_File_Name --
198       ----------------------
199
200       function Option_File_Name return String is
201       begin
202          if Symbol_Data.Symbol_File = No_Name then
203             return "symvec.opt";
204          else
205             Get_Name_String (Symbol_Data.Symbol_File);
206             To_Lower (Name_Buffer (1 .. Name_Len));
207             return Name_Buffer (1 .. Name_Len);
208          end if;
209       end Option_File_Name;
210
211       --------------------
212       -- Version_String --
213       --------------------
214
215       function Version_String return String is
216          Version : Integer := 0;
217       begin
218          if Lib_Version = "" then
219             return "1";
220
221          else
222             begin
223                Version := Integer'Value (Lib_Version);
224
225                if Version <= 0 then
226                   raise Constraint_Error;
227                end if;
228
229                return Lib_Version;
230
231             exception
232                when Constraint_Error =>
233                   Fail ("illegal version """, Lib_Version,
234                         """ (on VMS version must be a positive number)");
235                   return "";
236             end;
237          end if;
238       end Version_String;
239
240       Opt_File_Name  : constant String := Option_File_Name;
241       Version        : constant String := Version_String;
242       For_Linker_Opt : String_Access;
243
244    --  Start of processing for Build_Dynamic_Library
245
246    begin
247       --  Invoke gcc with -shared-libgcc, but only for GCC 3 or higher
248
249       if GCC_Version >= 3 then
250          Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access;
251       else
252          Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access;
253       end if;
254
255       --  If option file name does not ends with ".opt", append "/OPTIONS"
256       --  to its specification for the VMS linker.
257
258       if Opt_File_Name'Length > 4
259         and then
260           Opt_File_Name (Opt_File_Name'Last - 3 .. Opt_File_Name'Last) = ".opt"
261       then
262          For_Linker_Opt := new String'("--for-linker=" & Opt_File_Name);
263       else
264          For_Linker_Opt :=
265            new String'("--for-linker=" & Opt_File_Name & "/OPTIONS");
266       end if;
267
268       VMS_Options (VMS_Options'First) := For_Linker_Opt;
269
270       for J in Inter'Range loop
271          To_Lower (Inter (J).all);
272       end loop;
273
274       --  "gnatsym" is necessary for building the option file
275
276       if Gnatsym_Path = null then
277          Gnatsym_Path := OS_Lib.Locate_Exec_On_Path (Gnatsym_Name);
278
279          if Gnatsym_Path = null then
280             Fail (Gnatsym_Name, " not found in path");
281          end if;
282       end if;
283
284       --  For auto-initialization of a stand-alone library, we create
285       --  a macro-assembly file and we invoke the macro-assembler.
286
287       if Auto_Init then
288          declare
289             Macro_File_Name : constant String := Lib_Filename & "$init.asm";
290             Macro_File      : File_Descriptor;
291             Init_Proc       : String := Lib_Filename & "INIT";
292             Popen_Result    : System.Address;
293             Pclose_Result   : Integer;
294             Len             : Natural;
295             OK              : Boolean := True;
296
297             command  : constant String :=
298                          Macro_Name & " " & Macro_File_Name & ASCII.NUL;
299             --  The command to invoke the assembler on the generated auto-init
300             --  assembly file.
301
302             mode : constant String := "r" & ASCII.NUL;
303             --  The mode for the invocation of Popen
304
305          begin
306             To_Upper (Init_Proc);
307
308             if Verbose_Mode then
309                Write_Str ("Creating auto-init assembly file """);
310                Write_Str (Macro_File_Name);
311                Write_Line ("""");
312             end if;
313
314             --  Create and write the auto-init assembly file
315
316             declare
317                First_Line : constant String :=
318                               ASCII.HT & ".section LIB$INITIALIZE,GBL,NOWRT" &
319                ASCII.LF;
320                Second_Line : constant String :=
321                                ASCII.HT & ".long " & Init_Proc & ASCII.LF;
322                --  First and second lines of the auto-init assembly file
323
324             begin
325                Macro_File := Create_File (Macro_File_Name, Text);
326                OK := Macro_File /= Invalid_FD;
327
328                if OK then
329                   Len := Write
330                     (Macro_File, First_Line (First_Line'First)'Address,
331                      First_Line'Length);
332                   OK := Len = First_Line'Length;
333                end if;
334
335                if OK then
336                   Len := Write
337                     (Macro_File, Second_Line (Second_Line'First)'Address,
338                      Second_Line'Length);
339                   OK := Len = Second_Line'Length;
340                end if;
341
342                if OK then
343                   Close (Macro_File, OK);
344                end if;
345
346                if not OK then
347                   Fail ("creation of auto-init assembly file """,
348                         Macro_File_Name, """ failed");
349                end if;
350             end;
351
352             --  Invoke the macro-assembler
353
354             if Verbose_Mode then
355                Write_Str ("Assembling auto-init assembly file """);
356                Write_Str (Macro_File_Name);
357                Write_Line ("""");
358             end if;
359
360             Popen_Result := popen (command (command'First)'Address,
361                                    mode (mode'First)'Address);
362
363             if Popen_Result = Null_Address then
364                Fail ("assembly of auto-init assembly file """,
365                      Macro_File_Name, """ failed");
366             end if;
367
368             --  Wait for the end of execution of the macro-assembler
369
370             Pclose_Result := pclose (Popen_Result);
371
372             if Pclose_Result < 0 then
373                Fail ("assembly of auto init assembly file """,
374                      Macro_File_Name, """ failed");
375             end if;
376
377             --  Add the generated object file to the list of objects to be
378             --  included in the library.
379
380             Additional_Objects :=
381               new Argument_List'
382                 (1 => new String'(Lib_Filename & "$init.obj"));
383          end;
384       end if;
385
386       --  Allocate the argument list and put the symbol file name, the
387       --  reference (if any) and the policy (if not autonomous).
388
389       Arguments := new Argument_List (1 .. Ofiles'Length + 8);
390
391       Last_Argument := 0;
392
393       --  Verbosity
394
395       if Verbose_Mode then
396          Last_Argument := Last_Argument + 1;
397          Arguments (Last_Argument) := new String'("-v");
398       end if;
399
400       --  Version number (major ID)
401
402       if Lib_Version /= "" then
403          Last_Argument := Last_Argument + 1;
404          Arguments (Last_Argument) := new String'("-V");
405          Last_Argument := Last_Argument + 1;
406          Arguments (Last_Argument) := new String'(Version);
407       end if;
408
409       --  Symbol file
410
411       Last_Argument := Last_Argument + 1;
412       Arguments (Last_Argument) := new String'("-s");
413       Last_Argument := Last_Argument + 1;
414       Arguments (Last_Argument) := new String'(Opt_File_Name);
415
416       --  Reference Symbol File
417
418       if Symbol_Data.Reference /= No_Name then
419          Last_Argument := Last_Argument + 1;
420          Arguments (Last_Argument) := new String'("-r");
421          Last_Argument := Last_Argument + 1;
422          Arguments (Last_Argument) :=
423            new String'(Get_Name_String (Symbol_Data.Reference));
424       end if;
425
426       --  Policy
427
428       case Symbol_Data.Symbol_Policy is
429          when Autonomous =>
430             null;
431
432          when Compliant =>
433             Last_Argument := Last_Argument + 1;
434             Arguments (Last_Argument) := new String'("-c");
435
436          when Controlled =>
437             Last_Argument := Last_Argument + 1;
438             Arguments (Last_Argument) := new String'("-C");
439
440          when Restricted =>
441             Last_Argument := Last_Argument + 1;
442             Arguments (Last_Argument) := new String'("-R");
443       end case;
444
445       --  Add each relevant object file
446
447       for Index in Ofiles'Range loop
448          if Is_Interface (Ofiles (Index).all) then
449             Last_Argument := Last_Argument + 1;
450             Arguments (Last_Argument) := new String'(Ofiles (Index).all);
451          end if;
452       end loop;
453
454       --  Spawn gnatsym
455
456       Spawn (Program_Name => Gnatsym_Path.all,
457              Args         => Arguments (1 .. Last_Argument),
458              Success      => Success);
459
460       if not Success then
461          Fail ("unable to create symbol file for library """,
462                Lib_Filename, """");
463       end if;
464
465       Free (Arguments);
466
467       --  Move all the -l switches from Opts to Opts2
468
469       declare
470          Index : Natural := Opts'First;
471          Opt   : String_Access;
472
473       begin
474          while Index <= Last_Opt loop
475             Opt := Opts (Index);
476
477             if Opt'Length > 2 and then
478               Opt (Opt'First .. Opt'First + 1) = "-l"
479             then
480                if Index < Last_Opt then
481                   Opts (Index .. Last_Opt - 1) :=
482                     Opts (Index + 1 .. Last_Opt);
483                end if;
484
485                Last_Opt := Last_Opt - 1;
486
487                Last_Opt2 := Last_Opt2 + 1;
488                Opts2 (Last_Opt2) := Opt;
489
490             else
491                Index := Index + 1;
492             end if;
493          end loop;
494       end;
495
496       --  Invoke gcc to build the library
497
498       Utl.Gcc
499         (Output_File => Lib_File,
500          Objects     => Ofiles & Additional_Objects.all,
501          Options     => VMS_Options,
502          Options_2   => Link_With_Shared_Libgcc.all &
503                         Opts (Opts'First .. Last_Opt) &
504                         Opts2 (Opts2'First .. Last_Opt2) & Options_2,
505          Driver_Name => Driver_Name);
506
507       --  The auto-init object file need to be deleted, so that it will not
508       --  be included in the library as a regular object file, otherwise
509       --  it will be included twice when the library will be built next
510       --  time, which may lead to errors.
511
512       if Auto_Init then
513          declare
514             Auto_Init_Object_File_Name : constant String :=
515                                            Lib_Filename & "$init.obj";
516             Disregard : Boolean;
517
518          begin
519             if Verbose_Mode then
520                Write_Str ("deleting auto-init object file """);
521                Write_Str (Auto_Init_Object_File_Name);
522                Write_Line ("""");
523             end if;
524
525             Delete_File (Auto_Init_Object_File_Name, Success => Disregard);
526          end;
527       end if;
528    end Build_Dynamic_Library;
529
530    -------------
531    -- DLL_Ext --
532    -------------
533
534    function DLL_Ext return String is
535    begin
536       return "exe";
537    end DLL_Ext;
538
539    --------------------
540    -- Dynamic_Option --
541    --------------------
542
543    function Dynamic_Option return String is
544    begin
545       return "-shared";
546    end Dynamic_Option;
547
548    -------------------
549    -- Is_Object_Ext --
550    -------------------
551
552    function Is_Object_Ext (Ext : String) return Boolean is
553    begin
554       return Ext = ".obj";
555    end Is_Object_Ext;
556
557    --------------
558    -- Is_C_Ext --
559    --------------
560
561    function Is_C_Ext (Ext : String) return Boolean is
562    begin
563       return Ext = ".c";
564    end Is_C_Ext;
565
566    --------------------
567    -- Is_Archive_Ext --
568    --------------------
569
570    function Is_Archive_Ext (Ext : String) return Boolean is
571    begin
572       return Ext = ".olb" or else Ext = ".exe";
573    end Is_Archive_Ext;
574
575    -------------
576    -- Libgnat --
577    -------------
578
579    function Libgnat return String is
580       Libgnat_A : constant String := "libgnat.a";
581       Libgnat_Olb : constant String := "libgnat.olb";
582
583    begin
584       Name_Len := Libgnat_A'Length;
585       Name_Buffer (1 .. Name_Len) := Libgnat_A;
586
587       if Osint.Find_File (Name_Enter, Osint.Library) /= No_File then
588          return Libgnat_A;
589
590       else
591          return Libgnat_Olb;
592       end if;
593    end Libgnat;
594
595    ------------------------
596    -- Library_Exists_For --
597    ------------------------
598
599    function Library_Exists_For
600      (Project : Project_Id; In_Tree : Project_Tree_Ref) return Boolean
601    is
602    begin
603       if not In_Tree.Projects.Table (Project).Library then
604          Fail ("INTERNAL ERROR: Library_Exists_For called " &
605                "for non library project");
606          return False;
607
608       else
609          declare
610             Lib_Dir : constant String :=
611               Get_Name_String
612                 (In_Tree.Projects.Table (Project).Library_Dir);
613             Lib_Name : constant String :=
614               Get_Name_String
615                 (In_Tree.Projects.Table (Project).Library_Name);
616
617          begin
618             if In_Tree.Projects.Table (Project).Library_Kind =
619               Static
620             then
621                return Is_Regular_File
622                  (Lib_Dir & Directory_Separator & "lib" &
623                   Fil.Ext_To (Lib_Name, Archive_Ext));
624
625             else
626                return Is_Regular_File
627                  (Lib_Dir & Directory_Separator & "lib" &
628                   Fil.Ext_To (Lib_Name, DLL_Ext));
629             end if;
630          end;
631       end if;
632    end Library_Exists_For;
633
634    ---------------------------
635    -- Library_File_Name_For --
636    ---------------------------
637
638    function Library_File_Name_For
639      (Project : Project_Id;
640       In_Tree : Project_Tree_Ref) return Name_Id
641    is
642    begin
643       if not In_Tree.Projects.Table (Project).Library then
644          Prj.Com.Fail ("INTERNAL ERROR: Library_File_Name_For called " &
645                        "for non library project");
646          return No_Name;
647
648       else
649          declare
650             Lib_Name : constant String :=
651               Get_Name_String
652                 (In_Tree.Projects.Table (Project).Library_Name);
653
654          begin
655             Name_Len := 3;
656             Name_Buffer (1 .. Name_Len) := "lib";
657
658             if In_Tree.Projects.Table (Project).Library_Kind =
659               Static
660             then
661                Add_Str_To_Name_Buffer (Fil.Ext_To (Lib_Name, Archive_Ext));
662
663             else
664                Add_Str_To_Name_Buffer (Fil.Ext_To (Lib_Name, DLL_Ext));
665             end if;
666
667             return Name_Find;
668          end;
669       end if;
670    end Library_File_Name_For;
671
672    ----------------
673    -- Object_Ext --
674    ----------------
675
676    function Object_Ext return String is
677    begin
678       return "obj";
679    end Object_Ext;
680
681    ----------------
682    -- PIC_Option --
683    ----------------
684
685    function PIC_Option return String is
686    begin
687       return "";
688    end PIC_Option;
689
690    -----------------------------------------------
691    -- Standalone_Library_Auto_Init_Is_Supported --
692    -----------------------------------------------
693
694    function Standalone_Library_Auto_Init_Is_Supported return Boolean is
695    begin
696       return True;
697    end Standalone_Library_Auto_Init_Is_Supported;
698
699    ---------------------------
700    -- Support_For_Libraries --
701    ---------------------------
702
703    function Support_For_Libraries return Library_Support is
704    begin
705       return Full;
706    end Support_For_Libraries;
707
708 end MLib.Tgt;