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

Subversion Repositories openrisc_me

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc1/] [gcc/] [ada/] [mlib-prj.adb] - Blame information for rev 338

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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