OSDN Git Service

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