OSDN Git Service

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