OSDN Git Service

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