OSDN Git Service

2007-08-14 Tristan Gingold <gingold@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 . S P E C I F I C                     --
6 --                         (Integrity VMS Version)                          --
7 --                                                                          --
8 --                                 B o d y                                  --
9 --                                                                          --
10 --            Copyright (C) 2004-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 Integrity 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       begin
182          if Lib_Version = ""
183            or else Symbol_Data.Symbol_Policy /= Autonomous
184          then
185             return "";
186
187          else
188             begin
189                Version := Integer'Value (Lib_Version);
190
191                if Version <= 0 then
192                   raise Constraint_Error;
193                end if;
194
195                return Lib_Version;
196
197             exception
198                when Constraint_Error =>
199                   Fail ("illegal version """, Lib_Version,
200                         """ (on VMS version must be a positive number)");
201                   return "";
202             end;
203          end if;
204       end Version_String;
205
206       ---------------------
207       -- Local Variables --
208       ---------------------
209
210       Opt_File_Name  : constant String := Option_File_Name;
211       Version        : constant String := Version_String;
212       For_Linker_Opt : String_Access;
213
214    --  Start of processing for Build_Dynamic_Library
215
216    begin
217       --  Option file must end with ".opt"
218
219       if Opt_File_Name'Length > 4
220         and then
221           Opt_File_Name (Opt_File_Name'Last - 3 .. Opt_File_Name'Last) = ".opt"
222       then
223          For_Linker_Opt := new String'("--for-linker=" & Opt_File_Name);
224       else
225          Fail ("Options File """, Opt_File_Name, """ must end with .opt");
226       end if;
227
228       VMS_Options (VMS_Options'First) := For_Linker_Opt;
229
230       for J in Inter'Range loop
231          To_Lower (Inter (J).all);
232       end loop;
233
234       --  "gnatsym" is necessary for building the option file
235
236       if Gnatsym_Path = null then
237          Gnatsym_Path := Locate_Exec_On_Path (Gnatsym_Name);
238
239          if Gnatsym_Path = null then
240             Fail (Gnatsym_Name, " not found in path");
241          end if;
242       end if;
243
244       --  For auto-initialization of a stand-alone library, we create
245       --  a macro-assembly file and we invoke the macro-assembler.
246
247       if Auto_Init then
248          declare
249             Macro_File_Name : constant String := Lib_Filename & "__init.asm";
250             Macro_File      : File_Descriptor;
251             Init_Proc       : String := Lib_Filename & "INIT";
252             Popen_Result    : System.Address;
253             Pclose_Result   : Integer;
254             Len             : Natural;
255             OK              : Boolean := True;
256
257             command : constant String :=
258                         Macro_Name & " " & Macro_File_Name & ASCII.NUL;
259             --  The command to invoke the assembler on the generated auto-init
260             --  assembly file.
261             --  Why odd lower case name ???
262
263             mode : constant String := "r" & ASCII.NUL;
264             --  The mode for the invocation of Popen
265             --  Why odd lower case name ???
266
267          begin
268             To_Upper (Init_Proc);
269
270             if Verbose_Mode then
271                Write_Str ("Creating auto-init assembly file """);
272                Write_Str (Macro_File_Name);
273                Write_Line ("""");
274             end if;
275
276             --  Create and write the auto-init assembly file
277
278             declare
279                First_Line  : constant String :=
280                                ASCII.HT
281                                & ".type " & Init_Proc & "#, @function"
282                                & ASCII.LF;
283                Second_Line : constant String :=
284                                ASCII.HT
285                                & ".global " & Init_Proc & "#"
286                                & ASCII.LF;
287                Third_Line  : constant String :=
288                                ASCII.HT
289                                & ".global LIB$INITIALIZE#"
290                                & ASCII.LF;
291                Fourth_Line : constant String :=
292                                ASCII.HT
293                                & ".section LIB$INITIALIZE#,""a"",@progbits"
294                                & ASCII.LF;
295                Fifth_Line  : constant String :=
296                                ASCII.HT
297                                & "data4 @fptr(" & Init_Proc & "#)"
298                                & ASCII.LF;
299
300             begin
301                Macro_File := Create_File (Macro_File_Name, Text);
302                OK := Macro_File /= Invalid_FD;
303
304                if OK then
305                   Len := Write
306                     (Macro_File, First_Line (First_Line'First)'Address,
307                      First_Line'Length);
308                   OK := Len = First_Line'Length;
309                end if;
310
311                if OK then
312                   Len := Write
313                     (Macro_File, Second_Line (Second_Line'First)'Address,
314                      Second_Line'Length);
315                   OK := Len = Second_Line'Length;
316                end if;
317
318                if OK then
319                   Len := Write
320                     (Macro_File, Third_Line (Third_Line'First)'Address,
321                      Third_Line'Length);
322                   OK := Len = Third_Line'Length;
323                end if;
324
325                if OK then
326                   Len := Write
327                     (Macro_File, Fourth_Line (Fourth_Line'First)'Address,
328                      Fourth_Line'Length);
329                   OK := Len = Fourth_Line'Length;
330                end if;
331
332                if OK then
333                   Len := Write
334                     (Macro_File, Fifth_Line (Fifth_Line'First)'Address,
335                      Fifth_Line'Length);
336                   OK := Len = Fifth_Line'Length;
337                end if;
338
339                if OK then
340                   Close (Macro_File, OK);
341                end if;
342
343                if not OK then
344                   Fail ("creation of auto-init assembly file """,
345                         Macro_File_Name, """ failed");
346                end if;
347             end;
348
349             --  Invoke the macro-assembler
350
351             if Verbose_Mode then
352                Write_Str ("Assembling auto-init assembly file """);
353                Write_Str (Macro_File_Name);
354                Write_Line ("""");
355             end if;
356
357             Popen_Result := popen (command (command'First)'Address,
358                                    mode (mode'First)'Address);
359
360             if Popen_Result = Null_Address then
361                Fail ("assembly of auto-init assembly file """,
362                      Macro_File_Name, """ failed");
363             end if;
364
365             --  Wait for the end of execution of the macro-assembler
366
367             Pclose_Result := pclose (Popen_Result);
368
369             if Pclose_Result < 0 then
370                Fail ("assembly of auto init assembly file """,
371                      Macro_File_Name, """ failed");
372             end if;
373
374             --  Add the generated object file to the list of objects to be
375             --  included in the library.
376
377             Additional_Objects :=
378               new Argument_List'
379                 (1 => new String'(Lib_Filename & "__init.obj"));
380          end;
381       end if;
382
383       --  Allocate the argument list and put the symbol file name, the
384       --  reference (if any) and the policy (if not autonomous).
385
386       Arguments := new Argument_List (1 .. Ofiles'Length + 8);
387
388       Last_Argument := 0;
389
390       --  Verbosity
391
392       if Verbose_Mode then
393          Last_Argument := Last_Argument + 1;
394          Arguments (Last_Argument) := new String'("-v");
395       end if;
396
397       --  Version number (major ID)
398
399       if Lib_Version /= "" then
400          Last_Argument := Last_Argument + 1;
401          Arguments (Last_Argument) := new String'("-V");
402          Last_Argument := Last_Argument + 1;
403          Arguments (Last_Argument) := new String'(Version);
404       end if;
405
406       --  Symbol file
407
408       Last_Argument := Last_Argument + 1;
409       Arguments (Last_Argument) := new String'("-s");
410       Last_Argument := Last_Argument + 1;
411       Arguments (Last_Argument) := new String'(Opt_File_Name);
412
413       --  Reference Symbol File
414
415       if Symbol_Data.Reference /= No_Path then
416          Last_Argument := Last_Argument + 1;
417          Arguments (Last_Argument) := new String'("-r");
418          Last_Argument := Last_Argument + 1;
419          Arguments (Last_Argument) :=
420            new String'(Get_Name_String (Symbol_Data.Reference));
421       end if;
422
423       --  Policy
424
425       case Symbol_Data.Symbol_Policy is
426          when Autonomous =>
427             null;
428
429          when Compliant =>
430             Last_Argument := Last_Argument + 1;
431             Arguments (Last_Argument) := new String'("-c");
432
433          when Controlled =>
434             Last_Argument := Last_Argument + 1;
435             Arguments (Last_Argument) := new String'("-C");
436
437          when Restricted =>
438             Last_Argument := Last_Argument + 1;
439             Arguments (Last_Argument) := new String'("-R");
440
441          when Direct =>
442             Last_Argument := Last_Argument + 1;
443             Arguments (Last_Argument) := new String'("-D");
444       end case;
445
446       --  Add each relevant object file
447
448       for Index in Ofiles'Range loop
449          if Is_Interface (Ofiles (Index).all) then
450             Last_Argument := Last_Argument + 1;
451             Arguments (Last_Argument) := new String'(Ofiles (Index).all);
452          end if;
453       end loop;
454
455       --  Spawn gnatsym
456
457       Spawn (Program_Name => Gnatsym_Path.all,
458              Args         => Arguments (1 .. Last_Argument),
459              Success      => Success);
460
461       if not Success then
462          Fail ("unable to create symbol file for library """,
463                Lib_Filename, """");
464       end if;
465
466       Free (Arguments);
467
468       --  Move all the -l switches from Opts to Opts2
469
470       declare
471          Index : Natural := Opts'First;
472          Opt   : String_Access;
473
474       begin
475          while Index <= Last_Opt loop
476             Opt := Opts (Index);
477
478             if Opt'Length > 2 and then
479               Opt (Opt'First .. Opt'First + 1) = "-l"
480             then
481                if Index < Last_Opt then
482                   Opts (Index .. Last_Opt - 1) :=
483                     Opts (Index + 1 .. Last_Opt);
484                end if;
485
486                Last_Opt := Last_Opt - 1;
487
488                Last_Opt2 := Last_Opt2 + 1;
489                Opts2 (Last_Opt2) := Opt;
490
491             else
492                Index := Index + 1;
493             end if;
494          end loop;
495       end;
496
497       --  Invoke gcc to build the library
498
499       Utl.Gcc
500         (Output_File => Lib_File,
501          Objects     => Ofiles & Additional_Objects.all,
502          Options     => VMS_Options,
503          Options_2   => Shared_Libgcc_Switch &
504                         Opts (Opts'First .. Last_Opt) &
505                         Opts2 (Opts2'First .. Last_Opt2),
506          Driver_Name => Driver_Name);
507
508       --  The auto-init object file need to be deleted, so that it will not
509       --  be included in the library as a regular object file, otherwise
510       --  it will be included twice when the library will be built next
511       --  time, which may lead to errors.
512
513       if Auto_Init then
514          declare
515             Auto_Init_Object_File_Name : constant String :=
516                                            Lib_Filename & "__init.obj";
517
518             Disregard : Boolean;
519             pragma Warnings (Off, Disregard);
520
521          begin
522             if Verbose_Mode then
523                Write_Str ("deleting auto-init object file """);
524                Write_Str (Auto_Init_Object_File_Name);
525                Write_Line ("""");
526             end if;
527
528             Delete_File (Auto_Init_Object_File_Name, Success => Disregard);
529          end;
530       end if;
531    end Build_Dynamic_Library;
532
533 --  Package initialization
534
535 begin
536    Build_Dynamic_Library_Ptr    := Build_Dynamic_Library'Access;
537 end MLib.Tgt.Specific;