]>
Commit | Line | Data |
---|---|---|
84481f76 RK |
1 | ------------------------------------------------------------------------------ |
2 | -- -- | |
3 | -- GNAT COMPILER COMPONENTS -- | |
4 | -- -- | |
5 | -- M A K E -- | |
6 | -- -- | |
7 | -- B o d y -- | |
8 | -- -- | |
1d005acc | 9 | -- Copyright (C) 1992-2019, Free Software Foundation, Inc. -- |
84481f76 RK |
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- -- | |
b5c84c3c | 13 | -- ware Foundation; either version 3, or (at your option) any later ver- -- |
84481f76 RK |
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 -- | |
b5c84c3c RD |
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. -- | |
84481f76 RK |
20 | -- -- |
21 | -- GNAT was originally developed by the GNAT team at New York University. -- | |
71ff80dc | 22 | -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
84481f76 RK |
23 | -- -- |
24 | ------------------------------------------------------------------------------ | |
25 | ||
851e9f19 PMR |
26 | with ALI; use ALI; |
27 | with ALI.Util; use ALI.Util; | |
84481f76 RK |
28 | with Csets; |
29 | with Debug; | |
fbf5a39b | 30 | with Fmap; |
315f0c42 | 31 | with Fname; use Fname; |
851e9f19 | 32 | with Fname.SF; |
315f0c42 AC |
33 | with Fname.UF; use Fname.UF; |
34 | with Gnatvsn; use Gnatvsn; | |
35 | with Hostparm; use Hostparm; | |
84481f76 | 36 | with Makeusg; |
315f0c42 | 37 | with Make_Util; use Make_Util; |
851e9f19 PMR |
38 | with Namet; use Namet; |
39 | with Opt; use Opt; | |
40 | with Osint.M; use Osint.M; | |
41 | with Osint; use Osint; | |
42 | with Output; use Output; | |
84481f76 | 43 | with SFN_Scan; |
315f0c42 | 44 | with Sinput; |
851e9f19 | 45 | with Snames; |
308aab0b | 46 | with Stringt; |
daa72421 AC |
47 | |
48 | pragma Warnings (Off); | |
49 | with System.HTable; | |
50 | pragma Warnings (On); | |
51 | ||
07fc65c4 GB |
52 | with Switch; use Switch; |
53 | with Switch.M; use Switch.M; | |
d3cc6a32 | 54 | with Table; |
851e9f19 | 55 | with Targparm; |
fbf5a39b | 56 | with Tempdir; |
d3cc6a32 | 57 | with Types; use Types; |
84481f76 | 58 | |
a21d245c | 59 | with Ada.Command_Line; use Ada.Command_Line; |
0187b60e | 60 | with Ada.Directories; |
a21d245c | 61 | with Ada.Exceptions; use Ada.Exceptions; |
6c1e24d3 | 62 | |
bb012790 | 63 | with GNAT.Command_Line; use GNAT.Command_Line; |
6c1e24d3 | 64 | with GNAT.Directory_Operations; use GNAT.Directory_Operations; |
f86eb278 | 65 | with GNAT.OS_Lib; use GNAT.OS_Lib; |
6c1e24d3 | 66 | |
84481f76 RK |
67 | package body Make is |
68 | ||
69 | use ASCII; | |
70 | -- Make control characters visible | |
71 | ||
72 | Standard_Library_Package_Body_Name : constant String := "s-stalib.adb"; | |
2f8d7dfe AC |
73 | System_Package_Spec_Name : constant String := "system.ads"; |
74 | -- Every program depends on one of these packages: usually the first one, | |
75 | -- or if Supress_Standard_Library is true on the second one. The dependency | |
76 | -- is not always explicit and considering it is important when -f and -a | |
77 | -- are used. | |
84481f76 | 78 | |
fbf5a39b | 79 | type Sigint_Handler is access procedure; |
f5552c89 | 80 | pragma Convention (C, Sigint_Handler); |
fbf5a39b AC |
81 | |
82 | procedure Install_Int_Handler (Handler : Sigint_Handler); | |
83 | pragma Import (C, Install_Int_Handler, "__gnat_install_int_handler"); | |
84 | -- Called by Gnatmake to install the SIGINT handler below | |
85 | ||
86 | procedure Sigint_Intercepted; | |
f5552c89 | 87 | pragma Convention (C, Sigint_Intercepted); |
ae71d81b | 88 | pragma No_Return (Sigint_Intercepted); |
fbf5a39b AC |
89 | -- Called when the program is interrupted by Ctrl-C to delete the |
90 | -- temporary mapping files and configuration pragmas files. | |
91 | ||
15cf0748 VC |
92 | No_Mapping_File : constant Natural := 0; |
93 | ||
94 | type Compilation_Data is record | |
95 | Pid : Process_Id; | |
96 | Full_Source_File : File_Name_Type; | |
97 | Lib_File : File_Name_Type; | |
98 | Source_Unit : Unit_Name_Type; | |
48263c9a EB |
99 | Full_Lib_File : File_Name_Type; |
100 | Lib_File_Attr : aliased File_Attributes; | |
15cf0748 | 101 | Mapping_File : Natural := No_Mapping_File; |
15cf0748 VC |
102 | end record; |
103 | -- Data recorded for each compilation process spawned | |
104 | ||
48263c9a EB |
105 | No_Compilation_Data : constant Compilation_Data := |
106 | (Invalid_Pid, No_File, No_File, No_Unit_Name, No_File, Unknown_Attributes, | |
315f0c42 | 107 | No_Mapping_File); |
48263c9a | 108 | |
15cf0748 VC |
109 | type Comp_Data_Arr is array (Positive range <>) of Compilation_Data; |
110 | type Comp_Data_Ptr is access Comp_Data_Arr; | |
111 | Running_Compile : Comp_Data_Ptr; | |
112 | -- Used to save information about outstanding compilations | |
113 | ||
114 | Outstanding_Compiles : Natural := 0; | |
115 | -- Current number of outstanding compiles | |
116 | ||
315f0c42 AC |
117 | procedure Initialize; |
118 | ||
119 | Project_File_Name_Present : Boolean := False; | |
120 | ||
121 | Project_File_Name : String_Access := null; | |
122 | ||
84481f76 RK |
123 | ------------------------- |
124 | -- Note on terminology -- | |
125 | ------------------------- | |
126 | ||
64c69860 AC |
127 | -- In this program, we use the phrase "termination" of a file name to refer |
128 | -- to the suffix that appears after the unit name portion. Very often this | |
129 | -- is simply the extension, but in some cases, the sequence may be more | |
130 | -- complex, for example in main.1.ada, the termination in this name is | |
131 | -- ".1.ada" and in main_.ada the termination is "_.ada". | |
84481f76 | 132 | |
84481f76 | 133 | Unique_Compile : Boolean := False; |
315f0c42 | 134 | -- Set to True if -u or -U is used |
fbf5a39b | 135 | |
3e2399ba AC |
136 | Must_Compile : Boolean := False; |
137 | -- True if gnatmake is invoked with -f -u and one or several mains on the | |
138 | -- command line. | |
139 | ||
140 | Main_On_Command_Line : Boolean := False; | |
141 | -- True if gnatmake is invoked with one or several mains on the command | |
142 | -- line. | |
143 | ||
fbf5a39b AC |
144 | RTS_Specified : String_Access := null; |
145 | -- Used to detect multiple --RTS= switches | |
84481f76 | 146 | |
305418c8 LG |
147 | N_M_Switch : Natural := 0; |
148 | -- Used to count -mxxx switches that can affect multilib | |
149 | ||
d3cc6a32 AC |
150 | -- The 3 following packages are used to store gcc, gnatbind and gnatlink |
151 | -- switches found in the project files. | |
152 | ||
153 | package Gcc_Switches is new Table.Table ( | |
154 | Table_Component_Type => String_Access, | |
155 | Table_Index_Type => Integer, | |
156 | Table_Low_Bound => 1, | |
157 | Table_Initial => 20, | |
158 | Table_Increment => 100, | |
159 | Table_Name => "Make.Gcc_Switches"); | |
160 | ||
161 | package Binder_Switches is new Table.Table ( | |
162 | Table_Component_Type => String_Access, | |
163 | Table_Index_Type => Integer, | |
164 | Table_Low_Bound => 1, | |
165 | Table_Initial => 20, | |
166 | Table_Increment => 100, | |
167 | Table_Name => "Make.Binder_Switches"); | |
168 | ||
169 | package Linker_Switches is new Table.Table ( | |
170 | Table_Component_Type => String_Access, | |
171 | Table_Index_Type => Integer, | |
172 | Table_Low_Bound => 1, | |
173 | Table_Initial => 20, | |
174 | Table_Increment => 100, | |
175 | Table_Name => "Make.Linker_Switches"); | |
176 | ||
07fc65c4 GB |
177 | package Switches_To_Check is new Table.Table ( |
178 | Table_Component_Type => String_Access, | |
179 | Table_Index_Type => Integer, | |
180 | Table_Low_Bound => 1, | |
181 | Table_Initial => 20, | |
182 | Table_Increment => 100, | |
183 | Table_Name => "Make.Switches_To_Check"); | |
184 | ||
fbf5a39b AC |
185 | package Failed_Links is new Table.Table ( |
186 | Table_Component_Type => File_Name_Type, | |
187 | Table_Index_Type => Integer, | |
188 | Table_Low_Bound => 1, | |
189 | Table_Initial => 10, | |
190 | Table_Increment => 100, | |
191 | Table_Name => "Make.Failed_Links"); | |
192 | ||
193 | package Successful_Links is new Table.Table ( | |
194 | Table_Component_Type => File_Name_Type, | |
195 | Table_Index_Type => Integer, | |
196 | Table_Low_Bound => 1, | |
197 | Table_Initial => 10, | |
198 | Table_Increment => 100, | |
199 | Table_Name => "Make.Successful_Links"); | |
200 | ||
07fc65c4 GB |
201 | Normalized_Switches : Argument_List_Access := new Argument_List (1 .. 10); |
202 | Last_Norm_Switch : Natural := 0; | |
203 | ||
aa0df10b VC |
204 | Map_File : String_Access := null; |
205 | -- Value of switch --create-map-file | |
206 | ||
315f0c42 | 207 | procedure Add_Library_Search_Dir (Path : String); |
64c69860 | 208 | -- Call Add_Lib_Search_Dir with an absolute directory path. If Path is |
315f0c42 | 209 | -- relative path,, it is relative to the current working directory. |
a7ab2998 | 210 | |
315f0c42 | 211 | procedure Add_Source_Search_Dir (Path : String); |
a7ab2998 | 212 | -- Call Add_Src_Search_Dir with an absolute directory path. If Path is a |
315f0c42 | 213 | -- relative path, it is relative to the current working directory. |
81a5b587 | 214 | |
84481f76 RK |
215 | type Bad_Compilation_Info is record |
216 | File : File_Name_Type; | |
217 | Unit : Unit_Name_Type; | |
218 | Found : Boolean; | |
219 | end record; | |
a7ab2998 VC |
220 | -- File is the name of the file for which a compilation failed. Unit is for |
221 | -- gnatdist use in order to easily get the unit name of a file when its | |
222 | -- name is krunched or declared in gnat.adc. Found is False if the | |
223 | -- compilation failed because the file could not be found. | |
84481f76 RK |
224 | |
225 | package Bad_Compilation is new Table.Table ( | |
226 | Table_Component_Type => Bad_Compilation_Info, | |
227 | Table_Index_Type => Natural, | |
228 | Table_Low_Bound => 1, | |
229 | Table_Initial => 20, | |
230 | Table_Increment => 100, | |
231 | Table_Name => "Make.Bad_Compilation"); | |
44e1918a | 232 | -- Full name of all the source files for which compilation fails |
84481f76 | 233 | |
7ffa903f VC |
234 | Do_Compile_Step : Boolean := True; |
235 | Do_Bind_Step : Boolean := True; | |
236 | Do_Link_Step : Boolean := True; | |
64c69860 AC |
237 | -- Flags to indicate what step should be executed. Can be set to False |
238 | -- with the switches -c, -b and -l. These flags are reset to True for | |
dec55d76 | 239 | -- each invocation of procedure Gnatmake. |
7ffa903f | 240 | |
92966893 | 241 | CodePeer_Mode_String : aliased String := "-P"; |
fbf5a39b | 242 | |
9f4fd324 | 243 | No_Shared_Switch : aliased Argument_List := (1 .. 0 => null); |
9f4fd324 | 244 | Bind_Shared : Argument_List_Access := No_Shared_Switch'Access; |
fbf5a39b AC |
245 | -- Switch to added in front of gnatbind switches. By default no switch is |
246 | -- added. Switch "-shared" is added if there is a non-static Library | |
247 | -- Project File. | |
248 | ||
9bc43c53 AC |
249 | Shared_Libgcc : aliased String := "-shared-libgcc"; |
250 | ||
251 | No_Shared_Libgcc_Switch : aliased Argument_List := (1 .. 0 => null); | |
252 | Shared_Libgcc_Switch : aliased Argument_List := | |
253 | (1 => Shared_Libgcc'Access); | |
254 | Link_With_Shared_Libgcc : Argument_List_Access := | |
255 | No_Shared_Libgcc_Switch'Access; | |
256 | ||
3dd9959c | 257 | procedure Make_Failed (S : String); |
ae71d81b | 258 | pragma No_Return (Make_Failed); |
3dd9959c | 259 | -- Delete all temp files created by Gnatmake and call Osint.Fail, with the |
315f0c42 | 260 | -- parameter S (see osint.ads). |
fbf5a39b AC |
261 | |
262 | -------------------------- | |
263 | -- Obsolete Executables -- | |
264 | -------------------------- | |
265 | ||
266 | Executable_Obsolete : Boolean := False; | |
267 | -- Executable_Obsolete is initially set to False for each executable, | |
268 | -- and is set to True whenever one of the source of the executable is | |
269 | -- compiled, or has already been compiled for another executable. | |
270 | ||
9f4fd324 | 271 | Max_Header : constant := 200; |
2c1b72d7 AC |
272 | -- This needs a proper comment, it used to say "arbitrary" that's not an |
273 | -- adequate comment ??? | |
fbf5a39b AC |
274 | |
275 | type Header_Num is range 1 .. Max_Header; | |
276 | -- Header_Num for the hash table Obsoleted below | |
277 | ||
d3cc6a32 | 278 | function Hash (F : File_Name_Type) return Header_Num; |
fbf5a39b AC |
279 | -- Hash function for the hash table Obsoleted below |
280 | ||
281 | package Obsoleted is new System.HTable.Simple_HTable | |
282 | (Header_Num => Header_Num, | |
283 | Element => Boolean, | |
284 | No_Element => False, | |
d3cc6a32 | 285 | Key => File_Name_Type, |
fbf5a39b AC |
286 | Hash => Hash, |
287 | Equal => "="); | |
288 | -- A hash table to keep all files that have been compiled, to detect | |
289 | -- if an executable is up to date or not. | |
290 | ||
d3cc6a32 | 291 | procedure Enter_Into_Obsoleted (F : File_Name_Type); |
a7ab2998 | 292 | -- Enter a file name, without directory information, into the hash table |
fbf5a39b AC |
293 | -- Obsoleted. |
294 | ||
d3cc6a32 | 295 | function Is_In_Obsoleted (F : File_Name_Type) return Boolean; |
fbf5a39b AC |
296 | -- Check if a file name, without directory information, has already been |
297 | -- entered into the hash table Obsoleted. | |
298 | ||
299 | type Dependency is record | |
d3cc6a32 AC |
300 | This : File_Name_Type; |
301 | Depends_On : File_Name_Type; | |
fbf5a39b | 302 | end record; |
44e1918a | 303 | -- Components of table Dependencies below |
fbf5a39b AC |
304 | |
305 | package Dependencies is new Table.Table ( | |
306 | Table_Component_Type => Dependency, | |
307 | Table_Index_Type => Integer, | |
308 | Table_Low_Bound => 1, | |
309 | Table_Initial => 20, | |
310 | Table_Increment => 100, | |
311 | Table_Name => "Make.Dependencies"); | |
312 | -- A table to keep dependencies, to be able to decide if an executable | |
d3cc6a32 | 313 | -- is obsolete. More explanation needed ??? |
fbf5a39b AC |
314 | |
315 | ---------------------------- | |
316 | -- Arguments and Switches -- | |
317 | ---------------------------- | |
318 | ||
319 | Arguments : Argument_List_Access; | |
320 | -- Used to gather the arguments for invocation of the compiler | |
321 | ||
322 | Last_Argument : Natural := 0; | |
323 | -- Last index of arguments in Arguments above | |
324 | ||
fbf5a39b AC |
325 | Dummy_Switch : constant String_Access := new String'("- "); |
326 | -- Used to initialized Prev_Switch in procedure Check | |
327 | ||
328 | procedure Add_Arguments (Args : Argument_List); | |
329 | -- Add arguments to global variable Arguments, increasing its size | |
330 | -- if necessary and adjusting Last_Argument. | |
331 | ||
84481f76 RK |
332 | ------------------- |
333 | -- Misc Routines -- | |
334 | ------------------- | |
335 | ||
336 | procedure List_Depend; | |
337 | -- Prints to standard output the list of object dependencies. This list | |
338 | -- can be used directly in a Makefile. A call to Compile_Sources must | |
339 | -- precede the call to List_Depend. Also because this routine uses the | |
340 | -- ALI files that were originally loaded and scanned by Compile_Sources, | |
341 | -- no additional ALI files should be scanned between the two calls (i.e. | |
342 | -- between the call to Compile_Sources and List_Depend.) | |
343 | ||
84481f76 | 344 | procedure List_Bad_Compilations; |
44e1918a | 345 | -- Prints out the list of all files for which the compilation failed |
84481f76 | 346 | |
07fc65c4 GB |
347 | Usage_Needed : Boolean := True; |
348 | -- Flag used to make sure Makeusg is call at most once | |
349 | ||
350 | procedure Usage; | |
351 | -- Call Makeusg, if Usage_Needed is True. | |
352 | -- Set Usage_Needed to False. | |
353 | ||
fbf5a39b | 354 | procedure Debug_Msg (S : String; N : Name_Id); |
d3cc6a32 AC |
355 | procedure Debug_Msg (S : String; N : File_Name_Type); |
356 | procedure Debug_Msg (S : String; N : Unit_Name_Type); | |
44e1918a | 357 | -- If Debug.Debug_Flag_W is set outputs string S followed by name N |
fbf5a39b | 358 | |
84481f76 RK |
359 | ----------------------- |
360 | -- Gnatmake Routines -- | |
361 | ----------------------- | |
362 | ||
363 | subtype Lib_Mark_Type is Byte; | |
fbf5a39b | 364 | -- Used in Mark_Directory |
84481f76 | 365 | |
07fc65c4 | 366 | Ada_Lib_Dir : constant Lib_Mark_Type := 1; |
fbf5a39b | 367 | -- Used to mark a directory as a GNAT lib dir |
84481f76 | 368 | |
a7ab2998 VC |
369 | -- Note that the notion of GNAT lib dir is no longer used. The code related |
370 | -- to it has not been removed to give an idea on how to use the directory | |
371 | -- prefix marking mechanism. | |
84481f76 | 372 | |
a7ab2998 VC |
373 | -- An Ada library directory is a directory containing ali and object files |
374 | -- but no source files for the bodies (the specs can be in the same or some | |
375 | -- other directory). These directories are specified in the Gnatmake | |
376 | -- command line with the switch "-Adir" (to specify the spec location -Idir | |
377 | -- cab be used). Gnatmake skips the missing sources whose ali are in Ada | |
378 | -- library directories. For an explanation of why Gnatmake behaves that | |
379 | -- way, see the spec of Make.Compile_Sources. The directory lookup penalty | |
380 | -- is incurred every single time this routine is called. | |
84481f76 | 381 | |
d3cc6a32 | 382 | function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean; |
84481f76 RK |
383 | -- Get directory prefix of this file and get lib mark stored in name |
384 | -- table for this directory. Then check if an Ada lib mark has been set. | |
385 | ||
315f0c42 | 386 | procedure Mark_Directory (Dir : String; Mark : Lib_Mark_Type); |
a7ab2998 VC |
387 | -- Store the absolute path from Dir in name table and set lib mark as name |
388 | -- info to identify Ada libraries. | |
389 | -- | |
315f0c42 AC |
390 | -- If Dir is a relative path, it is relative to the current working |
391 | -- directory. | |
84481f76 | 392 | |
fbf5a39b AC |
393 | Output_Is_Object : Boolean := True; |
394 | -- Set to False when using a switch -S for the compiler | |
84481f76 | 395 | |
fbf5a39b AC |
396 | procedure Check_For_S_Switch; |
397 | -- Set Output_Is_Object to False when the -S switch is used for the | |
398 | -- compiler. | |
84481f76 | 399 | |
315f0c42 | 400 | procedure Process_Multilib; |
5568b57c | 401 | -- Add appropriate --RTS argument to handle multilib |
305418c8 | 402 | |
6367dd30 AC |
403 | procedure Compute_Executable |
404 | (Main_Source_File : File_Name_Type; | |
405 | Executable : out File_Name_Type; | |
406 | Non_Std_Executable : out Boolean); | |
407 | -- Parse the linker switches and project file to compute the name of the | |
408 | -- executable to generate. | |
409 | -- ??? What is the meaning of Non_Std_Executable | |
410 | ||
411 | procedure Compilation_Phase | |
412 | (Main_Source_File : File_Name_Type; | |
413 | Current_Main_Index : Int := 0; | |
414 | Total_Compilation_Failures : in out Natural; | |
6367dd30 | 415 | Executable : File_Name_Type := No_File; |
6367dd30 | 416 | Stop_Compile : out Boolean); |
5969611f RD |
417 | -- Build all source files for a given main file |
418 | -- | |
419 | -- Current_Main_Index, if not zero, is the index of the current main unit | |
420 | -- in its source file. | |
421 | -- | |
6367dd30 AC |
422 | -- Stand_Alone_Libraries is set to True when there are Stand-Alone |
423 | -- Libraries, so that gnatbind is invoked with the -F switch to force | |
424 | -- checking of elaboration flags. | |
5969611f | 425 | -- |
6367dd30 AC |
426 | -- Stop_Compile is set to true if we should not try to compile any more |
427 | -- of the main units | |
428 | ||
429 | procedure Binding_Phase | |
315f0c42 | 430 | (Main_ALI_File : File_Name_Type); |
6367dd30 AC |
431 | -- Stand_Alone_Libraries should be set to True when there are Stand-Alone |
432 | -- Libraries, so that gnatbind is invoked with the -F switch to force | |
433 | -- checking of elaboration flags. | |
434 | ||
6367dd30 AC |
435 | procedure Linking_Phase |
436 | (Non_Std_Executable : Boolean := False; | |
437 | Executable : File_Name_Type := No_File; | |
438 | Main_ALI_File : File_Name_Type); | |
5969611f RD |
439 | -- Perform the link of a single executable. The ali file corresponds |
440 | -- to Main_ALI_File. Executable is the file name of an executable. | |
6367dd30 AC |
441 | -- Non_Std_Executable is set to True when there is a possibility that |
442 | -- the linker will not choose the correct executable file name. | |
443 | ||
84481f76 RK |
444 | ---------------------------------------------------- |
445 | -- Compiler, Binder & Linker Data and Subprograms -- | |
446 | ---------------------------------------------------- | |
447 | ||
535a8637 | 448 | Gcc : String_Access := Program_Name ("gcc", "gnatmake"); |
015fbc5c RD |
449 | Gnatbind : String_Access := Program_Name ("gnatbind", "gnatmake"); |
450 | Gnatlink : String_Access := Program_Name ("gnatlink", "gnatmake"); | |
84481f76 RK |
451 | -- Default compiler, binder, linker programs |
452 | ||
015fbc5c | 453 | Gcc_Path : String_Access := |
2551782d | 454 | GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all); |
015fbc5c | 455 | Gnatbind_Path : String_Access := |
2551782d | 456 | GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all); |
015fbc5c | 457 | Gnatlink_Path : String_Access := |
2551782d | 458 | GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all); |
84481f76 RK |
459 | -- Path for compiler, binder, linker programs, defaulted now for gnatdist. |
460 | -- Changed later if overridden on command line. | |
461 | ||
462 | Comp_Flag : constant String_Access := new String'("-c"); | |
463 | Output_Flag : constant String_Access := new String'("-o"); | |
464 | Ada_Flag_1 : constant String_Access := new String'("-x"); | |
465 | Ada_Flag_2 : constant String_Access := new String'("ada"); | |
e8e581cd | 466 | AdaSCIL_Flag : constant String_Access := new String'("adascil"); |
84481f76 RK |
467 | GNAT_Flag : constant String_Access := new String'("-gnatpg"); |
468 | Do_Not_Check_Flag : constant String_Access := new String'("-x"); | |
469 | ||
64c69860 | 470 | Object_Suffix : constant String := Get_Target_Object_Suffix.all; |
84481f76 | 471 | |
07fc65c4 GB |
472 | Syntax_Only : Boolean := False; |
473 | -- Set to True when compiling with -gnats | |
474 | ||
84481f76 RK |
475 | Output_File_Name_Seen : Boolean := False; |
476 | -- Set to True after having scanned the file_name for | |
477 | -- switch "-o file_name" | |
478 | ||
fbf5a39b AC |
479 | Object_Directory_Seen : Boolean := False; |
480 | -- Set to True after having scanned the object directory for | |
481 | -- switch "-D obj_dir". | |
482 | ||
483 | Object_Directory_Path : String_Access := null; | |
44e1918a | 484 | -- The path name of the object directory, set with switch -D |
fbf5a39b | 485 | |
84481f76 RK |
486 | type Make_Program_Type is (None, Compiler, Binder, Linker); |
487 | ||
488 | Program_Args : Make_Program_Type := None; | |
a71742a8 | 489 | -- Used to indicate if we are scanning gnatmake, gcc, gnatbind, or gnatbind |
44e1918a AC |
490 | -- options within the gnatmake command line. Used in Scan_Make_Arg only, |
491 | -- but must be global since value preserved from one call to another. | |
84481f76 | 492 | |
84481f76 RK |
493 | procedure Add_Switch |
494 | (S : String_Access; | |
495 | Program : Make_Program_Type; | |
315f0c42 | 496 | Append_Switch : Boolean := True); |
84481f76 RK |
497 | procedure Add_Switch |
498 | (S : String; | |
499 | Program : Make_Program_Type; | |
315f0c42 | 500 | Append_Switch : Boolean := True); |
84481f76 RK |
501 | -- Make invokes one of three programs (the compiler, the binder or the |
502 | -- linker). For the sake of convenience, some program specific switches | |
dec55d76 RW |
503 | -- can be passed directly on the gnatmake command line. This procedure |
504 | -- records these switches so that gnatmake can pass them to the right | |
64ac53f4 | 505 | -- program. S is the switch to be added at the end of the command line |
84481f76 RK |
506 | -- for Program if Append_Switch is True. If Append_Switch is False S is |
507 | -- added at the beginning of the command line. | |
508 | ||
509 | procedure Check | |
f5552c89 | 510 | (Source_File : File_Name_Type; |
f5552c89 GD |
511 | The_Args : Argument_List; |
512 | Lib_File : File_Name_Type; | |
b11cb5fd | 513 | Full_Lib_File : File_Name_Type; |
48263c9a | 514 | Lib_File_Attr : access File_Attributes; |
f5552c89 GD |
515 | Read_Only : Boolean; |
516 | ALI : out ALI_Id; | |
517 | O_File : out File_Name_Type; | |
518 | O_Stamp : out Time_Stamp_Type); | |
84481f76 RK |
519 | -- Determines whether the library file Lib_File is up-to-date or not. The |
520 | -- full name (with path information) of the object file corresponding to | |
521 | -- Lib_File is returned in O_File. Its time stamp is saved in O_Stamp. | |
522 | -- ALI is the ALI_Id corresponding to Lib_File. If Lib_File in not | |
523 | -- up-to-date, then the corresponding source file needs to be recompiled. | |
524 | -- In this case ALI = No_ALI_Id. | |
b11cb5fd | 525 | -- Full_Lib_File must be the result of calling Osint.Full_Lib_File_Name on |
48263c9a EB |
526 | -- Lib_File. Precomputing it saves system calls. Lib_File_Attr is the |
527 | -- initialized attributes of that file, which is also used to save on | |
528 | -- system calls (it can safely be initialized to Unknown_Attributes). | |
84481f76 RK |
529 | |
530 | procedure Check_Linker_Options | |
531 | (E_Stamp : Time_Stamp_Type; | |
532 | O_File : out File_Name_Type; | |
533 | O_Stamp : out Time_Stamp_Type); | |
534 | -- Checks all linker options for linker files that are newer | |
535 | -- than E_Stamp. If such objects are found, the youngest object | |
536 | -- is returned in O_File and its stamp in O_Stamp. | |
537 | -- | |
538 | -- If no obsolete linker files were found, the first missing | |
539 | -- linker file is returned in O_File and O_Stamp is empty. | |
540 | -- Otherwise O_File is No_File. | |
541 | ||
315f0c42 AC |
542 | procedure Collect_Arguments (Args : Argument_List); |
543 | -- Collect all arguments for a source to be compiled. | |
fbf5a39b | 544 | |
84481f76 RK |
545 | procedure Display (Program : String; Args : Argument_List); |
546 | -- Displays Program followed by the arguments in Args if variable | |
547 | -- Display_Executed_Programs is set. The lower bound of Args must be 1. | |
548 | ||
d3cc6a32 | 549 | procedure Report_Compilation_Failed; |
ae71d81b | 550 | pragma No_Return (Report_Compilation_Failed); |
d3cc6a32 AC |
551 | -- Delete all temporary files and fail graciously |
552 | ||
fbf5a39b AC |
553 | ----------------- |
554 | -- Mapping files | |
555 | ----------------- | |
556 | ||
66713d62 | 557 | type Temp_Path_Names is array (Positive range <>) of Path_Name_Type; |
d3cc6a32 | 558 | type Temp_Path_Ptr is access Temp_Path_Names; |
07fc65c4 | 559 | |
3b42c566 RD |
560 | type Free_File_Indexes is array (Positive range <>) of Positive; |
561 | type Free_Indexes_Ptr is access Free_File_Indexes; | |
fbf5a39b | 562 | |
315f0c42 | 563 | type Mapping_File_Data is record |
66713d62 AC |
564 | Mapping_File_Names : Temp_Path_Ptr; |
565 | -- The name ids of the temporary mapping files used. This is indexed | |
566 | -- on the maximum number of compilation processes we will be spawning | |
567 | -- (-j parameter) | |
fbf5a39b | 568 | |
66713d62 AC |
569 | Last_Mapping_File_Names : Natural; |
570 | -- Index of the last mapping file created for this project | |
fbf5a39b | 571 | |
3b42c566 RD |
572 | Free_Mapping_File_Indexes : Free_Indexes_Ptr; |
573 | -- Indexes in Mapping_File_Names of the mapping file names that can be | |
66713d62 | 574 | -- reused for subsequent compilations. |
fbf5a39b | 575 | |
3b42c566 | 576 | Last_Free_Indexes : Natural; |
66713d62 AC |
577 | -- Number of mapping files that can be reused |
578 | end record; | |
579 | -- Information necessary when compiling a project | |
fbf5a39b | 580 | |
315f0c42 | 581 | The_Mapping_Files : Mapping_File_Data; |
fbf5a39b AC |
582 | |
583 | Gnatmake_Mapping_File : String_Access := null; | |
584 | -- The path name of a mapping file specified by switch -C= | |
07fc65c4 | 585 | |
ae71d81b | 586 | procedure Init_Mapping_File (File_Index : out Natural); |
315f0c42 AC |
587 | -- Create a new mapping file or reuse one already created. |
588 | ||
589 | package Temp_File_Paths is new Table.Table | |
590 | (Table_Component_Type => Path_Name_Type, | |
591 | Table_Index_Type => Natural, | |
592 | Table_Low_Bound => 1, | |
593 | Table_Initial => 4, | |
594 | Table_Increment => 100, | |
595 | Table_Name => "Make.Temp_File_Paths", | |
596 | Release_Threshold => 0); | |
597 | ||
598 | procedure Record_Temp_File (Path : Path_Name_Type); | |
599 | -- Record the path of a temporary file, so that it can be deleted at the | |
600 | -- end of execution of gnatmake. | |
601 | ||
602 | procedure Record_Temp_File (Path : Path_Name_Type) is | |
603 | begin | |
604 | for J in 1 .. Temp_File_Paths.Last loop | |
605 | if Temp_File_Paths.Table (J) = Path then | |
606 | return; | |
607 | end if; | |
608 | end loop; | |
609 | ||
610 | Temp_File_Paths.Append (Path); | |
611 | end Record_Temp_File; | |
fbf5a39b | 612 | |
d3cc6a32 AC |
613 | ------------------------------------------------- |
614 | -- Subprogram declarations moved from the spec -- | |
615 | ------------------------------------------------- | |
616 | ||
617 | procedure Bind (ALI_File : File_Name_Type; Args : Argument_List); | |
618 | -- Binds ALI_File. Args are the arguments to pass to the binder. | |
619 | -- Args must have a lower bound of 1. | |
620 | ||
d3cc6a32 AC |
621 | -- If a compilation, bind or link failed one of the following 3 exceptions |
622 | -- is raised. These need to be handled by the calling routines. | |
623 | ||
624 | procedure Compile_Sources | |
625 | (Main_Source : File_Name_Type; | |
626 | Args : Argument_List; | |
627 | First_Compiled_File : out File_Name_Type; | |
628 | Most_Recent_Obj_File : out File_Name_Type; | |
629 | Most_Recent_Obj_Stamp : out Time_Stamp_Type; | |
630 | Main_Unit : out Boolean; | |
631 | Compilation_Failures : out Natural; | |
632 | Main_Index : Int := 0; | |
633 | Check_Readonly_Files : Boolean := False; | |
634 | Do_Not_Execute : Boolean := False; | |
635 | Force_Compilations : Boolean := False; | |
636 | Keep_Going : Boolean := False; | |
637 | In_Place_Mode : Boolean := False; | |
638 | Initialize_ALI_Data : Boolean := True; | |
639 | Max_Process : Positive := 1); | |
640 | -- Compile_Sources will recursively compile all the sources needed by | |
641 | -- Main_Source. Before calling this routine make sure Namet has been | |
642 | -- initialized. This routine can be called repeatedly with different | |
643 | -- Main_Source file as long as all the source (-I flags), library | |
644 | -- (-B flags) and ada library (-A flags) search paths between calls are | |
645 | -- *exactly* the same. The default directory must also be the same. | |
646 | -- | |
647 | -- Args contains the arguments to use during the compilations. | |
648 | -- The lower bound of Args must be 1. | |
649 | -- | |
650 | -- First_Compiled_File is set to the name of the first file that is | |
651 | -- compiled or that needs to be compiled. This is set to No_Name if no | |
652 | -- compilations were needed. | |
653 | -- | |
654 | -- Most_Recent_Obj_File is set to the full name of the most recent | |
655 | -- object file found when no compilations are needed, that is when | |
656 | -- First_Compiled_File is set to No_Name. When First_Compiled_File | |
657 | -- is set then Most_Recent_Obj_File is set to No_Name. | |
658 | -- | |
659 | -- Most_Recent_Obj_Stamp is the time stamp of Most_Recent_Obj_File. | |
660 | -- | |
661 | -- Main_Unit is set to True if Main_Source can be a main unit. | |
662 | -- If Do_Not_Execute is False and First_Compiled_File /= No_Name | |
663 | -- the value of Main_Unit is always False. | |
664 | -- Is this used any more??? It is certainly not used by gnatmake??? | |
665 | -- | |
666 | -- Compilation_Failures is a count of compilation failures. This count | |
667 | -- is used to extract compilation failure reports with Extract_Failure. | |
668 | -- | |
669 | -- Main_Index, when not zero, is the index of the main unit in source | |
670 | -- file Main_Source which is a multi-unit source. | |
671 | -- Zero indicates that Main_Source is a single unit source file. | |
672 | -- | |
673 | -- Check_Readonly_Files set it to True to compile source files | |
674 | -- which library files are read-only. When compiling GNAT predefined | |
675 | -- files the "-gnatg" flag is used. | |
676 | -- | |
677 | -- Do_Not_Execute set it to True to find out the first source that | |
678 | -- needs to be recompiled, but without recompiling it. This file is | |
679 | -- saved in First_Compiled_File. | |
680 | -- | |
681 | -- Force_Compilations forces all compilations no matter what but | |
682 | -- recompiles read-only files only if Check_Readonly_Files | |
683 | -- is set. | |
684 | -- | |
685 | -- Keep_Going when True keep compiling even in the presence of | |
686 | -- compilation errors. | |
687 | -- | |
688 | -- In_Place_Mode when True save library/object files in their object | |
689 | -- directory if they already exist; otherwise, in the source directory. | |
690 | -- | |
691 | -- Initialize_ALI_Data set it to True when you want to initialize ALI | |
692 | -- data-structures. This is what you should do most of the time. | |
693 | -- (especially the first time around when you call this routine). | |
694 | -- This parameter is set to False to preserve previously recorded | |
695 | -- ALI file data. | |
696 | -- | |
697 | -- Max_Process is the maximum number of processes that should be spawned | |
698 | -- to carry out compilations. | |
699 | -- | |
700 | -- Flags in Package Opt Affecting Compile_Sources | |
701 | -- ----------------------------------------------- | |
702 | -- | |
703 | -- Check_Object_Consistency set it to False to omit all consistency | |
704 | -- checks between an .ali file and its corresponding object file. | |
705 | -- When this flag is set to true, every time an .ali is read, | |
706 | -- package Osint checks that the corresponding object file | |
707 | -- exists and is more recent than the .ali. | |
708 | -- | |
709 | -- Use of Name Table Info | |
710 | -- ---------------------- | |
711 | -- | |
712 | -- All file names manipulated by Compile_Sources are entered into the | |
713 | -- Names table. The Byte field of a source file is used to mark it. | |
714 | -- | |
715 | -- Calling Compile_Sources Several Times | |
716 | -- ------------------------------------- | |
717 | -- | |
718 | -- Upon return from Compile_Sources all the ALI data structures are left | |
719 | -- intact for further browsing. HOWEVER upon entry to this routine ALI | |
720 | -- data structures are re-initialized if parameter Initialize_ALI_Data | |
721 | -- above is set to true. Typically this is what you want the first time | |
722 | -- you call Compile_Sources. You should not load an ali file, call this | |
723 | -- routine with flag Initialize_ALI_Data set to True and then expect | |
724 | -- that ALI information to be around after the call. Note that the first | |
725 | -- time you call Compile_Sources you better set Initialize_ALI_Data to | |
726 | -- True unless you have called Initialize_ALI yourself. | |
727 | -- | |
728 | -- Compile_Sources ALGORITHM : Compile_Sources (Main_Source) | |
729 | -- ------------------------- | |
730 | -- | |
731 | -- 1. Insert Main_Source in a Queue (Q) and mark it. | |
732 | -- | |
733 | -- 2. Let unit.adb be the file at the head of the Q. If unit.adb is | |
734 | -- missing but its corresponding ali file is in an Ada library directory | |
735 | -- (see below) then, remove unit.adb from the Q and goto step 4. | |
736 | -- Otherwise, look at the files under the D (dependency) section of | |
737 | -- unit.ali. If unit.ali does not exist or some of the time stamps do | |
738 | -- not match, (re)compile unit.adb. | |
739 | -- | |
740 | -- An Ada library directory is a directory containing Ada specs, ali | |
741 | -- and object files but no source files for the bodies. An Ada library | |
742 | -- directory is communicated to gnatmake by means of some switch so that | |
743 | -- gnatmake can skip the sources whole ali are in that directory. | |
744 | -- There are two reasons for skipping the sources in this case. Firstly, | |
745 | -- Ada libraries typically come without full sources but binding and | |
746 | -- linking against those libraries is still possible. Secondly, it would | |
747 | -- be very wasteful for gnatmake to systematically check the consistency | |
748 | -- of every external Ada library used in a program. The binder is | |
749 | -- already in charge of catching any potential inconsistencies. | |
750 | -- | |
751 | -- 3. Look into the W section of unit.ali and insert into the Q all | |
752 | -- unmarked source files. Mark all files newly inserted in the Q. | |
753 | -- Specifically, assuming that the W section looks like | |
754 | -- | |
755 | -- W types%s types.adb types.ali | |
756 | -- W unchecked_deallocation%s | |
757 | -- W xref_tab%s xref_tab.adb xref_tab.ali | |
758 | -- | |
759 | -- Then xref_tab.adb and types.adb are inserted in the Q if they are not | |
760 | -- already marked. | |
761 | -- Note that there is no file listed under W unchecked_deallocation%s | |
762 | -- so no generic body should ever be explicitly compiled (unless the | |
763 | -- Main_Source at the start was a generic body). | |
764 | -- | |
765 | -- 4. Repeat steps 2 and 3 above until the Q is empty | |
766 | -- | |
767 | -- Note that the above algorithm works because the units withed in | |
768 | -- subunits are transitively included in the W section (with section) of | |
769 | -- the main unit. Likewise the withed units in a generic body needed | |
770 | -- during a compilation are also transitively included in the W section | |
771 | -- of the originally compiled file. | |
772 | ||
d3cc6a32 AC |
773 | procedure Link |
774 | (ALI_File : File_Name_Type; | |
775 | Args : Argument_List; | |
776 | Success : out Boolean); | |
777 | -- Links ALI_File. Args are the arguments to pass to the linker. | |
778 | -- Args must have a lower bound of 1. Success indicates if the link | |
779 | -- succeeded or not. | |
780 | ||
315f0c42 AC |
781 | Gnatmake_Switch_Found : Boolean := False; |
782 | ||
783 | procedure Scan_Make_Arg (Argv : String); | |
daa72421 | 784 | -- Scan make arguments. Argv is a single argument to be processed. |
d3cc6a32 | 785 | |
fbf5a39b AC |
786 | ------------------- |
787 | -- Add_Arguments -- | |
788 | ------------------- | |
789 | ||
790 | procedure Add_Arguments (Args : Argument_List) is | |
791 | begin | |
792 | if Arguments = null then | |
793 | Arguments := new Argument_List (1 .. Args'Length + 10); | |
794 | ||
795 | else | |
796 | while Last_Argument + Args'Length > Arguments'Last loop | |
797 | declare | |
6b6fcd3e AC |
798 | New_Arguments : constant Argument_List_Access := |
799 | new Argument_List (1 .. Arguments'Last * 2); | |
fbf5a39b AC |
800 | begin |
801 | New_Arguments (1 .. Last_Argument) := | |
802 | Arguments (1 .. Last_Argument); | |
803 | Arguments := New_Arguments; | |
804 | end; | |
805 | end loop; | |
806 | end if; | |
807 | ||
808 | Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args; | |
809 | Last_Argument := Last_Argument + Args'Length; | |
810 | end Add_Arguments; | |
811 | ||
a7ab2998 VC |
812 | ---------------------------- |
813 | -- Add_Library_Search_Dir -- | |
814 | ---------------------------- | |
815 | ||
315f0c42 | 816 | procedure Add_Library_Search_Dir (Path : String) is |
a7ab2998 | 817 | begin |
315f0c42 | 818 | Add_Lib_Search_Dir (Normalize_Pathname (Path)); |
a7ab2998 VC |
819 | end Add_Library_Search_Dir; |
820 | ||
a7ab2998 VC |
821 | --------------------------- |
822 | -- Add_Source_Search_Dir -- | |
823 | --------------------------- | |
824 | ||
315f0c42 | 825 | procedure Add_Source_Search_Dir (Path : String) is |
a7ab2998 | 826 | begin |
315f0c42 | 827 | Add_Src_Search_Dir (Normalize_Pathname (Path)); |
a7ab2998 VC |
828 | end Add_Source_Search_Dir; |
829 | ||
84481f76 RK |
830 | ---------------- |
831 | -- Add_Switch -- | |
832 | ---------------- | |
833 | ||
834 | procedure Add_Switch | |
835 | (S : String_Access; | |
836 | Program : Make_Program_Type; | |
315f0c42 | 837 | Append_Switch : Boolean := True) |
84481f76 RK |
838 | is |
839 | generic | |
840 | with package T is new Table.Table (<>); | |
7bc7d27b FW |
841 | procedure Generic_Position (New_Position : out Integer); |
842 | -- Generic procedure that chooses a position for S in T at the | |
843 | -- beginning or the end, depending on the boolean Append_Switch. | |
fbf5a39b | 844 | -- Calling this procedure may expand the table. |
84481f76 RK |
845 | |
846 | ---------------------- | |
847 | -- Generic_Position -- | |
848 | ---------------------- | |
849 | ||
a7ab2998 | 850 | procedure Generic_Position (New_Position : out Integer) is |
84481f76 RK |
851 | begin |
852 | T.Increment_Last; | |
853 | ||
854 | if Append_Switch then | |
7bc7d27b | 855 | New_Position := Integer (T.Last); |
84481f76 RK |
856 | else |
857 | for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop | |
858 | T.Table (J) := T.Table (T.Table_Index_Type'Pred (J)); | |
859 | end loop; | |
860 | ||
7bc7d27b | 861 | New_Position := Integer (T.First); |
84481f76 RK |
862 | end if; |
863 | end Generic_Position; | |
864 | ||
7bc7d27b FW |
865 | procedure Gcc_Switches_Pos is new Generic_Position (Gcc_Switches); |
866 | procedure Binder_Switches_Pos is new Generic_Position (Binder_Switches); | |
867 | procedure Linker_Switches_Pos is new Generic_Position (Linker_Switches); | |
84481f76 | 868 | |
7bc7d27b FW |
869 | New_Position : Integer; |
870 | ||
84481f76 RK |
871 | -- Start of processing for Add_Switch |
872 | ||
873 | begin | |
315f0c42 AC |
874 | case Program is |
875 | when Compiler => | |
876 | Gcc_Switches_Pos (New_Position); | |
877 | Gcc_Switches.Table (New_Position) := S; | |
878 | ||
879 | when Binder => | |
880 | Binder_Switches_Pos (New_Position); | |
881 | Binder_Switches.Table (New_Position) := S; | |
882 | ||
883 | when Linker => | |
884 | Linker_Switches_Pos (New_Position); | |
885 | Linker_Switches.Table (New_Position) := S; | |
886 | ||
887 | when None => | |
888 | raise Program_Error; | |
889 | end case; | |
84481f76 RK |
890 | end Add_Switch; |
891 | ||
892 | procedure Add_Switch | |
893 | (S : String; | |
894 | Program : Make_Program_Type; | |
315f0c42 | 895 | Append_Switch : Boolean := True) |
84481f76 RK |
896 | is |
897 | begin | |
898 | Add_Switch (S => new String'(S), | |
899 | Program => Program, | |
315f0c42 | 900 | Append_Switch => Append_Switch); |
84481f76 RK |
901 | end Add_Switch; |
902 | ||
84481f76 RK |
903 | ---------- |
904 | -- Bind -- | |
905 | ---------- | |
906 | ||
907 | procedure Bind (ALI_File : File_Name_Type; Args : Argument_List) is | |
908 | Bind_Args : Argument_List (1 .. Args'Last + 2); | |
909 | Bind_Last : Integer; | |
910 | Success : Boolean; | |
911 | ||
912 | begin | |
913 | pragma Assert (Args'First = 1); | |
914 | ||
915 | -- Optimize the simple case where the gnatbind command line looks like | |
2d395256 AC |
916 | -- gnatbind -aO. -I- file.ali |
917 | -- into | |
918 | -- gnatbind file.adb | |
84481f76 RK |
919 | |
920 | if Args'Length = 2 | |
921 | and then Args (Args'First).all = "-aO" & Normalized_CWD | |
922 | and then Args (Args'Last).all = "-I-" | |
923 | and then ALI_File = Strip_Directory (ALI_File) | |
924 | then | |
925 | Bind_Last := Args'First - 1; | |
926 | ||
927 | else | |
928 | Bind_Last := Args'Last; | |
929 | Bind_Args (Args'Range) := Args; | |
930 | end if; | |
931 | ||
a7ab2998 VC |
932 | -- It is completely pointless to re-check source file time stamps. This |
933 | -- has been done already by gnatmake | |
84481f76 RK |
934 | |
935 | Bind_Last := Bind_Last + 1; | |
936 | Bind_Args (Bind_Last) := Do_Not_Check_Flag; | |
937 | ||
938 | Get_Name_String (ALI_File); | |
939 | ||
940 | Bind_Last := Bind_Last + 1; | |
941 | Bind_Args (Bind_Last) := new String'(Name_Buffer (1 .. Name_Len)); | |
942 | ||
f86eb278 | 943 | GNAT.OS_Lib.Normalize_Arguments (Bind_Args (Args'First .. Bind_Last)); |
07fc65c4 | 944 | |
84481f76 RK |
945 | Display (Gnatbind.all, Bind_Args (Args'First .. Bind_Last)); |
946 | ||
947 | if Gnatbind_Path = null then | |
3dd9959c | 948 | Make_Failed ("error, unable to locate " & Gnatbind.all); |
84481f76 RK |
949 | end if; |
950 | ||
f86eb278 | 951 | GNAT.OS_Lib.Spawn |
84481f76 RK |
952 | (Gnatbind_Path.all, Bind_Args (Args'First .. Bind_Last), Success); |
953 | ||
954 | if not Success then | |
d3cc6a32 | 955 | Make_Failed ("*** bind failed."); |
84481f76 RK |
956 | end if; |
957 | end Bind; | |
958 | ||
959 | ----------- | |
960 | -- Check -- | |
961 | ----------- | |
962 | ||
963 | procedure Check | |
f5552c89 | 964 | (Source_File : File_Name_Type; |
f5552c89 GD |
965 | The_Args : Argument_List; |
966 | Lib_File : File_Name_Type; | |
b11cb5fd | 967 | Full_Lib_File : File_Name_Type; |
48263c9a | 968 | Lib_File_Attr : access File_Attributes; |
f5552c89 GD |
969 | Read_Only : Boolean; |
970 | ALI : out ALI_Id; | |
971 | O_File : out File_Name_Type; | |
972 | O_Stamp : out Time_Stamp_Type) | |
84481f76 RK |
973 | is |
974 | function First_New_Spec (A : ALI_Id) return File_Name_Type; | |
975 | -- Looks in the with table entries of A and returns the spec file name | |
976 | -- of the first withed unit (subprogram) for which no spec existed when | |
977 | -- A was generated but for which there exists one now, implying that A | |
978 | -- is now obsolete. If no such unit is found No_File is returned. | |
979 | -- Otherwise the spec file name of the unit is returned. | |
980 | -- | |
981 | -- **WARNING** in the event of Uname format modifications, one *MUST* | |
982 | -- make sure this function is also updated. | |
983 | -- | |
984 | -- Note: This function should really be in ali.adb and use Uname | |
985 | -- services, but this causes the whole compiler to be dragged along | |
986 | -- for gnatbind and gnatmake. | |
987 | ||
988 | -------------------- | |
989 | -- First_New_Spec -- | |
990 | -------------------- | |
991 | ||
992 | function First_New_Spec (A : ALI_Id) return File_Name_Type is | |
993 | Spec_File_Name : File_Name_Type := No_File; | |
994 | ||
995 | function New_Spec (Uname : Unit_Name_Type) return Boolean; | |
a7ab2998 VC |
996 | -- Uname is the name of the spec or body of some ada unit. This |
997 | -- function returns True if the Uname is the name of a body which has | |
d3cc6a32 | 998 | -- a spec not mentioned in ALI file A. If True is returned |
84481f76 RK |
999 | -- Spec_File_Name above is set to the name of this spec file. |
1000 | ||
1001 | -------------- | |
1002 | -- New_Spec -- | |
1003 | -------------- | |
1004 | ||
1005 | function New_Spec (Uname : Unit_Name_Type) return Boolean is | |
1006 | Spec_Name : Unit_Name_Type; | |
1007 | File_Name : File_Name_Type; | |
1008 | ||
1009 | begin | |
dec55d76 | 1010 | -- Test whether Uname is the name of a body unit (i.e. ends |
2d395256 | 1011 | -- with %b). |
84481f76 RK |
1012 | |
1013 | Get_Name_String (Uname); | |
1014 | pragma | |
1015 | Assert (Name_Len > 2 and then Name_Buffer (Name_Len - 1) = '%'); | |
1016 | ||
1017 | if Name_Buffer (Name_Len) /= 'b' then | |
1018 | return False; | |
1019 | end if; | |
1020 | ||
1021 | -- Convert unit name into spec name | |
1022 | ||
1023 | -- ??? this code seems dubious in presence of pragma | |
1024 | -- Source_File_Name since there is no more direct relationship | |
1025 | -- between unit name and file name. | |
1026 | ||
1027 | -- ??? Further, what about alternative subunit naming | |
1028 | ||
1029 | Name_Buffer (Name_Len) := 's'; | |
1030 | Spec_Name := Name_Find; | |
1031 | File_Name := Get_File_Name (Spec_Name, Subunit => False); | |
1032 | ||
1033 | -- Look if File_Name is mentioned in A's sdep list. | |
1034 | -- If not look if the file exists. If it does return True. | |
1035 | ||
1036 | for D in | |
1037 | ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep | |
1038 | loop | |
1039 | if Sdep.Table (D).Sfile = File_Name then | |
1040 | return False; | |
1041 | end if; | |
1042 | end loop; | |
1043 | ||
1044 | if Full_Source_Name (File_Name) /= No_File then | |
1045 | Spec_File_Name := File_Name; | |
1046 | return True; | |
1047 | end if; | |
1048 | ||
1049 | return False; | |
1050 | end New_Spec; | |
1051 | ||
1052 | -- Start of processing for First_New_Spec | |
1053 | ||
1054 | begin | |
1055 | U_Chk : for U in | |
1056 | ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit | |
1057 | loop | |
1058 | exit U_Chk when Units.Table (U).Utype = Is_Body_Only | |
1059 | and then New_Spec (Units.Table (U).Uname); | |
1060 | ||
1061 | for W in Units.Table (U).First_With | |
1062 | .. | |
1063 | Units.Table (U).Last_With | |
1064 | loop | |
1065 | exit U_Chk when | |
1066 | Withs.Table (W).Afile /= No_File | |
1067 | and then New_Spec (Withs.Table (W).Uname); | |
1068 | end loop; | |
1069 | end loop U_Chk; | |
1070 | ||
1071 | return Spec_File_Name; | |
1072 | end First_New_Spec; | |
1073 | ||
1074 | --------------------------------- | |
1075 | -- Data declarations for Check -- | |
1076 | --------------------------------- | |
1077 | ||
79503fdd | 1078 | Full_Obj_File : File_Name_Type; |
44e1918a | 1079 | -- Full name of the object file corresponding to Lib_File |
84481f76 | 1080 | |
79503fdd | 1081 | Lib_Stamp : Time_Stamp_Type; |
44e1918a | 1082 | -- Time stamp of the current ada library file |
84481f76 | 1083 | |
79503fdd | 1084 | Obj_Stamp : Time_Stamp_Type; |
44e1918a | 1085 | -- Time stamp of the current object file |
84481f76 | 1086 | |
79503fdd | 1087 | Modified_Source : File_Name_Type; |
2d395256 AC |
1088 | -- The first source in Lib_File whose current time stamp differs from |
1089 | -- that stored in Lib_File. | |
84481f76 | 1090 | |
79503fdd | 1091 | New_Spec : File_Name_Type; |
84481f76 | 1092 | -- If Lib_File contains in its W (with) section a body (for a |
2d395256 | 1093 | -- subprogram) for which there exists a spec, and the spec did not |
84481f76 RK |
1094 | -- appear in the Sdep section of Lib_File, New_Spec contains the file |
1095 | -- name of this new spec. | |
1096 | ||
d3cc6a32 | 1097 | Source_Name : File_Name_Type; |
79503fdd | 1098 | Text : Text_Buffer_Ptr; |
84481f76 | 1099 | |
47b79f78 AC |
1100 | First_Arg : Arg_Id; |
1101 | -- Index of the first argument in Args.Table for a given unit | |
1102 | ||
1103 | Last_Arg : Arg_Id; | |
1104 | -- Index of the last argument in Args.Table for a given unit | |
84481f76 RK |
1105 | |
1106 | Arg : Arg_Id := Arg_Id'First; | |
1107 | -- Current index in Args.Table for a given unit (init to stop warning) | |
1108 | ||
47b79f78 AC |
1109 | Number_Of_Switches : Natural; |
1110 | -- Number of switches recorded for a given unit | |
1111 | ||
1112 | Prev_Switch : String_Access; | |
1113 | -- Previous switch processed | |
1114 | ||
84481f76 RK |
1115 | Switch_Found : Boolean; |
1116 | -- True if a given switch has been found | |
1117 | ||
84481f76 RK |
1118 | begin |
1119 | pragma Assert (Lib_File /= No_File); | |
1120 | ||
a7ab2998 VC |
1121 | -- If ALI file is read-only, temporarily set Check_Object_Consistency to |
1122 | -- False. We don't care if the object file is not there (presumably a | |
1123 | -- library will be used for linking.) | |
fbf5a39b AC |
1124 | |
1125 | if Read_Only then | |
1126 | declare | |
1127 | Saved_Check_Object_Consistency : constant Boolean := | |
b7e429ab | 1128 | Check_Object_Consistency; |
fbf5a39b | 1129 | begin |
b7e429ab | 1130 | Check_Object_Consistency := False; |
48263c9a | 1131 | Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr); |
b7e429ab | 1132 | Check_Object_Consistency := Saved_Check_Object_Consistency; |
fbf5a39b AC |
1133 | end; |
1134 | ||
1135 | else | |
48263c9a | 1136 | Text := Read_Library_Info_From_Full (Full_Lib_File, Lib_File_Attr); |
fbf5a39b AC |
1137 | end if; |
1138 | ||
84481f76 RK |
1139 | Full_Obj_File := Full_Object_File_Name; |
1140 | Lib_Stamp := Current_Library_File_Stamp; | |
1141 | Obj_Stamp := Current_Object_File_Stamp; | |
1142 | ||
1143 | if Full_Lib_File = No_File then | |
a7ab2998 VC |
1144 | Verbose_Msg |
1145 | (Lib_File, | |
1146 | "being checked ...", | |
1147 | Prefix => " ", | |
1148 | Minimum_Verbosity => Opt.Medium); | |
84481f76 | 1149 | else |
a7ab2998 VC |
1150 | Verbose_Msg |
1151 | (Full_Lib_File, | |
1152 | "being checked ...", | |
1153 | Prefix => " ", | |
1154 | Minimum_Verbosity => Opt.Medium); | |
84481f76 RK |
1155 | end if; |
1156 | ||
1157 | ALI := No_ALI_Id; | |
1158 | O_File := Full_Obj_File; | |
1159 | O_Stamp := Obj_Stamp; | |
1160 | ||
1161 | if Text = null then | |
1162 | if Full_Lib_File = No_File then | |
1163 | Verbose_Msg (Lib_File, "missing."); | |
1164 | ||
1165 | elsif Obj_Stamp (Obj_Stamp'First) = ' ' then | |
1166 | Verbose_Msg (Full_Obj_File, "missing."); | |
1167 | ||
1168 | else | |
1169 | Verbose_Msg | |
1170 | (Full_Lib_File, "(" & String (Lib_Stamp) & ") newer than", | |
1171 | Full_Obj_File, "(" & String (Obj_Stamp) & ")"); | |
1172 | end if; | |
1173 | ||
1174 | else | |
1175 | ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True); | |
1176 | Free (Text); | |
1177 | ||
1178 | if ALI = No_ALI_Id then | |
1179 | Verbose_Msg (Full_Lib_File, "incorrectly formatted ALI file"); | |
1180 | return; | |
1181 | ||
1182 | elsif ALIs.Table (ALI).Ver (1 .. ALIs.Table (ALI).Ver_Len) /= | |
efdfd311 | 1183 | Verbose_Library_Version |
84481f76 RK |
1184 | then |
1185 | Verbose_Msg (Full_Lib_File, "compiled with old GNAT version"); | |
1186 | ALI := No_ALI_Id; | |
1187 | return; | |
1188 | end if; | |
1189 | ||
2d395256 | 1190 | -- Don't take ALI file into account if it was generated with errors |
fbf5a39b AC |
1191 | |
1192 | if ALIs.Table (ALI).Compile_Errors then | |
1193 | Verbose_Msg (Full_Lib_File, "had errors, must be recompiled"); | |
1194 | ALI := No_ALI_Id; | |
1195 | return; | |
1196 | end if; | |
1197 | ||
2d395256 | 1198 | -- Don't take ALI file into account if no object was generated |
84481f76 | 1199 | |
b7e429ab | 1200 | if Operating_Mode /= Check_Semantics |
84481f76 RK |
1201 | and then ALIs.Table (ALI).No_Object |
1202 | then | |
1203 | Verbose_Msg (Full_Lib_File, "has no corresponding object"); | |
1204 | ALI := No_ALI_Id; | |
1205 | return; | |
1206 | end if; | |
1207 | ||
98ee5fc4 AC |
1208 | -- When compiling with -gnatc, don't take ALI file into account if |
1209 | -- it has not been generated for the current source, for example if | |
1210 | -- it has been generated for the spec, but we are compiling the body. | |
1211 | ||
1212 | if Operating_Mode = Check_Semantics then | |
1213 | declare | |
4fdebd93 | 1214 | File_Name : String := Get_Name_String (Source_File); |
98ee5fc4 AC |
1215 | OK : Boolean := False; |
1216 | ||
1217 | begin | |
46414266 VC |
1218 | -- In the ALI file, the source file names are in canonical case |
1219 | ||
1220 | Canonical_Case_File_Name (File_Name); | |
1221 | ||
98ee5fc4 AC |
1222 | for U in ALIs.Table (ALI).First_Unit .. |
1223 | ALIs.Table (ALI).Last_Unit | |
1224 | loop | |
1225 | OK := Get_Name_String (Units.Table (U).Sfile) = File_Name; | |
1226 | exit when OK; | |
1227 | end loop; | |
1228 | ||
1229 | if not OK then | |
1230 | Verbose_Msg | |
1231 | (Full_Lib_File, "not generated for the same source"); | |
1232 | ALI := No_ALI_Id; | |
1233 | return; | |
1234 | end if; | |
1235 | end; | |
1236 | end if; | |
1237 | ||
84481f76 RK |
1238 | -- Check for matching compiler switches if needed |
1239 | ||
b7e429ab | 1240 | if Check_Switches then |
fbf5a39b AC |
1241 | |
1242 | -- First, collect all the switches | |
1243 | ||
315f0c42 | 1244 | Collect_Arguments (The_Args); |
fbf5a39b | 1245 | Prev_Switch := Dummy_Switch; |
84481f76 | 1246 | Get_Name_String (ALIs.Table (ALI).Sfile); |
07fc65c4 GB |
1247 | Switches_To_Check.Set_Last (0); |
1248 | ||
fbf5a39b | 1249 | for J in 1 .. Last_Argument loop |
07fc65c4 | 1250 | |
47b79f78 | 1251 | -- Skip -c, -I and -o switches |
07fc65c4 | 1252 | |
fbf5a39b AC |
1253 | if Arguments (J) (1) = '-' |
1254 | and then Arguments (J) (2) /= 'c' | |
1255 | and then Arguments (J) (2) /= 'o' | |
1256 | and then Arguments (J) (2) /= 'I' | |
84481f76 | 1257 | then |
07fc65c4 | 1258 | Normalize_Compiler_Switches |
fbf5a39b | 1259 | (Arguments (J).all, |
07fc65c4 GB |
1260 | Normalized_Switches, |
1261 | Last_Norm_Switch); | |
1262 | ||
1263 | for K in 1 .. Last_Norm_Switch loop | |
1264 | Switches_To_Check.Increment_Last; | |
1265 | Switches_To_Check.Table (Switches_To_Check.Last) := | |
1266 | Normalized_Switches (K); | |
1267 | end loop; | |
84481f76 RK |
1268 | end if; |
1269 | end loop; | |
1270 | ||
47b79f78 AC |
1271 | First_Arg := Units.Table (ALIs.Table (ALI).First_Unit).First_Arg; |
1272 | Last_Arg := Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg; | |
1273 | ||
07fc65c4 | 1274 | for J in 1 .. Switches_To_Check.Last loop |
84481f76 | 1275 | |
a7ab2998 VC |
1276 | -- Comparing switches is delicate because gcc reorders a number |
1277 | -- of switches, according to lang-specs.h, but gnatmake doesn't | |
64c69860 AC |
1278 | -- have sufficient knowledge to perform the same reordering. |
1279 | -- Instead, we ignore orders between different "first letter" | |
1280 | -- switches, but keep orders between same switches, e.g -O -O2 | |
1281 | -- is different than -O2 -O, but -g -O is equivalent to -O -g. | |
84481f76 | 1282 | |
fbf5a39b AC |
1283 | if Switches_To_Check.Table (J) (2) /= Prev_Switch (2) or else |
1284 | (Prev_Switch'Length >= 6 and then | |
1285 | Prev_Switch (2 .. 5) = "gnat" and then | |
1286 | Switches_To_Check.Table (J)'Length >= 6 and then | |
1287 | Switches_To_Check.Table (J) (2 .. 5) = "gnat" and then | |
1288 | Prev_Switch (6) /= Switches_To_Check.Table (J) (6)) | |
1289 | then | |
1290 | Prev_Switch := Switches_To_Check.Table (J); | |
47b79f78 | 1291 | Arg := First_Arg; |
07fc65c4 | 1292 | end if; |
84481f76 | 1293 | |
07fc65c4 | 1294 | Switch_Found := False; |
84481f76 | 1295 | |
47b79f78 | 1296 | for K in Arg .. Last_Arg loop |
07fc65c4 GB |
1297 | if |
1298 | Switches_To_Check.Table (J).all = Args.Table (K).all | |
1299 | then | |
1300 | Arg := K + 1; | |
1301 | Switch_Found := True; | |
1302 | exit; | |
84481f76 RK |
1303 | end if; |
1304 | end loop; | |
1305 | ||
07fc65c4 | 1306 | if not Switch_Found then |
b7e429ab | 1307 | if Verbose_Mode then |
07fc65c4 | 1308 | Verbose_Msg (ALIs.Table (ALI).Sfile, |
fbf5a39b AC |
1309 | "switch mismatch """ & |
1310 | Switches_To_Check.Table (J).all & '"'); | |
84481f76 | 1311 | end if; |
07fc65c4 GB |
1312 | |
1313 | ALI := No_ALI_Id; | |
1314 | return; | |
1315 | end if; | |
1316 | end loop; | |
84481f76 | 1317 | |
47b79f78 AC |
1318 | Number_Of_Switches := Natural (Last_Arg - First_Arg + 1); |
1319 | ||
1320 | -- Do not count the multilib switches reinstated by the compiler | |
1321 | -- according to the lang-specs.h.settings. | |
1322 | ||
1323 | for K in First_Arg .. Last_Arg loop | |
0ab0bf95 | 1324 | if Args.Table (K).all = "-mrtp" then |
47b79f78 AC |
1325 | Number_Of_Switches := Number_Of_Switches - 1; |
1326 | end if; | |
1327 | end loop; | |
1328 | ||
1329 | if Switches_To_Check.Last /= Number_Of_Switches then | |
b7e429ab | 1330 | if Verbose_Mode then |
84481f76 | 1331 | Verbose_Msg (ALIs.Table (ALI).Sfile, |
fbf5a39b AC |
1332 | "different number of switches"); |
1333 | ||
47b79f78 | 1334 | for K in First_Arg .. Last_Arg loop |
fbf5a39b AC |
1335 | Write_Str (Args.Table (K).all); |
1336 | Write_Char (' '); | |
1337 | end loop; | |
1338 | ||
1339 | Write_Eol; | |
1340 | ||
1341 | for J in 1 .. Switches_To_Check.Last loop | |
1342 | Write_Str (Switches_To_Check.Table (J).all); | |
1343 | Write_Char (' '); | |
1344 | end loop; | |
1345 | ||
1346 | Write_Eol; | |
84481f76 RK |
1347 | end if; |
1348 | ||
1349 | ALI := No_ALI_Id; | |
1350 | return; | |
1351 | end if; | |
1352 | end if; | |
1353 | ||
fbf5a39b | 1354 | -- Get the source files and their message digests. Note that some |
84481f76 RK |
1355 | -- sources may be missing if ALI is out-of-date. |
1356 | ||
1357 | Set_Source_Table (ALI); | |
1358 | ||
fbf5a39b | 1359 | Modified_Source := Time_Stamp_Mismatch (ALI, Read_Only); |
84481f76 | 1360 | |
6f76a257 AC |
1361 | -- To avoid using too much memory when switch -m is used, free the |
1362 | -- memory allocated for the source file when computing the checksum. | |
1363 | ||
1364 | if Minimal_Recompilation then | |
315f0c42 | 1365 | Sinput.Clear_Source_File_Table; |
6f76a257 AC |
1366 | end if; |
1367 | ||
84481f76 RK |
1368 | if Modified_Source /= No_File then |
1369 | ALI := No_ALI_Id; | |
1370 | ||
b7e429ab | 1371 | if Verbose_Mode then |
84481f76 RK |
1372 | Source_Name := Full_Source_Name (Modified_Source); |
1373 | ||
1374 | if Source_Name /= No_File then | |
1375 | Verbose_Msg (Source_Name, "time stamp mismatch"); | |
1376 | else | |
1377 | Verbose_Msg (Modified_Source, "missing"); | |
1378 | end if; | |
1379 | end if; | |
1380 | ||
1381 | else | |
1382 | New_Spec := First_New_Spec (ALI); | |
1383 | ||
1384 | if New_Spec /= No_File then | |
1385 | ALI := No_ALI_Id; | |
1386 | ||
b7e429ab | 1387 | if Verbose_Mode then |
84481f76 RK |
1388 | Source_Name := Full_Source_Name (New_Spec); |
1389 | ||
1390 | if Source_Name /= No_File then | |
1391 | Verbose_Msg (Source_Name, "new spec"); | |
1392 | else | |
1393 | Verbose_Msg (New_Spec, "old spec missing"); | |
1394 | end if; | |
1395 | end if; | |
f86eb278 | 1396 | |
84481f76 RK |
1397 | end if; |
1398 | end if; | |
1399 | end if; | |
1400 | end Check; | |
1401 | ||
fbf5a39b AC |
1402 | ------------------------ |
1403 | -- Check_For_S_Switch -- | |
1404 | ------------------------ | |
1405 | ||
1406 | procedure Check_For_S_Switch is | |
1407 | begin | |
1408 | -- By default, we generate an object file | |
1409 | ||
1410 | Output_Is_Object := True; | |
1411 | ||
1412 | for Arg in 1 .. Last_Argument loop | |
1413 | if Arguments (Arg).all = "-S" then | |
1414 | Output_Is_Object := False; | |
1415 | ||
1416 | elsif Arguments (Arg).all = "-c" then | |
1417 | Output_Is_Object := True; | |
1418 | end if; | |
1419 | end loop; | |
1420 | end Check_For_S_Switch; | |
1421 | ||
84481f76 RK |
1422 | -------------------------- |
1423 | -- Check_Linker_Options -- | |
1424 | -------------------------- | |
1425 | ||
1426 | procedure Check_Linker_Options | |
61770974 HK |
1427 | (E_Stamp : Time_Stamp_Type; |
1428 | O_File : out File_Name_Type; | |
1429 | O_Stamp : out Time_Stamp_Type) | |
84481f76 RK |
1430 | is |
1431 | procedure Check_File (File : File_Name_Type); | |
1432 | -- Update O_File and O_Stamp if the given file is younger than E_Stamp | |
1433 | -- and O_Stamp, or if O_File is No_File and File does not exist. | |
1434 | ||
1435 | function Get_Library_File (Name : String) return File_Name_Type; | |
1436 | -- Return the full file name including path of a library based | |
1437 | -- on the name specified with the -l linker option, using the | |
1438 | -- Ada object path. Return No_File if no such file can be found. | |
1439 | ||
1440 | type Char_Array is array (Natural) of Character; | |
1441 | type Char_Array_Access is access constant Char_Array; | |
1442 | ||
1443 | Template : Char_Array_Access; | |
1444 | pragma Import (C, Template, "__gnat_library_template"); | |
1445 | ||
1446 | ---------------- | |
1447 | -- Check_File -- | |
1448 | ---------------- | |
1449 | ||
1450 | procedure Check_File (File : File_Name_Type) is | |
1451 | Stamp : Time_Stamp_Type; | |
1452 | Name : File_Name_Type := File; | |
1453 | ||
1454 | begin | |
1455 | Get_Name_String (Name); | |
1456 | ||
1457 | -- Remove any trailing NUL characters | |
1458 | ||
1459 | while Name_Len >= Name_Buffer'First | |
1460 | and then Name_Buffer (Name_Len) = NUL | |
1461 | loop | |
1462 | Name_Len := Name_Len - 1; | |
1463 | end loop; | |
1464 | ||
a7ab2998 | 1465 | if Name_Len = 0 then |
84481f76 RK |
1466 | return; |
1467 | ||
07fc65c4 GB |
1468 | elsif Name_Buffer (1) = '-' then |
1469 | ||
84481f76 RK |
1470 | -- Do not check if File is a switch other than "-l" |
1471 | ||
1472 | if Name_Buffer (2) /= 'l' then | |
1473 | return; | |
1474 | end if; | |
1475 | ||
1476 | -- The argument is a library switch, get actual name. It | |
1477 | -- is necessary to make a copy of the relevant part of | |
1478 | -- Name_Buffer as Get_Library_Name uses Name_Buffer as well. | |
1479 | ||
1480 | declare | |
1481 | Base_Name : constant String := Name_Buffer (3 .. Name_Len); | |
1482 | ||
1483 | begin | |
1484 | Name := Get_Library_File (Base_Name); | |
1485 | end; | |
1486 | ||
1487 | if Name = No_File then | |
1488 | return; | |
1489 | end if; | |
1490 | end if; | |
1491 | ||
1492 | Stamp := File_Stamp (Name); | |
1493 | ||
1494 | -- Find the youngest object file that is younger than the | |
1495 | -- executable. If no such file exist, record the first object | |
1496 | -- file that is not found. | |
1497 | ||
1498 | if (O_Stamp < Stamp and then E_Stamp < Stamp) | |
1499 | or else (O_File = No_File and then Stamp (Stamp'First) = ' ') | |
1500 | then | |
1501 | O_Stamp := Stamp; | |
1502 | O_File := Name; | |
1503 | ||
1504 | -- Strip the trailing NUL if present | |
1505 | ||
1506 | Get_Name_String (O_File); | |
1507 | ||
1508 | if Name_Buffer (Name_Len) = NUL then | |
1509 | Name_Len := Name_Len - 1; | |
1510 | O_File := Name_Find; | |
1511 | end if; | |
1512 | end if; | |
1513 | end Check_File; | |
1514 | ||
1515 | ---------------------- | |
1516 | -- Get_Library_Name -- | |
1517 | ---------------------- | |
1518 | ||
1519 | -- See comments in a-adaint.c about template syntax | |
1520 | ||
1521 | function Get_Library_File (Name : String) return File_Name_Type is | |
1522 | File : File_Name_Type := No_File; | |
1523 | ||
1524 | begin | |
1525 | Name_Len := 0; | |
1526 | ||
1527 | for Ptr in Template'Range loop | |
1528 | case Template (Ptr) is | |
d8f43ee6 | 1529 | when '*' => |
84481f76 RK |
1530 | Add_Str_To_Name_Buffer (Name); |
1531 | ||
d8f43ee6 | 1532 | when ';' => |
84481f76 RK |
1533 | File := Full_Lib_File_Name (Name_Find); |
1534 | exit when File /= No_File; | |
1535 | Name_Len := 0; | |
1536 | ||
d8f43ee6 | 1537 | when NUL => |
84481f76 RK |
1538 | exit; |
1539 | ||
1540 | when others => | |
1541 | Add_Char_To_Name_Buffer (Template (Ptr)); | |
1542 | end case; | |
1543 | end loop; | |
1544 | ||
1545 | -- The for loop exited because the end of the template | |
1546 | -- was reached. File contains the last possible file name | |
1547 | -- for the library. | |
1548 | ||
1549 | if File = No_File and then Name_Len > 0 then | |
1550 | File := Full_Lib_File_Name (Name_Find); | |
1551 | end if; | |
1552 | ||
1553 | return File; | |
1554 | end Get_Library_File; | |
1555 | ||
1556 | -- Start of processing for Check_Linker_Options | |
1557 | ||
1558 | begin | |
1559 | O_File := No_File; | |
1560 | O_Stamp := (others => ' '); | |
1561 | ||
44e1918a | 1562 | -- Process linker options from the ALI files |
84481f76 RK |
1563 | |
1564 | for Opt in 1 .. Linker_Options.Last loop | |
d3cc6a32 | 1565 | Check_File (File_Name_Type (Linker_Options.Table (Opt).Name)); |
84481f76 RK |
1566 | end loop; |
1567 | ||
44e1918a | 1568 | -- Process options given on the command line |
84481f76 RK |
1569 | |
1570 | for Opt in Linker_Switches.First .. Linker_Switches.Last loop | |
1571 | ||
1572 | -- Check if the previous Opt has one of the two switches | |
1573 | -- that take an extra parameter. (See GCC manual.) | |
1574 | ||
1575 | if Opt = Linker_Switches.First | |
1576 | or else (Linker_Switches.Table (Opt - 1).all /= "-u" | |
1577 | and then | |
fbf5a39b AC |
1578 | Linker_Switches.Table (Opt - 1).all /= "-Xlinker" |
1579 | and then | |
1580 | Linker_Switches.Table (Opt - 1).all /= "-L") | |
84481f76 RK |
1581 | then |
1582 | Name_Len := 0; | |
1583 | Add_Str_To_Name_Buffer (Linker_Switches.Table (Opt).all); | |
1584 | Check_File (Name_Find); | |
1585 | end if; | |
1586 | end loop; | |
84481f76 RK |
1587 | end Check_Linker_Options; |
1588 | ||
fbf5a39b AC |
1589 | ----------------------- |
1590 | -- Collect_Arguments -- | |
1591 | ----------------------- | |
84481f76 | 1592 | |
315f0c42 | 1593 | procedure Collect_Arguments (Args : Argument_List) is |
fbf5a39b | 1594 | begin |
fbf5a39b AC |
1595 | Last_Argument := 0; |
1596 | Add_Arguments (Args); | |
84481f76 | 1597 | |
315f0c42 AC |
1598 | -- Set Output_Is_Object, depending if there is a -S switch. |
1599 | -- If the bind step is not performed, and there is a -S switch, | |
1600 | -- then we will not check for a valid object file. | |
84481f76 | 1601 | |
315f0c42 AC |
1602 | Check_For_S_Switch; |
1603 | end Collect_Arguments; | |
84481f76 | 1604 | |
315f0c42 AC |
1605 | --------------------- |
1606 | -- Compile_Sources -- | |
1607 | --------------------- | |
fbf5a39b AC |
1608 | |
1609 | procedure Compile_Sources | |
1610 | (Main_Source : File_Name_Type; | |
1611 | Args : Argument_List; | |
d3cc6a32 AC |
1612 | First_Compiled_File : out File_Name_Type; |
1613 | Most_Recent_Obj_File : out File_Name_Type; | |
fbf5a39b AC |
1614 | Most_Recent_Obj_Stamp : out Time_Stamp_Type; |
1615 | Main_Unit : out Boolean; | |
1616 | Compilation_Failures : out Natural; | |
aa720a54 | 1617 | Main_Index : Int := 0; |
fbf5a39b AC |
1618 | Check_Readonly_Files : Boolean := False; |
1619 | Do_Not_Execute : Boolean := False; | |
1620 | Force_Compilations : Boolean := False; | |
1621 | Keep_Going : Boolean := False; | |
1622 | In_Place_Mode : Boolean := False; | |
1623 | Initialize_ALI_Data : Boolean := True; | |
1624 | Max_Process : Positive := 1) | |
1625 | is | |
48263c9a EB |
1626 | Mfile : Natural := No_Mapping_File; |
1627 | Mapping_File_Arg : String_Access; | |
1628 | -- Info on the mapping file | |
84481f76 | 1629 | |
fbf5a39b | 1630 | Need_To_Check_Standard_Library : Boolean := |
5b599df4 | 1631 | (Check_Readonly_Files or Must_Compile) |
cd5a9750 | 1632 | and not Unique_Compile; |
84481f76 RK |
1633 | |
1634 | procedure Add_Process | |
48263c9a EB |
1635 | (Pid : Process_Id; |
1636 | Sfile : File_Name_Type; | |
1637 | Afile : File_Name_Type; | |
1638 | Uname : Unit_Name_Type; | |
1639 | Full_Lib_File : File_Name_Type; | |
1640 | Lib_File_Attr : File_Attributes; | |
1641 | Mfile : Natural := No_Mapping_File); | |
84481f76 RK |
1642 | -- Adds process Pid to the current list of outstanding compilation |
1643 | -- processes and record the full name of the source file Sfile that | |
1644 | -- we are compiling, the name of its library file Afile and the | |
fbf5a39b AC |
1645 | -- name of its unit Uname. If Mfile is not equal to No_Mapping_File, |
1646 | -- it is the index of the mapping file used during compilation in the | |
1647 | -- array The_Mapping_File_Names. | |
84481f76 RK |
1648 | |
1649 | procedure Await_Compile | |
48263c9a | 1650 | (Data : out Compilation_Data; |
84481f76 | 1651 | OK : out Boolean); |
d56e7acd AC |
1652 | -- Awaits that an outstanding compilation process terminates. When it |
1653 | -- does set Data to the information registered for the corresponding | |
1654 | -- call to Add_Process. Note that this time stamp can be used to check | |
1655 | -- whether the compilation did generate an object file. OK is set to | |
1656 | -- True if the compilation succeeded. Data could be No_Compilation_Data | |
1657 | -- if there was no compilation to wait for. | |
84481f76 | 1658 | |
aa720a54 | 1659 | function Bad_Compilation_Count return Natural; |
44e1918a | 1660 | -- Returns the number of compilation failures |
aa720a54 | 1661 | |
0da2c8ac AC |
1662 | procedure Check_Standard_Library; |
1663 | -- Check if s-stalib.adb needs to be compiled | |
1664 | ||
48263c9a EB |
1665 | procedure Collect_Arguments_And_Compile |
1666 | (Full_Source_File : File_Name_Type; | |
1667 | Lib_File : File_Name_Type; | |
1668 | Source_Index : Int; | |
1669 | Pid : out Process_Id; | |
1670 | Process_Created : out Boolean); | |
d56e7acd AC |
1671 | -- Collect arguments from project file (if any) and compile. If no |
1672 | -- compilation was attempted, Processed_Created is set to False, and the | |
1673 | -- value of Pid is unknown. | |
84481f76 | 1674 | |
aa720a54 | 1675 | function Compile |
315f0c42 | 1676 | (S : File_Name_Type; |
d3cc6a32 | 1677 | L : File_Name_Type; |
aa720a54 AC |
1678 | Source_Index : Int; |
1679 | Args : Argument_List) return Process_Id; | |
d3cc6a32 AC |
1680 | -- Compiles S using Args. If S is a GNAT predefined source "-gnatpg" is |
1681 | -- added to Args. Non blocking call. L corresponds to the expected | |
1682 | -- library file name. Process_Id of the process spawned to execute the | |
1683 | -- compilation. | |
aa720a54 | 1684 | |
84481f76 | 1685 | package Good_ALI is new Table.Table ( |
315f0c42 | 1686 | Table_Component_Type => ALI_Id, |
84481f76 RK |
1687 | Table_Index_Type => Natural, |
1688 | Table_Low_Bound => 1, | |
1689 | Table_Initial => 50, | |
1690 | Table_Increment => 100, | |
1691 | Table_Name => "Make.Good_ALI"); | |
44e1918a | 1692 | -- Contains the set of valid ALI files that have not yet been scanned |
84481f76 | 1693 | |
84481f76 | 1694 | function Good_ALI_Present return Boolean; |
44e1918a | 1695 | -- Returns True if any ALI file was recorded in the previous set |
84481f76 | 1696 | |
315f0c42 | 1697 | procedure Get_Mapping_File; |
aa720a54 AC |
1698 | -- Get a mapping file name. If there is one to be reused, reuse it. |
1699 | -- Otherwise, create a new mapping file. | |
1700 | ||
315f0c42 | 1701 | function Get_Next_Good_ALI return ALI_Id; |
44e1918a | 1702 | -- Returns the next good ALI_Id record |
84481f76 RK |
1703 | |
1704 | procedure Record_Failure | |
1705 | (File : File_Name_Type; | |
1706 | Unit : Unit_Name_Type; | |
1707 | Found : Boolean := True); | |
1708 | -- Records in the previous table that the compilation for File failed. | |
1709 | -- If Found is False then the compilation of File failed because we | |
1710 | -- could not find it. Records also Unit when possible. | |
1711 | ||
315f0c42 | 1712 | procedure Record_Good_ALI (A : ALI_Id); |
44e1918a | 1713 | -- Records in the previous set the Id of an ALI file |
07fc65c4 | 1714 | |
48263c9a EB |
1715 | function Must_Exit_Because_Of_Error return Boolean; |
1716 | -- Return True if there were errors and the user decided to exit in such | |
1717 | -- a case. This waits for any outstanding compilation. | |
1718 | ||
1719 | function Start_Compile_If_Possible (Args : Argument_List) return Boolean; | |
1720 | -- Check if there is more work that we can do (i.e. the Queue is non | |
1721 | -- empty). If there is, do it only if we have not yet used up all the | |
1722 | -- available processes. | |
1723 | -- Returns True if we should exit the main loop | |
1724 | ||
1725 | procedure Wait_For_Available_Slot; | |
1726 | -- Check if we should wait for a compilation to finish. This is the case | |
1727 | -- if all the available processes are busy compiling sources or there is | |
1728 | -- nothing else to do (that is the Q is empty and there are no good ALIs | |
1729 | -- to process). | |
1730 | ||
1731 | procedure Fill_Queue_From_ALI_Files; | |
1732 | -- Check if we recorded good ALI files. If yes process them now in the | |
1733 | -- order in which they have been recorded. There are two occasions in | |
1734 | -- which we record good ali files. The first is in phase 1 when, after | |
1735 | -- scanning an existing ALI file we realize it is up-to-date, the second | |
1736 | -- instance is after a successful compilation. | |
1737 | ||
84481f76 RK |
1738 | ----------------- |
1739 | -- Add_Process -- | |
1740 | ----------------- | |
1741 | ||
1742 | procedure Add_Process | |
48263c9a EB |
1743 | (Pid : Process_Id; |
1744 | Sfile : File_Name_Type; | |
1745 | Afile : File_Name_Type; | |
1746 | Uname : Unit_Name_Type; | |
1747 | Full_Lib_File : File_Name_Type; | |
1748 | Lib_File_Attr : File_Attributes; | |
1749 | Mfile : Natural := No_Mapping_File) | |
84481f76 RK |
1750 | is |
1751 | OC1 : constant Positive := Outstanding_Compiles + 1; | |
1752 | ||
1753 | begin | |
1754 | pragma Assert (OC1 <= Max_Process); | |
1755 | pragma Assert (Pid /= Invalid_Pid); | |
1756 | ||
48263c9a | 1757 | Running_Compile (OC1) := |
6528a7ed | 1758 | (Pid => Pid, |
48263c9a EB |
1759 | Full_Source_File => Sfile, |
1760 | Lib_File => Afile, | |
1761 | Full_Lib_File => Full_Lib_File, | |
1762 | Lib_File_Attr => Lib_File_Attr, | |
1763 | Source_Unit => Uname, | |
315f0c42 | 1764 | Mapping_File => Mfile); |
84481f76 RK |
1765 | |
1766 | Outstanding_Compiles := OC1; | |
02954c25 | 1767 | |
84481f76 RK |
1768 | end Add_Process; |
1769 | ||
1770 | -------------------- | |
1771 | -- Await_Compile -- | |
1772 | ------------------- | |
1773 | ||
1774 | procedure Await_Compile | |
d56e7acd AC |
1775 | (Data : out Compilation_Data; |
1776 | OK : out Boolean) | |
84481f76 | 1777 | is |
ccd0ed95 | 1778 | Pid : Process_Id; |
84481f76 RK |
1779 | |
1780 | begin | |
1781 | pragma Assert (Outstanding_Compiles > 0); | |
1782 | ||
d56e7acd AC |
1783 | Data := No_Compilation_Data; |
1784 | OK := False; | |
84481f76 | 1785 | |
7a5b62b0 | 1786 | Wait_Process (Pid, OK); |
84481f76 | 1787 | |
7a5b62b0 AC |
1788 | if Pid = Invalid_Pid then |
1789 | return; | |
1790 | end if; | |
84481f76 | 1791 | |
7a5b62b0 | 1792 | -- Look into the running compilation processes for this PID |
07fc65c4 | 1793 | |
7a5b62b0 AC |
1794 | for J in Running_Compile'First .. Outstanding_Compiles loop |
1795 | if Pid = Running_Compile (J).Pid then | |
ccd0ed95 | 1796 | Data := Running_Compile (J); |
7a5b62b0 AC |
1797 | -- If a mapping file was used by this compilation, get its file |
1798 | -- name for reuse by a subsequent compilation. | |
1799 | ||
1800 | if Running_Compile (J).Mapping_File /= No_Mapping_File then | |
315f0c42 AC |
1801 | The_Mapping_Files.Last_Free_Indexes := |
1802 | The_Mapping_Files.Last_Free_Indexes + 1; | |
1803 | The_Mapping_Files.Free_Mapping_File_Indexes | |
1804 | (The_Mapping_Files.Last_Free_Indexes) := | |
7a5b62b0 AC |
1805 | Running_Compile (J).Mapping_File; |
1806 | end if; | |
07fc65c4 | 1807 | |
7a5b62b0 AC |
1808 | -- To actually remove this Pid and related info from |
1809 | -- Running_Compile replace its entry with the last valid | |
1810 | -- entry in Running_Compile. | |
84481f76 | 1811 | |
7a5b62b0 AC |
1812 | if J = Outstanding_Compiles then |
1813 | null; | |
1814 | else | |
1815 | Running_Compile (J) := | |
1816 | Running_Compile (Outstanding_Compiles); | |
84481f76 RK |
1817 | end if; |
1818 | ||
7a5b62b0 AC |
1819 | Outstanding_Compiles := Outstanding_Compiles - 1; |
1820 | exit; | |
1821 | end if; | |
1822 | end loop; | |
84481f76 | 1823 | |
7a5b62b0 | 1824 | -- If the PID was not found, return with OK set to False |
d56e7acd | 1825 | |
7a5b62b0 AC |
1826 | if Data = No_Compilation_Data then |
1827 | OK := False; | |
1828 | end if; | |
84481f76 RK |
1829 | end Await_Compile; |
1830 | ||
1831 | --------------------------- | |
1832 | -- Bad_Compilation_Count -- | |
1833 | --------------------------- | |
1834 | ||
1835 | function Bad_Compilation_Count return Natural is | |
1836 | begin | |
1837 | return Bad_Compilation.Last - Bad_Compilation.First + 1; | |
1838 | end Bad_Compilation_Count; | |
1839 | ||
0da2c8ac AC |
1840 | ---------------------------- |
1841 | -- Check_Standard_Library -- | |
1842 | ---------------------------- | |
1843 | ||
1844 | procedure Check_Standard_Library is | |
1845 | begin | |
1846 | Need_To_Check_Standard_Library := False; | |
2f8d7dfe AC |
1847 | Name_Len := 0; |
1848 | ||
0da2c8ac | 1849 | if not Targparm.Suppress_Standard_Library_On_Target then |
2f8d7dfe AC |
1850 | Add_Str_To_Name_Buffer (Standard_Library_Package_Body_Name); |
1851 | else | |
1852 | Add_Str_To_Name_Buffer (System_Package_Spec_Name); | |
1853 | end if; | |
0da2c8ac | 1854 | |
2f8d7dfe | 1855 | declare |
2f8d7dfe | 1856 | Add_It : Boolean := True; |
20250fb8 | 1857 | Sfile : File_Name_Type; |
0da2c8ac | 1858 | |
2f8d7dfe AC |
1859 | begin |
1860 | Sfile := Name_Enter; | |
0da2c8ac | 1861 | |
2f8d7dfe AC |
1862 | -- If we have a special runtime, we add the standard library only |
1863 | -- if we can find it. | |
0da2c8ac | 1864 | |
2f8d7dfe AC |
1865 | if RTS_Switch then |
1866 | Add_It := Full_Source_Name (Sfile) /= No_File; | |
1867 | end if; | |
1868 | ||
1869 | if Add_It then | |
1870 | if not Queue.Insert | |
61770974 HK |
1871 | ((File => Sfile, |
1872 | Unit => No_Unit_Name, | |
1873 | Index => 0)) | |
2f8d7dfe AC |
1874 | then |
1875 | if Is_In_Obsoleted (Sfile) then | |
1876 | Executable_Obsolete := True; | |
0da2c8ac AC |
1877 | end if; |
1878 | end if; | |
2f8d7dfe AC |
1879 | end if; |
1880 | end; | |
0da2c8ac AC |
1881 | end Check_Standard_Library; |
1882 | ||
84481f76 RK |
1883 | ----------------------------------- |
1884 | -- Collect_Arguments_And_Compile -- | |
1885 | ----------------------------------- | |
1886 | ||
48263c9a EB |
1887 | procedure Collect_Arguments_And_Compile |
1888 | (Full_Source_File : File_Name_Type; | |
1889 | Lib_File : File_Name_Type; | |
1890 | Source_Index : Int; | |
1891 | Pid : out Process_Id; | |
1892 | Process_Created : out Boolean) is | |
84481f76 | 1893 | begin |
44e1918a | 1894 | Process_Created := False; |
07fc65c4 | 1895 | |
fbf5a39b | 1896 | -- If we use mapping file (-P or -C switches), then get one |
84481f76 | 1897 | |
fbf5a39b | 1898 | if Create_Mapping_File then |
315f0c42 | 1899 | Get_Mapping_File; |
fbf5a39b | 1900 | end if; |
84481f76 | 1901 | |
315f0c42 AC |
1902 | Pid := |
1903 | Compile | |
1904 | (S => Full_Source_File, | |
1905 | L => Lib_File, | |
1906 | Source_Index => Source_Index, | |
1907 | Args => Arguments (1 .. Last_Argument)); | |
1908 | Process_Created := True; | |
84481f76 RK |
1909 | end Collect_Arguments_And_Compile; |
1910 | ||
1911 | ------------- | |
1912 | -- Compile -- | |
1913 | ------------- | |
1914 | ||
fbf5a39b | 1915 | function Compile |
315f0c42 | 1916 | (S : File_Name_Type; |
d3cc6a32 | 1917 | L : File_Name_Type; |
aa720a54 AC |
1918 | Source_Index : Int; |
1919 | Args : Argument_List) return Process_Id | |
84481f76 | 1920 | is |
7fee6a39 | 1921 | Comp_Args : Argument_List (Args'First .. Args'Last + 10); |
84481f76 RK |
1922 | Comp_Next : Integer := Args'First; |
1923 | Comp_Last : Integer; | |
d4881d36 | 1924 | Arg_Index : Integer; |
84481f76 | 1925 | |
d3cc6a32 | 1926 | function Ada_File_Name (Name : File_Name_Type) return Boolean; |
84481f76 RK |
1927 | -- Returns True if Name is the name of an ada source file |
1928 | -- (i.e. suffix is .ads or .adb) | |
1929 | ||
1930 | ------------------- | |
1931 | -- Ada_File_Name -- | |
1932 | ------------------- | |
1933 | ||
d3cc6a32 | 1934 | function Ada_File_Name (Name : File_Name_Type) return Boolean is |
84481f76 RK |
1935 | begin |
1936 | Get_Name_String (Name); | |
1937 | return | |
1938 | Name_Len > 4 | |
1939 | and then Name_Buffer (Name_Len - 3 .. Name_Len - 1) = ".ad" | |
1940 | and then (Name_Buffer (Name_Len) = 'b' | |
1941 | or else | |
1942 | Name_Buffer (Name_Len) = 's'); | |
1943 | end Ada_File_Name; | |
1944 | ||
1945 | -- Start of processing for Compile | |
1946 | ||
1947 | begin | |
fbf5a39b AC |
1948 | Enter_Into_Obsoleted (S); |
1949 | ||
07fc65c4 GB |
1950 | -- By default, Syntax_Only is False |
1951 | ||
1952 | Syntax_Only := False; | |
1953 | ||
1954 | for J in Args'Range loop | |
1955 | if Args (J).all = "-gnats" then | |
1956 | ||
1957 | -- If we compile with -gnats, the bind step and the link step | |
1958 | -- are inhibited. Also, we set Syntax_Only to True, so that | |
1959 | -- we don't fail when we don't find the ALI file, after | |
1960 | -- compilation. | |
1961 | ||
1962 | Do_Bind_Step := False; | |
1963 | Do_Link_Step := False; | |
1964 | Syntax_Only := True; | |
1965 | ||
1966 | elsif Args (J).all = "-gnatc" then | |
1967 | ||
1968 | -- If we compile with -gnatc, the bind step and the link step | |
fbf5a39b | 1969 | -- are inhibited. We set Syntax_Only to False for the case when |
07fc65c4 GB |
1970 | -- -gnats was previously specified. |
1971 | ||
1972 | Do_Bind_Step := False; | |
1973 | Do_Link_Step := False; | |
1974 | Syntax_Only := False; | |
1975 | end if; | |
1976 | end loop; | |
1977 | ||
7fee6a39 BZ |
1978 | Comp_Args (Comp_Next) := new String'("-gnatea"); |
1979 | Comp_Next := Comp_Next + 1; | |
1980 | ||
84481f76 RK |
1981 | Comp_Args (Comp_Next) := Comp_Flag; |
1982 | Comp_Next := Comp_Next + 1; | |
1983 | ||
1984 | -- Optimize the simple case where the gcc command line looks like | |
3a336262 AC |
1985 | -- gcc -c -I. ... -I- file.adb |
1986 | -- into | |
1987 | -- gcc -c ... file.adb | |
84481f76 RK |
1988 | |
1989 | if Args (Args'First).all = "-I" & Normalized_CWD | |
1990 | and then Args (Args'Last).all = "-I-" | |
1991 | and then S = Strip_Directory (S) | |
1992 | then | |
1993 | Comp_Last := Comp_Next + Args'Length - 3; | |
d4881d36 | 1994 | Arg_Index := Args'First + 1; |
84481f76 RK |
1995 | |
1996 | else | |
1997 | Comp_Last := Comp_Next + Args'Length - 1; | |
d4881d36 | 1998 | Arg_Index := Args'First; |
84481f76 RK |
1999 | end if; |
2000 | ||
d4881d36 | 2001 | -- Make a deep copy of the arguments, because Normalize_Arguments |
6a2e4f0b AC |
2002 | -- may deallocate some arguments. Also strip target specific -mxxx |
2003 | -- switches in CodePeer mode. | |
d4881d36 | 2004 | |
383e179e | 2005 | declare |
6a2e4f0b | 2006 | Index : Natural; |
383e179e | 2007 | Last : constant Natural := Comp_Last; |
6a2e4f0b | 2008 | |
383e179e | 2009 | begin |
6a2e4f0b | 2010 | Index := Comp_Next; |
383e179e AC |
2011 | for J in Comp_Next .. Last loop |
2012 | declare | |
2013 | Str : String renames Args (Arg_Index).all; | |
2014 | begin | |
92966893 | 2015 | if CodePeer_Mode |
383e179e AC |
2016 | and then Str'Length > 2 |
2017 | and then Str (Str'First .. Str'First + 1) = "-m" | |
2018 | then | |
2019 | Comp_Last := Comp_Last - 1; | |
2020 | else | |
2021 | Comp_Args (Index) := new String'(Str); | |
2022 | Index := Index + 1; | |
2023 | end if; | |
2024 | end; | |
2025 | ||
2026 | Arg_Index := Arg_Index + 1; | |
2027 | end loop; | |
2028 | end; | |
d4881d36 | 2029 | |
84481f76 RK |
2030 | -- Set -gnatpg for predefined files (for this purpose the renamings |
2031 | -- such as Text_IO do not count as predefined). Note that we strip | |
dec55d76 | 2032 | -- the directory name from the source file name because the call to |
84481f76 RK |
2033 | -- Fname.Is_Predefined_File_Name cannot deal with directory prefixes. |
2034 | ||
2035 | declare | |
2036 | Fname : constant File_Name_Type := Strip_Directory (S); | |
2037 | ||
2038 | begin | |
b043ae01 | 2039 | if Is_Predefined_File_Name |
94d3a18d | 2040 | (Fname, Renamings_Included => False) |
b043ae01 | 2041 | then |
5b599df4 | 2042 | if Check_Readonly_Files or else Must_Compile then |
958a816e VC |
2043 | Comp_Args (Comp_Args'First + 2 .. Comp_Last + 1) := |
2044 | Comp_Args (Comp_Args'First + 1 .. Comp_Last); | |
84481f76 | 2045 | Comp_Last := Comp_Last + 1; |
958a816e | 2046 | Comp_Args (Comp_Args'First + 1) := GNAT_Flag; |
84481f76 RK |
2047 | |
2048 | else | |
fbf5a39b | 2049 | Make_Failed |
84481f76 RK |
2050 | ("not allowed to compile """ & |
2051 | Get_Name_String (Fname) & | |
e03c5253 VC |
2052 | """; use -a switch, or use the compiler directly with " |
2053 | & "the ""-gnatg"" switch"); | |
84481f76 RK |
2054 | end if; |
2055 | end if; | |
2056 | end; | |
2057 | ||
2058 | -- Now check if the file name has one of the suffixes familiar to | |
2059 | -- the gcc driver. If this is not the case then add the ada flag | |
2060 | -- "-x ada". | |
e8e581cd AC |
2061 | -- Append systematically "-x adascil" in CodePeer mode instead, to |
2062 | -- force the use of gnat1scil instead of gnat1. | |
84481f76 | 2063 | |
e8e581cd AC |
2064 | if CodePeer_Mode then |
2065 | Comp_Last := Comp_Last + 1; | |
2066 | Comp_Args (Comp_Last) := Ada_Flag_1; | |
2067 | Comp_Last := Comp_Last + 1; | |
2068 | Comp_Args (Comp_Last) := AdaSCIL_Flag; | |
2069 | ||
f96fd197 | 2070 | elsif not Ada_File_Name (S) then |
84481f76 RK |
2071 | Comp_Last := Comp_Last + 1; |
2072 | Comp_Args (Comp_Last) := Ada_Flag_1; | |
2073 | Comp_Last := Comp_Last + 1; | |
2074 | Comp_Args (Comp_Last) := Ada_Flag_2; | |
2075 | end if; | |
2076 | ||
aa720a54 AC |
2077 | if Source_Index /= 0 then |
2078 | declare | |
2079 | Num : constant String := Source_Index'Img; | |
2080 | begin | |
2081 | Comp_Last := Comp_Last + 1; | |
2082 | Comp_Args (Comp_Last) := | |
2083 | new String'("-gnateI" & Num (Num'First + 1 .. Num'Last)); | |
2084 | end; | |
2085 | end if; | |
2086 | ||
d3cc6a32 AC |
2087 | if Source_Index /= 0 |
2088 | or else L /= Strip_Directory (L) | |
2089 | or else Object_Directory_Path /= null | |
aa720a54 | 2090 | then |
44e1918a | 2091 | -- Build -o argument |
84481f76 RK |
2092 | |
2093 | Get_Name_String (L); | |
2094 | ||
2095 | for J in reverse 1 .. Name_Len loop | |
2096 | if Name_Buffer (J) = '.' then | |
2097 | Name_Len := J + Object_Suffix'Length - 1; | |
2098 | Name_Buffer (J .. Name_Len) := Object_Suffix; | |
2099 | exit; | |
2100 | end if; | |
2101 | end loop; | |
2102 | ||
2103 | Comp_Last := Comp_Last + 1; | |
2104 | Comp_Args (Comp_Last) := Output_Flag; | |
2105 | Comp_Last := Comp_Last + 1; | |
fbf5a39b AC |
2106 | |
2107 | -- If an object directory was specified, prepend the object file | |
2108 | -- name with this object directory. | |
2109 | ||
2110 | if Object_Directory_Path /= null then | |
2111 | Comp_Args (Comp_Last) := | |
2112 | new String'(Object_Directory_Path.all & | |
2113 | Name_Buffer (1 .. Name_Len)); | |
2114 | ||
2115 | else | |
2116 | Comp_Args (Comp_Last) := | |
2117 | new String'(Name_Buffer (1 .. Name_Len)); | |
2118 | end if; | |
84481f76 RK |
2119 | end if; |
2120 | ||
811c6a85 | 2121 | if Create_Mapping_File and then Mapping_File_Arg /= null then |
07fc65c4 | 2122 | Comp_Last := Comp_Last + 1; |
811c6a85 | 2123 | Comp_Args (Comp_Last) := new String'(Mapping_File_Arg.all); |
07fc65c4 GB |
2124 | end if; |
2125 | ||
84481f76 RK |
2126 | Get_Name_String (S); |
2127 | ||
2128 | Comp_Last := Comp_Last + 1; | |
2129 | Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len)); | |
2130 | ||
241bea26 AC |
2131 | -- Change to object directory of the project file, if necessary |
2132 | ||
f86eb278 | 2133 | GNAT.OS_Lib.Normalize_Arguments (Comp_Args (Args'First .. Comp_Last)); |
07fc65c4 | 2134 | |
0da2c8ac AC |
2135 | Comp_Last := Comp_Last + 1; |
2136 | Comp_Args (Comp_Last) := new String'("-gnatez"); | |
2137 | ||
84481f76 RK |
2138 | Display (Gcc.all, Comp_Args (Args'First .. Comp_Last)); |
2139 | ||
2140 | if Gcc_Path = null then | |
3dd9959c | 2141 | Make_Failed ("error, unable to locate " & Gcc.all); |
84481f76 RK |
2142 | end if; |
2143 | ||
2144 | return | |
f86eb278 | 2145 | GNAT.OS_Lib.Non_Blocking_Spawn |
84481f76 RK |
2146 | (Gcc_Path.all, Comp_Args (Args'First .. Comp_Last)); |
2147 | end Compile; | |
2148 | ||
48263c9a EB |
2149 | ------------------------------- |
2150 | -- Fill_Queue_From_ALI_Files -- | |
2151 | ------------------------------- | |
2152 | ||
2153 | procedure Fill_Queue_From_ALI_Files is | |
2154 | ALI : ALI_Id; | |
2155 | Source_Index : Int; | |
2156 | Sfile : File_Name_Type; | |
d56e7acd | 2157 | |
48263c9a EB |
2158 | begin |
2159 | while Good_ALI_Present loop | |
315f0c42 AC |
2160 | ALI := Get_Next_Good_ALI; |
2161 | Source_Index := Unit_Index_Of (ALIs.Table (ALI).Afile); | |
48263c9a EB |
2162 | |
2163 | -- If we are processing the library file corresponding to the | |
2164 | -- main source file check if this source can be a main unit. | |
2165 | ||
2166 | if ALIs.Table (ALI).Sfile = Main_Source | |
2167 | and then Source_Index = Main_Index | |
2168 | then | |
2169 | Main_Unit := ALIs.Table (ALI).Main_Program /= None; | |
2170 | end if; | |
2171 | ||
d56e7acd AC |
2172 | -- The following adds the standard library (s-stalib) to the list |
2173 | -- of files to be handled by gnatmake: this file and any files it | |
2174 | -- depends on are always included in every bind, even if they are | |
2175 | -- not in the explicit dependency list. Of course, it is not added | |
2176 | -- if Suppress_Standard_Library is True. | |
48263c9a | 2177 | |
d56e7acd AC |
2178 | -- However, to avoid annoying output about s-stalib.ali being read |
2179 | -- only, when "-v" is used, we add the standard library only when | |
2180 | -- "-a" is used. | |
48263c9a EB |
2181 | |
2182 | if Need_To_Check_Standard_Library then | |
2183 | Check_Standard_Library; | |
2184 | end if; | |
2185 | ||
d56e7acd AC |
2186 | -- Now insert in the Q the unmarked source files (i.e. those which |
2187 | -- have never been inserted in the Q and hence never considered). | |
2188 | -- Only do that if Unique_Compile is False. | |
48263c9a EB |
2189 | |
2190 | if not Unique_Compile then | |
2191 | for J in | |
2192 | ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit | |
2193 | loop | |
2194 | for K in | |
2195 | Units.Table (J).First_With .. Units.Table (J).Last_With | |
2196 | loop | |
2197 | Sfile := Withs.Table (K).Sfile; | |
48263c9a EB |
2198 | |
2199 | Dependencies.Append ((ALIs.Table (ALI).Sfile, Sfile)); | |
2200 | ||
2201 | if Is_In_Obsoleted (Sfile) then | |
2202 | Executable_Obsolete := True; | |
2203 | end if; | |
2204 | ||
2205 | if Sfile = No_File then | |
2206 | Debug_Msg ("Skipping generic:", Withs.Table (K).Uname); | |
2207 | ||
2208 | else | |
2209 | Source_Index := Unit_Index_Of (Withs.Table (K).Afile); | |
2210 | ||
e280f981 | 2211 | if not (Check_Readonly_Files or Must_Compile) |
48263c9a EB |
2212 | and then Is_Internal_File_Name (Sfile, False) |
2213 | then | |
2214 | Debug_Msg ("Skipping internal file:", Sfile); | |
2215 | ||
2216 | else | |
02954c25 | 2217 | Queue.Insert |
315f0c42 | 2218 | ((File => Sfile, |
e280f981 | 2219 | Unit => Withs.Table (K).Uname, |
315f0c42 | 2220 | Index => Source_Index)); |
48263c9a EB |
2221 | end if; |
2222 | end if; | |
2223 | end loop; | |
2224 | end loop; | |
2225 | end if; | |
2226 | end loop; | |
2227 | end Fill_Queue_From_ALI_Files; | |
2228 | ||
07fc65c4 GB |
2229 | ---------------------- |
2230 | -- Get_Mapping_File -- | |
2231 | ---------------------- | |
2232 | ||
315f0c42 | 2233 | procedure Get_Mapping_File is |
07fc65c4 GB |
2234 | begin |
2235 | -- If there is a mapping file ready to be reused, reuse it | |
2236 | ||
315f0c42 AC |
2237 | if The_Mapping_Files.Last_Free_Indexes > 0 then |
2238 | Mfile := | |
2239 | The_Mapping_Files.Free_Mapping_File_Indexes | |
2240 | (The_Mapping_Files.Last_Free_Indexes); | |
2241 | The_Mapping_Files.Last_Free_Indexes := | |
2242 | The_Mapping_Files.Last_Free_Indexes - 1; | |
07fc65c4 GB |
2243 | |
2244 | -- Otherwise, create and initialize a new one | |
2245 | ||
2246 | else | |
315f0c42 | 2247 | Init_Mapping_File (File_Index => Mfile); |
07fc65c4 GB |
2248 | end if; |
2249 | ||
2250 | -- Put the name in the mapping file argument for the invocation | |
2251 | -- of the compiler. | |
2252 | ||
fbf5a39b AC |
2253 | Free (Mapping_File_Arg); |
2254 | Mapping_File_Arg := | |
315f0c42 AC |
2255 | new String' |
2256 | ("-gnatem=" & | |
2257 | Get_Name_String | |
2258 | (The_Mapping_Files.Mapping_File_Names (Mfile))); | |
07fc65c4 GB |
2259 | end Get_Mapping_File; |
2260 | ||
84481f76 RK |
2261 | ----------------------- |
2262 | -- Get_Next_Good_ALI -- | |
2263 | ----------------------- | |
2264 | ||
315f0c42 AC |
2265 | function Get_Next_Good_ALI return ALI_Id is |
2266 | ALIP : ALI_Id; | |
84481f76 RK |
2267 | |
2268 | begin | |
2269 | pragma Assert (Good_ALI_Present); | |
02954c25 | 2270 | ALIP := Good_ALI.Table (Good_ALI.Last); |
84481f76 | 2271 | Good_ALI.Decrement_Last; |
02954c25 | 2272 | return ALIP; |
84481f76 RK |
2273 | end Get_Next_Good_ALI; |
2274 | ||
2275 | ---------------------- | |
2276 | -- Good_ALI_Present -- | |
2277 | ---------------------- | |
2278 | ||
2279 | function Good_ALI_Present return Boolean is | |
2280 | begin | |
2281 | return Good_ALI.First <= Good_ALI.Last; | |
2282 | end Good_ALI_Present; | |
2283 | ||
48263c9a EB |
2284 | -------------------------------- |
2285 | -- Must_Exit_Because_Of_Error -- | |
2286 | -------------------------------- | |
2287 | ||
2288 | function Must_Exit_Because_Of_Error return Boolean is | |
d56e7acd AC |
2289 | Data : Compilation_Data; |
2290 | Success : Boolean; | |
2291 | ||
48263c9a EB |
2292 | begin |
2293 | if Bad_Compilation_Count > 0 and then not Keep_Going then | |
2294 | while Outstanding_Compiles > 0 loop | |
2295 | Await_Compile (Data, Success); | |
2296 | ||
2297 | if not Success then | |
2298 | Record_Failure (Data.Full_Source_File, Data.Source_Unit); | |
2299 | end if; | |
2300 | end loop; | |
2301 | ||
2302 | return True; | |
2303 | end if; | |
2304 | ||
2305 | return False; | |
2306 | end Must_Exit_Because_Of_Error; | |
2307 | ||
84481f76 RK |
2308 | -------------------- |
2309 | -- Record_Failure -- | |
2310 | -------------------- | |
2311 | ||
2312 | procedure Record_Failure | |
2313 | (File : File_Name_Type; | |
2314 | Unit : Unit_Name_Type; | |
2315 | Found : Boolean := True) | |
2316 | is | |
2317 | begin | |
2318 | Bad_Compilation.Increment_Last; | |
2319 | Bad_Compilation.Table (Bad_Compilation.Last) := (File, Unit, Found); | |
2320 | end Record_Failure; | |
2321 | ||
2322 | --------------------- | |
2323 | -- Record_Good_ALI -- | |
2324 | --------------------- | |
2325 | ||
315f0c42 | 2326 | procedure Record_Good_ALI (A : ALI_Id) is |
84481f76 RK |
2327 | begin |
2328 | Good_ALI.Increment_Last; | |
315f0c42 | 2329 | Good_ALI.Table (Good_ALI.Last) := A; |
84481f76 RK |
2330 | end Record_Good_ALI; |
2331 | ||
48263c9a EB |
2332 | ------------------------------- |
2333 | -- Start_Compile_If_Possible -- | |
2334 | ------------------------------- | |
84481f76 | 2335 | |
48263c9a EB |
2336 | function Start_Compile_If_Possible |
2337 | (Args : Argument_List) return Boolean | |
2338 | is | |
d56e7acd AC |
2339 | In_Lib_Dir : Boolean; |
2340 | Need_To_Compile : Boolean; | |
42f1d661 | 2341 | Pid : Process_Id := Invalid_Pid; |
d56e7acd | 2342 | Process_Created : Boolean; |
48263c9a | 2343 | |
e280f981 | 2344 | Source : Queue.Source_Info; |
42f1d661 | 2345 | Full_Source_File : File_Name_Type := No_File; |
48263c9a | 2346 | Source_File_Attr : aliased File_Attributes; |
cafdbd2e | 2347 | -- The full name of the source file and its attributes (size, ...) |
48263c9a | 2348 | |
d56e7acd | 2349 | Lib_File : File_Name_Type; |
42f1d661 | 2350 | Full_Lib_File : File_Name_Type := No_File; |
d56e7acd AC |
2351 | Lib_File_Attr : aliased File_Attributes; |
2352 | Read_Only : Boolean := False; | |
ae71d81b | 2353 | ALI : ALI_Id := No_ALI_Id; |
cafdbd2e | 2354 | -- The ALI file and its attributes (size, stamp, ...) |
48263c9a | 2355 | |
ae71d81b | 2356 | Obj_File : File_Name_Type := No_File; |
d56e7acd | 2357 | Obj_Stamp : Time_Stamp_Type; |
48263c9a | 2358 | -- The object file |
84481f76 | 2359 | |
e280f981 AC |
2360 | Found : Boolean; |
2361 | ||
48263c9a | 2362 | begin |
315f0c42 | 2363 | if not Queue.Is_Empty and then |
02954c25 AC |
2364 | Outstanding_Compiles < Max_Process |
2365 | then | |
e280f981 | 2366 | Queue.Extract (Found, Source); |
6b6fcd3e | 2367 | |
315f0c42 AC |
2368 | Osint.Full_Source_Name |
2369 | (Source.File, | |
2370 | Full_File => Full_Source_File, | |
2371 | Attr => Source_File_Attr'Access); | |
3acdda2d | 2372 | |
315f0c42 | 2373 | Lib_File := Osint.Lib_File_Name (Source.File, Source.Index); |
3acdda2d | 2374 | |
315f0c42 AC |
2375 | Osint.Full_Lib_File_Name |
2376 | (Lib_File, | |
2377 | Lib_File => Full_Lib_File, | |
2378 | Attr => Lib_File_Attr); | |
84481f76 | 2379 | |
d56e7acd | 2380 | -- If source has already been compiled, executable is obsolete |
84481f76 | 2381 | |
e280f981 | 2382 | if Is_In_Obsoleted (Source.File) then |
48263c9a EB |
2383 | Executable_Obsolete := True; |
2384 | end if; | |
84481f76 | 2385 | |
5b599df4 AC |
2386 | In_Lib_Dir := Full_Lib_File /= No_File |
2387 | and then In_Ada_Lib_Dir (Full_Lib_File); | |
84481f76 | 2388 | |
48263c9a | 2389 | -- Since the following requires a system call, we precompute it |
cafdbd2e | 2390 | -- when needed. |
84481f76 | 2391 | |
48263c9a EB |
2392 | if not In_Lib_Dir then |
2393 | if Full_Lib_File /= No_File | |
5b599df4 | 2394 | and then not (Check_Readonly_Files or else Must_Compile) |
48263c9a EB |
2395 | then |
2396 | Get_Name_String (Full_Lib_File); | |
2397 | Name_Buffer (Name_Len + 1) := ASCII.NUL; | |
2398 | Read_Only := not Is_Writable_File | |
2399 | (Name_Buffer'Address, Lib_File_Attr'Access); | |
2400 | else | |
2401 | Read_Only := False; | |
84481f76 | 2402 | end if; |
48263c9a | 2403 | end if; |
b11cb5fd | 2404 | |
48263c9a | 2405 | -- If the library file is an Ada library skip it |
fbf5a39b | 2406 | |
48263c9a EB |
2407 | if In_Lib_Dir then |
2408 | Verbose_Msg | |
2409 | (Lib_File, | |
2410 | "is in an Ada library", | |
2411 | Prefix => " ", | |
2412 | Minimum_Verbosity => Opt.High); | |
b11cb5fd | 2413 | |
cafdbd2e AC |
2414 | -- If the library file is a read-only library skip it, but only |
2415 | -- if, when using project files, this library file is in the | |
2416 | -- right object directory (a read-only ALI file in the object | |
2417 | -- directory of a project being extended must not be skipped). | |
b11cb5fd | 2418 | |
315f0c42 | 2419 | elsif Read_Only then |
48263c9a EB |
2420 | Verbose_Msg |
2421 | (Lib_File, | |
2422 | "is a read-only library", | |
2423 | Prefix => " ", | |
2424 | Minimum_Verbosity => Opt.High); | |
fbf5a39b | 2425 | |
48263c9a | 2426 | -- The source file that we are checking cannot be located |
84481f76 | 2427 | |
48263c9a | 2428 | elsif Full_Source_File = No_File then |
e280f981 | 2429 | Record_Failure (Source.File, Source.Unit, False); |
84481f76 | 2430 | |
48263c9a | 2431 | -- Source and library files can be located but are internal |
cafdbd2e | 2432 | -- files. |
b11cb5fd | 2433 | |
5b599df4 | 2434 | elsif not (Check_Readonly_Files or else Must_Compile) |
48263c9a | 2435 | and then Full_Lib_File /= No_File |
e280f981 | 2436 | and then Is_Internal_File_Name (Source.File, False) |
48263c9a EB |
2437 | then |
2438 | if Force_Compilations then | |
2439 | Fail | |
2440 | ("not allowed to compile """ & | |
e280f981 | 2441 | Get_Name_String (Source.File) & |
e03c5253 VC |
2442 | """; use -a switch, or use the compiler directly with " |
2443 | & "the ""-gnatg"" switch"); | |
b11cb5fd EB |
2444 | end if; |
2445 | ||
48263c9a EB |
2446 | Verbose_Msg |
2447 | (Lib_File, | |
2448 | "is an internal library", | |
2449 | Prefix => " ", | |
2450 | Minimum_Verbosity => Opt.High); | |
84481f76 | 2451 | |
48263c9a | 2452 | -- The source file that we are checking can be located |
84481f76 | 2453 | |
48263c9a | 2454 | else |
315f0c42 AC |
2455 | Collect_Arguments (Args); |
2456 | ||
2457 | -- Don't waste any time if we have to recompile anyway | |
2458 | ||
2459 | Obj_Stamp := Empty_Time_Stamp; | |
2460 | Need_To_Compile := Force_Compilations; | |
2461 | ||
2462 | if not Force_Compilations then | |
2463 | Check (Source_File => Source.File, | |
2464 | The_Args => Args, | |
2465 | Lib_File => Lib_File, | |
2466 | Full_Lib_File => Full_Lib_File, | |
2467 | Lib_File_Attr => Lib_File_Attr'Access, | |
2468 | Read_Only => Read_Only, | |
2469 | ALI => ALI, | |
2470 | O_File => Obj_File, | |
2471 | O_Stamp => Obj_Stamp); | |
2472 | Need_To_Compile := (ALI = No_ALI_Id); | |
2473 | end if; | |
84481f76 | 2474 | |
315f0c42 | 2475 | if not Need_To_Compile then |
84481f76 | 2476 | |
315f0c42 | 2477 | -- The ALI file is up-to-date; record its Id |
84481f76 | 2478 | |
315f0c42 | 2479 | Record_Good_ALI (ALI); |
84481f76 | 2480 | |
315f0c42 AC |
2481 | -- Record the time stamp of the most recent object |
2482 | -- file as long as no (re)compilations are needed. | |
84481f76 | 2483 | |
315f0c42 AC |
2484 | if First_Compiled_File = No_File |
2485 | and then (Most_Recent_Obj_File = No_File | |
2486 | or else Obj_Stamp > Most_Recent_Obj_Stamp) | |
2487 | then | |
2488 | Most_Recent_Obj_File := Obj_File; | |
2489 | Most_Recent_Obj_Stamp := Obj_Stamp; | |
2490 | end if; | |
84481f76 | 2491 | |
315f0c42 AC |
2492 | else |
2493 | -- Is this the first file we have to compile? | |
a7ab2998 | 2494 | |
315f0c42 AC |
2495 | if First_Compiled_File = No_File then |
2496 | First_Compiled_File := Full_Source_File; | |
2497 | Most_Recent_Obj_File := No_File; | |
a7ab2998 | 2498 | |
315f0c42 | 2499 | if Do_Not_Execute then |
d56e7acd | 2500 | |
315f0c42 | 2501 | -- Exit the main loop |
cafdbd2e | 2502 | |
315f0c42 | 2503 | return True; |
48263c9a | 2504 | end if; |
315f0c42 | 2505 | end if; |
84481f76 | 2506 | |
315f0c42 AC |
2507 | -- Compute where the ALI file must be generated in |
2508 | -- In_Place_Mode (this does not require to know the | |
2509 | -- location of the object directory). | |
6528a7ed | 2510 | |
315f0c42 AC |
2511 | if In_Place_Mode then |
2512 | if Full_Lib_File = No_File then | |
d56e7acd | 2513 | |
315f0c42 AC |
2514 | -- If the library file was not found, then save |
2515 | -- the library file near the source file. | |
84481f76 | 2516 | |
315f0c42 AC |
2517 | Lib_File := |
2518 | Osint.Lib_File_Name | |
2519 | (Full_Source_File, Source.Index); | |
2520 | Full_Lib_File := Lib_File; | |
84481f76 | 2521 | |
315f0c42 AC |
2522 | else |
2523 | -- If the library file was found, then save the | |
2524 | -- library file in the same place. | |
84481f76 | 2525 | |
315f0c42 | 2526 | Lib_File := Full_Lib_File; |
48263c9a | 2527 | end if; |
315f0c42 | 2528 | end if; |
84481f76 | 2529 | |
315f0c42 AC |
2530 | -- Start the compilation and record it. We can do this |
2531 | -- because there is at least one free process. This might | |
2532 | -- change the current directory. | |
2533 | ||
2534 | Collect_Arguments_And_Compile | |
2535 | (Full_Source_File => Full_Source_File, | |
2536 | Lib_File => Lib_File, | |
2537 | Source_Index => Source.Index, | |
2538 | Pid => Pid, | |
2539 | Process_Created => Process_Created); | |
2540 | ||
2541 | -- Compute where the ALI file will be generated (for | |
2542 | -- cases that might require to know the current | |
2543 | -- directory). The current directory might be changed | |
2544 | -- when compiling other files so we cannot rely on it | |
2545 | -- being the same to find the resulting ALI file. | |
2546 | ||
2547 | if not In_Place_Mode then | |
2548 | ||
2549 | -- Compute the expected location of the ALI file. This | |
2550 | -- can be from several places: | |
2551 | -- -i => in place mode. In such a case, | |
2552 | -- Full_Lib_File has already been set above | |
2553 | -- -D => if specified | |
2554 | -- or defaults in current dir | |
2555 | -- We could simply use a call similar to | |
2556 | -- Osint.Full_Lib_File_Name (Lib_File) | |
2557 | -- but that involves system calls and is thus slower | |
2558 | ||
2559 | if Object_Directory_Path /= null then | |
2560 | Name_Len := 0; | |
2561 | Add_Str_To_Name_Buffer (Object_Directory_Path.all); | |
2562 | Add_Str_To_Name_Buffer (Get_Name_String (Lib_File)); | |
2563 | Full_Lib_File := Name_Find; | |
6528a7ed | 2564 | |
315f0c42 AC |
2565 | else |
2566 | Full_Lib_File := Lib_File; | |
6528a7ed AC |
2567 | end if; |
2568 | ||
315f0c42 | 2569 | end if; |
6528a7ed | 2570 | |
315f0c42 | 2571 | Lib_File_Attr := Unknown_Attributes; |
48263c9a | 2572 | |
315f0c42 AC |
2573 | -- Make sure we could successfully start the compilation |
2574 | ||
2575 | if Process_Created then | |
2576 | if Pid = Invalid_Pid then | |
2577 | Record_Failure (Full_Source_File, Source.Unit); | |
2578 | else | |
2579 | Add_Process | |
2580 | (Pid => Pid, | |
2581 | Sfile => Full_Source_File, | |
2582 | Afile => Lib_File, | |
2583 | Uname => Source.Unit, | |
2584 | Mfile => Mfile, | |
2585 | Full_Lib_File => Full_Lib_File, | |
2586 | Lib_File_Attr => Lib_File_Attr); | |
aa720a54 | 2587 | end if; |
84481f76 RK |
2588 | end if; |
2589 | end if; | |
48263c9a | 2590 | end if; |
84481f76 | 2591 | end if; |
48263c9a EB |
2592 | return False; |
2593 | end Start_Compile_If_Possible; | |
2594 | ||
2595 | ----------------------------- | |
2596 | -- Wait_For_Available_Slot -- | |
2597 | ----------------------------- | |
84481f76 | 2598 | |
48263c9a | 2599 | procedure Wait_For_Available_Slot is |
d56e7acd AC |
2600 | Compilation_OK : Boolean; |
2601 | Text : Text_Buffer_Ptr; | |
2602 | ALI : ALI_Id; | |
2603 | Data : Compilation_Data; | |
84481f76 | 2604 | |
48263c9a | 2605 | begin |
84481f76 | 2606 | if Outstanding_Compiles = Max_Process |
315f0c42 | 2607 | or else (Queue.Is_Empty |
d56e7acd AC |
2608 | and then not Good_ALI_Present |
2609 | and then Outstanding_Compiles > 0) | |
84481f76 | 2610 | then |
48263c9a | 2611 | Await_Compile (Data, Compilation_OK); |
84481f76 RK |
2612 | |
2613 | if not Compilation_OK then | |
48263c9a | 2614 | Record_Failure (Data.Full_Source_File, Data.Source_Unit); |
07fc65c4 GB |
2615 | end if; |
2616 | ||
2617 | if Compilation_OK or else Keep_Going then | |
84481f76 | 2618 | |
84481f76 RK |
2619 | -- Re-read the updated library file |
2620 | ||
07fc65c4 GB |
2621 | declare |
2622 | Saved_Object_Consistency : constant Boolean := | |
b7e429ab | 2623 | Check_Object_Consistency; |
07fc65c4 GB |
2624 | |
2625 | begin | |
cafdbd2e AC |
2626 | -- If compilation was not OK, or if output is not an object |
2627 | -- file and we don't do the bind step, don't check for | |
2628 | -- object consistency. | |
07fc65c4 | 2629 | |
b7e429ab AC |
2630 | Check_Object_Consistency := |
2631 | Check_Object_Consistency | |
d56e7acd AC |
2632 | and Compilation_OK |
2633 | and (Output_Is_Object or Do_Bind_Step); | |
b11cb5fd | 2634 | |
d56e7acd AC |
2635 | Text := |
2636 | Read_Library_Info_From_Full | |
2637 | (Data.Full_Lib_File, Data.Lib_File_Attr'Access); | |
07fc65c4 GB |
2638 | |
2639 | -- Restore Check_Object_Consistency to its initial value | |
2640 | ||
b7e429ab | 2641 | Check_Object_Consistency := Saved_Object_Consistency; |
07fc65c4 | 2642 | end; |
84481f76 | 2643 | |
d56e7acd AC |
2644 | -- If an ALI file was generated by this compilation, scan the |
2645 | -- ALI file and record it. | |
0df218a9 | 2646 | |
84481f76 RK |
2647 | -- If the scan fails, a previous ali file is inconsistent with |
2648 | -- the unit just compiled. | |
2649 | ||
2650 | if Text /= null then | |
d56e7acd AC |
2651 | ALI := |
2652 | Scan_ALI | |
2653 | (Data.Lib_File, Text, Ignore_ED => False, Err => True); | |
84481f76 RK |
2654 | |
2655 | if ALI = No_ALI_Id then | |
07fc65c4 GB |
2656 | |
2657 | -- Record a failure only if not already done | |
2658 | ||
2659 | if Compilation_OK then | |
2660 | Inform | |
48263c9a | 2661 | (Data.Lib_File, |
07fc65c4 | 2662 | "incompatible ALI file, please recompile"); |
48263c9a EB |
2663 | Record_Failure |
2664 | (Data.Full_Source_File, Data.Source_Unit); | |
07fc65c4 | 2665 | end if; |
48263c9a | 2666 | |
84481f76 | 2667 | else |
315f0c42 | 2668 | Record_Good_ALI (ALI); |
84481f76 RK |
2669 | end if; |
2670 | ||
48263c9a EB |
2671 | Free (Text); |
2672 | ||
84481f76 RK |
2673 | -- If we could not read the ALI file that was just generated |
2674 | -- then there could be a problem reading either the ALI or the | |
189641a2 VC |
2675 | -- corresponding object file (if Check_Object_Consistency is |
2676 | -- set Read_Library_Info checks that the time stamp of the | |
2677 | -- object file is more recent than that of the ALI). However, | |
2678 | -- we record a failure only if not already done. | |
84481f76 RK |
2679 | |
2680 | else | |
07fc65c4 GB |
2681 | if Compilation_OK and not Syntax_Only then |
2682 | Inform | |
48263c9a | 2683 | (Data.Lib_File, |
07fc65c4 | 2684 | "WARNING: ALI or object file not found after compile"); |
dda38714 AC |
2685 | |
2686 | if not Is_Regular_File | |
9926efec | 2687 | (Get_Name_String (Name_Id (Data.Full_Lib_File))) |
dda38714 AC |
2688 | then |
2689 | Inform (Data.Full_Lib_File, "not found"); | |
2690 | end if; | |
2691 | ||
48263c9a | 2692 | Record_Failure (Data.Full_Source_File, Data.Source_Unit); |
07fc65c4 | 2693 | end if; |
84481f76 RK |
2694 | end if; |
2695 | end if; | |
2696 | end if; | |
48263c9a | 2697 | end Wait_For_Available_Slot; |
84481f76 | 2698 | |
48263c9a | 2699 | -- Start of processing for Compile_Sources |
84481f76 | 2700 | |
48263c9a EB |
2701 | begin |
2702 | pragma Assert (Args'First = 1); | |
84481f76 | 2703 | |
48263c9a EB |
2704 | Outstanding_Compiles := 0; |
2705 | Running_Compile := new Comp_Data_Arr (1 .. Max_Process); | |
84481f76 | 2706 | |
48263c9a | 2707 | -- Package and Queue initializations |
84481f76 | 2708 | |
48263c9a | 2709 | Good_ALI.Init; |
84481f76 | 2710 | |
48263c9a EB |
2711 | if Initialize_ALI_Data then |
2712 | Initialize_ALI; | |
2713 | Initialize_ALI_Source; | |
2714 | end if; | |
84481f76 | 2715 | |
48263c9a | 2716 | -- The following two flags affect the behavior of ALI.Set_Source_Table. |
d56e7acd AC |
2717 | -- We set Check_Source_Files to True to ensure that source file time |
2718 | -- stamps are checked, and we set All_Sources to False to avoid checking | |
2719 | -- the presence of the source files listed in the source dependency | |
2720 | -- section of an ali file (which would be a mistake since the ali file | |
2721 | -- may be obsolete). | |
84481f76 | 2722 | |
48263c9a EB |
2723 | Check_Source_Files := True; |
2724 | All_Sources := False; | |
d3cc6a32 | 2725 | |
e280f981 | 2726 | Queue.Insert |
315f0c42 | 2727 | ((File => Main_Source, |
e280f981 | 2728 | Unit => No_Unit_Name, |
315f0c42 | 2729 | Index => Main_Index)); |
aa720a54 | 2730 | |
48263c9a EB |
2731 | First_Compiled_File := No_File; |
2732 | Most_Recent_Obj_File := No_File; | |
2733 | Most_Recent_Obj_Stamp := Empty_Time_Stamp; | |
2734 | Main_Unit := False; | |
84481f76 | 2735 | |
48263c9a | 2736 | -- Keep looping until there is no more work to do (the Q is empty) |
cafdbd2e | 2737 | -- and all the outstanding compilations have terminated. |
84481f76 | 2738 | |
02954c25 AC |
2739 | Make_Loop : |
2740 | while not Queue.Is_Empty or else Outstanding_Compiles > 0 loop | |
48263c9a EB |
2741 | exit Make_Loop when Must_Exit_Because_Of_Error; |
2742 | exit Make_Loop when Start_Compile_If_Possible (Args); | |
84481f76 | 2743 | |
48263c9a | 2744 | Wait_For_Available_Slot; |
fbf5a39b | 2745 | |
48263c9a | 2746 | -- ??? Should be done as soon as we add a Good_ALI, wouldn't it avoid |
cafdbd2e AC |
2747 | -- the need for a list of good ALI? |
2748 | ||
48263c9a | 2749 | Fill_Queue_From_ALI_Files; |
84481f76 | 2750 | |
b7e429ab | 2751 | if Display_Compilation_Progress then |
84481f76 | 2752 | Write_Str ("completed "); |
02954c25 | 2753 | Write_Int (Int (Queue.Processed)); |
84481f76 | 2754 | Write_Str (" out of "); |
02954c25 | 2755 | Write_Int (Int (Queue.Size)); |
84481f76 | 2756 | Write_Str (" ("); |
02954c25 | 2757 | Write_Int (Int ((Queue.Processed * 100) / Queue.Size)); |
84481f76 RK |
2758 | Write_Str ("%)..."); |
2759 | Write_Eol; | |
2760 | end if; | |
2761 | end loop Make_Loop; | |
2762 | ||
2763 | Compilation_Failures := Bad_Compilation_Count; | |
2764 | ||
2765 | -- Compilation is finished | |
2766 | ||
fbf5a39b AC |
2767 | end Compile_Sources; |
2768 | ||
fbf5a39b AC |
2769 | --------------- |
2770 | -- Debug_Msg -- | |
2771 | --------------- | |
2772 | ||
2773 | procedure Debug_Msg (S : String; N : Name_Id) is | |
2774 | begin | |
2775 | if Debug.Debug_Flag_W then | |
2776 | Write_Str (" ... "); | |
2777 | Write_Str (S); | |
2778 | Write_Str (" "); | |
2779 | Write_Name (N); | |
2780 | Write_Eol; | |
2781 | end if; | |
2782 | end Debug_Msg; | |
2783 | ||
d3cc6a32 AC |
2784 | procedure Debug_Msg (S : String; N : File_Name_Type) is |
2785 | begin | |
2786 | Debug_Msg (S, Name_Id (N)); | |
2787 | end Debug_Msg; | |
2788 | ||
2789 | procedure Debug_Msg (S : String; N : Unit_Name_Type) is | |
2790 | begin | |
2791 | Debug_Msg (S, Name_Id (N)); | |
2792 | end Debug_Msg; | |
2793 | ||
84481f76 RK |
2794 | ------------- |
2795 | -- Display -- | |
2796 | ------------- | |
2797 | ||
2798 | procedure Display (Program : String; Args : Argument_List) is | |
2799 | begin | |
2800 | pragma Assert (Args'First = 1); | |
2801 | ||
315f0c42 | 2802 | if not Quiet_Output then |
84481f76 RK |
2803 | Write_Str (Program); |
2804 | ||
2805 | for J in Args'Range loop | |
07fc65c4 | 2806 | |
7fee6a39 | 2807 | -- Never display -gnatea nor -gnatez |
07fc65c4 | 2808 | |
c5288c90 | 2809 | if Args (J).all /= "-gnatea" |
315f0c42 AC |
2810 | and then |
2811 | Args (J).all /= "-gnatez" | |
7fee6a39 | 2812 | then |
315f0c42 AC |
2813 | -- Do not display the -F=mapping_file switch for gnatbind if |
2814 | -- -dn is not specified. | |
fbf5a39b | 2815 | |
315f0c42 AC |
2816 | if Opt.Keep_Temporary_Files |
2817 | or else Args (J)'Length < 4 | |
0da2c8ac | 2818 | or else |
315f0c42 | 2819 | Args (J) (Args (J)'First .. Args (J)'First + 2) /= "-F=" |
fbf5a39b | 2820 | then |
315f0c42 | 2821 | Write_Str (" "); |
0da2c8ac | 2822 | |
315f0c42 AC |
2823 | -- If -df is used, only display file names, not path |
2824 | -- names. | |
0da2c8ac | 2825 | |
315f0c42 AC |
2826 | if Debug.Debug_Flag_F then |
2827 | declare | |
2828 | Equal_Pos : Natural; | |
2829 | ||
2830 | begin | |
2831 | Equal_Pos := Args (J)'First - 1; | |
2832 | for K in Args (J)'Range loop | |
2833 | if Args (J) (K) = '=' then | |
2834 | Equal_Pos := K; | |
2835 | exit; | |
189641a2 | 2836 | end if; |
315f0c42 | 2837 | end loop; |
189641a2 | 2838 | |
315f0c42 AC |
2839 | if Is_Absolute_Path |
2840 | (Args (J) (Equal_Pos + 1 .. Args (J)'Last)) | |
2841 | then | |
2842 | Write_Str | |
2843 | (Args (J) (Args (J)'First .. Equal_Pos)); | |
2844 | Write_Str | |
2845 | (File_Name | |
2846 | (Args (J) | |
2847 | (Equal_Pos + 1 .. Args (J)'Last))); | |
2848 | ||
2849 | else | |
2850 | Write_Str (Args (J).all); | |
2851 | end if; | |
2852 | end; | |
2853 | ||
2854 | else | |
2855 | Write_Str (Args (J).all); | |
0da2c8ac | 2856 | end if; |
fbf5a39b | 2857 | end if; |
07fc65c4 | 2858 | end if; |
84481f76 RK |
2859 | end loop; |
2860 | ||
2861 | Write_Eol; | |
2862 | end if; | |
2863 | end Display; | |
2864 | ||
fbf5a39b AC |
2865 | -------------------------- |
2866 | -- Enter_Into_Obsoleted -- | |
2867 | -------------------------- | |
2868 | ||
d3cc6a32 | 2869 | procedure Enter_Into_Obsoleted (F : File_Name_Type) is |
91b1417d | 2870 | Name : constant String := Get_Name_String (F); |
d3cc6a32 AC |
2871 | First : Natural; |
2872 | F2 : File_Name_Type; | |
fbf5a39b AC |
2873 | |
2874 | begin | |
d3cc6a32 | 2875 | First := Name'Last; |
fbf5a39b | 2876 | while First > Name'First |
43c58950 | 2877 | and then not Is_Directory_Separator (Name (First - 1)) |
fbf5a39b AC |
2878 | loop |
2879 | First := First - 1; | |
2880 | end loop; | |
2881 | ||
2882 | if First /= Name'First then | |
2883 | Name_Len := 0; | |
2884 | Add_Str_To_Name_Buffer (Name (First .. Name'Last)); | |
2885 | F2 := Name_Find; | |
f86eb278 | 2886 | |
d3cc6a32 AC |
2887 | else |
2888 | F2 := F; | |
fbf5a39b AC |
2889 | end if; |
2890 | ||
2891 | Debug_Msg ("New entry in Obsoleted table:", F2); | |
2892 | Obsoleted.Set (F2, True); | |
2893 | end Enter_Into_Obsoleted; | |
2894 | ||
6367dd30 AC |
2895 | ------------------- |
2896 | -- Linking_Phase -- | |
2897 | ------------------- | |
84481f76 | 2898 | |
6367dd30 AC |
2899 | procedure Linking_Phase |
2900 | (Non_Std_Executable : Boolean := False; | |
2901 | Executable : File_Name_Type := No_File; | |
2902 | Main_ALI_File : File_Name_Type) | |
2903 | is | |
2904 | Linker_Switches_Last : constant Integer := Linker_Switches.Last; | |
5969611f | 2905 | |
6367dd30 AC |
2906 | begin |
2907 | if not Run_Path_Option then | |
2908 | Linker_Switches.Increment_Last; | |
2909 | Linker_Switches.Table (Linker_Switches.Last) := | |
2910 | new String'("-R"); | |
2911 | end if; | |
07fc65c4 | 2912 | |
92966893 AC |
2913 | if CodePeer_Mode then |
2914 | Linker_Switches.Increment_Last; | |
2915 | Linker_Switches.Table (Linker_Switches.Last) := | |
2916 | new String'(CodePeer_Mode_String); | |
2917 | end if; | |
2918 | ||
2919 | -- Add switch -M to gnatlink if builder switch --create-map-file | |
6367dd30 | 2920 | -- has been specified. |
aa720a54 | 2921 | |
6367dd30 AC |
2922 | if Map_File /= null then |
2923 | Linker_Switches.Increment_Last; | |
2924 | Linker_Switches.Table (Linker_Switches.Last) := | |
2925 | new String'("-M" & Map_File.all); | |
2926 | end if; | |
07fc65c4 | 2927 | |
6367dd30 AC |
2928 | declare |
2929 | Args : Argument_List | |
5969611f | 2930 | (Linker_Switches.First .. Linker_Switches.Last + 2); |
07fc65c4 | 2931 | |
6367dd30 AC |
2932 | Last_Arg : Integer := Linker_Switches.First - 1; |
2933 | Skip : Boolean := False; | |
2934 | ||
2935 | begin | |
2936 | -- Get all the linker switches | |
2937 | ||
2938 | for J in Linker_Switches.First .. Linker_Switches.Last loop | |
2939 | if Skip then | |
2940 | Skip := False; | |
2941 | ||
2942 | elsif Non_Std_Executable | |
2943 | and then Linker_Switches.Table (J).all = "-o" | |
12e0c41c | 2944 | then |
6367dd30 | 2945 | Skip := True; |
b0f26df5 | 2946 | |
6367dd30 | 2947 | -- Here we capture and duplicate the linker argument. We |
5969611f RD |
2948 | -- need to do the duplication since the arguments will get |
2949 | -- normalized. Not doing so will result in calling normalized | |
2950 | -- two times for the same set of arguments if gnatmake is | |
a21d245c AC |
2951 | -- passed multiple mains. This can result in the wrong |
2952 | -- argument being passed to the linker. | |
b0f26df5 | 2953 | |
6367dd30 AC |
2954 | else |
2955 | Last_Arg := Last_Arg + 1; | |
5969611f | 2956 | Args (Last_Arg) := new String'(Linker_Switches.Table (J).all); |
fbf5a39b | 2957 | end if; |
6367dd30 | 2958 | end loop; |
07fc65c4 | 2959 | |
6367dd30 | 2960 | -- If need be, add the -o switch |
84481f76 | 2961 | |
6367dd30 AC |
2962 | if Non_Std_Executable then |
2963 | Last_Arg := Last_Arg + 1; | |
2964 | Args (Last_Arg) := new String'("-o"); | |
2965 | Last_Arg := Last_Arg + 1; | |
2966 | Args (Last_Arg) := new String'(Get_Name_String (Executable)); | |
2967 | end if; | |
aa720a54 | 2968 | |
6367dd30 | 2969 | -- And invoke the linker |
84481f76 | 2970 | |
6367dd30 AC |
2971 | declare |
2972 | Success : Boolean := False; | |
a21d245c | 2973 | |
6367dd30 | 2974 | begin |
315f0c42 AC |
2975 | -- If gnatmake was invoked with --subdirs, put the executable in |
2976 | -- the subdirectory specified. | |
1e4b91fc | 2977 | |
315f0c42 | 2978 | if Subdirs /= null then |
1e4b91fc AC |
2979 | Change_Dir (Object_Directory_Path.all); |
2980 | end if; | |
2981 | ||
6367dd30 AC |
2982 | Link (Main_ALI_File, |
2983 | Link_With_Shared_Libgcc.all & | |
2984 | Args (Args'First .. Last_Arg), | |
2985 | Success); | |
2986 | ||
2987 | if Success then | |
2988 | Successful_Links.Increment_Last; | |
5969611f | 2989 | Successful_Links.Table (Successful_Links.Last) := Main_ALI_File; |
6367dd30 | 2990 | |
a21d245c | 2991 | elsif Osint.Number_Of_Files = 1 or else not Keep_Going then |
6367dd30 | 2992 | Make_Failed ("*** link failed."); |
84481f76 | 2993 | |
6367dd30 AC |
2994 | else |
2995 | Set_Standard_Error; | |
2996 | Write_Line ("*** link failed"); | |
84481f76 | 2997 | |
6367dd30 AC |
2998 | if Commands_To_Stdout then |
2999 | Set_Standard_Output; | |
3000 | end if; | |
84481f76 | 3001 | |
6367dd30 | 3002 | Failed_Links.Increment_Last; |
5969611f | 3003 | Failed_Links.Table (Failed_Links.Last) := Main_ALI_File; |
6367dd30 AC |
3004 | end if; |
3005 | end; | |
3006 | end; | |
84481f76 | 3007 | |
6367dd30 AC |
3008 | Linker_Switches.Set_Last (Linker_Switches_Last); |
3009 | end Linking_Phase; | |
84481f76 | 3010 | |
6367dd30 AC |
3011 | ------------------- |
3012 | -- Binding_Phase -- | |
3013 | ------------------- | |
84481f76 | 3014 | |
315f0c42 | 3015 | procedure Binding_Phase (Main_ALI_File : File_Name_Type) is |
5969611f | 3016 | Args : Argument_List (Binder_Switches.First .. Binder_Switches.Last + 2); |
6367dd30 | 3017 | -- The arguments for the invocation of gnatbind |
84481f76 | 3018 | |
6367dd30 AC |
3019 | Last_Arg : Natural := Binder_Switches.Last; |
3020 | -- Index of the last argument in Args | |
3d3026cf | 3021 | |
6367dd30 AC |
3022 | Shared_Libs : Boolean := False; |
3023 | -- Set to True when there are shared library project files or | |
3024 | -- when gnatbind is invoked with -shared. | |
84481f76 | 3025 | |
6367dd30 | 3026 | begin |
b0f26df5 | 3027 | |
6367dd30 | 3028 | -- Check now for switch -shared |
b0f26df5 | 3029 | |
315f0c42 AC |
3030 | for J in Binder_Switches.First .. Last_Arg loop |
3031 | if Binder_Switches.Table (J).all = "-shared" then | |
3032 | Shared_Libs := True; | |
3033 | exit; | |
3034 | end if; | |
3035 | end loop; | |
b0f26df5 | 3036 | |
6367dd30 AC |
3037 | -- If shared libraries present, invoke gnatlink with |
3038 | -- -shared-libgcc. | |
b0f26df5 | 3039 | |
6367dd30 AC |
3040 | if Shared_Libs then |
3041 | Link_With_Shared_Libgcc := Shared_Libgcc_Switch'Access; | |
3042 | end if; | |
b0f26df5 | 3043 | |
6367dd30 | 3044 | -- Get all the binder switches |
b0f26df5 | 3045 | |
6367dd30 AC |
3046 | for J in Binder_Switches.First .. Last_Arg loop |
3047 | Args (J) := Binder_Switches.Table (J); | |
3048 | end loop; | |
bed8af19 | 3049 | |
92966893 AC |
3050 | if CodePeer_Mode then |
3051 | Last_Arg := Last_Arg + 1; | |
3052 | Args (Last_Arg) := CodePeer_Mode_String'Access; | |
3053 | end if; | |
3054 | ||
315f0c42 | 3055 | -- If gnatmake was invoked with --subdirs, put the |
1e4b91fc AC |
3056 | -- binder generated files in the subdirectory specified. |
3057 | ||
315f0c42 | 3058 | if Subdirs /= null then |
1e4b91fc AC |
3059 | Change_Dir (Object_Directory_Path.all); |
3060 | end if; | |
3061 | ||
315f0c42 | 3062 | Bind (Main_ALI_File, Bind_Shared.all & Args (Args'First .. Last_Arg)); |
64c69860 | 3063 | |
6367dd30 | 3064 | end Binding_Phase; |
056b0f6f | 3065 | |
6367dd30 AC |
3066 | ----------------------- |
3067 | -- Compilation_Phase -- | |
3068 | ----------------------- | |
84481f76 | 3069 | |
6367dd30 AC |
3070 | procedure Compilation_Phase |
3071 | (Main_Source_File : File_Name_Type; | |
3072 | Current_Main_Index : Int := 0; | |
3073 | Total_Compilation_Failures : in out Natural; | |
6367dd30 | 3074 | Executable : File_Name_Type := No_File; |
6367dd30 AC |
3075 | Stop_Compile : out Boolean) |
3076 | is | |
3077 | Args : Argument_List (1 .. Gcc_Switches.Last); | |
6367dd30 AC |
3078 | First_Compiled_File : File_Name_Type; |
3079 | Youngest_Obj_File : File_Name_Type; | |
3080 | Youngest_Obj_Stamp : Time_Stamp_Type; | |
84481f76 | 3081 | |
6367dd30 AC |
3082 | Is_Main_Unit : Boolean; |
3083 | -- Set True by Compile_Sources if Main_Source_File can be a main unit | |
84481f76 | 3084 | |
6367dd30 | 3085 | Compilation_Failures : Natural; |
84481f76 | 3086 | |
6367dd30 | 3087 | Executable_Stamp : Time_Stamp_Type; |
84481f76 | 3088 | |
6367dd30 AC |
3089 | begin |
3090 | Stop_Compile := False; | |
84481f76 | 3091 | |
6367dd30 AC |
3092 | for J in 1 .. Gcc_Switches.Last loop |
3093 | Args (J) := Gcc_Switches.Table (J); | |
3094 | end loop; | |
84481f76 | 3095 | |
6367dd30 AC |
3096 | -- Now we invoke Compile_Sources for the current main |
3097 | ||
3098 | Compile_Sources | |
3099 | (Main_Source => Main_Source_File, | |
3100 | Args => Args, | |
3101 | First_Compiled_File => First_Compiled_File, | |
3102 | Most_Recent_Obj_File => Youngest_Obj_File, | |
3103 | Most_Recent_Obj_Stamp => Youngest_Obj_Stamp, | |
3104 | Main_Unit => Is_Main_Unit, | |
3105 | Main_Index => Current_Main_Index, | |
3106 | Compilation_Failures => Compilation_Failures, | |
3107 | Check_Readonly_Files => Check_Readonly_Files, | |
3108 | Do_Not_Execute => Do_Not_Execute, | |
3109 | Force_Compilations => Force_Compilations, | |
3110 | In_Place_Mode => In_Place_Mode, | |
3111 | Keep_Going => Keep_Going, | |
3112 | Initialize_ALI_Data => True, | |
315f0c42 | 3113 | Max_Process => Maximum_Processes); |
84481f76 | 3114 | |
6367dd30 AC |
3115 | if Verbose_Mode then |
3116 | Write_Str ("End of compilation"); | |
3117 | Write_Eol; | |
3118 | end if; | |
84481f76 | 3119 | |
6367dd30 AC |
3120 | Total_Compilation_Failures := |
3121 | Total_Compilation_Failures + Compilation_Failures; | |
54e03461 | 3122 | |
6367dd30 AC |
3123 | if Total_Compilation_Failures /= 0 then |
3124 | Stop_Compile := True; | |
3125 | return; | |
3126 | end if; | |
54e03461 | 3127 | |
6367dd30 AC |
3128 | if List_Dependencies then |
3129 | if First_Compiled_File /= No_File then | |
3130 | Inform | |
3131 | (First_Compiled_File, | |
3132 | "must be recompiled. Can't generate dependence list."); | |
3133 | else | |
3134 | List_Depend; | |
3135 | end if; | |
84481f76 | 3136 | |
6367dd30 AC |
3137 | elsif First_Compiled_File = No_File |
3138 | and then not Do_Bind_Step | |
3139 | and then not Quiet_Output | |
6367dd30 AC |
3140 | and then Osint.Number_Of_Files = 1 |
3141 | then | |
3142 | Inform (Msg => "objects up to date."); | |
97ed5872 AC |
3143 | Stop_Compile := True; |
3144 | return; | |
84481f76 | 3145 | |
5969611f | 3146 | elsif Do_Not_Execute and then First_Compiled_File /= No_File then |
6367dd30 AC |
3147 | Write_Name (First_Compiled_File); |
3148 | Write_Eol; | |
3149 | end if; | |
84481f76 | 3150 | |
6367dd30 | 3151 | -- Stop after compile step if any of: |
84481f76 | 3152 | |
6367dd30 | 3153 | -- 1) -n (Do_Not_Execute) specified |
84481f76 | 3154 | |
6367dd30 AC |
3155 | -- 2) -M (List_Dependencies) specified (also sets |
3156 | -- Do_Not_Execute above, so this is probably superfluous). | |
0df218a9 | 3157 | |
6367dd30 | 3158 | -- 3) -c (Compile_Only) specified, but not -b (Bind_Only) |
0df218a9 | 3159 | |
6367dd30 | 3160 | -- 4) Made unit cannot be a main unit |
fbf5a39b | 3161 | |
6367dd30 | 3162 | if ((Do_Not_Execute |
5969611f RD |
3163 | or List_Dependencies |
3164 | or not Do_Bind_Step | |
3165 | or not Is_Main_Unit) | |
3166 | and not No_Main_Subprogram | |
3167 | and not Build_Bind_And_Link_Full_Project) | |
3168 | or Unique_Compile | |
6367dd30 AC |
3169 | then |
3170 | Stop_Compile := True; | |
3171 | return; | |
3172 | end if; | |
fbf5a39b | 3173 | |
0319cacc | 3174 | -- If the objects were up-to-date check if the executable file is also |
535a8637 AC |
3175 | -- up-to-date. For now always bind and link in CodePeer mode where there |
3176 | -- is no executable. | |
54e03461 | 3177 | |
535a8637 | 3178 | if not CodePeer_Mode |
315f0c42 | 3179 | and then Do_Link_Step |
6367dd30 AC |
3180 | and then First_Compiled_File = No_File |
3181 | then | |
3182 | Executable_Stamp := File_Stamp (Executable); | |
54e03461 | 3183 | |
6367dd30 | 3184 | if not Executable_Obsolete then |
5969611f | 3185 | Executable_Obsolete := Youngest_Obj_Stamp > Executable_Stamp; |
6367dd30 | 3186 | end if; |
54e03461 | 3187 | |
6367dd30 AC |
3188 | if not Executable_Obsolete then |
3189 | for Index in reverse 1 .. Dependencies.Last loop | |
5969611f RD |
3190 | if Is_In_Obsoleted (Dependencies.Table (Index).Depends_On) then |
3191 | Enter_Into_Obsoleted (Dependencies.Table (Index).This); | |
6367dd30 AC |
3192 | end if; |
3193 | end loop; | |
54e03461 | 3194 | |
6367dd30 AC |
3195 | Executable_Obsolete := Is_In_Obsoleted (Main_Source_File); |
3196 | Dependencies.Init; | |
3197 | end if; | |
54e03461 | 3198 | |
6367dd30 | 3199 | if not Executable_Obsolete then |
54e03461 | 3200 | |
6367dd30 AC |
3201 | -- If no Ada object files obsolete the executable, check |
3202 | -- for younger or missing linker files. | |
54e03461 | 3203 | |
6367dd30 AC |
3204 | Check_Linker_Options |
3205 | (Executable_Stamp, | |
3206 | Youngest_Obj_File, | |
3207 | Youngest_Obj_Stamp); | |
54e03461 | 3208 | |
6367dd30 AC |
3209 | Executable_Obsolete := Youngest_Obj_File /= No_File; |
3210 | end if; | |
54e03461 | 3211 | |
6367dd30 AC |
3212 | -- Return if the executable is up to date and otherwise |
3213 | -- motivate the relink/rebind. | |
84481f76 | 3214 | |
6367dd30 AC |
3215 | if not Executable_Obsolete then |
3216 | if not Quiet_Output then | |
3217 | Inform (Executable, "up to date."); | |
3218 | end if; | |
fbf5a39b | 3219 | |
6367dd30 AC |
3220 | Stop_Compile := True; |
3221 | return; | |
3222 | end if; | |
fbf5a39b | 3223 | |
6367dd30 AC |
3224 | if Executable_Stamp (1) = ' ' then |
3225 | if not No_Main_Subprogram then | |
3226 | Verbose_Msg (Executable, "missing.", Prefix => " "); | |
fbf5a39b | 3227 | end if; |
84481f76 | 3228 | |
6367dd30 AC |
3229 | elsif Youngest_Obj_Stamp (1) = ' ' then |
3230 | Verbose_Msg | |
3231 | (Youngest_Obj_File, "missing.", Prefix => " "); | |
84481f76 | 3232 | |
6367dd30 AC |
3233 | elsif Youngest_Obj_Stamp > Executable_Stamp then |
3234 | Verbose_Msg | |
3235 | (Youngest_Obj_File, | |
3236 | "(" & String (Youngest_Obj_Stamp) & ") newer than", | |
3237 | Executable, | |
3238 | "(" & String (Executable_Stamp) & ")"); | |
84481f76 | 3239 | |
6367dd30 AC |
3240 | else |
3241 | Verbose_Msg | |
3242 | (Executable, "needs to be rebuilt", Prefix => " "); | |
3e2399ba | 3243 | |
6367dd30 | 3244 | end if; |
3e2399ba | 3245 | end if; |
6367dd30 | 3246 | end Compilation_Phase; |
3e2399ba | 3247 | |
6367dd30 AC |
3248 | ------------------------ |
3249 | -- Compute_Executable -- | |
3250 | ------------------------ | |
84481f76 | 3251 | |
6367dd30 AC |
3252 | procedure Compute_Executable |
3253 | (Main_Source_File : File_Name_Type; | |
3254 | Executable : out File_Name_Type; | |
3255 | Non_Std_Executable : out Boolean) | |
3256 | is | |
3257 | begin | |
3258 | Executable := No_File; | |
3259 | Non_Std_Executable := | |
3260 | Targparm.Executable_Extension_On_Target /= No_Name; | |
7ffa903f | 3261 | |
6367dd30 AC |
3262 | -- Look inside the linker switches to see if the name of the final |
3263 | -- executable program was specified. | |
7ffa903f | 3264 | |
6367dd30 AC |
3265 | for J in reverse Linker_Switches.First .. Linker_Switches.Last loop |
3266 | if Linker_Switches.Table (J).all = Output_Flag.all then | |
3267 | pragma Assert (J < Linker_Switches.Last); | |
3c971dcc | 3268 | |
6367dd30 AC |
3269 | -- We cannot specify a single executable for several main |
3270 | -- subprograms | |
07fc65c4 | 3271 | |
6367dd30 AC |
3272 | if Osint.Number_Of_Files > 1 then |
3273 | Fail ("cannot specify a single executable for several mains"); | |
3274 | end if; | |
91c2cbdb | 3275 | |
6367dd30 AC |
3276 | Name_Len := 0; |
3277 | Add_Str_To_Name_Buffer (Linker_Switches.Table (J + 1).all); | |
3278 | Executable := Name_Enter; | |
66713d62 | 3279 | |
6367dd30 AC |
3280 | Verbose_Msg (Executable, "final executable"); |
3281 | end if; | |
3282 | end loop; | |
91c2cbdb | 3283 | |
6367dd30 AC |
3284 | -- If the name of the final executable program was not specified then |
3285 | -- construct it from the main input file. | |
07fc65c4 | 3286 | |
6367dd30 | 3287 | if Executable = No_File then |
315f0c42 | 3288 | Executable := Executable_Name (Strip_Suffix (Main_Source_File)); |
15cf0748 VC |
3289 | end if; |
3290 | ||
6367dd30 | 3291 | end Compute_Executable; |
aa720a54 | 3292 | |
6367dd30 AC |
3293 | -------------- |
3294 | -- Gnatmake -- | |
3295 | -------------- | |
fbf5a39b | 3296 | |
6367dd30 AC |
3297 | procedure Gnatmake is |
3298 | Main_Source_File : File_Name_Type; | |
3299 | -- The source file containing the main compilation unit | |
66713d62 | 3300 | |
6367dd30 | 3301 | Total_Compilation_Failures : Natural := 0; |
fbf5a39b | 3302 | |
6367dd30 AC |
3303 | Main_ALI_File : File_Name_Type; |
3304 | -- The ali file corresponding to Main_Source_File | |
a7ab2998 | 3305 | |
6367dd30 AC |
3306 | Executable : File_Name_Type := No_File; |
3307 | -- The file name of an executable | |
a7ab2998 | 3308 | |
6367dd30 AC |
3309 | Non_Std_Executable : Boolean := False; |
3310 | -- Non_Std_Executable is set to True when there is a possibility that | |
3311 | -- the linker will not choose the correct executable file name. | |
66713d62 | 3312 | |
6367dd30 AC |
3313 | Current_Main_Index : Int := 0; |
3314 | -- If not zero, the index of the current main unit in its source file | |
a7ab2998 | 3315 | |
1ab4a286 EB |
3316 | Is_First_Main : Boolean; |
3317 | -- Whether we are processing the first main | |
3318 | ||
6367dd30 | 3319 | Stop_Compile : Boolean; |
f2c573b1 | 3320 | |
6367dd30 AC |
3321 | Discard : Boolean; |
3322 | pragma Warnings (Off, Discard); | |
f2c573b1 | 3323 | |
6367dd30 AC |
3324 | begin |
3325 | Install_Int_Handler (Sigint_Intercepted'Access); | |
84481f76 | 3326 | |
6367dd30 AC |
3327 | Do_Compile_Step := True; |
3328 | Do_Bind_Step := True; | |
3329 | Do_Link_Step := True; | |
84481f76 | 3330 | |
6367dd30 | 3331 | Obsoleted.Reset; |
84481f76 | 3332 | |
315f0c42 | 3333 | Make.Initialize; |
84481f76 | 3334 | |
6367dd30 AC |
3335 | Bind_Shared := No_Shared_Switch'Access; |
3336 | Link_With_Shared_Libgcc := No_Shared_Libgcc_Switch'Access; | |
84481f76 | 3337 | |
6367dd30 AC |
3338 | Failed_Links.Set_Last (0); |
3339 | Successful_Links.Set_Last (0); | |
84481f76 | 3340 | |
6367dd30 | 3341 | -- Special case when switch -B was specified |
84481f76 | 3342 | |
315f0c42 | 3343 | if Main_Index /= 0 and then Osint.Number_Of_Files > 1 then |
6367dd30 | 3344 | Make_Failed ("cannot specify several mains with a multi-unit index"); |
6367dd30 | 3345 | end if; |
fbf5a39b | 3346 | |
6367dd30 AC |
3347 | if Verbose_Mode then |
3348 | Write_Eol; | |
ac401891 | 3349 | Display_Version ("GNATMAKE", "1992"); |
6367dd30 | 3350 | end if; |
fbf5a39b | 3351 | |
6367dd30 | 3352 | if Osint.Number_Of_Files = 0 then |
315f0c42 AC |
3353 | -- Call Get_Target_Parameters to ensure that flags are properly |
3354 | -- set before calling Usage. | |
fbf5a39b | 3355 | |
315f0c42 | 3356 | Targparm.Get_Target_Parameters; |
fbf5a39b | 3357 | |
315f0c42 | 3358 | -- Output usage information if no argument on the command line |
f5552c89 | 3359 | |
315f0c42 AC |
3360 | if Argument_Count = 0 then |
3361 | Usage; | |
6367dd30 | 3362 | else |
315f0c42 | 3363 | Try_Help; |
6367dd30 | 3364 | end if; |
315f0c42 AC |
3365 | |
3366 | Finish_Program (E_Success); | |
6367dd30 | 3367 | end if; |
fbf5a39b | 3368 | |
6367dd30 AC |
3369 | -- Get the first executable. |
3370 | -- ??? This needs to be done early, because Osint.Next_Main_File also | |
23cc1ace | 3371 | -- initializes the primary search directory, used below to initialize |
6367dd30 | 3372 | -- the "-I" parameter |
fbf5a39b | 3373 | |
6367dd30 | 3374 | Main_Source_File := Next_Main_Source; -- No directory information |
fbf5a39b | 3375 | |
6367dd30 | 3376 | -- If -M was specified, behave as if -n was specified |
84481f76 | 3377 | |
6367dd30 AC |
3378 | if List_Dependencies then |
3379 | Do_Not_Execute := True; | |
3380 | end if; | |
66713d62 | 3381 | |
315f0c42 | 3382 | Add_Switch ("-I-", Compiler); |
f5552c89 | 3383 | |
315f0c42 AC |
3384 | if Look_In_Primary_Dir then |
3385 | Add_Switch | |
3386 | ("-I" & | |
3387 | Normalize_Directory_Name | |
3388 | (Get_Primary_Src_Search_Directory.all).all, | |
3389 | Compiler, | |
3390 | Append_Switch => False); | |
84481f76 | 3391 | |
6367dd30 | 3392 | end if; |
84481f76 | 3393 | |
6367dd30 AC |
3394 | -- If the user wants a program without a main subprogram, add the |
3395 | -- appropriate switch to the binder. | |
84481f76 | 3396 | |
6367dd30 | 3397 | if No_Main_Subprogram then |
315f0c42 | 3398 | Add_Switch ("-z", Binder); |
6367dd30 | 3399 | end if; |
84481f76 | 3400 | |
6367dd30 AC |
3401 | -- The combination of -f -u and one or several mains on the command line |
3402 | -- implies -a. | |
fbf5a39b | 3403 | |
6367dd30 AC |
3404 | if Force_Compilations |
3405 | and then Unique_Compile | |
6367dd30 | 3406 | and then Main_On_Command_Line |
315f0c42 AC |
3407 | then |
3408 | Must_Compile := True; | |
6367dd30 | 3409 | end if; |
84481f76 | 3410 | |
6367dd30 | 3411 | Bad_Compilation.Init; |
84481f76 | 3412 | |
6367dd30 | 3413 | -- Here is where the make process is started |
84481f76 | 3414 | |
315f0c42 | 3415 | Queue.Initialize; |
84481f76 | 3416 | |
1ab4a286 EB |
3417 | Is_First_Main := True; |
3418 | ||
6367dd30 AC |
3419 | Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop |
3420 | if Current_File_Index /= No_Index then | |
3421 | Main_Index := Current_File_Index; | |
3422 | end if; | |
fbf5a39b | 3423 | |
6367dd30 | 3424 | Current_Main_Index := Main_Index; |
fbf5a39b | 3425 | |
d3cb4cc0 | 3426 | if Is_First_Main then |
164e06c6 AC |
3427 | |
3428 | -- Put the default source dirs in the source path only now, so | |
3429 | -- that we take the correct ones in the case where --RTS= is | |
d3cb4cc0 AC |
3430 | -- specified in the Builder switches. |
3431 | ||
3432 | Osint.Add_Default_Search_Dirs; | |
3433 | ||
3434 | -- Get the target parameters, which are only needed for a couple | |
3435 | -- of cases in gnatmake. Protect against an exception, such as the | |
3436 | -- case of system.ads missing from the library, and fail | |
3437 | -- gracefully. | |
3438 | ||
3439 | begin | |
3440 | Targparm.Get_Target_Parameters; | |
3441 | exception | |
3442 | when Unrecoverable_Error => | |
3443 | Make_Failed ("*** make failed."); | |
3444 | end; | |
3445 | ||
67645bde AC |
3446 | Gcc_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all); |
3447 | Gnatbind_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all); | |
3448 | Gnatlink_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all); | |
3449 | ||
3e24afaa AC |
3450 | -- If we have specified -j switch both from the project file |
3451 | -- and on the command line, the one from the command line takes | |
3452 | -- precedence. | |
3453 | ||
3e24afaa AC |
3454 | if Debug.Debug_Flag_M then |
3455 | Write_Line ("Maximum number of simultaneous compilations =" & | |
315f0c42 | 3456 | Maximum_Processes'Img); |
3e24afaa AC |
3457 | end if; |
3458 | ||
3459 | -- Allocate as many temporary mapping file names as the maximum | |
315f0c42 | 3460 | -- number of compilations processed. |
3e24afaa | 3461 | |
315f0c42 AC |
3462 | The_Mapping_Files := |
3463 | (Mapping_File_Names => | |
3464 | new Temp_Path_Names (1 .. Maximum_Processes), | |
3465 | Last_Mapping_File_Names => 0, | |
3466 | Free_Mapping_File_Indexes => | |
3467 | new Free_File_Indexes (1 .. Maximum_Processes), | |
3468 | Last_Free_Indexes => 0); | |
5d59eef2 | 3469 | |
d3cb4cc0 AC |
3470 | Is_First_Main := False; |
3471 | end if; | |
3472 | ||
6367dd30 | 3473 | Executable_Obsolete := False; |
fbf5a39b | 3474 | |
6367dd30 AC |
3475 | Compute_Executable |
3476 | (Main_Source_File => Main_Source_File, | |
3477 | Executable => Executable, | |
3478 | Non_Std_Executable => Non_Std_Executable); | |
fbf5a39b | 3479 | |
6367dd30 AC |
3480 | if Do_Compile_Step then |
3481 | Compilation_Phase | |
3482 | (Main_Source_File => Main_Source_File, | |
3483 | Current_Main_Index => Current_Main_Index, | |
3484 | Total_Compilation_Failures => Total_Compilation_Failures, | |
6367dd30 | 3485 | Executable => Executable, |
6367dd30 AC |
3486 | Stop_Compile => Stop_Compile); |
3487 | ||
3488 | if Stop_Compile then | |
3489 | if Total_Compilation_Failures /= 0 then | |
3490 | if Keep_Going then | |
3491 | goto Next_Main; | |
fbf5a39b | 3492 | |
6367dd30 AC |
3493 | else |
3494 | List_Bad_Compilations; | |
3495 | Report_Compilation_Failed; | |
fbf5a39b AC |
3496 | end if; |
3497 | ||
6367dd30 AC |
3498 | elsif Osint.Number_Of_Files = 1 then |
3499 | exit Multiple_Main_Loop; | |
3500 | else | |
3501 | goto Next_Main; | |
3502 | end if; | |
3503 | end if; | |
3504 | end if; | |
fbf5a39b | 3505 | |
6367dd30 AC |
3506 | -- If we are here, it means that we need to rebuilt the current main, |
3507 | -- so we set Executable_Obsolete to True to make sure that subsequent | |
3508 | -- mains will be rebuilt. | |
757240b3 | 3509 | |
6367dd30 AC |
3510 | Main_ALI_In_Place_Mode_Step : declare |
3511 | ALI_File : File_Name_Type; | |
3512 | Src_File : File_Name_Type; | |
fbf5a39b | 3513 | |
6367dd30 AC |
3514 | begin |
3515 | Src_File := Strip_Directory (Main_Source_File); | |
3516 | ALI_File := Lib_File_Name (Src_File, Current_Main_Index); | |
3517 | Main_ALI_File := Full_Lib_File_Name (ALI_File); | |
fbf5a39b | 3518 | |
6367dd30 AC |
3519 | -- When In_Place_Mode, the library file can be located in the |
3520 | -- Main_Source_File directory which may not be present in the | |
3521 | -- library path. If it is not present then use the corresponding | |
3522 | -- library file name. | |
fbf5a39b | 3523 | |
6367dd30 AC |
3524 | if Main_ALI_File = No_File and then In_Place_Mode then |
3525 | Get_Name_String (Get_Directory (Full_Source_Name (Src_File))); | |
3526 | Get_Name_String_And_Append (ALI_File); | |
3527 | Main_ALI_File := Name_Find; | |
3528 | Main_ALI_File := Full_Lib_File_Name (Main_ALI_File); | |
3529 | end if; | |
fbf5a39b | 3530 | |
6367dd30 AC |
3531 | if Main_ALI_File = No_File then |
3532 | Make_Failed ("could not find the main ALI file"); | |
84481f76 | 3533 | end if; |
6367dd30 AC |
3534 | end Main_ALI_In_Place_Mode_Step; |
3535 | ||
3536 | if Do_Bind_Step then | |
315f0c42 | 3537 | Binding_Phase (Main_ALI_File); |
6367dd30 AC |
3538 | end if; |
3539 | ||
3540 | if Do_Link_Step then | |
3541 | Linking_Phase | |
3542 | (Non_Std_Executable => Non_Std_Executable, | |
3543 | Executable => Executable, | |
3544 | Main_ALI_File => Main_ALI_File); | |
84481f76 | 3545 | end if; |
6b6fcd3e | 3546 | |
6367dd30 AC |
3547 | -- We go to here when we skip the bind and link steps |
3548 | ||
3549 | <<Next_Main>> | |
3550 | ||
e280f981 | 3551 | Queue.Remove_Marks; |
6367dd30 AC |
3552 | |
3553 | if N_File < Osint.Number_Of_Files then | |
3554 | Main_Source_File := Next_Main_Source; -- No directory information | |
3555 | end if; | |
84481f76 RK |
3556 | end loop Multiple_Main_Loop; |
3557 | ||
fbf5a39b AC |
3558 | if Failed_Links.Last > 0 then |
3559 | for Index in 1 .. Successful_Links.Last loop | |
3560 | Write_Str ("Linking of """); | |
3561 | Write_Str (Get_Name_String (Successful_Links.Table (Index))); | |
3562 | Write_Line (""" succeeded."); | |
3563 | end loop; | |
3564 | ||
d3cc6a32 AC |
3565 | Set_Standard_Error; |
3566 | ||
fbf5a39b AC |
3567 | for Index in 1 .. Failed_Links.Last loop |
3568 | Write_Str ("Linking of """); | |
3569 | Write_Str (Get_Name_String (Failed_Links.Table (Index))); | |
3570 | Write_Line (""" failed."); | |
3571 | end loop; | |
3572 | ||
d3cc6a32 AC |
3573 | if Commands_To_Stdout then |
3574 | Set_Standard_Output; | |
3575 | end if; | |
3576 | ||
fbf5a39b | 3577 | if Total_Compilation_Failures = 0 then |
d3cc6a32 | 3578 | Report_Compilation_Failed; |
fbf5a39b AC |
3579 | end if; |
3580 | end if; | |
3581 | ||
07fc65c4 GB |
3582 | if Total_Compilation_Failures /= 0 then |
3583 | List_Bad_Compilations; | |
d3cc6a32 | 3584 | Report_Compilation_Failed; |
07fc65c4 GB |
3585 | end if; |
3586 | ||
315f0c42 | 3587 | Finish_Program (E_Success); |
ce09f8b3 | 3588 | |
84481f76 | 3589 | exception |
84481f76 | 3590 | when X : others => |
d3cc6a32 | 3591 | Set_Standard_Error; |
84481f76 | 3592 | Write_Line (Exception_Information (X)); |
fbf5a39b | 3593 | Make_Failed ("INTERNAL ERROR. Please report."); |
84481f76 RK |
3594 | end Gnatmake; |
3595 | ||
fbf5a39b AC |
3596 | ---------- |
3597 | -- Hash -- | |
3598 | ---------- | |
3599 | ||
d3cc6a32 | 3600 | function Hash (F : File_Name_Type) return Header_Num is |
fbf5a39b AC |
3601 | begin |
3602 | return Header_Num (1 + F mod Max_Header); | |
3603 | end Hash; | |
3604 | ||
84481f76 RK |
3605 | -------------------- |
3606 | -- In_Ada_Lib_Dir -- | |
3607 | -------------------- | |
3608 | ||
3609 | function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean is | |
d3cc6a32 AC |
3610 | D : constant File_Name_Type := Get_Directory (File); |
3611 | B : constant Byte := Get_Name_Table_Byte (D); | |
84481f76 RK |
3612 | begin |
3613 | return (B and Ada_Lib_Dir) /= 0; | |
3614 | end In_Ada_Lib_Dir; | |
3615 | ||
07fc65c4 GB |
3616 | ----------------------- |
3617 | -- Init_Mapping_File -- | |
3618 | ----------------------- | |
3619 | ||
ae71d81b | 3620 | procedure Init_Mapping_File (File_Index : out Natural) is |
d3cc6a32 | 3621 | FD : File_Descriptor; |
fbf5a39b AC |
3622 | Status : Boolean; |
3623 | -- For call to Close | |
3624 | ||
07fc65c4 | 3625 | begin |
fbf5a39b | 3626 | -- Increase the index of the last mapping file for this project |
07fc65c4 | 3627 | |
315f0c42 AC |
3628 | The_Mapping_Files.Last_Mapping_File_Names := |
3629 | The_Mapping_Files.Last_Mapping_File_Names + 1; | |
07fc65c4 | 3630 | |
315f0c42 | 3631 | -- Just create an empty file |
fbf5a39b | 3632 | |
315f0c42 AC |
3633 | Tempdir.Create_Temp_File |
3634 | (FD, | |
3635 | The_Mapping_Files.Mapping_File_Names | |
3636 | (The_Mapping_Files.Last_Mapping_File_Names)); | |
fbf5a39b | 3637 | |
315f0c42 AC |
3638 | if FD = Invalid_FD then |
3639 | Make_Failed ("disk full"); | |
fbf5a39b | 3640 | else |
315f0c42 AC |
3641 | Record_Temp_File |
3642 | (The_Mapping_Files.Mapping_File_Names | |
3643 | (The_Mapping_Files.Last_Mapping_File_Names)); | |
3644 | end if; | |
07fc65c4 | 3645 | |
315f0c42 | 3646 | Close (FD, Status); |
fbf5a39b | 3647 | |
315f0c42 AC |
3648 | if not Status then |
3649 | Make_Failed ("disk full"); | |
07fc65c4 | 3650 | end if; |
fbf5a39b AC |
3651 | |
3652 | -- And return the index of the newly created file | |
3653 | ||
315f0c42 | 3654 | File_Index := The_Mapping_Files.Last_Mapping_File_Names; |
07fc65c4 GB |
3655 | end Init_Mapping_File; |
3656 | ||
84481f76 RK |
3657 | ---------------- |
3658 | -- Initialize -- | |
3659 | ---------------- | |
3660 | ||
315f0c42 | 3661 | procedure Initialize is |
f5552c89 | 3662 | procedure Check_Version_And_Help is |
5969611f | 3663 | new Check_Version_And_Help_G (Makeusg); |
f5552c89 | 3664 | |
84481f76 | 3665 | begin |
f5552c89 GD |
3666 | -- Override default initialization of Check_Object_Consistency since |
3667 | -- this is normally False for GNATBIND, but is True for GNATMAKE since | |
3668 | -- we do not need to check source consistency again once GNATMAKE has | |
3669 | -- looked at the sources to check. | |
84481f76 | 3670 | |
b7e429ab | 3671 | Check_Object_Consistency := True; |
84481f76 | 3672 | |
498d1b80 | 3673 | -- Package initializations (the order of calls is important here) |
84481f76 RK |
3674 | |
3675 | Output.Set_Standard_Error; | |
84481f76 RK |
3676 | |
3677 | Gcc_Switches.Init; | |
3678 | Binder_Switches.Init; | |
3679 | Linker_Switches.Init; | |
3680 | ||
3681 | Csets.Initialize; | |
84481f76 | 3682 | Snames.Initialize; |
308aab0b | 3683 | Stringt.Initialize; |
84481f76 | 3684 | |
fbf5a39b AC |
3685 | Dependencies.Init; |
3686 | ||
3687 | RTS_Specified := null; | |
305418c8 | 3688 | N_M_Switch := 0; |
fbf5a39b | 3689 | |
b0f26df5 AC |
3690 | Mains.Delete; |
3691 | ||
cafdbd2e AC |
3692 | -- Add the directory where gnatmake is invoked in front of the path, |
3693 | -- if gnatmake is invoked from a bin directory or with directory | |
62883e6b | 3694 | -- information. |
5453d5bd | 3695 | |
62883e6b AC |
3696 | declare |
3697 | Prefix : constant String := Executable_Prefix_Path; | |
3698 | Command : constant String := Command_Name; | |
cc335f43 | 3699 | |
62883e6b AC |
3700 | begin |
3701 | if Prefix'Length > 0 then | |
3702 | declare | |
3703 | PATH : constant String := | |
ea0c8cfb RD |
3704 | Prefix & Directory_Separator & "bin" & Path_Separator |
3705 | & Getenv ("PATH").all; | |
62883e6b AC |
3706 | begin |
3707 | Setenv ("PATH", PATH); | |
3708 | end; | |
5453d5bd | 3709 | |
62883e6b AC |
3710 | else |
3711 | for Index in reverse Command'Range loop | |
3712 | if Command (Index) = Directory_Separator then | |
3713 | declare | |
3714 | Absolute_Dir : constant String := | |
3715 | Normalize_Pathname | |
3716 | (Command (Command'First .. Index)); | |
3717 | PATH : constant String := | |
3718 | Absolute_Dir & | |
3719 | Path_Separator & | |
3720 | Getenv ("PATH").all; | |
3721 | begin | |
3722 | Setenv ("PATH", PATH); | |
3723 | end; | |
5453d5bd | 3724 | |
62883e6b AC |
3725 | exit; |
3726 | end if; | |
3727 | end loop; | |
3728 | end if; | |
3729 | end; | |
5453d5bd AC |
3730 | |
3731 | -- Scan the switches and arguments | |
3732 | ||
41c8951a | 3733 | -- First, scan to detect --version and/or --help |
f86eb278 | 3734 | |
f5552c89 | 3735 | Check_Version_And_Help ("GNATMAKE", "1995"); |
f86eb278 | 3736 | |
f5552c89 GD |
3737 | -- Scan again the switch and arguments, now that we are sure that they |
3738 | -- do not include --version or --help. | |
f86eb278 | 3739 | |
0c61772a AC |
3740 | -- First, check for switch -P and, if found and gprbuild is available, |
3741 | -- silently invoke gprbuild, with switch --target if not on a native | |
3742 | -- platform. | |
ccd6f414 | 3743 | |
0c61772a | 3744 | declare |
fb8d37ef | 3745 | Arg_Len : Natural := Argument_Count; |
0c61772a AC |
3746 | Call_Gprbuild : Boolean := False; |
3747 | Gprbuild : String_Access := null; | |
3748 | Pos : Natural := 0; | |
3749 | Success : Boolean; | |
3750 | Target : String_Access := null; | |
ccd6f414 | 3751 | |
5e9cb404 AC |
3752 | In_Gnatmake_Switches : Boolean := True; |
3753 | -- Set to False after -cargs, -bargs, or -largs, to avoid detecting | |
3754 | -- -P switches that are not for gnatmake. | |
3755 | ||
0c61772a AC |
3756 | begin |
3757 | Find_Program_Name; | |
3758 | ||
3759 | if Name_Len >= 8 | |
3760 | and then Name_Buffer (Name_Len - 7 .. Name_Len) = "gnatmake" | |
3761 | then | |
315f0c42 | 3762 | if Name_Len > 9 then |
0c61772a AC |
3763 | Target := new String'(Name_Buffer (1 .. Name_Len - 9)); |
3764 | Arg_Len := Arg_Len + 1; | |
3765 | end if; | |
ccd6f414 | 3766 | |
ccd6f414 AC |
3767 | for J in 1 .. Argument_Count loop |
3768 | declare | |
3769 | Arg : constant String := Argument (J); | |
3770 | begin | |
5e9cb404 AC |
3771 | if Arg = "-cargs" or Arg = "-bargs" or Arg = "-largs" then |
3772 | In_Gnatmake_Switches := False; | |
3773 | ||
3774 | elsif Arg = "-margs" then | |
3775 | In_Gnatmake_Switches := True; | |
3776 | ||
3777 | elsif In_Gnatmake_Switches | |
3778 | and then Arg'Length >= 2 | |
ccd6f414 AC |
3779 | and then Arg (Arg'First .. Arg'First + 1) = "-P" |
3780 | then | |
3781 | Call_Gprbuild := True; | |
3782 | exit; | |
3783 | end if; | |
3784 | end; | |
3785 | end loop; | |
3786 | ||
3787 | if Call_Gprbuild then | |
0c61772a AC |
3788 | Gprbuild := Locate_Exec_On_Path (Exec_Name => "gprbuild"); |
3789 | ||
315f0c42 AC |
3790 | if Gprbuild = null then |
3791 | Fail_Program | |
e42183e7 | 3792 | ("project files are no longer supported by gnatmake;" & |
315f0c42 AC |
3793 | " use gprbuild instead"); |
3794 | end if; | |
ccd6f414 | 3795 | |
315f0c42 AC |
3796 | declare |
3797 | Args : Argument_List (1 .. Arg_Len); | |
3798 | begin | |
3799 | if Target /= null then | |
3800 | Args (1) := new String'("--target=" & Target.all); | |
3801 | Pos := 1; | |
3802 | end if; | |
ccd6f414 | 3803 | |
315f0c42 AC |
3804 | for J in 1 .. Argument_Count loop |
3805 | Pos := Pos + 1; | |
3806 | Args (Pos) := new String'(Argument (J)); | |
3807 | end loop; | |
ccd6f414 | 3808 | |
315f0c42 | 3809 | Spawn (Gprbuild.all, Args, Success); |
ccd6f414 | 3810 | |
315f0c42 AC |
3811 | Free (Gprbuild); |
3812 | ||
3813 | if Success then | |
3814 | Exit_Program (E_Success); | |
3815 | else | |
3816 | Exit_Program (E_Errors); | |
3817 | end if; | |
3818 | end; | |
ccd6f414 | 3819 | end if; |
0c61772a AC |
3820 | end if; |
3821 | end; | |
ccd6f414 | 3822 | |
41c8951a | 3823 | Scan_Args : for Next_Arg in 1 .. Argument_Count loop |
315f0c42 | 3824 | Scan_Make_Arg (Argument (Next_Arg)); |
41c8951a | 3825 | end loop Scan_Args; |
84481f76 | 3826 | |
315f0c42 AC |
3827 | if Make_Steps then |
3828 | Do_Compile_Step := Compile_Only; | |
3829 | Do_Bind_Step := Bind_Only; | |
3830 | Do_Link_Step := Link_Only; | |
3831 | ||
3832 | if Do_Compile_Step and then Do_Link_Step then | |
3833 | Do_Bind_Step := True; | |
3834 | end if; | |
3835 | end if; | |
3836 | ||
305418c8 | 3837 | if N_M_Switch > 0 and RTS_Specified = null then |
315f0c42 | 3838 | Process_Multilib; |
305418c8 LG |
3839 | end if; |
3840 | ||
d3cc6a32 AC |
3841 | if Commands_To_Stdout then |
3842 | Set_Standard_Output; | |
3843 | end if; | |
3844 | ||
84481f76 | 3845 | if Usage_Requested then |
6c1e24d3 | 3846 | Usage; |
84481f76 RK |
3847 | end if; |
3848 | ||
fbf5a39b AC |
3849 | -- Test for trailing -P switch |
3850 | ||
3851 | if Project_File_Name_Present and then Project_File_Name = null then | |
3852 | Make_Failed ("project file name missing after -P"); | |
3853 | ||
84481f76 RK |
3854 | -- Test for trailing -o switch |
3855 | ||
a21d245c | 3856 | elsif Output_File_Name_Present and then not Output_File_Name_Seen then |
fbf5a39b AC |
3857 | Make_Failed ("output file name missing after -o"); |
3858 | ||
3859 | -- Test for trailing -D switch | |
3860 | ||
a21d245c | 3861 | elsif Object_Directory_Present and then not Object_Directory_Seen then |
fbf5a39b AC |
3862 | Make_Failed ("object directory missing after -D"); |
3863 | end if; | |
3864 | ||
3865 | -- Test for simultaneity of -i and -D | |
3866 | ||
3867 | if Object_Directory_Path /= null and then In_Place_Mode then | |
ad6b5b00 | 3868 | Make_Failed ("-i and -D cannot be used simultaneously"); |
fbf5a39b AC |
3869 | end if; |
3870 | ||
0187b60e AC |
3871 | -- If --subdirs= is specified, but not -P, this is equivalent to -D, |
3872 | -- except that the directory is created if it does not exist. | |
3873 | ||
315f0c42 | 3874 | if Subdirs /= null then |
0187b60e AC |
3875 | if Object_Directory_Path /= null then |
3876 | Make_Failed ("--subdirs and -D cannot be used simultaneously"); | |
3877 | ||
3878 | elsif In_Place_Mode then | |
3879 | Make_Failed ("--subdirs and -i cannot be used simultaneously"); | |
3880 | ||
3881 | else | |
315f0c42 | 3882 | if not Is_Directory (Subdirs.all) then |
0187b60e | 3883 | begin |
315f0c42 | 3884 | Ada.Directories.Create_Path (Subdirs.all); |
0187b60e AC |
3885 | exception |
3886 | when others => | |
3887 | Make_Failed ("unable to create object directory " & | |
315f0c42 | 3888 | Subdirs.all); |
0187b60e AC |
3889 | end; |
3890 | end if; | |
3891 | ||
3892 | Object_Directory_Present := True; | |
3893 | ||
3894 | declare | |
315f0c42 AC |
3895 | Argv : constant String (1 .. Subdirs'Length) := |
3896 | Subdirs.all; | |
0187b60e | 3897 | begin |
315f0c42 | 3898 | Scan_Make_Arg (Argv); |
0187b60e AC |
3899 | end; |
3900 | end if; | |
3901 | end if; | |
3902 | ||
fbf5a39b AC |
3903 | -- Deal with -C= switch |
3904 | ||
3905 | if Gnatmake_Mapping_File /= null then | |
f5552c89 | 3906 | |
fbf5a39b AC |
3907 | -- First, check compatibility with other switches |
3908 | ||
315f0c42 | 3909 | if Maximum_Processes > 1 then |
fbf5a39b AC |
3910 | Make_Failed ("-C= switch is not compatible with -jnnn switch"); |
3911 | end if; | |
3912 | ||
3913 | Fmap.Initialize (Gnatmake_Mapping_File.all); | |
3914 | Add_Switch | |
3915 | ("-gnatem=" & Gnatmake_Mapping_File.all, | |
315f0c42 | 3916 | Compiler); |
84481f76 RK |
3917 | end if; |
3918 | ||
315f0c42 | 3919 | Osint.Add_Default_Search_Dirs; |
84481f76 | 3920 | |
315f0c42 AC |
3921 | -- Source file lookups should be cached for efficiency. Source files |
3922 | -- are not supposed to change. However, we do that now only if no | |
3923 | -- project file is used; if a project file is used, we do it just | |
3924 | -- after changing the directory to the object directory. | |
84481f76 | 3925 | |
315f0c42 | 3926 | Osint.Source_File_Data (Cache => True); |
84481f76 | 3927 | |
315f0c42 | 3928 | -- Read gnat.adc file to initialize Fname.UF |
84481f76 | 3929 | |
315f0c42 | 3930 | Fname.UF.Initialize; |
84481f76 | 3931 | |
315f0c42 AC |
3932 | if Config_File then |
3933 | begin | |
3934 | Fname.SF.Read_Source_File_Name_Pragmas; | |
fbf5a39b | 3935 | |
315f0c42 AC |
3936 | exception |
3937 | when Err : SFN_Scan.Syntax_Error_In_GNAT_ADC => | |
3938 | Make_Failed (Exception_Message (Err)); | |
3939 | end; | |
fbf5a39b | 3940 | end if; |
6c1e24d3 | 3941 | |
b330e3c8 AC |
3942 | if Debug.Debug_Flag_N then |
3943 | Opt.Keep_Temporary_Files := True; | |
3944 | end if; | |
84481f76 RK |
3945 | end Initialize; |
3946 | ||
fbf5a39b AC |
3947 | --------------------- |
3948 | -- Is_In_Obsoleted -- | |
3949 | --------------------- | |
3950 | ||
d3cc6a32 | 3951 | function Is_In_Obsoleted (F : File_Name_Type) return Boolean is |
fbf5a39b AC |
3952 | begin |
3953 | if F = No_File then | |
3954 | return False; | |
3955 | ||
3956 | else | |
3957 | declare | |
91b1417d | 3958 | Name : constant String := Get_Name_String (F); |
d3cc6a32 AC |
3959 | First : Natural; |
3960 | F2 : File_Name_Type; | |
fbf5a39b AC |
3961 | |
3962 | begin | |
d3cc6a32 | 3963 | First := Name'Last; |
fbf5a39b | 3964 | while First > Name'First |
43c58950 | 3965 | and then not Is_Directory_Separator (Name (First - 1)) |
fbf5a39b AC |
3966 | loop |
3967 | First := First - 1; | |
3968 | end loop; | |
3969 | ||
3970 | if First /= Name'First then | |
3971 | Name_Len := 0; | |
3972 | Add_Str_To_Name_Buffer (Name (First .. Name'Last)); | |
3973 | F2 := Name_Find; | |
f86eb278 | 3974 | |
d3cc6a32 AC |
3975 | else |
3976 | F2 := F; | |
fbf5a39b AC |
3977 | end if; |
3978 | ||
3979 | return Obsoleted.Get (F2); | |
3980 | end; | |
3981 | end if; | |
3982 | end Is_In_Obsoleted; | |
3983 | ||
84481f76 RK |
3984 | ---------- |
3985 | -- Link -- | |
3986 | ---------- | |
3987 | ||
d3cc6a32 AC |
3988 | procedure Link |
3989 | (ALI_File : File_Name_Type; | |
3990 | Args : Argument_List; | |
3991 | Success : out Boolean) | |
3992 | is | |
fbf5a39b | 3993 | Link_Args : Argument_List (1 .. Args'Length + 1); |
84481f76 RK |
3994 | |
3995 | begin | |
84481f76 | 3996 | Get_Name_String (ALI_File); |
fbf5a39b AC |
3997 | Link_Args (1) := new String'(Name_Buffer (1 .. Name_Len)); |
3998 | ||
c8307596 | 3999 | Link_Args (2 .. Args'Length + 1) := Args; |
84481f76 | 4000 | |
f86eb278 | 4001 | GNAT.OS_Lib.Normalize_Arguments (Link_Args); |
07fc65c4 | 4002 | |
84481f76 RK |
4003 | Display (Gnatlink.all, Link_Args); |
4004 | ||
4005 | if Gnatlink_Path = null then | |
3dd9959c | 4006 | Make_Failed ("error, unable to locate " & Gnatlink.all); |
84481f76 RK |
4007 | end if; |
4008 | ||
f86eb278 | 4009 | GNAT.OS_Lib.Spawn (Gnatlink_Path.all, Link_Args, Success); |
84481f76 RK |
4010 | end Link; |
4011 | ||
4012 | --------------------------- | |
4013 | -- List_Bad_Compilations -- | |
4014 | --------------------------- | |
4015 | ||
4016 | procedure List_Bad_Compilations is | |
4017 | begin | |
3849c246 | 4018 | if not No_Exit_Message then |
16b10ccc AC |
4019 | for J in Bad_Compilation.First .. Bad_Compilation.Last loop |
4020 | if Bad_Compilation.Table (J).File = No_File then | |
4021 | null; | |
4022 | elsif not Bad_Compilation.Table (J).Found then | |
4023 | Inform (Bad_Compilation.Table (J).File, "not found"); | |
4024 | else | |
4025 | Inform (Bad_Compilation.Table (J).File, "compilation error"); | |
4026 | end if; | |
4027 | end loop; | |
4028 | end if; | |
84481f76 RK |
4029 | end List_Bad_Compilations; |
4030 | ||
4031 | ----------------- | |
4032 | -- List_Depend -- | |
4033 | ----------------- | |
4034 | ||
4035 | procedure List_Depend is | |
d3cc6a32 AC |
4036 | Lib_Name : File_Name_Type; |
4037 | Obj_Name : File_Name_Type; | |
4038 | Src_Name : File_Name_Type; | |
84481f76 RK |
4039 | |
4040 | Len : Natural; | |
4041 | Line_Pos : Natural; | |
4042 | Line_Size : constant := 77; | |
4043 | ||
4044 | begin | |
4045 | Set_Standard_Output; | |
4046 | ||
4047 | for A in ALIs.First .. ALIs.Last loop | |
4048 | Lib_Name := ALIs.Table (A).Afile; | |
4049 | ||
4050 | -- We have to provide the full library file name in In_Place_Mode | |
4051 | ||
b7e429ab | 4052 | if In_Place_Mode then |
84481f76 RK |
4053 | Lib_Name := Full_Lib_File_Name (Lib_Name); |
4054 | end if; | |
4055 | ||
4056 | Obj_Name := Object_File_Name (Lib_Name); | |
4057 | Write_Name (Obj_Name); | |
4058 | Write_Str (" :"); | |
4059 | ||
4060 | Get_Name_String (Obj_Name); | |
4061 | Len := Name_Len; | |
4062 | Line_Pos := Len + 2; | |
4063 | ||
4064 | for D in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop | |
4065 | Src_Name := Sdep.Table (D).Sfile; | |
4066 | ||
4067 | if Is_Internal_File_Name (Src_Name) | |
4068 | and then not Check_Readonly_Files | |
4069 | then | |
4070 | null; | |
4071 | else | |
b7e429ab | 4072 | if not Quiet_Output then |
84481f76 RK |
4073 | Src_Name := Full_Source_Name (Src_Name); |
4074 | end if; | |
4075 | ||
4076 | Get_Name_String (Src_Name); | |
4077 | Len := Name_Len; | |
4078 | ||
4079 | if Line_Pos + Len + 1 > Line_Size then | |
4080 | Write_Str (" \"); | |
4081 | Write_Eol; | |
4082 | Line_Pos := 0; | |
4083 | end if; | |
4084 | ||
4085 | Line_Pos := Line_Pos + Len + 1; | |
4086 | ||
4087 | Write_Str (" "); | |
4088 | Write_Name (Src_Name); | |
4089 | end if; | |
4090 | end loop; | |
4091 | ||
4092 | Write_Eol; | |
4093 | end loop; | |
4094 | ||
d3cc6a32 AC |
4095 | if not Commands_To_Stdout then |
4096 | Set_Standard_Error; | |
4097 | end if; | |
84481f76 RK |
4098 | end List_Depend; |
4099 | ||
aa720a54 AC |
4100 | ----------------- |
4101 | -- Make_Failed -- | |
4102 | ----------------- | |
84481f76 | 4103 | |
3dd9959c | 4104 | procedure Make_Failed (S : String) is |
84481f76 | 4105 | begin |
315f0c42 | 4106 | Fail_Program (S); |
aa720a54 | 4107 | end Make_Failed; |
84481f76 | 4108 | |
84481f76 RK |
4109 | -------------------- |
4110 | -- Mark_Directory -- | |
4111 | -------------------- | |
4112 | ||
315f0c42 | 4113 | procedure Mark_Directory (Dir : String; Mark : Lib_Mark_Type) is |
84481f76 RK |
4114 | N : Name_Id; |
4115 | B : Byte; | |
4116 | ||
315f0c42 | 4117 | Real_Path : constant String := Normalize_Pathname (Dir, ""); |
a7ab2998 | 4118 | |
91c2cbdb AC |
4119 | begin |
4120 | Name_Len := 0; | |
4121 | ||
4122 | if Real_Path'Length = 0 then | |
4123 | Add_Str_To_Name_Buffer (Dir); | |
4124 | ||
4125 | else | |
4126 | Add_Str_To_Name_Buffer (Real_Path); | |
a7ab2998 | 4127 | end if; |
84481f76 | 4128 | |
a7ab2998 | 4129 | -- Last character is supposed to be a directory separator |
84481f76 RK |
4130 | |
4131 | if not Is_Directory_Separator (Name_Buffer (Name_Len)) then | |
91c2cbdb | 4132 | Add_Char_To_Name_Buffer (Directory_Separator); |
84481f76 RK |
4133 | end if; |
4134 | ||
4135 | -- Add flags to the already existing flags | |
4136 | ||
4137 | N := Name_Find; | |
4138 | B := Get_Name_Table_Byte (N); | |
4139 | Set_Name_Table_Byte (N, B or Mark); | |
4140 | end Mark_Directory; | |
4141 | ||
305418c8 LG |
4142 | ---------------------- |
4143 | -- Process_Multilib -- | |
4144 | ---------------------- | |
4145 | ||
315f0c42 | 4146 | procedure Process_Multilib is |
305418c8 LG |
4147 | Output_FD : File_Descriptor; |
4148 | Output_Name : String_Access; | |
4149 | Arg_Index : Natural := 0; | |
4150 | Success : Boolean := False; | |
4151 | Return_Code : Integer := 0; | |
4152 | Multilib_Gcc_Path : String_Access; | |
4153 | Multilib_Gcc : String_Access; | |
4154 | N_Read : Integer := 0; | |
4155 | Line : String (1 .. 1000); | |
4156 | Args : Argument_List (1 .. N_M_Switch + 1); | |
4157 | ||
4158 | begin | |
4159 | pragma Assert (N_M_Switch > 0 and RTS_Specified = null); | |
4160 | ||
e9491f46 LG |
4161 | -- In case we detected a multilib switch and the user has not |
4162 | -- manually specified a specific RTS we emulate the following command: | |
4163 | -- gnatmake $FLAGS --RTS=$(gcc -print-multi-directory $FLAGS) | |
4164 | ||
4165 | -- First select the flags which might have an impact on multilib | |
4166 | -- processing. Note that this is an heuristic selection and it | |
4167 | -- will need to be maintained over time. The condition has to | |
4168 | -- be kept synchronized with N_M_Switch counting in Scan_Make_Arg. | |
06274cd5 | 4169 | |
305418c8 LG |
4170 | for Next_Arg in 1 .. Argument_Count loop |
4171 | declare | |
4172 | Argv : constant String := Argument (Next_Arg); | |
f9ad6b62 | 4173 | |
305418c8 LG |
4174 | begin |
4175 | if Argv'Length > 2 | |
4176 | and then Argv (1) = '-' | |
4177 | and then Argv (2) = 'm' | |
4178 | and then Argv /= "-margs" | |
06274cd5 RD |
4179 | |
4180 | -- Ignore -mieee to avoid spawning an extra gcc in this case | |
4181 | ||
579fab00 | 4182 | and then Argv /= "-mieee" |
305418c8 LG |
4183 | then |
4184 | Arg_Index := Arg_Index + 1; | |
4185 | Args (Arg_Index) := new String'(Argv); | |
4186 | end if; | |
305418c8 LG |
4187 | end; |
4188 | end loop; | |
4189 | ||
4190 | pragma Assert (Arg_Index = N_M_Switch); | |
4191 | ||
4192 | Args (Args'Last) := new String'("-print-multi-directory"); | |
4193 | ||
e9491f46 LG |
4194 | -- Call the GCC driver with the collected flags and save its |
4195 | -- output. Alternate design would be to link in gnatmake the | |
4196 | -- relevant part of the GCC driver. | |
4197 | ||
315f0c42 | 4198 | Multilib_Gcc := Gcc; |
305418c8 | 4199 | |
5568b57c | 4200 | Multilib_Gcc_Path := GNAT.OS_Lib.Locate_Exec_On_Path (Multilib_Gcc.all); |
305418c8 | 4201 | |
477b99b6 | 4202 | Create_Temp_Output_File (Output_FD, Output_Name); |
5568b57c | 4203 | |
305418c8 LG |
4204 | if Output_FD = Invalid_FD then |
4205 | return; | |
4206 | end if; | |
4207 | ||
5568b57c AC |
4208 | GNAT.OS_Lib.Spawn |
4209 | (Multilib_Gcc_Path.all, Args, Output_FD, Return_Code, False); | |
305418c8 | 4210 | Close (Output_FD); |
5568b57c | 4211 | |
305418c8 LG |
4212 | if Return_Code /= 0 then |
4213 | return; | |
4214 | end if; | |
4215 | ||
e9491f46 LG |
4216 | -- Parse the GCC driver output which is a single line, removing CR/LF |
4217 | ||
305418c8 | 4218 | Output_FD := Open_Read (Output_Name.all, Binary); |
5568b57c | 4219 | |
305418c8 LG |
4220 | if Output_FD = Invalid_FD then |
4221 | return; | |
4222 | end if; | |
4223 | ||
4224 | N_Read := Read (Output_FD, Line (1)'Address, Line'Length); | |
4225 | Close (Output_FD); | |
4226 | Delete_File (Output_Name.all, Success); | |
4227 | ||
06274cd5 RD |
4228 | for J in reverse 1 .. N_Read loop |
4229 | if Line (J) = ASCII.CR or else Line (J) = ASCII.LF then | |
305418c8 LG |
4230 | N_Read := N_Read - 1; |
4231 | else | |
4232 | exit; | |
4233 | end if; | |
4234 | end loop; | |
4235 | ||
e9491f46 LG |
4236 | -- In case the standard RTS is selected do nothing |
4237 | ||
305418c8 LG |
4238 | if N_Read = 0 or else Line (1 .. N_Read) = "." then |
4239 | return; | |
4240 | end if; | |
4241 | ||
e9491f46 LG |
4242 | -- Otherwise add -margs --RTS=output |
4243 | ||
315f0c42 AC |
4244 | Scan_Make_Arg ("-margs"); |
4245 | Scan_Make_Arg ("--RTS=" & Line (1 .. N_Read)); | |
305418c8 LG |
4246 | end Process_Multilib; |
4247 | ||
d3cc6a32 AC |
4248 | ------------------------------- |
4249 | -- Report_Compilation_Failed -- | |
4250 | ------------------------------- | |
4251 | ||
4252 | procedure Report_Compilation_Failed is | |
4253 | begin | |
315f0c42 | 4254 | Fail_Program (""); |
d3cc6a32 AC |
4255 | end Report_Compilation_Failed; |
4256 | ||
f86eb278 VC |
4257 | ------------------------ |
4258 | -- Sigint_Intercepted -- | |
4259 | ------------------------ | |
fbf5a39b AC |
4260 | |
4261 | procedure Sigint_Intercepted is | |
4262 | begin | |
d3cc6a32 | 4263 | Set_Standard_Error; |
fbf5a39b | 4264 | Write_Line ("*** Interrupted ***"); |
15cf0748 | 4265 | |
dec55d76 | 4266 | -- Send SIGINT to all outstanding compilation processes spawned |
15cf0748 VC |
4267 | |
4268 | for J in 1 .. Outstanding_Compiles loop | |
3fee081a | 4269 | Kill (Running_Compile (J).Pid, Hard_Kill => False); |
15cf0748 VC |
4270 | end loop; |
4271 | ||
315f0c42 | 4272 | Finish_Program (E_No_Compile); |
fbf5a39b | 4273 | end Sigint_Intercepted; |
84481f76 RK |
4274 | |
4275 | ------------------- | |
4276 | -- Scan_Make_Arg -- | |
4277 | ------------------- | |
4278 | ||
315f0c42 | 4279 | procedure Scan_Make_Arg (Argv : String) is |
958a816e VC |
4280 | Success : Boolean; |
4281 | ||
84481f76 | 4282 | begin |
54e03461 VC |
4283 | Gnatmake_Switch_Found := True; |
4284 | ||
84481f76 RK |
4285 | pragma Assert (Argv'First = 1); |
4286 | ||
4287 | if Argv'Length = 0 then | |
4288 | return; | |
4289 | end if; | |
4290 | ||
64c69860 AC |
4291 | -- If the previous switch has set the Output_File_Name_Present flag |
4292 | -- (that is we have seen a -o), then the next argument is the name of | |
4293 | -- the output executable. | |
84481f76 | 4294 | |
315f0c42 | 4295 | if Output_File_Name_Present and then not Output_File_Name_Seen then |
84481f76 RK |
4296 | Output_File_Name_Seen := True; |
4297 | ||
07fc65c4 | 4298 | if Argv (1) = '-' then |
fbf5a39b | 4299 | Make_Failed ("output file name missing after -o"); |
07fc65c4 | 4300 | |
84481f76 | 4301 | else |
315f0c42 AC |
4302 | Add_Switch ("-o", Linker); |
4303 | Add_Switch (Executable_Name (Argv), Linker); | |
84481f76 RK |
4304 | end if; |
4305 | ||
fbf5a39b | 4306 | -- If the previous switch has set the Object_Directory_Present flag |
64c69860 | 4307 | -- (that is we have seen a -D), then the next argument is the path name |
cafdbd2e | 4308 | -- of the object directory. |
fbf5a39b | 4309 | |
b7e429ab | 4310 | elsif Object_Directory_Present |
fbf5a39b AC |
4311 | and then not Object_Directory_Seen |
4312 | then | |
4313 | Object_Directory_Seen := True; | |
4314 | ||
4315 | if Argv (1) = '-' then | |
4316 | Make_Failed ("object directory path name missing after -D"); | |
4317 | ||
4318 | elsif not Is_Directory (Argv) then | |
3dd9959c | 4319 | Make_Failed ("cannot find object directory """ & Argv & """"); |
fbf5a39b AC |
4320 | |
4321 | else | |
cafdbd2e AC |
4322 | -- Record the object directory. Make sure it ends with a directory |
4323 | -- separator. | |
4324 | ||
4325 | declare | |
4326 | Norm : constant String := Normalize_Pathname (Argv); | |
d56e7acd | 4327 | |
cafdbd2e AC |
4328 | begin |
4329 | if Norm (Norm'Last) = Directory_Separator then | |
4330 | Object_Directory_Path := new String'(Norm); | |
4331 | else | |
4332 | Object_Directory_Path := | |
4333 | new String'(Norm & Directory_Separator); | |
4334 | end if; | |
fbf5a39b | 4335 | |
cafdbd2e | 4336 | Add_Lib_Search_Dir (Norm); |
fbf5a39b | 4337 | |
cafdbd2e | 4338 | -- Specify the object directory to the binder |
fbf5a39b | 4339 | |
315f0c42 | 4340 | Add_Switch ("-aO" & Norm, Binder); |
cafdbd2e | 4341 | end; |
fbf5a39b | 4342 | |
fbf5a39b AC |
4343 | end if; |
4344 | ||
ddf67a1d AC |
4345 | -- Then check if we are dealing with -cargs/-bargs/-largs/-margs. These |
4346 | -- options are taken as is when found in package Compiler, Binder or | |
4347 | -- Linker of the main project file. | |
4348 | ||
315f0c42 AC |
4349 | elsif Argv = "-bargs" or else |
4350 | Argv = "-cargs" or else | |
4351 | Argv = "-largs" or else | |
4352 | Argv = "-margs" | |
84481f76 | 4353 | then |
84481f76 RK |
4354 | case Argv (2) is |
4355 | when 'c' => Program_Args := Compiler; | |
4356 | when 'b' => Program_Args := Binder; | |
4357 | when 'l' => Program_Args := Linker; | |
a71742a8 | 4358 | when 'm' => Program_Args := None; |
84481f76 RK |
4359 | |
4360 | when others => | |
4361 | raise Program_Error; | |
4362 | end case; | |
4363 | ||
cafdbd2e AC |
4364 | -- A special test is needed for the -o switch within a -largs since that |
4365 | -- is another way to specify the name of the final executable. | |
84481f76 | 4366 | |
a21d245c | 4367 | elsif Program_Args = Linker and then Argv = "-o" then |
e03c5253 VC |
4368 | Make_Failed |
4369 | ("switch -o not allowed within a -largs. Use -o directly."); | |
84481f76 | 4370 | |
cafdbd2e AC |
4371 | -- Check to see if we are reading switches after a -cargs, -bargs or |
4372 | -- -largs switch. If so, save it. | |
84481f76 RK |
4373 | |
4374 | elsif Program_Args /= None then | |
4375 | ||
f9ad6b62 AC |
4376 | -- Check to see if we are reading -I switches in order to take into |
4377 | -- account in the src & lib search directories. | |
84481f76 RK |
4378 | |
4379 | if Argv'Length > 2 and then Argv (1 .. 2) = "-I" then | |
4380 | if Argv (3 .. Argv'Last) = "-" then | |
b7e429ab | 4381 | Look_In_Primary_Dir := False; |
84481f76 RK |
4382 | |
4383 | elsif Program_Args = Compiler then | |
ae71d81b | 4384 | Add_Source_Search_Dir (Argv (3 .. Argv'Last)); |
84481f76 RK |
4385 | |
4386 | elsif Program_Args = Binder then | |
315f0c42 | 4387 | Add_Library_Search_Dir (Argv (3 .. Argv'Last)); |
84481f76 RK |
4388 | end if; |
4389 | end if; | |
4390 | ||
315f0c42 | 4391 | Add_Switch (Argv, Program_Args); |
84481f76 | 4392 | |
2a1f6a1f AC |
4393 | -- Make sure that all significant switches -m on the command line |
4394 | -- are counted. | |
4395 | ||
4396 | if Argv'Length > 2 | |
4397 | and then Argv (1 .. 2) = "-m" | |
4398 | and then Argv /= "-mieee" | |
4399 | then | |
4400 | N_M_Switch := N_M_Switch + 1; | |
4401 | end if; | |
4402 | ||
07fc65c4 | 4403 | -- Handle non-default compiler, binder, linker, and handle --RTS switch |
84481f76 RK |
4404 | |
4405 | elsif Argv'Length > 2 and then Argv (1 .. 2) = "--" then | |
4406 | if Argv'Length > 6 | |
4407 | and then Argv (1 .. 6) = "--GCC=" | |
4408 | then | |
4409 | declare | |
fbf5a39b | 4410 | Program_Args : constant Argument_List_Access := |
84481f76 RK |
4411 | Argument_String_To_List |
4412 | (Argv (7 .. Argv'Last)); | |
4413 | ||
4414 | begin | |
315f0c42 | 4415 | Gcc := new String'(Program_Args.all (1).all); |
84481f76 RK |
4416 | |
4417 | for J in 2 .. Program_Args.all'Last loop | |
4418 | Add_Switch | |
315f0c42 | 4419 | (Program_Args.all (J).all, Compiler); |
84481f76 RK |
4420 | end loop; |
4421 | end; | |
4422 | ||
4423 | elsif Argv'Length > 11 | |
4424 | and then Argv (1 .. 11) = "--GNATBIND=" | |
4425 | then | |
4426 | declare | |
fbf5a39b | 4427 | Program_Args : constant Argument_List_Access := |
84481f76 RK |
4428 | Argument_String_To_List |
4429 | (Argv (12 .. Argv'Last)); | |
4430 | ||
4431 | begin | |
315f0c42 | 4432 | Gnatbind := new String'(Program_Args.all (1).all); |
84481f76 RK |
4433 | |
4434 | for J in 2 .. Program_Args.all'Last loop | |
4435 | Add_Switch | |
315f0c42 | 4436 | (Program_Args.all (J).all, Binder); |
84481f76 RK |
4437 | end loop; |
4438 | end; | |
4439 | ||
4440 | elsif Argv'Length > 11 | |
4441 | and then Argv (1 .. 11) = "--GNATLINK=" | |
4442 | then | |
4443 | declare | |
fbf5a39b | 4444 | Program_Args : constant Argument_List_Access := |
84481f76 RK |
4445 | Argument_String_To_List |
4446 | (Argv (12 .. Argv'Last)); | |
4447 | begin | |
315f0c42 | 4448 | Gnatlink := new String'(Program_Args.all (1).all); |
84481f76 RK |
4449 | |
4450 | for J in 2 .. Program_Args.all'Last loop | |
4451 | Add_Switch (Program_Args.all (J).all, Linker); | |
4452 | end loop; | |
4453 | end; | |
4454 | ||
07fc65c4 GB |
4455 | elsif Argv'Length >= 5 and then |
4456 | Argv (1 .. 5) = "--RTS" | |
4457 | then | |
315f0c42 AC |
4458 | Add_Switch (Argv, Compiler); |
4459 | Add_Switch (Argv, Binder); | |
07fc65c4 GB |
4460 | |
4461 | if Argv'Length <= 6 or else Argv (6) /= '=' then | |
fbf5a39b | 4462 | Make_Failed ("missing path for --RTS"); |
07fc65c4 GB |
4463 | |
4464 | else | |
fbf5a39b AC |
4465 | -- Check that this is the first time we see this switch or |
4466 | -- if it is not the first time, the same path is specified. | |
4467 | ||
4468 | if RTS_Specified = null then | |
4469 | RTS_Specified := new String'(Argv (7 .. Argv'Last)); | |
4470 | ||
4471 | elsif RTS_Specified.all /= Argv (7 .. Argv'Last) then | |
4472 | Make_Failed ("--RTS cannot be specified multiple times"); | |
4473 | end if; | |
4474 | ||
07fc65c4 GB |
4475 | -- Valid --RTS switch |
4476 | ||
b7e429ab AC |
4477 | No_Stdinc := True; |
4478 | No_Stdlib := True; | |
4479 | RTS_Switch := True; | |
07fc65c4 GB |
4480 | |
4481 | declare | |
fbf5a39b | 4482 | Src_Path_Name : constant String_Ptr := |
07fc65c4 GB |
4483 | Get_RTS_Search_Dir |
4484 | (Argv (7 .. Argv'Last), Include); | |
fbf5a39b AC |
4485 | |
4486 | Lib_Path_Name : constant String_Ptr := | |
07fc65c4 GB |
4487 | Get_RTS_Search_Dir |
4488 | (Argv (7 .. Argv'Last), Objects); | |
4489 | ||
4490 | begin | |
64c69860 AC |
4491 | if Src_Path_Name /= null |
4492 | and then Lib_Path_Name /= null | |
07fc65c4 | 4493 | then |
64c69860 AC |
4494 | -- Set RTS_*_Path_Name variables, so that correct direct- |
4495 | -- ories will be set when Osint.Add_Default_Search_Dirs | |
4496 | -- is called later. | |
fbf5a39b AC |
4497 | |
4498 | RTS_Src_Path_Name := Src_Path_Name; | |
4499 | RTS_Lib_Path_Name := Lib_Path_Name; | |
07fc65c4 | 4500 | |
d1ced162 RD |
4501 | elsif Src_Path_Name = null |
4502 | and then Lib_Path_Name = null | |
64c69860 | 4503 | then |
9fe696a3 AC |
4504 | Make_Failed |
4505 | ("RTS path not valid: missing adainclude and adalib " | |
4506 | & "directories"); | |
07fc65c4 GB |
4507 | |
4508 | elsif Src_Path_Name = null then | |
9fe696a3 AC |
4509 | Make_Failed |
4510 | ("RTS path not valid: missing adainclude directory"); | |
07fc65c4 | 4511 | |
9fe696a3 AC |
4512 | elsif Lib_Path_Name = null then |
4513 | Make_Failed | |
4514 | ("RTS path not valid: missing adalib directory"); | |
07fc65c4 GB |
4515 | end if; |
4516 | end; | |
4517 | end if; | |
4518 | ||
a6fa2e83 MR |
4519 | elsif (Argv'Length >= 8 and then Argv (1 .. 8) = "--param=") |
4520 | or else (Argv'Length >= 10 and then Argv (1 .. 10) = "--sysroot=") | |
4521 | then | |
315f0c42 AC |
4522 | Add_Switch (Argv, Compiler); |
4523 | Add_Switch (Argv, Linker); | |
ffef1219 | 4524 | |
aa0df10b VC |
4525 | elsif Argv = Create_Map_File_Switch then |
4526 | Map_File := new String'(""); | |
4527 | ||
4528 | elsif Argv'Length > Create_Map_File_Switch'Length + 1 | |
4529 | and then | |
4530 | Argv (1 .. Create_Map_File_Switch'Length) = Create_Map_File_Switch | |
4531 | and then | |
4532 | Argv (Create_Map_File_Switch'Length + 1) = '=' | |
4533 | then | |
4534 | Map_File := | |
4535 | new String' | |
4536 | (Argv (Create_Map_File_Switch'Length + 2 .. Argv'Last)); | |
4537 | ||
84481f76 | 4538 | else |
315f0c42 | 4539 | Scan_Make_Switches (Argv, Success); |
84481f76 RK |
4540 | end if; |
4541 | ||
4542 | -- If we have seen a regular switch process it | |
4543 | ||
07fc65c4 | 4544 | elsif Argv (1) = '-' then |
84481f76 | 4545 | if Argv'Length = 1 then |
fbf5a39b | 4546 | Make_Failed ("switch character cannot be followed by a blank"); |
84481f76 | 4547 | |
958a816e VC |
4548 | -- Incorrect switches that should start with "--" |
4549 | ||
4550 | elsif (Argv'Length > 5 and then Argv (1 .. 5) = "-RTS=") | |
4551 | or else (Argv'Length > 5 and then Argv (1 .. 5) = "-GCC=") | |
ffef1219 | 4552 | or else (Argv'Length > 8 and then Argv (1 .. 7) = "-param=") |
958a816e VC |
4553 | or else (Argv'Length > 10 and then Argv (1 .. 10) = "-GNATLINK=") |
4554 | or else (Argv'Length > 10 and then Argv (1 .. 10) = "-GNATBIND=") | |
4555 | then | |
3dd9959c | 4556 | Make_Failed ("option " & Argv & " should start with '--'"); |
958a816e | 4557 | |
84481f76 RK |
4558 | -- -I- |
4559 | ||
4560 | elsif Argv (2 .. Argv'Last) = "I-" then | |
b7e429ab | 4561 | Look_In_Primary_Dir := False; |
84481f76 RK |
4562 | |
4563 | -- Forbid -?- or -??- where ? is any character | |
4564 | ||
4565 | elsif (Argv'Length = 3 and then Argv (3) = '-') | |
4566 | or else (Argv'Length = 4 and then Argv (4) = '-') | |
4567 | then | |
3dd9959c AC |
4568 | Make_Failed |
4569 | ("trailing ""-"" at the end of " & Argv & " forbidden."); | |
84481f76 RK |
4570 | |
4571 | -- -Idir | |
4572 | ||
4573 | elsif Argv (2) = 'I' then | |
315f0c42 AC |
4574 | Add_Source_Search_Dir (Argv (3 .. Argv'Last)); |
4575 | Add_Library_Search_Dir (Argv (3 .. Argv'Last)); | |
4576 | Add_Switch (Argv, Compiler); | |
4577 | Add_Switch (Argv, Binder); | |
84481f76 RK |
4578 | |
4579 | -- -aIdir (to gcc this is like a -I switch) | |
4580 | ||
4581 | elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then | |
315f0c42 | 4582 | Add_Source_Search_Dir (Argv (4 .. Argv'Last)); |
cafdbd2e | 4583 | Add_Switch |
315f0c42 AC |
4584 | ("-I" & Argv (4 .. Argv'Last), Compiler); |
4585 | Add_Switch (Argv, Binder); | |
84481f76 RK |
4586 | |
4587 | -- -aOdir | |
4588 | ||
4589 | elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aO" then | |
315f0c42 AC |
4590 | Add_Library_Search_Dir (Argv (4 .. Argv'Last)); |
4591 | Add_Switch (Argv, Binder); | |
84481f76 RK |
4592 | |
4593 | -- -aLdir (to gnatbind this is like a -aO switch) | |
4594 | ||
4595 | elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then | |
315f0c42 AC |
4596 | Mark_Directory (Argv (4 .. Argv'Last), Ada_Lib_Dir); |
4597 | Add_Library_Search_Dir (Argv (4 .. Argv'Last)); | |
cafdbd2e | 4598 | Add_Switch |
315f0c42 | 4599 | ("-aO" & Argv (4 .. Argv'Last), Binder); |
84481f76 | 4600 | |
f5552c89 GD |
4601 | -- -aamp_target=... |
4602 | ||
4603 | elsif Argv'Length >= 13 and then Argv (2 .. 13) = "aamp_target=" then | |
315f0c42 | 4604 | Add_Switch (Argv, Compiler); |
f5552c89 GD |
4605 | |
4606 | -- Set the aamp_target environment variable so that the binder and | |
4607 | -- linker will use the proper target library. This is consistent | |
4608 | -- with how things work when -aamp_target is passed on the command | |
4609 | -- line to gnaampmake. | |
4610 | ||
4611 | Setenv ("aamp_target", Argv (14 .. Argv'Last)); | |
4612 | ||
84481f76 RK |
4613 | -- -Adir (to gnatbind this is like a -aO switch, to gcc like a -I) |
4614 | ||
4615 | elsif Argv (2) = 'A' then | |
315f0c42 AC |
4616 | Mark_Directory (Argv (3 .. Argv'Last), Ada_Lib_Dir); |
4617 | Add_Source_Search_Dir (Argv (3 .. Argv'Last)); | |
4618 | Add_Library_Search_Dir (Argv (3 .. Argv'Last)); | |
4619 | Add_Switch ("-I" & Argv (3 .. Argv'Last), Compiler); | |
4620 | Add_Switch ("-aO" & Argv (3 .. Argv'Last), Binder); | |
84481f76 RK |
4621 | |
4622 | -- -Ldir | |
4623 | ||
4624 | elsif Argv (2) = 'L' then | |
315f0c42 | 4625 | Add_Switch (Argv, Linker); |
84481f76 | 4626 | |
a3f2babd | 4627 | -- For -gxxx, -pg, -mxxx, -fxxx, -Oxxx, pass the switch to both the |
cafdbd2e AC |
4628 | -- compiler and the linker (except for -gnatxxx which is only for the |
4629 | -- compiler). Some of the -mxxx (for example -m64) and -fxxx (for | |
4630 | -- example -ftest-coverage for gcov) need to be used when compiling | |
4631 | -- the binder generated files, and using all these gcc switches for | |
a3f2babd | 4632 | -- them should not be a problem. Pass -Oxxx to the linker for LTO. |
84481f76 RK |
4633 | |
4634 | elsif | |
4635 | (Argv (2) = 'g' and then (Argv'Last < 5 | |
4636 | or else Argv (2 .. 5) /= "gnat")) | |
4637 | or else Argv (2 .. Argv'Last) = "pg" | |
fbf5a39b | 4638 | or else (Argv (2) = 'm' and then Argv'Last > 2) |
30c20106 | 4639 | or else (Argv (2) = 'f' and then Argv'Last > 2) |
21a5b575 | 4640 | or else Argv (2) = 'O' |
84481f76 | 4641 | then |
315f0c42 AC |
4642 | Add_Switch (Argv, Compiler); |
4643 | Add_Switch (Argv, Linker); | |
84481f76 | 4644 | |
e9491f46 LG |
4645 | -- The following condition has to be kept synchronized with |
4646 | -- the Process_Multilib one. | |
4647 | ||
579fab00 AC |
4648 | if Argv (2) = 'm' |
4649 | and then Argv /= "-mieee" | |
4650 | then | |
305418c8 LG |
4651 | N_M_Switch := N_M_Switch + 1; |
4652 | end if; | |
4653 | ||
fbf5a39b AC |
4654 | -- -C=<mapping file> |
4655 | ||
4656 | elsif Argv'Last > 2 and then Argv (2) = 'C' then | |
315f0c42 AC |
4657 | if Argv (3) /= '=' or else Argv'Last <= 3 then |
4658 | Make_Failed ("illegal switch " & Argv); | |
fbf5a39b AC |
4659 | end if; |
4660 | ||
315f0c42 AC |
4661 | Gnatmake_Mapping_File := new String'(Argv (4 .. Argv'Last)); |
4662 | ||
fbf5a39b AC |
4663 | -- -D |
4664 | ||
4665 | elsif Argv'Last = 2 and then Argv (2) = 'D' then | |
4666 | if Project_File_Name /= null then | |
cafdbd2e AC |
4667 | Make_Failed |
4668 | ("-D cannot be used in conjunction with a project file"); | |
fbf5a39b AC |
4669 | |
4670 | else | |
315f0c42 | 4671 | Scan_Make_Switches (Argv, Success); |
fbf5a39b AC |
4672 | end if; |
4673 | ||
84481f76 RK |
4674 | -- -d |
4675 | ||
cafdbd2e | 4676 | elsif Argv (2) = 'd' and then Argv'Last = 2 then |
b7e429ab | 4677 | Display_Compilation_Progress := True; |
84481f76 | 4678 | |
fbf5a39b AC |
4679 | -- -i |
4680 | ||
4681 | elsif Argv'Last = 2 and then Argv (2) = 'i' then | |
4682 | if Project_File_Name /= null then | |
cafdbd2e AC |
4683 | Make_Failed |
4684 | ("-i cannot be used in conjunction with a project file"); | |
fbf5a39b | 4685 | else |
315f0c42 | 4686 | Scan_Make_Switches (Argv, Success); |
fbf5a39b AC |
4687 | end if; |
4688 | ||
84481f76 RK |
4689 | -- -j (need to save the result) |
4690 | ||
4691 | elsif Argv (2) = 'j' then | |
315f0c42 | 4692 | Scan_Make_Switches (Argv, Success); |
84481f76 RK |
4693 | |
4694 | -- -m | |
4695 | ||
ae71d81b AC |
4696 | elsif Argv (2) = 'm' then |
4697 | pragma Assert (Argv'Last = 2); | |
b7e429ab | 4698 | Minimal_Recompilation := True; |
84481f76 RK |
4699 | |
4700 | -- -u | |
4701 | ||
cafdbd2e AC |
4702 | elsif Argv (2) = 'u' and then Argv'Last = 2 then |
4703 | Unique_Compile := True; | |
4704 | Compile_Only := True; | |
4705 | Do_Bind_Step := False; | |
4706 | Do_Link_Step := False; | |
84481f76 | 4707 | |
fbf5a39b | 4708 | -- -U |
84481f76 | 4709 | |
fbf5a39b AC |
4710 | elsif Argv (2) = 'U' |
4711 | and then Argv'Last = 2 | |
84481f76 | 4712 | then |
cafdbd2e AC |
4713 | Unique_Compile := True; |
4714 | Compile_Only := True; | |
4715 | Do_Bind_Step := False; | |
4716 | Do_Link_Step := False; | |
fbf5a39b AC |
4717 | |
4718 | -- -Pprj or -P prj (only once, and only on the command line) | |
4719 | ||
4720 | elsif Argv (2) = 'P' then | |
84481f76 | 4721 | if Project_File_Name /= null then |
fbf5a39b AC |
4722 | Make_Failed ("cannot have several project files specified"); |
4723 | ||
4724 | elsif Object_Directory_Path /= null then | |
cafdbd2e AC |
4725 | Make_Failed |
4726 | ("-D cannot be used in conjunction with a project file"); | |
fbf5a39b AC |
4727 | |
4728 | elsif In_Place_Mode then | |
cafdbd2e AC |
4729 | Make_Failed |
4730 | ("-i cannot be used in conjunction with a project file"); | |
84481f76 | 4731 | |
fbf5a39b | 4732 | elsif Argv'Last = 2 then |
84481f76 | 4733 | |
fbf5a39b | 4734 | -- -P is used alone: the project file name is the next option |
84481f76 | 4735 | |
fbf5a39b | 4736 | Project_File_Name_Present := True; |
84481f76 | 4737 | |
fbf5a39b AC |
4738 | else |
4739 | Project_File_Name := new String'(Argv (3 .. Argv'Last)); | |
4740 | end if; | |
84481f76 RK |
4741 | |
4742 | -- -vPx (verbosity of the parsing of the project files) | |
4743 | ||
05b34c18 | 4744 | elsif Argv'Length >= 3 and then Argv (2 .. 3) = "vP" then |
8e983d80 AC |
4745 | if Argv'Last /= 4 or else Argv (4) not in '0' .. '2' then |
4746 | Make_Failed | |
4747 | ("invalid verbosity level " & Argv (4 .. Argv'Last)); | |
84481f76 RK |
4748 | end if; |
4749 | ||
84481f76 RK |
4750 | -- -Xext=val (External assignment) |
4751 | ||
315f0c42 | 4752 | elsif Argv (2) = 'X' then |
84481f76 RK |
4753 | null; |
4754 | ||
cafdbd2e AC |
4755 | -- If -gnath is present, then generate the usage information right |
4756 | -- now and do not pass this option on to the compiler calls. | |
84481f76 RK |
4757 | |
4758 | elsif Argv = "-gnath" then | |
07fc65c4 | 4759 | Usage; |
84481f76 | 4760 | |
cafdbd2e AC |
4761 | -- If -gnatc is specified, make sure the bind and link steps are not |
4762 | -- executed. | |
7ffa903f VC |
4763 | |
4764 | elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatc" then | |
4765 | ||
cafdbd2e AC |
4766 | -- If -gnatc is specified, make sure the bind and link steps are |
4767 | -- not executed. | |
84481f76 | 4768 | |
315f0c42 | 4769 | Add_Switch (Argv, Compiler); |
cafdbd2e | 4770 | Operating_Mode := Check_Semantics; |
b7e429ab | 4771 | Check_Object_Consistency := False; |
92966893 | 4772 | |
a53c5613 AC |
4773 | -- Except in CodePeer mode (set by -gnatcC), where we do want to |
4774 | -- call bind/link in CodePeer mode (-P switch). | |
9aff36e9 | 4775 | |
0319cacc AC |
4776 | if Argv'Last >= 7 and then Argv (7) = 'C' then |
4777 | CodePeer_Mode := True; | |
4778 | else | |
92966893 AC |
4779 | Compile_Only := True; |
4780 | Do_Bind_Step := False; | |
4781 | Do_Link_Step := False; | |
4782 | end if; | |
84481f76 | 4783 | |
36f6df66 AC |
4784 | -- If -gnatA is specified, make sure that gnat.adc is never read |
4785 | ||
4786 | elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatA" then | |
315f0c42 | 4787 | Add_Switch (Argv, Compiler); |
36f6df66 AC |
4788 | Opt.Config_File := False; |
4789 | ||
84481f76 RK |
4790 | elsif Argv (2 .. Argv'Last) = "nostdlib" then |
4791 | ||
6989bc1f | 4792 | -- Pass -nstdlib to gnatbind and gnatlink |
9596236a | 4793 | |
6989bc1f | 4794 | No_Stdlib := True; |
315f0c42 AC |
4795 | Add_Switch (Argv, Binder); |
4796 | Add_Switch (Argv, Linker); | |
946db1e2 | 4797 | |
84481f76 | 4798 | elsif Argv (2 .. Argv'Last) = "nostdinc" then |
7ffa903f | 4799 | |
9596236a | 4800 | -- Pass -nostdinc to the Compiler and to gnatbind |
7ffa903f | 4801 | |
b7e429ab | 4802 | No_Stdinc := True; |
315f0c42 AC |
4803 | Add_Switch (Argv, Compiler); |
4804 | Add_Switch (Argv, Binder); | |
84481f76 | 4805 | |
54e03461 VC |
4806 | -- All other switches are processed by Scan_Make_Switches. If the |
4807 | -- call returns with Gnatmake_Switch_Found = False, then the switch | |
4808 | -- is passed to the compiler. | |
84481f76 RK |
4809 | |
4810 | else | |
315f0c42 | 4811 | Scan_Make_Switches (Argv, Gnatmake_Switch_Found); |
958a816e | 4812 | |
54e03461 | 4813 | if not Gnatmake_Switch_Found then |
315f0c42 | 4814 | Add_Switch (Argv, Compiler); |
958a816e | 4815 | end if; |
84481f76 RK |
4816 | end if; |
4817 | ||
4818 | -- If not a switch it must be a file name | |
4819 | ||
4820 | else | |
315f0c42 | 4821 | Main_On_Command_Line := True; |
3e2399ba | 4822 | |
07fc65c4 | 4823 | Add_File (Argv); |
b0f26df5 | 4824 | Mains.Add_Main (Argv); |
84481f76 RK |
4825 | end if; |
4826 | end Scan_Make_Arg; | |
4827 | ||
07fc65c4 GB |
4828 | ----------- |
4829 | -- Usage -- | |
4830 | ----------- | |
84481f76 | 4831 | |
07fc65c4 | 4832 | procedure Usage is |
84481f76 | 4833 | begin |
07fc65c4 GB |
4834 | if Usage_Needed then |
4835 | Usage_Needed := False; | |
4836 | Makeusg; | |
4837 | end if; | |
4838 | end Usage; | |
84481f76 | 4839 | |
84481f76 | 4840 | end Make; |