OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [mlib-prj.adb] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                            M L I B . P R J                               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--                     Copyright (C) 2001-2005, AdaCore                     --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20
-- Boston, MA 02110-1301, USA.                                              --
21
--                                                                          --
22
-- GNAT was originally developed  by the GNAT team at  New York University. --
23
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
24
--                                                                          --
25
------------------------------------------------------------------------------
26
 
27
with ALI;      use ALI;
28
with Gnatvsn;  use Gnatvsn;
29
with Hostparm;
30
with MLib.Fil; use MLib.Fil;
31
with MLib.Tgt; use MLib.Tgt;
32
with MLib.Utl; use MLib.Utl;
33
with Namet;    use Namet;
34
with Opt;
35
with Output;   use Output;
36
with Prj.Com;  use Prj.Com;
37
with Prj.Env;  use Prj.Env;
38
with Prj.Util; use Prj.Util;
39
with Sinput.P;
40
with Snames;   use Snames;
41
with Switch;   use Switch;
42
with Table;
43
 
44
with Ada.Characters.Handling;
45
 
46
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
47
with GNAT.HTable;
48
with Interfaces.C_Streams;      use Interfaces.C_Streams;
49
with System;                    use System;
50
with System.Case_Util;          use System.Case_Util;
51
 
52
package body MLib.Prj is
53
 
54
   Prj_Add_Obj_Files : Types.Int;
55
   pragma Import (C, Prj_Add_Obj_Files, "__gnat_prj_add_obj_files");
56
   Add_Object_Files : constant Boolean := Prj_Add_Obj_Files /= 0;
57
   --  Indicates if object files in pragmas Linker_Options (found in the
58
   --  binder generated file) should be taken when linking aq stand-alone
59
   --  library.
60
   --  False for Windows, True for other platforms.
61
 
62
   ALI_Suffix : constant String := ".ali";
63
   B_Start    : String := "b~";
64
 
65
   S_Osinte_Ads : Name_Id := No_Name;
66
   --  Name_Id for "s-osinte.ads"
67
 
68
   S_Dec_Ads : Name_Id := No_Name;
69
   --  Name_Id for "dec.ads"
70
 
71
   G_Trasym_Ads : Name_Id := No_Name;
72
   --  Name_Id for "g-trasym.ads"
73
 
74
   No_Argument_List : aliased String_List := (1 .. 0 => null);
75
   No_Argument      : constant String_List_Access := No_Argument_List'Access;
76
 
77
   Arguments : String_List_Access := No_Argument;
78
   --  Used to accumulate arguments for the invocation of gnatbind and of
79
   --  the compiler. Also used to collect the interface ALI when copying
80
   --  the ALI files to the library directory.
81
 
82
   Argument_Number : Natural := 0;
83
   --  Index of the last argument in Arguments
84
 
85
   Initial_Argument_Max : constant := 10;
86
 
87
   No_Main_String : aliased String := "-n";
88
   No_Main : constant String_Access := No_Main_String'Access;
89
 
90
   Output_Switch_String : aliased String := "-o";
91
   Output_Switch : constant String_Access := Output_Switch_String'Access;
92
 
93
   Compile_Switch_String : aliased String := "-c";
94
   Compile_Switch : constant String_Access := Compile_Switch_String'Access;
95
 
96
   Auto_Initialize : constant String := "-a";
97
 
98
   --  List of objects to put inside the library
99
 
100
   Object_Files : Argument_List_Access;
101
 
102
   package Objects is new Table.Table
103
     (Table_Name           => "Mlib.Prj.Objects",
104
      Table_Component_Type => String_Access,
105
      Table_Index_Type     => Natural,
106
      Table_Low_Bound      => 1,
107
      Table_Initial        => 50,
108
      Table_Increment      => 100);
109
 
110
   package Objects_Htable is new GNAT.HTable.Simple_HTable
111
     (Header_Num => Header_Num,
112
      Element    => Boolean,
113
      No_Element => False,
114
      Key        => Name_Id,
115
      Hash       => Hash,
116
      Equal      => "=");
117
 
118
   --  List of non-Ada object files
119
 
120
   Foreign_Objects : Argument_List_Access;
121
 
122
   package Foreigns is new Table.Table
123
     (Table_Name           => "Mlib.Prj.Foreigns",
124
      Table_Component_Type => String_Access,
125
      Table_Index_Type     => Natural,
126
      Table_Low_Bound      => 1,
127
      Table_Initial        => 20,
128
      Table_Increment      => 100);
129
 
130
   --  List of ALI files
131
 
132
   Ali_Files : Argument_List_Access;
133
 
134
   package ALIs is new Table.Table
135
     (Table_Name           => "Mlib.Prj.Alis",
136
      Table_Component_Type => String_Access,
137
      Table_Index_Type     => Natural,
138
      Table_Low_Bound      => 1,
139
      Table_Initial        => 50,
140
      Table_Increment      => 100);
141
 
142
   --  List of options set in the command line
143
 
144
   Options : Argument_List_Access;
145
 
146
   package Opts is new Table.Table
147
     (Table_Name           => "Mlib.Prj.Opts",
148
      Table_Component_Type => String_Access,
149
      Table_Index_Type     => Natural,
150
      Table_Low_Bound      => 1,
151
      Table_Initial        => 5,
152
      Table_Increment      => 100);
153
 
154
   --  All the ALI file in the library
155
 
156
   package Library_ALIs is new GNAT.HTable.Simple_HTable
157
     (Header_Num => Header_Num,
158
      Element    => Boolean,
159
      No_Element => False,
160
      Key        => Name_Id,
161
      Hash       => Hash,
162
      Equal      => "=");
163
 
164
   --  The ALI files in the interface sets
165
 
166
   package Interface_ALIs is new GNAT.HTable.Simple_HTable
167
     (Header_Num => Header_Num,
168
      Element    => Boolean,
169
      No_Element => False,
170
      Key        => Name_Id,
171
      Hash       => Hash,
172
      Equal      => "=");
173
 
174
   --  The ALI files that have been processed to check if the corresponding
175
   --  library unit is in the interface set.
176
 
177
   package Processed_ALIs is new GNAT.HTable.Simple_HTable
178
     (Header_Num => Header_Num,
179
      Element    => Boolean,
180
      No_Element => False,
181
      Key        => Name_Id,
182
      Hash       => Hash,
183
      Equal      => "=");
184
 
185
   --  The projects imported directly or indirectly
186
 
187
   package Processed_Projects is new GNAT.HTable.Simple_HTable
188
     (Header_Num => Header_Num,
189
      Element    => Boolean,
190
      No_Element => False,
191
      Key        => Name_Id,
192
      Hash       => Hash,
193
      Equal      => "=");
194
 
195
   --  The library projects imported directly or indirectly
196
 
197
   package Library_Projs is new Table.Table (
198
     Table_Component_Type => Project_Id,
199
     Table_Index_Type     => Integer,
200
     Table_Low_Bound      => 1,
201
     Table_Initial        => 10,
202
     Table_Increment      => 10,
203
     Table_Name           => "Make.Library_Projs");
204
 
205
   type Build_Mode_State is (None, Static, Dynamic, Relocatable);
206
 
207
   procedure Add_Argument (S : String);
208
   --  Add one argument to Arguments array, if array is full, double its size
209
 
210
   function ALI_File_Name (Source : String) return String;
211
   --  Return the ALI file name corresponding to a source
212
 
213
   procedure Check (Filename : String);
214
   --  Check if filename is a regular file. Fail if it is not
215
 
216
   procedure Check_Context;
217
   --  Check each object files in table Object_Files
218
   --  Fail if any of them is not a regular file
219
 
220
   procedure Copy_Interface_Sources
221
     (For_Project : Project_Id;
222
      In_Tree     : Project_Tree_Ref;
223
      Interfaces  : Argument_List;
224
      To_Dir      : Name_Id);
225
   --  Copy the interface sources of a SAL to directory To_Dir
226
 
227
   procedure Display (Executable : String);
228
   --  Display invocation of gnatbind and of the compiler with the arguments
229
   --  in Arguments, except when Quiet_Output is True.
230
 
231
   procedure Process_Binder_File (Name : String);
232
   --  For Stand-Alone libraries, get the Linker Options in the binder
233
   --  generated file.
234
 
235
   procedure Reset_Tables;
236
   --  Make sure that all the above tables are empty
237
   --  (Objects, Foreign_Objects, Ali_Files, Options).
238
 
239
   function SALs_Use_Constructors return Boolean;
240
   --  Indicate if Stand-Alone Libraries are automatically initialized using
241
   --  the constructor mechanism.
242
 
243
   function Ultimate_Extension_Of
244
     (Project : Project_Id;
245
      In_Tree : Project_Tree_Ref) return Project_Id;
246
   --  Returns the Project_Id of project Project. Returns No_Project
247
   --  if Project is No_Project.
248
 
249
   ------------------
250
   -- Add_Argument --
251
   ------------------
252
 
253
   procedure Add_Argument (S : String) is
254
   begin
255
      if Argument_Number = Arguments'Last then
256
         declare
257
            New_Args : constant String_List_Access :=
258
              new String_List (1 .. 2 * Arguments'Last);
259
 
260
         begin
261
            --  Copy the String_Accesses and set them to null in Arguments
262
            --  so that they will not be deallocated by the call to
263
            --  Free (Arguments).
264
 
265
            New_Args (Arguments'Range) := Arguments.all;
266
            Arguments.all := (others => null);
267
            Free (Arguments);
268
            Arguments := New_Args;
269
         end;
270
      end if;
271
 
272
      Argument_Number := Argument_Number + 1;
273
      Arguments (Argument_Number) := new String'(S);
274
   end Add_Argument;
275
 
276
   -------------------
277
   -- ALI_File_Name --
278
   -------------------
279
 
280
   function ALI_File_Name (Source : String) return String is
281
   begin
282
      --  If the source name has an extension, then replace it with
283
      --  the ALI suffix.
284
 
285
      for Index in reverse Source'First + 1 .. Source'Last loop
286
         if Source (Index) = '.' then
287
            return Source (Source'First .. Index - 1) & ALI_Suffix;
288
         end if;
289
      end loop;
290
 
291
      --  If there is no dot, or if it is the first character, just add the
292
      --  ALI suffix.
293
 
294
      return Source & ALI_Suffix;
295
   end ALI_File_Name;
296
 
297
   -------------------
298
   -- Build_Library --
299
   -------------------
300
 
301
   procedure Build_Library
302
     (For_Project   : Project_Id;
303
      In_Tree       : Project_Tree_Ref;
304
      Gnatbind      : String;
305
      Gnatbind_Path : String_Access;
306
      Gcc           : String;
307
      Gcc_Path      : String_Access;
308
      Bind          : Boolean := True;
309
      Link          : Boolean := True)
310
   is
311
      Warning_For_Library : Boolean := False;
312
      --  Set to True for the first warning about a unit missing from the
313
      --  interface set.
314
 
315
      Libgnarl_Needed   : Boolean := False;
316
      --  Set to True if library needs to be linked with libgnarl
317
 
318
      Libdecgnat_Needed : Boolean := False;
319
      --  On OpenVMS, set to True if library needs to be linked with libdecgnat
320
 
321
      Gtrasymobj_Needed : Boolean := False;
322
      --  On OpenVMS, set to True if library needs to be linked with
323
      --  g-trasym.obj.
324
 
325
      Data : Project_Data := In_Tree.Projects.Table (For_Project);
326
 
327
      Object_Directory_Path : constant String :=
328
                          Get_Name_String (Data.Object_Directory);
329
 
330
      Standalone   : constant Boolean := Data.Standalone_Library;
331
 
332
      Project_Name : constant String := Get_Name_String (Data.Name);
333
 
334
      Current_Dir  : constant String := Get_Current_Dir;
335
 
336
      Lib_Filename : String_Access;
337
      Lib_Dirpath  : String_Access;
338
      Lib_Version  : String_Access := new String'("");
339
 
340
      The_Build_Mode : Build_Mode_State := None;
341
 
342
      Success : Boolean := False;
343
 
344
      Library_Options : Variable_Value := Nil_Variable_Value;
345
 
346
      Library_GCC     : Variable_Value := Nil_Variable_Value;
347
 
348
      Driver_Name : Name_Id := No_Name;
349
 
350
      In_Main_Object_Directory : Boolean := True;
351
 
352
      Rpath : String_Access := null;
353
      --  Allocated only if Path Option is supported
354
 
355
      Rpath_Last : Natural := 0;
356
      --  Index of last valid character of Rpath
357
 
358
      Initial_Rpath_Length : constant := 200;
359
      --  Initial size of Rpath, when first allocated
360
 
361
      Path_Option : String_Access := Linker_Library_Path_Option;
362
      --  If null, Path Option is not supported.
363
      --  Not a constant so that it can be deallocated.
364
 
365
      First_ALI : Name_Id := No_Name;
366
      --  Store the ALI file name of a source of the library (the first found)
367
 
368
      procedure Add_ALI_For (Source : Name_Id);
369
      --  Add the name of the ALI file corresponding to Source to the
370
      --  Arguments.
371
 
372
      procedure Add_Rpath (Path : String);
373
      --  Add a path name to Rpath
374
 
375
      function Check_Project (P : Project_Id) return Boolean;
376
      --  Returns True if P is For_Project or a project extended by For_Project
377
 
378
      procedure Check_Libs (ALI_File : String);
379
      --  Set Libgnarl_Needed if the ALI_File indicates that there is a need
380
      --  to link with -lgnarl (this is the case when there is a dependency
381
      --  on s-osinte.ads). On OpenVMS, set Libdecgnat_Needed if the ALI file
382
      --  indicates that there is a need to link with -ldecgnat (this is the
383
      --  case when there is a dependency on dec.ads), and set
384
      --  Gtrasymobj_Needed if there is a dependency on g-trasym.ads.
385
 
386
      procedure Process (The_ALI : File_Name_Type);
387
      --  Check if the closure of a library unit which is or should be in the
388
      --  interface set is also in the interface set. Issue a warning for each
389
      --  missing library unit.
390
 
391
      procedure Process_Imported_Libraries;
392
      --  Add the -L and -l switches for the imported Library Project Files,
393
      --  and, if Path Option is supported, the library directory path names
394
      --  to Rpath.
395
 
396
      -----------------
397
      -- Add_ALI_For --
398
      -----------------
399
 
400
      procedure Add_ALI_For (Source : Name_Id) is
401
         ALI    : constant String := ALI_File_Name (Get_Name_String (Source));
402
         ALI_Id : Name_Id;
403
 
404
      begin
405
         if Bind then
406
            Add_Argument (ALI);
407
         end if;
408
 
409
         Name_Len := 0;
410
         Add_Str_To_Name_Buffer (S => ALI);
411
         ALI_Id := Name_Find;
412
 
413
         --  Add the ALI file name to the library ALIs
414
 
415
         if Bind then
416
            Library_ALIs.Set (ALI_Id, True);
417
         end if;
418
 
419
         --  Set First_ALI, if not already done
420
 
421
         if First_ALI = No_Name then
422
            First_ALI := ALI_Id;
423
         end if;
424
      end Add_ALI_For;
425
 
426
      ---------------
427
      -- Add_Rpath --
428
      ---------------
429
 
430
      procedure Add_Rpath (Path : String) is
431
 
432
         procedure Double;
433
         --  Double Rpath size
434
 
435
         ------------
436
         -- Double --
437
         ------------
438
 
439
         procedure Double is
440
            New_Rpath : constant String_Access :=
441
                          new String (1 .. 2 * Rpath'Length);
442
         begin
443
            New_Rpath (1 .. Rpath_Last) := Rpath (1 .. Rpath_Last);
444
            Free (Rpath);
445
            Rpath := New_Rpath;
446
         end Double;
447
 
448
      --  Start of processing for Add_Rpath
449
 
450
      begin
451
         --  If firt path, allocate initial Rpath
452
 
453
         if Rpath = null then
454
            Rpath := new String (1 .. Initial_Rpath_Length);
455
            Rpath_Last := 0;
456
 
457
         else
458
            --  Otherwise, add a path separator between two path names
459
 
460
            if Rpath_Last = Rpath'Last then
461
               Double;
462
            end if;
463
 
464
            Rpath_Last := Rpath_Last + 1;
465
            Rpath (Rpath_Last) := Path_Separator;
466
         end if;
467
 
468
         --  Increase Rpath size until it is large enough
469
 
470
         while Rpath_Last + Path'Length > Rpath'Last loop
471
            Double;
472
         end loop;
473
 
474
         --  Add the path name
475
 
476
         Rpath (Rpath_Last + 1 .. Rpath_Last + Path'Length) := Path;
477
         Rpath_Last := Rpath_Last + Path'Length;
478
      end Add_Rpath;
479
 
480
      -------------------
481
      -- Check_Project --
482
      -------------------
483
 
484
      function Check_Project (P : Project_Id) return Boolean is
485
      begin
486
         if P = For_Project then
487
            return True;
488
 
489
         elsif P /= No_Project then
490
            declare
491
               Data : Project_Data :=
492
                        In_Tree.Projects.Table (For_Project);
493
            begin
494
               while Data.Extends /= No_Project loop
495
                  if P = Data.Extends then
496
                     return True;
497
                  end if;
498
 
499
                  Data := In_Tree.Projects.Table (Data.Extends);
500
               end loop;
501
            end;
502
         end if;
503
 
504
         return False;
505
      end Check_Project;
506
 
507
      ----------------
508
      -- Check_Libs --
509
      ----------------
510
 
511
      procedure Check_Libs (ALI_File : String) is
512
         Lib_File : Name_Id;
513
         Text     : Text_Buffer_Ptr;
514
         Id       : ALI.ALI_Id;
515
 
516
      begin
517
         if not Libgnarl_Needed or
518
           (Hostparm.OpenVMS and then
519
              ((not Libdecgnat_Needed) or
520
               (not Gtrasymobj_Needed)))
521
         then
522
            --  Scan the ALI file
523
 
524
            Name_Len := ALI_File'Length;
525
            Name_Buffer (1 .. Name_Len) := ALI_File;
526
            Lib_File := Name_Find;
527
            Text := Read_Library_Info (Lib_File, True);
528
 
529
            Id  := ALI.Scan_ALI
530
                         (F          => Lib_File,
531
                          T          => Text,
532
                          Ignore_ED  => False,
533
                          Err        => True,
534
                          Read_Lines => "D");
535
            Free (Text);
536
 
537
            --  Look for s-osinte.ads in the dependencies
538
 
539
            for Index in ALI.ALIs.Table (Id).First_Sdep ..
540
                         ALI.ALIs.Table (Id).Last_Sdep
541
            loop
542
               if ALI.Sdep.Table (Index).Sfile = S_Osinte_Ads then
543
                  Libgnarl_Needed := True;
544
 
545
               elsif Hostparm.OpenVMS then
546
                  if ALI.Sdep.Table (Index).Sfile = S_Dec_Ads then
547
                     Libdecgnat_Needed := True;
548
 
549
                  elsif ALI.Sdep.Table (Index).Sfile = G_Trasym_Ads then
550
                     Gtrasymobj_Needed := True;
551
                  end if;
552
               end if;
553
            end loop;
554
         end if;
555
      end Check_Libs;
556
 
557
      -------------
558
      -- Process --
559
      -------------
560
 
561
      procedure Process (The_ALI : File_Name_Type) is
562
         Text       : Text_Buffer_Ptr;
563
         Idread     : ALI_Id;
564
         First_Unit : ALI.Unit_Id;
565
         Last_Unit  : ALI.Unit_Id;
566
         Unit_Data  : Unit_Record;
567
         Afile      : File_Name_Type;
568
 
569
      begin
570
         --  Nothing to do if the ALI file has already been processed.
571
         --  This happens if an interface imports another interface.
572
 
573
         if not Processed_ALIs.Get (The_ALI) then
574
            Processed_ALIs.Set (The_ALI, True);
575
            Text := Read_Library_Info (The_ALI);
576
 
577
            if Text /= null then
578
               Idread :=
579
                 Scan_ALI
580
                   (F         => The_ALI,
581
                    T         => Text,
582
                    Ignore_ED => False,
583
                    Err       => True);
584
               Free (Text);
585
 
586
               if Idread /= No_ALI_Id then
587
                  First_Unit := ALI.ALIs.Table (Idread).First_Unit;
588
                  Last_Unit  := ALI.ALIs.Table (Idread).Last_Unit;
589
 
590
                  --  Process both unit (spec and body) if the body is needed
591
                  --  by the spec (inline or generic). Otherwise, just process
592
                  --  the spec.
593
 
594
                  if First_Unit /= Last_Unit and then
595
                    not ALI.Units.Table (Last_Unit).Body_Needed_For_SAL
596
                  then
597
                     First_Unit := Last_Unit;
598
                  end if;
599
 
600
                  for Unit in First_Unit .. Last_Unit loop
601
                     Unit_Data := ALI.Units.Table (Unit);
602
 
603
                     --  Check if each withed unit which is in the library is
604
                     --  also in the interface set, if it has not yet been
605
                     --  processed.
606
 
607
                     for W in Unit_Data.First_With .. Unit_Data.Last_With loop
608
                        Afile := Withs.Table (W).Afile;
609
 
610
                        if Afile /= No_Name and then Library_ALIs.Get (Afile)
611
                          and then not Processed_ALIs.Get (Afile)
612
                        then
613
                           if not Interface_ALIs.Get (Afile) then
614
                              if not Warning_For_Library then
615
                                 Write_Str ("Warning: In library project """);
616
                                 Get_Name_String (Data.Name);
617
                                 To_Mixed (Name_Buffer (1 .. Name_Len));
618
                                 Write_Str (Name_Buffer (1 .. Name_Len));
619
                                 Write_Line ("""");
620
                                 Warning_For_Library := True;
621
                              end if;
622
 
623
                              Write_Str ("         Unit """);
624
                              Get_Name_String (Withs.Table (W).Uname);
625
                              To_Mixed (Name_Buffer (1 .. Name_Len - 2));
626
                              Write_Str (Name_Buffer (1 .. Name_Len - 2));
627
                              Write_Line (""" is not in the interface set");
628
                              Write_Str ("         but it is needed by ");
629
 
630
                              case Unit_Data.Utype is
631
                                 when Is_Spec =>
632
                                    Write_Str ("the spec of ");
633
 
634
                                 when Is_Body =>
635
                                    Write_Str ("the body of ");
636
 
637
                                 when others =>
638
                                    null;
639
                              end case;
640
 
641
                              Write_Str ("""");
642
                              Get_Name_String (Unit_Data.Uname);
643
                              To_Mixed (Name_Buffer (1 .. Name_Len - 2));
644
                              Write_Str (Name_Buffer (1 .. Name_Len - 2));
645
                              Write_Line ("""");
646
                           end if;
647
 
648
                           --  Now, process this unit
649
 
650
                           Process (Afile);
651
                        end if;
652
                     end loop;
653
                  end loop;
654
               end if;
655
            end if;
656
         end if;
657
      end Process;
658
 
659
      --------------------------------
660
      -- Process_Imported_Libraries --
661
      --------------------------------
662
 
663
      procedure Process_Imported_Libraries is
664
         Current : Project_Id;
665
 
666
         procedure Process_Project (Project : Project_Id);
667
         --  Process Project and its imported projects recursively.
668
         --  Add any library projects to table Library_Projs.
669
 
670
         ---------------------
671
         -- Process_Project --
672
         ---------------------
673
 
674
         procedure Process_Project (Project : Project_Id) is
675
            Data     : constant Project_Data :=
676
                         In_Tree.Projects.Table (Project);
677
            Imported : Project_List := Data.Imported_Projects;
678
            Element  : Project_Element;
679
 
680
         begin
681
            --  Nothing to do if process has already been processed
682
 
683
            if not Processed_Projects.Get (Data.Name) then
684
               Processed_Projects.Set (Data.Name, True);
685
 
686
               --  Call Process_Project recursively for any imported project.
687
               --  We first process the imported projects to guarantee that
688
               --  we have a proper reverse order for the libraries.
689
 
690
               while Imported /= Empty_Project_List loop
691
                  Element :=
692
                    In_Tree.Project_Lists.Table (Imported);
693
 
694
                  if Element.Project /= No_Project then
695
                     Process_Project (Element.Project);
696
                  end if;
697
 
698
                  Imported := Element.Next;
699
               end loop;
700
 
701
               --  If it is a library project, add it to Library_Projs
702
 
703
               if Project /= For_Project and then Data.Library then
704
                  Library_Projs.Increment_Last;
705
                  Library_Projs.Table (Library_Projs.Last) := Project;
706
               end if;
707
 
708
            end if;
709
         end Process_Project;
710
 
711
      --  Start of processing for Process_Imported_Libraries
712
 
713
      begin
714
         --  Build list of library projects imported directly or indirectly,
715
         --  in the reverse order.
716
 
717
         Process_Project (For_Project);
718
 
719
         --  Add the -L and -l switches and, if the Rpath option is supported,
720
         --  add the directory to the Rpath.
721
         --  As the library projects are in the wrong order, process from the
722
         --  last to the first.
723
 
724
         for Index in reverse 1 .. Library_Projs.Last loop
725
            Current := Library_Projs.Table (Index);
726
 
727
            Get_Name_String
728
              (In_Tree.Projects.Table (Current).Library_Dir);
729
            Opts.Increment_Last;
730
            Opts.Table (Opts.Last) :=
731
              new String'("-L" & Name_Buffer (1 .. Name_Len));
732
 
733
            if Path_Option /= null then
734
               Add_Rpath (Name_Buffer (1 .. Name_Len));
735
            end if;
736
 
737
            Opts.Increment_Last;
738
            Opts.Table (Opts.Last) :=
739
              new String'
740
                ("-l" &
741
                 Get_Name_String
742
                   (In_Tree.Projects.Table
743
                      (Current).Library_Name));
744
         end loop;
745
      end Process_Imported_Libraries;
746
 
747
   --  Start of processing for Build_Library
748
 
749
   begin
750
      Reset_Tables;
751
 
752
      --  Fail if project is not a library project
753
 
754
      if not Data.Library then
755
         Com.Fail ("project """, Project_Name, """ has no library");
756
      end if;
757
 
758
      --  If this is the first time Build_Library is called, get the Name_Id
759
      --  of "s-osinte.ads".
760
 
761
      if S_Osinte_Ads = No_Name then
762
         Name_Len := 0;
763
         Add_Str_To_Name_Buffer ("s-osinte.ads");
764
         S_Osinte_Ads := Name_Find;
765
      end if;
766
 
767
      if S_Dec_Ads = No_Name then
768
         Name_Len := 0;
769
         Add_Str_To_Name_Buffer ("dec.ads");
770
         S_Dec_Ads := Name_Find;
771
      end if;
772
 
773
      if G_Trasym_Ads = No_Name then
774
         Name_Len := 0;
775
         Add_Str_To_Name_Buffer ("g-trasym.ads");
776
         G_Trasym_Ads := Name_Find;
777
      end if;
778
 
779
      --  We work in the object directory
780
 
781
      Change_Dir (Object_Directory_Path);
782
 
783
      if Standalone then
784
         --  Call gnatbind only if Bind is True
785
 
786
         if Bind then
787
            if Gnatbind_Path = null then
788
               Com.Fail ("unable to locate ", Gnatbind);
789
            end if;
790
 
791
            if Gcc_Path = null then
792
               Com.Fail ("unable to locate ", Gcc);
793
            end if;
794
 
795
            --  Allocate Arguments, if it is the first time we see a standalone
796
            --  library.
797
 
798
            if Arguments = No_Argument then
799
               Arguments := new String_List (1 .. Initial_Argument_Max);
800
            end if;
801
 
802
            --  Add "-n -o b~<lib>.adb (b$<lib>.adb on VMS) -L<lib>"
803
 
804
            Argument_Number := 2;
805
            Arguments (1) := No_Main;
806
            Arguments (2) := Output_Switch;
807
 
808
            if Hostparm.OpenVMS then
809
               B_Start (B_Start'Last) := '$';
810
            end if;
811
 
812
            Add_Argument
813
              (B_Start & Get_Name_String (Data.Library_Name) & ".adb");
814
            Add_Argument ("-L" & Get_Name_String (Data.Library_Name));
815
 
816
            if Data.Lib_Auto_Init and then SALs_Use_Constructors then
817
               Add_Argument (Auto_Initialize);
818
            end if;
819
 
820
            --  Check if Binder'Default_Switches ("Ada") is defined. If it is,
821
            --  add these switches to call gnatbind.
822
 
823
            declare
824
               Binder_Package : constant Package_Id :=
825
                                  Value_Of
826
                                    (Name        => Name_Binder,
827
                                     In_Packages => Data.Decl.Packages,
828
                                     In_Tree     => In_Tree);
829
 
830
            begin
831
               if Binder_Package /= No_Package then
832
                  declare
833
                     Defaults : constant Array_Element_Id :=
834
                                  Value_Of
835
                                    (Name      => Name_Default_Switches,
836
                                     In_Arrays =>
837
                                       In_Tree.Packages.Table
838
                                         (Binder_Package).Decl.Arrays,
839
                                     In_Tree   => In_Tree);
840
                     Switches : Variable_Value := Nil_Variable_Value;
841
 
842
                     Switch : String_List_Id := Nil_String;
843
 
844
                  begin
845
                     if Defaults /= No_Array_Element then
846
                        Switches :=
847
                          Value_Of
848
                            (Index     => Name_Ada,
849
                             Src_Index => 0,
850
                             In_Array  => Defaults,
851
                             In_Tree   => In_Tree);
852
 
853
                        if not Switches.Default then
854
                           Switch := Switches.Values;
855
 
856
                           while Switch /= Nil_String loop
857
                              Add_Argument
858
                                (Get_Name_String
859
                                   (In_Tree.String_Elements.Table
860
                                      (Switch).Value));
861
                              Switch := In_Tree.String_Elements.
862
                                          Table (Switch).Next;
863
                           end loop;
864
                        end if;
865
                     end if;
866
                  end;
867
               end if;
868
            end;
869
         end if;
870
 
871
         --  Get all the ALI files of the project file. We do that even if
872
         --  Bind is False, so that First_ALI is set.
873
 
874
         declare
875
            Unit : Unit_Data;
876
 
877
         begin
878
            Library_ALIs.Reset;
879
            Interface_ALIs.Reset;
880
            Processed_ALIs.Reset;
881
 
882
            for Source in Unit_Table.First ..
883
                          Unit_Table.Last (In_Tree.Units)
884
            loop
885
               Unit := In_Tree.Units.Table (Source);
886
 
887
               if Unit.File_Names (Body_Part).Name /= No_Name
888
                 and then Unit.File_Names (Body_Part).Path /= Slash
889
               then
890
                  if
891
                    Check_Project (Unit.File_Names (Body_Part).Project)
892
                  then
893
                     if Unit.File_Names (Specification).Name = No_Name then
894
                        declare
895
                           Src_Ind : Source_File_Index;
896
 
897
                        begin
898
                           Src_Ind := Sinput.P.Load_Project_File
899
                             (Get_Name_String
900
                                (Unit.File_Names
901
                                   (Body_Part).Path));
902
 
903
                           --  Add the ALI file only if it is not a subunit
904
 
905
                           if
906
                           not Sinput.P.Source_File_Is_Subunit (Src_Ind)
907
                           then
908
                              Add_ALI_For
909
                                (Unit.File_Names (Body_Part).Name);
910
                              exit when not Bind;
911
                           end if;
912
                        end;
913
 
914
                     else
915
                        Add_ALI_For (Unit.File_Names (Body_Part).Name);
916
                        exit when not Bind;
917
                     end if;
918
                  end if;
919
 
920
               elsif Unit.File_Names (Specification).Name /= No_Name
921
                 and then Unit.File_Names (Specification).Path /= Slash
922
                 and then Check_Project
923
                   (Unit.File_Names (Specification).Project)
924
               then
925
                  Add_ALI_For (Unit.File_Names (Specification).Name);
926
                  exit when not Bind;
927
               end if;
928
            end loop;
929
         end;
930
 
931
         --  Continue setup and call gnatbind if Bind is True
932
 
933
         if Bind then
934
 
935
            --  Get an eventual --RTS from the ALI file
936
 
937
            if First_ALI /= No_Name then
938
               declare
939
                  T : Text_Buffer_Ptr;
940
                  A : ALI_Id;
941
 
942
               begin
943
                  --  Load the ALI file
944
 
945
                  T := Read_Library_Info (First_ALI, True);
946
 
947
                  --  Read it
948
 
949
                  A := Scan_ALI
950
                         (First_ALI, T, Ignore_ED => False, Err => False);
951
 
952
                  if A /= No_ALI_Id then
953
                     for Index in
954
                       ALI.Units.Table
955
                         (ALI.ALIs.Table (A).First_Unit).First_Arg ..
956
                       ALI.Units.Table
957
                         (ALI.ALIs.Table (A).First_Unit).Last_Arg
958
                     loop
959
                        --  Look for --RTS. If found, add the switch to call
960
                        --  gnatbind.
961
 
962
                        declare
963
                           Arg : String_Ptr renames Args.Table (Index);
964
                        begin
965
                           if Arg'Length >= 6 and then
966
                              Arg (Arg'First + 2 .. Arg'First + 5) = "RTS="
967
                           then
968
                              Add_Argument (Arg.all);
969
                              exit;
970
                           end if;
971
                        end;
972
                     end loop;
973
                  end if;
974
               end;
975
            end if;
976
 
977
            --  Set the paths
978
 
979
            Set_Ada_Paths
980
              (Project             => For_Project,
981
               In_Tree             => In_Tree,
982
               Including_Libraries => True);
983
 
984
            --  Display the gnatbind command, if not in quiet output
985
 
986
            Display (Gnatbind);
987
 
988
            --  Invoke gnatbind
989
 
990
            GNAT.OS_Lib.Spawn
991
              (Gnatbind_Path.all, Arguments (1 .. Argument_Number), Success);
992
 
993
            if not Success then
994
               Com.Fail ("could not bind standalone library ",
995
                         Get_Name_String (Data.Library_Name));
996
            end if;
997
         end if;
998
 
999
         --  Compile the binder generated file only if Link is true
1000
 
1001
         if Link then
1002
            --  Set the paths
1003
 
1004
            Set_Ada_Paths
1005
              (Project             => For_Project,
1006
               In_Tree             => In_Tree,
1007
               Including_Libraries => True);
1008
 
1009
            --  Invoke <gcc> -c b$$<lib>.adb
1010
 
1011
            --  Allocate Arguments, if it is the first time we see a standalone
1012
            --  library.
1013
 
1014
            if Arguments = No_Argument then
1015
               Arguments := new String_List (1 .. Initial_Argument_Max);
1016
            end if;
1017
 
1018
            Argument_Number := 1;
1019
            Arguments (1) := Compile_Switch;
1020
 
1021
            if Hostparm.OpenVMS then
1022
               B_Start (B_Start'Last) := '$';
1023
            end if;
1024
 
1025
            Add_Argument
1026
              (B_Start & Get_Name_String (Data.Library_Name) & ".adb");
1027
 
1028
            --  If necessary, add the PIC option
1029
 
1030
            if PIC_Option /= "" then
1031
               Add_Argument (PIC_Option);
1032
            end if;
1033
 
1034
            --  Get the back-end switches and --RTS from the ALI file
1035
 
1036
            if First_ALI /= No_Name then
1037
               declare
1038
                  T : Text_Buffer_Ptr;
1039
                  A : ALI_Id;
1040
 
1041
               begin
1042
                  --  Load the ALI file
1043
 
1044
                  T := Read_Library_Info (First_ALI, True);
1045
 
1046
                  --  Read it
1047
 
1048
                  A := Scan_ALI
1049
                         (First_ALI, T, Ignore_ED => False, Err => False);
1050
 
1051
                  if A /= No_ALI_Id then
1052
                     for Index in
1053
                       ALI.Units.Table
1054
                         (ALI.ALIs.Table (A).First_Unit).First_Arg ..
1055
                       ALI.Units.Table
1056
                         (ALI.ALIs.Table (A).First_Unit).Last_Arg
1057
                     loop
1058
                        --  Do not compile with the front end switches except
1059
                        --  for --RTS.
1060
 
1061
                        declare
1062
                           Arg : String_Ptr renames Args.Table (Index);
1063
                        begin
1064
                           if not Is_Front_End_Switch (Arg.all)
1065
                             or else
1066
                               Arg (Arg'First + 2 .. Arg'First + 5) = "RTS="
1067
                           then
1068
                              Add_Argument (Arg.all);
1069
                           end if;
1070
                        end;
1071
                     end loop;
1072
                  end if;
1073
               end;
1074
            end if;
1075
 
1076
            --  Now that all the arguments are set, compile the binder
1077
            --  generated file.
1078
 
1079
            Display (Gcc);
1080
            GNAT.OS_Lib.Spawn
1081
              (Gcc_Path.all, Arguments (1 .. Argument_Number), Success);
1082
 
1083
            if not Success then
1084
               Com.Fail
1085
                 ("could not compile binder generated file for library ",
1086
                  Get_Name_String (Data.Library_Name));
1087
            end if;
1088
 
1089
            --  Process binder generated file for pragmas Linker_Options
1090
 
1091
            Process_Binder_File (Arguments (2).all & ASCII.NUL);
1092
         end if;
1093
      end if;
1094
 
1095
      --  Build the library only if Link is True
1096
 
1097
      if Link then
1098
         --  If attribute Library_GCC was specified, get the driver name
1099
 
1100
         Library_GCC :=
1101
           Value_Of (Name_Library_GCC, Data.Decl.Attributes, In_Tree);
1102
 
1103
         if not Library_GCC.Default then
1104
            Driver_Name := Library_GCC.Value;
1105
         end if;
1106
 
1107
         --  If attribute Library_Options was specified, add these additional
1108
         --  options.
1109
 
1110
         Library_Options :=
1111
           Value_Of (Name_Library_Options, Data.Decl.Attributes, In_Tree);
1112
 
1113
         if not Library_Options.Default then
1114
            declare
1115
               Current : String_List_Id := Library_Options.Values;
1116
               Element : String_Element;
1117
 
1118
            begin
1119
               while Current /= Nil_String loop
1120
                  Element :=
1121
                    In_Tree.String_Elements.Table (Current);
1122
                  Get_Name_String (Element.Value);
1123
 
1124
                  if Name_Len /= 0 then
1125
                     Opts.Increment_Last;
1126
                     Opts.Table (Opts.Last) :=
1127
                       new String'(Name_Buffer (1 .. Name_Len));
1128
                  end if;
1129
 
1130
                  Current := Element.Next;
1131
               end loop;
1132
            end;
1133
         end if;
1134
 
1135
         Lib_Dirpath  := new String'(Get_Name_String (Data.Library_Dir));
1136
         Lib_Filename := new String'(Get_Name_String (Data.Library_Name));
1137
 
1138
         case Data.Library_Kind is
1139
            when Static =>
1140
               The_Build_Mode := Static;
1141
 
1142
            when Dynamic =>
1143
               The_Build_Mode := Dynamic;
1144
 
1145
            when Relocatable =>
1146
               The_Build_Mode := Relocatable;
1147
 
1148
               if PIC_Option /= "" then
1149
                  Opts.Increment_Last;
1150
                  Opts.Table (Opts.Last) := new String'(PIC_Option);
1151
               end if;
1152
         end case;
1153
 
1154
         --  Get the library version, if any
1155
 
1156
         if Data.Lib_Internal_Name /= No_Name then
1157
            Lib_Version :=
1158
              new String'(Get_Name_String (Data.Lib_Internal_Name));
1159
         end if;
1160
 
1161
         --  Add the objects found in the object directory and the object
1162
         --  directories of the extended files, if any, except for generated
1163
         --  object files (b~.. or B$..) from extended projects.
1164
         --  When there are one or more extended files, only add an object file
1165
         --  if no object file with the same name have already been added.
1166
 
1167
         In_Main_Object_Directory := True;
1168
 
1169
         loop
1170
            declare
1171
               Object_Dir_Path : constant String :=
1172
                                   Get_Name_String (Data.Object_Directory);
1173
               Object_Dir      : Dir_Type;
1174
               Filename        : String (1 .. 255);
1175
               Last            : Natural;
1176
               Id              : Name_Id;
1177
 
1178
            begin
1179
               Open (Dir => Object_Dir, Dir_Name => Object_Dir_Path);
1180
 
1181
               --  For all entries in the object directory
1182
 
1183
               loop
1184
                  Read (Object_Dir, Filename, Last);
1185
 
1186
                  exit when Last = 0;
1187
 
1188
                  --  Check if it is an object file
1189
 
1190
                  if Is_Obj (Filename (1 .. Last)) then
1191
                     declare
1192
                        Object_Path : String :=
1193
                          Normalize_Pathname
1194
                            (Object_Dir_Path & Directory_Separator &
1195
                             Filename (1 .. Last));
1196
 
1197
                     begin
1198
                        Canonical_Case_File_Name (Object_Path);
1199
                        Canonical_Case_File_Name (Filename (1 .. Last));
1200
 
1201
                        --  If in the object directory of an extended project,
1202
                        --  do not consider generated object files.
1203
 
1204
                        if In_Main_Object_Directory
1205
                          or else Last < 5
1206
                          or else Filename (1 .. B_Start'Length) /= B_Start
1207
                        then
1208
                           Name_Len := Last;
1209
                           Name_Buffer (1 .. Name_Len) := Filename (1 .. Last);
1210
                           Id := Name_Find;
1211
 
1212
                           if not Objects_Htable.Get (Id) then
1213
 
1214
                              --  Record this object file
1215
 
1216
                              Objects_Htable.Set (Id, True);
1217
                              Objects.Increment_Last;
1218
                              Objects.Table (Objects.Last) :=
1219
                                new String'(Object_Path);
1220
 
1221
                              declare
1222
                                 ALI_File : constant String :=
1223
                                              Ext_To (Object_Path, "ali");
1224
 
1225
                              begin
1226
                                 if Is_Regular_File (ALI_File) then
1227
 
1228
                                    --  Record the ALI file
1229
 
1230
                                    ALIs.Increment_Last;
1231
                                    ALIs.Table (ALIs.Last) :=
1232
                                      new String'(ALI_File);
1233
 
1234
                                    --  Find out if for this ALI file,
1235
                                    --  libgnarl or libdecgnat or g-trasym.obj
1236
                                    --  (on OpenVMS) is necessary.
1237
 
1238
                                    Check_Libs (ALI_File);
1239
 
1240
                                 else
1241
                                    --  Object file is a foreign object file
1242
 
1243
                                    Foreigns.Increment_Last;
1244
                                    Foreigns.Table (Foreigns.Last) :=
1245
                                      new String'(Object_Path);
1246
                                 end if;
1247
                              end;
1248
                           end if;
1249
                        end if;
1250
                     end;
1251
                  end if;
1252
               end loop;
1253
 
1254
               Close (Dir => Object_Dir);
1255
 
1256
            exception
1257
               when Directory_Error =>
1258
                  Com.Fail ("cannot find object directory """,
1259
                            Get_Name_String (Data.Object_Directory),
1260
                            """");
1261
            end;
1262
 
1263
            exit when Data.Extends = No_Project;
1264
 
1265
            In_Main_Object_Directory  := False;
1266
            Data := In_Tree.Projects.Table (Data.Extends);
1267
         end loop;
1268
 
1269
         --  Add the -L and -l switches for the imported Library Project Files,
1270
         --  and, if Path Option is supported, the library directory path names
1271
         --  to Rpath.
1272
 
1273
         Process_Imported_Libraries;
1274
 
1275
         --  Link with libgnat and possibly libgnarl
1276
 
1277
         Opts.Increment_Last;
1278
         Opts.Table (Opts.Last) := new String'("-L" & Lib_Directory);
1279
 
1280
         --  If Path Option is supported, add libgnat directory path name to
1281
         --  Rpath.
1282
 
1283
         if Path_Option /= null then
1284
            Add_Rpath (Lib_Directory);
1285
         end if;
1286
 
1287
         if Libgnarl_Needed then
1288
            Opts.Increment_Last;
1289
 
1290
            if The_Build_Mode = Static then
1291
               Opts.Table (Opts.Last) := new String'("-lgnarl");
1292
            else
1293
               Opts.Table (Opts.Last) := new String'(Shared_Lib ("gnarl"));
1294
            end if;
1295
         end if;
1296
 
1297
         if Gtrasymobj_Needed then
1298
            Opts.Increment_Last;
1299
            Opts.Table (Opts.Last) :=
1300
              new String'(Lib_Directory & "/g-trasym.obj");
1301
         end if;
1302
 
1303
         if Libdecgnat_Needed then
1304
            Opts.Increment_Last;
1305
            Opts.Table (Opts.Last) :=
1306
              new String'("-L" & Lib_Directory & "/../declib");
1307
            Opts.Increment_Last;
1308
            Opts.Table (Opts.Last) := new String'("-ldecgnat");
1309
         end if;
1310
 
1311
         Opts.Increment_Last;
1312
 
1313
         if The_Build_Mode = Static then
1314
            Opts.Table (Opts.Last) := new String'("-lgnat");
1315
         else
1316
            Opts.Table (Opts.Last) := new String'(Shared_Lib ("gnat"));
1317
         end if;
1318
 
1319
         --  If Path Option is supported, add the necessary switch with the
1320
         --  content of Rpath. As Rpath contains at least libgnat directory
1321
         --  path name, it is guaranteed that it is not null.
1322
 
1323
         if Path_Option /= null then
1324
            Opts.Increment_Last;
1325
            Opts.Table (Opts.Last) :=
1326
              new String'(Path_Option.all & Rpath (1 .. Rpath_Last));
1327
            Free (Path_Option);
1328
            Free (Rpath);
1329
         end if;
1330
 
1331
         Object_Files :=
1332
           new Argument_List'
1333
             (Argument_List (Objects.Table (1 .. Objects.Last)));
1334
 
1335
         Foreign_Objects :=
1336
           new Argument_List'(Argument_List
1337
                                (Foreigns.Table (1 .. Foreigns.Last)));
1338
 
1339
         Ali_Files :=
1340
           new Argument_List'(Argument_List (ALIs.Table (1 .. ALIs.Last)));
1341
 
1342
         Options :=
1343
           new Argument_List'(Argument_List (Opts.Table (1 .. Opts.Last)));
1344
 
1345
         --  We fail if there are no object to put in the library
1346
         --  (Ada or foreign objects).
1347
 
1348
         if Object_Files'Length = 0 then
1349
            Com.Fail ("no object files for library """ &
1350
                      Lib_Filename.all & '"');
1351
         end if;
1352
 
1353
         if not Opt.Quiet_Output then
1354
            Write_Eol;
1355
            Write_Str  ("building ");
1356
            Write_Str (Ada.Characters.Handling.To_Lower
1357
                         (Build_Mode_State'Image (The_Build_Mode)));
1358
            Write_Str  (" library for project ");
1359
            Write_Line (Project_Name);
1360
 
1361
            Write_Eol;
1362
 
1363
            Write_Line ("object files:");
1364
 
1365
            for Index in Object_Files'Range loop
1366
               Write_Str  ("   ");
1367
               Write_Line (Object_Files (Index).all);
1368
            end loop;
1369
 
1370
            Write_Eol;
1371
 
1372
            if Ali_Files'Length = 0 then
1373
               Write_Line ("NO ALI files");
1374
 
1375
            else
1376
               Write_Line ("ALI files:");
1377
 
1378
               for Index in Ali_Files'Range loop
1379
                  Write_Str  ("   ");
1380
                  Write_Line (Ali_Files (Index).all);
1381
               end loop;
1382
            end if;
1383
 
1384
            Write_Eol;
1385
         end if;
1386
 
1387
         --  We check that all object files are regular files
1388
 
1389
         Check_Context;
1390
 
1391
         --  Delete the existing library file, if it exists.
1392
         --  Fail if the library file is not writable, or if it is not possible
1393
         --  to delete the file.
1394
 
1395
         declare
1396
            DLL_Name : aliased String :=
1397
                         Lib_Dirpath.all & '/' & DLL_Prefix &
1398
                           Lib_Filename.all & "." & DLL_Ext;
1399
 
1400
            Archive_Name : aliased String :=
1401
                             Lib_Dirpath.all & "/lib" &
1402
                               Lib_Filename.all & "." & Archive_Ext;
1403
 
1404
            type Str_Ptr is access all String;
1405
            --  This type is necessary to meet the accessibility rules of Ada.
1406
            --  It is not possible to use String_Access here.
1407
 
1408
            Full_Lib_Name : Str_Ptr;
1409
            --  Designates the full library path name. Either DLL_Name or
1410
            --  Archive_Name, depending on the library kind.
1411
 
1412
            Success : Boolean := False;
1413
            --  Used to call Delete_File
1414
 
1415
         begin
1416
            if The_Build_Mode = Static then
1417
               Full_Lib_Name := Archive_Name'Access;
1418
            else
1419
               Full_Lib_Name := DLL_Name'Access;
1420
            end if;
1421
 
1422
            if Is_Regular_File (Full_Lib_Name.all) then
1423
               if Is_Writable_File (Full_Lib_Name.all) then
1424
                  Delete_File (Full_Lib_Name.all, Success);
1425
               end if;
1426
 
1427
               if Is_Regular_File (Full_Lib_Name.all) then
1428
                  Com.Fail ("could not delete """ & Full_Lib_Name.all & """");
1429
               end if;
1430
            end if;
1431
         end;
1432
 
1433
         Argument_Number := 0;
1434
 
1435
         --  If we have a standalone library, gather all the interface ALI.
1436
         --  They are passed to Build_Dynamic_Library, where they are used by
1437
         --  some platforms (VMS, for example) to decide what symbols should be
1438
         --  exported. They are also flagged as Interface when we copy them to
1439
         --  the library directory (by Copy_ALI_Files, below).
1440
 
1441
         if Standalone then
1442
            Data := In_Tree.Projects.Table (For_Project);
1443
 
1444
            declare
1445
               Iface : String_List_Id := Data.Lib_Interface_ALIs;
1446
               ALI   : File_Name_Type;
1447
 
1448
            begin
1449
               while Iface /= Nil_String loop
1450
                  ALI :=
1451
                    In_Tree.String_Elements.Table (Iface).Value;
1452
                  Interface_ALIs.Set (ALI, True);
1453
                  Get_Name_String
1454
                    (In_Tree.String_Elements.Table (Iface).Value);
1455
                  Add_Argument (Name_Buffer (1 .. Name_Len));
1456
                  Iface :=
1457
                    In_Tree.String_Elements.Table (Iface).Next;
1458
               end loop;
1459
 
1460
               Iface := Data.Lib_Interface_ALIs;
1461
 
1462
               if not Opt.Quiet_Output then
1463
 
1464
                  --  Check that the interface set is complete: any unit in the
1465
                  --  library that is needed by an interface should also be an
1466
                  --  interface. If it is not the case, output a warning.
1467
 
1468
                  while Iface /= Nil_String loop
1469
                     ALI := In_Tree.String_Elements.Table
1470
                              (Iface).Value;
1471
                     Process (ALI);
1472
                     Iface :=
1473
                       In_Tree.String_Elements.Table (Iface).Next;
1474
                  end loop;
1475
               end if;
1476
            end;
1477
         end if;
1478
 
1479
         declare
1480
            Current_Dir  : constant String := Get_Current_Dir;
1481
            Dir          : Dir_Type;
1482
 
1483
            Name : String (1 .. 200);
1484
            Last : Natural;
1485
 
1486
            Disregard : Boolean;
1487
 
1488
            DLL_Name : aliased constant String :=
1489
                         Lib_Filename.all & "." & DLL_Ext;
1490
 
1491
            Archive_Name : aliased constant String :=
1492
                             Lib_Filename.all & "." & Archive_Ext;
1493
 
1494
            Delete : Boolean := False;
1495
 
1496
         begin
1497
            --  Clean the library directory: remove any file with the name of
1498
            --  the library file and any ALI file of a source of the project.
1499
 
1500
            begin
1501
               Get_Name_String
1502
                 (In_Tree.Projects.Table (For_Project).Library_Dir);
1503
               Change_Dir (Name_Buffer (1 .. Name_Len));
1504
 
1505
            exception
1506
               when others =>
1507
                  Com.Fail
1508
                    ("unable to access library directory """,
1509
                     Name_Buffer (1 .. Name_Len),
1510
                     """");
1511
            end;
1512
 
1513
            Open (Dir, ".");
1514
 
1515
            loop
1516
               Read (Dir, Name, Last);
1517
               exit when Last = 0;
1518
 
1519
               if Is_Regular_File (Name (1 .. Last)) then
1520
                  Canonical_Case_File_Name (Name (1 .. Last));
1521
                  Delete := False;
1522
 
1523
                  if (The_Build_Mode = Static and then
1524
                        Name (1 .. Last) =  Archive_Name)
1525
                    or else
1526
                      ((The_Build_Mode = Dynamic or else
1527
                          The_Build_Mode = Relocatable)
1528
                       and then
1529
                         Name (1 .. Last) = DLL_Name)
1530
                  then
1531
                     Delete := True;
1532
 
1533
                  elsif Last > 4 and then Name (Last - 3 .. Last) = ".ali" then
1534
                     declare
1535
                        Unit : Unit_Data;
1536
                     begin
1537
                        --  Compare with ALI file names of the project
1538
 
1539
                        for Index in 1 .. Unit_Table.Last (In_Tree.Units) loop
1540
                           Unit := In_Tree.Units.Table (Index);
1541
 
1542
                           if Unit.File_Names (Body_Part).Project /=
1543
                             No_Project
1544
                           then
1545
                              if  Ultimate_Extension_Of
1546
                                (Unit.File_Names (Body_Part).Project, In_Tree)
1547
                                 = For_Project
1548
                              then
1549
                                 Get_Name_String
1550
                                   (Unit.File_Names (Body_Part).Name);
1551
                                 Name_Len := Name_Len -
1552
                                   File_Extension
1553
                                     (Name (1 .. Name_Len))'Length;
1554
                                 if Name_Buffer (1 .. Name_Len) =
1555
                                     Name (1 .. Last - 4)
1556
                                 then
1557
                                    Delete := True;
1558
                                    exit;
1559
                                 end if;
1560
                              end if;
1561
 
1562
                           elsif Ultimate_Extension_Of
1563
                             (Unit.File_Names (Specification).Project, In_Tree)
1564
                             = For_Project
1565
                           then
1566
                              Get_Name_String
1567
                                (Unit.File_Names (Specification).Name);
1568
                              Name_Len := Name_Len -
1569
                                File_Extension (Name (1 .. Name_Len))'Length;
1570
 
1571
                              if Name_Buffer (1 .. Name_Len) =
1572
                                   Name (1 .. Last - 4)
1573
                              then
1574
                                 Delete := True;
1575
                                 exit;
1576
                              end if;
1577
                           end if;
1578
                        end loop;
1579
                     end;
1580
                  end if;
1581
 
1582
                  if Delete then
1583
                     Set_Writable (Name (1 .. Last));
1584
                     Delete_File (Name (1 .. Last), Disregard);
1585
                  end if;
1586
               end if;
1587
            end loop;
1588
 
1589
            Close (Dir);
1590
 
1591
            Change_Dir (Current_Dir);
1592
         end;
1593
 
1594
         --  Call procedure to build the library, depending on the build mode
1595
 
1596
         case The_Build_Mode is
1597
            when Dynamic | Relocatable =>
1598
               Build_Dynamic_Library
1599
                 (Ofiles        => Object_Files.all,
1600
                  Foreign       => Foreign_Objects.all,
1601
                  Afiles        => Ali_Files.all,
1602
                  Options       => Options.all,
1603
                  Options_2     => No_Argument_List,
1604
                  Interfaces    => Arguments (1 .. Argument_Number),
1605
                  Lib_Filename  => Lib_Filename.all,
1606
                  Lib_Dir       => Lib_Dirpath.all,
1607
                  Symbol_Data   => Data.Symbol_Data,
1608
                  Driver_Name   => Driver_Name,
1609
                  Lib_Version   => Lib_Version.all,
1610
                  Auto_Init     => Data.Lib_Auto_Init);
1611
 
1612
            when Static =>
1613
               MLib.Build_Library
1614
                 (Object_Files.all,
1615
                  Ali_Files.all,
1616
                  Lib_Filename.all,
1617
                  Lib_Dirpath.all);
1618
 
1619
            when None =>
1620
               null;
1621
         end case;
1622
 
1623
         --  We need to copy the ALI files from the object directory to
1624
         --  the library ALI directory, so that the linker find them there,
1625
         --  and does not need to look in the object directory where it
1626
         --  would also find the object files; and we don't want that:
1627
         --  we want the linker to use the library.
1628
 
1629
         --  Copy the ALI files and make the copies read-only. For interfaces,
1630
         --  mark the copies as interfaces.
1631
 
1632
         Copy_ALI_Files
1633
           (Files      => Ali_Files.all,
1634
            To         => In_Tree.Projects.Table (For_Project).Library_ALI_Dir,
1635
            Interfaces => Arguments (1 .. Argument_Number));
1636
 
1637
         --  Copy interface sources if Library_Src_Dir specified
1638
 
1639
         if Standalone
1640
           and then In_Tree.Projects.Table
1641
                      (For_Project).Library_Src_Dir /= No_Name
1642
         then
1643
            --  Clean the interface copy directory: remove any source that
1644
            --  could be a source of the project.
1645
 
1646
            begin
1647
               Get_Name_String
1648
                 (In_Tree.Projects.Table (For_Project).Library_Src_Dir);
1649
               Change_Dir (Name_Buffer (1 .. Name_Len));
1650
 
1651
            exception
1652
               when others =>
1653
                  Com.Fail
1654
                    ("unable to access library source copy directory """,
1655
                     Name_Buffer (1 .. Name_Len),
1656
                     """");
1657
            end;
1658
 
1659
            declare
1660
               Dir    : Dir_Type;
1661
               Delete : Boolean;
1662
               Unit   : Unit_Data;
1663
 
1664
               Name : String (1 .. 200);
1665
               Last : Natural;
1666
 
1667
               Disregard : Boolean;
1668
 
1669
            begin
1670
               Open (Dir, ".");
1671
 
1672
               loop
1673
                  Read (Dir, Name, Last);
1674
                  exit when Last = 0;
1675
 
1676
                  if Is_Regular_File (Name (1 .. Last)) then
1677
                     Canonical_Case_File_Name (Name (1 .. Last));
1678
                     Delete := False;
1679
 
1680
                     --  Compare with source file names of the project
1681
 
1682
                     for Index in 1 .. Unit_Table.Last (In_Tree.Units) loop
1683
                        Unit := In_Tree.Units.Table (Index);
1684
 
1685
                        if Ultimate_Extension_Of
1686
                            (Unit.File_Names (Body_Part).Project, In_Tree) =
1687
                            For_Project
1688
                          and then
1689
                            Get_Name_String
1690
                              (Unit.File_Names (Body_Part).Name) =
1691
                            Name (1 .. Last)
1692
                        then
1693
                           Delete := True;
1694
                           exit;
1695
                        end if;
1696
 
1697
                        if Ultimate_Extension_Of
1698
                           (Unit.File_Names (Specification).Project, In_Tree) =
1699
                           For_Project
1700
                          and then
1701
                           Get_Name_String
1702
                             (Unit.File_Names (Specification).Name) =
1703
                           Name (1 .. Last)
1704
                        then
1705
                           Delete := True;
1706
                           exit;
1707
                        end if;
1708
                     end loop;
1709
                  end if;
1710
 
1711
                  if Delete then
1712
                     Set_Writable (Name (1 .. Last));
1713
                     Delete_File (Name (1 .. Last), Disregard);
1714
                  end if;
1715
               end loop;
1716
 
1717
               Close (Dir);
1718
            end;
1719
 
1720
            Copy_Interface_Sources
1721
              (For_Project => For_Project,
1722
               In_Tree     => In_Tree,
1723
               Interfaces  => Arguments (1 .. Argument_Number),
1724
               To_Dir      => In_Tree.Projects.Table
1725
                                (For_Project).Library_Src_Dir);
1726
         end if;
1727
      end if;
1728
 
1729
      --  Reset the current working directory to its previous value
1730
 
1731
      Change_Dir (Current_Dir);
1732
   end Build_Library;
1733
 
1734
   -----------
1735
   -- Check --
1736
   -----------
1737
 
1738
   procedure Check (Filename : String) is
1739
   begin
1740
      if not Is_Regular_File (Filename) then
1741
         Com.Fail (Filename, " not found.");
1742
      end if;
1743
   end Check;
1744
 
1745
   -------------------
1746
   -- Check_Context --
1747
   -------------------
1748
 
1749
   procedure Check_Context is
1750
   begin
1751
      --  Check that each object file exists
1752
 
1753
      for F in Object_Files'Range loop
1754
         Check (Object_Files (F).all);
1755
      end loop;
1756
   end Check_Context;
1757
 
1758
   -------------------
1759
   -- Check_Library --
1760
   -------------------
1761
 
1762
   procedure Check_Library
1763
     (For_Project : Project_Id; In_Tree : Project_Tree_Ref)
1764
   is
1765
      Data    : constant Project_Data :=
1766
                  In_Tree.Projects.Table (For_Project);
1767
      Lib_TS  : Time_Stamp_Type;
1768
      Current : constant Dir_Name_Str := Get_Current_Dir;
1769
 
1770
   begin
1771
      --  No need to build the library if there is no object directory,
1772
      --  hence no object files to build the library.
1773
 
1774
      if Data.Library then
1775
         declare
1776
            Lib_Name : constant Name_Id :=
1777
              Library_File_Name_For (For_Project, In_Tree);
1778
         begin
1779
            Change_Dir (Get_Name_String (Data.Library_Dir));
1780
            Lib_TS := File_Stamp (Lib_Name);
1781
            In_Tree.Projects.Table (For_Project).Library_TS := Lib_TS;
1782
         end;
1783
 
1784
         if not Data.Externally_Built
1785
           and then not Data.Need_To_Build_Lib
1786
           and then Data.Object_Directory /= No_Name
1787
         then
1788
            declare
1789
               Obj_TS     : Time_Stamp_Type;
1790
               Object_Dir : Dir_Type;
1791
 
1792
            begin
1793
               if Hostparm.OpenVMS then
1794
                  B_Start (B_Start'Last) := '$';
1795
               end if;
1796
 
1797
               --  If the library file does not exist, then the time stamp will
1798
               --  be Empty_Time_Stamp, earlier than any other time stamp.
1799
 
1800
               Change_Dir (Get_Name_String (Data.Object_Directory));
1801
               Open (Dir => Object_Dir, Dir_Name => ".");
1802
 
1803
               --  For all entries in the object directory
1804
 
1805
               loop
1806
                  Read (Object_Dir, Name_Buffer, Name_Len);
1807
                  exit when Name_Len = 0;
1808
 
1809
                  --  Check if it is an object file, but ignore any binder
1810
                  --  generated file.
1811
 
1812
                  if Is_Obj (Name_Buffer (1 .. Name_Len))
1813
                    and then Name_Buffer (1 .. B_Start'Length) /= B_Start
1814
                  then
1815
                     --  Get the object file time stamp
1816
 
1817
                     Obj_TS := File_Stamp (Name_Find);
1818
 
1819
                     --  If library file time stamp is earlier, set
1820
                     --  Need_To_Build_Lib and return. String comparaison is
1821
                     --  used, otherwise time stamps may be too close and the
1822
                     --  comparaison would return True, which would trigger
1823
                     --  an unnecessary rebuild of the library.
1824
 
1825
                     if String (Lib_TS) < String (Obj_TS) then
1826
 
1827
                        --  Library must be rebuilt
1828
 
1829
                        In_Tree.Projects.Table
1830
                          (For_Project).Need_To_Build_Lib := True;
1831
                        exit;
1832
                     end if;
1833
                  end if;
1834
               end loop;
1835
 
1836
               Close (Object_Dir);
1837
            end;
1838
         end if;
1839
 
1840
         Change_Dir (Current);
1841
      end if;
1842
   end Check_Library;
1843
 
1844
   ----------------------------
1845
   -- Copy_Interface_Sources --
1846
   ----------------------------
1847
 
1848
   procedure Copy_Interface_Sources
1849
     (For_Project : Project_Id;
1850
      In_Tree     : Project_Tree_Ref;
1851
      Interfaces  : Argument_List;
1852
      To_Dir      : Name_Id)
1853
   is
1854
      Current : constant Dir_Name_Str := Get_Current_Dir;
1855
      --  The current directory, where to return to at the end
1856
 
1857
      Target : constant Dir_Name_Str := Get_Name_String (To_Dir);
1858
      --  The directory where to copy sources
1859
 
1860
      Text     : Text_Buffer_Ptr;
1861
      The_ALI  : ALI.ALI_Id;
1862
      Lib_File : Name_Id;
1863
 
1864
      First_Unit  : ALI.Unit_Id;
1865
      Second_Unit : ALI.Unit_Id;
1866
 
1867
      Data : Unit_Data;
1868
 
1869
      Copy_Subunits : Boolean := False;
1870
      --  When True, indicates that subunits, if any, need to be copied too
1871
 
1872
      procedure Copy (File_Name : Name_Id);
1873
      --  Copy one source of the project to the target directory
1874
 
1875
      function Is_Same_Or_Extension
1876
        (Extending : Project_Id;
1877
         Extended  : Project_Id) return Boolean;
1878
      --  Return True if project Extending is equal to or extends project
1879
      --  Extended.
1880
 
1881
      ----------
1882
      -- Copy --
1883
      ----------
1884
 
1885
      procedure Copy (File_Name : Name_Id) is
1886
         Success : Boolean := False;
1887
 
1888
      begin
1889
         Unit_Loop :
1890
         for Index in Unit_Table.First ..
1891
                      Unit_Table.Last (In_Tree.Units)
1892
         loop
1893
            Data := In_Tree.Units.Table (Index);
1894
 
1895
            --  Find and copy the immediate or inherited source
1896
 
1897
            for J in Data.File_Names'Range loop
1898
               if Is_Same_Or_Extension
1899
                    (For_Project, Data.File_Names (J).Project)
1900
                 and then Data.File_Names (J).Name = File_Name
1901
               then
1902
                  Copy_File
1903
                    (Get_Name_String (Data.File_Names (J).Path),
1904
                     Target,
1905
                     Success,
1906
                     Mode => Overwrite,
1907
                     Preserve => Preserve);
1908
                  exit Unit_Loop;
1909
               end if;
1910
            end loop;
1911
         end loop Unit_Loop;
1912
      end Copy;
1913
 
1914
      --------------------------
1915
      -- Is_Same_Or_Extension --
1916
      --------------------------
1917
 
1918
      function Is_Same_Or_Extension
1919
        (Extending : Project_Id;
1920
         Extended  : Project_Id) return Boolean
1921
      is
1922
         Ext : Project_Id := Extending;
1923
 
1924
      begin
1925
         while Ext /= No_Project loop
1926
            if Ext = Extended then
1927
               return True;
1928
            end if;
1929
 
1930
            Ext := In_Tree.Projects.Table (Ext).Extends;
1931
         end loop;
1932
 
1933
         return False;
1934
      end Is_Same_Or_Extension;
1935
 
1936
   --  Start of processing for Copy_Interface_Sources
1937
 
1938
   begin
1939
      --  Change the working directory to the object directory
1940
 
1941
      Change_Dir
1942
        (Get_Name_String
1943
           (In_Tree.Projects.Table
1944
              (For_Project).Object_Directory));
1945
 
1946
      for Index in Interfaces'Range loop
1947
 
1948
         --  First, load the ALI file
1949
 
1950
         Name_Len := 0;
1951
         Add_Str_To_Name_Buffer (Interfaces (Index).all);
1952
         Lib_File := Name_Find;
1953
         Text := Read_Library_Info (Lib_File);
1954
         The_ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
1955
         Free (Text);
1956
 
1957
         Second_Unit := No_Unit_Id;
1958
         First_Unit := ALI.ALIs.Table (The_ALI).First_Unit;
1959
         Copy_Subunits := True;
1960
 
1961
         --  If there is both a spec and a body, check if they are both needed
1962
 
1963
         if ALI.Units.Table (First_Unit).Utype = Is_Body then
1964
            Second_Unit := ALI.ALIs.Table (The_ALI).Last_Unit;
1965
 
1966
            --  If the body is not needed, then reset First_Unit
1967
 
1968
            if not ALI.Units.Table (Second_Unit).Body_Needed_For_SAL then
1969
               First_Unit := No_Unit_Id;
1970
               Copy_Subunits := False;
1971
            end if;
1972
 
1973
         elsif ALI.Units.Table (First_Unit).Utype = Is_Spec_Only then
1974
            Copy_Subunits := False;
1975
         end if;
1976
 
1977
         --  Copy the file(s) that need to be copied
1978
 
1979
         if First_Unit /= No_Unit_Id then
1980
            Copy (File_Name => ALI.Units.Table (First_Unit).Sfile);
1981
         end if;
1982
 
1983
         if Second_Unit /= No_Unit_Id then
1984
            Copy (File_Name => ALI.Units.Table (Second_Unit).Sfile);
1985
         end if;
1986
 
1987
         --  Copy all the separates, if any
1988
 
1989
         if Copy_Subunits then
1990
            for Dep in ALI.ALIs.Table (The_ALI).First_Sdep ..
1991
              ALI.ALIs.Table (The_ALI).Last_Sdep
1992
            loop
1993
               if Sdep.Table (Dep).Subunit_Name /= No_Name then
1994
                  Copy (File_Name => Sdep.Table (Dep).Sfile);
1995
               end if;
1996
            end loop;
1997
         end if;
1998
      end loop;
1999
 
2000
      --  Restore the initial working directory
2001
 
2002
      Change_Dir (Current);
2003
   end Copy_Interface_Sources;
2004
 
2005
   -------------
2006
   -- Display --
2007
   -------------
2008
 
2009
   procedure Display (Executable : String) is
2010
   begin
2011
      if not Opt.Quiet_Output then
2012
         Write_Str (Executable);
2013
 
2014
         for Index in 1 .. Argument_Number loop
2015
            Write_Char (' ');
2016
            Write_Str (Arguments (Index).all);
2017
         end loop;
2018
 
2019
         Write_Eol;
2020
      end if;
2021
   end Display;
2022
 
2023
   -------------------------
2024
   -- Process_Binder_File --
2025
   -------------------------
2026
 
2027
   procedure Process_Binder_File (Name : String) is
2028
      Fd : FILEs;
2029
      --  Binder file's descriptor
2030
 
2031
      Read_Mode : constant String := "r" & ASCII.Nul;
2032
      --  For fopen
2033
 
2034
      Status : Interfaces.C_Streams.int;
2035
      pragma Unreferenced (Status);
2036
      --  For fclose
2037
 
2038
      Begin_Info : constant String := "--  BEGIN Object file/option list";
2039
      End_Info   : constant String := "--  END Object file/option list   ";
2040
 
2041
      Next_Line : String (1 .. 1000);
2042
      --  Current line value
2043
      --  Where does this odd constant 1000 come from, looks suspicious ???
2044
 
2045
      Nlast : Integer;
2046
      --  End of line slice (the slice does not contain the line terminator)
2047
 
2048
      procedure Get_Next_Line;
2049
      --  Read the next line from the binder file without the line terminator
2050
 
2051
      -------------------
2052
      -- Get_Next_Line --
2053
      -------------------
2054
 
2055
      procedure Get_Next_Line is
2056
         Fchars : chars;
2057
 
2058
      begin
2059
         Fchars := fgets (Next_Line'Address, Next_Line'Length, Fd);
2060
 
2061
         if Fchars = System.Null_Address then
2062
            Fail ("Error reading binder output");
2063
         end if;
2064
 
2065
         Nlast := 1;
2066
         while Nlast <= Next_Line'Last
2067
           and then Next_Line (Nlast) /= ASCII.LF
2068
           and then Next_Line (Nlast) /= ASCII.CR
2069
         loop
2070
            Nlast := Nlast + 1;
2071
         end loop;
2072
 
2073
         Nlast := Nlast - 1;
2074
      end Get_Next_Line;
2075
 
2076
   --  Start of processing for Process_Binder_File
2077
 
2078
   begin
2079
      Fd := fopen (Name'Address, Read_Mode'Address);
2080
 
2081
      if Fd = NULL_Stream then
2082
         Fail ("Failed to open binder output");
2083
      end if;
2084
 
2085
      --  Skip up to the Begin Info line
2086
 
2087
      loop
2088
         Get_Next_Line;
2089
         exit when Next_Line (1 .. Nlast) = Begin_Info;
2090
      end loop;
2091
 
2092
      --  Find the first switch
2093
 
2094
      loop
2095
         Get_Next_Line;
2096
 
2097
         exit when Next_Line (1 .. Nlast) = End_Info;
2098
 
2099
         --  As the binder generated file is in Ada, remove the first eight
2100
         --  characters "   --   ".
2101
 
2102
         Next_Line (1 .. Nlast - 8) := Next_Line (9 .. Nlast);
2103
         Nlast := Nlast - 8;
2104
 
2105
         --  Stop when the first switch is found
2106
 
2107
         exit when Next_Line (1) = '-';
2108
      end loop;
2109
 
2110
      if Next_Line (1 .. Nlast) /= End_Info then
2111
         loop
2112
            --  Ignore -static and -shared, since -shared will be used
2113
            --  in any case.
2114
 
2115
            --  Ignore -lgnat, -lgnarl and -ldecgnat as they will be added
2116
            --  later, because they are also needed for non Stand-Alone shared
2117
            --  libraries.
2118
 
2119
            --  Also ignore the shared libraries which are :
2120
 
2121
            --  UNIX / Windows    VMS
2122
            --  -lgnat-<version>  -lgnat_<version>  (7 + version'length chars)
2123
            --  -lgnarl-<version> -lgnarl_<version> (8 + version'length chars)
2124
 
2125
            if Next_Line (1 .. Nlast) /= "-static" and then
2126
               Next_Line (1 .. Nlast) /= "-shared" and then
2127
               Next_Line (1 .. Nlast) /= "-ldecgnat" and then
2128
               Next_Line (1 .. Nlast) /= "-lgnarl" and then
2129
               Next_Line (1 .. Nlast) /= "-lgnat" and then
2130
               Next_Line
2131
                 (1 .. Natural'Min (Nlast, 8 + Library_Version'Length)) /=
2132
                   Shared_Lib ("gnarl") and then
2133
               Next_Line
2134
                 (1 .. Natural'Min (Nlast, 7 + Library_Version'Length)) /=
2135
                   Shared_Lib ("gnat")
2136
            then
2137
               if Next_Line (1) /= '-' then
2138
 
2139
                  --  This is not an option, should we add it?
2140
 
2141
                  if Add_Object_Files then
2142
                     Opts.Increment_Last;
2143
                     Opts.Table (Opts.Last) :=
2144
                       new String'(Next_Line (1 .. Nlast));
2145
                  end if;
2146
 
2147
               else
2148
                  --  Add all other options
2149
 
2150
                  Opts.Increment_Last;
2151
                  Opts.Table (Opts.Last) :=
2152
                    new String'(Next_Line (1 .. Nlast));
2153
               end if;
2154
            end if;
2155
 
2156
            --  Next option, if any
2157
 
2158
            Get_Next_Line;
2159
            exit when Next_Line (1 .. Nlast) = End_Info;
2160
 
2161
            --  Remove first eight characters "   --   "
2162
 
2163
            Next_Line (1 .. Nlast - 8) := Next_Line (9 .. Nlast);
2164
            Nlast := Nlast - 8;
2165
         end loop;
2166
      end if;
2167
 
2168
      Status := fclose (Fd);
2169
 
2170
      --  Is it really right to ignore any close error ???
2171
 
2172
   end Process_Binder_File;
2173
 
2174
   ------------------
2175
   -- Reset_Tables --
2176
   ------------------
2177
 
2178
   procedure Reset_Tables is
2179
   begin
2180
      Objects.Init;
2181
      Objects_Htable.Reset;
2182
      Foreigns.Init;
2183
      ALIs.Init;
2184
      Opts.Init;
2185
      Processed_Projects.Reset;
2186
      Library_Projs.Init;
2187
   end Reset_Tables;
2188
 
2189
   ---------------------------
2190
   -- SALs_Use_Constructors --
2191
   ---------------------------
2192
 
2193
   function SALs_Use_Constructors return Boolean is
2194
      function C_SALs_Init_Using_Constructors return Integer;
2195
      pragma Import (C, C_SALs_Init_Using_Constructors,
2196
                     "__gnat_sals_init_using_constructors");
2197
   begin
2198
      return C_SALs_Init_Using_Constructors /= 0;
2199
   end SALs_Use_Constructors;
2200
 
2201
   ---------------------------
2202
   -- Ultimate_Extension_Of --
2203
   ---------------------------
2204
 
2205
   function Ultimate_Extension_Of
2206
     (Project : Project_Id;
2207
      In_Tree : Project_Tree_Ref) return Project_Id
2208
   is
2209
      Result : Project_Id := Project;
2210
      Data   : Project_Data;
2211
 
2212
   begin
2213
      if Project /= No_Project then
2214
         loop
2215
            Data := In_Tree.Projects.Table (Result);
2216
            exit when Data.Extended_By = No_Project;
2217
            Result := Data.Extended_By;
2218
         end loop;
2219
      end if;
2220
 
2221
      return Result;
2222
   end Ultimate_Extension_Of;
2223
 
2224
end MLib.Prj;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.