OSDN Git Service

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