]> gcc.gnu.org Git - gcc.git/blame - gcc/ada/makegpr.adb
re PR fortran/13792 (lbound/ubound generates internal compiler error)
[gcc.git] / gcc / ada / makegpr.adb
CommitLineData
9f4fd324
AC
1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- M A K E G P R --
6-- --
7-- B o d y --
8-- --
9-- Copyright (C) 2004 Free Software Foundation, Inc. --
10-- --
11-- GNAT is free software; you can redistribute it and/or modify it under --
12-- terms of the GNU General Public License as published by the Free Soft- --
13-- ware Foundation; either version 2, or (at your option) any later ver- --
14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17-- for more details. You should have received a copy of the GNU General --
18-- Public License distributed with GNAT; see file COPYING. If not, write --
19-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20-- MA 02111-1307, USA. --
21-- --
22-- GNAT was originally developed by the GNAT team at New York University. --
23-- Extensive contributions were provided by Ada Core Technologies Inc. --
24-- --
25------------------------------------------------------------------------------
26
27with Ada.Command_Line; use Ada.Command_Line;
28with Ada.Strings.Fixed; use Ada.Strings.Fixed;
29with Ada.Text_IO; use Ada.Text_IO;
30with Ada.Unchecked_Deallocation;
31
32with Csets;
33with Gnatvsn;
34
35with GNAT.Directory_Operations; use GNAT.Directory_Operations;
36with GNAT.Dynamic_Tables;
37with GNAT.Expect; use GNAT.Expect;
38with GNAT.HTable;
39with GNAT.OS_Lib; use GNAT.OS_Lib;
40with GNAT.Regpat; use GNAT.Regpat;
41
42with Makeutl; use Makeutl;
43with MLib.Tgt; use MLib.Tgt;
44with Namet; use Namet;
45with Output; use Output;
46with Opt; use Opt;
47with Osint; use Osint;
48with Prj; use Prj;
49with Prj.Com; use Prj.Com;
50with Prj.Pars;
51with Prj.Util; use Prj.Util;
52with Snames; use Snames;
53with System;
54with System.Case_Util; use System.Case_Util;
55with Table;
56with Types; use Types;
57
58package body Makegpr is
59
60 Max_In_Archives : constant := 50;
61 -- The maximum number of arguments for a single invocation of the
62 -- Archive Indexer (ar).
63
64 Cpp_Linker : constant String := "c++linker";
65 -- The name of a linking script, built one the fly, when there are C++
66 -- sources and the C++ compiler is not g++.
67
68 No_Argument : constant Argument_List := (1 .. 0 => null);
0da2c8ac 69 -- Null argument list representing case of no arguments
9f4fd324
AC
70
71 FD : Process_Descriptor;
72 -- The process descriptor used when invoking a non GNU compiler with -M
73 -- and getting the output with GNAT.Expect.
74
0da2c8ac
AC
75 Line_Matcher : constant Pattern_Matcher := Compile ("^.*?\n", Single_Line);
76 -- Pattern for GNAT.Expect for the invocation of a non GNU compiler with -M
9f4fd324
AC
77
78 Name_Ide : Name_Id;
79 Name_Compiler_Command : Name_Id;
80 -- Names of package IDE and its attribute Compiler_Command.
81 -- Set up by Initialize.
82
83 Unique_Compile : Boolean := False;
84 -- True when switch -u is used on the command line
85
86 type Source_Index_Rec is record
0da2c8ac
AC
87 Project : Project_Id;
88 Id : Other_Source_Id;
89 Found : Boolean := False;
9f4fd324 90 end record;
0da2c8ac 91 -- Used as Source_Indexes component to check if archive needs to be rebuilt
9f4fd324
AC
92
93 type Source_Index_Array is array (Positive range <>) of Source_Index_Rec;
94 type Source_Indexes_Ref is access Source_Index_Array;
95
96 procedure Free is new Ada.Unchecked_Deallocation
97 (Source_Index_Array, Source_Indexes_Ref);
98
99 Initial_Source_Index_Count : constant Positive := 20;
100 Source_Indexes : Source_Indexes_Ref :=
101 new Source_Index_Array (1 .. Initial_Source_Index_Count);
102 -- A list of the Other_Source_Ids of a project file, with an indication
103 -- that they have been found in the archive dependency file.
104
105 Last_Source : Natural := 0;
106 -- The index of the last valid component of Source_Indexes
107
108 Compiler_Names : array (Programming_Language) of String_Access;
109 -- The names of the compilers to be used. Set up by Get_Compiler.
110 -- Used to display the commands spawned.
111
112 Compiler_Paths : array (Programming_Language) of String_Access;
113 -- The path names of the compiler to be used. Set up by Get_Compiler.
114 -- Used to spawn compiling/linking processes.
115
116 Compiler_Is_Gcc : array (Programming_Language) of Boolean;
117 -- An indication that a compiler is a GCC compiler, to be able to use
118 -- specific GCC switches.
119
120 Archive_Builder_Path : String_Access := null;
121 -- The path name of the archive builder (ar). To be used when spawning
122 -- ar commands.
123
124 Archive_Indexer_Path : String_Access := null;
125 -- The path name of the archive indexer (ranlib), if it exists.
126
127 Copyright_Output : Boolean := False;
128 Usage_Output : Boolean := False;
0da2c8ac 129 -- Flags to avoid multiple displays of Copyright notice and of Usage
9f4fd324
AC
130
131 Output_File_Name : String_Access := null;
132 -- The name given after a switch -o
133
134 Output_File_Name_Expected : Boolean := False;
135 -- True when last switch was -o
136
137 Project_File_Name : String_Access := null;
138 -- The name of the project file specified with switch -P
139
140 Project_File_Name_Expected : Boolean := False;
141 -- True when last switch was -P
142
143 Naming_String : aliased String := "naming";
144 Builder_String : aliased String := "builder";
145 Compiler_String : aliased String := "compiler";
146 Binder_String : aliased String := "binder";
147 Linker_String : aliased String := "linker";
148 -- Name of packages to be checked when parsing/processing project files
149
150 List_Of_Packages : aliased String_List :=
151 (Naming_String 'Access,
152 Builder_String 'Access,
153 Compiler_String 'Access,
154 Binder_String 'Access,
155 Linker_String 'Access);
156 Packages_To_Check : constant String_List_Access := List_Of_Packages'Access;
0da2c8ac 157 -- List of the packages to be checked when parsing/processing project files
9f4fd324
AC
158
159 Main_Project : Project_Id;
160 -- The project id of the main project
161
162 type Processor is (None, Linker, Compiler);
163 Current_Processor : Processor := None;
164 -- This variable changes when switches -*args are used
165
166 Current_Language : Programming_Language := Lang_Ada;
167 -- The compiler language to consider when Processor is Compiler
168
169 package Comp_Opts is new GNAT.Dynamic_Tables
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 Options : array (Programming_Language) of Comp_Opts.Instance;
176 -- Tables to store compiling options for the different compilers
177
9f4fd324
AC
178 package Linker_Options is new Table.Table
179 (Table_Component_Type => String_Access,
180 Table_Index_Type => Integer,
181 Table_Low_Bound => 1,
182 Table_Initial => 20,
183 Table_Increment => 100,
184 Table_Name => "Makegpr.Linker_Options");
185 -- Table to store the linking options
186
187 package Ada_Mains is new Table.Table
188 (Table_Component_Type => String_Access,
189 Table_Index_Type => Integer,
190 Table_Low_Bound => 1,
191 Table_Initial => 20,
192 Table_Increment => 100,
193 Table_Name => "Makegpr.Ada_Mains");
194 -- Table to store the Ada mains, either specified on the command line
195 -- or found in attribute Main of the main project file.
196
197 package Other_Mains is new Table.Table
198 (Table_Component_Type => Other_Source,
199 Table_Index_Type => Integer,
200 Table_Low_Bound => 1,
201 Table_Initial => 20,
202 Table_Increment => 100,
203 Table_Name => "Makegpr.Other_Mains");
204 -- Table to store the mains of languages other than Ada, either specified
205 -- on the command line or found in attribute Main of the main project file.
206
207 package Sources_Compiled is new GNAT.HTable.Simple_HTable
208 (Header_Num => Header_Num,
209 Element => Boolean,
210 No_Element => False,
211 Key => Name_Id,
212 Hash => Hash,
213 Equal => "=");
214
15ce9ca2
AC
215 package X_Switches is new Table.Table
216 (Table_Component_Type => String_Access,
217 Table_Index_Type => Integer,
218 Table_Low_Bound => 1,
219 Table_Initial => 2,
220 Table_Increment => 100,
221 Table_Name => "Makegpr.X_Switches");
222 -- Table to store the -X switches to be passed to gnatmake
223
9f4fd324
AC
224 Initial_Argument_Count : constant Positive := 20;
225 type Boolean_Array is array (Positive range <>) of Boolean;
226 type Booleans is access Boolean_Array;
227
228 procedure Free is new Ada.Unchecked_Deallocation (Boolean_Array, Booleans);
229
230 Arguments : Argument_List_Access :=
231 new Argument_List (1 .. Initial_Argument_Count);
232 -- Used to store lists of arguments to be used when spawning a process
233
234 Arguments_Displayed : Booleans :=
235 new Boolean_Array (1 .. Initial_Argument_Count);
236 -- For each argument in Arguments, indicate if the argument should be
237 -- displayed when procedure Display_Command is called.
238
239 Last_Argument : Natural := 0;
240 -- Index of the last valid argument in Arguments
241
242 package Cache_Args is new Table.Table
243 (Table_Component_Type => String_Access,
244 Table_Index_Type => Integer,
245 Table_Low_Bound => 1,
246 Table_Initial => 200,
247 Table_Increment => 50,
248 Table_Name => "Makegpr.Cache_Args");
249 -- A table to cache arguments, to avoid multiple allocation of the same
250 -- strings. It is not possible to use a hash table, because String is
251 -- an unconstrained type.
252
253 -- Various switches used when spawning processes:
254
255 Dash_B_String : aliased String := "-B";
256 Dash_B : constant String_Access := Dash_B_String'Access;
257 Dash_c_String : aliased String := "-c";
258 Dash_c : constant String_Access := Dash_c_String'Access;
259 Dash_cargs_String : aliased String := "-cargs";
260 Dash_cargs : constant String_Access := Dash_cargs_String'Access;
261 Dash_f_String : aliased String := "-f";
262 Dash_f : constant String_Access := Dash_f_String'Access;
263 Dash_k_String : aliased String := "-k";
264 Dash_k : constant String_Access := Dash_k_String'Access;
265 Dash_largs_String : aliased String := "-largs";
266 Dash_largs : constant String_Access := Dash_largs_String'Access;
267 Dash_M_String : aliased String := "-M";
268 Dash_M : constant String_Access := Dash_M_String'Access;
269 Dash_margs_String : aliased String := "-margs";
270 Dash_margs : constant String_Access := Dash_margs_String'Access;
271 Dash_o_String : aliased String := "-o";
272 Dash_o : constant String_Access := Dash_o_String'Access;
273 Dash_P_String : aliased String := "-P";
274 Dash_P : constant String_Access := Dash_P_String'Access;
275 Dash_q_String : aliased String := "-q";
276 Dash_q : constant String_Access := Dash_q_String'Access;
277 Dash_u_String : aliased String := "-u";
278 Dash_u : constant String_Access := Dash_u_String'Access;
279 Dash_v_String : aliased String := "-v";
280 Dash_v : constant String_Access := Dash_v_String'Access;
281 Dash_vP1_String : aliased String := "-vP1";
282 Dash_vP1 : constant String_Access := Dash_vP1_String'Access;
283 Dash_vP2_String : aliased String := "-vP2";
284 Dash_vP2 : constant String_Access := Dash_vP2_String'Access;
285 Dash_x_String : aliased String := "-x";
286 Dash_x : constant String_Access := Dash_x_String'Access;
287 r_String : aliased String := "r";
288 r : constant String_Access := r_String'Access;
289
290 CPATH : constant String := "CPATH";
291 -- The environment variable to set when compiler is a GCC compiler
292 -- to indicate the include directory path.
293
294 Current_Include_Paths : array (Programming_Language) of String_Access;
295 -- A cache for the paths of included directories, to avoid setting
296 -- env var CPATH unnecessarily.
297
298 C_Plus_Plus_Is_Used : Boolean := False;
299 -- True when there are sources in C++
300
301 Link_Options_Switches : Argument_List_Access := null;
302 -- The link options coming from the attributes Linker'Linker_Options in
303 -- project files imported, directly or indirectly, by the main project.
304
305 Total_Number_Of_Errors : Natural := 0;
306 -- Used when Keep_Going is True (switch -k) to keep the total number
307 -- of compilation/linking errors, to report at the end of execution.
308
0da2c8ac
AC
309 Need_To_Rebuild_Global_Archive : Boolean := False;
310
9f4fd324
AC
311 Error_Header : constant String := "*** ERROR: ";
312 -- The beginning of error message, when Keep_Going is True
313
314 Need_To_Relink : Boolean := False;
315 -- True when an executable of a language other than Ada need to be linked
316
15ce9ca2
AC
317 Global_Archive_Exists : Boolean := False;
318 -- True if there is a non empty global archive, to prevent creation
319 -- of such archives.
320
9f4fd324
AC
321 Path_Option : String_Access;
322 -- The path option switch, when supported
323
324 package Lib_Path is new Table.Table
325 (Table_Component_Type => Character,
326 Table_Index_Type => Integer,
327 Table_Low_Bound => 1,
328 Table_Initial => 200,
329 Table_Increment => 50,
330 Table_Name => "Makegpr.Lib_Path");
331 -- A table to compute the path to put in the path option switch, when it
332 -- is supported.
333
334 procedure Add_Archives (For_Gnatmake : Boolean);
335 -- Add to Arguments the list of archives for linking an executable
336
337 procedure Add_Argument (Arg : String_Access; Display : Boolean);
338 procedure Add_Argument (Arg : String; Display : Boolean);
339 -- Add an argument to Arguments. Reallocate if necessary.
340
341 procedure Add_Arguments (Args : Argument_List; Display : Boolean);
342 -- Add a list of arguments to Arguments. Reallocate if necessary
343
344 procedure Add_Option (Arg : String);
345 -- Add a switch for the Ada, C or C++ compiler, or for the linker.
346 -- The table where this option is stored depends on the values of
347 -- Current_Processor and Current_Language.
348
349 procedure Add_Search_Directories
0da2c8ac
AC
350 (Data : Project_Data;
351 Language : Programming_Language);
9f4fd324
AC
352 -- Either add to the Arguments the necessary -I switches needed to
353 -- compile, or, when compiler is gcc/g++, set up the C*INCLUDE_PATH
354 -- environment variable, if necessary.
355
0da2c8ac 356 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id);
9f4fd324
AC
357 -- Add a source id to Source_Indexes, with Found set to False
358
359 procedure Add_Switches
360 (Data : Project_Data;
361 Proc : Processor;
362 Language : Other_Programming_Language;
363 File_Name : Name_Id);
364 -- Add to Arguments the switches, if any, for a source (attribute Switches)
365 -- or language (attribute Default_Switches), coming from package Compiler
366 -- or Linker (depending on Proc) of a specified project file.
367
0da2c8ac
AC
368 procedure Build_Global_Archive;
369 -- Build the archive for the main project
370
371 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean);
372 -- Build the library for a library project. If Unconditionally is
373 -- False, first check if the library is up to date, and build it only
aa720a54 374 -- if it is not.
9f4fd324 375
0da2c8ac
AC
376 procedure Check (Option : String);
377 -- Check that a switch coming from a project file is not the concatenation
378 -- of several valid switch, for example "-g -v". If it is, issue a warning.
379
380 procedure Check_Archive_Builder;
381 -- Check if the archive builder (ar) is there
382
9f4fd324
AC
383 procedure Check_Compilation_Needed
384 (Source : Other_Source;
385 Need_To_Compile : out Boolean);
386 -- Check if a source of a language other than Ada needs to be compiled or
387 -- recompiled.
388
389 procedure Check_For_C_Plus_Plus;
390 -- Check if C++ is used in at least one project
391
392 procedure Compile
393 (Source_Id : Other_Source_Id;
aa720a54 394 Data : Project_Data;
9f4fd324 395 Local_Errors : in out Boolean);
0da2c8ac 396 -- Compile one non-Ada source
9f4fd324
AC
397
398 procedure Compile_Individual_Sources;
399 -- Compile the sources specified on the command line, when in
400 -- Unique_Compile mode.
401
402 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean);
403 -- Compile/Link with gnatmake when there are Ada sources in the main
aa720a54
AC
404 -- project. Arguments may already contain options to be used by
405 -- gnatmake. Used for both Ada mains and mains of other languages.
9f4fd324
AC
406 -- When Compile_Only is True, do not use the linking options
407
408 procedure Compile_Sources;
409 -- Compile the sources of languages other than Ada, if necessary
410
411 procedure Copyright;
412 -- Output the Copyright notice
413
414 procedure Create_Archive_Dependency_File
aa720a54
AC
415 (Name : String;
416 First_Source : Other_Source_Id);
0da2c8ac
AC
417 -- Create the archive dependency file for a library project
418
419 procedure Create_Global_Archive_Dependency_File (Name : String);
420 -- Create the archive depenency file for the main project
9f4fd324 421
5453d5bd
AC
422 procedure Display_Command
423 (Name : String;
424 Path : String_Access;
425 CPATH : String_Access := null);
9f4fd324
AC
426 -- Display the command for a spawned process, if in Verbose_Mode or
427 -- not in Quiet_Output.
428
429 procedure Get_Compiler (For_Language : Programming_Language);
430 -- Find the compiler name and path name for a specified programming
431 -- language, if not already done. Results are in the corresponding
432 -- elements of arrays Compiler_Names and Compiler_Paths. Name of compiler
433 -- is found in package IDE of the main project, or defaulted.
434 -- Fail if compiler cannot be found on the path. For the Ada language,
435 -- gnatmake, rather than the Ada compiler is returned.
436
437 procedure Get_Imported_Directories
438 (Project : Project_Id;
439 Data : in out Project_Data);
440 -- Find the necessary switches -I to be used when compiling sources
441 -- of languages other than Ada, in a specified project file. Cache the
442 -- result in component Imported_Directories_Switches of the project data.
443 -- For gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
444
445 procedure Initialize;
446 -- Do the necessary package initialization and process the command line
447 -- arguments.
448
0da2c8ac
AC
449 function Is_Included_In_Global_Archive
450 (Object_Name : Name_Id;
451 Project : Project_Id) return Boolean;
452 -- Return True if the object Object_Name is not overridden by a source
453 -- in a project extending project Project.
454
9f4fd324
AC
455 procedure Link_Executables;
456 -- Link executables
457
458 procedure Report_Error (S1 : String; S2 : String := ""; S3 : String := "");
459 -- Report an error. If Keep_Going is False, just call Osint.Fail.
460 -- If Keep_Going is True, display the error and increase the total number
461 -- of errors.
462
463 procedure Report_Total_Errors (Kind : String);
464 -- If Total_Number_Of_Errors is not zero, report it, and fail
465
466 procedure Scan_Arg (Arg : String);
467 -- Process one command line argument
468
469 function Strip_CR_LF (Text : String) return String;
0da2c8ac 470 -- Remove characters ASCII.CR and ASCII.LF from a String
9f4fd324
AC
471
472 procedure Usage;
473 -- Display the usage
474
475 ------------------
476 -- Add_Archives --
477 ------------------
478
479 procedure Add_Archives (For_Gnatmake : Boolean) is
480 Last_Arg : constant Natural := Last_Argument;
481 -- The position of the last argument before adding the archives.
482 -- Used to reverse the order of the arguments added when processing
483 -- the archives.
484
485 procedure Recursive_Add_Archives (Project : Project_Id);
486 -- Recursive procedure to add the archive of a project file, if any,
487 -- then call itself for the project imported.
488
489 ----------------------------
490 -- Recursive_Add_Archives --
491 ----------------------------
492
493 procedure Recursive_Add_Archives (Project : Project_Id) is
494 Data : Project_Data;
495 Imported : Project_List;
496 Prj : Project_Id;
497
0da2c8ac
AC
498 procedure Add_Archive_Path;
499 -- For a library project or the main project, add the archive
500 -- path to the arguments.
501
502 ----------------------
503 -- Add_Archive_Path --
504 ----------------------
505
506 procedure Add_Archive_Path is
507 Increment : Positive;
508 Prev_Last : Positive;
509
510 begin
511 if Data.Library then
512
513 -- If it is a library project file, nothing to do if
514 -- gnatmake will be invoked, because gnatmake will take
515 -- care of it, even if the library is not an Ada library.
516
517 if not For_Gnatmake then
518 if Data.Library_Kind = Static then
519 Add_Argument
520 (Get_Name_String (Data.Library_Dir) &
521 Directory_Separator &
522 "lib" & Get_Name_String (Data.Library_Name) &
523 '.' & Archive_Ext,
524 Verbose_Mode);
525
526 else
527 -- As we first insert in the reverse order,
528 -- -L<dir> is put after -l<lib>
529
530 Add_Argument
531 ("-l" & Get_Name_String (Data.Library_Name),
532 Verbose_Mode);
533
534 Get_Name_String (Data.Library_Dir);
535
536 Add_Argument
537 ("-L" & Name_Buffer (1 .. Name_Len),
538 Verbose_Mode);
539
540 -- If there is a run path option, prepend this
541 -- directory to the library path. It is probable
542 -- that the order of the directories in the path
543 -- option is not important, but just in case
544 -- put the directories in the same order as the
545 -- libraries.
546
547 if Path_Option /= null then
548
549 -- If it is not the first directory, make room
550 -- at the beginning of the table, including
551 -- for a path separator.
552
553 if Lib_Path.Last > 0 then
554 Increment := Name_Len + 1;
555 Prev_Last := Lib_Path.Last;
556 Lib_Path.Set_Last (Prev_Last + Increment);
557
558 for Index in reverse 1 .. Prev_Last loop
559 Lib_Path.Table (Index + Increment) :=
560 Lib_Path.Table (Index);
561 end loop;
562
563 Lib_Path.Table (Increment) := Path_Separator;
564
565 else
566 -- If it is the first directory, just set
567 -- Last to the length of the directory.
568
569 Lib_Path.Set_Last (Name_Len);
570 end if;
571
572 -- Put the directory at the beginning of the
573 -- table.
574
575 for Index in 1 .. Name_Len loop
576 Lib_Path.Table (Index) := Name_Buffer (Index);
577 end loop;
578 end if;
579 end if;
580 end if;
581
582 -- For a non-library project, the only archive needed
15ce9ca2 583 -- is the one for the main project, if there is one.
0da2c8ac 584
15ce9ca2 585 elsif Project = Main_Project and then Global_Archive_Exists then
0da2c8ac
AC
586 Add_Argument
587 (Get_Name_String (Data.Object_Directory) &
588 Directory_Separator &
589 "lib" & Get_Name_String (Data.Name) &
590 '.' & Archive_Ext,
591 Verbose_Mode);
592 end if;
593 end Add_Archive_Path;
594
9f4fd324
AC
595 begin
596 -- Nothing to do when there is no project specified
597
598 if Project /= No_Project then
599 Data := Projects.Table (Project);
600
601 -- Nothing to do if the project has already been processed
602
603 if not Data.Seen then
aa720a54 604
9f4fd324
AC
605 -- Mark the project as processed, to avoid processing it again
606
607 Projects.Table (Project).Seen := True;
608
609 Recursive_Add_Archives (Data.Extends);
610
611 Imported := Data.Imported_Projects;
612
613 -- Call itself recursively for all imported projects
614
615 while Imported /= Empty_Project_List loop
616 Prj := Project_Lists.Table (Imported).Project;
617
618 if Prj /= No_Project then
619 while Projects.Table (Prj).Extended_By /= No_Project loop
620 Prj := Projects.Table (Prj).Extended_By;
621 end loop;
622
623 Recursive_Add_Archives (Prj);
624 end if;
625
626 Imported := Project_Lists.Table (Imported).Next;
627 end loop;
628
629 -- If there is sources of language other than Ada in this
630 -- project, add the path of the archive to Arguments.
631
0da2c8ac
AC
632 if Project = Main_Project
633 or else Data.Other_Sources_Present
634 then
635 Add_Archive_Path;
9f4fd324
AC
636 end if;
637 end if;
638 end if;
639 end Recursive_Add_Archives;
640
0da2c8ac
AC
641 -- Start of processing for Add_Archives
642
9f4fd324
AC
643 begin
644 -- First, mark all projects as not processed
645
646 for Project in 1 .. Projects.Last loop
647 Projects.Table (Project).Seen := False;
648 end loop;
649
650 -- Take care of the run path option
651
652 if Path_Option = null then
653 Path_Option := MLib.Linker_Library_Path_Option;
654 end if;
655
656 Lib_Path.Set_Last (0);
657
658 -- Add archives in the reverse order
659
660 Recursive_Add_Archives (Main_Project);
661
662 -- And reverse the order
663
664 declare
665 First : Positive := Last_Arg + 1;
666 Last : Natural := Last_Argument;
667 Temp : String_Access;
668
669 begin
670 while First < Last loop
671 Temp := Arguments (First);
672 Arguments (First) := Arguments (Last);
673 Arguments (Last) := Temp;
674 First := First + 1;
675 Last := Last - 1;
676 end loop;
677 end;
678 end Add_Archives;
679
680 ------------------
681 -- Add_Argument --
682 ------------------
683
684 procedure Add_Argument (Arg : String_Access; Display : Boolean) is
685 begin
686 -- Nothing to do if no argument is specified or if argument is empty
687
688 if Arg /= null or else Arg'Length = 0 then
aa720a54 689
9f4fd324
AC
690 -- Reallocate arrays if necessary
691
692 if Last_Argument = Arguments'Last then
693 declare
694 New_Arguments : constant Argument_List_Access :=
aa720a54
AC
695 new Argument_List
696 (1 .. Last_Argument +
697 Initial_Argument_Count);
698
9f4fd324 699 New_Arguments_Displayed : constant Booleans :=
aa720a54
AC
700 new Boolean_Array
701 (1 .. Last_Argument +
702 Initial_Argument_Count);
9f4fd324
AC
703
704 begin
705 New_Arguments (Arguments'Range) := Arguments.all;
706
707 -- To avoid deallocating the strings, nullify all components
708 -- of Arguments before calling Free.
709
710 Arguments.all := (others => null);
711
712 Free (Arguments);
713 Arguments := New_Arguments;
714
715 New_Arguments_Displayed (Arguments_Displayed'Range) :=
716 Arguments_Displayed.all;
717 Free (Arguments_Displayed);
718 Arguments_Displayed := New_Arguments_Displayed;
719 end;
720 end if;
721
722 -- Add the argument and its display indication
723
724 Last_Argument := Last_Argument + 1;
725 Arguments (Last_Argument) := Arg;
726 Arguments_Displayed (Last_Argument) := Display;
727 end if;
728 end Add_Argument;
729
730 procedure Add_Argument (Arg : String; Display : Boolean) is
731 Argument : String_Access := null;
aa720a54 732
9f4fd324
AC
733 begin
734 -- Nothing to do if argument is empty
735
736 if Arg'Length > 0 then
737 -- Check if the argument is already in the Cache_Args table.
738 -- If it is already there, reuse the allocated value.
739
740 for Index in 1 .. Cache_Args.Last loop
741 if Cache_Args.Table (Index).all = Arg then
742 Argument := Cache_Args.Table (Index);
743 exit;
744 end if;
745 end loop;
746
747 -- If the argument is not in the cache, create a new entry in the
748 -- cache.
749
750 if Argument = null then
751 Argument := new String'(Arg);
752 Cache_Args.Increment_Last;
753 Cache_Args.Table (Cache_Args.Last) := Argument;
754 end if;
755
756 -- And add the argument
757
758 Add_Argument (Argument, Display);
759 end if;
760 end Add_Argument;
761
762 -------------------
763 -- Add_Arguments --
764 -------------------
765
766 procedure Add_Arguments (Args : Argument_List; Display : Boolean) is
767 begin
768 -- Reallocate the arrays, if necessary
769
770 if Last_Argument + Args'Length > Arguments'Last then
771 declare
772 New_Arguments : constant Argument_List_Access :=
0da2c8ac
AC
773 new Argument_List
774 (1 .. Last_Argument + Args'Length +
775 Initial_Argument_Count);
776
9f4fd324 777 New_Arguments_Displayed : constant Booleans :=
0da2c8ac
AC
778 new Boolean_Array
779 (1 .. Last_Argument +
780 Args'Length +
781 Initial_Argument_Count);
9f4fd324
AC
782
783 begin
784 New_Arguments (1 .. Last_Argument) :=
785 Arguments (1 .. Last_Argument);
786
787 -- To avoid deallocating the strings, nullify all components
788 -- of Arguments before calling Free.
789
790 Arguments.all := (others => null);
791 Free (Arguments);
792
793 Arguments := New_Arguments;
794 New_Arguments_Displayed (1 .. Last_Argument) :=
795 Arguments_Displayed (1 .. Last_Argument);
796 Free (Arguments_Displayed);
797 Arguments_Displayed := New_Arguments_Displayed;
798 end;
799 end if;
800
801 -- Add the new arguments and the display indications
802
803 Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
804 Arguments_Displayed (Last_Argument + 1 .. Last_Argument + Args'Length) :=
805 (others => Display);
806 Last_Argument := Last_Argument + Args'Length;
807 end Add_Arguments;
808
809 ----------------
810 -- Add_Option --
811 ----------------
812
813 procedure Add_Option (Arg : String) is
814 Option : constant String_Access := new String'(Arg);
aa720a54 815
9f4fd324
AC
816 begin
817 case Current_Processor is
818 when None =>
819 null;
820
821 when Linker =>
aa720a54 822
9f4fd324
AC
823 -- Add option to the linker table
824
825 Linker_Options.Increment_Last;
826 Linker_Options.Table (Linker_Options.Last) := Option;
827
828 when Compiler =>
aa720a54 829
9f4fd324
AC
830 -- Add option to the compiler option table, depending on the
831 -- value of Current_Language.
832
833 Comp_Opts.Increment_Last (Options (Current_Language));
834 Options (Current_Language).Table
835 (Comp_Opts.Last (Options (Current_Language))) := Option;
836
837 end case;
838 end Add_Option;
839
840 -------------------
841 -- Add_Source_Id --
842 -------------------
843
0da2c8ac 844 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id) is
9f4fd324
AC
845 begin
846 -- Reallocate the array, if necessary
847
848 if Last_Source = Source_Indexes'Last then
849 declare
850 New_Indexes : constant Source_Indexes_Ref :=
aa720a54
AC
851 new Source_Index_Array
852 (1 .. Source_Indexes'Last +
853 Initial_Source_Index_Count);
9f4fd324
AC
854 begin
855 New_Indexes (Source_Indexes'Range) := Source_Indexes.all;
856 Free (Source_Indexes);
857 Source_Indexes := New_Indexes;
858 end;
859 end if;
860
861 Last_Source := Last_Source + 1;
0da2c8ac 862 Source_Indexes (Last_Source) := (Project, Id, False);
9f4fd324
AC
863 end Add_Source_Id;
864
865 ----------------------------
866 -- Add_Search_Directories --
867 ----------------------------
868
869 procedure Add_Search_Directories
aa720a54
AC
870 (Data : Project_Data;
871 Language : Programming_Language)
9f4fd324
AC
872 is
873 begin
874 -- If a GNU compiler is used, set the CPATH environment variable,
875 -- if it does not already has the correct value.
876
877 if Compiler_Is_Gcc (Language) then
878 if Current_Include_Paths (Language) /= Data.Include_Path then
879 Current_Include_Paths (Language) := Data.Include_Path;
880 Setenv (CPATH, Data.Include_Path.all);
881 end if;
882
883 else
884 Add_Arguments (Data.Imported_Directories_Switches.all, Verbose_Mode);
885 end if;
886 end Add_Search_Directories;
887
888 ------------------
889 -- Add_Switches --
890 ------------------
891
892 procedure Add_Switches
893 (Data : Project_Data;
894 Proc : Processor;
895 Language : Other_Programming_Language;
896 File_Name : Name_Id)
897 is
898 Switches : Variable_Value;
899 -- The switches, if any, for the file/language
900
901 Pkg : Package_Id;
902 -- The id of the package where to look for the switches
903
904 Defaults : Array_Element_Id;
905 -- The Default_Switches associative array
906
907 Switches_Array : Array_Element_Id;
908 -- The Switches associative array
909
910 Element_Id : String_List_Id;
911 Element : String_Element;
912
913 begin
914 -- First, choose the proper package
915
916 case Proc is
917 when None =>
918 raise Program_Error;
919
920 when Linker =>
921 Pkg := Value_Of (Name_Linker, Data.Decl.Packages);
922
923 when Compiler =>
924 Pkg := Value_Of (Name_Compiler, Data.Decl.Packages);
925 end case;
926
927 -- Get the Switches ("file name"), if they exist
aa720a54 928
9f4fd324
AC
929 Switches_Array := Prj.Util.Value_Of
930 (Name => Name_Switches,
931 In_Arrays =>
932 Packages.Table (Pkg).Decl.Arrays);
933
934 Switches :=
935 Prj.Util.Value_Of
aa720a54
AC
936 (Index => File_Name,
937 Src_Index => 0,
938 In_Array => Switches_Array);
9f4fd324
AC
939
940 -- Otherwise, get the Default_Switches ("language"), if they exist
941
942 if Switches = Nil_Variable_Value then
943 Defaults := Prj.Util.Value_Of
944 (Name => Name_Default_Switches,
945 In_Arrays => Packages.Table (Pkg).Decl.Arrays);
946 Switches := Prj.Util.Value_Of
aa720a54
AC
947 (Index => Lang_Name_Ids (Language),
948 Src_Index => 0,
949 In_Array => Defaults);
9f4fd324
AC
950 end if;
951
952 -- If there are switches, add them to Arguments
953
954 if Switches /= Nil_Variable_Value then
955 Element_Id := Switches.Values;
9f4fd324
AC
956 while Element_Id /= Nil_String loop
957 Element := String_Elements.Table (Element_Id);
958
959 if Element.Value /= No_Name then
0da2c8ac
AC
960 Get_Name_String (Element.Value);
961
962 if not Quiet_Output then
963
964 -- When not in quiet output (no -q), check that the switch
965 -- is not the concatenation of several valid switches,
966 -- such as "-g -v". If it is, issue a warning.
967
968 Check (Option => Name_Buffer (1 .. Name_Len));
969 end if;
970
971 Add_Argument (Name_Buffer (1 .. Name_Len), True);
9f4fd324
AC
972 end if;
973
974 Element_Id := Element.Next;
975 end loop;
976 end if;
977 end Add_Switches;
978
0da2c8ac
AC
979 --------------------------
980 -- Build_Global_Archive --
981 --------------------------
9f4fd324 982
0da2c8ac
AC
983 procedure Build_Global_Archive is
984 Data : Project_Data := Projects.Table (Main_Project);
9f4fd324
AC
985 Source_Id : Other_Source_Id;
986 Source : Other_Source;
987 Success : Boolean;
988
989 Archive_Name : constant String :=
990 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
991 -- The name of the archive file for this project
992
993 Archive_Dep_Name : constant String :=
994 "lib" & Get_Name_String (Data.Name) & ".deps";
995 -- The name of the archive dependency file for this project
996
0da2c8ac 997 Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
9f4fd324
AC
998 -- When True, archive will be rebuilt
999
1000 File : Prj.Util.Text_File;
1001
0da2c8ac
AC
1002 Object_Path : Name_Id;
1003 Time_Stamp : Time_Stamp_Type;
9f4fd324
AC
1004
1005 Saved_Last_Argument : Natural;
0da2c8ac
AC
1006 First_Object : Natural;
1007
1008 Discard : Boolean;
aa720a54 1009
9f4fd324 1010 begin
0da2c8ac 1011 Check_Archive_Builder;
9f4fd324 1012
0da2c8ac 1013 Change_Dir (Get_Name_String (Data.Object_Directory));
9f4fd324 1014
0da2c8ac
AC
1015 if not Need_To_Rebuild then
1016 if Verbose_Mode then
1017 Write_Str (" Checking ");
1018 Write_Line (Archive_Name);
9f4fd324
AC
1019 end if;
1020
0da2c8ac 1021 -- If the archive does not exist, of course it needs to be built
9f4fd324 1022
0da2c8ac
AC
1023 if not Is_Regular_File (Archive_Name) then
1024 Need_To_Rebuild := True;
1025
1026 if Verbose_Mode then
1027 Write_Line (" -> archive does not exist");
1028 end if;
1029
1030 -- Archive does exist
1031
1032 else
1033 -- Check the archive dependency file
1034
1035 Open (File, Archive_Dep_Name);
1036
1037 -- If the archive dependency file does not exist, we need to
1038 -- to rebuild the archive and to create its dependency file.
1039
1040 if not Is_Valid (File) then
1041 Need_To_Rebuild := True;
1042
1043 if Verbose_Mode then
1044 Write_Str (" -> archive dependency file ");
1045 Write_Str (Archive_Dep_Name);
1046 Write_Line (" does not exist");
1047 end if;
1048
1049 else
1050 -- Put all sources of language other than Ada in
1051 -- Source_Indexes.
1052
1053 for Proj in 1 .. Projects.Last loop
1054 Data := Projects.Table (Proj);
1055
1056 if not Data.Library then
1057 Last_Source := 0;
1058 Source_Id := Data.First_Other_Source;
1059
1060 while Source_Id /= No_Other_Source loop
1061 Add_Source_Id (Proj, Source_Id);
1062 Source_Id := Other_Sources.Table (Source_Id).Next;
1063 end loop;
1064 end if;
1065 end loop;
1066
1067 -- Read the dependency file, line by line
1068
1069 while not End_Of_File (File) loop
1070 Get_Line (File, Name_Buffer, Name_Len);
1071
1072 -- First line is the path of the object file
1073
1074 Object_Path := Name_Find;
1075 Source_Id := No_Other_Source;
1076
1077 -- Check if this object file is for a source of this project
1078
1079 for S in 1 .. Last_Source loop
1080 Source_Id := Source_Indexes (S).Id;
1081 Source := Other_Sources.Table (Source_Id);
1082
1083 if (not Source_Indexes (S).Found)
1084 and then Source.Object_Path = Object_Path
1085 then
1086 -- We have found the object file: get the source
1087 -- data, and mark it as found.
1088
1089 Source_Indexes (S).Found := True;
1090 exit;
1091 end if;
1092 end loop;
1093
1094 -- If it is not for a source of this project, then the
1095 -- archive needs to be rebuilt.
1096
1097 if Source_Id = No_Other_Source then
1098 Need_To_Rebuild := True;
1099 if Verbose_Mode then
1100 Write_Str (" -> ");
1101 Write_Str (Get_Name_String (Object_Path));
1102 Write_Line (" is not an object of any project");
1103 end if;
1104
1105 exit;
1106 end if;
1107
1108 -- The second line is the time stamp of the object file.
1109 -- If there is no next line, then the dependency file is
1110 -- truncated, and the archive need to be rebuilt.
1111
1112 if End_Of_File (File) then
1113 Need_To_Rebuild := True;
1114
1115 if Verbose_Mode then
1116 Write_Str (" -> archive dependency file ");
1117 Write_Line (" is truncated");
1118 end if;
1119
1120 exit;
1121 end if;
1122
1123 Get_Line (File, Name_Buffer, Name_Len);
1124
1125 -- If the line has the wrong number of characters, then
1126 -- the dependency file is incorrectly formatted, and the
1127 -- archive needs to be rebuilt.
1128
1129 if Name_Len /= Time_Stamp_Length then
1130 Need_To_Rebuild := True;
1131
1132 if Verbose_Mode then
1133 Write_Str (" -> archive dependency file ");
1134 Write_Line (" is incorrectly formatted (time stamp)");
1135 end if;
1136
1137 exit;
1138 end if;
1139
1140 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1141
1142 -- If the time stamp in the dependency file is different
1143 -- from the time stamp of the object file, then the archive
1144 -- needs to be rebuilt.
1145
1146 if Time_Stamp /= Source.Object_TS then
1147 Need_To_Rebuild := True;
1148
1149 if Verbose_Mode then
1150 Write_Str (" -> time stamp of ");
1151 Write_Str (Get_Name_String (Object_Path));
1152 Write_Str (" is incorrect in the archive");
1153 Write_Line (" dependency file");
1154 end if;
1155
1156 exit;
1157 end if;
1158 end loop;
1159
1160 Close (File);
1161 end if;
1162 end if;
1163 end if;
1164
1165 if not Need_To_Rebuild then
1166 if Verbose_Mode then
1167 Write_Line (" -> up to date");
1168 end if;
1169
1170 -- Archive needs to be rebuilt
1171
1172 else
0da2c8ac
AC
1173 -- If archive already exists, first delete it
1174
1175 -- Comment needed on why we discard result???
1176
1177 if Is_Regular_File (Archive_Name) then
1178 Delete_File (Archive_Name, Discard);
1179 end if;
1180
1181 Last_Argument := 0;
1182
1183 -- Start with the options found in MLib.Tgt (usually just "rc")
1184
1185 Add_Arguments (Archive_Builder_Options.all, True);
1186
1187 -- Followed by the archive name
1188
1189 Add_Argument (Archive_Name, True);
1190
1191 First_Object := Last_Argument;
1192
1193 -- Followed by all the object files of the non library projects
1194
1195 for Proj in 1 .. Projects.Last loop
1196 Data := Projects.Table (Proj);
1197
1198 if not Data.Library then
1199 Source_Id := Data.First_Other_Source;
1200
1201 while Source_Id /= No_Other_Source loop
1202 Source := Other_Sources.Table (Source_Id);
1203
1204 -- Only include object file name that have not been
1205 -- overriden in extending projects.
1206
1207 if Is_Included_In_Global_Archive
1208 (Source.Object_Name, Proj)
1209 then
1210 Add_Argument
1211 (Get_Name_String (Source.Object_Path), Verbose_Mode);
1212 end if;
1213
1214 Source_Id := Source.Next;
1215 end loop;
1216 end if;
1217 end loop;
1218
15ce9ca2
AC
1219 -- No need to create a global archive, if there is no object
1220 -- file to put into.
0da2c8ac 1221
15ce9ca2 1222 Global_Archive_Exists := Last_Argument > First_Object;
0da2c8ac 1223
15ce9ca2
AC
1224 if Global_Archive_Exists then
1225 -- If the archive is built, then linking will need to occur
1226 -- unconditionally.
0da2c8ac 1227
15ce9ca2 1228 Need_To_Relink := True;
0da2c8ac 1229
15ce9ca2 1230 -- Spawn the archive builder (ar)
0da2c8ac 1231
15ce9ca2 1232 Saved_Last_Argument := Last_Argument;
0da2c8ac 1233
15ce9ca2 1234 Last_Argument := First_Object + Max_In_Archives;
0da2c8ac 1235
15ce9ca2
AC
1236 loop
1237 if Last_Argument > Saved_Last_Argument then
1238 Last_Argument := Saved_Last_Argument;
1239 end if;
0da2c8ac 1240
15ce9ca2 1241 Display_Command (Archive_Builder, Archive_Builder_Path);
0da2c8ac 1242
15ce9ca2
AC
1243 Spawn
1244 (Archive_Builder_Path.all,
1245 Arguments (1 .. Last_Argument),
1246 Success);
0da2c8ac 1247
15ce9ca2 1248 exit when not Success;
0da2c8ac 1249
15ce9ca2
AC
1250 exit when Last_Argument = Saved_Last_Argument;
1251
1252 Arguments (1) := r;
1253 Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
1254 Arguments (Last_Argument + 1 .. Saved_Last_Argument);
1255 Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
1256 end loop;
1257
1258 -- If the archive was built, run the archive indexer (ranlib)
0da2c8ac
AC
1259 -- if there is one.
1260
15ce9ca2 1261 if Success then
0da2c8ac 1262
15ce9ca2
AC
1263 -- If the archive was built, run the archive indexer (ranlib),
1264 -- if there is one.
0da2c8ac 1265
15ce9ca2
AC
1266 if Archive_Indexer_Path /= null then
1267 Last_Argument := 0;
1268 Add_Argument (Archive_Name, True);
0da2c8ac 1269
15ce9ca2 1270 Display_Command (Archive_Indexer, Archive_Indexer_Path);
0da2c8ac 1271
15ce9ca2
AC
1272 Spawn
1273 (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
0da2c8ac 1274
15ce9ca2
AC
1275 if not Success then
1276
1277 -- Running ranlib failed, delete the dependency file,
1278 -- if it exists.
1279
1280 if Is_Regular_File (Archive_Dep_Name) then
1281 Delete_File (Archive_Dep_Name, Success);
1282 end if;
0da2c8ac 1283
15ce9ca2 1284 -- And report the error
0da2c8ac 1285
15ce9ca2
AC
1286 Report_Error
1287 ("running" & Archive_Indexer & " for project """,
1288 Get_Name_String (Data.Name),
1289 """ failed");
1290 return;
1291 end if;
0da2c8ac 1292 end if;
0da2c8ac 1293
15ce9ca2 1294 -- The archive was correctly built, create its dependency file
0da2c8ac 1295
15ce9ca2 1296 Create_Global_Archive_Dependency_File (Archive_Dep_Name);
0da2c8ac 1297
15ce9ca2
AC
1298 -- Building the archive failed, delete dependency file if one
1299 -- exists.
0da2c8ac 1300
15ce9ca2
AC
1301 else
1302 if Is_Regular_File (Archive_Dep_Name) then
1303 Delete_File (Archive_Dep_Name, Success);
1304 end if;
0da2c8ac 1305
15ce9ca2 1306 -- And report the error
0da2c8ac 1307
15ce9ca2
AC
1308 Report_Error
1309 ("building archive for project """,
1310 Get_Name_String (Data.Name),
1311 """ failed");
1312 end if;
9f4fd324
AC
1313 end if;
1314 end if;
0da2c8ac
AC
1315 end Build_Global_Archive;
1316
1317 -------------------
1318 -- Build_Library --
1319 -------------------
1320
1321 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean) is
1322 Data : constant Project_Data := Projects.Table (Project);
1323 Source_Id : Other_Source_Id;
1324 Source : Other_Source;
1325
1326 Archive_Name : constant String :=
1327 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
1328 -- The name of the archive file for this project
1329
1330 Archive_Dep_Name : constant String :=
1331 "lib" & Get_Name_String (Data.Name) & ".deps";
1332 -- The name of the archive dependency file for this project
1333
1334 Need_To_Rebuild : Boolean := Unconditionally;
1335 -- When True, archive will be rebuilt
1336
1337 File : Prj.Util.Text_File;
1338
1339 Object_Name : Name_Id;
1340 Time_Stamp : Time_Stamp_Type;
1341
1342 begin
1343 Check_Archive_Builder;
9f4fd324
AC
1344
1345 -- If Unconditionally is False, check if the archive need to be built
1346
1347 if not Need_To_Rebuild then
1348 if Verbose_Mode then
1349 Write_Str (" Checking ");
1350 Write_Line (Archive_Name);
1351 end if;
1352
1353 -- If the archive does not exist, of course it needs to be built
1354
1355 if not Is_Regular_File (Archive_Name) then
1356 Need_To_Rebuild := True;
1357
1358 if Verbose_Mode then
1359 Write_Line (" -> archive does not exist");
1360 end if;
1361
aa720a54
AC
1362 -- Archive does exist
1363
9f4fd324
AC
1364 else
1365 -- Check the archive dependency file
1366
1367 Open (File, Archive_Dep_Name);
1368
1369 -- If the archive dependency file does not exist, we need to
1370 -- to rebuild the archive and to create its dependency file.
1371
1372 if not Is_Valid (File) then
1373 Need_To_Rebuild := True;
1374
1375 if Verbose_Mode then
1376 Write_Str (" -> archive dependency file ");
1377 Write_Str (Archive_Dep_Name);
1378 Write_Line (" does not exist");
1379 end if;
1380
1381 else
0da2c8ac 1382 -- Put all sources of language other than Ada in Source_Indexes
9f4fd324
AC
1383
1384 Last_Source := 0;
1385 Source_Id := Data.First_Other_Source;
1386
1387 while Source_Id /= No_Other_Source loop
0da2c8ac 1388 Add_Source_Id (Project, Source_Id);
9f4fd324
AC
1389 Source_Id := Other_Sources.Table (Source_Id).Next;
1390 end loop;
1391
1392 -- Read the dependency file, line by line
1393
1394 while not End_Of_File (File) loop
1395 Get_Line (File, Name_Buffer, Name_Len);
1396
1397 -- First line is the name of an object file
1398
1399 Object_Name := Name_Find;
1400 Source_Id := No_Other_Source;
1401
aa720a54 1402 -- Check if this object file is for a source of this project
9f4fd324
AC
1403
1404 for S in 1 .. Last_Source loop
1405 if (not Source_Indexes (S).Found) and then
1406 Other_Sources.Table
1407 (Source_Indexes (S).Id).Object_Name =
1408 Object_Name
1409 then
1410 -- We have found the object file: get the source
1411 -- data, and mark it as found.
1412
1413 Source_Id := Source_Indexes (S).Id;
1414 Source := Other_Sources.Table (Source_Id);
1415 Source_Indexes (S).Found := True;
1416 exit;
1417 end if;
1418 end loop;
1419
1420 -- If it is not for a source of this project, then the
1421 -- archive needs to be rebuilt.
1422
1423 if Source_Id = No_Other_Source then
1424 Need_To_Rebuild := True;
0da2c8ac 1425
9f4fd324
AC
1426 if Verbose_Mode then
1427 Write_Str (" -> ");
1428 Write_Str (Get_Name_String (Object_Name));
1429 Write_Line (" is not an object of the project");
1430 end if;
1431
1432 exit;
1433 end if;
1434
1435 -- The second line is the time stamp of the object file.
1436 -- If there is no next line, then the dependency file is
1437 -- truncated, and the archive need to be rebuilt.
1438
1439 if End_Of_File (File) then
1440 Need_To_Rebuild := True;
1441
1442 if Verbose_Mode then
1443 Write_Str (" -> archive dependency file ");
1444 Write_Line (" is truncated");
1445 end if;
1446
1447 exit;
1448 end if;
1449
1450 Get_Line (File, Name_Buffer, Name_Len);
1451
1452 -- If the line has the wrong number of character, then
1453 -- the dependency file is incorrectly formatted, and the
1454 -- archive needs to be rebuilt.
1455
1456 if Name_Len /= Time_Stamp_Length then
1457 Need_To_Rebuild := True;
1458
1459 if Verbose_Mode then
1460 Write_Str (" -> archive dependency file ");
1461 Write_Line (" is incorrectly formatted (time stamp)");
1462 end if;
1463
1464 exit;
1465 end if;
1466
1467 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1468
1469 -- If the time stamp in the dependency file is different
1470 -- from the time stamp of the object file, then the archive
1471 -- needs to be rebuilt.
1472
1473 if Time_Stamp /= Source.Object_TS then
1474 Need_To_Rebuild := True;
1475
1476 if Verbose_Mode then
1477 Write_Str (" -> time stamp of ");
1478 Write_Str (Get_Name_String (Object_Name));
1479 Write_Str (" is incorrect in the archive");
1480 Write_Line (" dependency file");
1481 end if;
1482
1483 exit;
1484 end if;
1485 end loop;
1486
1487 Close (File);
1488
1489 if not Need_To_Rebuild then
aa720a54 1490
9f4fd324
AC
1491 -- Now, check if all object files of the project have been
1492 -- accounted for. If any of them is not in the dependency
1493 -- file, the archive needs to be rebuilt.
1494
1495 for Index in 1 .. Last_Source loop
1496 if not Source_Indexes (Index).Found then
1497 Need_To_Rebuild := True;
1498
1499 if Verbose_Mode then
1500 Source_Id := Source_Indexes (Index).Id;
1501 Source := Other_Sources.Table (Source_Id);
1502 Write_Str (" -> ");
1503 Write_Str (Get_Name_String (Source.Object_Name));
1504 Write_Str (" is not in the archive ");
1505 Write_Line ("dependency file");
1506 end if;
1507
1508 exit;
1509 end if;
1510 end loop;
1511 end if;
1512
1513 if (not Need_To_Rebuild) and Verbose_Mode then
1514 Write_Line (" -> up to date");
1515 end if;
1516 end if;
1517 end if;
1518 end if;
1519
0da2c8ac 1520 -- Build the library if necessary
9f4fd324
AC
1521
1522 if Need_To_Rebuild then
aa720a54 1523
0da2c8ac 1524 -- If a library is built, then linking will need to occur
9f4fd324
AC
1525 -- unconditionally.
1526
1527 Need_To_Relink := True;
1528
1529 Last_Argument := 0;
1530
9f4fd324
AC
1531 -- If there are sources in Ada, then gnatmake will build the
1532 -- library, so nothing to do.
1533
1534 if not Data.Languages (Lang_Ada) then
aa720a54 1535
9f4fd324
AC
1536 -- Get all the object files of the project
1537
1538 Source_Id := Data.First_Other_Source;
1539
1540 while Source_Id /= No_Other_Source loop
1541 Source := Other_Sources.Table (Source_Id);
1542 Add_Argument
1543 (Get_Name_String (Source.Object_Name), Verbose_Mode);
1544 Source_Id := Source.Next;
1545 end loop;
1546
1547 -- If it is a library, it need to be built it the same way
1548 -- Ada libraries are built.
1549
1550 if Data.Library_Kind = Static then
1551 MLib.Build_Library
1552 (Ofiles => Arguments (1 .. Last_Argument),
1553 Afiles => No_Argument,
1554 Output_File => Get_Name_String (Data.Library_Name),
1555 Output_Dir => Get_Name_String (Data.Library_Dir));
1556
1557 else
1558 MLib.Tgt.Build_Dynamic_Library
1559 (Ofiles => Arguments (1 .. Last_Argument),
1560 Foreign => Arguments (1 .. Last_Argument),
1561 Afiles => No_Argument,
1562 Options => No_Argument,
1563 Interfaces => No_Argument,
1564 Lib_Filename => Get_Name_String (Data.Library_Name),
1565 Lib_Dir => Get_Name_String (Data.Library_Dir),
1566 Symbol_Data => No_Symbols,
1567 Driver_Name => No_Name,
9f4fd324 1568 Lib_Version => "",
9f4fd324
AC
1569 Auto_Init => False);
1570 end if;
0da2c8ac 1571 end if;
9f4fd324 1572
0da2c8ac 1573 -- Create fake empty archive, so we can check its time stamp later
9f4fd324 1574
0da2c8ac
AC
1575 declare
1576 Archive : Ada.Text_IO.File_Type;
1577 use Ada.Text_IO;
1578 begin
1579 Create (Archive, Out_File, Archive_Name);
1580 Close (Archive);
1581 end;
9f4fd324 1582
0da2c8ac
AC
1583 Create_Archive_Dependency_File
1584 (Archive_Dep_Name, Data.First_Other_Source);
9f4fd324 1585
0da2c8ac
AC
1586 end if;
1587 end Build_Library;
9f4fd324 1588
0da2c8ac
AC
1589 -----------
1590 -- Check --
1591 -----------
aa720a54 1592
0da2c8ac
AC
1593 procedure Check (Option : String) is
1594 First : Positive := Option'First;
1595 Last : Natural;
9f4fd324 1596
0da2c8ac
AC
1597 begin
1598 for Index in Option'First + 1 .. Option'Last - 1 loop
1599 if Option (Index) = ' ' and then Option (Index + 1) = '-' then
1600 Write_Str ("warning: switch """);
1601 Write_Str (Option);
1602 Write_Str (""" is suspicious; consider using ");
1603
1604 Last := First;
1605 while Last <= Option'Last loop
1606 if Option (Last) = ' ' then
1607 if First /= Option'First then
1608 Write_Str (", ");
1609 end if;
9f4fd324 1610
0da2c8ac
AC
1611 Write_Char ('"');
1612 Write_Str (Option (First .. Last - 1));
1613 Write_Char ('"');
9f4fd324 1614
0da2c8ac
AC
1615 while Last <= Option'Last and then Option (Last) = ' ' loop
1616 Last := Last + 1;
1617 end loop;
9f4fd324 1618
0da2c8ac 1619 First := Last;
aa720a54 1620
0da2c8ac
AC
1621 else
1622 if Last = Option'Last then
1623 if First /= Option'First then
1624 Write_Str (", ");
1625 end if;
9f4fd324 1626
0da2c8ac
AC
1627 Write_Char ('"');
1628 Write_Str (Option (First .. Last));
1629 Write_Char ('"');
9f4fd324
AC
1630 end if;
1631
0da2c8ac 1632 Last := Last + 1;
9f4fd324 1633 end if;
0da2c8ac 1634 end loop;
9f4fd324 1635
0da2c8ac
AC
1636 Write_Line (" instead");
1637 exit;
1638 end if;
1639 end loop;
1640 end Check;
9f4fd324 1641
0da2c8ac
AC
1642 ---------------------------
1643 -- Check_Archive_Builder --
1644 ---------------------------
9f4fd324 1645
0da2c8ac
AC
1646 procedure Check_Archive_Builder is
1647 begin
1648 -- First, make sure that the archive builder (ar) is on the path
9f4fd324 1649
0da2c8ac
AC
1650 if Archive_Builder_Path = null then
1651 Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
9f4fd324 1652
0da2c8ac
AC
1653 if Archive_Builder_Path = null then
1654 Osint.Fail
1655 ("unable to locate archive builder """,
1656 Archive_Builder,
1657 """");
1658 end if;
9f4fd324 1659
0da2c8ac
AC
1660 -- If there is an archive indexer (ranlib), try to locate it on the
1661 -- path. Don't fail if it is not found.
1662
1663 if Archive_Indexer /= "" then
1664 Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
9f4fd324
AC
1665 end if;
1666 end if;
0da2c8ac 1667 end Check_Archive_Builder;
9f4fd324
AC
1668
1669 ------------------------------
1670 -- Check_Compilation_Needed --
1671 ------------------------------
1672
1673 procedure Check_Compilation_Needed
1674 (Source : Other_Source;
1675 Need_To_Compile : out Boolean)
1676 is
1677 Source_Name : constant String := Get_Name_String (Source.File_Name);
1678 Source_Path : constant String := Get_Name_String (Source.Path_Name);
1679 Object_Name : constant String := Get_Name_String (Source.Object_Name);
1680 Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
1681
1682 Source_In_Dependencies : Boolean := False;
0da2c8ac 1683 -- Set True if source was found in dependency file of its object file
9f4fd324
AC
1684
1685 Dep_File : Prj.Util.Text_File;
aa720a54
AC
1686 Start : Natural;
1687 Finish : Natural;
1688
9f4fd324
AC
1689 begin
1690 -- Assume the worst, so that statement "return;" may be used if there
1691 -- is any problem.
1692
1693 Need_To_Compile := True;
1694
1695 if Verbose_Mode then
1696 Write_Str (" Checking ");
1697 Write_Str (Source_Name);
1698 Write_Line (" ... ");
1699 end if;
1700
0da2c8ac 1701 -- If object file does not exist, of course source need to be compiled
9f4fd324
AC
1702
1703 if Source.Object_TS = Empty_Time_Stamp then
1704 if Verbose_Mode then
1705 Write_Str (" -> object file ");
1706 Write_Str (Object_Name);
1707 Write_Line (" does not exist");
1708 end if;
1709
1710 return;
1711 end if;
1712
1713 -- If the object file has been created before the last modification
1714 -- of the source, the source need to be recompiled.
1715
1716 if Source.Object_TS < Source.Source_TS then
1717 if Verbose_Mode then
1718 Write_Str (" -> object file ");
1719 Write_Str (Object_Name);
1720 Write_Line (" has time stamp earlier than source");
1721 end if;
1722
1723 return;
1724 end if;
1725
1726 -- If there is no dependency file, then the source needs to be
1727 -- recompiled and the dependency file need to be created.
1728
1729 if Source.Dep_TS = Empty_Time_Stamp then
1730 if Verbose_Mode then
1731 Write_Str (" -> dependency file ");
1732 Write_Str (Dep_Name);
1733 Write_Line (" does not exist");
1734 end if;
1735
1736 return;
1737 end if;
1738
1739 -- The source needs to be recompiled if the source has been modified
1740 -- after the dependency file has been created.
1741
1742 if Source.Dep_TS < Source.Source_TS then
1743 if Verbose_Mode then
1744 Write_Str (" -> dependency file ");
1745 Write_Str (Dep_Name);
1746 Write_Line (" has time stamp earlier than source");
1747 end if;
1748
1749 return;
1750 end if;
1751
1752 -- Look for all dependencies
1753
1754 Open (Dep_File, Dep_Name);
1755
aa720a54 1756 -- If dependency file cannot be open, we need to recompile the source
9f4fd324
AC
1757
1758 if not Is_Valid (Dep_File) then
1759 if Verbose_Mode then
1760 Write_Str (" -> could not open dependency file ");
1761 Write_Line (Dep_Name);
1762 end if;
1763
1764 return;
1765 end if;
1766
1767 declare
1768 End_Of_File_Reached : Boolean := False;
aa720a54 1769
9f4fd324
AC
1770 begin
1771 loop
1772 if End_Of_File (Dep_File) then
1773 End_Of_File_Reached := True;
1774 exit;
1775 end if;
1776
1777 Get_Line (Dep_File, Name_Buffer, Name_Len);
1778
1779 exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
1780 end loop;
1781
1782 -- If dependency file contains only empty lines or comments, then
0da2c8ac 1783 -- dependencies are unknown, and the source needs to be recompiled.
9f4fd324
AC
1784
1785 if End_Of_File_Reached then
1786 if Verbose_Mode then
1787 Write_Str (" -> dependency file ");
1788 Write_Str (Dep_Name);
1789 Write_Line (" is empty");
1790 end if;
1791
1792 Close (Dep_File);
1793 return;
1794 end if;
1795 end;
1796
1797 Start := 1;
1798 Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
1799
0da2c8ac 1800 -- First line must start with name of object file, followed by colon
9f4fd324
AC
1801
1802 if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
1803 if Verbose_Mode then
1804 Write_Str (" -> dependency file ");
1805 Write_Str (Dep_Name);
1806 Write_Line (" has wrong format");
1807 end if;
1808
1809 Close (Dep_File);
1810 return;
1811
1812 else
1813 Start := Finish + 2;
1814
1815 -- Process each line
1816
1817 Line_Loop : loop
1818 declare
0da2c8ac 1819 Line : constant String := Name_Buffer (1 .. Name_Len);
9f4fd324 1820 Last : constant Natural := Name_Len;
aa720a54 1821
9f4fd324
AC
1822 begin
1823 Name_Loop : loop
aa720a54 1824
9f4fd324
AC
1825 -- Find the beginning of the next source path name
1826
1827 while Start < Last and then Line (Start) = ' ' loop
1828 Start := Start + 1;
1829 end loop;
1830
1831 -- Go to next line when there is a continuation character \
1832 -- at the end of the line.
1833
1834 exit Name_Loop when Start = Last
1835 and then Line (Start) = '\';
1836
1837 -- We should not be at the end of the line, without
1838 -- a continuation character \.
1839
1840 if Start = Last then
1841 if Verbose_Mode then
1842 Write_Str (" -> dependency file ");
1843 Write_Str (Dep_Name);
1844 Write_Line (" has wrong format");
1845 end if;
1846
1847 Close (Dep_File);
1848 return;
1849 end if;
1850
1851 -- Look for the end of the source path name
1852
1853 Finish := Start;
1854 while Finish < Last and then Line (Finish + 1) /= ' ' loop
1855 Finish := Finish + 1;
1856 end loop;
1857
1858 -- Check this source
1859
1860 declare
1861 Src_Name : constant String :=
aa720a54
AC
1862 Normalize_Pathname
1863 (Name => Line (Start .. Finish),
1864 Case_Sensitive => False);
9f4fd324 1865 Src_TS : Time_Stamp_Type;
aa720a54 1866
9f4fd324 1867 begin
aa720a54 1868 -- If it is original source, set Source_In_Dependencies
9f4fd324
AC
1869
1870 if Src_Name = Source_Path then
1871 Source_In_Dependencies := True;
1872 end if;
1873
1874 Name_Len := 0;
1875 Add_Str_To_Name_Buffer (Src_Name);
1876 Src_TS := File_Stamp (Name_Find);
1877
1878 -- If the source does not exist, we need to recompile
1879
1880 if Src_TS = Empty_Time_Stamp then
1881 if Verbose_Mode then
1882 Write_Str (" -> source ");
1883 Write_Str (Src_Name);
1884 Write_Line (" does not exist");
1885 end if;
1886
1887 Close (Dep_File);
1888 return;
1889
1890 -- If the source has been modified after the object file,
1891 -- we need to recompile.
1892
1893 elsif Src_TS > Source.Object_TS then
1894 if Verbose_Mode then
1895 Write_Str (" -> source ");
1896 Write_Str (Src_Name);
1897 Write_Line
1898 (" has time stamp later than object file");
1899 end if;
1900
1901 Close (Dep_File);
1902 return;
1903 end if;
1904 end;
1905
1906 -- If the source path name ends the line, we are done.
1907
1908 exit Line_Loop when Finish = Last;
1909
1910 -- Go get the next source on the line
1911
1912 Start := Finish + 1;
1913 end loop Name_Loop;
1914 end;
1915
1916 -- If we are here, we had a continuation character \ at the end
1917 -- of the line, so we continue with the next line.
1918
1919 Get_Line (Dep_File, Name_Buffer, Name_Len);
1920 Start := 1;
1921 end loop Line_Loop;
1922 end if;
1923
1924 Close (Dep_File);
1925
1926 -- If the original sources were not in the dependency file, then we
1927 -- need to recompile. It may mean that we are using a different source
1928 -- (different variant) for this object file.
1929
1930 if not Source_In_Dependencies then
1931 if Verbose_Mode then
1932 Write_Str (" -> source ");
1933 Write_Str (Source_Path);
1934 Write_Line (" is not in the dependencies");
1935 end if;
1936
1937 return;
1938 end if;
1939
1940 -- If we are here, then everything is OK, and we don't need
1941 -- to recompile.
1942
1943 if Verbose_Mode then
1944 Write_Line (" -> up to date");
1945 end if;
1946
1947 Need_To_Compile := False;
1948 end Check_Compilation_Needed;
1949
1950 ---------------------------
1951 -- Check_For_C_Plus_Plus --
1952 ---------------------------
1953
1954 procedure Check_For_C_Plus_Plus is
1955 begin
1956 C_Plus_Plus_Is_Used := False;
1957
1958 for Project in 1 .. Projects.Last loop
1959 if Projects.Table (Project).Languages (Lang_C_Plus_Plus) then
1960 C_Plus_Plus_Is_Used := True;
1961 exit;
1962 end if;
1963 end loop;
1964 end Check_For_C_Plus_Plus;
1965
1966 -------------
1967 -- Compile --
1968 -------------
1969
1970 procedure Compile
1971 (Source_Id : Other_Source_Id;
1972 Data : in Project_Data;
1973 Local_Errors : in out Boolean)
1974 is
1975 Source : Other_Source := Other_Sources.Table (Source_Id);
1976 Success : Boolean;
5453d5bd 1977 CPATH : String_Access := null;
aa720a54 1978
9f4fd324 1979 begin
0da2c8ac 1980 -- If the compiler is not known yet, get its path name
9f4fd324
AC
1981
1982 if Compiler_Names (Source.Language) = null then
1983 Get_Compiler (Source.Language);
1984 end if;
1985
0da2c8ac 1986 -- For non GCC compilers, get the dependency file, first calling the
9f4fd324
AC
1987 -- compiler with the switch -M.
1988
1989 if not Compiler_Is_Gcc (Source.Language) then
1990 Last_Argument := 0;
1991
1992 -- Add the source name, preceded by -M
1993
1994 Add_Argument (Dash_M, True);
1995 Add_Argument (Get_Name_String (Source.Path_Name), True);
1996
1997 -- Add the compiling switches for this source found in
1998 -- package Compiler of the project file, if they exist.
1999
2000 Add_Switches
2001 (Data, Compiler, Source.Language, Source.File_Name);
2002
2003 -- Add the compiling switches for the language specified
2004 -- on the command line, if any.
2005
2006 for
2007 J in 1 .. Comp_Opts.Last (Options (Source.Language))
2008 loop
2009 Add_Argument (Options (Source.Language).Table (J), True);
2010 end loop;
2011
0da2c8ac 2012 -- Finally, add imported directory switches for this project file
9f4fd324
AC
2013
2014 Add_Search_Directories (Data, Source.Language);
2015
2016 -- And invoke the compiler using GNAT.Expect
2017
2018 Display_Command
2019 (Compiler_Names (Source.Language).all,
2020 Compiler_Paths (Source.Language));
2021
2022 begin
2023 Non_Blocking_Spawn
2024 (FD,
2025 Compiler_Paths (Source.Language).all,
2026 Arguments (1 .. Last_Argument),
2027 Buffer_Size => 0,
2028 Err_To_Out => True);
2029
2030 declare
2031 Dep_File : Ada.Text_IO.File_Type;
2032 Result : Expect_Match;
2033 Status : Integer;
2034
2035 begin
2036 -- Create the dependency file
2037
2038 Create (Dep_File, Out_File, Get_Name_String (Source.Dep_Name));
2039
2040 loop
2041 Expect (FD, Result, Line_Matcher);
2042
2043 exit when Result = Expect_Timeout;
2044
2045 declare
2046 S : constant String := Strip_CR_LF (Expect_Out (FD));
aa720a54 2047
9f4fd324
AC
2048 begin
2049 -- Each line of the output is put in the dependency
2050 -- file, including errors. If there are errors, the
2051 -- syntax of the dependency file will be incorrect and
2052 -- recompilation will occur automatically the next time
2053 -- the dependencies are checked.
2054
2055 Put_Line (Dep_File, S);
2056 end;
2057 end loop;
2058
aa720a54
AC
2059 -- If we are here, it means we had a timeout, so the
2060 -- dependency file may be incomplete. It is safer to
9f4fd324
AC
2061 -- delete it, otherwise the dependencies may be wrong.
2062
2063 Close (FD, Status);
2064 Close (Dep_File);
2065 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2066
2067 exception
aa720a54
AC
2068 when Process_Died =>
2069
2070 -- This is the normal outcome. Just close the file
9f4fd324
AC
2071
2072 Close (FD, Status);
2073 Close (Dep_File);
2074
aa720a54
AC
2075 when others =>
2076
9f4fd324
AC
2077 -- Something wrong happened. It is safer to delete the
2078 -- dependency file, otherwise the dependencies may be wrong.
2079
2080 Close (FD, Status);
2081
2082 if Is_Open (Dep_File) then
2083 Close (Dep_File);
2084 end if;
2085
2086 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2087 end;
2088
2089 exception
2090 -- If we cannot spawn the compiler, then the dependencies are
2091 -- not updated. It is safer then to delete the dependency file,
2092 -- otherwise the dependencies may be wrong.
2093
2094 when Invalid_Process =>
2095 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2096 end;
2097 end if;
2098
2099 Last_Argument := 0;
2100
aa720a54
AC
2101 -- For GCC compilers, make sure the language is always specified to
2102 -- to the GCC driver, in case the extension is not recognized by the
2103 -- GCC driver as a source of the language.
9f4fd324
AC
2104
2105 if Compiler_Is_Gcc (Source.Language) then
2106 Add_Argument (Dash_x, Verbose_Mode);
2107 Add_Argument
2108 (Lang_Names (Source.Language), Verbose_Mode);
2109 end if;
2110
2111 -- Specify the source to be compiled
aa720a54 2112
9f4fd324
AC
2113 Add_Argument (Dash_c, True);
2114 Add_Argument (Get_Name_String (Source.Path_Name), True);
2115
aa720a54
AC
2116 -- If non static library project, compile with the PIC option if there
2117 -- is one (when there is no PIC option, function MLib.Tgt.PIC_Option
2118 -- returns an empty string, and Add_Argument with an empty string has
2119 -- no effect).
9f4fd324
AC
2120
2121 if Data.Library and then Data.Library_Kind /= Static then
2122 Add_Argument (PIC_Option, True);
2123 end if;
2124
2125 -- Indicate the name of the object
2126
2127 Add_Argument (Dash_o, True);
2128 Add_Argument (Get_Name_String (Source.Object_Name), True);
2129
2130 -- When compiler is GCC, use the magic switch that creates
2131 -- the dependency file in the correct format.
2132
2133 if Compiler_Is_Gcc (Source.Language) then
2134 Add_Argument
2135 ("-Wp,-MD," & Get_Name_String (Source.Dep_Name),
2136 Verbose_Mode);
2137 end if;
2138
2139 -- Add the compiling switches for this source found in
2140 -- package Compiler of the project file, if they exist.
2141
2142 Add_Switches
2143 (Data, Compiler, Source.Language, Source.File_Name);
2144
2145 -- Add the compiling switches for the language specified
2146 -- on the command line, if any.
2147
0da2c8ac 2148 for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
9f4fd324
AC
2149 Add_Argument (Options (Source.Language).Table (J), True);
2150 end loop;
2151
2152 -- Finally, add the imported directory switches for this
2153 -- project file (or, for gcc compilers, set up the CPATH env var
2154 -- if needed).
2155
2156 Add_Search_Directories (Data, Source.Language);
2157
5453d5bd
AC
2158 -- Set CPATH, if compiler is GCC
2159
2160 if Compiler_Is_Gcc (Source.Language) then
2161 CPATH := Current_Include_Paths (Source.Language);
2162 end if;
2163
9f4fd324
AC
2164 -- And invoke the compiler
2165
2166 Display_Command
5453d5bd
AC
2167 (Name => Compiler_Names (Source.Language).all,
2168 Path => Compiler_Paths (Source.Language),
2169 CPATH => CPATH);
9f4fd324
AC
2170
2171 Spawn
2172 (Compiler_Paths (Source.Language).all,
2173 Arguments (1 .. Last_Argument),
2174 Success);
2175
0da2c8ac
AC
2176 -- Case of successful compilation
2177
9f4fd324 2178 if Success then
aa720a54 2179
0da2c8ac 2180 -- Update the time stamp of the object file
9f4fd324
AC
2181
2182 Source.Object_TS := File_Stamp (Source.Object_Name);
2183
2184 -- Do some sanity checks
2185
2186 if Source.Object_TS = Empty_Time_Stamp then
2187 Local_Errors := True;
2188 Report_Error
2189 ("object file ",
2190 Get_Name_String (Source.Object_Name),
2191 " has not been created");
2192
2193 elsif Source.Object_TS < Source.Source_TS then
2194 Local_Errors := True;
2195 Report_Error
2196 ("object file ",
2197 Get_Name_String (Source.Object_Name),
2198 " has not been modified");
2199
2200 else
aa720a54 2201 -- Everything looks fine, update the Other_Sources table
9f4fd324
AC
2202
2203 Other_Sources.Table (Source_Id) := Source;
2204 end if;
2205
0da2c8ac
AC
2206 -- Compilation failed
2207
9f4fd324
AC
2208 else
2209 Local_Errors := True;
2210 Report_Error
2211 ("compilation of ",
2212 Get_Name_String (Source.Path_Name),
2213 " failed");
2214 end if;
2215 end Compile;
2216
2217 --------------------------------
2218 -- Compile_Individual_Sources --
2219 --------------------------------
2220
2221 procedure Compile_Individual_Sources is
aa720a54
AC
2222 Data : Project_Data := Projects.Table (Main_Project);
2223 Source_Id : Other_Source_Id;
2224 Source : Other_Source;
2225 Source_Name : Name_Id;
9f4fd324
AC
2226 Project_Name : String := Get_Name_String (Data.Name);
2227 Dummy : Boolean := False;
aa720a54 2228
9f4fd324 2229 Ada_Is_A_Language : constant Boolean := Data.Languages (Lang_Ada);
aa720a54 2230
9f4fd324
AC
2231 begin
2232 Ada_Mains.Init;
9f4fd324 2233 To_Mixed (Project_Name);
9f4fd324
AC
2234 Compile_Only := True;
2235
2236 Get_Imported_Directories (Main_Project, Data);
2237 Projects.Table (Main_Project) := Data;
2238
5453d5bd
AC
2239 -- Compilation will occur in the object directory
2240
2241 Change_Dir (Get_Name_String (Data.Object_Directory));
2242
0da2c8ac 2243 if not Data.Other_Sources_Present then
9f4fd324
AC
2244 if Ada_Is_A_Language then
2245 Mains.Reset;
2246
2247 loop
2248 declare
2249 Main : constant String := Mains.Next_Main;
2250 begin
2251 exit when Main'Length = 0;
2252 Ada_Mains.Increment_Last;
2253 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2254 end;
2255 end loop;
2256
2257 else
2258 Osint.Fail
2259 ("project ", Project_Name, " contains no source");
2260 end if;
2261
2262 else
2263 Mains.Reset;
2264
2265 loop
2266 declare
2267 Main : constant String := Mains.Next_Main;
2268 begin
2269 Name_Len := Main'Length;
2270 exit when Name_Len = 0;
2271 Name_Buffer (1 .. Name_Len) := Main;
2272 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2273 Source_Name := Name_Find;
2274
2275 if not Sources_Compiled.Get (Source_Name) then
2276 Sources_Compiled.Set (Source_Name, True);
9f4fd324
AC
2277 Source_Id := Data.First_Other_Source;
2278
2279 while Source_Id /= No_Other_Source loop
2280 Source := Other_Sources.Table (Source_Id);
2281 exit when Source.File_Name = Source_Name;
2282 Source_Id := Source.Next;
2283 end loop;
2284
2285 if Source_Id = No_Other_Source then
2286 if Ada_Is_A_Language then
2287 Ada_Mains.Increment_Last;
0da2c8ac 2288 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
9f4fd324
AC
2289
2290 else
2291 Report_Error
2292 (Main,
2293 " is not a valid source of project ",
2294 Project_Name);
2295 end if;
2296
2297 else
2298 Compile (Source_Id, Data, Dummy);
2299 end if;
2300 end if;
2301 end;
2302 end loop;
2303 end if;
2304
2305 if Ada_Mains.Last > 0 then
aa720a54 2306
0da2c8ac 2307 -- Invoke gnatmake for all Ada sources
9f4fd324
AC
2308
2309 Last_Argument := 0;
9f4fd324
AC
2310 Add_Argument (Dash_u, True);
2311
2312 for Index in 1 .. Ada_Mains.Last loop
2313 Add_Argument (Ada_Mains.Table (Index), True);
2314 end loop;
2315
2316 Compile_Link_With_Gnatmake (Mains_Specified => False);
2317 end if;
2318 end Compile_Individual_Sources;
2319
2320 --------------------------------
2321 -- Compile_Link_With_Gnatmake --
2322 --------------------------------
2323
2324 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean) is
aa720a54 2325 Data : constant Project_Data := Projects.Table (Main_Project);
9f4fd324 2326 Success : Boolean;
aa720a54 2327
9f4fd324
AC
2328 begin
2329 -- Array Arguments may already contain some arguments, so we don't
2330 -- set Last_Argument to 0.
2331
2332 -- Get the gnatmake to invoke
2333
2334 Get_Compiler (Lang_Ada);
2335
2336 -- Specify the project file
2337
2338 Add_Argument (Dash_P, True);
2339 Add_Argument (Get_Name_String (Data.Path_Name), True);
2340
15ce9ca2
AC
2341 -- Add the -X switches, if any
2342
2343 for Index in 1 .. X_Switches.Last loop
2344 Add_Argument (X_Switches.Table (Index), True);
2345 end loop;
2346
9f4fd324
AC
2347 -- If Mains_Specified is True, find the mains in package Mains
2348
2349 if Mains_Specified then
2350 Mains.Reset;
2351
2352 loop
2353 declare
2354 Main : constant String := Mains.Next_Main;
2355 begin
2356 exit when Main'Length = 0;
2357 Add_Argument (Main, True);
2358 end;
2359 end loop;
2360 end if;
2361
2362 -- Specify output file name, if any was specified on the command line
2363
2364 if Output_File_Name /= null then
2365 Add_Argument (Dash_o, True);
2366 Add_Argument (Output_File_Name, True);
2367 end if;
2368
0da2c8ac 2369 -- Transmit some switches to gnatmake
9f4fd324
AC
2370
2371 -- -c
2372
2373 if Compile_Only then
2374 Add_Argument (Dash_c, True);
2375 end if;
2376
2377 -- -k
2378
2379 if Keep_Going then
2380 Add_Argument (Dash_k, True);
2381 end if;
2382
2383 -- -f
2384
2385 if Force_Compilations then
2386 Add_Argument (Dash_f, True);
2387 end if;
2388
2389 -- -v
2390
2391 if Verbose_Mode then
2392 Add_Argument (Dash_v, True);
2393 end if;
2394
2395 -- -q
2396
2397 if Quiet_Output then
2398 Add_Argument (Dash_q, True);
2399 end if;
2400
2401 -- -vP1 and -vP2
2402
2403 case Current_Verbosity is
2404 when Default =>
2405 null;
2406
2407 when Medium =>
2408 Add_Argument (Dash_vP1, True);
2409
2410 when High =>
2411 Add_Argument (Dash_vP2, True);
2412 end case;
2413
2414 -- If there are compiling options for Ada, transmit them to gnatmake
2415
2416 if Comp_Opts.Last (Options (Lang_Ada)) /= 0 then
2417 Add_Argument (Dash_cargs, True);
2418
2419 for Arg in 1 .. Comp_Opts.Last (Options (Lang_Ada)) loop
2420 Add_Argument (Options (Lang_Ada).Table (Arg), True);
2421 end loop;
2422 end if;
2423
2424 if not Compile_Only then
0da2c8ac 2425
246d2ceb 2426 -- Linking options
9f4fd324
AC
2427
2428 if Linker_Options.Last /= 0 then
2429 Add_Argument (Dash_largs, True);
9f4fd324
AC
2430 else
2431 Add_Argument (Dash_largs, Verbose_Mode);
2432 end if;
2433
2434 -- Add the archives
2435
2436 Add_Archives (For_Gnatmake => True);
246d2ceb
AC
2437
2438 -- If there are linking options from the command line,
2439 -- transmit them to gnatmake.
2440
2441 for Arg in 1 .. Linker_Options.Last loop
2442 Add_Argument (Linker_Options.Table (Arg), True);
2443 end loop;
9f4fd324
AC
2444 end if;
2445
2446 -- And invoke gnatmake
2447
2448 Display_Command
2449 (Compiler_Names (Lang_Ada).all, Compiler_Paths (Lang_Ada));
2450
2451 Spawn
2452 (Compiler_Paths (Lang_Ada).all,
2453 Arguments (1 .. Last_Argument),
2454 Success);
2455
2456 -- Report an error if call to gnatmake failed
2457
2458 if not Success then
2459 Report_Error
2460 ("invocation of ", Compiler_Names (Lang_Ada).all, " failed");
2461 end if;
2462
2463 end Compile_Link_With_Gnatmake;
2464
2465 ---------------------
2466 -- Compile_Sources --
2467 ---------------------
2468
2469 procedure Compile_Sources is
2470 Data : Project_Data;
2471 Source_Id : Other_Source_Id;
2472 Source : Other_Source;
2473
2474 Local_Errors : Boolean := False;
aa720a54
AC
2475 -- Set to True when there is a compilation error. Used only when
2476 -- Keep_Going is True, to inhibit the building of the archive.
9f4fd324
AC
2477
2478 Need_To_Compile : Boolean;
2479 -- Set to True when a source needs to be compiled/recompiled.
2480
2481 Need_To_Rebuild_Archive : Boolean := Force_Compilations;
2482 -- True when the archive needs to be built/rebuilt unconditionally
2483
2484 begin
0da2c8ac 2485 -- Loop through project files
9f4fd324
AC
2486
2487 for Project in 1 .. Projects.Last loop
2488 Local_Errors := False;
2489 Data := Projects.Table (Project);
2490
cc335f43
AC
2491 -- Nothing to do when no sources of language other than Ada
2492
0da2c8ac 2493 if (not Data.Virtual) and then Data.Other_Sources_Present then
aa720a54 2494
9f4fd324
AC
2495 -- If the imported directory switches are unknown, compute them
2496
2497 if not Data.Include_Data_Set then
2498 Get_Imported_Directories (Project, Data);
2499 Data.Include_Data_Set := True;
2500 Projects.Table (Project) := Data;
2501 end if;
2502
cc335f43 2503 Need_To_Rebuild_Archive := Force_Compilations;
9f4fd324 2504
cc335f43 2505 -- Compilation will occur in the object directory
9f4fd324 2506
cc335f43 2507 Change_Dir (Get_Name_String (Data.Object_Directory));
9f4fd324 2508
cc335f43 2509 Source_Id := Data.First_Other_Source;
9f4fd324 2510
cc335f43 2511 -- Process each source one by one
9f4fd324 2512
cc335f43
AC
2513 while Source_Id /= No_Other_Source loop
2514 Source := Other_Sources.Table (Source_Id);
2515 Need_To_Compile := Force_Compilations;
9f4fd324 2516
cc335f43 2517 -- Check if compilation is needed
9f4fd324 2518
cc335f43
AC
2519 if not Need_To_Compile then
2520 Check_Compilation_Needed (Source, Need_To_Compile);
2521 end if;
9f4fd324 2522
cc335f43 2523 -- Proceed, if compilation is needed
9f4fd324 2524
cc335f43 2525 if Need_To_Compile then
aa720a54 2526
cc335f43
AC
2527 -- If a source is compiled/recompiled, of course the
2528 -- archive will need to be built/rebuilt.
9f4fd324 2529
cc335f43
AC
2530 Need_To_Rebuild_Archive := True;
2531 Compile (Source_Id, Data, Local_Errors);
2532 end if;
9f4fd324 2533
cc335f43 2534 -- Next source, if any
9f4fd324 2535
cc335f43
AC
2536 Source_Id := Source.Next;
2537 end loop;
9f4fd324 2538
0da2c8ac
AC
2539 if Need_To_Rebuild_Archive and then (not Data.Library) then
2540 Need_To_Rebuild_Global_Archive := True;
2541 end if;
2542
cc335f43
AC
2543 -- If there was no compilation error, build/rebuild the archive
2544 -- if necessary.
9f4fd324 2545
0da2c8ac
AC
2546 if not Local_Errors
2547 and then Data.Library
2548 and then not Data.Languages (Lang_Ada)
2549 then
2550 Build_Library (Project, Need_To_Rebuild_Archive);
9f4fd324
AC
2551 end if;
2552 end if;
2553 end loop;
2554 end Compile_Sources;
2555
2556 ---------------
2557 -- Copyright --
2558 ---------------
2559
2560 procedure Copyright is
2561 begin
2562 -- Only output the Copyright notice once
2563
2564 if not Copyright_Output then
2565 Copyright_Output := True;
2566 Write_Eol;
2567 Write_Str ("GPRMAKE ");
2568 Write_Str (Gnatvsn.Gnat_Version_String);
2569 Write_Str (" Copyright 2004 Free Software Foundation, Inc.");
2570 Write_Eol;
2571 end if;
2572 end Copyright;
2573
2574 ------------------------------------
2575 -- Create_Archive_Dependency_File --
2576 ------------------------------------
2577
2578 procedure Create_Archive_Dependency_File
aa720a54
AC
2579 (Name : String;
2580 First_Source : Other_Source_Id)
9f4fd324
AC
2581 is
2582 Source_Id : Other_Source_Id := First_Source;
2583 Source : Other_Source;
aa720a54 2584 Dep_File : Ada.Text_IO.File_Type;
9f4fd324
AC
2585 use Ada.Text_IO;
2586
2587 begin
0da2c8ac
AC
2588 -- Create the file in Append mode, to avoid automatic insertion of
2589 -- an end of line if file is empty.
2590
2591 Create (Dep_File, Append_File, Name);
9f4fd324
AC
2592
2593 while Source_Id /= No_Other_Source loop
2594 Source := Other_Sources.Table (Source_Id);
2595 Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
2596 Put_Line (Dep_File, String (Source.Object_TS));
2597 Source_Id := Source.Next;
2598 end loop;
2599
2600 Close (Dep_File);
2601
2602 exception
2603 when others =>
2604 if Is_Open (Dep_File) then
2605 Close (Dep_File);
2606 end if;
2607 end Create_Archive_Dependency_File;
2608
0da2c8ac
AC
2609 -------------------------------------------
2610 -- Create_Global_Archive_Dependency_File --
2611 -------------------------------------------
2612
2613 procedure Create_Global_Archive_Dependency_File (Name : String) is
2614 Source_Id : Other_Source_Id;
2615 Source : Other_Source;
2616 Dep_File : Ada.Text_IO.File_Type;
2617
2618 use Ada.Text_IO;
2619
2620 begin
2621 -- Create the file in Append mode, to avoid automatic insertion of
2622 -- an end of line if file is empty.
2623
2624 Create (Dep_File, Append_File, Name);
2625
2626 -- Get all the object files of non-Ada sources in non-library projects
2627
2628 for Project in 1 .. Projects.Last loop
2629 if not Projects.Table (Project).Library then
2630 Source_Id := Projects.Table (Project).First_Other_Source;
2631
2632 while Source_Id /= No_Other_Source loop
2633 Source := Other_Sources.Table (Source_Id);
2634
2635 -- Put only those object files that are in the global archive
2636
2637 if Is_Included_In_Global_Archive
2638 (Source.Object_Name, Project)
2639 then
2640 Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
2641 Put_Line (Dep_File, String (Source.Object_TS));
2642 end if;
2643
2644 Source_Id := Source.Next;
2645 end loop;
2646 end if;
2647 end loop;
2648
2649 Close (Dep_File);
2650
2651 exception
2652 when others =>
2653 if Is_Open (Dep_File) then
2654 Close (Dep_File);
2655 end if;
2656 end Create_Global_Archive_Dependency_File;
2657
9f4fd324
AC
2658 ---------------------
2659 -- Display_Command --
2660 ---------------------
2661
5453d5bd
AC
2662 procedure Display_Command
2663 (Name : String;
2664 Path : String_Access;
2665 CPATH : String_Access := null)
2666 is
9f4fd324
AC
2667 begin
2668 -- Only display the command in Verbose Mode (-v) or when
2669 -- not in Quiet Output (no -q).
2670
2671 if Verbose_Mode or (not Quiet_Output) then
0da2c8ac 2672
9f4fd324
AC
2673 -- In Verbose Mode output the full path of the spawned process
2674
2675 if Verbose_Mode then
5453d5bd
AC
2676 if CPATH /= null then
2677 Write_Str ("CPATH = ");
2678 Write_Line (CPATH.all);
2679 end if;
2680
9f4fd324
AC
2681 Write_Str (Path.all);
2682
2683 else
2684 Write_Str (Name);
2685 end if;
2686
2687 -- Display only the arguments for which the display flag is set
2688 -- (in Verbose Mode, the display flag is set for all arguments)
2689
2690 for Arg in 1 .. Last_Argument loop
2691 if Arguments_Displayed (Arg) then
2692 Write_Char (' ');
2693 Write_Str (Arguments (Arg).all);
2694 end if;
2695 end loop;
2696
2697 Write_Eol;
2698 end if;
2699 end Display_Command;
2700
2701 ------------------
2702 -- Get_Compiler --
2703 ------------------
2704
2705 procedure Get_Compiler (For_Language : Programming_Language) is
2706 Data : constant Project_Data := Projects.Table (Main_Project);
2707
2708 Ide : constant Package_Id :=
2709 Value_Of (Name_Ide, In_Packages => Data.Decl.Packages);
2710 -- The id of the package IDE in the project file
2711
2712 Compiler : constant Variable_Value :=
aa720a54
AC
2713 Value_Of
2714 (Name => Lang_Name_Ids (For_Language),
2715 Index => 0,
2716 Attribute_Or_Array_Name => Name_Compiler_Command,
2717 In_Package => Ide);
2718 -- The value of Compiler_Command ("language") in package IDE, if defined
9f4fd324
AC
2719
2720 begin
2721 -- No need to do it again if the compiler is known for this language
2722
2723 if Compiler_Names (For_Language) = null then
aa720a54 2724
9f4fd324
AC
2725 -- If compiler command is not defined for this language in package
2726 -- IDE, use the default compiler for this language.
2727
2728 if Compiler = Nil_Variable_Value then
2729 Compiler_Names (For_Language) :=
2730 Default_Compiler_Names (For_Language);
2731
2732 else
2733 Compiler_Names (For_Language) :=
2734 new String'(Get_Name_String (Compiler.Value));
2735 end if;
2736
aa720a54 2737 -- Check we have a GCC compiler (name ends with "gcc" or "g++")
9f4fd324
AC
2738
2739 declare
2740 Comp_Name : constant String := Compiler_Names (For_Language).all;
2741 Last3 : String (1 .. 3);
2742 begin
2743 if Comp_Name'Length >= 3 then
2744 Last3 := Comp_Name (Comp_Name'Last - 2 .. Comp_Name'Last);
2745 Compiler_Is_Gcc (For_Language) :=
2746 (Last3 = "gcc") or (Last3 = "g++");
9f4fd324
AC
2747 else
2748 Compiler_Is_Gcc (For_Language) := False;
2749 end if;
2750 end;
2751
2752 -- Locate the compiler on the path
2753
2754 Compiler_Paths (For_Language) :=
2755 Locate_Exec_On_Path (Compiler_Names (For_Language).all);
2756
2757 -- Fail if compiler cannot be found
2758
2759 if Compiler_Paths (For_Language) = null then
2760 if For_Language = Lang_Ada then
2761 Osint.Fail
2762 ("unable to locate """,
2763 Compiler_Names (For_Language).all,
2764 """");
2765
2766 else
2767 Osint.Fail
2768 ("unable to locate " & Lang_Display_Names (For_Language).all,
2769 " compiler """, Compiler_Names (For_Language).all & '"');
2770 end if;
2771 end if;
2772 end if;
2773 end Get_Compiler;
2774
2775 ------------------------------
2776 -- Get_Imported_Directories --
2777 ------------------------------
2778
2779 procedure Get_Imported_Directories
2780 (Project : Project_Id;
2781 Data : in out Project_Data)
2782 is
2783 Imported_Projects : Project_List := Data.Imported_Projects;
aa720a54 2784
9f4fd324
AC
2785 Path_Length : Natural := 0;
2786 Position : Natural := 0;
2787
2788 procedure Add (Source_Dirs : String_List_Id);
2789 -- Add a list of source directories
2790
2791 procedure Recursive_Get_Dirs (Prj : Project_Id);
2792 -- Recursive procedure to get the source directories of this project
2793 -- file and of the project files it imports, in the correct order.
2794
2795 ---------
2796 -- Add --
2797 ---------
2798
2799 procedure Add (Source_Dirs : String_List_Id) is
2800 Element_Id : String_List_Id := Source_Dirs;
2801 Element : String_Element;
2802 Add_Arg : Boolean := True;
0da2c8ac 2803
9f4fd324 2804 begin
0da2c8ac 2805 -- Add each source directory path name, preceded by "-I" to Arguments
9f4fd324
AC
2806
2807 while Element_Id /= Nil_String loop
2808 Element := String_Elements.Table (Element_Id);
2809
2810 if Element.Value /= No_Name then
2811 Get_Name_String (Element.Value);
2812
2813 if Name_Len > 0 then
2814 declare
2815 Arg : constant String :=
2816 "-I" & Name_Buffer (1 .. Name_Len);
2817 begin
2818 -- Check if directory is already in the list.
2819 -- If it is, no need to put it again.
2820
2821 for Index in 1 .. Last_Argument loop
2822 if Arguments (Index).all = Arg then
2823 Add_Arg := False;
2824 exit;
2825 end if;
2826 end loop;
2827
2828 if Add_Arg then
2829 if Path_Length /= 0 then
2830 Path_Length := Path_Length + 1;
2831 end if;
2832
2833 Path_Length := Path_Length + Name_Len;
2834
2835 Add_Argument (Arg, True);
2836 end if;
2837 end;
2838 end if;
2839 end if;
2840
2841 Element_Id := Element.Next;
2842 end loop;
2843 end Add;
2844
2845 ------------------------
2846 -- Recursive_Get_Dirs --
2847 ------------------------
2848
2849 procedure Recursive_Get_Dirs (Prj : Project_Id) is
aa720a54 2850 Data : Project_Data;
9f4fd324 2851 Imported : Project_List;
aa720a54 2852
9f4fd324
AC
2853 begin
2854 -- Nothing to do if project is undefined
2855
2856 if Prj /= No_Project then
2857 Data := Projects.Table (Prj);
2858
2859 -- Nothing to do if project has already been processed
2860
2861 if not Data.Seen then
aa720a54 2862
9f4fd324
AC
2863 -- Mark the project as processed, to avoid multiple processing
2864 -- of the same project.
2865
2866 Projects.Table (Prj).Seen := True;
2867
2868 -- Add the source directories of this project
2869
2870 if not Data.Virtual then
2871 Add (Data.Source_Dirs);
2872 end if;
2873
2874 Recursive_Get_Dirs (Data.Extends);
2875
2876 Imported := Data.Imported_Projects;
2877
2878 -- Call itself for all imported projects, if any
2879
2880 while Imported /= Empty_Project_List loop
2881 Recursive_Get_Dirs (Project_Lists.Table (Imported).Project);
2882 Imported := Project_Lists.Table (Imported).Next;
2883 end loop;
2884 end if;
2885 end if;
2886 end Recursive_Get_Dirs;
2887
0da2c8ac
AC
2888 -- Start of processing for Get_Imported_Directories
2889
9f4fd324
AC
2890 begin
2891 -- First, mark all project as not processed
2892
2893 for J in 1 .. Projects.Last loop
2894 Projects.Table (J).Seen := False;
2895 end loop;
2896
2897 -- Empty Arguments
2898
2899 Last_Argument := 0;
2900
aa720a54 2901 -- Process this project individually, project data are already known
9f4fd324
AC
2902
2903 Projects.Table (Project).Seen := True;
2904
2905 Add (Data.Source_Dirs);
2906
2907 Recursive_Get_Dirs (Data.Extends);
2908
2909 while Imported_Projects /= Empty_Project_List loop
2910 Recursive_Get_Dirs (Project_Lists.Table (Imported_Projects).Project);
2911 Imported_Projects := Project_Lists.Table (Imported_Projects).Next;
2912 end loop;
2913
2914 Data.Imported_Directories_Switches :=
2915 new Argument_List'(Arguments (1 .. Last_Argument));
2916
2917 -- Create the Include_Path, from the Arguments
2918
2919 Data.Include_Path := new String (1 .. Path_Length);
2920 Data.Include_Path (1 .. Arguments (1)'Length - 2) :=
2921 Arguments (1)(Arguments (1)'First + 2 .. Arguments (1)'Last);
2922 Position := Arguments (1)'Length - 2;
2923
2924 for Arg in 2 .. Last_Argument loop
2925 Position := Position + 1;
2926 Data.Include_Path (Position) := Path_Separator;
2927 Data.Include_Path
2928 (Position + 1 .. Position + Arguments (Arg)'Length - 2) :=
2929 Arguments (Arg)(Arguments (Arg)'First + 2 .. Arguments (Arg)'Last);
2930 Position := Position + Arguments (Arg)'Length - 2;
2931 end loop;
2932
2933 Last_Argument := 0;
2934 end Get_Imported_Directories;
2935
2936 -------------
2937 -- Gprmake --
2938 -------------
2939
2940 procedure Gprmake is
2941 begin
2942 Initialize;
2943
2944 if Verbose_Mode then
2945 Write_Eol;
2946 Write_Str ("Parsing Project File """);
2947 Write_Str (Project_File_Name.all);
2948 Write_Str (""".");
2949 Write_Eol;
2950 end if;
2951
0da2c8ac 2952 -- Parse and process project files for other languages (not for Ada)
9f4fd324
AC
2953
2954 Prj.Pars.Parse
2955 (Project => Main_Project,
2956 Project_File_Name => Project_File_Name.all,
2957 Packages_To_Check => Packages_To_Check,
2958 Process_Languages => Other_Languages);
2959
2960 -- Fail if parsing/processing was unsuccessful
2961
2962 if Main_Project = No_Project then
2963 Osint.Fail ("""", Project_File_Name.all, """ processing failed");
2964 end if;
2965
2966 if Verbose_Mode then
2967 Write_Eol;
2968 Write_Str ("Parsing of Project File """);
2969 Write_Str (Project_File_Name.all);
2970 Write_Str (""" is finished.");
2971 Write_Eol;
2972 end if;
2973
2974 -- If -f was specified, we will certainly need to link (except when
2975 -- -u or -c were specified, of course).
2976
2977 Need_To_Relink := Force_Compilations;
2978
2979 if Unique_Compile then
2980 if Mains.Number_Of_Mains = 0 then
2981 Osint.Fail
2982 ("No source specified to compile in 'unique compile' mode");
9f4fd324
AC
2983 else
2984 Compile_Individual_Sources;
2985 Report_Total_Errors ("compilation");
2986 end if;
2987
2988 else
0da2c8ac
AC
2989 -- First compile sources and build archives for library project,
2990 -- if necessary.
9f4fd324
AC
2991
2992 Compile_Sources;
2993
2994 -- When Keep_Going is True, if we had some errors, fail now,
2995 -- reporting the number of compilation errors.
2996 -- Do not attempt to link.
2997
2998 Report_Total_Errors ("compilation");
2999
3000 -- If -c was not specified, link the executables, if there are any.
3001
3002 if not Compile_Only then
0da2c8ac 3003 Build_Global_Archive;
9f4fd324
AC
3004 Check_For_C_Plus_Plus;
3005 Link_Executables;
3006 end if;
3007
3008 -- When Keep_Going is True, if we had some errors, fail, reporting
3009 -- the number of linking errors.
3010
3011 Report_Total_Errors ("linking");
3012 end if;
3013 end Gprmake;
3014
3015 ----------------
3016 -- Initialize --
3017 ----------------
3018
3019 procedure Initialize is
9f4fd324
AC
3020 begin
3021 -- Do some necessary package initializations
3022
3023 Csets.Initialize;
3024 Namet.Initialize;
3025 Snames.Initialize;
3026 Prj.Initialize;
3027 Mains.Delete;
3028
3029 -- Set Name_Ide and Name_Compiler_Command
3030
3031 Name_Len := 0;
3032 Add_Str_To_Name_Buffer ("ide");
3033 Name_Ide := Name_Find;
3034
3035 Name_Len := 0;
3036 Add_Str_To_Name_Buffer ("compiler_command");
3037 Name_Compiler_Command := Name_Find;
3038
15ce9ca2
AC
3039 -- Make sure the -X switch table is empty
3040
3041 X_Switches.Set_Last (0);
3042
9f4fd324
AC
3043 -- Get the command line arguments
3044
5453d5bd 3045 Scan_Args : for Next_Arg in 1 .. Argument_Count loop
9f4fd324 3046 Scan_Arg (Argument (Next_Arg));
9f4fd324
AC
3047 end loop Scan_Args;
3048
3049 -- Fail if command line ended with "-P"
3050
3051 if Project_File_Name_Expected then
3052 Osint.Fail ("project file name missing after -P");
3053
3054 -- Or if it ended with "-o"
3055
3056 elsif Output_File_Name_Expected then
3057 Osint.Fail ("output file name missing after -o");
3058 end if;
3059
3060 -- If no project file was specified, display the usage and fail
3061
3062 if Project_File_Name = null then
3063 Usage;
3064 Exit_Program (E_Success);
3065 end if;
3066
3067 -- To be able of finding libgnat.a in MLib.Tgt, we need to have the
3068 -- default search dirs established in Osint.
3069
3070 Osint.Add_Default_Search_Dirs;
3071 end Initialize;
3072
0da2c8ac
AC
3073 -----------------------------------
3074 -- Is_Included_In_Global_Archive --
3075 -----------------------------------
3076
3077 function Is_Included_In_Global_Archive
3078 (Object_Name : Name_Id;
3079 Project : Project_Id) return Boolean
3080 is
3081 Data : Project_Data := Projects.Table (Project);
3082 Source : Other_Source_Id;
3083
3084 begin
3085 while Data.Extended_By /= No_Project loop
3086 Data := Projects.Table (Data.Extended_By);
3087 Source := Data.First_Other_Source;
3088
3089 while Source /= No_Other_Source loop
3090 if Other_Sources.Table (Source).Object_Name = Object_Name then
3091 return False;
3092 else
3093 Source := Other_Sources.Table (Source).Next;
3094 end if;
3095 end loop;
3096 end loop;
3097
3098 return True;
3099 end Is_Included_In_Global_Archive;
3100
9f4fd324
AC
3101 ----------------------
3102 -- Link_Executables --
3103 ----------------------
3104
3105 procedure Link_Executables is
3106 Data : constant Project_Data := Projects.Table (Main_Project);
3107
3108 Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
3109 -- True if main sources were specified on the command line
3110
3111 Object_Dir : constant String := Get_Name_String (Data.Object_Directory);
3112 -- Path of the object directory of the main project
3113
3114 Source_Id : Other_Source_Id;
3115 Source : Other_Source;
3116 Success : Boolean;
3117
3118 Linker_Name : String_Access;
3119 Linker_Path : String_Access;
3120 -- The linker name and path, when linking is not done by gnatlink
3121
3122 Link_Done : Boolean := False;
3123 -- Set to True when the linker is invoked directly (not through
3124 -- gnatmake) to be able to report if mains were up to date at the end
3125 -- of execution.
3126
3127 procedure Add_C_Plus_Plus_Link_For_Gnatmake;
3128 -- Add the --LINK= switch for gnatlink, depending on the C++ compiler
3129
0da2c8ac
AC
3130 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
3131 -- Check if there is an archive that is more recent than the executable
3132 -- to decide if we need to relink.
3133
9f4fd324
AC
3134 procedure Choose_C_Plus_Plus_Link_Process;
3135 -- If the C++ compiler is not g++, create the correct script to link
3136
0da2c8ac
AC
3137 procedure Link_Foreign
3138 (Main : String;
3139 Main_Id : Name_Id;
3140 Source : Other_Source);
3141 -- Link a non-Ada main, when there is no Ada code
3142
9f4fd324
AC
3143 ---------------------------------------
3144 -- Add_C_Plus_Plus_Link_For_Gnatmake --
3145 ---------------------------------------
3146
3147 procedure Add_C_Plus_Plus_Link_For_Gnatmake is
3148 begin
3149 if Compiler_Is_Gcc (Lang_C_Plus_Plus) then
3150 Add_Argument
3151 ("--LINK=" & Compiler_Names (Lang_C_Plus_Plus).all,
3152 Verbose_Mode);
3153
3154 else
3155 Add_Argument
3156 ("--LINK=" &
3157 Object_Dir & Directory_Separator &
3158 Cpp_Linker,
3159 Verbose_Mode);
3160 end if;
3161 end Add_C_Plus_Plus_Link_For_Gnatmake;
3162
0da2c8ac
AC
3163 -----------------------
3164 -- Check_Time_Stamps --
3165 -----------------------
3166
3167 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
3168 Prj_Data : Project_Data;
3169
3170 begin
3171 for Prj in 1 .. Projects.Last loop
3172 Prj_Data := Projects.Table (Prj);
3173
3174 -- There is an archive only in project
3175 -- files with sources other than Ada
3176 -- sources.
3177
3178 if Data.Other_Sources_Present then
3179 declare
3180 Archive_Path : constant String :=
3181 Get_Name_String
3182 (Prj_Data.Object_Directory) &
3183 Directory_Separator &
3184 "lib" &
3185 Get_Name_String (Prj_Data.Name) &
3186 '.' & Archive_Ext;
3187 Archive_TS : Time_Stamp_Type;
3188 begin
3189 Name_Len := 0;
3190 Add_Str_To_Name_Buffer
3191 (Archive_Path);
3192 Archive_TS := File_Stamp (Name_Find);
3193
3194 -- If the archive is later than the
3195 -- executable, we need to relink.
3196
3197 if Archive_TS /= Empty_Time_Stamp
3198 and then
3199 Exec_Time_Stamp < Archive_TS
3200 then
3201 Need_To_Relink := True;
3202
3203 if Verbose_Mode then
3204 Write_Str (" -> ");
3205 Write_Str (Archive_Path);
3206 Write_Str (" has time stamp ");
3207 Write_Str ("later than ");
3208 Write_Line ("executable");
3209 end if;
3210
3211 exit;
3212 end if;
3213 end;
3214 end if;
3215 end loop;
3216 end Check_Time_Stamps;
3217
9f4fd324
AC
3218 -------------------------------------
3219 -- Choose_C_Plus_Plus_Link_Process --
3220 -------------------------------------
3221
3222 procedure Choose_C_Plus_Plus_Link_Process is
3223 begin
3224 if Compiler_Names (Lang_C_Plus_Plus) = null then
3225 Get_Compiler (Lang_C_Plus_Plus);
3226 end if;
3227
3228 if not Compiler_Is_Gcc (Lang_C_Plus_Plus) then
3229 Change_Dir (Object_Dir);
3230
3231 declare
3232 procedure Set_Executable (Name : System.Address);
3233 pragma Import
3234 (C, Set_Executable, "__gnat_set_executable");
3235
3236 Name : constant String := Cpp_Linker & ASCII.NUL;
3237
3238 File : Ada.Text_IO.File_Type;
3239 use Ada.Text_IO;
aa720a54 3240
9f4fd324
AC
3241 begin
3242 Create (File, Out_File, Cpp_Linker);
3243
3244 Put_Line (File, "#!/bin/sh");
3245
3246 Put_Line (File, "LIBGCC=`gcc -print-libgcc-file-name`");
3247 Put_Line
3248 (File,
3249 Compiler_Names (Lang_C_Plus_Plus).all &
3250 " $* ${LIBGCC}");
3251
3252 Close (File);
3253 Set_Executable (Name (Name'First)'Address);
3254 end;
3255 end if;
3256 end Choose_C_Plus_Plus_Link_Process;
3257
0da2c8ac
AC
3258 ------------------
3259 -- Link_Foreign --
3260 ------------------
3261
3262 procedure Link_Foreign
3263 (Main : String;
3264 Main_Id : Name_Id;
3265 Source : Other_Source)
3266 is
3267 Executable_Name : constant String :=
3268 Get_Name_String
3269 (Executable_Of
3270 (Project => Main_Project,
3271 Main => Main_Id,
3272 Index => 0,
3273 Ada_Main => False));
3274 -- File name of the executable
3275
3276 Executable_Path : constant String :=
3277 Get_Name_String
3278 (Data.Exec_Directory) &
3279 Directory_Separator &
3280 Executable_Name;
3281 -- Path name of the executable
3282
3283 Exec_Time_Stamp : Time_Stamp_Type;
3284
3285 begin
3286 -- Now, check if the executable is up to date. It is considered
3287 -- up to date if its time stamp is not earlier that the time stamp
3288 -- of any archive. Only do that if we don't know if we need to link.
3289
3290 if not Need_To_Relink then
3291
3292 -- Get the time stamp of the executable
3293
3294 Name_Len := 0;
3295 Add_Str_To_Name_Buffer (Executable_Path);
3296 Exec_Time_Stamp := File_Stamp (Name_Find);
3297
3298 if Verbose_Mode then
3299 Write_Str (" Checking executable ");
3300 Write_Line (Executable_Name);
3301 end if;
3302
3303 -- If executable does not exist, we need to link
3304
3305 if Exec_Time_Stamp = Empty_Time_Stamp then
3306 Need_To_Relink := True;
3307
3308 if Verbose_Mode then
3309 Write_Line (" -> not found");
3310 end if;
3311
3312 -- Otherwise, get the time stamps of each archive. If one of
3313 -- them is found later than the executable, we need to relink.
3314
3315 else
3316 Check_Time_Stamps (Exec_Time_Stamp);
3317 end if;
3318
3319 -- If Need_To_Relink is False, we are done
3320
3321 if Verbose_Mode and (not Need_To_Relink) then
3322 Write_Line (" -> up to date");
3323 end if;
3324 end if;
3325
3326 -- Prepare to link
3327
3328 if Need_To_Relink then
3329 Link_Done := True;
3330
3331 Last_Argument := 0;
3332
3333 -- Specify the executable path name
3334
3335 Add_Argument (Dash_o, True);
3336 Add_Argument
3337 (Get_Name_String (Data.Exec_Directory) &
3338 Directory_Separator &
3339 Get_Name_String
3340 (Executable_Of
3341 (Project => Main_Project,
3342 Main => Main_Id,
3343 Index => 0,
3344 Ada_Main => False)),
3345 True);
3346
3347 -- Specify the object file of the main source
3348
3349 Add_Argument
3350 (Object_Dir & Directory_Separator &
3351 Get_Name_String (Source.Object_Name),
3352 True);
3353
246d2ceb
AC
3354 -- Add all the archives, in a correct order
3355
3356 Add_Archives (For_Gnatmake => False);
3357
0da2c8ac
AC
3358 -- Add the switches specified in package Linker of
3359 -- the main project.
3360
3361 Add_Switches
3362 (Data => Data,
3363 Proc => Linker,
3364 Language => Source.Language,
3365 File_Name => Main_Id);
3366
3367 -- Add the switches specified in attribute
3368 -- Linker_Options of packages Linker.
3369
3370 if Link_Options_Switches = null then
3371 Link_Options_Switches :=
3372 new Argument_List'
3373 (Linker_Options_Switches (Main_Project));
3374 end if;
3375
3376 Add_Arguments (Link_Options_Switches.all, True);
3377
3378 -- Add the linking options specified on the
3379 -- command line.
3380
3381 for Arg in 1 .. Linker_Options.Last loop
3382 Add_Argument (Linker_Options.Table (Arg), True);
3383 end loop;
3384
0da2c8ac
AC
3385 -- If there are shared libraries and the run path
3386 -- option is supported, add the run path switch.
3387
3388 if Lib_Path.Last > 0 then
3389 Add_Argument
3390 (Path_Option.all &
3391 String (Lib_Path.Table (1 .. Lib_Path.Last)),
3392 Verbose_Mode);
3393 end if;
3394
3395 -- And invoke the linker
3396
3397 Display_Command (Linker_Name.all, Linker_Path);
3398 Spawn
3399 (Linker_Path.all,
3400 Arguments (1 .. Last_Argument),
3401 Success);
3402
3403 if not Success then
3404 Report_Error ("could not link ", Main);
3405 end if;
3406 end if;
3407 end Link_Foreign;
3408
3409 -- Start of processing of Link_Executables
3410
9f4fd324 3411 begin
aa720a54 3412 -- If no mains specified, get mains from attribute Main, if it exists
9f4fd324
AC
3413
3414 if not Mains_Specified then
3415 declare
3416 Element_Id : String_List_Id := Data.Mains;
3417 Element : String_Element;
3418
3419 begin
3420 while Element_Id /= Nil_String loop
3421 Element := String_Elements.Table (Element_Id);
3422
3423 if Element.Value /= No_Name then
3424 Mains.Add_Main (Get_Name_String (Element.Value));
3425 end if;
3426
3427 Element_Id := Element.Next;
3428 end loop;
3429 end;
3430 end if;
3431
3432 if Mains.Number_Of_Mains = 0 then
0da2c8ac 3433
9f4fd324
AC
3434 -- If the attribute Main is an empty list or not specified,
3435 -- there is nothing to do.
3436
3437 if Verbose_Mode then
3438 Write_Line ("No main to link");
3439 end if;
3440 return;
3441 end if;
3442
3443 -- Check if -o was used for several mains
3444
3445 if Output_File_Name /= null and then Mains.Number_Of_Mains > 1 then
3446 Osint.Fail ("cannot specify an executable name for several mains");
3447 end if;
3448
3449 -- Check how we are going to do the link
3450
0da2c8ac
AC
3451 if not Data.Other_Sources_Present then
3452
9f4fd324
AC
3453 -- Only Ada sources in the main project, and even maybe not
3454
3455 if not Data.Languages (Lang_Ada) then
0da2c8ac 3456
9f4fd324
AC
3457 -- Fail if the main project has no source of any language
3458
3459 Osint.Fail
3460 ("project """,
3461 Get_Name_String (Data.Name),
3462 """ has no sources, so no main can be linked");
3463
3464 else
3465 -- Only Ada sources in the main project, call gnatmake directly
3466
3467 Last_Argument := 0;
3468
0da2c8ac 3469 -- Choose correct linker if there is C++ code in other projects
9f4fd324
AC
3470
3471 if C_Plus_Plus_Is_Used then
3472 Choose_C_Plus_Plus_Link_Process;
3473 Add_Argument (Dash_largs, Verbose_Mode);
3474 Add_C_Plus_Plus_Link_For_Gnatmake;
3475 Add_Argument (Dash_margs, Verbose_Mode);
3476 end if;
3477
3478 Compile_Link_With_Gnatmake (Mains_Specified);
3479 end if;
3480
3481 else
3482 -- There are other language sources. First check if there are also
3483 -- sources in Ada.
3484
3485 if Data.Languages (Lang_Ada) then
0da2c8ac 3486
9f4fd324
AC
3487 -- There is a mix of Ada and other language sources in the main
3488 -- project. Any main that is not a source of the other languages
3489 -- will be deemed to be an Ada main.
0da2c8ac 3490
9f4fd324
AC
3491 -- Find the mains of the other languages and the Ada mains.
3492
3493 Mains.Reset;
3494 Ada_Mains.Set_Last (0);
3495 Other_Mains.Set_Last (0);
3496
3497 -- For each main
3498
3499 loop
3500 declare
0da2c8ac 3501 Main : constant String := Mains.Next_Main;
9f4fd324 3502 Main_Id : Name_Id;
0da2c8ac 3503
9f4fd324
AC
3504 begin
3505 exit when Main'Length = 0;
3506
3507 -- Get the main file name
3508
3509 Name_Len := 0;
3510 Add_Str_To_Name_Buffer (Main);
3511 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3512 Main_Id := Name_Find;
3513 Source_Id := Data.First_Other_Source;
3514
3515 -- Check if it is a source of a language other than Ada
3516
3517 while Source_Id /= No_Other_Source loop
3518 Source := Other_Sources.Table (Source_Id);
3519 exit when Source.File_Name = Main_Id;
3520 Source_Id := Source.Next;
3521 end loop;
3522
3523 -- If it is not, put it in the list of Ada mains
3524
3525 if Source_Id = No_Other_Source then
3526 Ada_Mains.Increment_Last;
3527 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
3528
3529 -- Otherwise, put it in the list of other mains
3530
3531 else
3532 Other_Mains.Increment_Last;
3533 Other_Mains.Table (Other_Mains.Last) := Source;
3534 end if;
3535 end;
3536 end loop;
3537
3538 -- If C++ is one of the other language, create the shell script
3539 -- to do the link.
3540
3541 if C_Plus_Plus_Is_Used then
3542 Choose_C_Plus_Plus_Link_Process;
3543 end if;
3544
3545 -- Call gnatmake with the necessary switches for each non-Ada
3546 -- main, if there are some.
3547
3548 for Main in 1 .. Other_Mains.Last loop
3549 declare
3550 Source : constant Other_Source := Other_Mains.Table (Main);
0da2c8ac 3551
9f4fd324
AC
3552 begin
3553 Last_Argument := 0;
3554
3555 -- Add -o if -o was specified
3556
3557 if Output_File_Name = null then
3558 Add_Argument (Dash_o, True);
3559 Add_Argument
3560 (Get_Name_String
3561 (Executable_Of
3562 (Project => Main_Project,
3563 Main => Other_Mains.Table (Main).File_Name,
aa720a54 3564 Index => 0,
9f4fd324
AC
3565 Ada_Main => False)),
3566 True);
3567 end if;
3568
3569 -- Call gnatmake with the -B switch
3570
3571 Add_Argument (Dash_B, True);
3572
3573 -- Add to the linking options the object file of the source
3574
3575 Add_Argument (Dash_largs, Verbose_Mode);
3576 Add_Argument
3577 (Get_Name_String (Source.Object_Name), Verbose_Mode);
3578
3579 -- If C++ is one of the language, add the --LINK switch
3580 -- to the linking switches.
3581
3582 if C_Plus_Plus_Is_Used then
3583 Add_C_Plus_Plus_Link_For_Gnatmake;
3584 end if;
3585
3586 -- Add -margs so that the following switches are for
3587 -- gnatmake
3588
3589 Add_Argument (Dash_margs, Verbose_Mode);
3590
3591 -- And link with gnatmake
3592
3593 Compile_Link_With_Gnatmake (Mains_Specified => False);
3594 end;
3595 end loop;
3596
3597 -- If there are also Ada mains, call gnatmake for all these mains
3598
3599 if Ada_Mains.Last /= 0 then
3600 Last_Argument := 0;
3601
3602 -- Put all the Ada mains as the first arguments
3603
3604 for Main in 1 .. Ada_Mains.Last loop
3605 Add_Argument (Ada_Mains.Table (Main).all, True);
3606 end loop;
3607
3608 -- If C++ is one of the languages, add the --LINK switch to
3609 -- the linking switches.
3610
3611 if Data.Languages (Lang_C_Plus_Plus) then
3612 Add_Argument (Dash_largs, Verbose_Mode);
3613 Add_C_Plus_Plus_Link_For_Gnatmake;
3614 Add_Argument (Dash_margs, Verbose_Mode);
3615 end if;
3616
3617 -- And link with gnatmake
3618
3619 Compile_Link_With_Gnatmake (Mains_Specified => False);
3620 end if;
3621
3622 else
3623 -- No Ada source in main project
3624
3625 -- First, get the linker to invoke
3626
3627 if Data.Languages (Lang_C_Plus_Plus) then
3628 Get_Compiler (Lang_C_Plus_Plus);
3629 Linker_Name := Compiler_Names (Lang_C_Plus_Plus);
3630 Linker_Path := Compiler_Paths (Lang_C_Plus_Plus);
3631
3632 else
3633 Get_Compiler (Lang_C);
3634 Linker_Name := Compiler_Names (Lang_C);
3635 Linker_Path := Compiler_Paths (Lang_C);
3636 end if;
3637
3638 Link_Done := False;
3639
3640 Mains.Reset;
3641
3642 -- Get each main, check if it is a source of the main project,
3643 -- and if it is, invoke the linker.
3644
3645 loop
3646 declare
3647 Main : constant String := Mains.Next_Main;
3648 Main_Id : Name_Id;
3649 begin
3650 exit when Main'Length = 0;
3651
3652 -- Get the file name of the main
3653
3654 Name_Len := 0;
3655 Add_Str_To_Name_Buffer (Main);
3656 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3657 Main_Id := Name_Find;
3658 Source_Id := Data.First_Other_Source;
3659
3660 -- Check if it is a source of the main project file
3661
3662 while Source_Id /= No_Other_Source loop
3663 Source := Other_Sources.Table (Source_Id);
3664 exit when Source.File_Name = Main_Id;
3665 Source_Id := Source.Next;
3666 end loop;
3667
3668 -- Report an error if it is not
3669
3670 if Source_Id = No_Other_Source then
3671 Report_Error
3672 (Main, "is not a source of project ",
3673 Get_Name_String (Data.Name));
3674
3675 else
0da2c8ac 3676 Link_Foreign (Main, Main_Id, Source);
9f4fd324
AC
3677 end if;
3678 end;
3679 end loop;
3680
3681 -- If no linking was done, report it, except in Quiet Output
3682
3683 if (Verbose_Mode or (not Quiet_Output)) and (not Link_Done) then
3684 Osint.Write_Program_Name;
3685
3686 if Mains.Number_Of_Mains = 1 then
0da2c8ac 3687
9f4fd324
AC
3688 -- If there is only one executable, report its name too
3689
3690 Write_Str (": """);
3691 Mains.Reset;
3692
3693 declare
0da2c8ac 3694 Main : constant String := Mains.Next_Main;
9f4fd324
AC
3695 Main_Id : Name_Id;
3696 begin
3697 Name_Len := 0;
3698 Add_Str_To_Name_Buffer (Main);
3699 Main_Id := Name_Find;
3700 Write_Str
3701 (Get_Name_String
3702 (Executable_Of
aa720a54
AC
3703 (Project => Main_Project,
3704 Main => Main_Id,
3705 Index => 0,
3706 Ada_Main => False)));
9f4fd324
AC
3707 Write_Line (""" up to date");
3708 end;
3709
3710 else
3711 Write_Line (": all executables up to date");
3712 end if;
3713 end if;
3714 end if;
3715 end if;
3716 end Link_Executables;
3717
3718 ------------------
3719 -- Report_Error --
3720 ------------------
3721
3722 procedure Report_Error
aa720a54
AC
3723 (S1 : String;
3724 S2 : String := "";
3725 S3 : String := "")
9f4fd324
AC
3726 is
3727 begin
0da2c8ac 3728 -- If Keep_Going is True, output error message preceded by error header
9f4fd324
AC
3729
3730 if Keep_Going then
3731 Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
3732 Write_Str (Error_Header);
3733 Write_Str (S1);
3734 Write_Str (S2);
3735 Write_Str (S3);
3736 Write_Eol;
3737
0da2c8ac 3738 -- Otherwise just fail
9f4fd324 3739
0da2c8ac 3740 else
9f4fd324
AC
3741 Osint.Fail (S1, S2, S3);
3742 end if;
3743 end Report_Error;
3744
3745 -------------------------
3746 -- Report_Total_Errors --
3747 -------------------------
3748
3749 procedure Report_Total_Errors (Kind : String) is
3750 begin
3751 if Total_Number_Of_Errors /= 0 then
3752 if Total_Number_Of_Errors = 1 then
3753 Osint.Fail
3754 ("One ", Kind, " error");
3755
3756 else
3757 Osint.Fail
3758 ("Total of" & Total_Number_Of_Errors'Img,
3759 ' ' & Kind & " errors");
3760 end if;
3761 end if;
3762 end Report_Total_Errors;
3763
3764 --------------
3765 -- Scan_Arg --
3766 --------------
3767
3768 procedure Scan_Arg (Arg : String) is
3769 begin
3770 pragma Assert (Arg'First = 1);
3771
3772 if Arg'Length = 0 then
3773 return;
3774 end if;
3775
0da2c8ac
AC
3776 -- If preceding switch was -P, a project file name need to be
3777 -- specified, not a switch.
9f4fd324
AC
3778
3779 if Project_File_Name_Expected then
3780 if Arg (1) = '-' then
3781 Osint.Fail ("project file name missing after -P");
9f4fd324
AC
3782 else
3783 Project_File_Name_Expected := False;
3784 Project_File_Name := new String'(Arg);
3785 end if;
3786
0da2c8ac
AC
3787 -- If preceding switch was -o, an executable name need to be
3788 -- specified, not a switch.
9f4fd324
AC
3789
3790 elsif Output_File_Name_Expected then
3791 if Arg (1) = '-' then
3792 Osint.Fail ("output file name missing after -o");
9f4fd324
AC
3793 else
3794 Output_File_Name_Expected := False;
3795 Output_File_Name := new String'(Arg);
3796 end if;
3797
3798 -- Set the processor/language for the following switches
3799
3800 -- -c???args: Compiler arguments
3801
0da2c8ac
AC
3802 elsif Arg'Length >= 6
3803 and then Arg (Arg'First .. Arg'First + 1) = "-c"
3804 and then Arg (Arg'Last - 3 .. Arg'Last) = "args"
9f4fd324
AC
3805 then
3806 declare
aa720a54 3807 OK : Boolean := False;
9f4fd324
AC
3808 Args_String : constant String :=
3809 Arg (Arg'First + 2 .. Arg'Last - 4);
3810
3811 begin
3812 for Lang in Programming_Language loop
3813 if Args_String = Lang_Args (Lang).all then
3814 OK := True;
3815 Current_Language := Lang;
3816 exit;
3817 end if;
3818 end loop;
3819
3820 if OK then
3821 Current_Processor := Compiler;
9f4fd324
AC
3822 else
3823 Osint.Fail ("illegal option """, Arg, """");
3824 end if;
3825 end;
3826
3827 elsif Arg = "-largs" then
3828 Current_Processor := Linker;
3829
3830 -- -gargs: gprmake
3831
3832 elsif Arg = "-gargs" then
3833 Current_Processor := None;
3834
aa720a54
AC
3835 -- A special test is needed for the -o switch within a -largs since
3836 -- that is another way to specify the name of the final executable.
9f4fd324
AC
3837
3838 elsif Current_Processor = Linker and then Arg = "-o" then
3839 Osint.Fail
3840 ("switch -o not allowed within a -largs. Use -o directly.");
3841
15ce9ca2 3842 -- If current processor is not gprmake directly, store the option in
9f4fd324
AC
3843 -- the appropriate table.
3844
3845 elsif Current_Processor /= None then
3846 Add_Option (Arg);
3847
3848 -- Switches start with '-'
3849
3850 elsif Arg (1) = '-' then
3851 if Arg = "-c" then
3852 Compile_Only := True;
3853
3854 elsif Arg = "-f" then
3855 Force_Compilations := True;
3856
3857 elsif Arg = "-h" then
3858 Usage;
3859
3860 elsif Arg = "-k" then
3861 Keep_Going := True;
3862
3863 elsif Arg = "-o" then
3864 if Output_File_Name /= null then
3865 Osint.Fail ("cannot specify several -o switches");
3866
3867 else
3868 Output_File_Name_Expected := True;
3869 end if;
3870
3871 elsif Arg'Length >= 2 and then Arg (2) = 'P' then
3872 if Project_File_Name /= null then
3873 Osint.Fail ("cannot have several project files specified");
3874
3875 elsif Arg'Length = 2 then
3876 Project_File_Name_Expected := True;
3877
3878 else
3879 Project_File_Name := new String'(Arg (3 .. Arg'Last));
3880 end if;
3881
3882 elsif Arg = "-q" then
3883 Quiet_Output := True;
3884
3885 elsif Arg = "-u" then
3886 Unique_Compile := True;
3887 Compile_Only := True;
3888
3889 elsif Arg = "-v" then
3890 Verbose_Mode := True;
0da2c8ac 3891 Copyright;
9f4fd324
AC
3892
3893 elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
3894 and then Arg (4) in '0' .. '2'
3895 then
3896 case Arg (4) is
3897 when '0' =>
3898 Current_Verbosity := Prj.Default;
3899 when '1' =>
3900 Current_Verbosity := Prj.Medium;
3901 when '2' =>
3902 Current_Verbosity := Prj.High;
3903 when others =>
3904 null;
3905 end case;
3906
3907 elsif Arg'Length >= 3 and then Arg (2) = 'X'
3908 and then Is_External_Assignment (Arg)
3909 then
0da2c8ac 3910 -- Is_External_Assignment has side effects when it returns True
9f4fd324 3911
15ce9ca2
AC
3912 -- Record the -X switch, so that they can be passed to gnatmake,
3913 -- if gnatmake is called.
3914
3915 X_Switches.Increment_Last;
3916 X_Switches.Table (X_Switches.Last) := new String'(Arg);
9f4fd324
AC
3917
3918 else
3919 Osint.Fail ("illegal option """, Arg, """");
3920 end if;
3921
3922 else
3923 -- Not a switch: must be a main
3924
3925 Mains.Add_Main (Arg);
3926 end if;
3927 end Scan_Arg;
3928
3929 -----------------
3930 -- Strip_CR_LF --
3931 -----------------
3932
3933 function Strip_CR_LF (Text : String) return String is
0da2c8ac 3934 To : String (1 .. Text'Length);
9f4fd324
AC
3935 Index_To : Natural := 0;
3936
3937 begin
3938 for Index in Text'Range loop
3939 if (Text (Index) /= ASCII.CR) and then (Text (Index) /= ASCII.LF) then
3940 Index_To := Index_To + 1;
3941 To (Index_To) := Text (Index);
3942 end if;
3943 end loop;
3944
3945 return To (1 .. Index_To);
3946 end Strip_CR_LF;
3947
3948 -----------
3949 -- Usage --
3950 -----------
3951
3952 procedure Usage is
3953 begin
3954 if not Usage_Output then
3955 Usage_Output := True;
3956 Copyright;
3957
3958 Write_Str ("Usage: ");
3959 Osint.Write_Program_Name;
3960 Write_Str (" -P<project file> [opts] [name] {");
3961
3962 for Lang in Programming_Language loop
3963 Write_Str ("[-c");
3964 Write_Str (Lang_Args (Lang).all);
3965 Write_Str ("args opts] ");
3966 end loop;
3967
3968 Write_Str ("[-largs opts] [-gargs opts]}");
3969 Write_Eol;
3970 Write_Eol;
3971 Write_Str (" name is zero or more file names");
3972 Write_Eol;
3973 Write_Eol;
3974
3975 -- GPRMAKE switches
3976
3977 Write_Str ("gprmake switches:");
3978 Write_Eol;
3979
3980 -- Line for -c
3981
3982 Write_Str (" -c Compile only");
3983 Write_Eol;
3984
3985 -- Line for -f
3986
3987 Write_Str (" -f Force recompilations");
3988 Write_Eol;
3989
3990 -- Line for -k
3991
3992 Write_Str (" -k Keep going after compilation errors");
3993 Write_Eol;
3994
3995 -- Line for -o
3996
3997 Write_Str (" -o name Choose an alternate executable name");
3998 Write_Eol;
3999
4000 -- Line for -P
4001
4002 Write_Str (" -Pproj Use GNAT Project File proj");
4003 Write_Eol;
4004
4005 -- Line for -q
4006
4007 Write_Str (" -q Be quiet/terse");
4008 Write_Eol;
4009
4010 -- Line for -u
4011
4012 Write_Str
4013 (" -u Unique compilation. Only compile the given files");
4014 Write_Eol;
4015
4016 -- Line for -v
4017
4018 Write_Str (" -v Verbose output");
4019 Write_Eol;
4020
4021 -- Line for -vPx
4022
4023 Write_Str (" -vPx Specify verbosity when parsing Project Files");
4024 Write_Eol;
4025
4026 -- Line for -X
4027
4028 Write_Str (" -Xnm=val Specify an external reference for " &
4029 "Project Files");
4030 Write_Eol;
4031 Write_Eol;
4032
4033 -- Lines for -c*args
4034
4035 for Lang in Programming_Language loop
4036 declare
4037 Column : Positive := 13 + Lang_Args (Lang)'Length;
4038 -- " -cargs opts" is the minimum and is 13 character long
4039
4040 begin
4041 Write_Str (" -c");
4042 Write_Str (Lang_Args (Lang).all);
4043 Write_Str ("args opts");
4044
4045 loop
4046 Write_Char (' ');
4047 Column := Column + 1;
4048 exit when Column >= 17;
4049 end loop;
4050
4051 Write_Str ("opts are passed to the ");
4052 Write_Str (Lang_Display_Names (Lang).all);
4053 Write_Str (" compiler");
4054 Write_Eol;
4055 end;
4056 end loop;
4057
4058 -- Line for -largs
4059
4060 Write_Str (" -largs opts opts are passed to the linker");
4061 Write_Eol;
4062
4063 -- Line for -gargs
4064
4065 Write_Str (" -gargs opts opts directly interpreted by gprmake");
4066 Write_Eol;
4067 Write_Eol;
4068
4069 end if;
4070 end Usage;
4071
4072begin
4073 Makeutl.Do_Fail := Report_Error'Access;
4074end Makegpr;
This page took 0.497139 seconds and 5 git commands to generate.