OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [ada/] [make.adb] - Blame information for rev 293

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

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                                 M A K E                                  --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009, Free Software Foundation, Inc.         --
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 ALI.Util; use ALI.Util;
28
with Csets;
29
with Debug;
30
with Errutil;
31
with Fmap;
32
with Fname;    use Fname;
33
with Fname.SF; use Fname.SF;
34
with Fname.UF; use Fname.UF;
35
with Gnatvsn;  use Gnatvsn;
36
with Hostparm; use Hostparm;
37
with Makeusg;
38
with Makeutl;  use Makeutl;
39
with MLib;
40
with MLib.Prj;
41
with MLib.Tgt; use MLib.Tgt;
42
with MLib.Utl;
43
with Namet;    use Namet;
44
with Opt;      use Opt;
45
with Osint.M;  use Osint.M;
46
with Osint;    use Osint;
47
with Output;   use Output;
48
with Prj;      use Prj;
49
with Prj.Com;
50
with Prj.Env;
51
with Prj.Pars;
52
with Prj.Tree; use Prj.Tree;
53
with Prj.Util;
54
with SFN_Scan;
55
with Sinput.P;
56
with Snames;   use Snames;
57
 
58
pragma Warnings (Off);
59
with System.HTable;
60
pragma Warnings (On);
61
 
62
with Switch;   use Switch;
63
with Switch.M; use Switch.M;
64
with Targparm; use Targparm;
65
with Table;
66
with Tempdir;
67
with Types;    use Types;
68
 
69
with Ada.Exceptions;            use Ada.Exceptions;
70
with Ada.Command_Line;          use Ada.Command_Line;
71
 
72
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
73
with GNAT.Dynamic_HTables;      use GNAT.Dynamic_HTables;
74
with GNAT.Case_Util;            use GNAT.Case_Util;
75
with GNAT.OS_Lib;               use GNAT.OS_Lib;
76
 
77
package body Make is
78
 
79
   use ASCII;
80
   --  Make control characters visible
81
 
82
   Standard_Library_Package_Body_Name : constant String := "s-stalib.adb";
83
   --  Every program depends on this package, that must then be checked,
84
   --  especially when -f and -a are used.
85
 
86
   procedure Kill (Pid : Process_Id; Sig_Num : Integer; Close : Integer);
87
   pragma Import (C, Kill, "__gnat_kill");
88
   --  Called by Sigint_Intercepted to kill all spawned compilation processes
89
 
90
   type Sigint_Handler is access procedure;
91
   pragma Convention (C, Sigint_Handler);
92
 
93
   procedure Install_Int_Handler (Handler : Sigint_Handler);
94
   pragma Import (C, Install_Int_Handler, "__gnat_install_int_handler");
95
   --  Called by Gnatmake to install the SIGINT handler below
96
 
97
   procedure Sigint_Intercepted;
98
   pragma Convention (C, Sigint_Intercepted);
99
   --  Called when the program is interrupted by Ctrl-C to delete the
100
   --  temporary mapping files and configuration pragmas files.
101
 
102
   No_Mapping_File : constant Natural := 0;
103
 
104
   type Compilation_Data is record
105
      Pid              : Process_Id;
106
      Full_Source_File : File_Name_Type;
107
      Lib_File         : File_Name_Type;
108
      Source_Unit      : Unit_Name_Type;
109
      Full_Lib_File    : File_Name_Type;
110
      Lib_File_Attr    : aliased File_Attributes;
111
      Mapping_File     : Natural := No_Mapping_File;
112
      Project          : Project_Id := No_Project;
113
   end record;
114
   --  Data recorded for each compilation process spawned
115
 
116
   No_Compilation_Data : constant Compilation_Data :=
117
     (Invalid_Pid, No_File, No_File, No_Unit_Name, No_File, Unknown_Attributes,
118
      No_Mapping_File, No_Project);
119
 
120
   type Comp_Data_Arr is array (Positive range <>) of Compilation_Data;
121
   type Comp_Data_Ptr is access Comp_Data_Arr;
122
   Running_Compile : Comp_Data_Ptr;
123
   --  Used to save information about outstanding compilations
124
 
125
   Outstanding_Compiles : Natural := 0;
126
   --  Current number of outstanding compiles
127
 
128
   -------------------------
129
   -- Note on terminology --
130
   -------------------------
131
 
132
   --  In this program, we use the phrase "termination" of a file name to refer
133
   --  to the suffix that appears after the unit name portion. Very often this
134
   --  is simply the extension, but in some cases, the sequence may be more
135
   --  complex, for example in main.1.ada, the termination in this name is
136
   --  ".1.ada" and in main_.ada the termination is "_.ada".
137
 
138
   -------------------------------------
139
   -- Queue (Q) Manipulation Routines --
140
   -------------------------------------
141
 
142
   --  The Q is used in Compile_Sources below. Its implementation uses the GNAT
143
   --  generic package Table (basically an extensible array). Q_Front points to
144
   --  the first valid element in the Q, whereas Q.First is the first element
145
   --  ever enqueued, while Q.Last - 1 is the last element in the Q.
146
   --
147
   --        +---+--------------+---+---+---+-----------+---+--------
148
   --    Q   |   |  ........    |   |   |   | .......   |   |
149
   --        +---+--------------+---+---+---+-----------+---+--------
150
   --          ^                  ^                       ^
151
   --       Q.First             Q_Front               Q.Last-1
152
   --
153
   --  The elements comprised between Q.First and Q_Front-1 are the elements
154
   --  that have been enqueued and then dequeued, while the elements between
155
   --  Q_Front and Q.Last-1 are the elements currently in the Q. When the Q
156
   --  is initialized Q_Front = Q.First = Q.Last. After Compile_Sources has
157
   --  terminated its execution, Q_Front = Q.Last and the elements contained
158
   --  between Q.First and Q.Last-1 are those that were explored and thus
159
   --  marked by Compile_Sources. Whenever the Q is reinitialized, the elements
160
   --  between Q.First and Q.Last-1 are unmarked.
161
 
162
   procedure Init_Q;
163
   --  Must be called to (re)initialize the Q
164
 
165
   procedure Insert_Q
166
     (Source_File : File_Name_Type;
167
      Source_Unit : Unit_Name_Type := No_Unit_Name;
168
      Index       : Int            := 0);
169
   --  Inserts Source_File at the end of Q. Provide Source_Unit when possible
170
   --  for external use (gnatdist). Provide index for multi-unit sources.
171
 
172
   function Empty_Q return Boolean;
173
   --  Returns True if Q is empty
174
 
175
   procedure Extract_From_Q
176
     (Source_File  : out File_Name_Type;
177
      Source_Unit  : out Unit_Name_Type;
178
      Source_Index : out Int);
179
   --  Extracts the first element from the Q
180
 
181
   procedure Insert_Project_Sources
182
     (The_Project  : Project_Id;
183
      All_Projects : Boolean;
184
      Into_Q       : Boolean);
185
   --  If Into_Q is True, insert all sources of the project file(s) that are
186
   --  not already marked into the Q. If Into_Q is False, call Osint.Add_File
187
   --  for the first source, then insert all other sources that are not already
188
   --  marked into the Q. If All_Projects is True, all sources of all projects
189
   --  are concerned; otherwise, only sources of The_Project are concerned,
190
   --  including, if The_Project is an extending project, sources inherited
191
   --  from projects being extended.
192
 
193
   First_Q_Initialization : Boolean := True;
194
   --  Will be set to false after Init_Q has been called once
195
 
196
   Q_Front : Natural;
197
   --  Points to the first valid element in the Q
198
 
199
   Unique_Compile : Boolean := False;
200
   --  Set to True if -u or -U or a project file with no main is used
201
 
202
   Unique_Compile_All_Projects : Boolean := False;
203
   --  Set to True if -U is used
204
 
205
   RTS_Specified : String_Access := null;
206
   --  Used to detect multiple --RTS= switches
207
 
208
   N_M_Switch : Natural := 0;
209
   --  Used to count -mxxx switches that can affect multilib
210
 
211
   type Q_Record is record
212
      File  : File_Name_Type;
213
      Unit  : Unit_Name_Type;
214
      Index : Int;
215
   end record;
216
   --  File is the name of the file to compile. Unit is for gnatdist
217
   --  use in order to easily get the unit name of a file to compile
218
   --  when its name is krunched or declared in gnat.adc. Index, when not 0,
219
   --  is the index of the unit in a multi-unit source.
220
 
221
   package Q is new Table.Table (
222
     Table_Component_Type => Q_Record,
223
     Table_Index_Type     => Natural,
224
     Table_Low_Bound      => 0,
225
     Table_Initial        => 4000,
226
     Table_Increment      => 100,
227
     Table_Name           => "Make.Q");
228
   --  This is the actual Q
229
 
230
   --  The 3 following packages are used to store gcc, gnatbind and gnatlink
231
   --  switches found in the project files.
232
 
233
   package Gcc_Switches is new Table.Table (
234
     Table_Component_Type => String_Access,
235
     Table_Index_Type     => Integer,
236
     Table_Low_Bound      => 1,
237
     Table_Initial        => 20,
238
     Table_Increment      => 100,
239
     Table_Name           => "Make.Gcc_Switches");
240
 
241
   package Binder_Switches is new Table.Table (
242
     Table_Component_Type => String_Access,
243
     Table_Index_Type     => Integer,
244
     Table_Low_Bound      => 1,
245
     Table_Initial        => 20,
246
     Table_Increment      => 100,
247
     Table_Name           => "Make.Binder_Switches");
248
 
249
   package Linker_Switches is new Table.Table (
250
     Table_Component_Type => String_Access,
251
     Table_Index_Type     => Integer,
252
     Table_Low_Bound      => 1,
253
     Table_Initial        => 20,
254
     Table_Increment      => 100,
255
     Table_Name           => "Make.Linker_Switches");
256
 
257
   --  The following instantiations and variables are necessary to save what
258
   --  is found on the command line, in case there is a project file specified.
259
 
260
   package Saved_Gcc_Switches is new Table.Table (
261
     Table_Component_Type => String_Access,
262
     Table_Index_Type     => Integer,
263
     Table_Low_Bound      => 1,
264
     Table_Initial        => 20,
265
     Table_Increment      => 100,
266
     Table_Name           => "Make.Saved_Gcc_Switches");
267
 
268
   package Saved_Binder_Switches is new Table.Table (
269
     Table_Component_Type => String_Access,
270
     Table_Index_Type     => Integer,
271
     Table_Low_Bound      => 1,
272
     Table_Initial        => 20,
273
     Table_Increment      => 100,
274
     Table_Name           => "Make.Saved_Binder_Switches");
275
 
276
   package Saved_Linker_Switches is new Table.Table
277
     (Table_Component_Type => String_Access,
278
      Table_Index_Type     => Integer,
279
      Table_Low_Bound      => 1,
280
      Table_Initial        => 20,
281
      Table_Increment      => 100,
282
      Table_Name           => "Make.Saved_Linker_Switches");
283
 
284
   package Switches_To_Check is new Table.Table (
285
     Table_Component_Type => String_Access,
286
     Table_Index_Type     => Integer,
287
     Table_Low_Bound      => 1,
288
     Table_Initial        => 20,
289
     Table_Increment      => 100,
290
     Table_Name           => "Make.Switches_To_Check");
291
 
292
   package Library_Paths is new Table.Table (
293
     Table_Component_Type => String_Access,
294
     Table_Index_Type     => Integer,
295
     Table_Low_Bound      => 1,
296
     Table_Initial        => 20,
297
     Table_Increment      => 100,
298
     Table_Name           => "Make.Library_Paths");
299
 
300
   package Failed_Links is new Table.Table (
301
     Table_Component_Type => File_Name_Type,
302
     Table_Index_Type     => Integer,
303
     Table_Low_Bound      => 1,
304
     Table_Initial        => 10,
305
     Table_Increment      => 100,
306
     Table_Name           => "Make.Failed_Links");
307
 
308
   package Successful_Links is new Table.Table (
309
     Table_Component_Type => File_Name_Type,
310
     Table_Index_Type     => Integer,
311
     Table_Low_Bound      => 1,
312
     Table_Initial        => 10,
313
     Table_Increment      => 100,
314
     Table_Name           => "Make.Successful_Links");
315
 
316
   package Library_Projs is new Table.Table (
317
     Table_Component_Type => Project_Id,
318
     Table_Index_Type     => Integer,
319
     Table_Low_Bound      => 1,
320
     Table_Initial        => 10,
321
     Table_Increment      => 100,
322
     Table_Name           => "Make.Library_Projs");
323
 
324
   --  Two variables to keep the last binder and linker switch index in tables
325
   --  Binder_Switches and Linker_Switches, before adding switches from the
326
   --  project file (if any) and switches from the command line (if any).
327
 
328
   Last_Binder_Switch : Integer := 0;
329
   Last_Linker_Switch : Integer := 0;
330
 
331
   Normalized_Switches : Argument_List_Access := new Argument_List (1 .. 10);
332
   Last_Norm_Switch    : Natural := 0;
333
 
334
   Saved_Maximum_Processes : Natural := 0;
335
 
336
   Gnatmake_Switch_Found : Boolean;
337
   --  Set by Scan_Make_Arg. True when the switch is a gnatmake switch.
338
   --  Tested by Add_Switches when switches in package Builder must all be
339
   --  gnatmake switches.
340
 
341
   Switch_May_Be_Passed_To_The_Compiler : Boolean;
342
   --  Set by Add_Switches and Switches_Of. True when unrecognized switches
343
   --  are passed to the Ada compiler.
344
 
345
   type Arg_List_Ref is access Argument_List;
346
   The_Saved_Gcc_Switches : Arg_List_Ref;
347
 
348
   Project_File_Name : String_Access  := null;
349
   --  The path name of the main project file, if any
350
 
351
   Project_File_Name_Present : Boolean := False;
352
   --  True when -P is used with a space between -P and the project file name
353
 
354
   Current_Verbosity : Prj.Verbosity  := Prj.Default;
355
   --  Verbosity to parse the project files
356
 
357
   Main_Project : Prj.Project_Id := No_Project;
358
   --  The project id of the main project file, if any
359
 
360
   Project_Of_Current_Object_Directory : Project_Id := No_Project;
361
   --  The object directory of the project for the last compilation. Avoid
362
   --  calling Change_Dir if the current working directory is already this
363
   --  directory.
364
 
365
   --  Packages of project files where unknown attributes are errors
366
 
367
   Naming_String   : aliased String := "naming";
368
   Builder_String  : aliased String := "builder";
369
   Compiler_String : aliased String := "compiler";
370
   Binder_String   : aliased String := "binder";
371
   Linker_String   : aliased String := "linker";
372
 
373
   Gnatmake_Packages : aliased String_List :=
374
     (Naming_String   'Access,
375
      Builder_String  'Access,
376
      Compiler_String 'Access,
377
      Binder_String   'Access,
378
      Linker_String   'Access);
379
 
380
   Packages_To_Check_By_Gnatmake : constant String_List_Access :=
381
     Gnatmake_Packages'Access;
382
 
383
   procedure Add_Library_Search_Dir
384
     (Path            : String;
385
      On_Command_Line : Boolean);
386
   --  Call Add_Lib_Search_Dir with an absolute directory path. If Path is
387
   --  relative path, when On_Command_Line is True, it is relative to the
388
   --  current working directory. When On_Command_Line is False, it is relative
389
   --  to the project directory of the main project.
390
 
391
   procedure Add_Source_Search_Dir
392
     (Path            : String;
393
      On_Command_Line : Boolean);
394
   --  Call Add_Src_Search_Dir with an absolute directory path. If Path is a
395
   --  relative path, when On_Command_Line is True, it is relative to the
396
   --  current working directory. When On_Command_Line is False, it is relative
397
   --  to the project directory of the main project.
398
 
399
   procedure Add_Source_Dir (N : String);
400
   --  Call Add_Src_Search_Dir (output one line when in verbose mode)
401
 
402
   procedure Add_Source_Directories is
403
     new Prj.Env.For_All_Source_Dirs (Action => Add_Source_Dir);
404
 
405
   procedure Add_Object_Dir (N : String);
406
   --  Call Add_Lib_Search_Dir (output one line when in verbose mode)
407
 
408
   procedure Add_Object_Directories is
409
     new Prj.Env.For_All_Object_Dirs (Action => Add_Object_Dir);
410
 
411
   procedure Change_To_Object_Directory (Project : Project_Id);
412
   --  Change to the object directory of project Project, if this is not
413
   --  already the current working directory.
414
 
415
   type Bad_Compilation_Info is record
416
      File  : File_Name_Type;
417
      Unit  : Unit_Name_Type;
418
      Found : Boolean;
419
   end record;
420
   --  File is the name of the file for which a compilation failed. Unit is for
421
   --  gnatdist use in order to easily get the unit name of a file when its
422
   --  name is krunched or declared in gnat.adc. Found is False if the
423
   --  compilation failed because the file could not be found.
424
 
425
   package Bad_Compilation is new Table.Table (
426
     Table_Component_Type => Bad_Compilation_Info,
427
     Table_Index_Type     => Natural,
428
     Table_Low_Bound      => 1,
429
     Table_Initial        => 20,
430
     Table_Increment      => 100,
431
     Table_Name           => "Make.Bad_Compilation");
432
   --  Full name of all the source files for which compilation fails
433
 
434
   Do_Compile_Step : Boolean := True;
435
   Do_Bind_Step    : Boolean := True;
436
   Do_Link_Step    : Boolean := True;
437
   --  Flags to indicate what step should be executed. Can be set to False
438
   --  with the switches -c, -b and -l. These flags are reset to True for
439
   --  each invocation of procedure Gnatmake.
440
 
441
   Shared_String           : aliased String := "-shared";
442
   Force_Elab_Flags_String : aliased String := "-F";
443
 
444
   No_Shared_Switch : aliased Argument_List := (1 .. 0 => null);
445
   Shared_Switch    : aliased Argument_List := (1 => Shared_String'Access);
446
   Bind_Shared      : Argument_List_Access := No_Shared_Switch'Access;
447
   --  Switch to added in front of gnatbind switches. By default no switch is
448
   --  added. Switch "-shared" is added if there is a non-static Library
449
   --  Project File.
450
 
451
   Shared_Libgcc : aliased String := "-shared-libgcc";
452
 
453
   No_Shared_Libgcc_Switch : aliased Argument_List := (1 .. 0 => null);
454
   Shared_Libgcc_Switch    : aliased Argument_List :=
455
                               (1 => Shared_Libgcc'Access);
456
   Link_With_Shared_Libgcc : Argument_List_Access :=
457
                               No_Shared_Libgcc_Switch'Access;
458
 
459
   procedure Make_Failed (S : String);
460
   --  Delete all temp files created by Gnatmake and call Osint.Fail, with the
461
   --  parameter S (see osint.ads). This is called from the Prj hierarchy and
462
   --  the MLib hierarchy.
463
 
464
   --------------------------
465
   -- Obsolete Executables --
466
   --------------------------
467
 
468
   Executable_Obsolete : Boolean := False;
469
   --  Executable_Obsolete is initially set to False for each executable,
470
   --  and is set to True whenever one of the source of the executable is
471
   --  compiled, or has already been compiled for another executable.
472
 
473
   Max_Header : constant := 200;
474
   --  This needs a proper comment, it used to say "arbitrary"
475
   --  that's not an adequate comment ???
476
 
477
   type Header_Num is range 1 .. Max_Header;
478
   --  Header_Num for the hash table Obsoleted below
479
 
480
   function Hash (F : File_Name_Type) return Header_Num;
481
   --  Hash function for the hash table Obsoleted below
482
 
483
   package Obsoleted is new System.HTable.Simple_HTable
484
     (Header_Num => Header_Num,
485
      Element    => Boolean,
486
      No_Element => False,
487
      Key        => File_Name_Type,
488
      Hash       => Hash,
489
      Equal      => "=");
490
   --  A hash table to keep all files that have been compiled, to detect
491
   --  if an executable is up to date or not.
492
 
493
   procedure Enter_Into_Obsoleted (F : File_Name_Type);
494
   --  Enter a file name, without directory information, into the hash table
495
   --  Obsoleted.
496
 
497
   function Is_In_Obsoleted (F : File_Name_Type) return Boolean;
498
   --  Check if a file name, without directory information, has already been
499
   --  entered into the hash table Obsoleted.
500
 
501
   type Dependency is record
502
      This       : File_Name_Type;
503
      Depends_On : File_Name_Type;
504
   end record;
505
   --  Components of table Dependencies below
506
 
507
   package Dependencies is new Table.Table (
508
     Table_Component_Type => Dependency,
509
     Table_Index_Type     => Integer,
510
     Table_Low_Bound      => 1,
511
     Table_Initial        => 20,
512
     Table_Increment      => 100,
513
     Table_Name           => "Make.Dependencies");
514
   --  A table to keep dependencies, to be able to decide if an executable
515
   --  is obsolete. More explanation needed ???
516
 
517
--     procedure Add_Dependency (S : File_Name_Type; On : File_Name_Type);
518
--     --  Add one entry in table Dependencies
519
 
520
   ----------------------------
521
   -- Arguments and Switches --
522
   ----------------------------
523
 
524
   Arguments : Argument_List_Access;
525
   --  Used to gather the arguments for invocation of the compiler
526
 
527
   Last_Argument : Natural := 0;
528
   --  Last index of arguments in Arguments above
529
 
530
   Arguments_Project : Project_Id;
531
   --  Project id, if any, of the source to be compiled
532
 
533
   Arguments_Path_Name : Path_Name_Type;
534
   --  Full path of the source to be compiled, when Arguments_Project is not
535
   --  No_Project.
536
 
537
   Dummy_Switch : constant String_Access := new String'("- ");
538
   --  Used to initialized Prev_Switch in procedure Check
539
 
540
   procedure Add_Arguments (Args : Argument_List);
541
   --  Add arguments to global variable Arguments, increasing its size
542
   --  if necessary and adjusting Last_Argument.
543
 
544
   function Configuration_Pragmas_Switch
545
     (For_Project : Project_Id) return Argument_List;
546
   --  Return an argument list of one element, if there is a configuration
547
   --  pragmas file to be specified for For_Project,
548
   --  otherwise return an empty argument list.
549
 
550
   -------------------
551
   -- Misc Routines --
552
   -------------------
553
 
554
   procedure List_Depend;
555
   --  Prints to standard output the list of object dependencies. This list
556
   --  can be used directly in a Makefile. A call to Compile_Sources must
557
   --  precede the call to List_Depend. Also because this routine uses the
558
   --  ALI files that were originally loaded and scanned by Compile_Sources,
559
   --  no additional ALI files should be scanned between the two calls (i.e.
560
   --  between the call to Compile_Sources and List_Depend.)
561
 
562
   procedure List_Bad_Compilations;
563
   --  Prints out the list of all files for which the compilation failed
564
 
565
   Usage_Needed : Boolean := True;
566
   --  Flag used to make sure Makeusg is call at most once
567
 
568
   procedure Usage;
569
   --  Call Makeusg, if Usage_Needed is True.
570
   --  Set Usage_Needed to False.
571
 
572
   procedure Debug_Msg (S : String; N : Name_Id);
573
   procedure Debug_Msg (S : String; N : File_Name_Type);
574
   procedure Debug_Msg (S : String; N : Unit_Name_Type);
575
   --  If Debug.Debug_Flag_W is set outputs string S followed by name N
576
 
577
   procedure Recursive_Compute_Depth (Project : Project_Id);
578
   --  Compute depth of Project and of the projects it depends on
579
 
580
   -----------------------
581
   -- Gnatmake Routines --
582
   -----------------------
583
 
584
   subtype Lib_Mark_Type is Byte;
585
   --  Used in Mark_Directory
586
 
587
   Ada_Lib_Dir : constant Lib_Mark_Type := 1;
588
   --  Used to mark a directory as a GNAT lib dir
589
 
590
   --  Note that the notion of GNAT lib dir is no longer used. The code related
591
   --  to it has not been removed to give an idea on how to use the directory
592
   --  prefix marking mechanism.
593
 
594
   --  An Ada library directory is a directory containing ali and object files
595
   --  but no source files for the bodies (the specs can be in the same or some
596
   --  other directory). These directories are specified in the Gnatmake
597
   --  command line with the switch "-Adir" (to specify the spec location -Idir
598
   --  cab be used). Gnatmake skips the missing sources whose ali are in Ada
599
   --  library directories. For an explanation of why Gnatmake behaves that
600
   --  way, see the spec of Make.Compile_Sources. The directory lookup penalty
601
   --  is incurred every single time this routine is called.
602
 
603
   procedure Check_Steps;
604
   --  Check what steps (Compile, Bind, Link) must be executed.
605
   --  Set the step flags accordingly.
606
 
607
   function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean;
608
   --  Get directory prefix of this file and get lib mark stored in name
609
   --  table for this directory. Then check if an Ada lib mark has been set.
610
 
611
   procedure Mark_Directory
612
     (Dir             : String;
613
      Mark            : Lib_Mark_Type;
614
      On_Command_Line : Boolean);
615
   --  Store the absolute path from Dir in name table and set lib mark as name
616
   --  info to identify Ada libraries.
617
   --
618
   --  If Dir is a relative path, when On_Command_Line is True, it is relative
619
   --  to the current working directory; when On_Command_Line is False, it is
620
   --  relative to the project directory of the main project.
621
 
622
   Output_Is_Object : Boolean := True;
623
   --  Set to False when using a switch -S for the compiler
624
 
625
   procedure Check_For_S_Switch;
626
   --  Set Output_Is_Object to False when the -S switch is used for the
627
   --  compiler.
628
 
629
   function Switches_Of
630
     (Source_File      : File_Name_Type;
631
      Source_File_Name : String;
632
      Source_Index     : Int;
633
      Project          : Project_Id;
634
      In_Package       : Package_Id;
635
      Allow_ALI        : Boolean) return Variable_Value;
636
   --  Return the switches for the source file in the specified package of a
637
   --  project file. If the Source_File ends with a standard GNAT extension
638
   --  (".ads" or ".adb"), try first the full name, then the name without the
639
   --  extension, then, if Allow_ALI is True, the name with the extension
640
   --  ".ali". If there is no switches for either names, try first Switches
641
   --  (others) then the default switches for Ada. If all failed, return
642
   --  No_Variable_Value.
643
 
644
   function Is_In_Object_Directory
645
     (Source_File   : File_Name_Type;
646
      Full_Lib_File : File_Name_Type) return Boolean;
647
   --  Check if, when using a project file, the ALI file is in the project
648
   --  directory of the ultimate extending project. If it is not, we ignore
649
   --  the fact that this ALI file is read-only.
650
 
651
   procedure Process_Multilib (Project_Node_Tree : Project_Node_Tree_Ref);
652
   --  Add appropriate --RTS argument to handle multilib
653
 
654
   ----------------------------------------------------
655
   -- Compiler, Binder & Linker Data and Subprograms --
656
   ----------------------------------------------------
657
 
658
   Gcc      : String_Access := Program_Name ("gcc", "gnatmake");
659
   Gnatbind : String_Access := Program_Name ("gnatbind", "gnatmake");
660
   Gnatlink : String_Access := Program_Name ("gnatlink", "gnatmake");
661
   --  Default compiler, binder, linker programs
662
 
663
   Saved_Gcc      : String_Access := null;
664
   Saved_Gnatbind : String_Access := null;
665
   Saved_Gnatlink : String_Access := null;
666
   --  Given by the command line. Will be used, if non null
667
 
668
   Gcc_Path      : String_Access :=
669
                       GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
670
   Gnatbind_Path : String_Access :=
671
                       GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
672
   Gnatlink_Path : String_Access :=
673
                       GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
674
   --  Path for compiler, binder, linker programs, defaulted now for gnatdist.
675
   --  Changed later if overridden on command line.
676
 
677
   Comp_Flag         : constant String_Access := new String'("-c");
678
   Output_Flag       : constant String_Access := new String'("-o");
679
   Ada_Flag_1        : constant String_Access := new String'("-x");
680
   Ada_Flag_2        : constant String_Access := new String'("ada");
681
   No_gnat_adc       : constant String_Access := new String'("-gnatA");
682
   GNAT_Flag         : constant String_Access := new String'("-gnatpg");
683
   Do_Not_Check_Flag : constant String_Access := new String'("-x");
684
 
685
   Object_Suffix : constant String := Get_Target_Object_Suffix.all;
686
 
687
   Syntax_Only : Boolean := False;
688
   --  Set to True when compiling with -gnats
689
 
690
   Display_Executed_Programs : Boolean := True;
691
   --  Set to True if name of commands should be output on stderr (or on stdout
692
   --  if the Commands_To_Stdout flag was set by use of the -eS switch).
693
 
694
   Output_File_Name_Seen : Boolean := False;
695
   --  Set to True after having scanned the file_name for
696
   --  switch "-o file_name"
697
 
698
   Object_Directory_Seen : Boolean := False;
699
   --  Set to True after having scanned the object directory for
700
   --  switch "-D obj_dir".
701
 
702
   Object_Directory_Path : String_Access := null;
703
   --  The path name of the object directory, set with switch -D
704
 
705
   type Make_Program_Type is (None, Compiler, Binder, Linker);
706
 
707
   Program_Args : Make_Program_Type := None;
708
   --  Used to indicate if we are scanning gnatmake, gcc, gnatbind, or gnatbind
709
   --  options within the gnatmake command line. Used in Scan_Make_Arg only,
710
   --  but must be global since value preserved from one call to another.
711
 
712
   Temporary_Config_File : Boolean := False;
713
   --  Set to True when there is a temporary config file used for a project
714
   --  file, to avoid displaying the -gnatec switch for a temporary file.
715
 
716
   procedure Add_Switches
717
     (The_Package                      : Package_Id;
718
      File_Name                        : String;
719
      Index                            : Int;
720
      Program                          : Make_Program_Type;
721
      Unknown_Switches_To_The_Compiler : Boolean := True;
722
      Project_Node_Tree                : Project_Node_Tree_Ref);
723
   procedure Add_Switch
724
     (S             : String_Access;
725
      Program       : Make_Program_Type;
726
      Append_Switch : Boolean := True;
727
      And_Save      : Boolean := True);
728
   procedure Add_Switch
729
     (S             : String;
730
      Program       : Make_Program_Type;
731
      Append_Switch : Boolean := True;
732
      And_Save      : Boolean := True);
733
   --  Make invokes one of three programs (the compiler, the binder or the
734
   --  linker). For the sake of convenience, some program specific switches
735
   --  can be passed directly on the gnatmake command line. This procedure
736
   --  records these switches so that gnatmake can pass them to the right
737
   --  program.  S is the switch to be added at the end of the command line
738
   --  for Program if Append_Switch is True. If Append_Switch is False S is
739
   --  added at the beginning of the command line.
740
 
741
   procedure Check
742
     (Source_File    : File_Name_Type;
743
      Source_Index   : Int;
744
      Is_Main_Source : Boolean;
745
      The_Args       : Argument_List;
746
      Lib_File       : File_Name_Type;
747
      Full_Lib_File  : File_Name_Type;
748
      Lib_File_Attr  : access File_Attributes;
749
      Read_Only      : Boolean;
750
      ALI            : out ALI_Id;
751
      O_File         : out File_Name_Type;
752
      O_Stamp        : out Time_Stamp_Type);
753
   --  Determines whether the library file Lib_File is up-to-date or not. The
754
   --  full name (with path information) of the object file corresponding to
755
   --  Lib_File is returned in O_File. Its time stamp is saved in O_Stamp.
756
   --  ALI is the ALI_Id corresponding to Lib_File. If Lib_File in not
757
   --  up-to-date, then the corresponding source file needs to be recompiled.
758
   --  In this case ALI = No_ALI_Id.
759
   --  Full_Lib_File must be the result of calling Osint.Full_Lib_File_Name on
760
   --  Lib_File. Precomputing it saves system calls. Lib_File_Attr is the
761
   --  initialized attributes of that file, which is also used to save on
762
   --  system calls (it can safely be initialized to Unknown_Attributes).
763
 
764
   procedure Check_Linker_Options
765
     (E_Stamp : Time_Stamp_Type;
766
      O_File  : out File_Name_Type;
767
      O_Stamp : out Time_Stamp_Type);
768
   --  Checks all linker options for linker files that are newer
769
   --  than E_Stamp. If such objects are found, the youngest object
770
   --  is returned in O_File and its stamp in O_Stamp.
771
   --
772
   --  If no obsolete linker files were found, the first missing
773
   --  linker file is returned in O_File and O_Stamp is empty.
774
   --  Otherwise O_File is No_File.
775
 
776
   procedure Collect_Arguments
777
     (Source_File    : File_Name_Type;
778
      Source_Index   : Int;
779
      Is_Main_Source : Boolean;
780
      Args           : Argument_List);
781
   --  Collect all arguments for a source to be compiled, including those
782
   --  that come from a project file.
783
 
784
   procedure Display (Program : String; Args : Argument_List);
785
   --  Displays Program followed by the arguments in Args if variable
786
   --  Display_Executed_Programs is set. The lower bound of Args must be 1.
787
 
788
   procedure Report_Compilation_Failed;
789
   --  Delete all temporary files and fail graciously
790
 
791
   -----------------
792
   --  Mapping files
793
   -----------------
794
 
795
   type Temp_Path_Names is array (Positive range <>) of Path_Name_Type;
796
   type Temp_Path_Ptr is access Temp_Path_Names;
797
 
798
   type Free_File_Indices is array (Positive range <>) of Positive;
799
   type Free_Indices_Ptr is access Free_File_Indices;
800
 
801
   type Project_Compilation_Data is record
802
      Mapping_File_Names : Temp_Path_Ptr;
803
      --  The name ids of the temporary mapping files used. This is indexed
804
      --  on the maximum number of compilation processes we will be spawning
805
      --  (-j parameter)
806
 
807
      Last_Mapping_File_Names : Natural;
808
      --  Index of the last mapping file created for this project
809
 
810
      Free_Mapping_File_Indices : Free_Indices_Ptr;
811
      --  Indices in Mapping_File_Names of the mapping file names that can be
812
      --  reused for subsequent compilations.
813
 
814
      Last_Free_Indices : Natural;
815
      --  Number of mapping files that can be reused
816
   end record;
817
   --  Information necessary when compiling a project
818
 
819
   type Project_Compilation_Access is access Project_Compilation_Data;
820
 
821
   package Project_Compilation_Htable is new Simple_HTable
822
     (Header_Num => Prj.Header_Num,
823
      Element    => Project_Compilation_Access,
824
      No_Element => null,
825
      Key        => Project_Id,
826
      Hash       => Prj.Hash,
827
      Equal      => "=");
828
 
829
   Project_Compilation : Project_Compilation_Htable.Instance;
830
 
831
   Gnatmake_Mapping_File : String_Access := null;
832
   --  The path name of a mapping file specified by switch -C=
833
 
834
   procedure Init_Mapping_File
835
     (Project    : Project_Id;
836
      Data       : in out Project_Compilation_Data;
837
      File_Index : in out Natural);
838
   --  Create a new temporary mapping file, and fill it with the project file
839
   --  mappings, when using project file(s). The out parameter File_Index is
840
   --  the index to the name of the file in the array The_Mapping_File_Names.
841
 
842
   procedure Delete_Temp_Config_Files;
843
   --  Delete all temporary config files. Must not be called if Debug_Flag_N
844
   --  is False.
845
 
846
   procedure Delete_All_Temp_Files;
847
   --  Delete all temp files (config files, mapping files, path files), unless
848
   --  Debug_Flag_N is True (in which case all temp files are left for user
849
   --  examination).
850
 
851
   -------------------------------------------------
852
   -- Subprogram declarations moved from the spec --
853
   -------------------------------------------------
854
 
855
   procedure Bind (ALI_File : File_Name_Type; Args : Argument_List);
856
   --  Binds ALI_File. Args are the arguments to pass to the binder.
857
   --  Args must have a lower bound of 1.
858
 
859
   procedure Display_Commands (Display : Boolean := True);
860
   --  The default behavior of Make commands (Compile_Sources, Bind, Link)
861
   --  is to display them on stderr. This behavior can be changed repeatedly
862
   --  by invoking this procedure.
863
 
864
   --  If a compilation, bind or link failed one of the following 3 exceptions
865
   --  is raised. These need to be handled by the calling routines.
866
 
867
   procedure Compile_Sources
868
     (Main_Source           : File_Name_Type;
869
      Args                  : Argument_List;
870
      First_Compiled_File   : out File_Name_Type;
871
      Most_Recent_Obj_File  : out File_Name_Type;
872
      Most_Recent_Obj_Stamp : out Time_Stamp_Type;
873
      Main_Unit             : out Boolean;
874
      Compilation_Failures  : out Natural;
875
      Main_Index            : Int      := 0;
876
      Check_Readonly_Files  : Boolean  := False;
877
      Do_Not_Execute        : Boolean  := False;
878
      Force_Compilations    : Boolean  := False;
879
      Keep_Going            : Boolean  := False;
880
      In_Place_Mode         : Boolean  := False;
881
      Initialize_ALI_Data   : Boolean  := True;
882
      Max_Process           : Positive := 1);
883
   --  Compile_Sources will recursively compile all the sources needed by
884
   --  Main_Source. Before calling this routine make sure Namet has been
885
   --  initialized. This routine can be called repeatedly with different
886
   --  Main_Source file as long as all the source (-I flags), library
887
   --  (-B flags) and ada library (-A flags) search paths between calls are
888
   --  *exactly* the same. The default directory must also be the same.
889
   --
890
   --    Args contains the arguments to use during the compilations.
891
   --    The lower bound of Args must be 1.
892
   --
893
   --    First_Compiled_File is set to the name of the first file that is
894
   --    compiled or that needs to be compiled. This is set to No_Name if no
895
   --    compilations were needed.
896
   --
897
   --    Most_Recent_Obj_File is set to the full name of the most recent
898
   --    object file found when no compilations are needed, that is when
899
   --    First_Compiled_File is set to No_Name. When First_Compiled_File
900
   --    is set then Most_Recent_Obj_File is set to No_Name.
901
   --
902
   --    Most_Recent_Obj_Stamp is the time stamp of Most_Recent_Obj_File.
903
   --
904
   --    Main_Unit is set to True if Main_Source can be a main unit.
905
   --    If Do_Not_Execute is False and First_Compiled_File /= No_Name
906
   --    the value of Main_Unit is always False.
907
   --    Is this used any more??? It is certainly not used by gnatmake???
908
   --
909
   --    Compilation_Failures is a count of compilation failures. This count
910
   --    is used to extract compilation failure reports with Extract_Failure.
911
   --
912
   --    Main_Index, when not zero, is the index of the main unit in source
913
   --    file Main_Source which is a multi-unit source.
914
   --    Zero indicates that Main_Source is a single unit source file.
915
   --
916
   --    Check_Readonly_Files set it to True to compile source files
917
   --    which library files are read-only. When compiling GNAT predefined
918
   --    files the "-gnatg" flag is used.
919
   --
920
   --    Do_Not_Execute set it to True to find out the first source that
921
   --    needs to be recompiled, but without recompiling it. This file is
922
   --    saved in First_Compiled_File.
923
   --
924
   --    Force_Compilations forces all compilations no matter what but
925
   --    recompiles read-only files only if Check_Readonly_Files
926
   --    is set.
927
   --
928
   --    Keep_Going when True keep compiling even in the presence of
929
   --    compilation errors.
930
   --
931
   --    In_Place_Mode when True save library/object files in their object
932
   --    directory if they already exist; otherwise, in the source directory.
933
   --
934
   --    Initialize_ALI_Data set it to True when you want to initialize ALI
935
   --    data-structures. This is what you should do most of the time.
936
   --    (especially the first time around when you call this routine).
937
   --    This parameter is set to False to preserve previously recorded
938
   --    ALI file data.
939
   --
940
   --    Max_Process is the maximum number of processes that should be spawned
941
   --    to carry out compilations.
942
   --
943
   --  Flags in Package Opt Affecting Compile_Sources
944
   --  -----------------------------------------------
945
   --
946
   --    Check_Object_Consistency set it to False to omit all consistency
947
   --      checks between an .ali file and its corresponding object file.
948
   --      When this flag is set to true, every time an .ali is read,
949
   --      package Osint checks that the corresponding object file
950
   --      exists and is more recent than the .ali.
951
   --
952
   --  Use of Name Table Info
953
   --  ----------------------
954
   --
955
   --  All file names manipulated by Compile_Sources are entered into the
956
   --  Names table. The Byte field of a source file is used to mark it.
957
   --
958
   --  Calling Compile_Sources Several Times
959
   --  -------------------------------------
960
   --
961
   --  Upon return from Compile_Sources all the ALI data structures are left
962
   --  intact for further browsing. HOWEVER upon entry to this routine ALI
963
   --  data structures are re-initialized if parameter Initialize_ALI_Data
964
   --  above is set to true. Typically this is what you want the first time
965
   --  you call Compile_Sources. You should not load an ali file, call this
966
   --  routine with flag Initialize_ALI_Data set to True and then expect
967
   --  that ALI information to be around after the call. Note that the first
968
   --  time you call Compile_Sources you better set Initialize_ALI_Data to
969
   --  True unless you have called Initialize_ALI yourself.
970
   --
971
   --  Compile_Sources ALGORITHM : Compile_Sources (Main_Source)
972
   --  -------------------------
973
   --
974
   --  1. Insert Main_Source in a Queue (Q) and mark it.
975
   --
976
   --  2. Let unit.adb be the file at the head of the Q. If unit.adb is
977
   --     missing but its corresponding ali file is in an Ada library directory
978
   --     (see below) then, remove unit.adb from the Q and goto step 4.
979
   --     Otherwise, look at the files under the D (dependency) section of
980
   --     unit.ali. If unit.ali does not exist or some of the time stamps do
981
   --     not match, (re)compile unit.adb.
982
   --
983
   --     An Ada library directory is a directory containing Ada specs, ali
984
   --     and object files but no source files for the bodies. An Ada library
985
   --     directory is communicated to gnatmake by means of some switch so that
986
   --     gnatmake can skip the sources whole ali are in that directory.
987
   --     There are two reasons for skipping the sources in this case. Firstly,
988
   --     Ada libraries typically come without full sources but binding and
989
   --     linking against those libraries is still possible. Secondly, it would
990
   --     be very wasteful for gnatmake to systematically check the consistency
991
   --     of every external Ada library used in a program. The binder is
992
   --     already in charge of catching any potential inconsistencies.
993
   --
994
   --  3. Look into the W section of unit.ali and insert into the Q all
995
   --     unmarked source files. Mark all files newly inserted in the Q.
996
   --     Specifically, assuming that the W section looks like
997
   --
998
   --     W types%s               types.adb               types.ali
999
   --     W unchecked_deallocation%s
1000
   --     W xref_tab%s            xref_tab.adb            xref_tab.ali
1001
   --
1002
   --     Then xref_tab.adb and types.adb are inserted in the Q if they are not
1003
   --     already marked.
1004
   --     Note that there is no file listed under W unchecked_deallocation%s
1005
   --     so no generic body should ever be explicitly compiled (unless the
1006
   --     Main_Source at the start was a generic body).
1007
   --
1008
   --  4. Repeat steps 2 and 3 above until the Q is empty
1009
   --
1010
   --  Note that the above algorithm works because the units withed in
1011
   --  subunits are transitively included in the W section (with section) of
1012
   --  the main unit. Likewise the withed units in a generic body needed
1013
   --  during a compilation are also transitively included in the W section
1014
   --  of the originally compiled file.
1015
 
1016
   procedure Initialize (Project_Node_Tree : out Project_Node_Tree_Ref);
1017
   --  Performs default and package initialization. Therefore,
1018
   --  Compile_Sources can be called by an external unit.
1019
 
1020
   procedure Link
1021
     (ALI_File : File_Name_Type;
1022
      Args     : Argument_List;
1023
      Success  : out Boolean);
1024
   --  Links ALI_File. Args are the arguments to pass to the linker.
1025
   --  Args must have a lower bound of 1. Success indicates if the link
1026
   --  succeeded or not.
1027
 
1028
   procedure Scan_Make_Arg
1029
     (Project_Node_Tree : Project_Node_Tree_Ref;
1030
      Argv              : String;
1031
      And_Save          : Boolean);
1032
   --  Scan make arguments. Argv is a single argument to be processed.
1033
   --  Project_Node_Tree will be used to initialize external references. It
1034
   --  must have been initialized.
1035
 
1036
   -------------------
1037
   -- Add_Arguments --
1038
   -------------------
1039
 
1040
   procedure Add_Arguments (Args : Argument_List) is
1041
   begin
1042
      if Arguments = null then
1043
         Arguments := new Argument_List (1 .. Args'Length + 10);
1044
 
1045
      else
1046
         while Last_Argument + Args'Length > Arguments'Last loop
1047
            declare
1048
               New_Arguments : constant Argument_List_Access :=
1049
                                 new Argument_List (1 .. Arguments'Last * 2);
1050
            begin
1051
               New_Arguments (1 .. Last_Argument) :=
1052
                 Arguments (1 .. Last_Argument);
1053
               Arguments := New_Arguments;
1054
            end;
1055
         end loop;
1056
      end if;
1057
 
1058
      Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
1059
      Last_Argument := Last_Argument + Args'Length;
1060
   end Add_Arguments;
1061
 
1062
--     --------------------
1063
--     -- Add_Dependency --
1064
--     --------------------
1065
--
1066
--     procedure Add_Dependency (S : File_Name_Type; On : File_Name_Type) is
1067
--     begin
1068
--        Dependencies.Increment_Last;
1069
--        Dependencies.Table (Dependencies.Last) := (S, On);
1070
--     end Add_Dependency;
1071
 
1072
   ----------------------------
1073
   -- Add_Library_Search_Dir --
1074
   ----------------------------
1075
 
1076
   procedure Add_Library_Search_Dir
1077
     (Path            : String;
1078
      On_Command_Line : Boolean)
1079
   is
1080
   begin
1081
      if On_Command_Line then
1082
         Add_Lib_Search_Dir (Normalize_Pathname (Path));
1083
 
1084
      else
1085
         Get_Name_String (Main_Project.Directory.Display_Name);
1086
         Add_Lib_Search_Dir
1087
           (Normalize_Pathname (Path, Name_Buffer (1 .. Name_Len)));
1088
      end if;
1089
   end Add_Library_Search_Dir;
1090
 
1091
   --------------------
1092
   -- Add_Object_Dir --
1093
   --------------------
1094
 
1095
   procedure Add_Object_Dir (N : String) is
1096
   begin
1097
      Add_Lib_Search_Dir (N);
1098
 
1099
      if Verbose_Mode then
1100
         Write_Str ("Adding object directory """);
1101
         Write_Str (N);
1102
         Write_Str (""".");
1103
         Write_Eol;
1104
      end if;
1105
   end Add_Object_Dir;
1106
 
1107
   --------------------
1108
   -- Add_Source_Dir --
1109
   --------------------
1110
 
1111
   procedure Add_Source_Dir (N : String) is
1112
   begin
1113
      Add_Src_Search_Dir (N);
1114
 
1115
      if Verbose_Mode then
1116
         Write_Str ("Adding source directory """);
1117
         Write_Str (N);
1118
         Write_Str (""".");
1119
         Write_Eol;
1120
      end if;
1121
   end Add_Source_Dir;
1122
 
1123
   ---------------------------
1124
   -- Add_Source_Search_Dir --
1125
   ---------------------------
1126
 
1127
   procedure Add_Source_Search_Dir
1128
     (Path            : String;
1129
      On_Command_Line : Boolean)
1130
   is
1131
   begin
1132
      if On_Command_Line then
1133
         Add_Src_Search_Dir (Normalize_Pathname (Path));
1134
 
1135
      else
1136
         Get_Name_String (Main_Project.Directory.Display_Name);
1137
         Add_Src_Search_Dir
1138
           (Normalize_Pathname (Path, Name_Buffer (1 .. Name_Len)));
1139
      end if;
1140
   end Add_Source_Search_Dir;
1141
 
1142
   ----------------
1143
   -- Add_Switch --
1144
   ----------------
1145
 
1146
   procedure Add_Switch
1147
     (S             : String_Access;
1148
      Program       : Make_Program_Type;
1149
      Append_Switch : Boolean := True;
1150
      And_Save      : Boolean := True)
1151
   is
1152
      generic
1153
         with package T is new Table.Table (<>);
1154
      procedure Generic_Position (New_Position : out Integer);
1155
      --  Generic procedure that chooses a position for S in T at the
1156
      --  beginning or the end, depending on the boolean Append_Switch.
1157
      --  Calling this procedure may expand the table.
1158
 
1159
      ----------------------
1160
      -- Generic_Position --
1161
      ----------------------
1162
 
1163
      procedure Generic_Position (New_Position : out Integer) is
1164
      begin
1165
         T.Increment_Last;
1166
 
1167
         if Append_Switch then
1168
            New_Position := Integer (T.Last);
1169
         else
1170
            for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop
1171
               T.Table (J) := T.Table (T.Table_Index_Type'Pred (J));
1172
            end loop;
1173
 
1174
            New_Position := Integer (T.First);
1175
         end if;
1176
      end Generic_Position;
1177
 
1178
      procedure Gcc_Switches_Pos    is new Generic_Position (Gcc_Switches);
1179
      procedure Binder_Switches_Pos is new Generic_Position (Binder_Switches);
1180
      procedure Linker_Switches_Pos is new Generic_Position (Linker_Switches);
1181
 
1182
      procedure Saved_Gcc_Switches_Pos is new
1183
        Generic_Position (Saved_Gcc_Switches);
1184
 
1185
      procedure Saved_Binder_Switches_Pos is new
1186
        Generic_Position (Saved_Binder_Switches);
1187
 
1188
      procedure Saved_Linker_Switches_Pos is new
1189
        Generic_Position (Saved_Linker_Switches);
1190
 
1191
      New_Position : Integer;
1192
 
1193
   --  Start of processing for Add_Switch
1194
 
1195
   begin
1196
      if And_Save then
1197
         case Program is
1198
            when Compiler =>
1199
               Saved_Gcc_Switches_Pos (New_Position);
1200
               Saved_Gcc_Switches.Table (New_Position) := S;
1201
 
1202
            when Binder   =>
1203
               Saved_Binder_Switches_Pos (New_Position);
1204
               Saved_Binder_Switches.Table (New_Position) := S;
1205
 
1206
            when Linker   =>
1207
               Saved_Linker_Switches_Pos (New_Position);
1208
               Saved_Linker_Switches.Table (New_Position) := S;
1209
 
1210
            when None =>
1211
               raise Program_Error;
1212
         end case;
1213
 
1214
      else
1215
         case Program is
1216
            when Compiler =>
1217
               Gcc_Switches_Pos (New_Position);
1218
               Gcc_Switches.Table (New_Position) := S;
1219
 
1220
            when Binder   =>
1221
               Binder_Switches_Pos (New_Position);
1222
               Binder_Switches.Table (New_Position) := S;
1223
 
1224
            when Linker   =>
1225
               Linker_Switches_Pos (New_Position);
1226
               Linker_Switches.Table (New_Position) := S;
1227
 
1228
            when None =>
1229
               raise Program_Error;
1230
         end case;
1231
      end if;
1232
   end Add_Switch;
1233
 
1234
   procedure Add_Switch
1235
     (S             : String;
1236
      Program       : Make_Program_Type;
1237
      Append_Switch : Boolean := True;
1238
      And_Save      : Boolean := True)
1239
   is
1240
   begin
1241
      Add_Switch (S             => new String'(S),
1242
                  Program       => Program,
1243
                  Append_Switch => Append_Switch,
1244
                  And_Save      => And_Save);
1245
   end Add_Switch;
1246
 
1247
   ------------------
1248
   -- Add_Switches --
1249
   ------------------
1250
 
1251
   procedure Add_Switches
1252
     (The_Package                      : Package_Id;
1253
      File_Name                        : String;
1254
      Index                            : Int;
1255
      Program                          : Make_Program_Type;
1256
      Unknown_Switches_To_The_Compiler : Boolean := True;
1257
      Project_Node_Tree                : Project_Node_Tree_Ref)
1258
   is
1259
      Switches    : Variable_Value;
1260
      Switch_List : String_List_Id;
1261
      Element     : String_Element;
1262
 
1263
   begin
1264
      Switch_May_Be_Passed_To_The_Compiler :=
1265
        Unknown_Switches_To_The_Compiler;
1266
 
1267
      if File_Name'Length > 0 then
1268
         Name_Len := 0;
1269
         Add_Str_To_Name_Buffer (File_Name);
1270
         Switches :=
1271
           Switches_Of
1272
             (Source_File      => Name_Find,
1273
              Source_File_Name => File_Name,
1274
              Source_Index     => Index,
1275
              Project          => Main_Project,
1276
              In_Package       => The_Package,
1277
              Allow_ALI        => Program = Binder or else Program = Linker);
1278
 
1279
         if Switches.Kind = List then
1280
            Program_Args := Program;
1281
 
1282
            Switch_List := Switches.Values;
1283
            while Switch_List /= Nil_String loop
1284
               Element := Project_Tree.String_Elements.Table (Switch_List);
1285
               Get_Name_String (Element.Value);
1286
 
1287
               if Name_Len > 0 then
1288
                  declare
1289
                     Argv : constant String := Name_Buffer (1 .. Name_Len);
1290
                     --  We need a copy, because Name_Buffer may be modified
1291
 
1292
                  begin
1293
                     if Verbose_Mode then
1294
                        Write_Str ("   Adding ");
1295
                        Write_Line (Argv);
1296
                     end if;
1297
 
1298
                     Scan_Make_Arg
1299
                       (Project_Node_Tree, Argv, And_Save => False);
1300
 
1301
                     if not Gnatmake_Switch_Found
1302
                       and then not Switch_May_Be_Passed_To_The_Compiler
1303
                     then
1304
                        Errutil.Error_Msg
1305
                          ('"' & Argv &
1306
                           """ is not a gnatmake switch. Consider moving " &
1307
                           "it to Global_Compilation_Switches.",
1308
                           Element.Location);
1309
                        Errutil.Finalize;
1310
                        Make_Failed ("*** illegal switch """ & Argv & """");
1311
                     end if;
1312
                  end;
1313
               end if;
1314
 
1315
               Switch_List := Element.Next;
1316
            end loop;
1317
         end if;
1318
      end if;
1319
   end Add_Switches;
1320
 
1321
   ----------
1322
   -- Bind --
1323
   ----------
1324
 
1325
   procedure Bind (ALI_File : File_Name_Type; Args : Argument_List) is
1326
      Bind_Args : Argument_List (1 .. Args'Last + 2);
1327
      Bind_Last : Integer;
1328
      Success   : Boolean;
1329
 
1330
   begin
1331
      pragma Assert (Args'First = 1);
1332
 
1333
      --  Optimize the simple case where the gnatbind command line looks like
1334
      --     gnatbind -aO. -I- file.ali   --into->   gnatbind file.adb
1335
 
1336
      if Args'Length = 2
1337
        and then Args (Args'First).all = "-aO" & Normalized_CWD
1338
        and then Args (Args'Last).all = "-I-"
1339
        and then ALI_File = Strip_Directory (ALI_File)
1340
      then
1341
         Bind_Last := Args'First - 1;
1342
 
1343
      else
1344
         Bind_Last := Args'Last;
1345
         Bind_Args (Args'Range) := Args;
1346
      end if;
1347
 
1348
      --  It is completely pointless to re-check source file time stamps. This
1349
      --  has been done already by gnatmake
1350
 
1351
      Bind_Last := Bind_Last + 1;
1352
      Bind_Args (Bind_Last) := Do_Not_Check_Flag;
1353
 
1354
      Get_Name_String (ALI_File);
1355
 
1356
      Bind_Last := Bind_Last + 1;
1357
      Bind_Args (Bind_Last) := new String'(Name_Buffer (1 .. Name_Len));
1358
 
1359
      GNAT.OS_Lib.Normalize_Arguments (Bind_Args (Args'First .. Bind_Last));
1360
 
1361
      Display (Gnatbind.all, Bind_Args (Args'First .. Bind_Last));
1362
 
1363
      if Gnatbind_Path = null then
1364
         Make_Failed ("error, unable to locate " & Gnatbind.all);
1365
      end if;
1366
 
1367
      GNAT.OS_Lib.Spawn
1368
        (Gnatbind_Path.all, Bind_Args (Args'First .. Bind_Last), Success);
1369
 
1370
      if not Success then
1371
         Make_Failed ("*** bind failed.");
1372
      end if;
1373
   end Bind;
1374
 
1375
   --------------------------------
1376
   -- Change_To_Object_Directory --
1377
   --------------------------------
1378
 
1379
   procedure Change_To_Object_Directory (Project : Project_Id) is
1380
      Object_Directory : Path_Name_Type;
1381
 
1382
   begin
1383
      pragma Assert (Project /= No_Project);
1384
 
1385
      --  Nothing to do if the current working directory is already the correct
1386
      --  object directory.
1387
 
1388
      if Project_Of_Current_Object_Directory /= Project then
1389
         Project_Of_Current_Object_Directory := Project;
1390
         Object_Directory := Project.Object_Directory.Name;
1391
 
1392
         --  Set the working directory to the object directory of the actual
1393
         --  project.
1394
 
1395
         if Verbose_Mode then
1396
            Write_Str  ("Changing to object directory of """);
1397
            Write_Name (Project.Display_Name);
1398
            Write_Str  (""": """);
1399
            Write_Name (Object_Directory);
1400
            Write_Line ("""");
1401
         end if;
1402
 
1403
         Change_Dir (Get_Name_String (Object_Directory));
1404
      end if;
1405
 
1406
   exception
1407
      --  Fail if unable to change to the object directory
1408
 
1409
      when Directory_Error =>
1410
         Make_Failed ("unable to change to object directory """ &
1411
                      Path_Or_File_Name
1412
                        (Project.Object_Directory.Name) &
1413
                      """ of project " &
1414
                      Get_Name_String (Project.Display_Name));
1415
   end Change_To_Object_Directory;
1416
 
1417
   -----------
1418
   -- Check --
1419
   -----------
1420
 
1421
   procedure Check
1422
     (Source_File    : File_Name_Type;
1423
      Source_Index   : Int;
1424
      Is_Main_Source : Boolean;
1425
      The_Args       : Argument_List;
1426
      Lib_File       : File_Name_Type;
1427
      Full_Lib_File  : File_Name_Type;
1428
      Lib_File_Attr  : access File_Attributes;
1429
      Read_Only      : Boolean;
1430
      ALI            : out ALI_Id;
1431
      O_File         : out File_Name_Type;
1432
      O_Stamp        : out Time_Stamp_Type)
1433
   is
1434
      function First_New_Spec (A : ALI_Id) return File_Name_Type;
1435
      --  Looks in the with table entries of A and returns the spec file name
1436
      --  of the first withed unit (subprogram) for which no spec existed when
1437
      --  A was generated but for which there exists one now, implying that A
1438
      --  is now obsolete. If no such unit is found No_File is returned.
1439
      --  Otherwise the spec file name of the unit is returned.
1440
      --
1441
      --  **WARNING** in the event of Uname format modifications, one *MUST*
1442
      --  make sure this function is also updated.
1443
      --
1444
      --  Note: This function should really be in ali.adb and use Uname
1445
      --  services, but this causes the whole compiler to be dragged along
1446
      --  for gnatbind and gnatmake.
1447
 
1448
      --------------------
1449
      -- First_New_Spec --
1450
      --------------------
1451
 
1452
      function First_New_Spec (A : ALI_Id) return File_Name_Type is
1453
         Spec_File_Name : File_Name_Type := No_File;
1454
 
1455
         function New_Spec (Uname : Unit_Name_Type) return Boolean;
1456
         --  Uname is the name of the spec or body of some ada unit. This
1457
         --  function returns True if the Uname is the name of a body which has
1458
         --  a spec not mentioned in ALI file A. If True is returned
1459
         --  Spec_File_Name above is set to the name of this spec file.
1460
 
1461
         --------------
1462
         -- New_Spec --
1463
         --------------
1464
 
1465
         function New_Spec (Uname : Unit_Name_Type) return Boolean is
1466
            Spec_Name : Unit_Name_Type;
1467
            File_Name : File_Name_Type;
1468
 
1469
         begin
1470
            --  Test whether Uname is the name of a body unit (i.e. ends
1471
            --  with %b)
1472
 
1473
            Get_Name_String (Uname);
1474
            pragma
1475
              Assert (Name_Len > 2 and then Name_Buffer (Name_Len - 1) = '%');
1476
 
1477
            if Name_Buffer (Name_Len) /= 'b' then
1478
               return False;
1479
            end if;
1480
 
1481
            --  Convert unit name into spec name
1482
 
1483
            --  ??? this code seems dubious in presence of pragma
1484
            --  Source_File_Name since there is no more direct relationship
1485
            --  between unit name and file name.
1486
 
1487
            --  ??? Further, what about alternative subunit naming
1488
 
1489
            Name_Buffer (Name_Len) := 's';
1490
            Spec_Name := Name_Find;
1491
            File_Name := Get_File_Name (Spec_Name, Subunit => False);
1492
 
1493
            --  Look if File_Name is mentioned in A's sdep list.
1494
            --  If not look if the file exists. If it does return True.
1495
 
1496
            for D in
1497
              ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
1498
            loop
1499
               if Sdep.Table (D).Sfile = File_Name then
1500
                  return False;
1501
               end if;
1502
            end loop;
1503
 
1504
            if Full_Source_Name (File_Name) /= No_File then
1505
               Spec_File_Name := File_Name;
1506
               return True;
1507
            end if;
1508
 
1509
            return False;
1510
         end New_Spec;
1511
 
1512
      --  Start of processing for First_New_Spec
1513
 
1514
      begin
1515
         U_Chk : for U in
1516
           ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit
1517
         loop
1518
            exit U_Chk when Units.Table (U).Utype = Is_Body_Only
1519
               and then New_Spec (Units.Table (U).Uname);
1520
 
1521
            for W in Units.Table (U).First_With
1522
                       ..
1523
                     Units.Table (U).Last_With
1524
            loop
1525
               exit U_Chk when
1526
                 Withs.Table (W).Afile /= No_File
1527
                 and then New_Spec (Withs.Table (W).Uname);
1528
            end loop;
1529
         end loop U_Chk;
1530
 
1531
         return Spec_File_Name;
1532
      end First_New_Spec;
1533
 
1534
      ---------------------------------
1535
      -- Data declarations for Check --
1536
      ---------------------------------
1537
 
1538
      Full_Obj_File : File_Name_Type;
1539
      --  Full name of the object file corresponding to Lib_File
1540
 
1541
      Lib_Stamp : Time_Stamp_Type;
1542
      --  Time stamp of the current ada library file
1543
 
1544
      Obj_Stamp : Time_Stamp_Type;
1545
      --  Time stamp of the current object file
1546
 
1547
      Modified_Source : File_Name_Type;
1548
      --  The first source in Lib_File whose current time stamp differs
1549
      --  from that stored in Lib_File.
1550
 
1551
      New_Spec : File_Name_Type;
1552
      --  If Lib_File contains in its W (with) section a body (for a
1553
      --  subprogram) for which there exists a spec and the spec did not
1554
      --  appear in the Sdep section of Lib_File, New_Spec contains the file
1555
      --  name of this new spec.
1556
 
1557
      Source_Name : File_Name_Type;
1558
      Text        : Text_Buffer_Ptr;
1559
 
1560
      Prev_Switch : String_Access;
1561
      --  Previous switch processed
1562
 
1563
      Arg : Arg_Id := Arg_Id'First;
1564
      --  Current index in Args.Table for a given unit (init to stop warning)
1565
 
1566
      Switch_Found : Boolean;
1567
      --  True if a given switch has been found
1568
 
1569
      ALI_Project : Project_Id;
1570
      --  If the ALI file is in the object directory of a project, this is
1571
      --  the project id.
1572
 
1573
   --  Start of processing for Check
1574
 
1575
   begin
1576
      pragma Assert (Lib_File /= No_File);
1577
 
1578
      --  If ALI file is read-only, temporarily set Check_Object_Consistency to
1579
      --  False. We don't care if the object file is not there (presumably a
1580
      --  library will be used for linking.)
1581
 
1582
      if Read_Only then
1583
         declare
1584
            Saved_Check_Object_Consistency : constant Boolean :=
1585
                                               Check_Object_Consistency;
1586
         begin
1587
            Check_Object_Consistency := False;
1588
            Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr);
1589
            Check_Object_Consistency := Saved_Check_Object_Consistency;
1590
         end;
1591
 
1592
      else
1593
         Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr);
1594
      end if;
1595
 
1596
      Full_Obj_File := Full_Object_File_Name;
1597
      Lib_Stamp     := Current_Library_File_Stamp;
1598
      Obj_Stamp     := Current_Object_File_Stamp;
1599
 
1600
      if Full_Lib_File = No_File then
1601
         Verbose_Msg
1602
           (Lib_File,
1603
            "being checked ...",
1604
            Prefix => "  ",
1605
            Minimum_Verbosity => Opt.Medium);
1606
      else
1607
         Verbose_Msg
1608
           (Full_Lib_File,
1609
            "being checked ...",
1610
            Prefix => "  ",
1611
            Minimum_Verbosity => Opt.Medium);
1612
      end if;
1613
 
1614
      ALI     := No_ALI_Id;
1615
      O_File  := Full_Obj_File;
1616
      O_Stamp := Obj_Stamp;
1617
 
1618
      if Text = null then
1619
         if Full_Lib_File = No_File then
1620
            Verbose_Msg (Lib_File, "missing.");
1621
 
1622
         elsif Obj_Stamp (Obj_Stamp'First) = ' ' then
1623
            Verbose_Msg (Full_Obj_File, "missing.");
1624
 
1625
         else
1626
            Verbose_Msg
1627
              (Full_Lib_File, "(" & String (Lib_Stamp) & ") newer than",
1628
               Full_Obj_File, "(" & String (Obj_Stamp) & ")");
1629
         end if;
1630
 
1631
      else
1632
         ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
1633
         Free (Text);
1634
 
1635
         if ALI = No_ALI_Id then
1636
            Verbose_Msg (Full_Lib_File, "incorrectly formatted ALI file");
1637
            return;
1638
 
1639
         elsif ALIs.Table (ALI).Ver (1 .. ALIs.Table (ALI).Ver_Len) /=
1640
                 Verbose_Library_Version
1641
         then
1642
            Verbose_Msg (Full_Lib_File, "compiled with old GNAT version");
1643
            ALI := No_ALI_Id;
1644
            return;
1645
         end if;
1646
 
1647
         --  Don't take Ali file into account if it was generated with
1648
         --  errors.
1649
 
1650
         if ALIs.Table (ALI).Compile_Errors then
1651
            Verbose_Msg (Full_Lib_File, "had errors, must be recompiled");
1652
            ALI := No_ALI_Id;
1653
            return;
1654
         end if;
1655
 
1656
         --  Don't take Ali file into account if it was generated without
1657
         --  object.
1658
 
1659
         if Operating_Mode /= Check_Semantics
1660
           and then ALIs.Table (ALI).No_Object
1661
         then
1662
            Verbose_Msg (Full_Lib_File, "has no corresponding object");
1663
            ALI := No_ALI_Id;
1664
            return;
1665
         end if;
1666
 
1667
         --  Check for matching compiler switches if needed
1668
 
1669
         if Check_Switches then
1670
 
1671
            --  First, collect all the switches
1672
 
1673
            Collect_Arguments
1674
              (Source_File, Source_Index, Is_Main_Source, The_Args);
1675
 
1676
            Prev_Switch := Dummy_Switch;
1677
 
1678
            Get_Name_String (ALIs.Table (ALI).Sfile);
1679
 
1680
            Switches_To_Check.Set_Last (0);
1681
 
1682
            for J in 1 .. Last_Argument loop
1683
 
1684
               --  Skip non switches -c, -I and -o switches
1685
 
1686
               if Arguments (J) (1) = '-'
1687
                 and then Arguments (J) (2) /= 'c'
1688
                 and then Arguments (J) (2) /= 'o'
1689
                 and then Arguments (J) (2) /= 'I'
1690
               then
1691
                  Normalize_Compiler_Switches
1692
                    (Arguments (J).all,
1693
                     Normalized_Switches,
1694
                     Last_Norm_Switch);
1695
 
1696
                  for K in 1 .. Last_Norm_Switch loop
1697
                     Switches_To_Check.Increment_Last;
1698
                     Switches_To_Check.Table (Switches_To_Check.Last) :=
1699
                       Normalized_Switches (K);
1700
                  end loop;
1701
               end if;
1702
            end loop;
1703
 
1704
            for J in 1 .. Switches_To_Check.Last loop
1705
 
1706
               --  Comparing switches is delicate because gcc reorders a number
1707
               --  of switches, according to lang-specs.h, but gnatmake doesn't
1708
               --  have sufficient knowledge to perform the same reordering.
1709
               --  Instead, we ignore orders between different "first letter"
1710
               --  switches, but keep orders between same switches, e.g -O -O2
1711
               --  is different than -O2 -O, but -g -O is equivalent to -O -g.
1712
 
1713
               if Switches_To_Check.Table (J) (2) /= Prev_Switch (2) or else
1714
                   (Prev_Switch'Length >= 6 and then
1715
                    Prev_Switch (2 .. 5) = "gnat" and then
1716
                    Switches_To_Check.Table (J)'Length >= 6 and then
1717
                    Switches_To_Check.Table (J) (2 .. 5) = "gnat" and then
1718
                    Prev_Switch (6) /= Switches_To_Check.Table (J) (6))
1719
               then
1720
                  Prev_Switch := Switches_To_Check.Table (J);
1721
                  Arg :=
1722
                    Units.Table (ALIs.Table (ALI).First_Unit).First_Arg;
1723
               end if;
1724
 
1725
               Switch_Found := False;
1726
 
1727
               for K in Arg ..
1728
                 Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg
1729
               loop
1730
                  if
1731
                    Switches_To_Check.Table (J).all = Args.Table (K).all
1732
                  then
1733
                     Arg := K + 1;
1734
                     Switch_Found := True;
1735
                     exit;
1736
                  end if;
1737
               end loop;
1738
 
1739
               if not Switch_Found then
1740
                  if Verbose_Mode then
1741
                     Verbose_Msg (ALIs.Table (ALI).Sfile,
1742
                                  "switch mismatch """ &
1743
                                  Switches_To_Check.Table (J).all & '"');
1744
                  end if;
1745
 
1746
                  ALI := No_ALI_Id;
1747
                  return;
1748
               end if;
1749
            end loop;
1750
 
1751
            if Switches_To_Check.Last /=
1752
              Integer (Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg -
1753
                       Units.Table (ALIs.Table (ALI).First_Unit).First_Arg + 1)
1754
            then
1755
               if Verbose_Mode then
1756
                  Verbose_Msg (ALIs.Table (ALI).Sfile,
1757
                               "different number of switches");
1758
 
1759
                  for K in Units.Table (ALIs.Table (ALI).First_Unit).First_Arg
1760
                    .. Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg
1761
                  loop
1762
                     Write_Str (Args.Table (K).all);
1763
                     Write_Char (' ');
1764
                  end loop;
1765
 
1766
                  Write_Eol;
1767
 
1768
                  for J in 1 .. Switches_To_Check.Last loop
1769
                     Write_Str (Switches_To_Check.Table (J).all);
1770
                     Write_Char (' ');
1771
                  end loop;
1772
 
1773
                  Write_Eol;
1774
               end if;
1775
 
1776
               ALI := No_ALI_Id;
1777
               return;
1778
            end if;
1779
         end if;
1780
 
1781
         --  Get the source files and their message digests. Note that some
1782
         --  sources may be missing if ALI is out-of-date.
1783
 
1784
         Set_Source_Table (ALI);
1785
 
1786
         Modified_Source := Time_Stamp_Mismatch (ALI, Read_Only);
1787
 
1788
         if Modified_Source /= No_File then
1789
            ALI := No_ALI_Id;
1790
 
1791
            if Verbose_Mode then
1792
               Source_Name := Full_Source_Name (Modified_Source);
1793
 
1794
               if Source_Name /= No_File then
1795
                  Verbose_Msg (Source_Name, "time stamp mismatch");
1796
               else
1797
                  Verbose_Msg (Modified_Source, "missing");
1798
               end if;
1799
            end if;
1800
 
1801
         else
1802
            New_Spec := First_New_Spec (ALI);
1803
 
1804
            if New_Spec /= No_File then
1805
               ALI := No_ALI_Id;
1806
 
1807
               if Verbose_Mode then
1808
                  Source_Name := Full_Source_Name (New_Spec);
1809
 
1810
                  if Source_Name /= No_File then
1811
                     Verbose_Msg (Source_Name, "new spec");
1812
                  else
1813
                     Verbose_Msg (New_Spec, "old spec missing");
1814
                  end if;
1815
               end if;
1816
 
1817
            elsif not Read_Only and then Main_Project /= No_Project then
1818
 
1819
               if not Check_Source_Info_In_ALI (ALI) then
1820
                  ALI := No_ALI_Id;
1821
                  return;
1822
               end if;
1823
 
1824
               --  Check that the ALI file is in the correct object directory.
1825
               --  If it is in the object directory of a project that is
1826
               --  extended and it depends on a source that is in one of its
1827
               --  extending projects, then the ALI file is not in the correct
1828
               --  object directory.
1829
 
1830
               --  First, find the project of this ALI file. As there may be
1831
               --  several projects with the same object directory, we first
1832
               --  need to find the project of the source.
1833
 
1834
               ALI_Project := No_Project;
1835
 
1836
               declare
1837
                  Udata : Prj.Unit_Index;
1838
 
1839
               begin
1840
                  Udata := Units_Htable.Get_First (Project_Tree.Units_HT);
1841
                  while Udata /= No_Unit_Index loop
1842
                     if Udata.File_Names (Impl) /= null
1843
                       and then Udata.File_Names (Impl).File = Source_File
1844
                     then
1845
                        ALI_Project := Udata.File_Names (Impl).Project;
1846
                        exit;
1847
 
1848
                     elsif Udata.File_Names (Spec) /= null
1849
                       and then Udata.File_Names (Spec).File = Source_File
1850
                     then
1851
                        ALI_Project := Udata.File_Names (Spec).Project;
1852
                        exit;
1853
                     end if;
1854
 
1855
                     Udata := Units_Htable.Get_Next (Project_Tree.Units_HT);
1856
                  end loop;
1857
               end;
1858
 
1859
               if ALI_Project = No_Project then
1860
                  return;
1861
               end if;
1862
 
1863
               declare
1864
                  Obj_Dir : Path_Name_Type;
1865
                  Res_Obj_Dir : constant String :=
1866
                                  Normalize_Pathname
1867
                                    (Dir_Name
1868
                                      (Get_Name_String (Full_Lib_File)),
1869
                                     Resolve_Links  =>
1870
                                       Opt.Follow_Links_For_Dirs,
1871
                                     Case_Sensitive => False);
1872
 
1873
               begin
1874
                  Name_Len := 0;
1875
                  Add_Str_To_Name_Buffer (Res_Obj_Dir);
1876
 
1877
                  if not Is_Directory_Separator (Name_Buffer (Name_Len)) then
1878
                     Add_Char_To_Name_Buffer (Directory_Separator);
1879
                  end if;
1880
 
1881
                  Obj_Dir := Name_Find;
1882
 
1883
                  while ALI_Project /= No_Project
1884
                    and then Obj_Dir /= ALI_Project.Object_Directory.Name
1885
                  loop
1886
                     ALI_Project := ALI_Project.Extended_By;
1887
                  end loop;
1888
               end;
1889
 
1890
               if ALI_Project = No_Project then
1891
                  ALI := No_ALI_Id;
1892
 
1893
                  Verbose_Msg
1894
                    (Lib_File, " wrong object directory");
1895
                  return;
1896
               end if;
1897
 
1898
               --  If the ALI project is not extended, then it must be in
1899
               --  the correct object directory.
1900
 
1901
               if ALI_Project.Extended_By = No_Project then
1902
                  return;
1903
               end if;
1904
 
1905
               --  Count the extending projects
1906
 
1907
               declare
1908
                  Num_Ext : Natural;
1909
                  Proj    : Project_Id;
1910
 
1911
               begin
1912
                  Num_Ext := 0;
1913
                  Proj := ALI_Project;
1914
                  loop
1915
                     Proj := Proj.Extended_By;
1916
                     exit when Proj = No_Project;
1917
                     Num_Ext := Num_Ext + 1;
1918
                  end loop;
1919
 
1920
                  --  Make a list of the extending projects
1921
 
1922
                  declare
1923
                     Projects : array (1 .. Num_Ext) of Project_Id;
1924
                     Dep      : Sdep_Record;
1925
                     OK       : Boolean := True;
1926
                     UID      : Unit_Index;
1927
 
1928
                  begin
1929
                     Proj := ALI_Project;
1930
                     for J in Projects'Range loop
1931
                        Proj := Proj.Extended_By;
1932
                        Projects (J) := Proj;
1933
                     end loop;
1934
 
1935
                     --  Now check if any of the dependant sources are in
1936
                     --  any of these extending projects.
1937
 
1938
                     D_Chk :
1939
                     for D in ALIs.Table (ALI).First_Sdep ..
1940
                       ALIs.Table (ALI).Last_Sdep
1941
                     loop
1942
                        Dep := Sdep.Table (D);
1943
                        UID  := Units_Htable.Get_First (Project_Tree.Units_HT);
1944
                        Proj := No_Project;
1945
 
1946
                        Unit_Loop :
1947
                        while UID /= null loop
1948
                           if UID.File_Names (Impl) /= null
1949
                             and then UID.File_Names (Impl).File = Dep.Sfile
1950
                           then
1951
                              Proj := UID.File_Names (Impl).Project;
1952
 
1953
                           elsif UID.File_Names (Spec) /= null
1954
                             and then UID.File_Names (Spec).File = Dep.Sfile
1955
                           then
1956
                              Proj := UID.File_Names (Spec).Project;
1957
                           end if;
1958
 
1959
                           --  If a source is in a project, check if it is one
1960
                           --  in the list.
1961
 
1962
                           if Proj /= No_Project then
1963
                              for J in Projects'Range loop
1964
                                 if Proj = Projects (J) then
1965
                                    OK := False;
1966
                                    exit D_Chk;
1967
                                 end if;
1968
                              end loop;
1969
 
1970
                              exit Unit_Loop;
1971
                           end if;
1972
 
1973
                           UID :=
1974
                             Units_Htable.Get_Next (Project_Tree.Units_HT);
1975
                        end loop Unit_Loop;
1976
                     end loop D_Chk;
1977
 
1978
                     --  If one of the dependent sources is in one project of
1979
                     --  the list, then we must recompile.
1980
 
1981
                     if not OK then
1982
                        ALI := No_ALI_Id;
1983
                        Verbose_Msg (Lib_File, " wrong object directory");
1984
                     end if;
1985
                  end;
1986
               end;
1987
            end if;
1988
         end if;
1989
      end if;
1990
   end Check;
1991
 
1992
   ------------------------
1993
   -- Check_For_S_Switch --
1994
   ------------------------
1995
 
1996
   procedure Check_For_S_Switch is
1997
   begin
1998
      --  By default, we generate an object file
1999
 
2000
      Output_Is_Object := True;
2001
 
2002
      for Arg in 1 .. Last_Argument loop
2003
         if Arguments (Arg).all = "-S" then
2004
            Output_Is_Object := False;
2005
 
2006
         elsif Arguments (Arg).all = "-c" then
2007
            Output_Is_Object := True;
2008
         end if;
2009
      end loop;
2010
   end Check_For_S_Switch;
2011
 
2012
   --------------------------
2013
   -- Check_Linker_Options --
2014
   --------------------------
2015
 
2016
   procedure Check_Linker_Options
2017
     (E_Stamp   : Time_Stamp_Type;
2018
      O_File    : out File_Name_Type;
2019
      O_Stamp   : out Time_Stamp_Type)
2020
   is
2021
      procedure Check_File (File : File_Name_Type);
2022
      --  Update O_File and O_Stamp if the given file is younger than E_Stamp
2023
      --  and O_Stamp, or if O_File is No_File and File does not exist.
2024
 
2025
      function Get_Library_File (Name : String) return File_Name_Type;
2026
      --  Return the full file name including path of a library based
2027
      --  on the name specified with the -l linker option, using the
2028
      --  Ada object path. Return No_File if no such file can be found.
2029
 
2030
      type Char_Array is array (Natural) of Character;
2031
      type Char_Array_Access is access constant Char_Array;
2032
 
2033
      Template : Char_Array_Access;
2034
      pragma Import (C, Template, "__gnat_library_template");
2035
 
2036
      ----------------
2037
      -- Check_File --
2038
      ----------------
2039
 
2040
      procedure Check_File (File : File_Name_Type) is
2041
         Stamp : Time_Stamp_Type;
2042
         Name  : File_Name_Type := File;
2043
 
2044
      begin
2045
         Get_Name_String (Name);
2046
 
2047
         --  Remove any trailing NUL characters
2048
 
2049
         while Name_Len >= Name_Buffer'First
2050
           and then Name_Buffer (Name_Len) = NUL
2051
         loop
2052
            Name_Len := Name_Len - 1;
2053
         end loop;
2054
 
2055
         if Name_Len = 0 then
2056
            return;
2057
 
2058
         elsif Name_Buffer (1) = '-' then
2059
 
2060
            --  Do not check if File is a switch other than "-l"
2061
 
2062
            if Name_Buffer (2) /= 'l' then
2063
               return;
2064
            end if;
2065
 
2066
            --  The argument is a library switch, get actual name. It
2067
            --  is necessary to make a copy of the relevant part of
2068
            --  Name_Buffer as Get_Library_Name uses Name_Buffer as well.
2069
 
2070
            declare
2071
               Base_Name : constant String := Name_Buffer (3 .. Name_Len);
2072
 
2073
            begin
2074
               Name := Get_Library_File (Base_Name);
2075
            end;
2076
 
2077
            if Name = No_File then
2078
               return;
2079
            end if;
2080
         end if;
2081
 
2082
         Stamp := File_Stamp (Name);
2083
 
2084
         --  Find the youngest object file that is younger than the
2085
         --  executable. If no such file exist, record the first object
2086
         --  file that is not found.
2087
 
2088
         if (O_Stamp < Stamp and then E_Stamp < Stamp)
2089
           or else (O_File = No_File and then Stamp (Stamp'First) = ' ')
2090
         then
2091
            O_Stamp := Stamp;
2092
            O_File := Name;
2093
 
2094
            --  Strip the trailing NUL if present
2095
 
2096
            Get_Name_String (O_File);
2097
 
2098
            if Name_Buffer (Name_Len) = NUL then
2099
               Name_Len := Name_Len - 1;
2100
               O_File := Name_Find;
2101
            end if;
2102
         end if;
2103
      end Check_File;
2104
 
2105
      ----------------------
2106
      -- Get_Library_Name --
2107
      ----------------------
2108
 
2109
      --  See comments in a-adaint.c about template syntax
2110
 
2111
      function Get_Library_File (Name : String) return File_Name_Type is
2112
         File : File_Name_Type := No_File;
2113
 
2114
      begin
2115
         Name_Len := 0;
2116
 
2117
         for Ptr in Template'Range loop
2118
            case Template (Ptr) is
2119
               when '*'    =>
2120
                  Add_Str_To_Name_Buffer (Name);
2121
 
2122
               when ';'    =>
2123
                  File := Full_Lib_File_Name (Name_Find);
2124
                  exit when File /= No_File;
2125
                  Name_Len := 0;
2126
 
2127
               when NUL    =>
2128
                  exit;
2129
 
2130
               when others =>
2131
                  Add_Char_To_Name_Buffer (Template (Ptr));
2132
            end case;
2133
         end loop;
2134
 
2135
         --  The for loop exited because the end of the template
2136
         --  was reached. File contains the last possible file name
2137
         --  for the library.
2138
 
2139
         if File = No_File and then Name_Len > 0 then
2140
            File := Full_Lib_File_Name (Name_Find);
2141
         end if;
2142
 
2143
         return File;
2144
      end Get_Library_File;
2145
 
2146
   --  Start of processing for Check_Linker_Options
2147
 
2148
   begin
2149
      O_File  := No_File;
2150
      O_Stamp := (others => ' ');
2151
 
2152
      --  Process linker options from the ALI files
2153
 
2154
      for Opt in 1 .. Linker_Options.Last loop
2155
         Check_File (File_Name_Type (Linker_Options.Table (Opt).Name));
2156
      end loop;
2157
 
2158
      --  Process options given on the command line
2159
 
2160
      for Opt in Linker_Switches.First .. Linker_Switches.Last loop
2161
 
2162
         --  Check if the previous Opt has one of the two switches
2163
         --  that take an extra parameter. (See GCC manual.)
2164
 
2165
         if Opt = Linker_Switches.First
2166
           or else (Linker_Switches.Table (Opt - 1).all /= "-u"
2167
                      and then
2168
                    Linker_Switches.Table (Opt - 1).all /= "-Xlinker"
2169
                      and then
2170
                    Linker_Switches.Table (Opt - 1).all /= "-L")
2171
         then
2172
            Name_Len := 0;
2173
            Add_Str_To_Name_Buffer (Linker_Switches.Table (Opt).all);
2174
            Check_File (Name_Find);
2175
         end if;
2176
      end loop;
2177
 
2178
   end Check_Linker_Options;
2179
 
2180
   -----------------
2181
   -- Check_Steps --
2182
   -----------------
2183
 
2184
   procedure Check_Steps is
2185
   begin
2186
      --  If either -c, -b or -l has been specified, we will not necessarily
2187
      --  execute all steps.
2188
 
2189
      if Make_Steps then
2190
         Do_Compile_Step := Do_Compile_Step and Compile_Only;
2191
         Do_Bind_Step    := Do_Bind_Step    and Bind_Only;
2192
         Do_Link_Step    := Do_Link_Step    and Link_Only;
2193
 
2194
         --  If -c has been specified, but not -b, ignore any potential -l
2195
 
2196
         if Do_Compile_Step and then not Do_Bind_Step then
2197
            Do_Link_Step := False;
2198
         end if;
2199
      end if;
2200
   end Check_Steps;
2201
 
2202
   -----------------------
2203
   -- Collect_Arguments --
2204
   -----------------------
2205
 
2206
   procedure Collect_Arguments
2207
     (Source_File    : File_Name_Type;
2208
      Source_Index   : Int;
2209
      Is_Main_Source : Boolean;
2210
      Args           : Argument_List)
2211
   is
2212
   begin
2213
      Arguments_Project := No_Project;
2214
      Last_Argument := 0;
2215
      Add_Arguments (Args);
2216
 
2217
      if Main_Project /= No_Project then
2218
         declare
2219
            Source_File_Name : constant String :=
2220
                                 Get_Name_String (Source_File);
2221
            Compiler_Package : Prj.Package_Id;
2222
            Switches         : Prj.Variable_Value;
2223
 
2224
         begin
2225
            Prj.Env.
2226
              Get_Reference
2227
              (Source_File_Name => Source_File_Name,
2228
               Project          => Arguments_Project,
2229
               Path             => Arguments_Path_Name,
2230
               In_Tree          => Project_Tree);
2231
 
2232
            --  If the source is not a source of a project file, add the
2233
            --  recorded arguments. Check will be done later if the source
2234
            --  need to be compiled that the switch -x has been used.
2235
 
2236
            if Arguments_Project = No_Project then
2237
               Add_Arguments (The_Saved_Gcc_Switches.all);
2238
 
2239
            elsif not Arguments_Project.Externally_Built then
2240
               --  We get the project directory for the relative path
2241
               --  switches and arguments.
2242
 
2243
               Arguments_Project := Ultimate_Extending_Project_Of
2244
                 (Arguments_Project);
2245
 
2246
               --  If building a dynamic or relocatable library, compile with
2247
               --  PIC option, if it exists.
2248
 
2249
               if Arguments_Project.Library
2250
                 and then Arguments_Project.Library_Kind /= Static
2251
               then
2252
                  declare
2253
                     PIC : constant String := MLib.Tgt.PIC_Option;
2254
 
2255
                  begin
2256
                     if PIC /= "" then
2257
                        Add_Arguments ((1 => new String'(PIC)));
2258
                     end if;
2259
                  end;
2260
               end if;
2261
 
2262
               --  We now look for package Compiler and get the switches from
2263
               --  this package.
2264
 
2265
               Compiler_Package :=
2266
                 Prj.Util.Value_Of
2267
                   (Name        => Name_Compiler,
2268
                    In_Packages => Arguments_Project.Decl.Packages,
2269
                    In_Tree     => Project_Tree);
2270
 
2271
               if Compiler_Package /= No_Package then
2272
 
2273
                  --  If package Gnatmake.Compiler exists, we get the specific
2274
                  --  switches for the current source, or the global switches,
2275
                  --  if any.
2276
 
2277
                  Switches :=
2278
                    Switches_Of
2279
                      (Source_File      => Source_File,
2280
                       Source_File_Name => Source_File_Name,
2281
                       Source_Index     => Source_Index,
2282
                       Project          => Arguments_Project,
2283
                       In_Package       => Compiler_Package,
2284
                       Allow_ALI        => False);
2285
 
2286
               end if;
2287
 
2288
               case Switches.Kind is
2289
 
2290
                  --  We have a list of switches. We add these switches,
2291
                  --  plus the saved gcc switches.
2292
 
2293
                  when List =>
2294
 
2295
                     declare
2296
                        Current : String_List_Id := Switches.Values;
2297
                        Element : String_Element;
2298
                        Number  : Natural := 0;
2299
 
2300
                     begin
2301
                        while Current /= Nil_String loop
2302
                           Element := Project_Tree.String_Elements.
2303
                                        Table (Current);
2304
                           Number  := Number + 1;
2305
                           Current := Element.Next;
2306
                        end loop;
2307
 
2308
                        declare
2309
                           New_Args : Argument_List (1 .. Number);
2310
                           Last_New : Natural := 0;
2311
                           Dir_Path : constant String := Get_Name_String
2312
                             (Arguments_Project.Directory.Name);
2313
 
2314
                        begin
2315
                           Current := Switches.Values;
2316
 
2317
                           for Index in New_Args'Range loop
2318
                              Element := Project_Tree.String_Elements.
2319
                                           Table (Current);
2320
                              Get_Name_String (Element.Value);
2321
 
2322
                              if Name_Len > 0 then
2323
                                 Last_New := Last_New + 1;
2324
                                 New_Args (Last_New) :=
2325
                                   new String'(Name_Buffer (1 .. Name_Len));
2326
                                 Test_If_Relative_Path
2327
                                   (New_Args (Last_New),
2328
                                    Parent => Dir_Path,
2329
                                    Including_Non_Switch => False);
2330
                              end if;
2331
 
2332
                              Current := Element.Next;
2333
                           end loop;
2334
 
2335
                           Add_Arguments
2336
                             (Configuration_Pragmas_Switch
2337
                                (Arguments_Project) &
2338
                              New_Args (1 .. Last_New) &
2339
                              The_Saved_Gcc_Switches.all);
2340
                        end;
2341
                     end;
2342
 
2343
                     --  We have a single switch. We add this switch,
2344
                     --  plus the saved gcc switches.
2345
 
2346
                  when Single =>
2347
                     Get_Name_String (Switches.Value);
2348
 
2349
                     declare
2350
                        New_Args : Argument_List :=
2351
                                     (1 => new String'
2352
                                            (Name_Buffer (1 .. Name_Len)));
2353
                        Dir_Path : constant String :=
2354
                                     Get_Name_String
2355
                                       (Arguments_Project.Directory.Name);
2356
 
2357
                     begin
2358
                        Test_If_Relative_Path
2359
                          (New_Args (1),
2360
                           Parent               => Dir_Path,
2361
                           Including_Non_Switch => False);
2362
                        Add_Arguments
2363
                          (Configuration_Pragmas_Switch (Arguments_Project) &
2364
                           New_Args & The_Saved_Gcc_Switches.all);
2365
                     end;
2366
 
2367
                     --  We have no switches from Gnatmake.Compiler.
2368
                     --  We add the saved gcc switches.
2369
 
2370
                  when Undefined =>
2371
                     Add_Arguments
2372
                       (Configuration_Pragmas_Switch (Arguments_Project) &
2373
                        The_Saved_Gcc_Switches.all);
2374
               end case;
2375
            end if;
2376
         end;
2377
      end if;
2378
 
2379
      --  For VMS, when compiling the main source, add switch
2380
      --  -mdebug-main=_ada_ so that the executable can be debugged
2381
      --  by the standard VMS debugger.
2382
 
2383
      if not No_Main_Subprogram
2384
        and then Targparm.OpenVMS_On_Target
2385
        and then Is_Main_Source
2386
      then
2387
         --  First, check if compilation will be invoked with -g
2388
 
2389
         for J in 1 .. Last_Argument loop
2390
            if Arguments (J)'Length >= 2
2391
              and then Arguments (J) (1 .. 2) = "-g"
2392
              and then (Arguments (J)'Length < 5
2393
                        or else Arguments (J) (1 .. 5) /= "-gnat")
2394
            then
2395
               Add_Arguments
2396
                 ((1 => new String'("-mdebug-main=_ada_")));
2397
               exit;
2398
            end if;
2399
         end loop;
2400
      end if;
2401
 
2402
      --  Set Output_Is_Object, depending if there is a -S switch.
2403
      --  If the bind step is not performed, and there is a -S switch,
2404
      --  then we will not check for a valid object file.
2405
 
2406
      Check_For_S_Switch;
2407
   end Collect_Arguments;
2408
 
2409
   ---------------------
2410
   -- Compile_Sources --
2411
   ---------------------
2412
 
2413
   procedure Compile_Sources
2414
     (Main_Source           : File_Name_Type;
2415
      Args                  : Argument_List;
2416
      First_Compiled_File   : out File_Name_Type;
2417
      Most_Recent_Obj_File  : out File_Name_Type;
2418
      Most_Recent_Obj_Stamp : out Time_Stamp_Type;
2419
      Main_Unit             : out Boolean;
2420
      Compilation_Failures  : out Natural;
2421
      Main_Index            : Int      := 0;
2422
      Check_Readonly_Files  : Boolean  := False;
2423
      Do_Not_Execute        : Boolean  := False;
2424
      Force_Compilations    : Boolean  := False;
2425
      Keep_Going            : Boolean  := False;
2426
      In_Place_Mode         : Boolean  := False;
2427
      Initialize_ALI_Data   : Boolean  := True;
2428
      Max_Process           : Positive := 1)
2429
   is
2430
      Mfile            : Natural := No_Mapping_File;
2431
      Mapping_File_Arg : String_Access;
2432
      --  Info on the mapping file
2433
 
2434
      Need_To_Check_Standard_Library : Boolean :=
2435
                                         Check_Readonly_Files
2436
                                           and not Unique_Compile;
2437
 
2438
      procedure Add_Process
2439
        (Pid           : Process_Id;
2440
         Sfile         : File_Name_Type;
2441
         Afile         : File_Name_Type;
2442
         Uname         : Unit_Name_Type;
2443
         Full_Lib_File : File_Name_Type;
2444
         Lib_File_Attr : File_Attributes;
2445
         Mfile         : Natural := No_Mapping_File);
2446
      --  Adds process Pid to the current list of outstanding compilation
2447
      --  processes and record the full name of the source file Sfile that
2448
      --  we are compiling, the name of its library file Afile and the
2449
      --  name of its unit Uname. If Mfile is not equal to No_Mapping_File,
2450
      --  it is the index of the mapping file used during compilation in the
2451
      --  array The_Mapping_File_Names.
2452
 
2453
      procedure Await_Compile
2454
        (Data  : out Compilation_Data;
2455
         OK    : out Boolean);
2456
      --  Awaits that an outstanding compilation process terminates. When it
2457
      --  does set Data to the information registered for the corresponding
2458
      --  call to Add_Process. Note that this time stamp can be used to check
2459
      --  whether the compilation did generate an object file. OK is set to
2460
      --  True if the compilation succeeded. Data could be No_Compilation_Data
2461
      --  if there was no compilation to wait for.
2462
 
2463
      function Bad_Compilation_Count return Natural;
2464
      --  Returns the number of compilation failures
2465
 
2466
      procedure Check_Standard_Library;
2467
      --  Check if s-stalib.adb needs to be compiled
2468
 
2469
      procedure Collect_Arguments_And_Compile
2470
        (Full_Source_File : File_Name_Type;
2471
         Lib_File         : File_Name_Type;
2472
         Source_Index     : Int;
2473
         Pid              : out Process_Id;
2474
         Process_Created  : out Boolean);
2475
      --  Collect arguments from project file (if any) and compile. If no
2476
      --  compilation was attempted, Processed_Created is set to False, and the
2477
      --  value of Pid is unknown.
2478
 
2479
      function Compile
2480
        (Project      : Project_Id;
2481
         S            : File_Name_Type;
2482
         L            : File_Name_Type;
2483
         Source_Index : Int;
2484
         Args         : Argument_List) return Process_Id;
2485
      --  Compiles S using Args. If S is a GNAT predefined source "-gnatpg" is
2486
      --  added to Args. Non blocking call. L corresponds to the expected
2487
      --  library file name. Process_Id of the process spawned to execute the
2488
      --  compilation.
2489
 
2490
      package Good_ALI is new Table.Table (
2491
        Table_Component_Type => ALI_Id,
2492
        Table_Index_Type     => Natural,
2493
        Table_Low_Bound      => 1,
2494
        Table_Initial        => 50,
2495
        Table_Increment      => 100,
2496
        Table_Name           => "Make.Good_ALI");
2497
      --  Contains the set of valid ALI files that have not yet been scanned
2498
 
2499
      function Good_ALI_Present return Boolean;
2500
      --  Returns True if any ALI file was recorded in the previous set
2501
 
2502
      procedure Get_Mapping_File (Project : Project_Id);
2503
      --  Get a mapping file name. If there is one to be reused, reuse it.
2504
      --  Otherwise, create a new mapping file.
2505
 
2506
      function Get_Next_Good_ALI return ALI_Id;
2507
      --  Returns the next good ALI_Id record
2508
 
2509
      procedure Record_Failure
2510
        (File  : File_Name_Type;
2511
         Unit  : Unit_Name_Type;
2512
         Found : Boolean := True);
2513
      --  Records in the previous table that the compilation for File failed.
2514
      --  If Found is False then the compilation of File failed because we
2515
      --  could not find it. Records also Unit when possible.
2516
 
2517
      procedure Record_Good_ALI (A : ALI_Id);
2518
      --  Records in the previous set the Id of an ALI file
2519
 
2520
      function Must_Exit_Because_Of_Error return Boolean;
2521
      --  Return True if there were errors and the user decided to exit in such
2522
      --  a case. This waits for any outstanding compilation.
2523
 
2524
      function Start_Compile_If_Possible (Args : Argument_List) return Boolean;
2525
      --  Check if there is more work that we can do (i.e. the Queue is non
2526
      --  empty). If there is, do it only if we have not yet used up all the
2527
      --  available processes.
2528
      --  Returns True if we should exit the main loop
2529
 
2530
      procedure Wait_For_Available_Slot;
2531
      --  Check if we should wait for a compilation to finish. This is the case
2532
      --  if all the available processes are busy compiling sources or there is
2533
      --  nothing else to do (that is the Q is empty and there are no good ALIs
2534
      --  to process).
2535
 
2536
      procedure Fill_Queue_From_ALI_Files;
2537
      --  Check if we recorded good ALI files. If yes process them now in the
2538
      --  order in which they have been recorded. There are two occasions in
2539
      --  which we record good ali files. The first is in phase 1 when, after
2540
      --  scanning an existing ALI file we realize it is up-to-date, the second
2541
      --  instance is after a successful compilation.
2542
 
2543
      -----------------
2544
      -- Add_Process --
2545
      -----------------
2546
 
2547
      procedure Add_Process
2548
        (Pid           : Process_Id;
2549
         Sfile         : File_Name_Type;
2550
         Afile         : File_Name_Type;
2551
         Uname         : Unit_Name_Type;
2552
         Full_Lib_File : File_Name_Type;
2553
         Lib_File_Attr : File_Attributes;
2554
         Mfile         : Natural := No_Mapping_File)
2555
      is
2556
         OC1 : constant Positive := Outstanding_Compiles + 1;
2557
 
2558
      begin
2559
         pragma Assert (OC1 <= Max_Process);
2560
         pragma Assert (Pid /= Invalid_Pid);
2561
 
2562
         Running_Compile (OC1) :=
2563
           (Pid              => Pid,
2564
            Full_Source_File => Sfile,
2565
            Lib_File         => Afile,
2566
            Full_Lib_File    => Full_Lib_File,
2567
            Lib_File_Attr    => Lib_File_Attr,
2568
            Source_Unit      => Uname,
2569
            Mapping_File     => Mfile,
2570
            Project          => Arguments_Project);
2571
 
2572
         Outstanding_Compiles := OC1;
2573
      end Add_Process;
2574
 
2575
      --------------------
2576
      -- Await_Compile --
2577
      -------------------
2578
 
2579
      procedure Await_Compile
2580
        (Data : out Compilation_Data;
2581
         OK   : out Boolean)
2582
      is
2583
         Pid       : Process_Id;
2584
         Project   : Project_Id;
2585
         Comp_Data : Project_Compilation_Access;
2586
 
2587
      begin
2588
         pragma Assert (Outstanding_Compiles > 0);
2589
 
2590
         Data := No_Compilation_Data;
2591
         OK   := False;
2592
 
2593
         --  The loop here is a work-around for a problem on VMS; in some
2594
         --  circumstances (shared library and several executables, for
2595
         --  example), there are child processes other than compilation
2596
         --  processes that are received. Until this problem is resolved,
2597
         --  we will ignore such processes.
2598
 
2599
         loop
2600
            Wait_Process (Pid, OK);
2601
 
2602
            if Pid = Invalid_Pid then
2603
               return;
2604
            end if;
2605
 
2606
            for J in Running_Compile'First .. Outstanding_Compiles loop
2607
               if Pid = Running_Compile (J).Pid then
2608
                  Data    := Running_Compile (J);
2609
                  Project := Running_Compile (J).Project;
2610
 
2611
                  --  If a mapping file was used by this compilation, get its
2612
                  --  file name for reuse by a subsequent compilation.
2613
 
2614
                  if Running_Compile (J).Mapping_File /= No_Mapping_File then
2615
                     Comp_Data :=
2616
                       Project_Compilation_Htable.Get
2617
                         (Project_Compilation, Project);
2618
                     Comp_Data.Last_Free_Indices :=
2619
                       Comp_Data.Last_Free_Indices + 1;
2620
                     Comp_Data.Free_Mapping_File_Indices
2621
                       (Comp_Data.Last_Free_Indices) :=
2622
                         Running_Compile (J).Mapping_File;
2623
                  end if;
2624
 
2625
                  --  To actually remove this Pid and related info from
2626
                  --  Running_Compile replace its entry with the last valid
2627
                  --  entry in Running_Compile.
2628
 
2629
                  if J = Outstanding_Compiles then
2630
                     null;
2631
                  else
2632
                     Running_Compile (J) :=
2633
                       Running_Compile (Outstanding_Compiles);
2634
                  end if;
2635
 
2636
                  Outstanding_Compiles := Outstanding_Compiles - 1;
2637
                  return;
2638
               end if;
2639
            end loop;
2640
 
2641
            --  This child process was not one of our compilation processes;
2642
            --  just ignore it for now.
2643
 
2644
            --  Why is this commented out code sitting here???
2645
 
2646
            --  raise Program_Error;
2647
         end loop;
2648
      end Await_Compile;
2649
 
2650
      ---------------------------
2651
      -- Bad_Compilation_Count --
2652
      ---------------------------
2653
 
2654
      function Bad_Compilation_Count return Natural is
2655
      begin
2656
         return Bad_Compilation.Last - Bad_Compilation.First + 1;
2657
      end Bad_Compilation_Count;
2658
 
2659
      ----------------------------
2660
      -- Check_Standard_Library --
2661
      ----------------------------
2662
 
2663
      procedure Check_Standard_Library is
2664
      begin
2665
         Need_To_Check_Standard_Library := False;
2666
 
2667
         if not Targparm.Suppress_Standard_Library_On_Target then
2668
            declare
2669
               Sfile  : File_Name_Type;
2670
               Add_It : Boolean := True;
2671
 
2672
            begin
2673
               Name_Len := 0;
2674
               Add_Str_To_Name_Buffer (Standard_Library_Package_Body_Name);
2675
               Sfile := Name_Enter;
2676
 
2677
               --  If we have a special runtime, we add the standard
2678
               --  library only if we can find it.
2679
 
2680
               if RTS_Switch then
2681
                  Add_It := Full_Source_Name (Sfile) /= No_File;
2682
               end if;
2683
 
2684
               if Add_It then
2685
                  if Is_Marked (Sfile) then
2686
                     if Is_In_Obsoleted (Sfile) then
2687
                        Executable_Obsolete := True;
2688
                     end if;
2689
 
2690
                  else
2691
                     Insert_Q (Sfile, Index => 0);
2692
                     Mark (Sfile, Index => 0);
2693
                  end if;
2694
               end if;
2695
            end;
2696
         end if;
2697
      end Check_Standard_Library;
2698
 
2699
      -----------------------------------
2700
      -- Collect_Arguments_And_Compile --
2701
      -----------------------------------
2702
 
2703
      procedure Collect_Arguments_And_Compile
2704
        (Full_Source_File : File_Name_Type;
2705
         Lib_File         : File_Name_Type;
2706
         Source_Index     : Int;
2707
         Pid              : out Process_Id;
2708
         Process_Created  : out Boolean) is
2709
      begin
2710
         Process_Created := False;
2711
 
2712
         --  If we use mapping file (-P or -C switches), then get one
2713
 
2714
         if Create_Mapping_File then
2715
            Get_Mapping_File (Arguments_Project);
2716
         end if;
2717
 
2718
         --  If the source is part of a project file, we set the ADA_*_PATHs,
2719
         --  check for an eventual library project, and use the full path.
2720
 
2721
         if Arguments_Project /= No_Project then
2722
            if not Arguments_Project.Externally_Built then
2723
               Prj.Env.Set_Ada_Paths
2724
                 (Arguments_Project,
2725
                  Project_Tree,
2726
                  Including_Libraries => True);
2727
 
2728
               if not Unique_Compile
2729
                 and then MLib.Tgt.Support_For_Libraries /= Prj.None
2730
               then
2731
                  declare
2732
                     Prj : constant Project_Id :=
2733
                             Ultimate_Extending_Project_Of (Arguments_Project);
2734
 
2735
                  begin
2736
                     if Prj.Library
2737
                       and then not Prj.Externally_Built
2738
                       and then not Prj.Need_To_Build_Lib
2739
                     then
2740
                        --  Add to the Q all sources of the project that have
2741
                        --  not been marked.
2742
 
2743
                        Insert_Project_Sources
2744
                          (The_Project  => Prj,
2745
                           All_Projects => False,
2746
                           Into_Q       => True);
2747
 
2748
                        --  Now mark the project as processed
2749
 
2750
                        Prj.Need_To_Build_Lib := True;
2751
                     end if;
2752
                  end;
2753
               end if;
2754
 
2755
               Pid :=
2756
                 Compile
2757
                   (Project       => Arguments_Project,
2758
                    S             => File_Name_Type (Arguments_Path_Name),
2759
                    L             => Lib_File,
2760
                    Source_Index  => Source_Index,
2761
                    Args          => Arguments (1 .. Last_Argument));
2762
               Process_Created := True;
2763
            end if;
2764
 
2765
         else
2766
            --  If this is a source outside of any project file, make sure it
2767
            --  will be compiled in object directory of the main project file.
2768
 
2769
            Pid :=
2770
              Compile
2771
                (Project        => Main_Project,
2772
                 S              => Full_Source_File,
2773
                 L              => Lib_File,
2774
                 Source_Index   => Source_Index,
2775
                 Args           => Arguments (1 .. Last_Argument));
2776
            Process_Created := True;
2777
         end if;
2778
      end Collect_Arguments_And_Compile;
2779
 
2780
      -------------
2781
      -- Compile --
2782
      -------------
2783
 
2784
      function Compile
2785
        (Project      : Project_Id;
2786
         S            : File_Name_Type;
2787
         L            : File_Name_Type;
2788
         Source_Index : Int;
2789
         Args         : Argument_List) return Process_Id
2790
      is
2791
         Comp_Args : Argument_List (Args'First .. Args'Last + 10);
2792
         Comp_Next : Integer := Args'First;
2793
         Comp_Last : Integer;
2794
         Arg_Index : Integer;
2795
 
2796
         function Ada_File_Name (Name : File_Name_Type) return Boolean;
2797
         --  Returns True if Name is the name of an ada source file
2798
         --  (i.e. suffix is .ads or .adb)
2799
 
2800
         -------------------
2801
         -- Ada_File_Name --
2802
         -------------------
2803
 
2804
         function Ada_File_Name (Name : File_Name_Type) return Boolean is
2805
         begin
2806
            Get_Name_String (Name);
2807
            return
2808
              Name_Len > 4
2809
                and then Name_Buffer (Name_Len - 3 .. Name_Len - 1) = ".ad"
2810
                and then (Name_Buffer (Name_Len) = 'b'
2811
                            or else
2812
                          Name_Buffer (Name_Len) = 's');
2813
         end Ada_File_Name;
2814
 
2815
      --  Start of processing for Compile
2816
 
2817
      begin
2818
         Enter_Into_Obsoleted (S);
2819
 
2820
         --  By default, Syntax_Only is False
2821
 
2822
         Syntax_Only := False;
2823
 
2824
         for J in Args'Range loop
2825
            if Args (J).all = "-gnats" then
2826
 
2827
               --  If we compile with -gnats, the bind step and the link step
2828
               --  are inhibited. Also, we set Syntax_Only to True, so that
2829
               --  we don't fail when we don't find the ALI file, after
2830
               --  compilation.
2831
 
2832
               Do_Bind_Step := False;
2833
               Do_Link_Step := False;
2834
               Syntax_Only  := True;
2835
 
2836
            elsif Args (J).all = "-gnatc" then
2837
 
2838
               --  If we compile with -gnatc, the bind step and the link step
2839
               --  are inhibited. We set Syntax_Only to False for the case when
2840
               --  -gnats was previously specified.
2841
 
2842
               Do_Bind_Step := False;
2843
               Do_Link_Step := False;
2844
               Syntax_Only  := False;
2845
            end if;
2846
         end loop;
2847
 
2848
         Comp_Args (Comp_Next) := new String'("-gnatea");
2849
         Comp_Next := Comp_Next + 1;
2850
 
2851
         Comp_Args (Comp_Next) := Comp_Flag;
2852
         Comp_Next := Comp_Next + 1;
2853
 
2854
         --  Optimize the simple case where the gcc command line looks like
2855
         --     gcc -c -I. ... -I- file.adb
2856
         --  into
2857
         --     gcc -c ... file.adb
2858
 
2859
         if Args (Args'First).all = "-I" & Normalized_CWD
2860
           and then Args (Args'Last).all = "-I-"
2861
           and then S = Strip_Directory (S)
2862
         then
2863
            Comp_Last := Comp_Next + Args'Length - 3;
2864
            Arg_Index := Args'First + 1;
2865
 
2866
         else
2867
            Comp_Last := Comp_Next + Args'Length - 1;
2868
            Arg_Index := Args'First;
2869
         end if;
2870
 
2871
         --  Make a deep copy of the arguments, because Normalize_Arguments
2872
         --  may deallocate some arguments.
2873
 
2874
         for J in Comp_Next .. Comp_Last loop
2875
            Comp_Args (J) := new String'(Args (Arg_Index).all);
2876
            Arg_Index := Arg_Index + 1;
2877
         end loop;
2878
 
2879
         --  Set -gnatpg for predefined files (for this purpose the renamings
2880
         --  such as Text_IO do not count as predefined). Note that we strip
2881
         --  the directory name from the source file name because the call to
2882
         --  Fname.Is_Predefined_File_Name cannot deal with directory prefixes.
2883
 
2884
         declare
2885
            Fname : constant File_Name_Type := Strip_Directory (S);
2886
 
2887
         begin
2888
            if Is_Predefined_File_Name (Fname, False) then
2889
               if Check_Readonly_Files then
2890
                  Comp_Args (Comp_Args'First + 2 .. Comp_Last + 1) :=
2891
                    Comp_Args (Comp_Args'First + 1 .. Comp_Last);
2892
                  Comp_Last := Comp_Last + 1;
2893
                  Comp_Args (Comp_Args'First + 1) := GNAT_Flag;
2894
 
2895
               else
2896
                  Make_Failed
2897
                    ("not allowed to compile """ &
2898
                     Get_Name_String (Fname) &
2899
                     """; use -a switch, or compile file with " &
2900
                     """-gnatg"" switch");
2901
               end if;
2902
            end if;
2903
         end;
2904
 
2905
         --  Now check if the file name has one of the suffixes familiar to
2906
         --  the gcc driver. If this is not the case then add the ada flag
2907
         --  "-x ada".
2908
 
2909
         if not Ada_File_Name (S) and then not Targparm.AAMP_On_Target then
2910
            Comp_Last := Comp_Last + 1;
2911
            Comp_Args (Comp_Last) := Ada_Flag_1;
2912
            Comp_Last := Comp_Last + 1;
2913
            Comp_Args (Comp_Last) := Ada_Flag_2;
2914
         end if;
2915
 
2916
         if Source_Index /= 0 then
2917
            declare
2918
               Num : constant String := Source_Index'Img;
2919
            begin
2920
               Comp_Last := Comp_Last + 1;
2921
               Comp_Args (Comp_Last) :=
2922
                 new String'("-gnateI" & Num (Num'First + 1 .. Num'Last));
2923
            end;
2924
         end if;
2925
 
2926
         if Source_Index /= 0
2927
           or else L /= Strip_Directory (L)
2928
           or else Object_Directory_Path /= null
2929
         then
2930
            --  Build -o argument
2931
 
2932
            Get_Name_String (L);
2933
 
2934
            for J in reverse 1 .. Name_Len loop
2935
               if Name_Buffer (J) = '.' then
2936
                  Name_Len := J + Object_Suffix'Length - 1;
2937
                  Name_Buffer (J .. Name_Len) := Object_Suffix;
2938
                  exit;
2939
               end if;
2940
            end loop;
2941
 
2942
            Comp_Last := Comp_Last + 1;
2943
            Comp_Args (Comp_Last) := Output_Flag;
2944
            Comp_Last := Comp_Last + 1;
2945
 
2946
            --  If an object directory was specified, prepend the object file
2947
            --  name with this object directory.
2948
 
2949
            if Object_Directory_Path /= null then
2950
               Comp_Args (Comp_Last) :=
2951
                 new String'(Object_Directory_Path.all &
2952
                               Name_Buffer (1 .. Name_Len));
2953
 
2954
            else
2955
               Comp_Args (Comp_Last) :=
2956
                 new String'(Name_Buffer (1 .. Name_Len));
2957
            end if;
2958
         end if;
2959
 
2960
         if Create_Mapping_File and then Mapping_File_Arg /= null then
2961
            Comp_Last := Comp_Last + 1;
2962
            Comp_Args (Comp_Last) := new String'(Mapping_File_Arg.all);
2963
         end if;
2964
 
2965
         Get_Name_String (S);
2966
 
2967
         Comp_Last := Comp_Last + 1;
2968
         Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len));
2969
 
2970
         --  Change to object directory of the project file, if necessary
2971
 
2972
         if Project /= No_Project then
2973
            Change_To_Object_Directory (Project);
2974
         end if;
2975
 
2976
         GNAT.OS_Lib.Normalize_Arguments (Comp_Args (Args'First .. Comp_Last));
2977
 
2978
         Comp_Last := Comp_Last + 1;
2979
         Comp_Args (Comp_Last) := new String'("-gnatez");
2980
 
2981
         Display (Gcc.all, Comp_Args (Args'First .. Comp_Last));
2982
 
2983
         if Gcc_Path = null then
2984
            Make_Failed ("error, unable to locate " & Gcc.all);
2985
         end if;
2986
 
2987
         return
2988
           GNAT.OS_Lib.Non_Blocking_Spawn
2989
             (Gcc_Path.all, Comp_Args (Args'First .. Comp_Last));
2990
      end Compile;
2991
 
2992
      -------------------------------
2993
      -- Fill_Queue_From_ALI_Files --
2994
      -------------------------------
2995
 
2996
      procedure Fill_Queue_From_ALI_Files is
2997
         ALI          : ALI_Id;
2998
         Source_Index : Int;
2999
         Sfile        : File_Name_Type;
3000
         Uname        : Unit_Name_Type;
3001
         Unit_Name    : Name_Id;
3002
         Uid          : Prj.Unit_Index;
3003
 
3004
      begin
3005
         while Good_ALI_Present loop
3006
            ALI          := Get_Next_Good_ALI;
3007
            Source_Index := Unit_Index_Of (ALIs.Table (ALI).Afile);
3008
 
3009
            --  If we are processing the library file corresponding to the
3010
            --  main source file check if this source can be a main unit.
3011
 
3012
            if ALIs.Table (ALI).Sfile = Main_Source
3013
              and then Source_Index = Main_Index
3014
            then
3015
               Main_Unit := ALIs.Table (ALI).Main_Program /= None;
3016
            end if;
3017
 
3018
            --  The following adds the standard library (s-stalib) to the list
3019
            --  of files to be handled by gnatmake: this file and any files it
3020
            --  depends on are always included in every bind, even if they are
3021
            --  not in the explicit dependency list. Of course, it is not added
3022
            --  if Suppress_Standard_Library is True.
3023
 
3024
            --  However, to avoid annoying output about s-stalib.ali being read
3025
            --  only, when "-v" is used, we add the standard library only when
3026
            --  "-a" is used.
3027
 
3028
            if Need_To_Check_Standard_Library then
3029
               Check_Standard_Library;
3030
            end if;
3031
 
3032
            --  Now insert in the Q the unmarked source files (i.e. those which
3033
            --  have never been inserted in the Q and hence never considered).
3034
            --  Only do that if Unique_Compile is False.
3035
 
3036
            if not Unique_Compile then
3037
               for J in
3038
                 ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit
3039
               loop
3040
                  for K in
3041
                    Units.Table (J).First_With .. Units.Table (J).Last_With
3042
                  loop
3043
                     Sfile := Withs.Table (K).Sfile;
3044
                     Uname := Withs.Table (K).Uname;
3045
 
3046
                     --  If project files are used, find the proper source to
3047
                     --  compile in case Sfile is the spec but there is a body.
3048
 
3049
                     if Main_Project /= No_Project then
3050
                        Get_Name_String (Uname);
3051
                        Name_Len  := Name_Len - 2;
3052
                        Unit_Name := Name_Find;
3053
                        Uid :=
3054
                          Units_Htable.Get (Project_Tree.Units_HT, Unit_Name);
3055
 
3056
                        if Uid /= Prj.No_Unit_Index then
3057
                           if Uid.File_Names (Impl) /= null
3058
                             and then not Uid.File_Names (Impl).Locally_Removed
3059
                           then
3060
                              Sfile        := Uid.File_Names (Impl).File;
3061
                              Source_Index := Uid.File_Names (Impl).Index;
3062
 
3063
                           elsif Uid.File_Names (Spec) /= null
3064
                             and then not Uid.File_Names (Spec).Locally_Removed
3065
                           then
3066
                              Sfile        := Uid.File_Names (Spec).File;
3067
                              Source_Index := Uid.File_Names (Spec).Index;
3068
                           end if;
3069
                        end if;
3070
                     end if;
3071
 
3072
                     Dependencies.Append ((ALIs.Table (ALI).Sfile, Sfile));
3073
 
3074
                     if Is_In_Obsoleted (Sfile) then
3075
                        Executable_Obsolete := True;
3076
                     end if;
3077
 
3078
                     if Sfile = No_File then
3079
                        Debug_Msg ("Skipping generic:", Withs.Table (K).Uname);
3080
 
3081
                     else
3082
                        Source_Index := Unit_Index_Of (Withs.Table (K).Afile);
3083
 
3084
                        if Is_Marked (Sfile, Source_Index) then
3085
                           Debug_Msg ("Skipping marked file:", Sfile);
3086
 
3087
                        elsif not Check_Readonly_Files
3088
                          and then Is_Internal_File_Name (Sfile, False)
3089
                        then
3090
                           Debug_Msg ("Skipping internal file:", Sfile);
3091
 
3092
                        else
3093
                           Insert_Q
3094
                             (Sfile, Withs.Table (K).Uname, Source_Index);
3095
                           Mark (Sfile, Source_Index);
3096
                        end if;
3097
                     end if;
3098
                  end loop;
3099
               end loop;
3100
            end if;
3101
         end loop;
3102
      end Fill_Queue_From_ALI_Files;
3103
 
3104
      ----------------------
3105
      -- Get_Mapping_File --
3106
      ----------------------
3107
 
3108
      procedure Get_Mapping_File (Project : Project_Id) is
3109
         Data : Project_Compilation_Access;
3110
 
3111
      begin
3112
         Data := Project_Compilation_Htable.Get (Project_Compilation, Project);
3113
 
3114
         --  If there is a mapping file ready to be reused, reuse it
3115
 
3116
         if Data.Last_Free_Indices > 0 then
3117
            Mfile := Data.Free_Mapping_File_Indices (Data.Last_Free_Indices);
3118
            Data.Last_Free_Indices := Data.Last_Free_Indices - 1;
3119
 
3120
         --  Otherwise, create and initialize a new one
3121
 
3122
         else
3123
            Init_Mapping_File
3124
              (Project => Project, Data => Data.all, File_Index => Mfile);
3125
         end if;
3126
 
3127
         --  Put the name in the mapping file argument for the invocation
3128
         --  of the compiler.
3129
 
3130
         Free (Mapping_File_Arg);
3131
         Mapping_File_Arg :=
3132
           new String'("-gnatem=" &
3133
                       Get_Name_String (Data.Mapping_File_Names (Mfile)));
3134
      end Get_Mapping_File;
3135
 
3136
      -----------------------
3137
      -- Get_Next_Good_ALI --
3138
      -----------------------
3139
 
3140
      function Get_Next_Good_ALI return ALI_Id is
3141
         ALI : ALI_Id;
3142
 
3143
      begin
3144
         pragma Assert (Good_ALI_Present);
3145
         ALI := Good_ALI.Table (Good_ALI.Last);
3146
         Good_ALI.Decrement_Last;
3147
         return ALI;
3148
      end Get_Next_Good_ALI;
3149
 
3150
      ----------------------
3151
      -- Good_ALI_Present --
3152
      ----------------------
3153
 
3154
      function Good_ALI_Present return Boolean is
3155
      begin
3156
         return Good_ALI.First <= Good_ALI.Last;
3157
      end Good_ALI_Present;
3158
 
3159
      --------------------------------
3160
      -- Must_Exit_Because_Of_Error --
3161
      --------------------------------
3162
 
3163
      function Must_Exit_Because_Of_Error return Boolean is
3164
         Data    : Compilation_Data;
3165
         Success : Boolean;
3166
 
3167
      begin
3168
         if Bad_Compilation_Count > 0 and then not Keep_Going then
3169
            while Outstanding_Compiles > 0 loop
3170
               Await_Compile (Data, Success);
3171
 
3172
               if not Success then
3173
                  Record_Failure (Data.Full_Source_File, Data.Source_Unit);
3174
               end if;
3175
            end loop;
3176
 
3177
            return True;
3178
         end if;
3179
 
3180
         return False;
3181
      end Must_Exit_Because_Of_Error;
3182
 
3183
      --------------------
3184
      -- Record_Failure --
3185
      --------------------
3186
 
3187
      procedure Record_Failure
3188
        (File  : File_Name_Type;
3189
         Unit  : Unit_Name_Type;
3190
         Found : Boolean := True)
3191
      is
3192
      begin
3193
         Bad_Compilation.Increment_Last;
3194
         Bad_Compilation.Table (Bad_Compilation.Last) := (File, Unit, Found);
3195
      end Record_Failure;
3196
 
3197
      ---------------------
3198
      -- Record_Good_ALI --
3199
      ---------------------
3200
 
3201
      procedure Record_Good_ALI (A : ALI_Id) is
3202
      begin
3203
         Good_ALI.Increment_Last;
3204
         Good_ALI.Table (Good_ALI.Last) := A;
3205
      end Record_Good_ALI;
3206
 
3207
      -------------------------------
3208
      -- Start_Compile_If_Possible --
3209
      -------------------------------
3210
 
3211
      function Start_Compile_If_Possible
3212
        (Args : Argument_List) return Boolean
3213
      is
3214
         In_Lib_Dir      : Boolean;
3215
         Need_To_Compile : Boolean;
3216
         Pid             : Process_Id;
3217
         Process_Created : Boolean;
3218
 
3219
         Source_File      : File_Name_Type;
3220
         Full_Source_File : File_Name_Type;
3221
         Source_File_Attr : aliased File_Attributes;
3222
         --  The full name of the source file and its attributes (size, ...)
3223
 
3224
         Source_Unit  : Unit_Name_Type;
3225
         Source_Index : Int;
3226
         --  Index of the current unit in the current source file
3227
 
3228
         Lib_File      : File_Name_Type;
3229
         Full_Lib_File : File_Name_Type;
3230
         Lib_File_Attr : aliased File_Attributes;
3231
         Read_Only     : Boolean := False;
3232
         ALI           : ALI_Id;
3233
         --  The ALI file and its attributes (size, stamp, ...)
3234
 
3235
         Obj_File  : File_Name_Type;
3236
         Obj_Stamp : Time_Stamp_Type;
3237
         --  The object file
3238
 
3239
      begin
3240
         if not Empty_Q and then Outstanding_Compiles < Max_Process then
3241
            Extract_From_Q (Source_File, Source_Unit, Source_Index);
3242
 
3243
            Osint.Full_Source_Name
3244
              (Source_File,
3245
               Full_File => Full_Source_File,
3246
               Attr      => Source_File_Attr'Access);
3247
 
3248
            Lib_File := Osint.Lib_File_Name (Source_File, Source_Index);
3249
 
3250
            --  ??? This call could be avoided when using projects, since we
3251
            --  know where the ALI file is supposed to be. That would avoid
3252
            --  searches in the object directories, including in the runtime
3253
            --  dir. However, that would require getting access to the
3254
            --  Source_Id.
3255
 
3256
            Osint.Full_Lib_File_Name
3257
              (Lib_File,
3258
               Lib_File => Full_Lib_File,
3259
               Attr     => Lib_File_Attr);
3260
 
3261
            --  If source has already been compiled, executable is obsolete
3262
 
3263
            if Is_In_Obsoleted (Source_File) then
3264
               Executable_Obsolete := True;
3265
            end if;
3266
 
3267
            In_Lib_Dir := Full_Lib_File /= No_File
3268
              and then In_Ada_Lib_Dir (Full_Lib_File);
3269
 
3270
            --  Since the following requires a system call, we precompute it
3271
            --  when needed.
3272
 
3273
            if not In_Lib_Dir then
3274
               if Full_Lib_File /= No_File
3275
                 and then not Check_Readonly_Files
3276
               then
3277
                  Get_Name_String (Full_Lib_File);
3278
                  Name_Buffer (Name_Len + 1) := ASCII.NUL;
3279
                  Read_Only := not Is_Writable_File
3280
                    (Name_Buffer'Address, Lib_File_Attr'Access);
3281
               else
3282
                  Read_Only := False;
3283
               end if;
3284
            end if;
3285
 
3286
            --  If the library file is an Ada library skip it
3287
 
3288
            if In_Lib_Dir then
3289
               Verbose_Msg
3290
                 (Lib_File,
3291
                  "is in an Ada library",
3292
                  Prefix => "  ",
3293
                  Minimum_Verbosity => Opt.High);
3294
 
3295
               --  If the library file is a read-only library skip it, but only
3296
               --  if, when using project files, this library file is in the
3297
               --  right object directory (a read-only ALI file in the object
3298
               --  directory of a project being extended must not be skipped).
3299
 
3300
            elsif Read_Only
3301
              and then Is_In_Object_Directory (Source_File, Full_Lib_File)
3302
            then
3303
               Verbose_Msg
3304
                 (Lib_File,
3305
                  "is a read-only library",
3306
                  Prefix => "  ",
3307
                  Minimum_Verbosity => Opt.High);
3308
 
3309
               --  The source file that we are checking cannot be located
3310
 
3311
            elsif Full_Source_File = No_File then
3312
               Record_Failure (Source_File, Source_Unit, False);
3313
 
3314
               --  Source and library files can be located but are internal
3315
               --  files.
3316
 
3317
            elsif not Check_Readonly_Files
3318
              and then Full_Lib_File /= No_File
3319
              and then Is_Internal_File_Name (Source_File, False)
3320
            then
3321
               if Force_Compilations then
3322
                  Fail
3323
                    ("not allowed to compile """ &
3324
                     Get_Name_String (Source_File) &
3325
                     """; use -a switch, or compile file with " &
3326
                     """-gnatg"" switch");
3327
               end if;
3328
 
3329
               Verbose_Msg
3330
                 (Lib_File,
3331
                  "is an internal library",
3332
                  Prefix => "  ",
3333
                  Minimum_Verbosity => Opt.High);
3334
 
3335
               --  The source file that we are checking can be located
3336
 
3337
            else
3338
               Collect_Arguments (Source_File, Source_Index,
3339
                                  Source_File = Main_Source, Args);
3340
 
3341
               --  Do nothing if project of source is externally built
3342
 
3343
               if Arguments_Project = No_Project
3344
                 or else not Arguments_Project.Externally_Built
3345
               then
3346
                  --  Don't waste any time if we have to recompile anyway
3347
 
3348
                  Obj_Stamp       := Empty_Time_Stamp;
3349
                  Need_To_Compile := Force_Compilations;
3350
 
3351
                  if not Force_Compilations then
3352
                     Check (Source_File    => Source_File,
3353
                            Source_Index   => Source_Index,
3354
                            Is_Main_Source => Source_File = Main_Source,
3355
                            The_Args       => Args,
3356
                            Lib_File       => Lib_File,
3357
                            Full_Lib_File  => Full_Lib_File,
3358
                            Lib_File_Attr  => Lib_File_Attr'Access,
3359
                            Read_Only      => Read_Only,
3360
                            ALI            => ALI,
3361
                            O_File         => Obj_File,
3362
                            O_Stamp        => Obj_Stamp);
3363
                     Need_To_Compile := (ALI = No_ALI_Id);
3364
                  end if;
3365
 
3366
                  if not Need_To_Compile then
3367
 
3368
                     --  The ALI file is up-to-date; record its Id
3369
 
3370
                     Record_Good_ALI (ALI);
3371
 
3372
                     --  Record the time stamp of the most recent object
3373
                     --  file as long as no (re)compilations are needed.
3374
 
3375
                     if First_Compiled_File = No_File
3376
                       and then (Most_Recent_Obj_File = No_File
3377
                                  or else Obj_Stamp > Most_Recent_Obj_Stamp)
3378
                     then
3379
                        Most_Recent_Obj_File  := Obj_File;
3380
                        Most_Recent_Obj_Stamp := Obj_Stamp;
3381
                     end if;
3382
 
3383
                  else
3384
                     --  Check that switch -x has been used if a source outside
3385
                     --  of project files need to be compiled.
3386
 
3387
                     if Main_Project /= No_Project
3388
                       and then Arguments_Project = No_Project
3389
                       and then not External_Unit_Compilation_Allowed
3390
                     then
3391
                        Make_Failed ("external source ("
3392
                                     & Get_Name_String (Source_File)
3393
                                     & ") is not part of any project;"
3394
                                     & " cannot be compiled without"
3395
                                     & " gnatmake switch -x");
3396
                     end if;
3397
 
3398
                     --  Is this the first file we have to compile?
3399
 
3400
                     if First_Compiled_File = No_File then
3401
                        First_Compiled_File  := Full_Source_File;
3402
                        Most_Recent_Obj_File := No_File;
3403
 
3404
                        if Do_Not_Execute then
3405
 
3406
                           --  Exit the main loop
3407
 
3408
                           return True;
3409
                        end if;
3410
                     end if;
3411
 
3412
                     --  Compute where the ALI file must be generated in
3413
                     --  In_Place_Mode (this does not require to know the
3414
                     --  location of the object directory).
3415
 
3416
                     if In_Place_Mode then
3417
                        if Full_Lib_File = No_File then
3418
 
3419
                           --  If the library file was not found, then save
3420
                           --  the library file near the source file.
3421
 
3422
                           Lib_File :=
3423
                             Osint.Lib_File_Name
3424
                               (Full_Source_File, Source_Index);
3425
                           Full_Lib_File := Lib_File;
3426
 
3427
                        else
3428
                           --  If the library file was found, then save the
3429
                           --  library file in the same place.
3430
 
3431
                           Lib_File := Full_Lib_File;
3432
                        end if;
3433
                     end if;
3434
 
3435
                     --  Start the compilation and record it. We can do this
3436
                     --  because there is at least one free process. This might
3437
                     --  change the current directory.
3438
 
3439
                     Collect_Arguments_And_Compile
3440
                       (Full_Source_File => Full_Source_File,
3441
                        Lib_File         => Lib_File,
3442
                        Source_Index     => Source_Index,
3443
                        Pid              => Pid,
3444
                        Process_Created  => Process_Created);
3445
 
3446
                     --  Compute where the ALI file will be generated (for
3447
                     --  cases that might require to know the current
3448
                     --  directory). The current directory might be changed
3449
                     --  when compiling other files so we cannot rely on it
3450
                     --  being the same to find the resulting ALI file.
3451
 
3452
                     if not In_Place_Mode then
3453
 
3454
                        --  Compute the expected location of the ALI file. This
3455
                        --  can be from several places:
3456
                        --    -i => in place mode. In such a case,
3457
                        --          Full_Lib_File has already been set above
3458
                        --    -D => if specified
3459
                        --    or defaults in current dir
3460
                        --  We could simply use a call similar to
3461
                        --     Osint.Full_Lib_File_Name (Lib_File)
3462
                        --  but that involves system calls and is thus slower
3463
 
3464
                        if Object_Directory_Path /= null then
3465
                           Name_Len := 0;
3466
                           Add_Str_To_Name_Buffer (Object_Directory_Path.all);
3467
                           Add_Str_To_Name_Buffer (Get_Name_String (Lib_File));
3468
                           Full_Lib_File := Name_Find;
3469
 
3470
                        else
3471
                           if Project_Of_Current_Object_Directory /=
3472
                             No_Project
3473
                           then
3474
                              Get_Name_String
3475
                                (Project_Of_Current_Object_Directory
3476
                                 .Object_Directory.Name);
3477
                              Add_Str_To_Name_Buffer
3478
                                (Get_Name_String (Lib_File));
3479
                              Full_Lib_File := Name_Find;
3480
 
3481
                           else
3482
                              Full_Lib_File := Lib_File;
3483
                           end if;
3484
                        end if;
3485
 
3486
                     end if;
3487
 
3488
                     Lib_File_Attr := Unknown_Attributes;
3489
 
3490
                     --  Make sure we could successfully start the compilation
3491
 
3492
                     if Process_Created then
3493
                        if Pid = Invalid_Pid then
3494
                           Record_Failure (Full_Source_File, Source_Unit);
3495
                        else
3496
                           Add_Process
3497
                             (Pid           => Pid,
3498
                              Sfile         => Full_Source_File,
3499
                              Afile         => Lib_File,
3500
                              Uname         => Source_Unit,
3501
                              Mfile         => Mfile,
3502
                              Full_Lib_File => Full_Lib_File,
3503
                              Lib_File_Attr => Lib_File_Attr);
3504
                        end if;
3505
                     end if;
3506
                  end if;
3507
               end if;
3508
            end if;
3509
         end if;
3510
         return False;
3511
      end Start_Compile_If_Possible;
3512
 
3513
      -----------------------------
3514
      -- Wait_For_Available_Slot --
3515
      -----------------------------
3516
 
3517
      procedure Wait_For_Available_Slot is
3518
         Compilation_OK : Boolean;
3519
         Text           : Text_Buffer_Ptr;
3520
         ALI            : ALI_Id;
3521
         Data           : Compilation_Data;
3522
 
3523
      begin
3524
         if Outstanding_Compiles = Max_Process
3525
           or else (Empty_Q
3526
                     and then not Good_ALI_Present
3527
                     and then Outstanding_Compiles > 0)
3528
         then
3529
            Await_Compile (Data, Compilation_OK);
3530
 
3531
            if not Compilation_OK then
3532
               Record_Failure (Data.Full_Source_File, Data.Source_Unit);
3533
            end if;
3534
 
3535
            if Compilation_OK or else Keep_Going then
3536
 
3537
               --  Re-read the updated library file
3538
 
3539
               declare
3540
                  Saved_Object_Consistency : constant Boolean :=
3541
                                               Check_Object_Consistency;
3542
 
3543
               begin
3544
                  --  If compilation was not OK, or if output is not an object
3545
                  --  file and we don't do the bind step, don't check for
3546
                  --  object consistency.
3547
 
3548
                  Check_Object_Consistency :=
3549
                    Check_Object_Consistency
3550
                      and Compilation_OK
3551
                      and (Output_Is_Object or Do_Bind_Step);
3552
 
3553
                  Text :=
3554
                    Read_Library_Info_From_Full
3555
                      (Data.Full_Lib_File, Data.Lib_File_Attr'Access);
3556
 
3557
                  --  Restore Check_Object_Consistency to its initial value
3558
 
3559
                  Check_Object_Consistency := Saved_Object_Consistency;
3560
               end;
3561
 
3562
               --  If an ALI file was generated by this compilation, scan the
3563
               --  ALI file and record it.
3564
 
3565
               --  If the scan fails, a previous ali file is inconsistent with
3566
               --  the unit just compiled.
3567
 
3568
               if Text /= null then
3569
                  ALI :=
3570
                    Scan_ALI
3571
                      (Data.Lib_File, Text, Ignore_ED => False, Err => True);
3572
 
3573
                  if ALI = No_ALI_Id then
3574
 
3575
                     --  Record a failure only if not already done
3576
 
3577
                     if Compilation_OK then
3578
                        Inform
3579
                          (Data.Lib_File,
3580
                           "incompatible ALI file, please recompile");
3581
                        Record_Failure
3582
                          (Data.Full_Source_File, Data.Source_Unit);
3583
                     end if;
3584
 
3585
                  else
3586
                     Record_Good_ALI (ALI);
3587
                  end if;
3588
 
3589
                  Free (Text);
3590
 
3591
               --  If we could not read the ALI file that was just generated
3592
               --  then there could be a problem reading either the ALI or the
3593
               --  corresponding object file (if Check_Object_Consistency is
3594
               --  set Read_Library_Info checks that the time stamp of the
3595
               --  object file is more recent than that of the ALI). However,
3596
               --  we record a failure only if not already done.
3597
 
3598
               else
3599
                  if Compilation_OK and not Syntax_Only then
3600
                     Inform
3601
                       (Data.Lib_File,
3602
                        "WARNING: ALI or object file not found after compile");
3603
                     Record_Failure (Data.Full_Source_File, Data.Source_Unit);
3604
                  end if;
3605
               end if;
3606
            end if;
3607
         end if;
3608
      end Wait_For_Available_Slot;
3609
 
3610
   --  Start of processing for Compile_Sources
3611
 
3612
   begin
3613
      pragma Assert (Args'First = 1);
3614
 
3615
      Outstanding_Compiles := 0;
3616
      Running_Compile := new Comp_Data_Arr (1 .. Max_Process);
3617
 
3618
      --  Package and Queue initializations
3619
 
3620
      Good_ALI.Init;
3621
 
3622
      if First_Q_Initialization then
3623
         Init_Q;
3624
      end if;
3625
 
3626
      if Initialize_ALI_Data then
3627
         Initialize_ALI;
3628
         Initialize_ALI_Source;
3629
      end if;
3630
 
3631
      --  The following two flags affect the behavior of ALI.Set_Source_Table.
3632
      --  We set Check_Source_Files to True to ensure that source file time
3633
      --  stamps are checked, and we set All_Sources to False to avoid checking
3634
      --  the presence of the source files listed in the source dependency
3635
      --  section of an ali file (which would be a mistake since the ali file
3636
      --  may be obsolete).
3637
 
3638
      Check_Source_Files := True;
3639
      All_Sources        := False;
3640
 
3641
      --  Only insert in the Q if it is not already done, to avoid simultaneous
3642
      --  compilations if -jnnn is used.
3643
 
3644
      if not Is_Marked (Main_Source, Main_Index) then
3645
         Insert_Q (Main_Source, Index => Main_Index);
3646
         Mark (Main_Source, Main_Index);
3647
      end if;
3648
 
3649
      First_Compiled_File   := No_File;
3650
      Most_Recent_Obj_File  := No_File;
3651
      Most_Recent_Obj_Stamp := Empty_Time_Stamp;
3652
      Main_Unit             := False;
3653
 
3654
      --  Keep looping until there is no more work to do (the Q is empty)
3655
      --  and all the outstanding compilations have terminated.
3656
 
3657
      Make_Loop : while not Empty_Q or else Outstanding_Compiles > 0 loop
3658
         exit Make_Loop when Must_Exit_Because_Of_Error;
3659
         exit Make_Loop when Start_Compile_If_Possible (Args);
3660
 
3661
         Wait_For_Available_Slot;
3662
 
3663
         --  ??? Should be done as soon as we add a Good_ALI, wouldn't it avoid
3664
         --  the need for a list of good ALI?
3665
 
3666
         Fill_Queue_From_ALI_Files;
3667
 
3668
         if Display_Compilation_Progress then
3669
            Write_Str ("completed ");
3670
            Write_Int (Int (Q_Front));
3671
            Write_Str (" out of ");
3672
            Write_Int (Int (Q.Last));
3673
            Write_Str (" (");
3674
            Write_Int (Int ((Q_Front * 100) / (Q.Last - Q.First)));
3675
            Write_Str ("%)...");
3676
            Write_Eol;
3677
         end if;
3678
      end loop Make_Loop;
3679
 
3680
      Compilation_Failures := Bad_Compilation_Count;
3681
 
3682
      --  Compilation is finished
3683
 
3684
      --  Delete any temporary configuration pragma file
3685
 
3686
      if not Debug.Debug_Flag_N then
3687
         Delete_Temp_Config_Files;
3688
      end if;
3689
   end Compile_Sources;
3690
 
3691
   ----------------------------------
3692
   -- Configuration_Pragmas_Switch --
3693
   ----------------------------------
3694
 
3695
   function Configuration_Pragmas_Switch
3696
     (For_Project : Project_Id) return Argument_List
3697
   is
3698
      The_Packages : Package_Id;
3699
      Gnatmake     : Package_Id;
3700
      Compiler     : Package_Id;
3701
 
3702
      Global_Attribute : Variable_Value := Nil_Variable_Value;
3703
      Local_Attribute  : Variable_Value := Nil_Variable_Value;
3704
 
3705
      Global_Attribute_Present : Boolean := False;
3706
      Local_Attribute_Present  : Boolean := False;
3707
 
3708
      Result : Argument_List (1 .. 3);
3709
      Last   : Natural := 0;
3710
 
3711
      function Absolute_Path
3712
        (Path    : Path_Name_Type;
3713
         Project : Project_Id) return String;
3714
      --  Returns an absolute path for a configuration pragmas file
3715
 
3716
      -------------------
3717
      -- Absolute_Path --
3718
      -------------------
3719
 
3720
      function Absolute_Path
3721
        (Path    : Path_Name_Type;
3722
         Project : Project_Id) return String
3723
      is
3724
      begin
3725
         Get_Name_String (Path);
3726
 
3727
         declare
3728
            Path_Name : constant String := Name_Buffer (1 .. Name_Len);
3729
 
3730
         begin
3731
            if Is_Absolute_Path (Path_Name) then
3732
               return Path_Name;
3733
 
3734
            else
3735
               declare
3736
                  Parent_Directory : constant String :=
3737
                    Get_Name_String (Project.Directory.Display_Name);
3738
 
3739
               begin
3740
                  if Parent_Directory (Parent_Directory'Last) =
3741
                                                 Directory_Separator
3742
                  then
3743
                     return Parent_Directory & Path_Name;
3744
 
3745
                  else
3746
                     return Parent_Directory & Directory_Separator & Path_Name;
3747
                  end if;
3748
               end;
3749
            end if;
3750
         end;
3751
      end Absolute_Path;
3752
 
3753
   --  Start of processing for Configuration_Pragmas_Switch
3754
 
3755
   begin
3756
      Prj.Env.Create_Config_Pragmas_File
3757
        (For_Project, Project_Tree);
3758
 
3759
      if For_Project.Config_File_Name /= No_Path then
3760
         Temporary_Config_File := For_Project.Config_File_Temp;
3761
         Last := 1;
3762
         Result (1) :=
3763
           new String'
3764
                 ("-gnatec=" & Get_Name_String (For_Project.Config_File_Name));
3765
 
3766
      else
3767
         Temporary_Config_File := False;
3768
      end if;
3769
 
3770
      --  Check for attribute Builder'Global_Configuration_Pragmas
3771
 
3772
      The_Packages := Main_Project.Decl.Packages;
3773
      Gnatmake :=
3774
        Prj.Util.Value_Of
3775
          (Name        => Name_Builder,
3776
           In_Packages => The_Packages,
3777
           In_Tree     => Project_Tree);
3778
 
3779
      if Gnatmake /= No_Package then
3780
         Global_Attribute := Prj.Util.Value_Of
3781
           (Variable_Name => Name_Global_Configuration_Pragmas,
3782
            In_Variables  => Project_Tree.Packages.Table
3783
                               (Gnatmake).Decl.Attributes,
3784
            In_Tree       => Project_Tree);
3785
         Global_Attribute_Present :=
3786
           Global_Attribute /= Nil_Variable_Value
3787
           and then Get_Name_String (Global_Attribute.Value) /= "";
3788
 
3789
         if Global_Attribute_Present then
3790
            declare
3791
               Path : constant String :=
3792
                        Absolute_Path
3793
                          (Path_Name_Type (Global_Attribute.Value),
3794
                           Global_Attribute.Project);
3795
            begin
3796
               if not Is_Regular_File (Path) then
3797
                  if Debug.Debug_Flag_F then
3798
                     Make_Failed
3799
                       ("cannot find configuration pragmas file "
3800
                        & File_Name (Path));
3801
                  else
3802
                     Make_Failed
3803
                       ("cannot find configuration pragmas file " & Path);
3804
                  end if;
3805
               end if;
3806
 
3807
               Last := Last + 1;
3808
               Result (Last) := new String'("-gnatec=" &  Path);
3809
            end;
3810
         end if;
3811
      end if;
3812
 
3813
      --  Check for attribute Compiler'Local_Configuration_Pragmas
3814
 
3815
      The_Packages := For_Project.Decl.Packages;
3816
      Compiler :=
3817
        Prj.Util.Value_Of
3818
          (Name        => Name_Compiler,
3819
           In_Packages => The_Packages,
3820
           In_Tree     => Project_Tree);
3821
 
3822
      if Compiler /= No_Package then
3823
         Local_Attribute := Prj.Util.Value_Of
3824
           (Variable_Name => Name_Local_Configuration_Pragmas,
3825
            In_Variables  => Project_Tree.Packages.Table
3826
                               (Compiler).Decl.Attributes,
3827
            In_Tree       => Project_Tree);
3828
         Local_Attribute_Present :=
3829
           Local_Attribute /= Nil_Variable_Value
3830
           and then Get_Name_String (Local_Attribute.Value) /= "";
3831
 
3832
         if Local_Attribute_Present then
3833
            declare
3834
               Path : constant String :=
3835
                        Absolute_Path
3836
                          (Path_Name_Type (Local_Attribute.Value),
3837
                           Local_Attribute.Project);
3838
            begin
3839
               if not Is_Regular_File (Path) then
3840
                  if Debug.Debug_Flag_F then
3841
                     Make_Failed
3842
                       ("cannot find configuration pragmas file "
3843
                        & File_Name (Path));
3844
 
3845
                  else
3846
                     Make_Failed
3847
                       ("cannot find configuration pragmas file " & Path);
3848
                  end if;
3849
               end if;
3850
 
3851
               Last := Last + 1;
3852
               Result (Last) := new String'("-gnatec=" & Path);
3853
            end;
3854
         end if;
3855
      end if;
3856
 
3857
      return Result (1 .. Last);
3858
   end Configuration_Pragmas_Switch;
3859
 
3860
   ---------------
3861
   -- Debug_Msg --
3862
   ---------------
3863
 
3864
   procedure Debug_Msg (S : String; N : Name_Id) is
3865
   begin
3866
      if Debug.Debug_Flag_W then
3867
         Write_Str ("   ... ");
3868
         Write_Str (S);
3869
         Write_Str (" ");
3870
         Write_Name (N);
3871
         Write_Eol;
3872
      end if;
3873
   end Debug_Msg;
3874
 
3875
   procedure Debug_Msg (S : String; N : File_Name_Type) is
3876
   begin
3877
      Debug_Msg (S, Name_Id (N));
3878
   end Debug_Msg;
3879
 
3880
   procedure Debug_Msg (S : String; N : Unit_Name_Type) is
3881
   begin
3882
      Debug_Msg (S, Name_Id (N));
3883
   end Debug_Msg;
3884
 
3885
   ---------------------------
3886
   -- Delete_All_Temp_Files --
3887
   ---------------------------
3888
 
3889
   procedure Delete_All_Temp_Files is
3890
   begin
3891
      if not Debug.Debug_Flag_N then
3892
         Delete_Temp_Config_Files;
3893
         Prj.Delete_All_Temp_Files (Project_Tree);
3894
      end if;
3895
   end Delete_All_Temp_Files;
3896
 
3897
   ------------------------------
3898
   -- Delete_Temp_Config_Files --
3899
   ------------------------------
3900
 
3901
   procedure Delete_Temp_Config_Files is
3902
      Success : Boolean;
3903
      Proj    : Project_List;
3904
      pragma Warnings (Off, Success);
3905
 
3906
   begin
3907
      --  The caller is responsible for ensuring that Debug_Flag_N is False
3908
 
3909
      pragma Assert (not Debug.Debug_Flag_N);
3910
 
3911
      if Main_Project /= No_Project then
3912
         Proj := Project_Tree.Projects;
3913
         while Proj /= null loop
3914
            if Proj.Project.Config_File_Temp then
3915
               Delete_Temporary_File
3916
                 (Project_Tree, Proj.Project.Config_File_Name);
3917
 
3918
               --  Make sure that we don't have a config file for this project,
3919
               --  in case there are several mains. In this case, we will
3920
               --  recreate another config file: we cannot reuse the one that
3921
               --  we just deleted!
3922
 
3923
               Proj.Project.Config_Checked   := False;
3924
               Proj.Project.Config_File_Name := No_Path;
3925
               Proj.Project.Config_File_Temp := False;
3926
            end if;
3927
            Proj := Proj.Next;
3928
         end loop;
3929
      end if;
3930
   end Delete_Temp_Config_Files;
3931
 
3932
   -------------
3933
   -- Display --
3934
   -------------
3935
 
3936
   procedure Display (Program : String; Args : Argument_List) is
3937
   begin
3938
      pragma Assert (Args'First = 1);
3939
 
3940
      if Display_Executed_Programs then
3941
         Write_Str (Program);
3942
 
3943
         for J in Args'Range loop
3944
 
3945
            --  Never display -gnatea nor -gnatez
3946
 
3947
            if Args (J).all /= "-gnatea"
3948
                 and then
3949
               Args (J).all /= "-gnatez"
3950
            then
3951
               --  Do not display the mapping file argument automatically
3952
               --  created when using a project file.
3953
 
3954
               if Main_Project = No_Project
3955
                 or else Debug.Debug_Flag_N
3956
                 or else Args (J)'Length < 8
3957
                 or else
3958
                   Args (J) (Args (J)'First .. Args (J)'First + 6) /= "-gnatem"
3959
               then
3960
                  --  When -dn is not specified, do not display the config
3961
                  --  pragmas switch (-gnatec) for the temporary file created
3962
                  --  by the project manager (always the first -gnatec switch).
3963
                  --  Reset Temporary_Config_File to False so that the eventual
3964
                  --  other -gnatec switches will be displayed.
3965
 
3966
                  if (not Debug.Debug_Flag_N)
3967
                    and then Temporary_Config_File
3968
                    and then Args (J)'Length > 7
3969
                    and then Args (J) (Args (J)'First .. Args (J)'First + 6)
3970
                    = "-gnatec"
3971
                  then
3972
                     Temporary_Config_File := False;
3973
 
3974
                     --  Do not display the -F=mapping_file switch for gnatbind
3975
                     --  if -dn is not specified.
3976
 
3977
                  elsif Debug.Debug_Flag_N
3978
                    or else Args (J)'Length < 4
3979
                    or else
3980
                      Args (J) (Args (J)'First .. Args (J)'First + 2) /= "-F="
3981
                  then
3982
                     Write_Str (" ");
3983
 
3984
                     --  If -df is used, only display file names, not path
3985
                     --  names.
3986
 
3987
                     if Debug.Debug_Flag_F then
3988
                        declare
3989
                           Equal_Pos : Natural;
3990
                        begin
3991
                           Equal_Pos := Args (J)'First - 1;
3992
                           for K in Args (J)'Range loop
3993
                              if Args (J) (K) = '=' then
3994
                                 Equal_Pos := K;
3995
                                 exit;
3996
                              end if;
3997
                           end loop;
3998
 
3999
                           if Is_Absolute_Path
4000
                             (Args (J) (Equal_Pos + 1 .. Args (J)'Last))
4001
                           then
4002
                              Write_Str
4003
                                (Args (J) (Args (J)'First .. Equal_Pos));
4004
                              Write_Str
4005
                                (File_Name
4006
                                   (Args (J)
4007
                                    (Equal_Pos + 1 .. Args (J)'Last)));
4008
 
4009
                           else
4010
                              Write_Str (Args (J).all);
4011
                           end if;
4012
                        end;
4013
 
4014
                     else
4015
                        Write_Str (Args (J).all);
4016
                     end if;
4017
                  end if;
4018
               end if;
4019
            end if;
4020
         end loop;
4021
 
4022
         Write_Eol;
4023
      end if;
4024
   end Display;
4025
 
4026
   ----------------------
4027
   -- Display_Commands --
4028
   ----------------------
4029
 
4030
   procedure Display_Commands (Display : Boolean := True) is
4031
   begin
4032
      Display_Executed_Programs := Display;
4033
   end Display_Commands;
4034
 
4035
   -------------
4036
   -- Empty_Q --
4037
   -------------
4038
 
4039
   function Empty_Q return Boolean is
4040
   begin
4041
      if Debug.Debug_Flag_P then
4042
         Write_Str ("   Q := [");
4043
 
4044
         for J in Q_Front .. Q.Last - 1 loop
4045
            Write_Str (" ");
4046
            Write_Name (Q.Table (J).File);
4047
            Write_Eol;
4048
            Write_Str ("         ");
4049
         end loop;
4050
 
4051
         Write_Str ("]");
4052
         Write_Eol;
4053
      end if;
4054
 
4055
      return Q_Front >= Q.Last;
4056
   end Empty_Q;
4057
 
4058
   --------------------------
4059
   -- Enter_Into_Obsoleted --
4060
   --------------------------
4061
 
4062
   procedure Enter_Into_Obsoleted (F : File_Name_Type) is
4063
      Name  : constant String := Get_Name_String (F);
4064
      First : Natural;
4065
      F2    : File_Name_Type;
4066
 
4067
   begin
4068
      First := Name'Last;
4069
      while First > Name'First
4070
        and then Name (First - 1) /= Directory_Separator
4071
        and then Name (First - 1) /= '/'
4072
      loop
4073
         First := First - 1;
4074
      end loop;
4075
 
4076
      if First /= Name'First then
4077
         Name_Len := 0;
4078
         Add_Str_To_Name_Buffer (Name (First .. Name'Last));
4079
         F2 := Name_Find;
4080
 
4081
      else
4082
         F2 := F;
4083
      end if;
4084
 
4085
      Debug_Msg ("New entry in Obsoleted table:", F2);
4086
      Obsoleted.Set (F2, True);
4087
   end Enter_Into_Obsoleted;
4088
 
4089
   --------------------
4090
   -- Extract_From_Q --
4091
   --------------------
4092
 
4093
   procedure Extract_From_Q
4094
     (Source_File  : out File_Name_Type;
4095
      Source_Unit  : out Unit_Name_Type;
4096
      Source_Index : out Int)
4097
   is
4098
      File  : constant File_Name_Type := Q.Table (Q_Front).File;
4099
      Unit  : constant Unit_Name_Type := Q.Table (Q_Front).Unit;
4100
      Index : constant Int            := Q.Table (Q_Front).Index;
4101
 
4102
   begin
4103
      if Debug.Debug_Flag_Q then
4104
         Write_Str ("   Q := Q - [ ");
4105
         Write_Name (File);
4106
 
4107
         if Index /= 0 then
4108
            Write_Str (", ");
4109
            Write_Int (Index);
4110
         end if;
4111
 
4112
         Write_Str (" ]");
4113
         Write_Eol;
4114
      end if;
4115
 
4116
      Q_Front := Q_Front + 1;
4117
      Source_File  := File;
4118
      Source_Unit  := Unit;
4119
      Source_Index := Index;
4120
   end Extract_From_Q;
4121
 
4122
   --------------
4123
   -- Gnatmake --
4124
   --------------
4125
 
4126
   procedure Gnatmake is
4127
      Main_Source_File : File_Name_Type;
4128
      --  The source file containing the main compilation unit
4129
 
4130
      Compilation_Failures : Natural;
4131
 
4132
      Total_Compilation_Failures : Natural := 0;
4133
 
4134
      Is_Main_Unit : Boolean;
4135
      --  Set True by Compile_Sources if Main_Source_File can be a main unit
4136
 
4137
      Main_ALI_File : File_Name_Type;
4138
      --  The ali file corresponding to Main_Source_File
4139
 
4140
      Executable : File_Name_Type := No_File;
4141
      --  The file name of an executable
4142
 
4143
      Non_Std_Executable : Boolean := False;
4144
      --  Non_Std_Executable is set to True when there is a possibility that
4145
      --  the linker will not choose the correct executable file name.
4146
 
4147
      Current_Work_Dir : constant String_Access :=
4148
                                    new String'(Get_Current_Dir);
4149
      --  The current working directory, used to modify some relative path
4150
      --  switches on the command line when a project file is used.
4151
 
4152
      Current_Main_Index : Int := 0;
4153
      --  If not zero, the index of the current main unit in its source file
4154
 
4155
      Stand_Alone_Libraries : Boolean := False;
4156
      --  Set to True when there are Stand-Alone Libraries, so that gnatbind
4157
      --  is invoked with the -F switch to force checking of elaboration flags.
4158
 
4159
      Mapping_Path : Path_Name_Type := No_Path;
4160
      --  The path name of the mapping file
4161
 
4162
      Project_Node_Tree : Project_Node_Tree_Ref;
4163
 
4164
      Discard : Boolean;
4165
      pragma Warnings (Off, Discard);
4166
 
4167
      procedure Check_Mains;
4168
      --  Check that the main subprograms do exist and that they all
4169
      --  belong to the same project file.
4170
 
4171
      procedure Create_Binder_Mapping_File
4172
        (Args : in out Argument_List; Last_Arg : in out Natural);
4173
      --  Create a binder mapping file and add the necessary switch
4174
 
4175
      -----------------
4176
      -- Check_Mains --
4177
      -----------------
4178
 
4179
      procedure Check_Mains is
4180
         Real_Main_Project : Project_Id := No_Project;
4181
         --  The project of the first main
4182
 
4183
         Proj              : Project_Id := No_Project;
4184
         --  The project of the current main
4185
 
4186
         Real_Path         : String_Access;
4187
 
4188
      begin
4189
         Mains.Reset;
4190
 
4191
         --  Check each main
4192
 
4193
         loop
4194
            declare
4195
               Main      : constant String := Mains.Next_Main;
4196
               --  The name specified on the command line may include directory
4197
               --  information.
4198
 
4199
               File_Name : constant String := Base_Name (Main);
4200
               --  The simple file name of the current main
4201
 
4202
               Lang : Language_Ptr;
4203
 
4204
            begin
4205
               exit when Main = "";
4206
 
4207
               --  Get the project of the current main
4208
 
4209
               Proj := Prj.Env.Project_Of
4210
                         (File_Name, Main_Project, Project_Tree);
4211
 
4212
               --  Fail if the current main is not a source of a project
4213
 
4214
               if Proj = No_Project then
4215
                  Make_Failed
4216
                    ("""" & Main & """ is not a source of any project");
4217
 
4218
               else
4219
                  --  If there is directory information, check that the source
4220
                  --  exists and, if it does, that the path is the actual path
4221
                  --  of a source of a project.
4222
 
4223
                  if Main /= File_Name then
4224
                     Lang := Get_Language_From_Name (Main_Project, "ada");
4225
 
4226
                     Real_Path :=
4227
                       Locate_Regular_File
4228
                         (Main & Get_Name_String
4229
                              (Lang.Config.Naming_Data.Body_Suffix),
4230
                          "");
4231
                     if Real_Path = null then
4232
                        Real_Path :=
4233
                          Locate_Regular_File
4234
                            (Main & Get_Name_String
4235
                                 (Lang.Config.Naming_Data.Spec_Suffix),
4236
                             "");
4237
                     end if;
4238
 
4239
                     if Real_Path = null then
4240
                        Real_Path := Locate_Regular_File (Main, "");
4241
                     end if;
4242
 
4243
                     --  Fail if the file cannot be found
4244
 
4245
                     if Real_Path = null then
4246
                        Make_Failed ("file """ & Main & """ does not exist");
4247
                     end if;
4248
 
4249
                     declare
4250
                        Project_Path : constant String :=
4251
                                         Prj.Env.File_Name_Of_Library_Unit_Body
4252
                                           (Name              => File_Name,
4253
                                            Project           => Main_Project,
4254
                                            In_Tree           => Project_Tree,
4255
                                            Main_Project_Only => False,
4256
                                            Full_Path         => True);
4257
                        Normed_Path  : constant String :=
4258
                                         Normalize_Pathname
4259
                                           (Real_Path.all,
4260
                                            Case_Sensitive => False);
4261
                        Proj_Path    : constant String :=
4262
                                         Normalize_Pathname
4263
                                           (Project_Path,
4264
                                            Case_Sensitive => False);
4265
 
4266
                     begin
4267
                        Free (Real_Path);
4268
 
4269
                        --  Fail if it is not the correct path
4270
 
4271
                        if Normed_Path /= Proj_Path then
4272
                           if Verbose_Mode then
4273
                              Set_Standard_Error;
4274
                              Write_Str (Normed_Path);
4275
                              Write_Str (" /= ");
4276
                              Write_Line (Proj_Path);
4277
                           end if;
4278
 
4279
                           Make_Failed
4280
                             ("""" & Main &
4281
                              """ is not a source of any project");
4282
                        end if;
4283
                     end;
4284
                  end if;
4285
 
4286
                  if not Unique_Compile then
4287
 
4288
                     --  Record the project, if it is the first main
4289
 
4290
                     if Real_Main_Project = No_Project then
4291
                        Real_Main_Project := Proj;
4292
 
4293
                     elsif Proj /= Real_Main_Project then
4294
 
4295
                        --  Fail, as the current main is not a source of the
4296
                        --  same project as the first main.
4297
 
4298
                        Make_Failed
4299
                          ("""" & Main &
4300
                           """ is not a source of project " &
4301
                           Get_Name_String (Real_Main_Project.Name));
4302
                     end if;
4303
                  end if;
4304
               end if;
4305
 
4306
               --  If -u and -U are not used, we may have mains that are
4307
               --  sources of a project that is not the one specified with
4308
               --  switch -P.
4309
 
4310
               if not Unique_Compile then
4311
                  Main_Project := Real_Main_Project;
4312
               end if;
4313
            end;
4314
         end loop;
4315
      end Check_Mains;
4316
 
4317
      --------------------------------
4318
      -- Create_Binder_Mapping_File --
4319
      --------------------------------
4320
 
4321
      procedure Create_Binder_Mapping_File
4322
        (Args : in out Argument_List; Last_Arg : in out Natural)
4323
      is
4324
         Mapping_FD : File_Descriptor := Invalid_FD;
4325
         --  A File Descriptor for an eventual mapping file
4326
 
4327
         ALI_Unit : Unit_Name_Type := No_Unit_Name;
4328
         --  The unit name of an ALI file
4329
 
4330
         ALI_Name : File_Name_Type := No_File;
4331
         --  The file name of the ALI file
4332
 
4333
         ALI_Project : Project_Id := No_Project;
4334
         --  The project of the ALI file
4335
 
4336
         Bytes : Integer;
4337
         OK    : Boolean := True;
4338
         Unit  : Unit_Index;
4339
 
4340
         Status : Boolean;
4341
         --  For call to Close
4342
 
4343
      begin
4344
         Tempdir.Create_Temp_File (Mapping_FD, Mapping_Path);
4345
         Record_Temp_File (Project_Tree, Mapping_Path);
4346
 
4347
         if Mapping_FD /= Invalid_FD then
4348
 
4349
            --  Traverse all units
4350
 
4351
            Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
4352
 
4353
            while Unit /= No_Unit_Index loop
4354
               if Unit.Name /= No_Name then
4355
 
4356
                  --  If there is a body, put it in the mapping
4357
 
4358
                  if Unit.File_Names (Impl) /= No_Source
4359
                    and then Unit.File_Names (Impl).Project /=
4360
                    No_Project
4361
                  then
4362
                     Get_Name_String (Unit.Name);
4363
                     Add_Str_To_Name_Buffer ("%b");
4364
                     ALI_Unit := Name_Find;
4365
                     ALI_Name :=
4366
                       Lib_File_Name
4367
                         (Unit.File_Names (Impl).Display_File);
4368
                     ALI_Project := Unit.File_Names (Impl).Project;
4369
 
4370
                     --  Otherwise, if there is a spec, put it in the mapping
4371
 
4372
                  elsif Unit.File_Names (Spec) /= No_Source
4373
                    and then Unit.File_Names (Spec).Project /= No_Project
4374
                  then
4375
                     Get_Name_String (Unit.Name);
4376
                     Add_Str_To_Name_Buffer ("%s");
4377
                     ALI_Unit := Name_Find;
4378
                     ALI_Name :=
4379
                       Lib_File_Name
4380
                         (Unit.File_Names (Spec).Display_File);
4381
                     ALI_Project := Unit.File_Names (Spec).Project;
4382
 
4383
                  else
4384
                     ALI_Name := No_File;
4385
                  end if;
4386
 
4387
                  --  If we have something to put in the mapping then do it
4388
                  --  now. However, if the project is extended, we don't put
4389
                  --  anything in the mapping file, because we don't know where
4390
                  --  the ALI file is: it might be in the extended project
4391
                  --  object directory as well as in the extending project
4392
                  --  object directory.
4393
 
4394
                  if ALI_Name /= No_File
4395
                    and then ALI_Project.Extended_By = No_Project
4396
                    and then ALI_Project.Extends = No_Project
4397
                  then
4398
                     --  First check if the ALI file exists. If it does not,
4399
                     --  do not put the unit in the mapping file.
4400
 
4401
                     declare
4402
                        ALI : constant String := Get_Name_String (ALI_Name);
4403
 
4404
                     begin
4405
                        --  For library projects, use the library directory,
4406
                        --  for other projects, use the object directory.
4407
 
4408
                        if ALI_Project.Library then
4409
                           Get_Name_String (ALI_Project.Library_Dir.Name);
4410
                        else
4411
                           Get_Name_String
4412
                             (ALI_Project.Object_Directory.Name);
4413
                        end if;
4414
 
4415
                        if not
4416
                          Is_Directory_Separator (Name_Buffer (Name_Len))
4417
                        then
4418
                           Add_Char_To_Name_Buffer (Directory_Separator);
4419
                        end if;
4420
 
4421
                        Add_Str_To_Name_Buffer (ALI);
4422
                        Add_Char_To_Name_Buffer (ASCII.LF);
4423
 
4424
                        declare
4425
                           ALI_Path_Name : constant String :=
4426
                                             Name_Buffer (1 .. Name_Len);
4427
 
4428
                        begin
4429
                           if Is_Regular_File
4430
                                (ALI_Path_Name (1 .. ALI_Path_Name'Last - 1))
4431
                           then
4432
                              --  First line is the unit name
4433
 
4434
                              Get_Name_String (ALI_Unit);
4435
                              Add_Char_To_Name_Buffer (ASCII.LF);
4436
                              Bytes :=
4437
                                Write
4438
                                  (Mapping_FD,
4439
                                   Name_Buffer (1)'Address,
4440
                                   Name_Len);
4441
                              OK := Bytes = Name_Len;
4442
 
4443
                              exit when not OK;
4444
 
4445
                              --  Second line it the ALI file name
4446
 
4447
                              Get_Name_String (ALI_Name);
4448
                              Add_Char_To_Name_Buffer (ASCII.LF);
4449
                              Bytes :=
4450
                                Write
4451
                                  (Mapping_FD,
4452
                                   Name_Buffer (1)'Address,
4453
                                   Name_Len);
4454
                              OK := (Bytes = Name_Len);
4455
 
4456
                              exit when not OK;
4457
 
4458
                              --  Third line it the ALI path name
4459
 
4460
                              Bytes :=
4461
                                Write
4462
                                  (Mapping_FD,
4463
                                   ALI_Path_Name (1)'Address,
4464
                                   ALI_Path_Name'Length);
4465
                              OK := (Bytes = ALI_Path_Name'Length);
4466
 
4467
                              --  If OK is False, it means we were unable to
4468
                              --  write a line. No point in continuing with the
4469
                              --  other units.
4470
 
4471
                              exit when not OK;
4472
                           end if;
4473
                        end;
4474
                     end;
4475
                  end if;
4476
               end if;
4477
 
4478
               Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
4479
            end loop;
4480
 
4481
            Close (Mapping_FD, Status);
4482
 
4483
            OK := OK and Status;
4484
 
4485
            --  If the creation of the mapping file was successful, we add the
4486
            --  switch to the arguments of gnatbind.
4487
 
4488
            if OK then
4489
               Last_Arg := Last_Arg + 1;
4490
               Args (Last_Arg) :=
4491
                 new String'("-F=" & Get_Name_String (Mapping_Path));
4492
            end if;
4493
         end if;
4494
      end Create_Binder_Mapping_File;
4495
 
4496
   --  Start of processing for Gnatmake
4497
 
4498
   --  This body is very long, should be broken down???
4499
 
4500
   begin
4501
      Install_Int_Handler (Sigint_Intercepted'Access);
4502
 
4503
      Do_Compile_Step := True;
4504
      Do_Bind_Step    := True;
4505
      Do_Link_Step    := True;
4506
 
4507
      Obsoleted.Reset;
4508
 
4509
      Make.Initialize (Project_Node_Tree);
4510
 
4511
      Bind_Shared := No_Shared_Switch'Access;
4512
      Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access;
4513
 
4514
      Failed_Links.Set_Last (0);
4515
      Successful_Links.Set_Last (0);
4516
 
4517
      --  Special case when switch -B was specified
4518
 
4519
      if Build_Bind_And_Link_Full_Project then
4520
 
4521
         --  When switch -B is specified, there must be a project file
4522
 
4523
         if Main_Project = No_Project then
4524
            Make_Failed ("-B cannot be used without a project file");
4525
 
4526
         --  No main program may be specified on the command line
4527
 
4528
         elsif Osint.Number_Of_Files /= 0 then
4529
            Make_Failed ("-B cannot be used with a main specified on " &
4530
                         "the command line");
4531
 
4532
         --  And the project file cannot be a library project file
4533
 
4534
         elsif Main_Project.Library then
4535
            Make_Failed ("-B cannot be used for a library project file");
4536
 
4537
         else
4538
            No_Main_Subprogram := True;
4539
            Insert_Project_Sources
4540
              (The_Project  => Main_Project,
4541
               All_Projects => Unique_Compile_All_Projects,
4542
               Into_Q       => False);
4543
 
4544
            --  If there are no sources to compile, we fail
4545
 
4546
            if Osint.Number_Of_Files = 0 then
4547
               Make_Failed ("no sources to compile");
4548
            end if;
4549
 
4550
            --  Specify -n for gnatbind and add the ALI files of all the
4551
            --  sources, except the one which is a fake main subprogram: this
4552
            --  is the one for the binder generated file and it will be
4553
            --  transmitted to gnatlink. These sources are those that are in
4554
            --  the queue.
4555
 
4556
            Add_Switch ("-n", Binder, And_Save => True);
4557
 
4558
            for J in Q.First .. Q.Last - 1 loop
4559
               Add_Switch
4560
                 (Get_Name_String
4561
                    (Lib_File_Name (Q.Table (J).File)),
4562
                  Binder, And_Save => True);
4563
            end loop;
4564
         end if;
4565
 
4566
      elsif Main_Index /= 0 and then Osint.Number_Of_Files > 1 then
4567
         Make_Failed ("cannot specify several mains with a multi-unit index");
4568
 
4569
      elsif Main_Project /= No_Project then
4570
 
4571
         --  If the main project file is a library project file, main(s) cannot
4572
         --  be specified on the command line.
4573
 
4574
         if Osint.Number_Of_Files /= 0 then
4575
            if Main_Project.Library
4576
              and then not Unique_Compile
4577
              and then ((not Make_Steps) or else Bind_Only or else Link_Only)
4578
            then
4579
               Make_Failed ("cannot specify a main program " &
4580
                            "on the command line for a library project file");
4581
 
4582
            else
4583
               --  Check that each main on the command line is a source of a
4584
               --  project file and, if there are several mains, each of them
4585
               --  is a source of the same project file.
4586
 
4587
               Check_Mains;
4588
            end if;
4589
 
4590
         --  If no mains have been specified on the command line, and we are
4591
         --  using a project file, we either find the main(s) in attribute Main
4592
         --  of the main project, or we put all the sources of the project file
4593
         --  as mains.
4594
 
4595
         else
4596
            if Main_Index /= 0 then
4597
               Make_Failed ("cannot specify a multi-unit index but no main " &
4598
                            "on the command line");
4599
            end if;
4600
 
4601
            declare
4602
               Value : String_List_Id := Main_Project.Mains;
4603
 
4604
            begin
4605
               --  The attribute Main is an empty list or not specified, or
4606
               --  else gnatmake was invoked with the switch "-u".
4607
 
4608
               if Value = Prj.Nil_String or else Unique_Compile then
4609
 
4610
                  if (not Make_Steps) or else Compile_Only
4611
                    or else not Main_Project.Library
4612
                  then
4613
                     --  First make sure that the binder and the linker will
4614
                     --  not be invoked.
4615
 
4616
                     Do_Bind_Step := False;
4617
                     Do_Link_Step := False;
4618
 
4619
                     --  Put all the sources in the queue
4620
 
4621
                     No_Main_Subprogram := True;
4622
                     Insert_Project_Sources
4623
                       (The_Project  => Main_Project,
4624
                        All_Projects => Unique_Compile_All_Projects,
4625
                        Into_Q       => False);
4626
 
4627
                     --  If no sources to compile, then there is nothing to do
4628
 
4629
                     if Osint.Number_Of_Files = 0 then
4630
                        if not Quiet_Output then
4631
                           Osint.Write_Program_Name;
4632
                           Write_Line (": no sources to compile");
4633
                        end if;
4634
 
4635
                        Delete_All_Temp_Files;
4636
                        Exit_Program (E_Success);
4637
                     end if;
4638
                  end if;
4639
 
4640
               else
4641
                  --  The attribute Main is not an empty list. Put all the main
4642
                  --  subprograms in the list as if they were specified on the
4643
                  --  command line. However, if attribute Languages includes a
4644
                  --  language other than Ada, only include the Ada mains; if
4645
                  --  there is no Ada main, compile all sources of the project.
4646
 
4647
                  declare
4648
                     Languages : constant Variable_Value :=
4649
                                   Prj.Util.Value_Of
4650
                                     (Name_Languages,
4651
                                      Main_Project.Decl.Attributes,
4652
                                      Project_Tree);
4653
 
4654
                     Current : String_List_Id;
4655
                     Element : String_Element;
4656
 
4657
                     Foreign_Language  : Boolean := False;
4658
                     At_Least_One_Main : Boolean := False;
4659
 
4660
                  begin
4661
                     --  First, determine if there is a foreign language in
4662
                     --  attribute Languages.
4663
 
4664
                     if not Languages.Default then
4665
                        Current := Languages.Values;
4666
                        Look_For_Foreign :
4667
                        while Current /= Nil_String loop
4668
                           Element := Project_Tree.String_Elements.
4669
                                        Table (Current);
4670
                           Get_Name_String (Element.Value);
4671
                           To_Lower (Name_Buffer (1 .. Name_Len));
4672
 
4673
                           if Name_Buffer (1 .. Name_Len) /= "ada" then
4674
                              Foreign_Language := True;
4675
                              exit Look_For_Foreign;
4676
                           end if;
4677
 
4678
                           Current := Element.Next;
4679
                        end loop Look_For_Foreign;
4680
                     end if;
4681
 
4682
                     --  Then, find all mains, or if there is a foreign
4683
                     --  language, all the Ada mains.
4684
 
4685
                     while Value /= Prj.Nil_String loop
4686
                        Get_Name_String
4687
                          (Project_Tree.String_Elements.Table (Value).Value);
4688
 
4689
                        --  To know if a main is an Ada main, get its project.
4690
                        --  It should be the project specified on the command
4691
                        --  line.
4692
 
4693
                        if (not Foreign_Language) or else
4694
                            Prj.Env.Project_Of
4695
                              (Name_Buffer (1 .. Name_Len),
4696
                               Main_Project,
4697
                               Project_Tree) =
4698
                             Main_Project
4699
                        then
4700
                           At_Least_One_Main := True;
4701
                           Osint.Add_File
4702
                             (Get_Name_String
4703
                                (Project_Tree.String_Elements.Table
4704
                                   (Value).Value),
4705
                              Index =>
4706
                                Project_Tree.String_Elements.Table
4707
                                  (Value).Index);
4708
                        end if;
4709
 
4710
                        Value := Project_Tree.String_Elements.Table
4711
                                   (Value).Next;
4712
                     end loop;
4713
 
4714
                     --  If we did not get any main, it means that all mains
4715
                     --  in attribute Mains are in a foreign language and -B
4716
                     --  was not specified to gnatmake; so, we fail.
4717
 
4718
                     if not At_Least_One_Main then
4719
                        Make_Failed
4720
                          ("no Ada mains, use -B to build foreign main");
4721
                     end if;
4722
                  end;
4723
 
4724
               end if;
4725
            end;
4726
         end if;
4727
      end if;
4728
 
4729
      if Verbose_Mode then
4730
         Write_Eol;
4731
         Display_Version ("GNATMAKE", "1995");
4732
      end if;
4733
 
4734
      if Main_Project /= No_Project
4735
        and then Main_Project.Externally_Built
4736
      then
4737
         Make_Failed
4738
           ("nothing to do for a main project that is externally built");
4739
      end if;
4740
 
4741
      if Osint.Number_Of_Files = 0 then
4742
         if Main_Project /= No_Project
4743
           and then Main_Project.Library
4744
         then
4745
            if Do_Bind_Step
4746
              and then not Main_Project.Standalone_Library
4747
            then
4748
               Make_Failed ("only stand-alone libraries may be bound");
4749
            end if;
4750
 
4751
            --  Add the default search directories to be able to find libgnat
4752
 
4753
            Osint.Add_Default_Search_Dirs;
4754
 
4755
            --  Get the target parameters, so that the correct binder generated
4756
            --  files are generated if OpenVMS is the target.
4757
 
4758
            begin
4759
               Targparm.Get_Target_Parameters;
4760
 
4761
            exception
4762
               when Unrecoverable_Error =>
4763
                  Make_Failed ("*** make failed.");
4764
            end;
4765
 
4766
            --  And bind and or link the library
4767
 
4768
            MLib.Prj.Build_Library
4769
              (For_Project   => Main_Project,
4770
               In_Tree       => Project_Tree,
4771
               Gnatbind      => Gnatbind.all,
4772
               Gnatbind_Path => Gnatbind_Path,
4773
               Gcc           => Gcc.all,
4774
               Gcc_Path      => Gcc_Path,
4775
               Bind          => Bind_Only,
4776
               Link          => Link_Only);
4777
 
4778
            Delete_All_Temp_Files;
4779
            Exit_Program (E_Success);
4780
 
4781
         else
4782
            --  Call Get_Target_Parameters to ensure that VM_Target and
4783
            --  AAMP_On_Target get set before calling Usage.
4784
 
4785
            Targparm.Get_Target_Parameters;
4786
 
4787
            --  Output usage information if no files to compile
4788
 
4789
            Usage;
4790
            Exit_Program (E_Fatal);
4791
         end if;
4792
      end if;
4793
 
4794
      --  If -M was specified, behave as if -n was specified
4795
 
4796
      if List_Dependencies then
4797
         Do_Not_Execute := True;
4798
      end if;
4799
 
4800
      --  Note that Osint.M.Next_Main_Source will always return the (possibly
4801
      --  abbreviated file) without any directory information.
4802
 
4803
      Main_Source_File := Next_Main_Source;
4804
 
4805
      if Current_File_Index /= No_Index then
4806
         Main_Index := Current_File_Index;
4807
      end if;
4808
 
4809
      Add_Switch ("-I-", Compiler, And_Save => True);
4810
 
4811
      if Main_Project = No_Project then
4812
         if Look_In_Primary_Dir then
4813
 
4814
            Add_Switch
4815
              ("-I" &
4816
               Normalize_Directory_Name
4817
               (Get_Primary_Src_Search_Directory.all).all,
4818
               Compiler, Append_Switch => False,
4819
               And_Save => False);
4820
 
4821
         end if;
4822
 
4823
      else
4824
         --  If we use a project file, we have already checked that a main
4825
         --  specified on the command line with directory information has the
4826
         --  path name corresponding to a correct source in the project tree.
4827
         --  So, we don't need the directory information to be taken into
4828
         --  account by Find_File, and in fact it may lead to take the wrong
4829
         --  sources for other compilation units, when there are extending
4830
         --  projects.
4831
 
4832
         Look_In_Primary_Dir := False;
4833
         Add_Switch ("-I-", Binder, And_Save => True);
4834
      end if;
4835
 
4836
      --  If the user wants a program without a main subprogram, add the
4837
      --  appropriate switch to the binder.
4838
 
4839
      if No_Main_Subprogram then
4840
         Add_Switch ("-z", Binder, And_Save => True);
4841
      end if;
4842
 
4843
      if Main_Project /= No_Project then
4844
 
4845
         if Main_Project.Object_Directory /= No_Path_Information then
4846
            --  Change current directory to object directory of main project
4847
 
4848
            Project_Of_Current_Object_Directory := No_Project;
4849
            Change_To_Object_Directory (Main_Project);
4850
         end if;
4851
 
4852
         --  Source file lookups should be cached for efficiency.
4853
         --  Source files are not supposed to change.
4854
 
4855
         Osint.Source_File_Data (Cache => True);
4856
 
4857
         --  Find the file name of the (first) main unit
4858
 
4859
         declare
4860
            Main_Source_File_Name : constant String :=
4861
                                      Get_Name_String (Main_Source_File);
4862
            Main_Unit_File_Name   : constant String :=
4863
                                      Prj.Env.File_Name_Of_Library_Unit_Body
4864
                                        (Name    => Main_Source_File_Name,
4865
                                         Project => Main_Project,
4866
                                         In_Tree => Project_Tree,
4867
                                         Main_Project_Only =>
4868
                                           not Unique_Compile);
4869
 
4870
            The_Packages : constant Package_Id :=
4871
                             Main_Project.Decl.Packages;
4872
 
4873
            Builder_Package : constant Prj.Package_Id :=
4874
                                Prj.Util.Value_Of
4875
                                  (Name        => Name_Builder,
4876
                                   In_Packages => The_Packages,
4877
                                   In_Tree     => Project_Tree);
4878
 
4879
            Binder_Package : constant Prj.Package_Id :=
4880
                               Prj.Util.Value_Of
4881
                                 (Name        => Name_Binder,
4882
                                  In_Packages => The_Packages,
4883
                                  In_Tree     => Project_Tree);
4884
 
4885
            Linker_Package : constant Prj.Package_Id :=
4886
                               Prj.Util.Value_Of
4887
                                 (Name        => Name_Linker,
4888
                                  In_Packages => The_Packages,
4889
                                  In_Tree     => Project_Tree);
4890
 
4891
            Default_Switches_Array : Array_Id;
4892
 
4893
            Global_Compilation_Array    : Array_Element_Id;
4894
            Global_Compilation_Elem     : Array_Element;
4895
            Global_Compilation_Switches : Variable_Value;
4896
 
4897
         begin
4898
            --  We fail if we cannot find the main source file
4899
 
4900
            if Main_Unit_File_Name = "" then
4901
               Make_Failed ('"' & Main_Source_File_Name
4902
                            & """ is not a unit of project "
4903
                            & Project_File_Name.all & ".");
4904
            else
4905
               --  Remove any directory information from the main source file
4906
               --  file name.
4907
 
4908
               declare
4909
                  Pos : Natural := Main_Unit_File_Name'Last;
4910
 
4911
               begin
4912
                  loop
4913
                     exit when Pos < Main_Unit_File_Name'First or else
4914
                       Main_Unit_File_Name (Pos) = Directory_Separator;
4915
                     Pos := Pos - 1;
4916
                  end loop;
4917
 
4918
                  Name_Len := Main_Unit_File_Name'Last - Pos;
4919
 
4920
                  Name_Buffer (1 .. Name_Len) :=
4921
                    Main_Unit_File_Name
4922
                    (Pos + 1 .. Main_Unit_File_Name'Last);
4923
 
4924
                  Main_Source_File := Name_Find;
4925
 
4926
                  --  We only output the main source file if there is only one
4927
 
4928
                  if Verbose_Mode and then Osint.Number_Of_Files = 1 then
4929
                     Write_Str ("Main source file: """);
4930
                     Write_Str (Main_Unit_File_Name
4931
                                (Pos + 1 .. Main_Unit_File_Name'Last));
4932
                     Write_Line (""".");
4933
                  end if;
4934
               end;
4935
            end if;
4936
 
4937
            --  If there is a package Builder in the main project file, add
4938
            --  the switches from it.
4939
 
4940
            if Builder_Package /= No_Package then
4941
 
4942
               Global_Compilation_Array := Prj.Util.Value_Of
4943
                 (Name      => Name_Global_Compilation_Switches,
4944
                  In_Arrays => Project_Tree.Packages.Table
4945
                    (Builder_Package).Decl.Arrays,
4946
                  In_Tree   => Project_Tree);
4947
 
4948
               Default_Switches_Array :=
4949
                 Project_Tree.Packages.Table
4950
                   (Builder_Package).Decl.Arrays;
4951
 
4952
               while Default_Switches_Array /= No_Array and then
4953
               Project_Tree.Arrays.Table (Default_Switches_Array).Name /=
4954
                 Name_Default_Switches
4955
               loop
4956
                  Default_Switches_Array :=
4957
                    Project_Tree.Arrays.Table (Default_Switches_Array).Next;
4958
               end loop;
4959
 
4960
               if Global_Compilation_Array /= No_Array_Element and then
4961
                  Default_Switches_Array /= No_Array
4962
               then
4963
                  Errutil.Error_Msg
4964
                    ("Default_Switches forbidden in presence of " &
4965
                     "Global_Compilation_Switches. Use Switches instead.",
4966
                     Project_Tree.Arrays.Table
4967
                       (Default_Switches_Array).Location);
4968
                  Errutil.Finalize;
4969
                  Make_Failed
4970
                    ("*** illegal combination of Builder attributes");
4971
               end if;
4972
 
4973
               --  If there is only one main, we attempt to get the gnatmake
4974
               --  switches for this main (if any). If there are no specific
4975
               --  switch for this particular main, get the general gnatmake
4976
               --  switches (if any).
4977
 
4978
               if Osint.Number_Of_Files = 1 then
4979
                  if Verbose_Mode then
4980
                     Write_Str ("Adding gnatmake switches for """);
4981
                     Write_Str (Main_Unit_File_Name);
4982
                     Write_Line (""".");
4983
                  end if;
4984
 
4985
                  Add_Switches
4986
                    (Project_Node_Tree                => Project_Node_Tree,
4987
                     File_Name                        => Main_Unit_File_Name,
4988
                     Index                            => Main_Index,
4989
                     The_Package                      => Builder_Package,
4990
                     Program                          => None,
4991
                     Unknown_Switches_To_The_Compiler =>
4992
                       Global_Compilation_Array = No_Array_Element);
4993
 
4994
               else
4995
                  --  If there are several mains, we always get the general
4996
                  --  gnatmake switches (if any).
4997
 
4998
                  --  Warn the user, if necessary, so that he is not surprised
4999
                  --  that specific switches are not taken into account.
5000
 
5001
                  declare
5002
                     Defaults : constant Variable_Value :=
5003
                                  Prj.Util.Value_Of
5004
                                    (Name                    => Name_Ada,
5005
                                     Index                   => 0,
5006
                                     Attribute_Or_Array_Name =>
5007
                                       Name_Default_Switches,
5008
                                     In_Package              =>
5009
                                       Builder_Package,
5010
                                     In_Tree                 => Project_Tree);
5011
 
5012
                     Switches : constant Array_Element_Id :=
5013
                                  Prj.Util.Value_Of
5014
                                    (Name      => Name_Switches,
5015
                                     In_Arrays =>
5016
                                       Project_Tree.Packages.Table
5017
                                         (Builder_Package).Decl.Arrays,
5018
                                     In_Tree   => Project_Tree);
5019
 
5020
                     Other_Switches : constant Variable_Value :=
5021
                                        Prj.Util.Value_Of
5022
                                          (Name        => All_Other_Names,
5023
                                           Index       => 0,
5024
                                           Attribute_Or_Array_Name
5025
                                                       => Name_Switches,
5026
                                           In_Package  => Builder_Package,
5027
                                           In_Tree     => Project_Tree);
5028
 
5029
                  begin
5030
                     if Other_Switches /= Nil_Variable_Value then
5031
                        if not Quiet_Output
5032
                          and then Switches /= No_Array_Element
5033
                          and then Project_Tree.Array_Elements.Table
5034
                                     (Switches).Next /= No_Array_Element
5035
                        then
5036
                           Write_Line
5037
                             ("Warning: using Builder'Switches(others), "
5038
                              & "as there are several mains");
5039
                        end if;
5040
 
5041
                        Add_Switches
5042
                          (Project_Node_Tree              => Project_Node_Tree,
5043
                           File_Name                        => " ",
5044
                           Index                            => 0,
5045
                           The_Package                      => Builder_Package,
5046
                           Program                          => None,
5047
                           Unknown_Switches_To_The_Compiler => False);
5048
 
5049
                     elsif Defaults /= Nil_Variable_Value then
5050
                        if not Quiet_Output
5051
                          and then Switches /= No_Array_Element
5052
                        then
5053
                           Write_Line
5054
                             ("Warning: using Builder'Default_Switches"
5055
                              & "(""Ada""), as there are several mains");
5056
                        end if;
5057
 
5058
                        Add_Switches
5059
                          (Project_Node_Tree => Project_Node_Tree,
5060
                           File_Name   => " ",
5061
                           Index       => 0,
5062
                           The_Package => Builder_Package,
5063
                           Program     => None);
5064
 
5065
                     elsif not Quiet_Output
5066
                       and then Switches /= No_Array_Element
5067
                     then
5068
                        Write_Line
5069
                          ("Warning: using no switches from package "
5070
                           & "Builder, as there are several mains");
5071
                     end if;
5072
                  end;
5073
               end if;
5074
 
5075
               --  Take into account attribute Global_Compilation_Switches
5076
               --  ("Ada").
5077
 
5078
               declare
5079
                  Index : Name_Id;
5080
                  List  : String_List_Id;
5081
                  Elem  : String_Element;
5082
 
5083
               begin
5084
                  while Global_Compilation_Array /= No_Array_Element loop
5085
                     Global_Compilation_Elem :=
5086
                       Project_Tree.Array_Elements.Table
5087
                         (Global_Compilation_Array);
5088
 
5089
                     Get_Name_String (Global_Compilation_Elem.Index);
5090
                     To_Lower (Name_Buffer (1 .. Name_Len));
5091
                     Index := Name_Find;
5092
 
5093
                     if Index = Name_Ada then
5094
                        Global_Compilation_Switches :=
5095
                          Global_Compilation_Elem.Value;
5096
 
5097
                        if Global_Compilation_Switches /= Nil_Variable_Value
5098
                          and then not Global_Compilation_Switches.Default
5099
                        then
5100
                           --  We have found attribute
5101
                           --  Global_Compilation_Switches ("Ada"): put the
5102
                           --  switches in the appropriate table.
5103
 
5104
                           List := Global_Compilation_Switches.Values;
5105
 
5106
                           while List /= Nil_String loop
5107
                              Elem :=
5108
                                Project_Tree.String_Elements.Table (List);
5109
 
5110
                              if Elem.Value /= No_Name then
5111
                                 Add_Switch
5112
                                   (Get_Name_String (Elem.Value),
5113
                                    Compiler,
5114
                                    And_Save => False);
5115
                              end if;
5116
 
5117
                              List := Elem.Next;
5118
                           end loop;
5119
 
5120
                           exit;
5121
                        end if;
5122
                     end if;
5123
 
5124
                     Global_Compilation_Array := Global_Compilation_Elem.Next;
5125
                  end loop;
5126
               end;
5127
            end if;
5128
 
5129
            Osint.Add_Default_Search_Dirs;
5130
 
5131
            --  Record the current last switch index for table Binder_Switches
5132
            --  and Linker_Switches, so that these tables may be reset before
5133
            --  for each main, before adding switches from the project file
5134
            --  and from the command line.
5135
 
5136
            Last_Binder_Switch := Binder_Switches.Last;
5137
            Last_Linker_Switch := Linker_Switches.Last;
5138
 
5139
            Check_Steps;
5140
 
5141
            --  Add binder switches from the project file for the first main
5142
 
5143
            if Do_Bind_Step and then Binder_Package /= No_Package then
5144
               if Verbose_Mode then
5145
                  Write_Str ("Adding binder switches for """);
5146
                  Write_Str (Main_Unit_File_Name);
5147
                  Write_Line (""".");
5148
               end if;
5149
 
5150
               Add_Switches
5151
                 (Project_Node_Tree => Project_Node_Tree,
5152
                  File_Name         => Main_Unit_File_Name,
5153
                  Index             => Main_Index,
5154
                  The_Package       => Binder_Package,
5155
                  Program           => Binder);
5156
            end if;
5157
 
5158
            --  Add linker switches from the project file for the first main
5159
 
5160
            if Do_Link_Step and then Linker_Package /= No_Package then
5161
               if Verbose_Mode then
5162
                  Write_Str ("Adding linker switches for""");
5163
                  Write_Str (Main_Unit_File_Name);
5164
                  Write_Line (""".");
5165
               end if;
5166
 
5167
               Add_Switches
5168
                 (Project_Node_Tree => Project_Node_Tree,
5169
                  File_Name         => Main_Unit_File_Name,
5170
                  Index             => Main_Index,
5171
                  The_Package       => Linker_Package,
5172
                  Program           => Linker);
5173
            end if;
5174
         end;
5175
      end if;
5176
 
5177
      --  Get the target parameters, which are only needed for a couple of
5178
      --  cases in gnatmake. Protect against an exception, such as the case of
5179
      --  system.ads missing from the library, and fail gracefully.
5180
 
5181
      begin
5182
         Targparm.Get_Target_Parameters;
5183
      exception
5184
         when Unrecoverable_Error =>
5185
            Make_Failed ("*** make failed.");
5186
      end;
5187
 
5188
      --  Special processing for VM targets
5189
 
5190
      if Targparm.VM_Target /= No_VM then
5191
 
5192
         --  Set proper processing commands
5193
 
5194
         case Targparm.VM_Target is
5195
            when Targparm.JVM_Target =>
5196
 
5197
               --  Do not check for an object file (".o") when compiling to
5198
               --  JVM machine since ".class" files are generated instead.
5199
 
5200
               Check_Object_Consistency := False;
5201
               Gcc := new String'("jvm-gnatcompile");
5202
 
5203
            when Targparm.CLI_Target =>
5204
               Gcc := new String'("dotnet-gnatcompile");
5205
 
5206
            when Targparm.No_VM =>
5207
               raise Program_Error;
5208
         end case;
5209
      end if;
5210
 
5211
      Display_Commands (not Quiet_Output);
5212
 
5213
      Check_Steps;
5214
 
5215
      if Main_Project /= No_Project then
5216
 
5217
         --  For all library project, if the library file does not exist, put
5218
         --  all the project sources in the queue, and flag the project so that
5219
         --  the library is generated.
5220
 
5221
         if not Unique_Compile
5222
           and then MLib.Tgt.Support_For_Libraries /= Prj.None
5223
         then
5224
            declare
5225
               Proj : Project_List;
5226
 
5227
            begin
5228
               Proj := Project_Tree.Projects;
5229
               while Proj /= null loop
5230
                  if Proj.Project.Library then
5231
                     Proj.Project.Need_To_Build_Lib :=
5232
                       not MLib.Tgt.Library_Exists_For
5233
                         (Proj.Project, Project_Tree)
5234
                       and then not Proj.Project.Externally_Built;
5235
 
5236
                     if Proj.Project.Need_To_Build_Lib then
5237
 
5238
                        --  If there is no object directory, then it will be
5239
                        --  impossible to build the library. So fail
5240
                        --  immediately.
5241
 
5242
                        if
5243
                          Proj.Project.Object_Directory = No_Path_Information
5244
                        then
5245
                           Make_Failed
5246
                             ("no object files to build library for project """
5247
                              & Get_Name_String (Proj.Project.Name)
5248
                              & """");
5249
                           Proj.Project.Need_To_Build_Lib := False;
5250
 
5251
                        else
5252
                           if Verbose_Mode then
5253
                              Write_Str
5254
                                ("Library file does not exist for project """);
5255
                              Write_Str (Get_Name_String (Proj.Project.Name));
5256
                              Write_Line ("""");
5257
                           end if;
5258
 
5259
                           Insert_Project_Sources
5260
                             (The_Project  => Proj.Project,
5261
                              All_Projects => False,
5262
                              Into_Q       => True);
5263
                        end if;
5264
                     end if;
5265
                  end if;
5266
 
5267
                  Proj := Proj.Next;
5268
               end loop;
5269
            end;
5270
         end if;
5271
 
5272
         --  If a relative path output file has been specified, we add the
5273
         --  exec directory.
5274
 
5275
         for J in reverse 1 .. Saved_Linker_Switches.Last - 1 loop
5276
            if Saved_Linker_Switches.Table (J).all = Output_Flag.all then
5277
               declare
5278
                  Exec_File_Name : constant String :=
5279
                                     Saved_Linker_Switches.Table (J + 1).all;
5280
 
5281
               begin
5282
                  if not Is_Absolute_Path (Exec_File_Name) then
5283
                     Get_Name_String (Main_Project.Exec_Directory.Name);
5284
 
5285
                     if not
5286
                       Is_Directory_Separator (Name_Buffer (Name_Len))
5287
                     then
5288
                        Add_Char_To_Name_Buffer (Directory_Separator);
5289
                     end if;
5290
 
5291
                     Add_Str_To_Name_Buffer (Exec_File_Name);
5292
                     Saved_Linker_Switches.Table (J + 1) :=
5293
                       new String'(Name_Buffer (1 .. Name_Len));
5294
                  end if;
5295
               end;
5296
 
5297
               exit;
5298
            end if;
5299
         end loop;
5300
 
5301
         --  If we are using a project file, for relative paths we add the
5302
         --  current working directory for any relative path on the command
5303
         --  line and the project directory, for any relative path in the
5304
         --  project file.
5305
 
5306
         declare
5307
            Dir_Path : constant String :=
5308
                         Get_Name_String (Main_Project.Directory.Name);
5309
         begin
5310
            for J in 1 .. Binder_Switches.Last loop
5311
               Test_If_Relative_Path
5312
                 (Binder_Switches.Table (J),
5313
                  Parent => Dir_Path, Including_L_Switch => False);
5314
            end loop;
5315
 
5316
            for J in 1 .. Saved_Binder_Switches.Last loop
5317
               Test_If_Relative_Path
5318
                 (Saved_Binder_Switches.Table (J),
5319
                  Parent => Current_Work_Dir.all, Including_L_Switch => False);
5320
            end loop;
5321
 
5322
            for J in 1 .. Linker_Switches.Last loop
5323
               Test_If_Relative_Path
5324
                 (Linker_Switches.Table (J), Parent => Dir_Path);
5325
            end loop;
5326
 
5327
            for J in 1 .. Saved_Linker_Switches.Last loop
5328
               Test_If_Relative_Path
5329
                 (Saved_Linker_Switches.Table (J),
5330
                  Parent => Current_Work_Dir.all);
5331
            end loop;
5332
 
5333
            for J in 1 .. Gcc_Switches.Last loop
5334
               Test_If_Relative_Path
5335
                 (Gcc_Switches.Table (J),
5336
                  Parent               => Dir_Path,
5337
                  Including_Non_Switch => False);
5338
            end loop;
5339
 
5340
            for J in 1 .. Saved_Gcc_Switches.Last loop
5341
               Test_If_Relative_Path
5342
                 (Saved_Gcc_Switches.Table (J),
5343
                  Parent               => Current_Work_Dir.all,
5344
                  Including_Non_Switch => False);
5345
            end loop;
5346
         end;
5347
      end if;
5348
 
5349
      --  We now put in the Binder_Switches and Linker_Switches tables, the
5350
      --  binder and linker switches of the command line that have been put in
5351
      --  the Saved_ tables. If a project file was used, then the command line
5352
      --  switches will follow the project file switches.
5353
 
5354
      for J in 1 .. Saved_Binder_Switches.Last loop
5355
         Add_Switch
5356
           (Saved_Binder_Switches.Table (J),
5357
            Binder,
5358
            And_Save => False);
5359
      end loop;
5360
 
5361
      for J in 1 .. Saved_Linker_Switches.Last loop
5362
         Add_Switch
5363
           (Saved_Linker_Switches.Table (J),
5364
            Linker,
5365
            And_Save => False);
5366
      end loop;
5367
 
5368
      --  If no project file is used, we just put the gcc switches
5369
      --  from the command line in the Gcc_Switches table.
5370
 
5371
      if Main_Project = No_Project then
5372
         for J in 1 .. Saved_Gcc_Switches.Last loop
5373
            Add_Switch
5374
              (Saved_Gcc_Switches.Table (J), Compiler, And_Save => False);
5375
         end loop;
5376
 
5377
      else
5378
         --  If there is a project, put the command line gcc switches in the
5379
         --  variable The_Saved_Gcc_Switches. They are going to be used later
5380
         --  in procedure Compile_Sources.
5381
 
5382
         The_Saved_Gcc_Switches :=
5383
           new Argument_List (1 .. Saved_Gcc_Switches.Last + 1);
5384
 
5385
         for J in 1 .. Saved_Gcc_Switches.Last loop
5386
            The_Saved_Gcc_Switches (J) := Saved_Gcc_Switches.Table (J);
5387
         end loop;
5388
 
5389
         --  We never use gnat.adc when a project file is used
5390
 
5391
         The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) := No_gnat_adc;
5392
      end if;
5393
 
5394
      --  If there was a --GCC, --GNATBIND or --GNATLINK switch on the command
5395
      --  line, then we have to use it, even if there was another switch in
5396
      --  the project file.
5397
 
5398
      if Saved_Gcc /= null then
5399
         Gcc := Saved_Gcc;
5400
      end if;
5401
 
5402
      if Saved_Gnatbind /= null then
5403
         Gnatbind := Saved_Gnatbind;
5404
      end if;
5405
 
5406
      if Saved_Gnatlink /= null then
5407
         Gnatlink := Saved_Gnatlink;
5408
      end if;
5409
 
5410
      Gcc_Path       := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
5411
      Gnatbind_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
5412
      Gnatlink_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
5413
 
5414
      --  If we have specified -j switch both from the project file
5415
      --  and on the command line, the one from the command line takes
5416
      --  precedence.
5417
 
5418
      if Saved_Maximum_Processes = 0 then
5419
         Saved_Maximum_Processes := Maximum_Processes;
5420
      end if;
5421
 
5422
      --  Allocate as many temporary mapping file names as the maximum number
5423
      --  of compilations processed, for each possible project.
5424
 
5425
      declare
5426
         Data : Project_Compilation_Access;
5427
         Proj : Project_List := Project_Tree.Projects;
5428
      begin
5429
         while Proj /= null loop
5430
            Data := new Project_Compilation_Data'
5431
              (Mapping_File_Names        => new Temp_Path_Names
5432
                                              (1 .. Saved_Maximum_Processes),
5433
               Last_Mapping_File_Names   => 0,
5434
               Free_Mapping_File_Indices => new Free_File_Indices
5435
                                              (1 .. Saved_Maximum_Processes),
5436
               Last_Free_Indices         => 0);
5437
 
5438
            Project_Compilation_Htable.Set
5439
              (Project_Compilation, Proj.Project, Data);
5440
            Proj := Proj.Next;
5441
         end loop;
5442
 
5443
         Data := new Project_Compilation_Data'
5444
           (Mapping_File_Names        => new Temp_Path_Names
5445
                                           (1 .. Saved_Maximum_Processes),
5446
            Last_Mapping_File_Names   => 0,
5447
            Free_Mapping_File_Indices => new Free_File_Indices
5448
                                           (1 .. Saved_Maximum_Processes),
5449
            Last_Free_Indices         => 0);
5450
 
5451
         Project_Compilation_Htable.Set
5452
           (Project_Compilation, No_Project, Data);
5453
      end;
5454
 
5455
      Bad_Compilation.Init;
5456
 
5457
      --  If project files are used, create the mapping of all the sources, so
5458
      --  that the correct paths will be found. Otherwise, if there is a file
5459
      --  which is not a source with the same name in a source directory this
5460
      --  file may be incorrectly found.
5461
 
5462
      if Main_Project /= No_Project then
5463
         Prj.Env.Create_Mapping (Project_Tree);
5464
      end if;
5465
 
5466
      Current_Main_Index := Main_Index;
5467
 
5468
      --  Here is where the make process is started
5469
 
5470
      --  We do the same process for each main
5471
 
5472
      Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop
5473
 
5474
         --  First, find the executable name and path
5475
 
5476
         Executable          := No_File;
5477
         Executable_Obsolete := False;
5478
         Non_Std_Executable  :=
5479
           Targparm.Executable_Extension_On_Target /= No_Name;
5480
 
5481
         --  Look inside the linker switches to see if the name of the final
5482
         --  executable program was specified.
5483
 
5484
         for J in reverse Linker_Switches.First .. Linker_Switches.Last loop
5485
            if Linker_Switches.Table (J).all = Output_Flag.all then
5486
               pragma Assert (J < Linker_Switches.Last);
5487
 
5488
               --  We cannot specify a single executable for several main
5489
               --  subprograms
5490
 
5491
               if Osint.Number_Of_Files > 1 then
5492
                  Fail
5493
                    ("cannot specify a single executable for several mains");
5494
               end if;
5495
 
5496
               Name_Len := 0;
5497
               Add_Str_To_Name_Buffer (Linker_Switches.Table (J + 1).all);
5498
               Executable := Name_Enter;
5499
 
5500
               Verbose_Msg (Executable, "final executable");
5501
            end if;
5502
         end loop;
5503
 
5504
         --  If the name of the final executable program was not specified then
5505
         --  construct it from the main input file.
5506
 
5507
         if Executable = No_File then
5508
            if Main_Project = No_Project then
5509
               Executable := Executable_Name (Strip_Suffix (Main_Source_File));
5510
 
5511
            else
5512
               --  If we are using a project file, we attempt to remove the
5513
               --  body (or spec) termination of the main subprogram. We find
5514
               --  it the naming scheme of the project file. This avoids
5515
               --  generating an executable "main.2" for a main subprogram
5516
               --  "main.2.ada", when the body termination is ".2.ada".
5517
 
5518
               Executable :=
5519
                 Prj.Util.Executable_Of
5520
                   (Main_Project, Project_Tree, Main_Source_File, Main_Index);
5521
            end if;
5522
         end if;
5523
 
5524
         if Main_Project /= No_Project
5525
           and then Main_Project.Exec_Directory /= No_Path_Information
5526
         then
5527
            declare
5528
               Exec_File_Name : constant String :=
5529
                                  Get_Name_String (Executable);
5530
 
5531
            begin
5532
               if not Is_Absolute_Path (Exec_File_Name) then
5533
                  Get_Name_String (Main_Project.Exec_Directory.Display_Name);
5534
 
5535
                  if Name_Buffer (Name_Len) /= Directory_Separator then
5536
                     Add_Char_To_Name_Buffer (Directory_Separator);
5537
                  end if;
5538
 
5539
                  Add_Str_To_Name_Buffer (Exec_File_Name);
5540
                  Executable := Name_Find;
5541
               end if;
5542
 
5543
               Non_Std_Executable := True;
5544
            end;
5545
         end if;
5546
 
5547
         if Do_Compile_Step then
5548
            Recursive_Compilation_Step : declare
5549
               Args                : Argument_List (1 .. Gcc_Switches.Last);
5550
 
5551
               First_Compiled_File : File_Name_Type;
5552
               Youngest_Obj_File   : File_Name_Type;
5553
               Youngest_Obj_Stamp  : Time_Stamp_Type;
5554
 
5555
               Executable_Stamp : Time_Stamp_Type;
5556
               --  Executable is the final executable program
5557
               --  ??? comment seems unrelated to declaration
5558
 
5559
               Library_Rebuilt : Boolean := False;
5560
 
5561
            begin
5562
               for J in 1 .. Gcc_Switches.Last loop
5563
                  Args (J) := Gcc_Switches.Table (J);
5564
               end loop;
5565
 
5566
               --  Now we invoke Compile_Sources for the current main
5567
 
5568
               Compile_Sources
5569
                 (Main_Source           => Main_Source_File,
5570
                  Args                  => Args,
5571
                  First_Compiled_File   => First_Compiled_File,
5572
                  Most_Recent_Obj_File  => Youngest_Obj_File,
5573
                  Most_Recent_Obj_Stamp => Youngest_Obj_Stamp,
5574
                  Main_Unit             => Is_Main_Unit,
5575
                  Main_Index            => Current_Main_Index,
5576
                  Compilation_Failures  => Compilation_Failures,
5577
                  Check_Readonly_Files  => Check_Readonly_Files,
5578
                  Do_Not_Execute        => Do_Not_Execute,
5579
                  Force_Compilations    => Force_Compilations,
5580
                  In_Place_Mode         => In_Place_Mode,
5581
                  Keep_Going            => Keep_Going,
5582
                  Initialize_ALI_Data   => True,
5583
                  Max_Process           => Saved_Maximum_Processes);
5584
 
5585
               if Verbose_Mode then
5586
                  Write_Str ("End of compilation");
5587
                  Write_Eol;
5588
               end if;
5589
 
5590
               --  Make sure the queue will be reinitialized for the next round
5591
 
5592
               First_Q_Initialization := True;
5593
 
5594
               Total_Compilation_Failures :=
5595
                 Total_Compilation_Failures + Compilation_Failures;
5596
 
5597
               if Total_Compilation_Failures /= 0 then
5598
                  if Keep_Going then
5599
                     goto Next_Main;
5600
 
5601
                  else
5602
                     List_Bad_Compilations;
5603
                     Report_Compilation_Failed;
5604
                  end if;
5605
               end if;
5606
 
5607
               --  Regenerate libraries, if there are any and if object files
5608
               --  have been regenerated.
5609
 
5610
               if Main_Project /= No_Project
5611
                 and then MLib.Tgt.Support_For_Libraries /= Prj.None
5612
                 and then (Do_Bind_Step
5613
                             or Unique_Compile_All_Projects
5614
                             or not Compile_Only)
5615
                 and then (Do_Link_Step or else N_File = Osint.Number_Of_Files)
5616
               then
5617
                  Library_Projs.Init;
5618
 
5619
                  declare
5620
                     Depth   : Natural;
5621
                     Current : Natural;
5622
                     Proj1   : Project_List;
5623
 
5624
                     procedure Add_To_Library_Projs (Proj : Project_Id);
5625
                     --  Add project Project to table Library_Projs in
5626
                     --  decreasing depth order.
5627
 
5628
                     --------------------------
5629
                     -- Add_To_Library_Projs --
5630
                     --------------------------
5631
 
5632
                     procedure Add_To_Library_Projs (Proj : Project_Id) is
5633
                        Prj : Project_Id;
5634
 
5635
                     begin
5636
                        Library_Projs.Increment_Last;
5637
                        Depth := Proj.Depth;
5638
 
5639
                        --  Put the projects in decreasing depth order, so that
5640
                        --  if libA depends on libB, libB is first in order.
5641
 
5642
                        Current := Library_Projs.Last;
5643
                        while Current > 1 loop
5644
                           Prj := Library_Projs.Table (Current - 1);
5645
                           exit when Prj.Depth >= Depth;
5646
                           Library_Projs.Table (Current) := Prj;
5647
                           Current := Current - 1;
5648
                        end loop;
5649
 
5650
                        Library_Projs.Table (Current) := Proj;
5651
                     end Add_To_Library_Projs;
5652
 
5653
                  --  Start of processing for ??? (should name declare block
5654
                  --  or probably better, break this out as a nested proc).
5655
 
5656
                  begin
5657
                     --  Put in Library_Projs table all library project file
5658
                     --  ids when the library need to be rebuilt.
5659
 
5660
                     Proj1 := Project_Tree.Projects;
5661
                     while Proj1 /= null loop
5662
                        if Proj1.Project.Standalone_Library then
5663
                           Stand_Alone_Libraries := True;
5664
                        end if;
5665
 
5666
                        if Proj1.Project.Library then
5667
                           MLib.Prj.Check_Library
5668
                             (Proj1.Project, Project_Tree);
5669
                        end if;
5670
 
5671
                        if Proj1.Project.Need_To_Build_Lib then
5672
                           Add_To_Library_Projs (Proj1.Project);
5673
                        end if;
5674
 
5675
                        Proj1 := Proj1.Next;
5676
                     end loop;
5677
 
5678
                     --  Check if importing libraries should be regenerated
5679
                     --  because at least an imported library will be
5680
                     --  regenerated or is more recent.
5681
 
5682
                     Proj1 := Project_Tree.Projects;
5683
                     while Proj1 /= null loop
5684
                        if Proj1.Project.Library
5685
                          and then Proj1.Project.Library_Kind /= Static
5686
                          and then not Proj1.Project.Need_To_Build_Lib
5687
                          and then not Proj1.Project.Externally_Built
5688
                        then
5689
                           declare
5690
                              List    : Project_List;
5691
                              Proj2   : Project_Id;
5692
                              Rebuild : Boolean := False;
5693
 
5694
                              Lib_Timestamp1 : constant Time_Stamp_Type :=
5695
                                                 Proj1.Project.Library_TS;
5696
 
5697
                           begin
5698
                              List := Proj1.Project.All_Imported_Projects;
5699
                              while List /= null loop
5700
                                 Proj2 := List.Project;
5701
 
5702
                                 if Proj2.Library then
5703
                                    if Proj2.Need_To_Build_Lib
5704
                                      or else
5705
                                        (Lib_Timestamp1 < Proj2.Library_TS)
5706
                                    then
5707
                                       Rebuild := True;
5708
                                       exit;
5709
                                    end if;
5710
                                 end if;
5711
 
5712
                                 List := List.Next;
5713
                              end loop;
5714
 
5715
                              if Rebuild then
5716
                                 Proj1.Project.Need_To_Build_Lib := True;
5717
                                 Add_To_Library_Projs (Proj1.Project);
5718
                              end if;
5719
                           end;
5720
                        end if;
5721
 
5722
                        Proj1 := Proj1.Next;
5723
                     end loop;
5724
 
5725
                     --  Reset the flags Need_To_Build_Lib for the next main,
5726
                     --  to avoid rebuilding libraries uselessly.
5727
 
5728
                     Proj1 := Project_Tree.Projects;
5729
                     while Proj1 /= null loop
5730
                        Proj1.Project.Need_To_Build_Lib := False;
5731
                        Proj1 := Proj1.Next;
5732
                     end loop;
5733
                  end;
5734
 
5735
                  --  Build the libraries, if any need to be built
5736
 
5737
                  for J in 1 .. Library_Projs.Last loop
5738
                     Library_Rebuilt := True;
5739
 
5740
                     --  If a library is rebuilt, then executables are obsolete
5741
 
5742
                     Executable_Obsolete := True;
5743
 
5744
                     MLib.Prj.Build_Library
5745
                       (For_Project   => Library_Projs.Table (J),
5746
                        In_Tree       => Project_Tree,
5747
                        Gnatbind      => Gnatbind.all,
5748
                        Gnatbind_Path => Gnatbind_Path,
5749
                        Gcc           => Gcc.all,
5750
                        Gcc_Path      => Gcc_Path);
5751
                  end loop;
5752
               end if;
5753
 
5754
               if List_Dependencies then
5755
                  if First_Compiled_File /= No_File then
5756
                     Inform
5757
                       (First_Compiled_File,
5758
                        "must be recompiled. Can't generate dependence list.");
5759
                  else
5760
                     List_Depend;
5761
                  end if;
5762
 
5763
               elsif First_Compiled_File = No_File
5764
                 and then not Do_Bind_Step
5765
                 and then not Quiet_Output
5766
                 and then not Library_Rebuilt
5767
                 and then Osint.Number_Of_Files = 1
5768
               then
5769
                  Inform (Msg => "objects up to date.");
5770
 
5771
               elsif Do_Not_Execute
5772
                 and then First_Compiled_File /= No_File
5773
               then
5774
                  Write_Name (First_Compiled_File);
5775
                  Write_Eol;
5776
               end if;
5777
 
5778
               --  Stop after compile step if any of:
5779
 
5780
               --    1) -n (Do_Not_Execute) specified
5781
 
5782
               --    2) -M (List_Dependencies) specified (also sets
5783
               --       Do_Not_Execute above, so this is probably superfluous).
5784
 
5785
               --    3) -c (Compile_Only) specified, but not -b (Bind_Only)
5786
 
5787
               --    4) Made unit cannot be a main unit
5788
 
5789
               if ((Do_Not_Execute
5790
                    or List_Dependencies
5791
                    or not Do_Bind_Step
5792
                    or not Is_Main_Unit)
5793
                  and then not No_Main_Subprogram
5794
                  and then not Build_Bind_And_Link_Full_Project)
5795
                 or else Unique_Compile
5796
               then
5797
                  if Osint.Number_Of_Files = 1 then
5798
                     exit Multiple_Main_Loop;
5799
 
5800
                  else
5801
                     goto Next_Main;
5802
                  end if;
5803
               end if;
5804
 
5805
               --  If the objects were up-to-date check if the executable file
5806
               --  is also up-to-date. For now always bind and link on the JVM
5807
               --  since there is currently no simple way to check whether
5808
               --  objects are up-to-date.
5809
 
5810
               if Targparm.VM_Target /= JVM_Target
5811
                 and then First_Compiled_File = No_File
5812
               then
5813
                  Executable_Stamp := File_Stamp (Executable);
5814
 
5815
                  if not Executable_Obsolete then
5816
                     Executable_Obsolete :=
5817
                       Youngest_Obj_Stamp > Executable_Stamp;
5818
                  end if;
5819
 
5820
                  if not Executable_Obsolete then
5821
                     for Index in reverse 1 .. Dependencies.Last loop
5822
                        if Is_In_Obsoleted
5823
                             (Dependencies.Table (Index).Depends_On)
5824
                        then
5825
                           Enter_Into_Obsoleted
5826
                             (Dependencies.Table (Index).This);
5827
                        end if;
5828
                     end loop;
5829
 
5830
                     Executable_Obsolete := Is_In_Obsoleted (Main_Source_File);
5831
                     Dependencies.Init;
5832
                  end if;
5833
 
5834
                  if not Executable_Obsolete then
5835
 
5836
                     --  If no Ada object files obsolete the executable, check
5837
                     --  for younger or missing linker files.
5838
 
5839
                     Check_Linker_Options
5840
                       (Executable_Stamp,
5841
                        Youngest_Obj_File,
5842
                        Youngest_Obj_Stamp);
5843
 
5844
                     Executable_Obsolete := Youngest_Obj_File /= No_File;
5845
                  end if;
5846
 
5847
                  --  Check if any library file is more recent than the
5848
                  --  executable: there may be an externally built library
5849
                  --  file that has been modified.
5850
 
5851
                  if not Executable_Obsolete
5852
                    and then Main_Project /= No_Project
5853
                  then
5854
                     declare
5855
                        Proj1 : Project_List;
5856
 
5857
                     begin
5858
                        Proj1 := Project_Tree.Projects;
5859
                        while Proj1 /= null loop
5860
                           if Proj1.Project.Library
5861
                             and then
5862
                               Proj1.Project.Library_TS > Executable_Stamp
5863
                           then
5864
                              Executable_Obsolete := True;
5865
                              Youngest_Obj_Stamp := Proj1.Project.Library_TS;
5866
                              Name_Len := 0;
5867
                              Add_Str_To_Name_Buffer ("library ");
5868
                              Add_Str_To_Name_Buffer
5869
                                (Get_Name_String (Proj1.Project.Library_Name));
5870
                              Youngest_Obj_File := Name_Find;
5871
                              exit;
5872
                           end if;
5873
 
5874
                           Proj1 := Proj1.Next;
5875
                        end loop;
5876
                     end;
5877
                  end if;
5878
 
5879
                  --  Return if the executable is up to date and otherwise
5880
                  --  motivate the relink/rebind.
5881
 
5882
                  if not Executable_Obsolete then
5883
                     if not Quiet_Output then
5884
                        Inform (Executable, "up to date.");
5885
                     end if;
5886
 
5887
                     if Osint.Number_Of_Files = 1 then
5888
                        exit Multiple_Main_Loop;
5889
 
5890
                     else
5891
                        goto Next_Main;
5892
                     end if;
5893
                  end if;
5894
 
5895
                  if Executable_Stamp (1) = ' ' then
5896
                     if not No_Main_Subprogram then
5897
                        Verbose_Msg (Executable, "missing.", Prefix => "  ");
5898
                     end if;
5899
 
5900
                  elsif Youngest_Obj_Stamp (1) = ' ' then
5901
                     Verbose_Msg
5902
                       (Youngest_Obj_File, "missing.",  Prefix => "  ");
5903
 
5904
                  elsif Youngest_Obj_Stamp > Executable_Stamp then
5905
                     Verbose_Msg
5906
                       (Youngest_Obj_File,
5907
                        "(" & String (Youngest_Obj_Stamp) & ") newer than",
5908
                        Executable,
5909
                        "(" & String (Executable_Stamp) & ")");
5910
 
5911
                  else
5912
                     Verbose_Msg
5913
                       (Executable, "needs to be rebuilt", Prefix => "  ");
5914
 
5915
                  end if;
5916
               end if;
5917
            end Recursive_Compilation_Step;
5918
         end if;
5919
 
5920
         --  For binding and linking, we need to be in the object directory of
5921
         --  the main project.
5922
 
5923
         if Main_Project /= No_Project then
5924
            Change_To_Object_Directory (Main_Project);
5925
         end if;
5926
 
5927
         --  If we are here, it means that we need to rebuilt the current main,
5928
         --  so we set Executable_Obsolete to True to make sure that subsequent
5929
         --  mains will be rebuilt.
5930
 
5931
         Main_ALI_In_Place_Mode_Step : declare
5932
            ALI_File : File_Name_Type;
5933
            Src_File : File_Name_Type;
5934
 
5935
         begin
5936
            Src_File      := Strip_Directory (Main_Source_File);
5937
            ALI_File      := Lib_File_Name (Src_File, Current_Main_Index);
5938
            Main_ALI_File := Full_Lib_File_Name (ALI_File);
5939
 
5940
            --  When In_Place_Mode, the library file can be located in the
5941
            --  Main_Source_File directory which may not be present in the
5942
            --  library path. If it is not present then use the corresponding
5943
            --  library file name.
5944
 
5945
            if Main_ALI_File = No_File and then In_Place_Mode then
5946
               Get_Name_String (Get_Directory (Full_Source_Name (Src_File)));
5947
               Get_Name_String_And_Append (ALI_File);
5948
               Main_ALI_File := Name_Find;
5949
               Main_ALI_File := Full_Lib_File_Name (Main_ALI_File);
5950
            end if;
5951
 
5952
            if Main_ALI_File = No_File then
5953
               Make_Failed ("could not find the main ALI file");
5954
            end if;
5955
         end Main_ALI_In_Place_Mode_Step;
5956
 
5957
         if Do_Bind_Step then
5958
            Bind_Step : declare
5959
               Args : Argument_List
5960
                        (Binder_Switches.First .. Binder_Switches.Last + 2);
5961
               --  The arguments for the invocation of gnatbind
5962
 
5963
               Last_Arg : Natural := Binder_Switches.Last;
5964
               --  Index of the last argument in Args
5965
 
5966
               Shared_Libs : Boolean := False;
5967
               --  Set to True when there are shared library project files or
5968
               --  when gnatbind is invoked with -shared.
5969
 
5970
               Proj : Project_List;
5971
 
5972
            begin
5973
               --  Check if there are shared libraries, so that gnatbind is
5974
               --  called with -shared. Check also if gnatbind is called with
5975
               --  -shared, so that gnatlink is called with -shared-libgcc
5976
               --  ensuring that the shared version of libgcc will be used.
5977
 
5978
               if Main_Project /= No_Project
5979
                 and then MLib.Tgt.Support_For_Libraries /= Prj.None
5980
               then
5981
                  Proj := Project_Tree.Projects;
5982
                  while Proj /= null loop
5983
                     if Proj.Project.Library
5984
                       and then Proj.Project.Library_Kind /= Static
5985
                     then
5986
                        Shared_Libs := True;
5987
                        Bind_Shared := Shared_Switch'Access;
5988
                        exit;
5989
                     end if;
5990
                     Proj := Proj.Next;
5991
                  end loop;
5992
               end if;
5993
 
5994
               --  Check now for switch -shared
5995
 
5996
               if not Shared_Libs then
5997
                  for J in Binder_Switches.First .. Last_Arg loop
5998
                     if Binder_Switches.Table (J).all = "-shared" then
5999
                        Shared_Libs := True;
6000
                        exit;
6001
                     end if;
6002
                  end loop;
6003
               end if;
6004
 
6005
               --  If shared libraries present, invoke gnatlink with
6006
               --  -shared-libgcc.
6007
 
6008
               if Shared_Libs then
6009
                  Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access;
6010
               end if;
6011
 
6012
               --  Get all the binder switches
6013
 
6014
               for J in Binder_Switches.First .. Last_Arg loop
6015
                  Args (J) := Binder_Switches.Table (J);
6016
               end loop;
6017
 
6018
               if Stand_Alone_Libraries then
6019
                  Last_Arg := Last_Arg + 1;
6020
                  Args (Last_Arg) := Force_Elab_Flags_String'Access;
6021
               end if;
6022
 
6023
               if Main_Project /= No_Project then
6024
 
6025
                  --  Put all the source directories in ADA_INCLUDE_PATH,
6026
                  --  and all the object directories in ADA_OBJECTS_PATH,
6027
                  --  except those of library projects.
6028
 
6029
                  Prj.Env.Set_Ada_Paths (Main_Project, Project_Tree, False);
6030
 
6031
                  --  If switch -C was specified, create a binder mapping file
6032
 
6033
                  if Create_Mapping_File then
6034
                     Create_Binder_Mapping_File (Args, Last_Arg);
6035
                  end if;
6036
 
6037
               end if;
6038
 
6039
               begin
6040
                  Bind (Main_ALI_File,
6041
                        Bind_Shared.all & Args (Args'First .. Last_Arg));
6042
 
6043
               exception
6044
                  when others =>
6045
 
6046
                     --  Delete the temporary mapping file, if one was created.
6047
 
6048
                     if Mapping_Path /= No_Path then
6049
                        Delete_Temporary_File (Project_Tree, Mapping_Path);
6050
                     end if;
6051
 
6052
                     --  And reraise the exception
6053
 
6054
                     raise;
6055
               end;
6056
 
6057
               --  If -dn was not specified, delete the temporary mapping file,
6058
               --  if one was created.
6059
 
6060
               if Mapping_Path /= No_Path then
6061
                  Delete_Temporary_File (Project_Tree, Mapping_Path);
6062
               end if;
6063
            end Bind_Step;
6064
         end if;
6065
 
6066
         if Do_Link_Step then
6067
            Link_Step : declare
6068
               Linker_Switches_Last : constant Integer := Linker_Switches.Last;
6069
               Path_Option          : constant String_Access :=
6070
                                        MLib.Linker_Library_Path_Option;
6071
               Libraries_Present    : Boolean := False;
6072
               Current              : Natural;
6073
               Proj2                : Project_Id;
6074
               Depth                : Natural;
6075
               Proj1                : Project_List;
6076
 
6077
            begin
6078
               if not Run_Path_Option then
6079
                  Linker_Switches.Increment_Last;
6080
                  Linker_Switches.Table (Linker_Switches.Last) :=
6081
                    new String'("-R");
6082
               end if;
6083
 
6084
               if Main_Project /= No_Project then
6085
                  Library_Paths.Set_Last (0);
6086
                  Library_Projs.Init;
6087
 
6088
                  if MLib.Tgt.Support_For_Libraries /= Prj.None then
6089
 
6090
                     --  Check for library projects
6091
 
6092
                     Proj1 := Project_Tree.Projects;
6093
                     while Proj1 /= null loop
6094
                        if Proj1.Project /= Main_Project
6095
                          and then Proj1.Project.Library
6096
                        then
6097
                           --  Add this project to table Library_Projs
6098
 
6099
                           Libraries_Present := True;
6100
                           Depth := Proj1.Project.Depth;
6101
                           Library_Projs.Increment_Last;
6102
                           Current := Library_Projs.Last;
6103
 
6104
                           --  Any project with a greater depth should be
6105
                           --  after this project in the list.
6106
 
6107
                           while Current > 1 loop
6108
                              Proj2 := Library_Projs.Table (Current - 1);
6109
                              exit when Proj2.Depth <= Depth;
6110
                              Library_Projs.Table (Current) := Proj2;
6111
                              Current := Current - 1;
6112
                           end loop;
6113
 
6114
                           Library_Projs.Table (Current) := Proj1.Project;
6115
 
6116
                           --  If it is not a static library and path option
6117
                           --  is set, add it to the Library_Paths table.
6118
 
6119
                           if Proj1.Project.Library_Kind /= Static
6120
                             and then Path_Option /= null
6121
                           then
6122
                              Library_Paths.Increment_Last;
6123
                              Library_Paths.Table (Library_Paths.Last) :=
6124
                                new String'
6125
                                  (Get_Name_String
6126
                                     (Proj1.Project.Library_Dir.Display_Name));
6127
                           end if;
6128
                        end if;
6129
 
6130
                        Proj1 := Proj1.Next;
6131
                     end loop;
6132
 
6133
                     for Index in 1 .. Library_Projs.Last loop
6134
 
6135
                        --  Add the -L switch
6136
 
6137
                        Linker_Switches.Increment_Last;
6138
                        Linker_Switches.Table (Linker_Switches.Last) :=
6139
                          new String'("-L" &
6140
                                      Get_Name_String
6141
                                        (Library_Projs.Table (Index).
6142
                                            Library_Dir.Display_Name));
6143
 
6144
                        --  Add the -l switch
6145
 
6146
                        Linker_Switches.Increment_Last;
6147
                        Linker_Switches.Table (Linker_Switches.Last) :=
6148
                          new String'("-l" &
6149
                                      Get_Name_String
6150
                                        (Library_Projs.Table (Index).
6151
                                           Library_Name));
6152
                     end loop;
6153
                  end if;
6154
 
6155
                  if Libraries_Present then
6156
 
6157
                     --  If Path_Option is not null, create the switch
6158
                     --  ("-Wl,-rpath," or equivalent) with all the non static
6159
                     --  library dirs plus the standard GNAT library dir.
6160
                     --  We do that only if Run_Path_Option is True
6161
                     --  (not disabled by -R switch).
6162
 
6163
                     if Run_Path_Option and then Path_Option /= null then
6164
                        declare
6165
                           Option  : String_Access;
6166
                           Length  : Natural := Path_Option'Length;
6167
                           Current : Natural;
6168
 
6169
                        begin
6170
                           if MLib.Separate_Run_Path_Options then
6171
 
6172
                              --  We are going to create one switch of the form
6173
                              --  "-Wl,-rpath,dir_N" for each directory to
6174
                              --  consider.
6175
 
6176
                              --  One switch for each library directory
6177
 
6178
                              for Index in
6179
                                Library_Paths.First .. Library_Paths.Last
6180
                              loop
6181
                                 Linker_Switches.Increment_Last;
6182
                                 Linker_Switches.Table
6183
                                   (Linker_Switches.Last) := new String'
6184
                                   (Path_Option.all &
6185
                                    Library_Paths.Table (Index).all);
6186
                              end loop;
6187
 
6188
                              --  One switch for the standard GNAT library dir
6189
 
6190
                              Linker_Switches.Increment_Last;
6191
                              Linker_Switches.Table
6192
                                (Linker_Switches.Last) := new String'
6193
                                (Path_Option.all & MLib.Utl.Lib_Directory);
6194
 
6195
                           else
6196
                              --  We are going to create one switch of the form
6197
                              --  "-Wl,-rpath,dir_1:dir_2:dir_3"
6198
 
6199
                              for Index in
6200
                                Library_Paths.First .. Library_Paths.Last
6201
                              loop
6202
                                 --  Add the length of the library dir plus one
6203
                                 --  for the directory separator.
6204
 
6205
                                 Length :=
6206
                                   Length +
6207
                                     Library_Paths.Table (Index)'Length + 1;
6208
                              end loop;
6209
 
6210
                              --  Finally, add the length of the standard GNAT
6211
                              --  library dir.
6212
 
6213
                              Length := Length + MLib.Utl.Lib_Directory'Length;
6214
                              Option := new String (1 .. Length);
6215
                              Option (1 .. Path_Option'Length) :=
6216
                                Path_Option.all;
6217
                              Current := Path_Option'Length;
6218
 
6219
                              --  Put each library dir followed by a dir
6220
                              --  separator.
6221
 
6222
                              for Index in
6223
                                Library_Paths.First .. Library_Paths.Last
6224
                              loop
6225
                                 Option
6226
                                   (Current + 1 ..
6227
                                      Current +
6228
                                        Library_Paths.Table (Index)'Length) :=
6229
                                   Library_Paths.Table (Index).all;
6230
                                 Current :=
6231
                                   Current +
6232
                                     Library_Paths.Table (Index)'Length + 1;
6233
                                 Option (Current) := Path_Separator;
6234
                              end loop;
6235
 
6236
                              --  Finally put the standard GNAT library dir
6237
 
6238
                              Option
6239
                                (Current + 1 ..
6240
                                   Current + MLib.Utl.Lib_Directory'Length) :=
6241
                                  MLib.Utl.Lib_Directory;
6242
 
6243
                              --  And add the switch to the linker switches
6244
 
6245
                              Linker_Switches.Increment_Last;
6246
                              Linker_Switches.Table (Linker_Switches.Last) :=
6247
                                Option;
6248
                           end if;
6249
                        end;
6250
                     end if;
6251
 
6252
                  end if;
6253
 
6254
                  --  Put the object directories in ADA_OBJECTS_PATH
6255
 
6256
                  Prj.Env.Set_Ada_Paths (Main_Project, Project_Tree, False);
6257
 
6258
                  --  Check for attributes Linker'Linker_Options in projects
6259
                  --  other than the main project
6260
 
6261
                  declare
6262
                     Linker_Options : constant String_List :=
6263
                                        Linker_Options_Switches
6264
                                          (Main_Project, Project_Tree);
6265
                  begin
6266
                     for Option in Linker_Options'Range loop
6267
                        Linker_Switches.Increment_Last;
6268
                        Linker_Switches.Table (Linker_Switches.Last) :=
6269
                          Linker_Options (Option);
6270
                     end loop;
6271
                  end;
6272
               end if;
6273
 
6274
               declare
6275
                  Args : Argument_List
6276
                           (Linker_Switches.First .. Linker_Switches.Last + 2);
6277
 
6278
                  Last_Arg : Integer := Linker_Switches.First - 1;
6279
                  Skip     : Boolean := False;
6280
 
6281
               begin
6282
                  --  Get all the linker switches
6283
 
6284
                  for J in Linker_Switches.First .. Linker_Switches.Last loop
6285
                     if Skip then
6286
                        Skip := False;
6287
 
6288
                     elsif Non_Std_Executable
6289
                       and then Linker_Switches.Table (J).all = "-o"
6290
                     then
6291
                        Skip := True;
6292
 
6293
                     --  Here we capture and duplicate the linker argument. We
6294
                     --  need to do the duplication since the arguments will
6295
                     --  get normalized. Not doing so will result in calling
6296
                     --  normalized two times for the same set of arguments if
6297
                     --  gnatmake is passed multiple mains. This can result in
6298
                     --  the wrong argument being passed to the linker.
6299
 
6300
                     else
6301
                        Last_Arg := Last_Arg + 1;
6302
                        Args (Last_Arg) :=
6303
                          new String'(Linker_Switches.Table (J).all);
6304
                     end if;
6305
                  end loop;
6306
 
6307
                  --  If need be, add the -o switch
6308
 
6309
                  if Non_Std_Executable then
6310
                     Last_Arg := Last_Arg + 1;
6311
                     Args (Last_Arg) := new String'("-o");
6312
                     Last_Arg := Last_Arg + 1;
6313
                     Args (Last_Arg) :=
6314
                       new String'(Get_Name_String (Executable));
6315
                  end if;
6316
 
6317
                  --  And invoke the linker
6318
 
6319
                  declare
6320
                     Success : Boolean := False;
6321
                  begin
6322
                     Link (Main_ALI_File,
6323
                           Link_With_Shared_Libgcc.all &
6324
                           Args (Args'First .. Last_Arg),
6325
                           Success);
6326
 
6327
                     if Success then
6328
                        Successful_Links.Increment_Last;
6329
                        Successful_Links.Table (Successful_Links.Last) :=
6330
                          Main_ALI_File;
6331
 
6332
                     elsif Osint.Number_Of_Files = 1
6333
                       or else not Keep_Going
6334
                     then
6335
                        Make_Failed ("*** link failed.");
6336
 
6337
                     else
6338
                        Set_Standard_Error;
6339
                        Write_Line ("*** link failed");
6340
 
6341
                        if Commands_To_Stdout then
6342
                           Set_Standard_Output;
6343
                        end if;
6344
 
6345
                        Failed_Links.Increment_Last;
6346
                        Failed_Links.Table (Failed_Links.Last) :=
6347
                          Main_ALI_File;
6348
                     end if;
6349
                  end;
6350
               end;
6351
 
6352
               Linker_Switches.Set_Last (Linker_Switches_Last);
6353
            end Link_Step;
6354
         end if;
6355
 
6356
         --  We go to here when we skip the bind and link steps
6357
 
6358
         <<Next_Main>>
6359
 
6360
         --  We go to the next main, if we did not process the last one
6361
 
6362
         if N_File < Osint.Number_Of_Files then
6363
            Main_Source_File := Next_Main_Source;
6364
 
6365
            if Current_File_Index /= No_Index then
6366
               Main_Index := Current_File_Index;
6367
            end if;
6368
 
6369
            if Main_Project /= No_Project then
6370
 
6371
               --  Find the file name of the main unit
6372
 
6373
               declare
6374
                  Main_Source_File_Name : constant String :=
6375
                                            Get_Name_String (Main_Source_File);
6376
 
6377
                  Main_Unit_File_Name : constant String :=
6378
                                          Prj.Env.
6379
                                            File_Name_Of_Library_Unit_Body
6380
                                              (Name => Main_Source_File_Name,
6381
                                               Project => Main_Project,
6382
                                               In_Tree => Project_Tree,
6383
                                               Main_Project_Only =>
6384
                                                 not Unique_Compile);
6385
 
6386
                  The_Packages : constant Package_Id :=
6387
                    Main_Project.Decl.Packages;
6388
 
6389
                  Binder_Package : constant Prj.Package_Id :=
6390
                               Prj.Util.Value_Of
6391
                                 (Name        => Name_Binder,
6392
                                  In_Packages => The_Packages,
6393
                                  In_Tree     => Project_Tree);
6394
 
6395
                  Linker_Package : constant Prj.Package_Id :=
6396
                               Prj.Util.Value_Of
6397
                                 (Name        => Name_Linker,
6398
                                  In_Packages => The_Packages,
6399
                                  In_Tree     => Project_Tree);
6400
 
6401
               begin
6402
                  --  We fail if we cannot find the main source file
6403
                  --  as an immediate source of the main project file.
6404
 
6405
                  if Main_Unit_File_Name = "" then
6406
                     Make_Failed ('"' & Main_Source_File_Name
6407
                                  & """ is not a unit of project "
6408
                                  & Project_File_Name.all & ".");
6409
 
6410
                  else
6411
                     --  Remove any directory information from the main
6412
                     --  source file name.
6413
 
6414
                     declare
6415
                        Pos : Natural := Main_Unit_File_Name'Last;
6416
 
6417
                     begin
6418
                        loop
6419
                           exit when Pos < Main_Unit_File_Name'First
6420
                             or else
6421
                             Main_Unit_File_Name (Pos) = Directory_Separator;
6422
                           Pos := Pos - 1;
6423
                        end loop;
6424
 
6425
                        Name_Len := Main_Unit_File_Name'Last - Pos;
6426
 
6427
                        Name_Buffer (1 .. Name_Len) :=
6428
                          Main_Unit_File_Name
6429
                          (Pos + 1 .. Main_Unit_File_Name'Last);
6430
 
6431
                        Main_Source_File := Name_Find;
6432
                     end;
6433
                  end if;
6434
 
6435
                  --  We now deal with the binder and linker switches.
6436
                  --  If no project file is used, there is nothing to do
6437
                  --  because the binder and linker switches are the same
6438
                  --  for all mains.
6439
 
6440
                  --  Reset the tables Binder_Switches and Linker_Switches
6441
 
6442
                  Binder_Switches.Set_Last (Last_Binder_Switch);
6443
                  Linker_Switches.Set_Last (Last_Linker_Switch);
6444
 
6445
                  --  Add binder switches from the project file for this main,
6446
                  --  if any.
6447
 
6448
                  if Do_Bind_Step and then Binder_Package /= No_Package then
6449
                     if Verbose_Mode then
6450
                        Write_Str ("Adding binder switches for """);
6451
                        Write_Str (Main_Unit_File_Name);
6452
                        Write_Line (""".");
6453
                     end if;
6454
 
6455
                     Add_Switches
6456
                       (Project_Node_Tree => Project_Node_Tree,
6457
                        File_Name         => Main_Unit_File_Name,
6458
                        Index             => Main_Index,
6459
                        The_Package       => Binder_Package,
6460
                        Program           => Binder);
6461
                  end if;
6462
 
6463
                  --  Add linker switches from the project file for this main,
6464
                  --  if any.
6465
 
6466
                  if Do_Link_Step and then Linker_Package /= No_Package then
6467
                     if Verbose_Mode then
6468
                        Write_Str ("Adding linker switches for""");
6469
                        Write_Str (Main_Unit_File_Name);
6470
                        Write_Line (""".");
6471
                     end if;
6472
 
6473
                     Add_Switches
6474
                       (Project_Node_Tree => Project_Node_Tree,
6475
                        File_Name         => Main_Unit_File_Name,
6476
                        Index             => Main_Index,
6477
                        The_Package       => Linker_Package,
6478
                        Program           => Linker);
6479
                  end if;
6480
 
6481
                  --  As we are using a project file, for relative paths we add
6482
                  --  the current working directory for any relative path on
6483
                  --  the command line and the project directory, for any
6484
                  --  relative path in the project file.
6485
 
6486
                  declare
6487
                     Dir_Path : constant String :=
6488
                                  Get_Name_String
6489
                                    (Main_Project.Directory.Name);
6490
 
6491
                  begin
6492
                     for
6493
                       J in Last_Binder_Switch + 1 .. Binder_Switches.Last
6494
                     loop
6495
                        Test_If_Relative_Path
6496
                          (Binder_Switches.Table (J),
6497
                           Parent => Dir_Path, Including_L_Switch => False);
6498
                     end loop;
6499
 
6500
                     for
6501
                       J in Last_Linker_Switch + 1 .. Linker_Switches.Last
6502
                     loop
6503
                        Test_If_Relative_Path
6504
                          (Linker_Switches.Table (J), Parent => Dir_Path);
6505
                     end loop;
6506
                  end;
6507
 
6508
                  --  We now put in the Binder_Switches and Linker_Switches
6509
                  --  tables, the binder and linker switches of the command
6510
                  --  line that have been put in the Saved_ tables.
6511
                  --  These switches will follow the project file switches.
6512
 
6513
                  for J in 1 .. Saved_Binder_Switches.Last loop
6514
                     Add_Switch
6515
                       (Saved_Binder_Switches.Table (J),
6516
                        Binder,
6517
                        And_Save => False);
6518
                  end loop;
6519
 
6520
                  for J in 1 .. Saved_Linker_Switches.Last loop
6521
                     Add_Switch
6522
                       (Saved_Linker_Switches.Table (J),
6523
                        Linker,
6524
                        And_Save => False);
6525
                  end loop;
6526
               end;
6527
            end if;
6528
         end if;
6529
 
6530
         --  Remove all marks to be sure to check sources for all executables,
6531
         --  as the switches may be different and -s may be in use.
6532
 
6533
         Delete_All_Marks;
6534
      end loop Multiple_Main_Loop;
6535
 
6536
      if Failed_Links.Last > 0 then
6537
         for Index in 1 .. Successful_Links.Last loop
6538
            Write_Str ("Linking of """);
6539
            Write_Str (Get_Name_String (Successful_Links.Table (Index)));
6540
            Write_Line (""" succeeded.");
6541
         end loop;
6542
 
6543
         Set_Standard_Error;
6544
 
6545
         for Index in 1 .. Failed_Links.Last loop
6546
            Write_Str ("Linking of """);
6547
            Write_Str (Get_Name_String (Failed_Links.Table (Index)));
6548
            Write_Line (""" failed.");
6549
         end loop;
6550
 
6551
         if Commands_To_Stdout then
6552
            Set_Standard_Output;
6553
         end if;
6554
 
6555
         if Total_Compilation_Failures = 0 then
6556
            Report_Compilation_Failed;
6557
         end if;
6558
      end if;
6559
 
6560
      if Total_Compilation_Failures /= 0 then
6561
         List_Bad_Compilations;
6562
         Report_Compilation_Failed;
6563
      end if;
6564
 
6565
      --  Delete the temporary mapping file that was created if we are
6566
      --  using project files.
6567
 
6568
      Delete_All_Temp_Files;
6569
 
6570
   exception
6571
      when X : others =>
6572
         Set_Standard_Error;
6573
         Write_Line (Exception_Information (X));
6574
         Make_Failed ("INTERNAL ERROR. Please report.");
6575
   end Gnatmake;
6576
 
6577
   ----------
6578
   -- Hash --
6579
   ----------
6580
 
6581
   function Hash (F : File_Name_Type) return Header_Num is
6582
   begin
6583
      return Header_Num (1 + F mod Max_Header);
6584
   end Hash;
6585
 
6586
   --------------------
6587
   -- In_Ada_Lib_Dir --
6588
   --------------------
6589
 
6590
   function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean is
6591
      D : constant File_Name_Type := Get_Directory (File);
6592
      B : constant Byte           := Get_Name_Table_Byte (D);
6593
   begin
6594
      return (B and Ada_Lib_Dir) /= 0;
6595
   end In_Ada_Lib_Dir;
6596
 
6597
   -----------------------
6598
   -- Init_Mapping_File --
6599
   -----------------------
6600
 
6601
   procedure Init_Mapping_File
6602
     (Project    : Project_Id;
6603
      Data       : in out Project_Compilation_Data;
6604
      File_Index : in out Natural)
6605
   is
6606
      FD     : File_Descriptor;
6607
      Status : Boolean;
6608
      --  For call to Close
6609
 
6610
   begin
6611
      --  Increase the index of the last mapping file for this project
6612
 
6613
      Data.Last_Mapping_File_Names := Data.Last_Mapping_File_Names + 1;
6614
 
6615
      --  If there is a project file, call Create_Mapping_File with
6616
      --  the project id.
6617
 
6618
      if Project /= No_Project then
6619
         Prj.Env.Create_Mapping_File
6620
           (Project,
6621
            In_Tree  => Project_Tree,
6622
            Language => Name_Ada,
6623
            Name     => Data.Mapping_File_Names
6624
                          (Data.Last_Mapping_File_Names));
6625
 
6626
      --  Otherwise, just create an empty file
6627
 
6628
      else
6629
         Tempdir.Create_Temp_File
6630
           (FD,
6631
            Data.Mapping_File_Names (Data.Last_Mapping_File_Names));
6632
 
6633
         if FD = Invalid_FD then
6634
            Make_Failed ("disk full");
6635
 
6636
         else
6637
            Record_Temp_File
6638
              (Project_Tree,
6639
               Data.Mapping_File_Names (Data.Last_Mapping_File_Names));
6640
         end if;
6641
 
6642
         Close (FD, Status);
6643
 
6644
         if not Status then
6645
            Make_Failed ("disk full");
6646
         end if;
6647
      end if;
6648
 
6649
      --  And return the index of the newly created file
6650
 
6651
      File_Index := Data.Last_Mapping_File_Names;
6652
   end Init_Mapping_File;
6653
 
6654
   ------------
6655
   -- Init_Q --
6656
   ------------
6657
 
6658
   procedure Init_Q is
6659
   begin
6660
      First_Q_Initialization := False;
6661
      Q_Front := Q.First;
6662
      Q.Set_Last (Q.First);
6663
   end Init_Q;
6664
 
6665
   ----------------
6666
   -- Initialize --
6667
   ----------------
6668
 
6669
   procedure Initialize (Project_Node_Tree : out Project_Node_Tree_Ref) is
6670
 
6671
      procedure Check_Version_And_Help is
6672
         new Check_Version_And_Help_G (Makeusg);
6673
 
6674
      --  Start of processing for Initialize
6675
 
6676
   begin
6677
      --  Prepare the project's tree, since this is used to hold external
6678
      --  references, project path and other attributes that can be impacted by
6679
      --  the command line switches
6680
 
6681
      Project_Node_Tree := new Project_Node_Tree_Data;
6682
      Prj.Tree.Initialize (Project_Node_Tree);
6683
 
6684
      --  Override default initialization of Check_Object_Consistency since
6685
      --  this is normally False for GNATBIND, but is True for GNATMAKE since
6686
      --  we do not need to check source consistency again once GNATMAKE has
6687
      --  looked at the sources to check.
6688
 
6689
      Check_Object_Consistency := True;
6690
 
6691
      --  Package initializations. The order of calls is important here
6692
 
6693
      Output.Set_Standard_Error;
6694
 
6695
      Gcc_Switches.Init;
6696
      Binder_Switches.Init;
6697
      Linker_Switches.Init;
6698
 
6699
      Csets.Initialize;
6700
      Namet.Initialize;
6701
 
6702
      Snames.Initialize;
6703
 
6704
      Prj.Initialize (Project_Tree);
6705
 
6706
      Dependencies.Init;
6707
 
6708
      RTS_Specified := null;
6709
      N_M_Switch := 0;
6710
 
6711
      Mains.Delete;
6712
 
6713
      --  Add the directory where gnatmake is invoked in front of the path,
6714
      --  if gnatmake is invoked from a bin directory or with directory
6715
      --  information. Only do this if the platform is not VMS, where the
6716
      --  notion of path does not really exist.
6717
 
6718
      if not OpenVMS then
6719
         declare
6720
            Prefix  : constant String := Executable_Prefix_Path;
6721
            Command : constant String := Command_Name;
6722
 
6723
         begin
6724
            if Prefix'Length > 0 then
6725
               declare
6726
                  PATH : constant String :=
6727
                           Prefix & Directory_Separator & "bin" &
6728
                           Path_Separator &
6729
                           Getenv ("PATH").all;
6730
               begin
6731
                  Setenv ("PATH", PATH);
6732
               end;
6733
 
6734
            else
6735
               for Index in reverse Command'Range loop
6736
                  if Command (Index) = Directory_Separator then
6737
                     declare
6738
                        Absolute_Dir : constant String :=
6739
                                         Normalize_Pathname
6740
                                           (Command (Command'First .. Index));
6741
                        PATH         : constant String :=
6742
                                         Absolute_Dir &
6743
                                         Path_Separator &
6744
                                         Getenv ("PATH").all;
6745
                     begin
6746
                        Setenv ("PATH", PATH);
6747
                     end;
6748
 
6749
                     exit;
6750
                  end if;
6751
               end loop;
6752
            end if;
6753
         end;
6754
      end if;
6755
 
6756
      --  Scan the switches and arguments
6757
 
6758
      --  First, scan to detect --version and/or --help
6759
 
6760
      Check_Version_And_Help ("GNATMAKE", "1995");
6761
 
6762
      --  Scan again the switch and arguments, now that we are sure that they
6763
      --  do not include --version or --help.
6764
 
6765
      Scan_Args : for Next_Arg in 1 .. Argument_Count loop
6766
         Scan_Make_Arg
6767
           (Project_Node_Tree, Argument (Next_Arg), And_Save => True);
6768
      end loop Scan_Args;
6769
 
6770
      if N_M_Switch > 0 and RTS_Specified = null then
6771
         Process_Multilib (Project_Node_Tree);
6772
      end if;
6773
 
6774
      if Commands_To_Stdout then
6775
         Set_Standard_Output;
6776
      end if;
6777
 
6778
      if Usage_Requested then
6779
         Usage;
6780
      end if;
6781
 
6782
      --  Test for trailing -P switch
6783
 
6784
      if Project_File_Name_Present and then Project_File_Name = null then
6785
         Make_Failed ("project file name missing after -P");
6786
 
6787
      --  Test for trailing -o switch
6788
 
6789
      elsif Output_File_Name_Present
6790
        and then not Output_File_Name_Seen
6791
      then
6792
         Make_Failed ("output file name missing after -o");
6793
 
6794
      --  Test for trailing -D switch
6795
 
6796
      elsif Object_Directory_Present
6797
        and then not Object_Directory_Seen then
6798
         Make_Failed ("object directory missing after -D");
6799
      end if;
6800
 
6801
      --  Test for simultaneity of -i and -D
6802
 
6803
      if Object_Directory_Path /= null and then In_Place_Mode then
6804
         Make_Failed ("-i and -D cannot be used simultaneously");
6805
      end if;
6806
 
6807
      --  Deal with -C= switch
6808
 
6809
      if Gnatmake_Mapping_File /= null then
6810
 
6811
         --  First, check compatibility with other switches
6812
 
6813
         if Project_File_Name /= null then
6814
            Make_Failed ("-C= switch is not compatible with -P switch");
6815
 
6816
         elsif Saved_Maximum_Processes > 1 then
6817
            Make_Failed ("-C= switch is not compatible with -jnnn switch");
6818
         end if;
6819
 
6820
         Fmap.Initialize (Gnatmake_Mapping_File.all);
6821
         Add_Switch
6822
           ("-gnatem=" & Gnatmake_Mapping_File.all,
6823
            Compiler,
6824
            And_Save => True);
6825
      end if;
6826
 
6827
      if Project_File_Name /= null then
6828
 
6829
         --  A project file was specified by a -P switch
6830
 
6831
         if Verbose_Mode then
6832
            Write_Eol;
6833
            Write_Str ("Parsing project file """);
6834
            Write_Str (Project_File_Name.all);
6835
            Write_Str (""".");
6836
            Write_Eol;
6837
         end if;
6838
 
6839
         --  Avoid looking in the current directory for ALI files
6840
 
6841
         --  Look_In_Primary_Dir := False;
6842
 
6843
         --  Set the project parsing verbosity to whatever was specified
6844
         --  by a possible -vP switch.
6845
 
6846
         Prj.Pars.Set_Verbosity (To => Current_Verbosity);
6847
 
6848
         --  Parse the project file.
6849
         --  If there is an error, Main_Project will still be No_Project.
6850
 
6851
         Prj.Pars.Parse
6852
           (Project           => Main_Project,
6853
            In_Tree           => Project_Tree,
6854
            Project_File_Name => Project_File_Name.all,
6855
            Packages_To_Check => Packages_To_Check_By_Gnatmake,
6856
            Flags             => Gnatmake_Flags,
6857
            In_Node_Tree      => Project_Node_Tree);
6858
 
6859
         --  The parsing of project files may have changed the current output
6860
 
6861
         if Commands_To_Stdout then
6862
            Set_Standard_Output;
6863
         else
6864
            Set_Standard_Error;
6865
         end if;
6866
 
6867
         if Main_Project = No_Project then
6868
            Make_Failed
6869
              ("""" & Project_File_Name.all & """ processing failed");
6870
         end if;
6871
 
6872
         Create_Mapping_File := True;
6873
 
6874
         if Verbose_Mode then
6875
            Write_Eol;
6876
            Write_Str ("Parsing of project file """);
6877
            Write_Str (Project_File_Name.all);
6878
            Write_Str (""" is finished.");
6879
            Write_Eol;
6880
         end if;
6881
 
6882
         --  We add the source directories and the object directories to the
6883
         --  search paths.
6884
         --  ??? Why do we need these search directories, we already know the
6885
         --  locations from parsing the project, except for the runtime which
6886
         --  has its own directories anyway
6887
 
6888
         Add_Source_Directories (Main_Project, Project_Tree);
6889
         Add_Object_Directories (Main_Project);
6890
 
6891
         Recursive_Compute_Depth (Main_Project);
6892
         Compute_All_Imported_Projects (Project_Tree);
6893
 
6894
      else
6895
 
6896
         Osint.Add_Default_Search_Dirs;
6897
 
6898
         --  Source file lookups should be cached for efficiency. Source files
6899
         --  are not supposed to change. However, we do that now only if no
6900
         --  project file is used; if a project file is used, we do it just
6901
         --  after changing the directory to the object directory.
6902
 
6903
         Osint.Source_File_Data (Cache => True);
6904
 
6905
         --  Read gnat.adc file to initialize Fname.UF
6906
 
6907
         Fname.UF.Initialize;
6908
 
6909
         begin
6910
            Fname.SF.Read_Source_File_Name_Pragmas;
6911
 
6912
         exception
6913
            when Err : SFN_Scan.Syntax_Error_In_GNAT_ADC =>
6914
               Make_Failed (Exception_Message (Err));
6915
         end;
6916
      end if;
6917
 
6918
      --  Make sure no project object directory is recorded
6919
 
6920
      Project_Of_Current_Object_Directory := No_Project;
6921
 
6922
   end Initialize;
6923
 
6924
   ----------------------------
6925
   -- Insert_Project_Sources --
6926
   ----------------------------
6927
 
6928
   procedure Insert_Project_Sources
6929
     (The_Project  : Project_Id;
6930
      All_Projects : Boolean;
6931
      Into_Q       : Boolean)
6932
   is
6933
      Put_In_Q : Boolean := Into_Q;
6934
      Unit     : Unit_Index;
6935
      Sfile    : File_Name_Type;
6936
      Index    : Int;
6937
 
6938
      Extending : constant Boolean := The_Project.Extends /= No_Project;
6939
 
6940
      function Check_Project (P : Project_Id) return Boolean;
6941
      --  Returns True if P is The_Project or a project extended by The_Project
6942
 
6943
      -------------------
6944
      -- Check_Project --
6945
      -------------------
6946
 
6947
      function Check_Project (P : Project_Id) return Boolean is
6948
      begin
6949
         if All_Projects or else P = The_Project then
6950
            return True;
6951
 
6952
         elsif Extending then
6953
            declare
6954
               Proj : Project_Id;
6955
 
6956
            begin
6957
               Proj := The_Project;
6958
               while Proj /= null loop
6959
                  if P = Proj.Extends then
6960
                     return True;
6961
                  end if;
6962
 
6963
                  Proj := Proj.Extends;
6964
               end loop;
6965
            end;
6966
         end if;
6967
 
6968
         return False;
6969
      end Check_Project;
6970
 
6971
   --  Start of processing for Insert_Project_Sources
6972
 
6973
   begin
6974
      --  For all the sources in the project files,
6975
 
6976
      Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
6977
      while Unit /= null loop
6978
         Sfile := No_File;
6979
         Index := 0;
6980
 
6981
         --  If there is a source for the body, and the body has not been
6982
         --  locally removed.
6983
 
6984
         if Unit.File_Names (Impl) /= null
6985
           and then not Unit.File_Names (Impl).Locally_Removed
6986
         then
6987
            --  And it is a source for the specified project
6988
 
6989
            if Check_Project (Unit.File_Names (Impl).Project) then
6990
 
6991
               --  If we don't have a spec, we cannot consider the source
6992
               --  if it is a subunit.
6993
 
6994
               if Unit.File_Names (Spec) = null then
6995
                  declare
6996
                     Src_Ind : Source_File_Index;
6997
 
6998
                     --  Here we are cheating a little bit: we don't want to
6999
                     --  use Sinput.L, because it depends on the GNAT tree
7000
                     --  (Atree, Sinfo, ...). So, we pretend that it is a
7001
                     --  project file, and we use Sinput.P.
7002
 
7003
                     --  Source_File_Is_Subunit is just scanning through the
7004
                     --  file until it finds one of the reserved words
7005
                     --  separate, procedure, function, generic or package.
7006
                     --  Fortunately, these Ada reserved words are also
7007
                     --  reserved for project files.
7008
 
7009
                  begin
7010
                     Src_Ind := Sinput.P.Load_Project_File
7011
                                  (Get_Name_String
7012
                                     (Unit.File_Names (Impl).Path.Name));
7013
 
7014
                     --  If it is a subunit, discard it
7015
 
7016
                     if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7017
                        Sfile := No_File;
7018
                        Index := 0;
7019
                     else
7020
                        Sfile := Unit.File_Names (Impl).Display_File;
7021
                        Index := Unit.File_Names (Impl).Index;
7022
                     end if;
7023
                  end;
7024
 
7025
               else
7026
                  Sfile := Unit.File_Names (Impl).Display_File;
7027
                  Index := Unit.File_Names (Impl).Index;
7028
               end if;
7029
            end if;
7030
 
7031
         elsif Unit.File_Names (Spec) /= null
7032
           and then not Unit.File_Names (Spec).Locally_Removed
7033
           and then Check_Project (Unit.File_Names (Spec).Project)
7034
         then
7035
            --  If there is no source for the body, but there is one for the
7036
            --  spec which has not been locally removed, then we take this one.
7037
 
7038
            Sfile := Unit.File_Names (Spec).Display_File;
7039
            Index := Unit.File_Names (Spec).Index;
7040
         end if;
7041
 
7042
         --  If Put_In_Q is True, we insert into the Q
7043
 
7044
         if Put_In_Q then
7045
 
7046
            --  For the first source inserted into the Q, we need to initialize
7047
            --  the Q, but not for the subsequent sources.
7048
 
7049
            if First_Q_Initialization then
7050
               Init_Q;
7051
            end if;
7052
 
7053
            --  And of course, only insert in the Q if the source is not marked
7054
 
7055
            if Sfile /= No_File and then not Is_Marked (Sfile, Index) then
7056
               if Verbose_Mode then
7057
                  Write_Str ("Adding """);
7058
                  Write_Str (Get_Name_String (Sfile));
7059
                  Write_Line (""" to the queue");
7060
               end if;
7061
 
7062
               Insert_Q (Sfile, Index => Index);
7063
               Mark (Sfile, Index);
7064
            end if;
7065
 
7066
         elsif Sfile /= No_File then
7067
 
7068
            --  If Put_In_Q is False, we add the source as if it were specified
7069
            --  on the command line, and we set Put_In_Q to True, so that the
7070
            --  following sources will be put directly in the queue. This will
7071
            --  allow parallel compilation processes if -jx switch is used.
7072
 
7073
            if Verbose_Mode then
7074
               Write_Str ("Adding """);
7075
               Write_Str (Get_Name_String (Sfile));
7076
               Write_Line (""" as if on the command line");
7077
            end if;
7078
 
7079
            Osint.Add_File (Get_Name_String (Sfile), Index);
7080
            Put_In_Q := True;
7081
 
7082
            --  As we may look into the Q later, ensure the Q has been
7083
            --  initialized to avoid errors.
7084
 
7085
            if First_Q_Initialization then
7086
               Init_Q;
7087
            end if;
7088
         end if;
7089
 
7090
         Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
7091
      end loop;
7092
   end Insert_Project_Sources;
7093
 
7094
   --------------
7095
   -- Insert_Q --
7096
   --------------
7097
 
7098
   procedure Insert_Q
7099
     (Source_File : File_Name_Type;
7100
      Source_Unit : Unit_Name_Type := No_Unit_Name;
7101
      Index       : Int            := 0)
7102
   is
7103
   begin
7104
      if Debug.Debug_Flag_Q then
7105
         Write_Str ("   Q := Q + [ ");
7106
         Write_Name (Source_File);
7107
 
7108
         if Index /= 0 then
7109
            Write_Str (", ");
7110
            Write_Int (Index);
7111
         end if;
7112
 
7113
         Write_Str (" ] ");
7114
         Write_Eol;
7115
      end if;
7116
 
7117
      Q.Table (Q.Last) :=
7118
        (File  => Source_File,
7119
         Unit  => Source_Unit,
7120
         Index => Index);
7121
      Q.Increment_Last;
7122
   end Insert_Q;
7123
 
7124
   ---------------------
7125
   -- Is_In_Obsoleted --
7126
   ---------------------
7127
 
7128
   function Is_In_Obsoleted (F : File_Name_Type) return Boolean is
7129
   begin
7130
      if F = No_File then
7131
         return False;
7132
 
7133
      else
7134
         declare
7135
            Name  : constant String := Get_Name_String (F);
7136
            First : Natural;
7137
            F2    : File_Name_Type;
7138
 
7139
         begin
7140
            First := Name'Last;
7141
            while First > Name'First
7142
              and then Name (First - 1) /= Directory_Separator
7143
              and then Name (First - 1) /= '/'
7144
            loop
7145
               First := First - 1;
7146
            end loop;
7147
 
7148
            if First /= Name'First then
7149
               Name_Len := 0;
7150
               Add_Str_To_Name_Buffer (Name (First .. Name'Last));
7151
               F2 := Name_Find;
7152
 
7153
            else
7154
               F2 := F;
7155
            end if;
7156
 
7157
            return Obsoleted.Get (F2);
7158
         end;
7159
      end if;
7160
   end Is_In_Obsoleted;
7161
 
7162
   ----------------------------
7163
   -- Is_In_Object_Directory --
7164
   ----------------------------
7165
 
7166
   function Is_In_Object_Directory
7167
     (Source_File   : File_Name_Type;
7168
      Full_Lib_File : File_Name_Type) return Boolean
7169
   is
7170
   begin
7171
      --  There is something to check only when using project files. Otherwise,
7172
      --  this function returns True (last line of the function).
7173
 
7174
      if Main_Project /= No_Project then
7175
         declare
7176
            Source_File_Name : constant String :=
7177
                                 Get_Name_String (Source_File);
7178
            Saved_Verbosity  : constant Verbosity := Current_Verbosity;
7179
            Project          : Project_Id         := No_Project;
7180
 
7181
            Path_Name : Path_Name_Type := No_Path;
7182
            pragma Warnings (Off, Path_Name);
7183
 
7184
         begin
7185
            --  Call Get_Reference to know the ultimate extending project of
7186
            --  the source. Call it with verbosity default to avoid verbose
7187
            --  messages.
7188
 
7189
            Current_Verbosity := Default;
7190
            Prj.Env.Get_Reference
7191
              (Source_File_Name => Source_File_Name,
7192
               Project          => Project,
7193
               In_Tree          => Project_Tree,
7194
               Path             => Path_Name);
7195
            Current_Verbosity := Saved_Verbosity;
7196
 
7197
            --  If this source is in a project, check that the ALI file is in
7198
            --  its object directory. If it is not, return False, so that the
7199
            --  ALI file will not be skipped.
7200
 
7201
            if Project /= No_Project then
7202
               declare
7203
                  Object_Directory : constant String :=
7204
                                       Normalize_Pathname
7205
                                        (Get_Name_String
7206
                                         (Project.
7207
                                            Object_Directory.Display_Name));
7208
 
7209
                  Olast : Natural := Object_Directory'Last;
7210
 
7211
                  Lib_File_Directory : constant String :=
7212
                                         Normalize_Pathname (Dir_Name
7213
                                           (Get_Name_String (Full_Lib_File)));
7214
 
7215
                  Llast : Natural := Lib_File_Directory'Last;
7216
 
7217
               begin
7218
                  --  For directories, Normalize_Pathname may or may not put
7219
                  --  a directory separator at the end, depending on its input.
7220
                  --  Remove any last directory separator before comparison.
7221
                  --  Returns True only if the two directories are the same.
7222
 
7223
                  if Object_Directory (Olast) = Directory_Separator then
7224
                     Olast := Olast - 1;
7225
                  end if;
7226
 
7227
                  if Lib_File_Directory (Llast) = Directory_Separator then
7228
                     Llast := Llast - 1;
7229
                  end if;
7230
 
7231
                  return Object_Directory (Object_Directory'First .. Olast) =
7232
                        Lib_File_Directory (Lib_File_Directory'First .. Llast);
7233
               end;
7234
            end if;
7235
         end;
7236
      end if;
7237
 
7238
      --  When the source is not in a project file, always return True
7239
 
7240
      return True;
7241
   end Is_In_Object_Directory;
7242
 
7243
   ----------
7244
   -- Link --
7245
   ----------
7246
 
7247
   procedure Link
7248
     (ALI_File : File_Name_Type;
7249
      Args     : Argument_List;
7250
      Success  : out Boolean)
7251
   is
7252
      Link_Args : Argument_List (1 .. Args'Length + 1);
7253
 
7254
   begin
7255
      Get_Name_String (ALI_File);
7256
      Link_Args (1) := new String'(Name_Buffer (1 .. Name_Len));
7257
 
7258
      Link_Args (2 .. Args'Length + 1) :=  Args;
7259
 
7260
      GNAT.OS_Lib.Normalize_Arguments (Link_Args);
7261
 
7262
      Display (Gnatlink.all, Link_Args);
7263
 
7264
      if Gnatlink_Path = null then
7265
         Make_Failed ("error, unable to locate " & Gnatlink.all);
7266
      end if;
7267
 
7268
      GNAT.OS_Lib.Spawn (Gnatlink_Path.all, Link_Args, Success);
7269
   end Link;
7270
 
7271
   ---------------------------
7272
   -- List_Bad_Compilations --
7273
   ---------------------------
7274
 
7275
   procedure List_Bad_Compilations is
7276
   begin
7277
      for J in Bad_Compilation.First .. Bad_Compilation.Last loop
7278
         if Bad_Compilation.Table (J).File = No_File then
7279
            null;
7280
         elsif not Bad_Compilation.Table (J).Found then
7281
            Inform (Bad_Compilation.Table (J).File, "not found");
7282
         else
7283
            Inform (Bad_Compilation.Table (J).File, "compilation error");
7284
         end if;
7285
      end loop;
7286
   end List_Bad_Compilations;
7287
 
7288
   -----------------
7289
   -- List_Depend --
7290
   -----------------
7291
 
7292
   procedure List_Depend is
7293
      Lib_Name  : File_Name_Type;
7294
      Obj_Name  : File_Name_Type;
7295
      Src_Name  : File_Name_Type;
7296
 
7297
      Len       : Natural;
7298
      Line_Pos  : Natural;
7299
      Line_Size : constant := 77;
7300
 
7301
   begin
7302
      Set_Standard_Output;
7303
 
7304
      for A in ALIs.First .. ALIs.Last loop
7305
         Lib_Name := ALIs.Table (A).Afile;
7306
 
7307
         --  We have to provide the full library file name in In_Place_Mode
7308
 
7309
         if In_Place_Mode then
7310
            Lib_Name := Full_Lib_File_Name (Lib_Name);
7311
         end if;
7312
 
7313
         Obj_Name := Object_File_Name (Lib_Name);
7314
         Write_Name (Obj_Name);
7315
         Write_Str (" :");
7316
 
7317
         Get_Name_String (Obj_Name);
7318
         Len := Name_Len;
7319
         Line_Pos := Len + 2;
7320
 
7321
         for D in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop
7322
            Src_Name := Sdep.Table (D).Sfile;
7323
 
7324
            if Is_Internal_File_Name (Src_Name)
7325
              and then not Check_Readonly_Files
7326
            then
7327
               null;
7328
            else
7329
               if not Quiet_Output then
7330
                  Src_Name := Full_Source_Name (Src_Name);
7331
               end if;
7332
 
7333
               Get_Name_String (Src_Name);
7334
               Len := Name_Len;
7335
 
7336
               if Line_Pos + Len + 1 > Line_Size then
7337
                  Write_Str (" \");
7338
                  Write_Eol;
7339
                  Line_Pos := 0;
7340
               end if;
7341
 
7342
               Line_Pos := Line_Pos + Len + 1;
7343
 
7344
               Write_Str (" ");
7345
               Write_Name (Src_Name);
7346
            end if;
7347
         end loop;
7348
 
7349
         Write_Eol;
7350
      end loop;
7351
 
7352
      if not Commands_To_Stdout then
7353
         Set_Standard_Error;
7354
      end if;
7355
   end List_Depend;
7356
 
7357
   -----------------
7358
   -- Make_Failed --
7359
   -----------------
7360
 
7361
   procedure Make_Failed (S : String) is
7362
   begin
7363
      Delete_All_Temp_Files;
7364
      Osint.Fail (S);
7365
   end Make_Failed;
7366
 
7367
   --------------------
7368
   -- Mark_Directory --
7369
   --------------------
7370
 
7371
   procedure Mark_Directory
7372
     (Dir             : String;
7373
      Mark            : Lib_Mark_Type;
7374
      On_Command_Line : Boolean)
7375
   is
7376
      N : Name_Id;
7377
      B : Byte;
7378
 
7379
      function Base_Directory return String;
7380
      --  If Dir comes from the command line, empty string (relative paths are
7381
      --  resolved with respect to the current directory), else return the main
7382
      --  project's directory.
7383
 
7384
      --------------------
7385
      -- Base_Directory --
7386
      --------------------
7387
 
7388
      function Base_Directory return String is
7389
      begin
7390
         if On_Command_Line then
7391
            return "";
7392
         else
7393
            return Get_Name_String (Main_Project.Directory.Display_Name);
7394
         end if;
7395
      end Base_Directory;
7396
 
7397
      Real_Path : constant String := Normalize_Pathname (Dir, Base_Directory);
7398
 
7399
   --  Start of processing for Mark_Directory
7400
 
7401
   begin
7402
      Name_Len := 0;
7403
 
7404
      if Real_Path'Length = 0 then
7405
         Add_Str_To_Name_Buffer (Dir);
7406
 
7407
      else
7408
         Add_Str_To_Name_Buffer (Real_Path);
7409
      end if;
7410
 
7411
      --  Last character is supposed to be a directory separator
7412
 
7413
      if not Is_Directory_Separator (Name_Buffer (Name_Len)) then
7414
         Add_Char_To_Name_Buffer (Directory_Separator);
7415
      end if;
7416
 
7417
      --  Add flags to the already existing flags
7418
 
7419
      N := Name_Find;
7420
      B := Get_Name_Table_Byte (N);
7421
      Set_Name_Table_Byte (N, B or Mark);
7422
   end Mark_Directory;
7423
 
7424
   ----------------------
7425
   -- Process_Multilib --
7426
   ----------------------
7427
 
7428
   procedure Process_Multilib
7429
     (Project_Node_Tree : Project_Node_Tree_Ref)
7430
   is
7431
      Output_FD         : File_Descriptor;
7432
      Output_Name       : String_Access;
7433
      Arg_Index         : Natural := 0;
7434
      Success           : Boolean := False;
7435
      Return_Code       : Integer := 0;
7436
      Multilib_Gcc_Path : String_Access;
7437
      Multilib_Gcc      : String_Access;
7438
      N_Read            : Integer := 0;
7439
      Line              : String (1 .. 1000);
7440
      Args              : Argument_List (1 .. N_M_Switch + 1);
7441
 
7442
   begin
7443
      pragma Assert (N_M_Switch > 0 and RTS_Specified = null);
7444
 
7445
      --  In case we detected a multilib switch and the user has not
7446
      --  manually specified a specific RTS we emulate the following command:
7447
      --  gnatmake $FLAGS --RTS=$(gcc -print-multi-directory $FLAGS)
7448
 
7449
      --  First select the flags which might have an impact on multilib
7450
      --  processing. Note that this is an heuristic selection and it
7451
      --  will need to be maintained over time. The condition has to
7452
      --  be kept synchronized with N_M_Switch counting in Scan_Make_Arg.
7453
 
7454
      for Next_Arg in 1 .. Argument_Count loop
7455
         declare
7456
            Argv : constant String := Argument (Next_Arg);
7457
         begin
7458
            if Argv'Length > 2
7459
              and then Argv (1) = '-'
7460
              and then Argv (2) = 'm'
7461
              and then Argv /= "-margs"
7462
 
7463
              --  Ignore -mieee to avoid spawning an extra gcc in this case
7464
 
7465
              and then Argv /= "-mieee"
7466
            then
7467
               Arg_Index := Arg_Index + 1;
7468
               Args (Arg_Index) := new String'(Argv);
7469
            end if;
7470
         end;
7471
      end loop;
7472
 
7473
      pragma Assert (Arg_Index = N_M_Switch);
7474
 
7475
      Args (Args'Last) := new String'("-print-multi-directory");
7476
 
7477
      --  Call the GCC driver with the collected flags and save its
7478
      --  output. Alternate design would be to link in gnatmake the
7479
      --  relevant part of the GCC driver.
7480
 
7481
      if Saved_Gcc /= null then
7482
         Multilib_Gcc := Saved_Gcc;
7483
      else
7484
         Multilib_Gcc := Gcc;
7485
      end if;
7486
 
7487
      Multilib_Gcc_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Multilib_Gcc.all);
7488
 
7489
      Create_Temp_Output_File (Output_FD, Output_Name);
7490
 
7491
      if Output_FD = Invalid_FD then
7492
         return;
7493
      end if;
7494
 
7495
      GNAT.OS_Lib.Spawn
7496
        (Multilib_Gcc_Path.all, Args, Output_FD, Return_Code, False);
7497
      Close (Output_FD);
7498
 
7499
      if Return_Code /= 0 then
7500
         return;
7501
      end if;
7502
 
7503
      --  Parse the GCC driver output which is a single line, removing CR/LF
7504
 
7505
      Output_FD := Open_Read (Output_Name.all, Binary);
7506
 
7507
      if Output_FD = Invalid_FD then
7508
         return;
7509
      end if;
7510
 
7511
      N_Read := Read (Output_FD, Line (1)'Address, Line'Length);
7512
      Close (Output_FD);
7513
      Delete_File (Output_Name.all, Success);
7514
 
7515
      for J in reverse 1 .. N_Read loop
7516
         if Line (J) = ASCII.CR or else Line (J) = ASCII.LF then
7517
            N_Read := N_Read - 1;
7518
         else
7519
            exit;
7520
         end if;
7521
      end loop;
7522
 
7523
      --  In case the standard RTS is selected do nothing
7524
 
7525
      if N_Read = 0 or else Line (1 .. N_Read) = "." then
7526
         return;
7527
      end if;
7528
 
7529
      --  Otherwise add -margs --RTS=output
7530
 
7531
      Scan_Make_Arg (Project_Node_Tree, "-margs", And_Save => True);
7532
      Scan_Make_Arg
7533
        (Project_Node_Tree, "--RTS=" & Line (1 .. N_Read), And_Save => True);
7534
   end Process_Multilib;
7535
 
7536
   -----------------------------
7537
   -- Recursive_Compute_Depth --
7538
   -----------------------------
7539
 
7540
   procedure Recursive_Compute_Depth (Project : Project_Id) is
7541
      use Project_Boolean_Htable;
7542
      Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil;
7543
 
7544
      procedure Recurse (Prj : Project_Id; Depth : Natural);
7545
      --  Recursive procedure that does the work, keeping track of the depth
7546
 
7547
      -------------
7548
      -- Recurse --
7549
      -------------
7550
 
7551
      procedure Recurse (Prj : Project_Id; Depth : Natural) is
7552
         List : Project_List;
7553
         Proj : Project_Id;
7554
 
7555
      begin
7556
         if Prj.Depth >= Depth or else Get (Seen, Prj) then
7557
            return;
7558
         end if;
7559
 
7560
         --  We need a test to avoid infinite recursions with limited withs:
7561
         --  If we have A -> B -> A, then when set level of A to n, we try and
7562
         --  set level of B to n+1, and then level of A to n + 2, ...
7563
 
7564
         Set (Seen, Prj, True);
7565
 
7566
         Prj.Depth := Depth;
7567
 
7568
         --  Visit each imported project
7569
 
7570
         List := Prj.Imported_Projects;
7571
         while List /= null loop
7572
            Proj := List.Project;
7573
            List := List.Next;
7574
            Recurse (Prj => Proj, Depth => Depth + 1);
7575
         end loop;
7576
 
7577
         --  We again allow changing the depth of this project later on if it
7578
         --  is in fact imported by a lower-level project.
7579
 
7580
         Set (Seen, Prj, False);
7581
      end Recurse;
7582
 
7583
      Proj : Project_List;
7584
 
7585
   --  Start of processing for Recursive_Compute_Depth
7586
 
7587
   begin
7588
      Proj := Project_Tree.Projects;
7589
      while Proj /= null loop
7590
         Proj.Project.Depth := 0;
7591
         Proj := Proj.Next;
7592
      end loop;
7593
 
7594
      Recurse (Project, Depth => 1);
7595
      Reset (Seen);
7596
   end Recursive_Compute_Depth;
7597
 
7598
   -------------------------------
7599
   -- Report_Compilation_Failed --
7600
   -------------------------------
7601
 
7602
   procedure Report_Compilation_Failed is
7603
   begin
7604
      Delete_All_Temp_Files;
7605
      Exit_Program (E_Fatal);
7606
   end Report_Compilation_Failed;
7607
 
7608
   ------------------------
7609
   -- Sigint_Intercepted --
7610
   ------------------------
7611
 
7612
   procedure Sigint_Intercepted is
7613
      SIGINT  : constant := 2;
7614
 
7615
   begin
7616
      Set_Standard_Error;
7617
      Write_Line ("*** Interrupted ***");
7618
 
7619
      --  Send SIGINT to all outstanding compilation processes spawned
7620
 
7621
      for J in 1 .. Outstanding_Compiles loop
7622
         Kill (Running_Compile (J).Pid, SIGINT, 1);
7623
      end loop;
7624
 
7625
      Delete_All_Temp_Files;
7626
      OS_Exit (1);
7627
      --  ??? OS_Exit (1) is equivalent to Exit_Program (E_No_Compile),
7628
      --  shouldn't that be Exit_Program (E_Abort) instead?
7629
   end Sigint_Intercepted;
7630
 
7631
   -------------------
7632
   -- Scan_Make_Arg --
7633
   -------------------
7634
 
7635
   procedure Scan_Make_Arg
7636
     (Project_Node_Tree : Project_Node_Tree_Ref;
7637
      Argv              : String;
7638
      And_Save          : Boolean)
7639
   is
7640
      Success : Boolean;
7641
 
7642
   begin
7643
      Gnatmake_Switch_Found := True;
7644
 
7645
      pragma Assert (Argv'First = 1);
7646
 
7647
      if Argv'Length = 0 then
7648
         return;
7649
      end if;
7650
 
7651
      --  If the previous switch has set the Project_File_Name_Present flag
7652
      --  (that is we have seen a -P alone), then the next argument is the name
7653
      --  of the project file.
7654
 
7655
      if Project_File_Name_Present and then Project_File_Name = null then
7656
         if Argv (1) = '-' then
7657
            Make_Failed ("project file name missing after -P");
7658
 
7659
         else
7660
            Project_File_Name_Present := False;
7661
            Project_File_Name := new String'(Argv);
7662
         end if;
7663
 
7664
      --  If the previous switch has set the Output_File_Name_Present flag
7665
      --  (that is we have seen a -o), then the next argument is the name of
7666
      --  the output executable.
7667
 
7668
      elsif Output_File_Name_Present
7669
        and then not Output_File_Name_Seen
7670
      then
7671
         Output_File_Name_Seen := True;
7672
 
7673
         if Argv (1) = '-' then
7674
            Make_Failed ("output file name missing after -o");
7675
 
7676
         else
7677
            Add_Switch ("-o", Linker, And_Save => And_Save);
7678
            Add_Switch (Executable_Name (Argv), Linker, And_Save => And_Save);
7679
         end if;
7680
 
7681
      --  If the previous switch has set the Object_Directory_Present flag
7682
      --  (that is we have seen a -D), then the next argument is the path name
7683
      --  of the object directory.
7684
 
7685
      elsif Object_Directory_Present
7686
        and then not Object_Directory_Seen
7687
      then
7688
         Object_Directory_Seen := True;
7689
 
7690
         if Argv (1) = '-' then
7691
            Make_Failed ("object directory path name missing after -D");
7692
 
7693
         elsif not Is_Directory (Argv) then
7694
            Make_Failed ("cannot find object directory """ & Argv & """");
7695
 
7696
         else
7697
            --  Record the object directory. Make sure it ends with a directory
7698
            --  separator.
7699
 
7700
            declare
7701
               Norm : constant String := Normalize_Pathname (Argv);
7702
 
7703
            begin
7704
               if Norm (Norm'Last) = Directory_Separator then
7705
                  Object_Directory_Path := new String'(Norm);
7706
               else
7707
                  Object_Directory_Path :=
7708
                    new String'(Norm & Directory_Separator);
7709
               end if;
7710
 
7711
               Add_Lib_Search_Dir (Norm);
7712
 
7713
               --  Specify the object directory to the binder
7714
 
7715
               Add_Switch ("-aO" & Norm, Binder, And_Save => And_Save);
7716
            end;
7717
 
7718
         end if;
7719
 
7720
      --  Then check if we are dealing with -cargs/-bargs/-largs/-margs
7721
 
7722
      elsif Argv = "-bargs"
7723
              or else
7724
            Argv = "-cargs"
7725
              or else
7726
            Argv = "-largs"
7727
              or else
7728
            Argv = "-margs"
7729
      then
7730
         case Argv (2) is
7731
            when 'c' => Program_Args := Compiler;
7732
            when 'b' => Program_Args := Binder;
7733
            when 'l' => Program_Args := Linker;
7734
            when 'm' => Program_Args := None;
7735
 
7736
            when others =>
7737
               raise Program_Error;
7738
         end case;
7739
 
7740
      --  A special test is needed for the -o switch within a -largs since that
7741
      --  is another way to specify the name of the final executable.
7742
 
7743
      elsif Program_Args = Linker
7744
        and then Argv = "-o"
7745
      then
7746
         Make_Failed ("switch -o not allowed within a -largs. " &
7747
                      "Use -o directly.");
7748
 
7749
      --  Check to see if we are reading switches after a -cargs, -bargs or
7750
      --  -largs switch. If so, save it.
7751
 
7752
      elsif Program_Args /= None then
7753
 
7754
         --  Check to see if we are reading -I switches in order
7755
         --  to take into account in the src & lib search directories.
7756
 
7757
         if Argv'Length > 2 and then Argv (1 .. 2) = "-I" then
7758
            if Argv (3 .. Argv'Last) = "-" then
7759
               Look_In_Primary_Dir := False;
7760
 
7761
            elsif Program_Args = Compiler then
7762
               if Argv (3 .. Argv'Last) /= "-" then
7763
                  Add_Source_Search_Dir (Argv (3 .. Argv'Last), And_Save);
7764
               end if;
7765
 
7766
            elsif Program_Args = Binder then
7767
               Add_Library_Search_Dir (Argv (3 .. Argv'Last), And_Save);
7768
            end if;
7769
         end if;
7770
 
7771
         Add_Switch (Argv, Program_Args, And_Save => And_Save);
7772
 
7773
      --  Handle non-default compiler, binder, linker, and handle --RTS switch
7774
 
7775
      elsif Argv'Length > 2 and then Argv (1 .. 2) = "--" then
7776
         if Argv'Length > 6
7777
           and then Argv (1 .. 6) = "--GCC="
7778
         then
7779
            declare
7780
               Program_Args : constant Argument_List_Access :=
7781
                                Argument_String_To_List
7782
                                  (Argv (7 .. Argv'Last));
7783
 
7784
            begin
7785
               if And_Save then
7786
                  Saved_Gcc := new String'(Program_Args.all (1).all);
7787
               else
7788
                  Gcc := new String'(Program_Args.all (1).all);
7789
               end if;
7790
 
7791
               for J in 2 .. Program_Args.all'Last loop
7792
                  Add_Switch
7793
                    (Program_Args.all (J).all, Compiler, And_Save => And_Save);
7794
               end loop;
7795
            end;
7796
 
7797
         elsif Argv'Length > 11
7798
           and then Argv (1 .. 11) = "--GNATBIND="
7799
         then
7800
            declare
7801
               Program_Args : constant Argument_List_Access :=
7802
                                Argument_String_To_List
7803
                                  (Argv (12 .. Argv'Last));
7804
 
7805
            begin
7806
               if And_Save then
7807
                  Saved_Gnatbind := new String'(Program_Args.all (1).all);
7808
               else
7809
                  Gnatbind := new String'(Program_Args.all (1).all);
7810
               end if;
7811
 
7812
               for J in 2 .. Program_Args.all'Last loop
7813
                  Add_Switch
7814
                    (Program_Args.all (J).all, Binder, And_Save => And_Save);
7815
               end loop;
7816
            end;
7817
 
7818
         elsif Argv'Length > 11
7819
           and then Argv (1 .. 11) = "--GNATLINK="
7820
         then
7821
            declare
7822
               Program_Args : constant Argument_List_Access :=
7823
                                Argument_String_To_List
7824
                                  (Argv (12 .. Argv'Last));
7825
            begin
7826
               if And_Save then
7827
                  Saved_Gnatlink := new String'(Program_Args.all (1).all);
7828
               else
7829
                  Gnatlink := new String'(Program_Args.all (1).all);
7830
               end if;
7831
 
7832
               for J in 2 .. Program_Args.all'Last loop
7833
                  Add_Switch (Program_Args.all (J).all, Linker);
7834
               end loop;
7835
            end;
7836
 
7837
         elsif Argv'Length >= 5 and then
7838
           Argv (1 .. 5) = "--RTS"
7839
         then
7840
            Add_Switch (Argv, Compiler, And_Save => And_Save);
7841
            Add_Switch (Argv, Binder,   And_Save => And_Save);
7842
 
7843
            if Argv'Length <= 6 or else Argv (6) /= '=' then
7844
               Make_Failed ("missing path for --RTS");
7845
 
7846
            else
7847
               --  Check that this is the first time we see this switch or
7848
               --  if it is not the first time, the same path is specified.
7849
 
7850
               if RTS_Specified = null then
7851
                  RTS_Specified := new String'(Argv (7 .. Argv'Last));
7852
 
7853
               elsif RTS_Specified.all /= Argv (7 .. Argv'Last) then
7854
                  Make_Failed ("--RTS cannot be specified multiple times");
7855
               end if;
7856
 
7857
               --  Valid --RTS switch
7858
 
7859
               No_Stdinc := True;
7860
               No_Stdlib := True;
7861
               RTS_Switch := True;
7862
 
7863
               declare
7864
                  Src_Path_Name : constant String_Ptr :=
7865
                                    Get_RTS_Search_Dir
7866
                                      (Argv (7 .. Argv'Last), Include);
7867
 
7868
                  Lib_Path_Name : constant String_Ptr :=
7869
                                    Get_RTS_Search_Dir
7870
                                      (Argv (7 .. Argv'Last), Objects);
7871
 
7872
               begin
7873
                  if Src_Path_Name /= null
7874
                    and then Lib_Path_Name /= null
7875
                  then
7876
                     --  Set RTS_*_Path_Name variables, so that correct direct-
7877
                     --  ories will be set when Osint.Add_Default_Search_Dirs
7878
                     --  is called later.
7879
 
7880
                     RTS_Src_Path_Name := Src_Path_Name;
7881
                     RTS_Lib_Path_Name := Lib_Path_Name;
7882
 
7883
                  elsif Src_Path_Name = null
7884
                    and then Lib_Path_Name = null
7885
                  then
7886
                     Make_Failed ("RTS path not valid: missing " &
7887
                                  "adainclude and adalib directories");
7888
 
7889
                  elsif Src_Path_Name = null then
7890
                     Make_Failed ("RTS path not valid: missing adainclude " &
7891
                                  "directory");
7892
 
7893
                  elsif  Lib_Path_Name = null then
7894
                     Make_Failed ("RTS path not valid: missing adalib " &
7895
                                  "directory");
7896
                  end if;
7897
               end;
7898
            end if;
7899
 
7900
         elsif Argv'Length >= 8 and then
7901
           Argv (1 .. 8) = "--param="
7902
         then
7903
            Add_Switch (Argv, Compiler, And_Save => And_Save);
7904
            Add_Switch (Argv, Linker,   And_Save => And_Save);
7905
 
7906
         else
7907
            Scan_Make_Switches (Project_Node_Tree, Argv, Success);
7908
         end if;
7909
 
7910
      --  If we have seen a regular switch process it
7911
 
7912
      elsif Argv (1) = '-' then
7913
         if Argv'Length = 1 then
7914
            Make_Failed ("switch character cannot be followed by a blank");
7915
 
7916
         --  Incorrect switches that should start with "--"
7917
 
7918
         elsif     (Argv'Length > 5  and then Argv (1 .. 5) = "-RTS=")
7919
           or else (Argv'Length > 5  and then Argv (1 .. 5) = "-GCC=")
7920
           or else (Argv'Length > 8  and then Argv (1 .. 7) = "-param=")
7921
           or else (Argv'Length > 10 and then Argv (1 .. 10) = "-GNATLINK=")
7922
           or else (Argv'Length > 10 and then Argv (1 .. 10) = "-GNATBIND=")
7923
         then
7924
            Make_Failed ("option " & Argv & " should start with '--'");
7925
 
7926
         --  -I-
7927
 
7928
         elsif Argv (2 .. Argv'Last) = "I-" then
7929
            Look_In_Primary_Dir := False;
7930
 
7931
         --  Forbid  -?-  or  -??-  where ? is any character
7932
 
7933
         elsif (Argv'Length = 3 and then Argv (3) = '-')
7934
           or else (Argv'Length = 4 and then Argv (4) = '-')
7935
         then
7936
            Make_Failed
7937
              ("trailing ""-"" at the end of " & Argv & " forbidden.");
7938
 
7939
         --  -Idir
7940
 
7941
         elsif Argv (2) = 'I' then
7942
            Add_Source_Search_Dir  (Argv (3 .. Argv'Last), And_Save);
7943
            Add_Library_Search_Dir (Argv (3 .. Argv'Last), And_Save);
7944
            Add_Switch (Argv, Compiler, And_Save => And_Save);
7945
            Add_Switch (Argv, Binder,   And_Save => And_Save);
7946
 
7947
         --  -aIdir (to gcc this is like a -I switch)
7948
 
7949
         elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then
7950
            Add_Source_Search_Dir (Argv (4 .. Argv'Last), And_Save);
7951
            Add_Switch
7952
              ("-I" & Argv (4 .. Argv'Last), Compiler, And_Save => And_Save);
7953
            Add_Switch (Argv, Binder, And_Save => And_Save);
7954
 
7955
         --  -aOdir
7956
 
7957
         elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aO" then
7958
            Add_Library_Search_Dir (Argv (4 .. Argv'Last), And_Save);
7959
            Add_Switch (Argv, Binder, And_Save => And_Save);
7960
 
7961
         --  -aLdir (to gnatbind this is like a -aO switch)
7962
 
7963
         elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then
7964
            Mark_Directory (Argv (4 .. Argv'Last), Ada_Lib_Dir, And_Save);
7965
            Add_Library_Search_Dir (Argv (4 .. Argv'Last), And_Save);
7966
            Add_Switch
7967
              ("-aO" & Argv (4 .. Argv'Last), Binder, And_Save => And_Save);
7968
 
7969
         --  -aamp_target=...
7970
 
7971
         elsif Argv'Length >= 13 and then Argv (2 .. 13) = "aamp_target=" then
7972
            Add_Switch (Argv, Compiler, And_Save => And_Save);
7973
 
7974
            --  Set the aamp_target environment variable so that the binder and
7975
            --  linker will use the proper target library. This is consistent
7976
            --  with how things work when -aamp_target is passed on the command
7977
            --  line to gnaampmake.
7978
 
7979
            Setenv ("aamp_target", Argv (14 .. Argv'Last));
7980
 
7981
         --  -Adir (to gnatbind this is like a -aO switch, to gcc like a -I)
7982
 
7983
         elsif Argv (2) = 'A' then
7984
            Mark_Directory (Argv (3 .. Argv'Last), Ada_Lib_Dir, And_Save);
7985
            Add_Source_Search_Dir  (Argv (3 .. Argv'Last), And_Save);
7986
            Add_Library_Search_Dir (Argv (3 .. Argv'Last), And_Save);
7987
            Add_Switch
7988
              ("-I"  & Argv (3 .. Argv'Last), Compiler, And_Save => And_Save);
7989
            Add_Switch
7990
              ("-aO" & Argv (3 .. Argv'Last), Binder,   And_Save => And_Save);
7991
 
7992
         --  -Ldir
7993
 
7994
         elsif Argv (2) = 'L' then
7995
            Add_Switch (Argv, Linker, And_Save => And_Save);
7996
 
7997
         --  For -gxxxxx, -pg, -mxxx, -fxxx: give the switch to both the
7998
         --  compiler and the linker (except for -gnatxxx which is only for the
7999
         --  compiler). Some of the -mxxx (for example -m64) and -fxxx (for
8000
         --  example -ftest-coverage for gcov) need to be used when compiling
8001
         --  the binder generated files, and using all these gcc switches for
8002
         --  the binder generated files should not be a problem.
8003
 
8004
         elsif
8005
           (Argv (2) = 'g' and then (Argv'Last < 5
8006
                                       or else Argv (2 .. 5) /= "gnat"))
8007
             or else Argv (2 .. Argv'Last) = "pg"
8008
             or else (Argv (2) = 'm' and then Argv'Last > 2)
8009
             or else (Argv (2) = 'f' and then Argv'Last > 2)
8010
         then
8011
            Add_Switch (Argv, Compiler, And_Save => And_Save);
8012
            Add_Switch (Argv, Linker,   And_Save => And_Save);
8013
 
8014
            --  The following condition has to be kept synchronized with
8015
            --  the Process_Multilib one.
8016
 
8017
            if Argv (2) = 'm'
8018
              and then Argv /= "-mieee"
8019
            then
8020
               N_M_Switch := N_M_Switch + 1;
8021
            end if;
8022
 
8023
         --  -C=<mapping file>
8024
 
8025
         elsif Argv'Last > 2 and then Argv (2) = 'C' then
8026
            if And_Save then
8027
               if Argv (3) /= '=' or else Argv'Last <= 3 then
8028
                  Make_Failed ("illegal switch " & Argv);
8029
               end if;
8030
 
8031
               Gnatmake_Mapping_File := new String'(Argv (4 .. Argv'Last));
8032
            end if;
8033
 
8034
         --  -D
8035
 
8036
         elsif Argv'Last = 2 and then Argv (2) = 'D' then
8037
            if Project_File_Name /= null then
8038
               Make_Failed
8039
                 ("-D cannot be used in conjunction with a project file");
8040
 
8041
            else
8042
               Scan_Make_Switches (Project_Node_Tree, Argv, Success);
8043
            end if;
8044
 
8045
         --  -d
8046
 
8047
         elsif Argv (2) = 'd' and then Argv'Last = 2 then
8048
            Display_Compilation_Progress := True;
8049
 
8050
         --  -i
8051
 
8052
         elsif Argv'Last = 2 and then Argv (2) = 'i' then
8053
            if Project_File_Name /= null then
8054
               Make_Failed
8055
                 ("-i cannot be used in conjunction with a project file");
8056
            else
8057
               Scan_Make_Switches (Project_Node_Tree, Argv, Success);
8058
            end if;
8059
 
8060
         --  -j (need to save the result)
8061
 
8062
         elsif Argv (2) = 'j' then
8063
            Scan_Make_Switches (Project_Node_Tree, Argv, Success);
8064
 
8065
            if And_Save then
8066
               Saved_Maximum_Processes := Maximum_Processes;
8067
            end if;
8068
 
8069
         --  -m
8070
 
8071
         elsif Argv (2) = 'm' and then Argv'Last = 2 then
8072
            Minimal_Recompilation := True;
8073
 
8074
         --  -u
8075
 
8076
         elsif Argv (2) = 'u' and then Argv'Last = 2 then
8077
            Unique_Compile := True;
8078
            Compile_Only   := True;
8079
            Do_Bind_Step   := False;
8080
            Do_Link_Step   := False;
8081
 
8082
         --  -U
8083
 
8084
         elsif Argv (2) = 'U'
8085
           and then Argv'Last = 2
8086
         then
8087
            Unique_Compile_All_Projects := True;
8088
            Unique_Compile := True;
8089
            Compile_Only   := True;
8090
            Do_Bind_Step   := False;
8091
            Do_Link_Step   := False;
8092
 
8093
         --  -Pprj or -P prj (only once, and only on the command line)
8094
 
8095
         elsif Argv (2) = 'P' then
8096
            if Project_File_Name /= null then
8097
               Make_Failed ("cannot have several project files specified");
8098
 
8099
            elsif Object_Directory_Path /= null then
8100
               Make_Failed
8101
                 ("-D cannot be used in conjunction with a project file");
8102
 
8103
            elsif In_Place_Mode then
8104
               Make_Failed
8105
                 ("-i cannot be used in conjunction with a project file");
8106
 
8107
            elsif not And_Save then
8108
 
8109
               --  It could be a tool other than gnatmake (e.g. gnatdist)
8110
               --  or a -P switch inside a project file.
8111
 
8112
               Fail
8113
                 ("either the tool is not ""project-aware"" or " &
8114
                  "a project file is specified inside a project file");
8115
 
8116
            elsif Argv'Last = 2 then
8117
 
8118
               --  -P is used alone: the project file name is the next option
8119
 
8120
               Project_File_Name_Present := True;
8121
 
8122
            else
8123
               Project_File_Name := new String'(Argv (3 .. Argv'Last));
8124
            end if;
8125
 
8126
         --  -vPx  (verbosity of the parsing of the project files)
8127
 
8128
         elsif Argv'Last = 4
8129
           and then Argv (2 .. 3) = "vP"
8130
           and then Argv (4) in '0' .. '2'
8131
         then
8132
            if And_Save then
8133
               case Argv (4) is
8134
                  when '0' =>
8135
                     Current_Verbosity := Prj.Default;
8136
                  when '1' =>
8137
                     Current_Verbosity := Prj.Medium;
8138
                  when '2' =>
8139
                     Current_Verbosity := Prj.High;
8140
                  when others =>
8141
                     null;
8142
               end case;
8143
            end if;
8144
 
8145
         --  -Xext=val  (External assignment)
8146
 
8147
         elsif Argv (2) = 'X'
8148
           and then Is_External_Assignment (Project_Node_Tree, Argv)
8149
         then
8150
            --  Is_External_Assignment has side effects when it returns True
8151
 
8152
            null;
8153
 
8154
         --  If -gnath is present, then generate the usage information right
8155
         --  now and do not pass this option on to the compiler calls.
8156
 
8157
         elsif Argv = "-gnath" then
8158
            Usage;
8159
 
8160
         --  If -gnatc is specified, make sure the bind and link steps are not
8161
         --  executed.
8162
 
8163
         elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatc" then
8164
 
8165
            --  If -gnatc is specified, make sure the bind and link steps are
8166
            --  not executed.
8167
 
8168
            Add_Switch (Argv, Compiler, And_Save => And_Save);
8169
            Operating_Mode           := Check_Semantics;
8170
            Check_Object_Consistency := False;
8171
            Compile_Only             := True;
8172
            Do_Bind_Step             := False;
8173
            Do_Link_Step             := False;
8174
 
8175
         elsif Argv (2 .. Argv'Last) = "nostdlib" then
8176
 
8177
            --  Don't pass -nostdlib to gnatlink, it will disable
8178
            --  linking with all standard library files.
8179
 
8180
            No_Stdlib := True;
8181
 
8182
            Add_Switch (Argv, Compiler, And_Save => And_Save);
8183
            Add_Switch (Argv, Binder, And_Save => And_Save);
8184
 
8185
         elsif Argv (2 .. Argv'Last) = "nostdinc" then
8186
 
8187
            --  Pass -nostdinc to the Compiler and to gnatbind
8188
 
8189
            No_Stdinc := True;
8190
            Add_Switch (Argv, Compiler, And_Save => And_Save);
8191
            Add_Switch (Argv, Binder,   And_Save => And_Save);
8192
 
8193
         --  All other switches are processed by Scan_Make_Switches. If the
8194
         --  call returns with Gnatmake_Switch_Found = False, then the switch
8195
         --  is passed to the compiler.
8196
 
8197
         else
8198
            Scan_Make_Switches
8199
              (Project_Node_Tree, Argv, Gnatmake_Switch_Found);
8200
 
8201
            if not Gnatmake_Switch_Found then
8202
               Add_Switch (Argv, Compiler, And_Save => And_Save);
8203
            end if;
8204
         end if;
8205
 
8206
      --  If not a switch it must be a file name
8207
 
8208
      else
8209
         Add_File (Argv);
8210
         Mains.Add_Main (Argv);
8211
      end if;
8212
   end Scan_Make_Arg;
8213
 
8214
   -----------------
8215
   -- Switches_Of --
8216
   -----------------
8217
 
8218
   function Switches_Of
8219
     (Source_File      : File_Name_Type;
8220
      Source_File_Name : String;
8221
      Source_Index     : Int;
8222
      Project          : Project_Id;
8223
      In_Package       : Package_Id;
8224
      Allow_ALI        : Boolean) return Variable_Value
8225
   is
8226
      Lang : constant Language_Ptr := Get_Language_From_Name (Project, "ada");
8227
 
8228
      Switches : Variable_Value;
8229
 
8230
      Defaults : constant Array_Element_Id :=
8231
                   Prj.Util.Value_Of
8232
                     (Name      => Name_Default_Switches,
8233
                      In_Arrays =>
8234
                        Project_Tree.Packages.Table
8235
                          (In_Package).Decl.Arrays,
8236
                      In_Tree   => Project_Tree);
8237
 
8238
      Switches_Array : constant Array_Element_Id :=
8239
                         Prj.Util.Value_Of
8240
                           (Name      => Name_Switches,
8241
                            In_Arrays =>
8242
                              Project_Tree.Packages.Table
8243
                                (In_Package).Decl.Arrays,
8244
                            In_Tree   => Project_Tree);
8245
 
8246
   begin
8247
      --  First, try Switches (<file name>)
8248
 
8249
      Switches :=
8250
        Prj.Util.Value_Of
8251
          (Index     => Name_Id (Source_File),
8252
           Src_Index => Source_Index,
8253
           In_Array  => Switches_Array,
8254
           In_Tree   => Project_Tree);
8255
 
8256
      --  Check also without the suffix
8257
 
8258
      if Switches = Nil_Variable_Value
8259
        and then Lang /= null
8260
      then
8261
         declare
8262
            Naming      : Lang_Naming_Data renames Lang.Config.Naming_Data;
8263
            Name        : String (1 .. Source_File_Name'Length + 3);
8264
            Last        : Positive := Source_File_Name'Length;
8265
            Spec_Suffix : constant String :=
8266
                            Get_Name_String (Naming.Spec_Suffix);
8267
            Body_Suffix : constant String :=
8268
                            Get_Name_String (Naming.Body_Suffix);
8269
            Truncated   : Boolean := False;
8270
 
8271
         begin
8272
            Name (1 .. Last) := Source_File_Name;
8273
 
8274
            if Last > Body_Suffix'Length
8275
               and then Name (Last - Body_Suffix'Length + 1 .. Last) =
8276
                                                                  Body_Suffix
8277
            then
8278
               Truncated := True;
8279
               Last := Last - Body_Suffix'Length;
8280
            end if;
8281
 
8282
            if not Truncated
8283
              and then Last > Spec_Suffix'Length
8284
              and then Name (Last - Spec_Suffix'Length + 1 .. Last) =
8285
                                                                 Spec_Suffix
8286
            then
8287
               Truncated := True;
8288
               Last := Last - Spec_Suffix'Length;
8289
            end if;
8290
 
8291
            if Truncated then
8292
               Name_Len := 0;
8293
               Add_Str_To_Name_Buffer (Name (1 .. Last));
8294
               Switches :=
8295
                 Prj.Util.Value_Of
8296
                   (Index     => Name_Find,
8297
                    Src_Index => 0,
8298
                    In_Array  => Switches_Array,
8299
                    In_Tree   => Project_Tree);
8300
 
8301
               if Switches = Nil_Variable_Value and then Allow_ALI then
8302
                  Last := Source_File_Name'Length;
8303
 
8304
                  while Name (Last) /= '.' loop
8305
                     Last := Last - 1;
8306
                  end loop;
8307
 
8308
                  Name_Len := 0;
8309
                  Add_Str_To_Name_Buffer (Name (1 .. Last));
8310
                  Add_Str_To_Name_Buffer ("ali");
8311
 
8312
                  Switches :=
8313
                    Prj.Util.Value_Of
8314
                      (Index     => Name_Find,
8315
                       Src_Index => 0,
8316
                       In_Array  => Switches_Array,
8317
                       In_Tree   => Project_Tree);
8318
               end if;
8319
            end if;
8320
         end;
8321
      end if;
8322
 
8323
      --  Next, try Switches ("Ada")
8324
 
8325
      if Switches = Nil_Variable_Value then
8326
         Switches :=
8327
           Prj.Util.Value_Of
8328
             (Index                  => Name_Ada,
8329
              Src_Index              => 0,
8330
              In_Array               => Switches_Array,
8331
              In_Tree                => Project_Tree,
8332
              Force_Lower_Case_Index => True);
8333
 
8334
         if Switches /= Nil_Variable_Value then
8335
            Switch_May_Be_Passed_To_The_Compiler := False;
8336
         end if;
8337
      end if;
8338
 
8339
      --  Next, try Switches (others)
8340
 
8341
      if Switches = Nil_Variable_Value then
8342
         Switches :=
8343
           Prj.Util.Value_Of
8344
             (Index     => All_Other_Names,
8345
              Src_Index => 0,
8346
              In_Array  => Switches_Array,
8347
              In_Tree   => Project_Tree);
8348
 
8349
         if Switches /= Nil_Variable_Value then
8350
            Switch_May_Be_Passed_To_The_Compiler := False;
8351
         end if;
8352
      end if;
8353
 
8354
      --  And finally, Default_Switches ("Ada")
8355
 
8356
      if Switches = Nil_Variable_Value then
8357
         Switches :=
8358
           Prj.Util.Value_Of
8359
             (Index     => Name_Ada,
8360
              Src_Index => 0,
8361
              In_Array  => Defaults,
8362
              In_Tree   => Project_Tree);
8363
      end if;
8364
 
8365
      return Switches;
8366
   end Switches_Of;
8367
 
8368
   -----------
8369
   -- Usage --
8370
   -----------
8371
 
8372
   procedure Usage is
8373
   begin
8374
      if Usage_Needed then
8375
         Usage_Needed := False;
8376
         Makeusg;
8377
      end if;
8378
   end Usage;
8379
 
8380
begin
8381
   --  Make sure that in case of failure, the temp files will be deleted
8382
 
8383
   Prj.Com.Fail    := Make_Failed'Access;
8384
   MLib.Fail       := Make_Failed'Access;
8385
   Makeutl.Do_Fail := Make_Failed'Access;
8386
end Make;

powered by: WebSVN 2.1.0

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