OSDN Git Service

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