OSDN Git Service

2007-08-14 Robert Dewar <dewar@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 . S P E C I F I C                     --
6 --                           (Alpha VMS Version)                            --
7 --                                                                          --
8 --                                 B o d y                                  --
9 --                                                                          --
10 --          Copyright (C) 2003-2007, 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 Alpha VMS version of the body
29
30 with Ada.Characters.Handling; use Ada.Characters.Handling;
31
32 with MLib.Fil;
33 with MLib.Utl;
34
35 with MLib.Tgt.VMS;
36 pragma Warnings (Off, MLib.Tgt.VMS);
37 --  MLib.Tgt.VMS is with'ed only for elaboration purposes
38
39 with Opt;      use Opt;
40 with Output;   use Output;
41
42 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
43
44 with System;           use System;
45 with System.Case_Util; use System.Case_Util;
46 with System.CRTL;      use System.CRTL;
47
48 package body MLib.Tgt.Specific is
49
50    --  Non default subprogram. See comment in mlib-tgt.ads.
51
52    procedure Build_Dynamic_Library
53      (Ofiles       : Argument_List;
54       Options      : Argument_List;
55       Interfaces   : Argument_List;
56       Lib_Filename : String;
57       Lib_Dir      : String;
58       Symbol_Data  : Symbol_Record;
59       Driver_Name  : Name_Id := No_Name;
60       Lib_Version  : String  := "";
61       Auto_Init    : Boolean := False);
62
63    --  Local variables
64
65    Empty_Argument_List : aliased Argument_List := (1 .. 0 => null);
66    Additional_Objects  : Argument_List_Access := Empty_Argument_List'Access;
67    --  Used to add the generated auto-init object files for auto-initializing
68    --  stand-alone libraries.
69
70    Macro_Name : constant String := "mcr gnu:[bin]gcc -c -x assembler";
71    --  The name of the command to invoke the macro-assembler
72
73    VMS_Options : Argument_List := (1 .. 1 => null);
74
75    Gnatsym_Name : constant String := "gnatsym";
76
77    Gnatsym_Path : String_Access;
78
79    Arguments : Argument_List_Access := null;
80    Last_Argument : Natural := 0;
81
82    Success : Boolean := False;
83
84    Shared_Libgcc : aliased String := "-shared-libgcc";
85
86    Shared_Libgcc_Switch : constant Argument_List :=
87                             (1 => Shared_Libgcc'Access);
88
89    ---------------------------
90    -- Build_Dynamic_Library --
91    ---------------------------
92
93    procedure Build_Dynamic_Library
94      (Ofiles       : Argument_List;
95       Options      : Argument_List;
96       Interfaces   : Argument_List;
97       Lib_Filename : String;
98       Lib_Dir      : String;
99       Symbol_Data  : Symbol_Record;
100       Driver_Name  : Name_Id := No_Name;
101       Lib_Version  : String  := "";
102       Auto_Init    : Boolean := False)
103    is
104
105       Lib_File : constant String :=
106                    Lib_Dir & Directory_Separator & "lib" &
107                    Fil.Ext_To (Lib_Filename, DLL_Ext);
108
109       Opts      : Argument_List := Options;
110       Last_Opt  : Natural       := Opts'Last;
111       Opts2     : Argument_List (Options'Range);
112       Last_Opt2 : Natural       := Opts2'First - 1;
113
114       Inter : constant Argument_List := Interfaces;
115
116       function Is_Interface (Obj_File : String) return Boolean;
117       --  For a Stand-Alone Library, returns True if Obj_File is the object
118       --  file name of an interface of the SAL. For other libraries, always
119       --  return True.
120
121       function Option_File_Name return String;
122       --  Returns Symbol_File, if not empty. Otherwise, returns "symvec.opt"
123
124       function Version_String return String;
125       --  Returns Lib_Version if not empty and if Symbol_Data.Symbol_Policy is
126       --  not Autonomous, otherwise returns "". When Symbol_Data.Symbol_Policy
127       --  is Autonomous, fails gnatmake if Lib_Version is not the image of a
128       --  positive number.
129
130       ------------------
131       -- Is_Interface --
132       ------------------
133
134       function Is_Interface (Obj_File : String) return Boolean is
135          ALI : constant String :=
136                  Fil.Ext_To
137                   (Filename => To_Lower (Base_Name (Obj_File)),
138                    New_Ext  => "ali");
139
140       begin
141          if Inter'Length = 0 then
142             return True;
143
144          elsif ALI'Length > 2 and then
145                ALI (ALI'First .. ALI'First + 2) = "b__"
146          then
147             return True;
148
149          else
150             for J in Inter'Range loop
151                if Inter (J).all = ALI then
152                   return True;
153                end if;
154             end loop;
155
156             return False;
157          end if;
158       end Is_Interface;
159
160       ----------------------
161       -- Option_File_Name --
162       ----------------------
163
164       function Option_File_Name return String is
165       begin
166          if Symbol_Data.Symbol_File = No_Path then
167             return "symvec.opt";
168          else
169             Get_Name_String (Symbol_Data.Symbol_File);
170             To_Lower (Name_Buffer (1 .. Name_Len));
171             return Name_Buffer (1 .. Name_Len);
172          end if;
173       end Option_File_Name;
174
175       --------------------
176       -- Version_String --
177       --------------------
178
179       function Version_String return String is
180          Version : Integer := 0;
181
182       begin
183          if Lib_Version = ""
184            or else Symbol_Data.Symbol_Policy /= Autonomous
185          then
186             return "";
187
188          else
189             begin
190                Version := Integer'Value (Lib_Version);
191
192                if Version <= 0 then
193                   raise Constraint_Error;
194                end if;
195
196                return Lib_Version;
197
198             exception
199                when Constraint_Error =>
200                   Fail ("illegal version """, Lib_Version,
201                         """ (on VMS version must be a positive number)");
202                   return "";
203             end;
204          end if;
205       end Version_String;
206
207       ---------------------
208       -- Local Variables --
209       ---------------------
210
211       Opt_File_Name  : constant String := Option_File_Name;
212       Version        : constant String := Version_String;
213       For_Linker_Opt : String_Access;
214
215    --  Start of processing for Build_Dynamic_Library
216
217    begin
218       --  If option file name does not ends with ".opt", append "/OPTIONS"
219       --  to its specification for the VMS linker.
220
221       if Opt_File_Name'Length > 4
222         and then
223           Opt_File_Name (Opt_File_Name'Last - 3 .. Opt_File_Name'Last) = ".opt"
224       then
225          For_Linker_Opt := new String'("--for-linker=" & Opt_File_Name);
226       else
227          For_Linker_Opt :=
228            new String'("--for-linker=" & Opt_File_Name & "/OPTIONS");
229       end if;
230
231       VMS_Options (VMS_Options'First) := For_Linker_Opt;
232
233       for J in Inter'Range loop
234          To_Lower (Inter (J).all);
235       end loop;
236
237       --  "gnatsym" is necessary for building the option file
238
239       if Gnatsym_Path = null then
240          Gnatsym_Path := Locate_Exec_On_Path (Gnatsym_Name);
241
242          if Gnatsym_Path = null then
243             Fail (Gnatsym_Name, " not found in path");
244          end if;
245       end if;
246
247       --  For auto-initialization of a stand-alone library, we create
248       --  a macro-assembly file and we invoke the macro-assembler.
249
250       if Auto_Init then
251          declare
252             Macro_File_Name : constant String := Lib_Filename & "__init.asm";
253             Macro_File      : File_Descriptor;
254             Init_Proc       : String := Lib_Filename & "INIT";
255             Popen_Result    : System.Address;
256             Pclose_Result   : Integer;
257             Len             : Natural;
258             OK              : Boolean := True;
259
260             command  : constant String :=
261                          Macro_Name & " " & Macro_File_Name & ASCII.NUL;
262             --  The command to invoke the assembler on the generated auto-init
263             --  assembly file.
264
265             mode : constant String := "r" & ASCII.NUL;
266             --  The mode for the invocation of Popen
267
268          begin
269             To_Upper (Init_Proc);
270
271             if Verbose_Mode then
272                Write_Str ("Creating auto-init assembly file """);
273                Write_Str (Macro_File_Name);
274                Write_Line ("""");
275             end if;
276
277             --  Create and write the auto-init assembly file
278
279             declare
280                First_Line : constant String :=
281                               ASCII.HT & ".section LIB$INITIALIZE,GBL,NOWRT" &
282                ASCII.LF;
283                Second_Line : constant String :=
284                                ASCII.HT & ".long " & Init_Proc & ASCII.LF;
285                --  First and second lines of the auto-init assembly file
286
287             begin
288                Macro_File := Create_File (Macro_File_Name, Text);
289                OK := Macro_File /= Invalid_FD;
290
291                if OK then
292                   Len := Write
293                     (Macro_File, First_Line (First_Line'First)'Address,
294                      First_Line'Length);
295                   OK := Len = First_Line'Length;
296                end if;
297
298                if OK then
299                   Len := Write
300                     (Macro_File, Second_Line (Second_Line'First)'Address,
301                      Second_Line'Length);
302                   OK := Len = Second_Line'Length;
303                end if;
304
305                if OK then
306                   Close (Macro_File, OK);
307                end if;
308
309                if not OK then
310                   Fail ("creation of auto-init assembly file """,
311                         Macro_File_Name, """ failed");
312                end if;
313             end;
314
315             --  Invoke the macro-assembler
316
317             if Verbose_Mode then
318                Write_Str ("Assembling auto-init assembly file """);
319                Write_Str (Macro_File_Name);
320                Write_Line ("""");
321             end if;
322
323             Popen_Result := popen (command (command'First)'Address,
324                                    mode (mode'First)'Address);
325
326             if Popen_Result = Null_Address then
327                Fail ("assembly of auto-init assembly file """,
328                      Macro_File_Name, """ failed");
329             end if;
330
331             --  Wait for the end of execution of the macro-assembler
332
333             Pclose_Result := pclose (Popen_Result);
334
335             if Pclose_Result < 0 then
336                Fail ("assembly of auto init assembly file """,
337                      Macro_File_Name, """ failed");
338             end if;
339
340             --  Add the generated object file to the list of objects to be
341             --  included in the library.
342
343             Additional_Objects :=
344               new Argument_List'
345                 (1 => new String'(Lib_Filename & "__init.obj"));
346          end;
347       end if;
348
349       --  Allocate the argument list and put the symbol file name, the
350       --  reference (if any) and the policy (if not autonomous).
351
352       Arguments := new Argument_List (1 .. Ofiles'Length + 8);
353
354       Last_Argument := 0;
355
356       --  Verbosity
357
358       if Verbose_Mode then
359          Last_Argument := Last_Argument + 1;
360          Arguments (Last_Argument) := new String'("-v");
361       end if;
362
363       --  Version number (major ID)
364
365       if Lib_Version /= "" then
366          Last_Argument := Last_Argument + 1;
367          Arguments (Last_Argument) := new String'("-V");
368          Last_Argument := Last_Argument + 1;
369          Arguments (Last_Argument) := new String'(Version);
370       end if;
371
372       --  Symbol file
373
374       Last_Argument := Last_Argument + 1;
375       Arguments (Last_Argument) := new String'("-s");
376       Last_Argument := Last_Argument + 1;
377       Arguments (Last_Argument) := new String'(Opt_File_Name);
378
379       --  Reference Symbol File
380
381       if Symbol_Data.Reference /= No_Path then
382          Last_Argument := Last_Argument + 1;
383          Arguments (Last_Argument) := new String'("-r");
384          Last_Argument := Last_Argument + 1;
385          Arguments (Last_Argument) :=
386            new String'(Get_Name_String (Symbol_Data.Reference));
387       end if;
388
389       --  Policy
390
391       case Symbol_Data.Symbol_Policy is
392          when Autonomous =>
393             null;
394
395          when Compliant =>
396             Last_Argument := Last_Argument + 1;
397             Arguments (Last_Argument) := new String'("-c");
398
399          when Controlled =>
400             Last_Argument := Last_Argument + 1;
401             Arguments (Last_Argument) := new String'("-C");
402
403          when Restricted =>
404             Last_Argument := Last_Argument + 1;
405             Arguments (Last_Argument) := new String'("-R");
406
407          when Direct =>
408             Last_Argument := Last_Argument + 1;
409             Arguments (Last_Argument) := new String'("-D");
410
411       end case;
412
413       --  Add each relevant object file
414
415       for Index in Ofiles'Range loop
416          if Is_Interface (Ofiles (Index).all) then
417             Last_Argument := Last_Argument + 1;
418             Arguments (Last_Argument) := new String'(Ofiles (Index).all);
419          end if;
420       end loop;
421
422       --  Spawn gnatsym
423
424       Spawn (Program_Name => Gnatsym_Path.all,
425              Args         => Arguments (1 .. Last_Argument),
426              Success      => Success);
427
428       if not Success then
429          Fail ("unable to create symbol file for library """,
430                Lib_Filename, """");
431       end if;
432
433       Free (Arguments);
434
435       --  Move all the -l switches from Opts to Opts2
436
437       declare
438          Index : Natural := Opts'First;
439          Opt   : String_Access;
440
441       begin
442          while Index <= Last_Opt loop
443             Opt := Opts (Index);
444
445             if Opt'Length > 2 and then
446               Opt (Opt'First .. Opt'First + 1) = "-l"
447             then
448                if Index < Last_Opt then
449                   Opts (Index .. Last_Opt - 1) :=
450                     Opts (Index + 1 .. Last_Opt);
451                end if;
452
453                Last_Opt := Last_Opt - 1;
454
455                Last_Opt2 := Last_Opt2 + 1;
456                Opts2 (Last_Opt2) := Opt;
457
458             else
459                Index := Index + 1;
460             end if;
461          end loop;
462       end;
463
464       --  Invoke gcc to build the library
465
466       Utl.Gcc
467         (Output_File => Lib_File,
468          Objects     => Ofiles & Additional_Objects.all,
469          Options     => VMS_Options,
470          Options_2   => Shared_Libgcc_Switch &
471                         Opts (Opts'First .. Last_Opt) &
472                         Opts2 (Opts2'First .. Last_Opt2),
473          Driver_Name => Driver_Name);
474
475       --  The auto-init object file need to be deleted, so that it will not
476       --  be included in the library as a regular object file, otherwise
477       --  it will be included twice when the library will be built next
478       --  time, which may lead to errors.
479
480       if Auto_Init then
481          declare
482             Auto_Init_Object_File_Name : constant String :=
483                                            Lib_Filename & "__init.obj";
484             Disregard : Boolean;
485
486          begin
487             if Verbose_Mode then
488                Write_Str ("deleting auto-init object file """);
489                Write_Str (Auto_Init_Object_File_Name);
490                Write_Line ("""");
491             end if;
492
493             Delete_File (Auto_Init_Object_File_Name, Success => Disregard);
494          end;
495       end if;
496    end Build_Dynamic_Library;
497
498 --  Package initialization
499
500 begin
501    Build_Dynamic_Library_Ptr    := Build_Dynamic_Library'Access;
502 end MLib.Tgt.Specific;