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