1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2004 Free Software Foundation, Inc. --
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. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Ada.Command_Line; use Ada.Command_Line;
28 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
29 with Ada.Text_IO; use Ada.Text_IO;
30 with Ada.Unchecked_Deallocation;
35 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
36 with GNAT.Dynamic_Tables;
37 with GNAT.Expect; use GNAT.Expect;
39 with GNAT.OS_Lib; use GNAT.OS_Lib;
40 with GNAT.Regpat; use GNAT.Regpat;
42 with Makeutl; use Makeutl;
43 with MLib.Tgt; use MLib.Tgt;
44 with Namet; use Namet;
45 with Output; use Output;
47 with Osint; use Osint;
49 with Prj.Com; use Prj.Com;
51 with Prj.Util; use Prj.Util;
52 with Snames; use Snames;
54 with System.Case_Util; use System.Case_Util;
56 with Types; use Types;
58 package body Makegpr is
60 Max_In_Archives : constant := 50;
61 -- The maximum number of arguments for a single invocation of the
62 -- Archive Indexer (ar).
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++.
68 No_Argument : constant Argument_List := (1 .. 0 => null);
69 -- Null argument list representing case of no arguments
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.
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
79 Name_Compiler_Command : Name_Id;
80 -- Names of package IDE and its attribute Compiler_Command.
81 -- Set up by Initialize.
83 Unique_Compile : Boolean := False;
84 -- True when switch -u is used on the command line
86 type Source_Index_Rec is record
89 Found : Boolean := False;
91 -- Used as Source_Indexes component to check if archive needs to be rebuilt
93 type Source_Index_Array is array (Positive range <>) of Source_Index_Rec;
94 type Source_Indexes_Ref is access Source_Index_Array;
96 procedure Free is new Ada.Unchecked_Deallocation
97 (Source_Index_Array, Source_Indexes_Ref);
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.
105 Last_Source : Natural := 0;
106 -- The index of the last valid component of Source_Indexes
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.
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.
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.
120 Archive_Builder_Path : String_Access := null;
121 -- The path name of the archive builder (ar). To be used when spawning
124 Archive_Indexer_Path : String_Access := null;
125 -- The path name of the archive indexer (ranlib), if it exists.
127 Copyright_Output : Boolean := False;
128 Usage_Output : Boolean := False;
129 -- Flags to avoid multiple displays of Copyright notice and of Usage
131 Output_File_Name : String_Access := null;
132 -- The name given after a switch -o
134 Output_File_Name_Expected : Boolean := False;
135 -- True when last switch was -o
137 Project_File_Name : String_Access := null;
138 -- The name of the project file specified with switch -P
140 Project_File_Name_Expected : Boolean := False;
141 -- True when last switch was -P
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
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;
157 -- List of the packages to be checked when parsing/processing project files
159 Main_Project : Project_Id;
160 -- The project id of the main project
162 type Processor is (None, Linker, Compiler);
163 Current_Processor : Processor := None;
164 -- This variable changes when switches -*args are used
166 Current_Language : Programming_Language := Lang_Ada;
167 -- The compiler language to consider when Processor is Compiler
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,
174 Table_Increment => 100);
175 Options : array (Programming_Language) of Comp_Opts.Instance;
176 -- Tables to store compiling options for the different compilers
178 package Linker_Options is new Table.Table
179 (Table_Component_Type => String_Access,
180 Table_Index_Type => Integer,
181 Table_Low_Bound => 1,
183 Table_Increment => 100,
184 Table_Name => "Makegpr.Linker_Options");
185 -- Table to store the linking options
187 package Ada_Mains is new Table.Table
188 (Table_Component_Type => String_Access,
189 Table_Index_Type => Integer,
190 Table_Low_Bound => 1,
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.
197 package Other_Mains is new Table.Table
198 (Table_Component_Type => Other_Source,
199 Table_Index_Type => Integer,
200 Table_Low_Bound => 1,
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.
207 package Sources_Compiled is new GNAT.HTable.Simple_HTable
208 (Header_Num => Header_Num,
215 package X_Switches is new Table.Table
216 (Table_Component_Type => String_Access,
217 Table_Index_Type => Integer,
218 Table_Low_Bound => 1,
220 Table_Increment => 100,
221 Table_Name => "Makegpr.X_Switches");
222 -- Table to store the -X switches to be passed to gnatmake
224 Initial_Argument_Count : constant Positive := 20;
225 type Boolean_Array is array (Positive range <>) of Boolean;
226 type Booleans is access Boolean_Array;
228 procedure Free is new Ada.Unchecked_Deallocation (Boolean_Array, Booleans);
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
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.
239 Last_Argument : Natural := 0;
240 -- Index of the last valid argument in Arguments
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.
253 -- Various switches used when spawning processes:
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;
290 CPATH : constant String := "CPATH";
291 -- The environment variable to set when compiler is a GCC compiler
292 -- to indicate the include directory path.
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.
298 C_Plus_Plus_Is_Used : Boolean := False;
299 -- True when there are sources in C++
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.
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.
309 Need_To_Rebuild_Global_Archive : Boolean := False;
311 Error_Header : constant String := "*** ERROR: ";
312 -- The beginning of error message, when Keep_Going is True
314 Need_To_Relink : Boolean := False;
315 -- True when an executable of a language other than Ada need to be linked
317 Global_Archive_Exists : Boolean := False;
318 -- True if there is a non empty global archive, to prevent creation
321 Path_Option : String_Access;
322 -- The path option switch, when supported
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
334 procedure Add_Archives (For_Gnatmake : Boolean);
335 -- Add to Arguments the list of archives for linking an executable
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.
341 procedure Add_Arguments (Args : Argument_List; Display : Boolean);
342 -- Add a list of arguments to Arguments. Reallocate if necessary
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.
349 procedure Add_Search_Directories
350 (Data : Project_Data;
351 Language : Programming_Language);
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.
356 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id);
357 -- Add a source id to Source_Indexes, with Found set to False
359 procedure Add_Switches
360 (Data : Project_Data;
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.
368 procedure Build_Global_Archive;
369 -- Build the archive for the main project
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
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.
380 procedure Check_Archive_Builder;
381 -- Check if the archive builder (ar) is there
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
389 procedure Check_For_C_Plus_Plus;
390 -- Check if C++ is used in at least one project
393 (Source_Id : Other_Source_Id;
395 Local_Errors : in out Boolean);
396 -- Compile one non-Ada source
398 procedure Compile_Individual_Sources;
399 -- Compile the sources specified on the command line, when in
400 -- Unique_Compile mode.
402 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean);
403 -- Compile/Link with gnatmake when there are Ada sources in the main
404 -- project. Arguments may already contain options to be used by
405 -- gnatmake. Used for both Ada mains and mains of other languages.
406 -- When Compile_Only is True, do not use the linking options
408 procedure Compile_Sources;
409 -- Compile the sources of languages other than Ada, if necessary
412 -- Output the Copyright notice
414 procedure Create_Archive_Dependency_File
416 First_Source : Other_Source_Id);
417 -- Create the archive dependency file for a library project
419 procedure Create_Global_Archive_Dependency_File (Name : String);
420 -- Create the archive depenency file for the main project
422 procedure Display_Command
424 Path : String_Access;
425 CPATH : String_Access := null);
426 -- Display the command for a spawned process, if in Verbose_Mode or
427 -- not in Quiet_Output.
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.
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.
445 procedure Initialize;
446 -- Do the necessary package initialization and process the command line
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.
455 procedure Link_Executables;
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
463 procedure Report_Total_Errors (Kind : String);
464 -- If Total_Number_Of_Errors is not zero, report it, and fail
466 procedure Scan_Arg (Arg : String);
467 -- Process one command line argument
469 function Strip_CR_LF (Text : String) return String;
470 -- Remove characters ASCII.CR and ASCII.LF from a String
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
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.
489 ----------------------------
490 -- Recursive_Add_Archives --
491 ----------------------------
493 procedure Recursive_Add_Archives (Project : Project_Id) is
495 Imported : Project_List;
498 procedure Add_Archive_Path;
499 -- For a library project or the main project, add the archive
500 -- path to the arguments.
502 ----------------------
503 -- Add_Archive_Path --
504 ----------------------
506 procedure Add_Archive_Path is
507 Increment : Positive;
508 Prev_Last : Positive;
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.
517 if not For_Gnatmake then
518 if Data.Library_Kind = Static then
520 (Get_Name_String (Data.Library_Dir) &
521 Directory_Separator &
522 "lib" & Get_Name_String (Data.Library_Name) &
527 -- As we first insert in the reverse order,
528 -- -L<dir> is put after -l<lib>
531 ("-l" & Get_Name_String (Data.Library_Name),
534 Get_Name_String (Data.Library_Dir);
537 ("-L" & Name_Buffer (1 .. Name_Len),
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
547 if Path_Option /= null then
549 -- If it is not the first directory, make room
550 -- at the beginning of the table, including
551 -- for a path separator.
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);
558 for Index in reverse 1 .. Prev_Last loop
559 Lib_Path.Table (Index + Increment) :=
560 Lib_Path.Table (Index);
563 Lib_Path.Table (Increment) := Path_Separator;
566 -- If it is the first directory, just set
567 -- Last to the length of the directory.
569 Lib_Path.Set_Last (Name_Len);
572 -- Put the directory at the beginning of the
575 for Index in 1 .. Name_Len loop
576 Lib_Path.Table (Index) := Name_Buffer (Index);
582 -- For a non-library project, the only archive needed
583 -- is the one for the main project, if there is one.
585 elsif Project = Main_Project and then Global_Archive_Exists then
587 (Get_Name_String (Data.Object_Directory) &
588 Directory_Separator &
589 "lib" & Get_Name_String (Data.Name) &
593 end Add_Archive_Path;
596 -- Nothing to do when there is no project specified
598 if Project /= No_Project then
599 Data := Projects.Table (Project);
601 -- Nothing to do if the project has already been processed
603 if not Data.Seen then
605 -- Mark the project as processed, to avoid processing it again
607 Projects.Table (Project).Seen := True;
609 Recursive_Add_Archives (Data.Extends);
611 Imported := Data.Imported_Projects;
613 -- Call itself recursively for all imported projects
615 while Imported /= Empty_Project_List loop
616 Prj := Project_Lists.Table (Imported).Project;
618 if Prj /= No_Project then
619 while Projects.Table (Prj).Extended_By /= No_Project loop
620 Prj := Projects.Table (Prj).Extended_By;
623 Recursive_Add_Archives (Prj);
626 Imported := Project_Lists.Table (Imported).Next;
629 -- If there is sources of language other than Ada in this
630 -- project, add the path of the archive to Arguments.
632 if Project = Main_Project
633 or else Data.Other_Sources_Present
639 end Recursive_Add_Archives;
641 -- Start of processing for Add_Archives
644 -- First, mark all projects as not processed
646 for Project in 1 .. Projects.Last loop
647 Projects.Table (Project).Seen := False;
650 -- Take care of the run path option
652 if Path_Option = null then
653 Path_Option := MLib.Linker_Library_Path_Option;
656 Lib_Path.Set_Last (0);
658 -- Add archives in the reverse order
660 Recursive_Add_Archives (Main_Project);
662 -- And reverse the order
665 First : Positive := Last_Arg + 1;
666 Last : Natural := Last_Argument;
667 Temp : String_Access;
670 while First < Last loop
671 Temp := Arguments (First);
672 Arguments (First) := Arguments (Last);
673 Arguments (Last) := Temp;
684 procedure Add_Argument (Arg : String_Access; Display : Boolean) is
686 -- Nothing to do if no argument is specified or if argument is empty
688 if Arg /= null or else Arg'Length = 0 then
690 -- Reallocate arrays if necessary
692 if Last_Argument = Arguments'Last then
694 New_Arguments : constant Argument_List_Access :=
696 (1 .. Last_Argument +
697 Initial_Argument_Count);
699 New_Arguments_Displayed : constant Booleans :=
701 (1 .. Last_Argument +
702 Initial_Argument_Count);
705 New_Arguments (Arguments'Range) := Arguments.all;
707 -- To avoid deallocating the strings, nullify all components
708 -- of Arguments before calling Free.
710 Arguments.all := (others => null);
713 Arguments := New_Arguments;
715 New_Arguments_Displayed (Arguments_Displayed'Range) :=
716 Arguments_Displayed.all;
717 Free (Arguments_Displayed);
718 Arguments_Displayed := New_Arguments_Displayed;
722 -- Add the argument and its display indication
724 Last_Argument := Last_Argument + 1;
725 Arguments (Last_Argument) := Arg;
726 Arguments_Displayed (Last_Argument) := Display;
730 procedure Add_Argument (Arg : String; Display : Boolean) is
731 Argument : String_Access := null;
734 -- Nothing to do if argument is empty
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.
740 for Index in 1 .. Cache_Args.Last loop
741 if Cache_Args.Table (Index).all = Arg then
742 Argument := Cache_Args.Table (Index);
747 -- If the argument is not in the cache, create a new entry in the
750 if Argument = null then
751 Argument := new String'(Arg);
752 Cache_Args.Increment_Last;
753 Cache_Args.Table (Cache_Args.Last) := Argument;
756 -- And add the argument
758 Add_Argument (Argument, Display);
766 procedure Add_Arguments (Args : Argument_List; Display : Boolean) is
768 -- Reallocate the arrays, if necessary
770 if Last_Argument + Args'Length > Arguments'Last then
772 New_Arguments : constant Argument_List_Access :=
774 (1 .. Last_Argument + Args'Length +
775 Initial_Argument_Count);
777 New_Arguments_Displayed : constant Booleans :=
779 (1 .. Last_Argument +
781 Initial_Argument_Count);
784 New_Arguments (1 .. Last_Argument) :=
785 Arguments (1 .. Last_Argument);
787 -- To avoid deallocating the strings, nullify all components
788 -- of Arguments before calling Free.
790 Arguments.all := (others => null);
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;
801 -- Add the new arguments and the display indications
803 Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
804 Arguments_Displayed (Last_Argument + 1 .. Last_Argument + Args'Length) :=
806 Last_Argument := Last_Argument + Args'Length;
813 procedure Add_Option (Arg : String) is
814 Option : constant String_Access := new String'(Arg);
817 case Current_Processor is
823 -- Add option to the linker table
825 Linker_Options.Increment_Last;
826 Linker_Options.Table (Linker_Options.Last) := Option;
830 -- Add option to the compiler option table, depending on the
831 -- value of Current_Language.
833 Comp_Opts.Increment_Last (Options (Current_Language));
834 Options (Current_Language).Table
835 (Comp_Opts.Last (Options (Current_Language))) := Option;
844 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id) is
846 -- Reallocate the array, if necessary
848 if Last_Source = Source_Indexes'Last then
850 New_Indexes : constant Source_Indexes_Ref :=
851 new Source_Index_Array
852 (1 .. Source_Indexes'Last +
853 Initial_Source_Index_Count);
855 New_Indexes (Source_Indexes'Range) := Source_Indexes.all;
856 Free (Source_Indexes);
857 Source_Indexes := New_Indexes;
861 Last_Source := Last_Source + 1;
862 Source_Indexes (Last_Source) := (Project, Id, False);
865 ----------------------------
866 -- Add_Search_Directories --
867 ----------------------------
869 procedure Add_Search_Directories
870 (Data : Project_Data;
871 Language : Programming_Language)
874 -- If a GNU compiler is used, set the CPATH environment variable,
875 -- if it does not already has the correct value.
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);
884 Add_Arguments (Data.Imported_Directories_Switches.all, Verbose_Mode);
886 end Add_Search_Directories;
892 procedure Add_Switches
893 (Data : Project_Data;
895 Language : Other_Programming_Language;
898 Switches : Variable_Value;
899 -- The switches, if any, for the file/language
902 -- The id of the package where to look for the switches
904 Defaults : Array_Element_Id;
905 -- The Default_Switches associative array
907 Switches_Array : Array_Element_Id;
908 -- The Switches associative array
910 Element_Id : String_List_Id;
911 Element : String_Element;
914 -- First, choose the proper package
921 Pkg := Value_Of (Name_Linker, Data.Decl.Packages);
924 Pkg := Value_Of (Name_Compiler, Data.Decl.Packages);
927 -- Get the Switches ("file name"), if they exist
929 Switches_Array := Prj.Util.Value_Of
930 (Name => Name_Switches,
932 Packages.Table (Pkg).Decl.Arrays);
938 In_Array => Switches_Array);
940 -- Otherwise, get the Default_Switches ("language"), if they exist
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
947 (Index => Lang_Name_Ids (Language),
949 In_Array => Defaults);
952 -- If there are switches, add them to Arguments
954 if Switches /= Nil_Variable_Value then
955 Element_Id := Switches.Values;
956 while Element_Id /= Nil_String loop
957 Element := String_Elements.Table (Element_Id);
959 if Element.Value /= No_Name then
960 Get_Name_String (Element.Value);
962 if not Quiet_Output then
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.
968 Check (Option => Name_Buffer (1 .. Name_Len));
971 Add_Argument (Name_Buffer (1 .. Name_Len), True);
974 Element_Id := Element.Next;
979 --------------------------
980 -- Build_Global_Archive --
981 --------------------------
983 procedure Build_Global_Archive is
984 Data : Project_Data := Projects.Table (Main_Project);
985 Source_Id : Other_Source_Id;
986 Source : Other_Source;
989 Archive_Name : constant String :=
990 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
991 -- The name of the archive file for this project
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
997 Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
998 -- When True, archive will be rebuilt
1000 File : Prj.Util.Text_File;
1002 Object_Path : Name_Id;
1003 Time_Stamp : Time_Stamp_Type;
1005 Saved_Last_Argument : Natural;
1006 First_Object : Natural;
1011 Check_Archive_Builder;
1013 Change_Dir (Get_Name_String (Data.Object_Directory));
1015 if not Need_To_Rebuild then
1016 if Verbose_Mode then
1017 Write_Str (" Checking ");
1018 Write_Line (Archive_Name);
1021 -- If the archive does not exist, of course it needs to be built
1023 if not Is_Regular_File (Archive_Name) then
1024 Need_To_Rebuild := True;
1026 if Verbose_Mode then
1027 Write_Line (" -> archive does not exist");
1030 -- Archive does exist
1033 -- Check the archive dependency file
1035 Open (File, Archive_Dep_Name);
1037 -- If the archive dependency file does not exist, we need to
1038 -- to rebuild the archive and to create its dependency file.
1040 if not Is_Valid (File) then
1041 Need_To_Rebuild := True;
1043 if Verbose_Mode then
1044 Write_Str (" -> archive dependency file ");
1045 Write_Str (Archive_Dep_Name);
1046 Write_Line (" does not exist");
1050 -- Put all sources of language other than Ada in
1053 for Proj in 1 .. Projects.Last loop
1054 Data := Projects.Table (Proj);
1056 if not Data.Library then
1058 Source_Id := Data.First_Other_Source;
1060 while Source_Id /= No_Other_Source loop
1061 Add_Source_Id (Proj, Source_Id);
1062 Source_Id := Other_Sources.Table (Source_Id).Next;
1067 -- Read the dependency file, line by line
1069 while not End_Of_File (File) loop
1070 Get_Line (File, Name_Buffer, Name_Len);
1072 -- First line is the path of the object file
1074 Object_Path := Name_Find;
1075 Source_Id := No_Other_Source;
1077 -- Check if this object file is for a source of this project
1079 for S in 1 .. Last_Source loop
1080 Source_Id := Source_Indexes (S).Id;
1081 Source := Other_Sources.Table (Source_Id);
1083 if (not Source_Indexes (S).Found)
1084 and then Source.Object_Path = Object_Path
1086 -- We have found the object file: get the source
1087 -- data, and mark it as found.
1089 Source_Indexes (S).Found := True;
1094 -- If it is not for a source of this project, then the
1095 -- archive needs to be rebuilt.
1097 if Source_Id = No_Other_Source then
1098 Need_To_Rebuild := True;
1099 if Verbose_Mode then
1101 Write_Str (Get_Name_String (Object_Path));
1102 Write_Line (" is not an object of any project");
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.
1112 if End_Of_File (File) then
1113 Need_To_Rebuild := True;
1115 if Verbose_Mode then
1116 Write_Str (" -> archive dependency file ");
1117 Write_Line (" is truncated");
1123 Get_Line (File, Name_Buffer, Name_Len);
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.
1129 if Name_Len /= Time_Stamp_Length then
1130 Need_To_Rebuild := True;
1132 if Verbose_Mode then
1133 Write_Str (" -> archive dependency file ");
1134 Write_Line (" is incorrectly formatted (time stamp)");
1140 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
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.
1146 if Time_Stamp /= Source.Object_TS then
1147 Need_To_Rebuild := True;
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");
1165 if not Need_To_Rebuild then
1166 if Verbose_Mode then
1167 Write_Line (" -> up to date");
1170 -- Archive needs to be rebuilt
1173 -- If archive already exists, first delete it
1175 -- Comment needed on why we discard result???
1177 if Is_Regular_File (Archive_Name) then
1178 Delete_File (Archive_Name, Discard);
1183 -- Start with the options found in MLib.Tgt (usually just "rc")
1185 Add_Arguments (Archive_Builder_Options.all, True);
1187 -- Followed by the archive name
1189 Add_Argument (Archive_Name, True);
1191 First_Object := Last_Argument;
1193 -- Followed by all the object files of the non library projects
1195 for Proj in 1 .. Projects.Last loop
1196 Data := Projects.Table (Proj);
1198 if not Data.Library then
1199 Source_Id := Data.First_Other_Source;
1201 while Source_Id /= No_Other_Source loop
1202 Source := Other_Sources.Table (Source_Id);
1204 -- Only include object file name that have not been
1205 -- overriden in extending projects.
1207 if Is_Included_In_Global_Archive
1208 (Source.Object_Name, Proj)
1211 (Get_Name_String (Source.Object_Path), Verbose_Mode);
1214 Source_Id := Source.Next;
1219 -- No need to create a global archive, if there is no object
1220 -- file to put into.
1222 Global_Archive_Exists := Last_Argument > First_Object;
1224 if Global_Archive_Exists then
1226 -- If the archive is built, then linking will need to occur
1229 Need_To_Relink := True;
1231 -- Spawn the archive builder (ar)
1233 Saved_Last_Argument := Last_Argument;
1234 Last_Argument := First_Object + Max_In_Archives;
1236 if Last_Argument > Saved_Last_Argument then
1237 Last_Argument := Saved_Last_Argument;
1240 Display_Command (Archive_Builder, Archive_Builder_Path);
1243 (Archive_Builder_Path.all,
1244 Arguments (1 .. Last_Argument),
1247 exit when not Success;
1249 exit when Last_Argument = Saved_Last_Argument;
1252 Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
1253 Arguments (Last_Argument + 1 .. Saved_Last_Argument);
1254 Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
1257 -- If the archive was built, run the archive indexer (ranlib)
1262 -- If the archive was built, run the archive indexer (ranlib),
1265 if Archive_Indexer_Path /= null then
1267 Add_Argument (Archive_Name, True);
1269 Display_Command (Archive_Indexer, Archive_Indexer_Path);
1272 (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
1276 -- Running ranlib failed, delete the dependency file,
1279 if Is_Regular_File (Archive_Dep_Name) then
1280 Delete_File (Archive_Dep_Name, Success);
1283 -- And report the error
1286 ("running" & Archive_Indexer & " for project """,
1287 Get_Name_String (Data.Name),
1293 -- The archive was correctly built, create its dependency file
1295 Create_Global_Archive_Dependency_File (Archive_Dep_Name);
1297 -- Building the archive failed, delete dependency file if one
1301 if Is_Regular_File (Archive_Dep_Name) then
1302 Delete_File (Archive_Dep_Name, Success);
1305 -- And report the error
1308 ("building archive for project """,
1309 Get_Name_String (Data.Name),
1314 end Build_Global_Archive;
1320 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean) is
1321 Data : constant Project_Data := Projects.Table (Project);
1322 Source_Id : Other_Source_Id;
1323 Source : Other_Source;
1325 Archive_Name : constant String :=
1326 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
1327 -- The name of the archive file for this project
1329 Archive_Dep_Name : constant String :=
1330 "lib" & Get_Name_String (Data.Name) & ".deps";
1331 -- The name of the archive dependency file for this project
1333 Need_To_Rebuild : Boolean := Unconditionally;
1334 -- When True, archive will be rebuilt
1336 File : Prj.Util.Text_File;
1338 Object_Name : Name_Id;
1339 Time_Stamp : Time_Stamp_Type;
1342 Check_Archive_Builder;
1344 -- If Unconditionally is False, check if the archive need to be built
1346 if not Need_To_Rebuild then
1347 if Verbose_Mode then
1348 Write_Str (" Checking ");
1349 Write_Line (Archive_Name);
1352 -- If the archive does not exist, of course it needs to be built
1354 if not Is_Regular_File (Archive_Name) then
1355 Need_To_Rebuild := True;
1357 if Verbose_Mode then
1358 Write_Line (" -> archive does not exist");
1361 -- Archive does exist
1364 -- Check the archive dependency file
1366 Open (File, Archive_Dep_Name);
1368 -- If the archive dependency file does not exist, we need to
1369 -- to rebuild the archive and to create its dependency file.
1371 if not Is_Valid (File) then
1372 Need_To_Rebuild := True;
1374 if Verbose_Mode then
1375 Write_Str (" -> archive dependency file ");
1376 Write_Str (Archive_Dep_Name);
1377 Write_Line (" does not exist");
1381 -- Put all sources of language other than Ada in Source_Indexes
1384 Source_Id := Data.First_Other_Source;
1386 while Source_Id /= No_Other_Source loop
1387 Add_Source_Id (Project, Source_Id);
1388 Source_Id := Other_Sources.Table (Source_Id).Next;
1391 -- Read the dependency file, line by line
1393 while not End_Of_File (File) loop
1394 Get_Line (File, Name_Buffer, Name_Len);
1396 -- First line is the name of an object file
1398 Object_Name := Name_Find;
1399 Source_Id := No_Other_Source;
1401 -- Check if this object file is for a source of this project
1403 for S in 1 .. Last_Source loop
1404 if (not Source_Indexes (S).Found) and then
1406 (Source_Indexes (S).Id).Object_Name =
1409 -- We have found the object file: get the source
1410 -- data, and mark it as found.
1412 Source_Id := Source_Indexes (S).Id;
1413 Source := Other_Sources.Table (Source_Id);
1414 Source_Indexes (S).Found := True;
1419 -- If it is not for a source of this project, then the
1420 -- archive needs to be rebuilt.
1422 if Source_Id = No_Other_Source then
1423 Need_To_Rebuild := True;
1425 if Verbose_Mode then
1427 Write_Str (Get_Name_String (Object_Name));
1428 Write_Line (" is not an object of the project");
1434 -- The second line is the time stamp of the object file.
1435 -- If there is no next line, then the dependency file is
1436 -- truncated, and the archive need to be rebuilt.
1438 if End_Of_File (File) then
1439 Need_To_Rebuild := True;
1441 if Verbose_Mode then
1442 Write_Str (" -> archive dependency file ");
1443 Write_Line (" is truncated");
1449 Get_Line (File, Name_Buffer, Name_Len);
1451 -- If the line has the wrong number of character, then
1452 -- the dependency file is incorrectly formatted, and the
1453 -- archive needs to be rebuilt.
1455 if Name_Len /= Time_Stamp_Length then
1456 Need_To_Rebuild := True;
1458 if Verbose_Mode then
1459 Write_Str (" -> archive dependency file ");
1460 Write_Line (" is incorrectly formatted (time stamp)");
1466 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1468 -- If the time stamp in the dependency file is different
1469 -- from the time stamp of the object file, then the archive
1470 -- needs to be rebuilt.
1472 if Time_Stamp /= Source.Object_TS then
1473 Need_To_Rebuild := True;
1475 if Verbose_Mode then
1476 Write_Str (" -> time stamp of ");
1477 Write_Str (Get_Name_String (Object_Name));
1478 Write_Str (" is incorrect in the archive");
1479 Write_Line (" dependency file");
1488 if not Need_To_Rebuild then
1490 -- Now, check if all object files of the project have been
1491 -- accounted for. If any of them is not in the dependency
1492 -- file, the archive needs to be rebuilt.
1494 for Index in 1 .. Last_Source loop
1495 if not Source_Indexes (Index).Found then
1496 Need_To_Rebuild := True;
1498 if Verbose_Mode then
1499 Source_Id := Source_Indexes (Index).Id;
1500 Source := Other_Sources.Table (Source_Id);
1502 Write_Str (Get_Name_String (Source.Object_Name));
1503 Write_Str (" is not in the archive ");
1504 Write_Line ("dependency file");
1512 if (not Need_To_Rebuild) and Verbose_Mode then
1513 Write_Line (" -> up to date");
1519 -- Build the library if necessary
1521 if Need_To_Rebuild then
1523 -- If a library is built, then linking will need to occur
1526 Need_To_Relink := True;
1530 -- If there are sources in Ada, then gnatmake will build the
1531 -- library, so nothing to do.
1533 if not Data.Languages (Lang_Ada) then
1535 -- Get all the object files of the project
1537 Source_Id := Data.First_Other_Source;
1539 while Source_Id /= No_Other_Source loop
1540 Source := Other_Sources.Table (Source_Id);
1542 (Get_Name_String (Source.Object_Name), Verbose_Mode);
1543 Source_Id := Source.Next;
1546 -- If it is a library, it need to be built it the same way
1547 -- Ada libraries are built.
1549 if Data.Library_Kind = Static then
1551 (Ofiles => Arguments (1 .. Last_Argument),
1552 Afiles => No_Argument,
1553 Output_File => Get_Name_String (Data.Library_Name),
1554 Output_Dir => Get_Name_String (Data.Library_Dir));
1557 MLib.Tgt.Build_Dynamic_Library
1558 (Ofiles => Arguments (1 .. Last_Argument),
1559 Foreign => Arguments (1 .. Last_Argument),
1560 Afiles => No_Argument,
1561 Options => No_Argument,
1562 Interfaces => No_Argument,
1563 Lib_Filename => Get_Name_String (Data.Library_Name),
1564 Lib_Dir => Get_Name_String (Data.Library_Dir),
1565 Symbol_Data => No_Symbols,
1566 Driver_Name => No_Name,
1568 Auto_Init => False);
1572 -- Create fake empty archive, so we can check its time stamp later
1575 Archive : Ada.Text_IO.File_Type;
1578 Create (Archive, Out_File, Archive_Name);
1582 Create_Archive_Dependency_File
1583 (Archive_Dep_Name, Data.First_Other_Source);
1592 procedure Check (Option : String) is
1593 First : Positive := Option'First;
1597 for Index in Option'First + 1 .. Option'Last - 1 loop
1598 if Option (Index) = ' ' and then Option (Index + 1) = '-' then
1599 Write_Str ("warning: switch """);
1601 Write_Str (""" is suspicious; consider using ");
1604 while Last <= Option'Last loop
1605 if Option (Last) = ' ' then
1606 if First /= Option'First then
1611 Write_Str (Option (First .. Last - 1));
1614 while Last <= Option'Last and then Option (Last) = ' ' loop
1621 if Last = Option'Last then
1622 if First /= Option'First then
1627 Write_Str (Option (First .. Last));
1635 Write_Line (" instead");
1641 ---------------------------
1642 -- Check_Archive_Builder --
1643 ---------------------------
1645 procedure Check_Archive_Builder is
1647 -- First, make sure that the archive builder (ar) is on the path
1649 if Archive_Builder_Path = null then
1650 Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
1652 if Archive_Builder_Path = null then
1654 ("unable to locate archive builder """,
1659 -- If there is an archive indexer (ranlib), try to locate it on the
1660 -- path. Don't fail if it is not found.
1662 if Archive_Indexer /= "" then
1663 Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
1666 end Check_Archive_Builder;
1668 ------------------------------
1669 -- Check_Compilation_Needed --
1670 ------------------------------
1672 procedure Check_Compilation_Needed
1673 (Source : Other_Source;
1674 Need_To_Compile : out Boolean)
1676 Source_Name : constant String := Get_Name_String (Source.File_Name);
1677 Source_Path : constant String := Get_Name_String (Source.Path_Name);
1678 Object_Name : constant String := Get_Name_String (Source.Object_Name);
1679 Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
1681 Source_In_Dependencies : Boolean := False;
1682 -- Set True if source was found in dependency file of its object file
1684 Dep_File : Prj.Util.Text_File;
1689 -- Assume the worst, so that statement "return;" may be used if there
1692 Need_To_Compile := True;
1694 if Verbose_Mode then
1695 Write_Str (" Checking ");
1696 Write_Str (Source_Name);
1697 Write_Line (" ... ");
1700 -- If object file does not exist, of course source need to be compiled
1702 if Source.Object_TS = Empty_Time_Stamp then
1703 if Verbose_Mode then
1704 Write_Str (" -> object file ");
1705 Write_Str (Object_Name);
1706 Write_Line (" does not exist");
1712 -- If the object file has been created before the last modification
1713 -- of the source, the source need to be recompiled.
1715 if Source.Object_TS < Source.Source_TS then
1716 if Verbose_Mode then
1717 Write_Str (" -> object file ");
1718 Write_Str (Object_Name);
1719 Write_Line (" has time stamp earlier than source");
1725 -- If there is no dependency file, then the source needs to be
1726 -- recompiled and the dependency file need to be created.
1728 if Source.Dep_TS = Empty_Time_Stamp then
1729 if Verbose_Mode then
1730 Write_Str (" -> dependency file ");
1731 Write_Str (Dep_Name);
1732 Write_Line (" does not exist");
1738 -- The source needs to be recompiled if the source has been modified
1739 -- after the dependency file has been created.
1741 if Source.Dep_TS < Source.Source_TS then
1742 if Verbose_Mode then
1743 Write_Str (" -> dependency file ");
1744 Write_Str (Dep_Name);
1745 Write_Line (" has time stamp earlier than source");
1751 -- Look for all dependencies
1753 Open (Dep_File, Dep_Name);
1755 -- If dependency file cannot be open, we need to recompile the source
1757 if not Is_Valid (Dep_File) then
1758 if Verbose_Mode then
1759 Write_Str (" -> could not open dependency file ");
1760 Write_Line (Dep_Name);
1767 End_Of_File_Reached : Boolean := False;
1771 if End_Of_File (Dep_File) then
1772 End_Of_File_Reached := True;
1776 Get_Line (Dep_File, Name_Buffer, Name_Len);
1778 exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
1781 -- If dependency file contains only empty lines or comments, then
1782 -- dependencies are unknown, and the source needs to be recompiled.
1784 if End_Of_File_Reached then
1785 if Verbose_Mode then
1786 Write_Str (" -> dependency file ");
1787 Write_Str (Dep_Name);
1788 Write_Line (" is empty");
1797 Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
1799 -- First line must start with name of object file, followed by colon
1801 if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
1802 if Verbose_Mode then
1803 Write_Str (" -> dependency file ");
1804 Write_Str (Dep_Name);
1805 Write_Line (" has wrong format");
1812 Start := Finish + 2;
1814 -- Process each line
1818 Line : constant String := Name_Buffer (1 .. Name_Len);
1819 Last : constant Natural := Name_Len;
1824 -- Find the beginning of the next source path name
1826 while Start < Last and then Line (Start) = ' ' loop
1830 -- Go to next line when there is a continuation character \
1831 -- at the end of the line.
1833 exit Name_Loop when Start = Last
1834 and then Line (Start) = '\';
1836 -- We should not be at the end of the line, without
1837 -- a continuation character \.
1839 if Start = Last then
1840 if Verbose_Mode then
1841 Write_Str (" -> dependency file ");
1842 Write_Str (Dep_Name);
1843 Write_Line (" has wrong format");
1850 -- Look for the end of the source path name
1853 while Finish < Last and then Line (Finish + 1) /= ' ' loop
1854 Finish := Finish + 1;
1857 -- Check this source
1860 Src_Name : constant String :=
1862 (Name => Line (Start .. Finish),
1863 Case_Sensitive => False);
1864 Src_TS : Time_Stamp_Type;
1867 -- If it is original source, set Source_In_Dependencies
1869 if Src_Name = Source_Path then
1870 Source_In_Dependencies := True;
1874 Add_Str_To_Name_Buffer (Src_Name);
1875 Src_TS := File_Stamp (Name_Find);
1877 -- If the source does not exist, we need to recompile
1879 if Src_TS = Empty_Time_Stamp then
1880 if Verbose_Mode then
1881 Write_Str (" -> source ");
1882 Write_Str (Src_Name);
1883 Write_Line (" does not exist");
1889 -- If the source has been modified after the object file,
1890 -- we need to recompile.
1892 elsif Src_TS > Source.Object_TS then
1893 if Verbose_Mode then
1894 Write_Str (" -> source ");
1895 Write_Str (Src_Name);
1897 (" has time stamp later than object file");
1905 -- If the source path name ends the line, we are done.
1907 exit Line_Loop when Finish = Last;
1909 -- Go get the next source on the line
1911 Start := Finish + 1;
1915 -- If we are here, we had a continuation character \ at the end
1916 -- of the line, so we continue with the next line.
1918 Get_Line (Dep_File, Name_Buffer, Name_Len);
1925 -- If the original sources were not in the dependency file, then we
1926 -- need to recompile. It may mean that we are using a different source
1927 -- (different variant) for this object file.
1929 if not Source_In_Dependencies then
1930 if Verbose_Mode then
1931 Write_Str (" -> source ");
1932 Write_Str (Source_Path);
1933 Write_Line (" is not in the dependencies");
1939 -- If we are here, then everything is OK, and we don't need
1942 if Verbose_Mode then
1943 Write_Line (" -> up to date");
1946 Need_To_Compile := False;
1947 end Check_Compilation_Needed;
1949 ---------------------------
1950 -- Check_For_C_Plus_Plus --
1951 ---------------------------
1953 procedure Check_For_C_Plus_Plus is
1955 C_Plus_Plus_Is_Used := False;
1957 for Project in 1 .. Projects.Last loop
1958 if Projects.Table (Project).Languages (Lang_C_Plus_Plus) then
1959 C_Plus_Plus_Is_Used := True;
1963 end Check_For_C_Plus_Plus;
1970 (Source_Id : Other_Source_Id;
1971 Data : in Project_Data;
1972 Local_Errors : in out Boolean)
1974 Source : Other_Source := Other_Sources.Table (Source_Id);
1976 CPATH : String_Access := null;
1979 -- If the compiler is not known yet, get its path name
1981 if Compiler_Names (Source.Language) = null then
1982 Get_Compiler (Source.Language);
1985 -- For non GCC compilers, get the dependency file, first calling the
1986 -- compiler with the switch -M.
1988 if not Compiler_Is_Gcc (Source.Language) then
1991 -- Add the source name, preceded by -M
1993 Add_Argument (Dash_M, True);
1994 Add_Argument (Get_Name_String (Source.Path_Name), True);
1996 -- Add the compiling switches for this source found in
1997 -- package Compiler of the project file, if they exist.
2000 (Data, Compiler, Source.Language, Source.File_Name);
2002 -- Add the compiling switches for the language specified
2003 -- on the command line, if any.
2006 J in 1 .. Comp_Opts.Last (Options (Source.Language))
2008 Add_Argument (Options (Source.Language).Table (J), True);
2011 -- Finally, add imported directory switches for this project file
2013 Add_Search_Directories (Data, Source.Language);
2015 -- And invoke the compiler using GNAT.Expect
2018 (Compiler_Names (Source.Language).all,
2019 Compiler_Paths (Source.Language));
2024 Compiler_Paths (Source.Language).all,
2025 Arguments (1 .. Last_Argument),
2027 Err_To_Out => True);
2030 Dep_File : Ada.Text_IO.File_Type;
2031 Result : Expect_Match;
2035 -- Create the dependency file
2037 Create (Dep_File, Out_File, Get_Name_String (Source.Dep_Name));
2040 Expect (FD, Result, Line_Matcher);
2042 exit when Result = Expect_Timeout;
2045 S : constant String := Strip_CR_LF (Expect_Out (FD));
2048 -- Each line of the output is put in the dependency
2049 -- file, including errors. If there are errors, the
2050 -- syntax of the dependency file will be incorrect and
2051 -- recompilation will occur automatically the next time
2052 -- the dependencies are checked.
2054 Put_Line (Dep_File, S);
2058 -- If we are here, it means we had a timeout, so the
2059 -- dependency file may be incomplete. It is safer to
2060 -- delete it, otherwise the dependencies may be wrong.
2064 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2067 when Process_Died =>
2069 -- This is the normal outcome. Just close the file
2076 -- Something wrong happened. It is safer to delete the
2077 -- dependency file, otherwise the dependencies may be wrong.
2081 if Is_Open (Dep_File) then
2085 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2089 -- If we cannot spawn the compiler, then the dependencies are
2090 -- not updated. It is safer then to delete the dependency file,
2091 -- otherwise the dependencies may be wrong.
2093 when Invalid_Process =>
2094 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2100 -- For GCC compilers, make sure the language is always specified to
2101 -- to the GCC driver, in case the extension is not recognized by the
2102 -- GCC driver as a source of the language.
2104 if Compiler_Is_Gcc (Source.Language) then
2105 Add_Argument (Dash_x, Verbose_Mode);
2107 (Lang_Names (Source.Language), Verbose_Mode);
2110 -- Specify the source to be compiled
2112 Add_Argument (Dash_c, True);
2113 Add_Argument (Get_Name_String (Source.Path_Name), True);
2115 -- If non static library project, compile with the PIC option if there
2116 -- is one (when there is no PIC option, function MLib.Tgt.PIC_Option
2117 -- returns an empty string, and Add_Argument with an empty string has
2120 if Data.Library and then Data.Library_Kind /= Static then
2121 Add_Argument (PIC_Option, True);
2124 -- Indicate the name of the object
2126 Add_Argument (Dash_o, True);
2127 Add_Argument (Get_Name_String (Source.Object_Name), True);
2129 -- When compiler is GCC, use the magic switch that creates
2130 -- the dependency file in the correct format.
2132 if Compiler_Is_Gcc (Source.Language) then
2134 ("-Wp,-MD," & Get_Name_String (Source.Dep_Name),
2138 -- Add the compiling switches for this source found in
2139 -- package Compiler of the project file, if they exist.
2142 (Data, Compiler, Source.Language, Source.File_Name);
2144 -- Add the compiling switches for the language specified
2145 -- on the command line, if any.
2147 for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
2148 Add_Argument (Options (Source.Language).Table (J), True);
2151 -- Finally, add the imported directory switches for this
2152 -- project file (or, for gcc compilers, set up the CPATH env var
2155 Add_Search_Directories (Data, Source.Language);
2157 -- Set CPATH, if compiler is GCC
2159 if Compiler_Is_Gcc (Source.Language) then
2160 CPATH := Current_Include_Paths (Source.Language);
2163 -- And invoke the compiler
2166 (Name => Compiler_Names (Source.Language).all,
2167 Path => Compiler_Paths (Source.Language),
2171 (Compiler_Paths (Source.Language).all,
2172 Arguments (1 .. Last_Argument),
2175 -- Case of successful compilation
2179 -- Update the time stamp of the object file
2181 Source.Object_TS := File_Stamp (Source.Object_Name);
2183 -- Do some sanity checks
2185 if Source.Object_TS = Empty_Time_Stamp then
2186 Local_Errors := True;
2189 Get_Name_String (Source.Object_Name),
2190 " has not been created");
2192 elsif Source.Object_TS < Source.Source_TS then
2193 Local_Errors := True;
2196 Get_Name_String (Source.Object_Name),
2197 " has not been modified");
2200 -- Everything looks fine, update the Other_Sources table
2202 Other_Sources.Table (Source_Id) := Source;
2205 -- Compilation failed
2208 Local_Errors := True;
2211 Get_Name_String (Source.Path_Name),
2216 --------------------------------
2217 -- Compile_Individual_Sources --
2218 --------------------------------
2220 procedure Compile_Individual_Sources is
2221 Data : Project_Data := Projects.Table (Main_Project);
2222 Source_Id : Other_Source_Id;
2223 Source : Other_Source;
2224 Source_Name : Name_Id;
2225 Project_Name : String := Get_Name_String (Data.Name);
2226 Dummy : Boolean := False;
2228 Ada_Is_A_Language : constant Boolean := Data.Languages (Lang_Ada);
2232 To_Mixed (Project_Name);
2233 Compile_Only := True;
2235 Get_Imported_Directories (Main_Project, Data);
2236 Projects.Table (Main_Project) := Data;
2238 -- Compilation will occur in the object directory
2240 Change_Dir (Get_Name_String (Data.Object_Directory));
2242 if not Data.Other_Sources_Present then
2243 if Ada_Is_A_Language then
2248 Main : constant String := Mains.Next_Main;
2250 exit when Main'Length = 0;
2251 Ada_Mains.Increment_Last;
2252 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2258 ("project ", Project_Name, " contains no source");
2266 Main : constant String := Mains.Next_Main;
2268 Name_Len := Main'Length;
2269 exit when Name_Len = 0;
2270 Name_Buffer (1 .. Name_Len) := Main;
2271 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2272 Source_Name := Name_Find;
2274 if not Sources_Compiled.Get (Source_Name) then
2275 Sources_Compiled.Set (Source_Name, True);
2276 Source_Id := Data.First_Other_Source;
2278 while Source_Id /= No_Other_Source loop
2279 Source := Other_Sources.Table (Source_Id);
2280 exit when Source.File_Name = Source_Name;
2281 Source_Id := Source.Next;
2284 if Source_Id = No_Other_Source then
2285 if Ada_Is_A_Language then
2286 Ada_Mains.Increment_Last;
2287 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2292 " is not a valid source of project ",
2297 Compile (Source_Id, Data, Dummy);
2304 if Ada_Mains.Last > 0 then
2306 -- Invoke gnatmake for all Ada sources
2309 Add_Argument (Dash_u, True);
2311 for Index in 1 .. Ada_Mains.Last loop
2312 Add_Argument (Ada_Mains.Table (Index), True);
2315 Compile_Link_With_Gnatmake (Mains_Specified => False);
2317 end Compile_Individual_Sources;
2319 --------------------------------
2320 -- Compile_Link_With_Gnatmake --
2321 --------------------------------
2323 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean) is
2324 Data : constant Project_Data := Projects.Table (Main_Project);
2328 -- Array Arguments may already contain some arguments, so we don't
2329 -- set Last_Argument to 0.
2331 -- Get the gnatmake to invoke
2333 Get_Compiler (Lang_Ada);
2335 -- Specify the project file
2337 Add_Argument (Dash_P, True);
2338 Add_Argument (Get_Name_String (Data.Path_Name), True);
2340 -- Add the -X switches, if any
2342 for Index in 1 .. X_Switches.Last loop
2343 Add_Argument (X_Switches.Table (Index), True);
2346 -- If Mains_Specified is True, find the mains in package Mains
2348 if Mains_Specified then
2353 Main : constant String := Mains.Next_Main;
2355 exit when Main'Length = 0;
2356 Add_Argument (Main, True);
2361 -- Specify output file name, if any was specified on the command line
2363 if Output_File_Name /= null then
2364 Add_Argument (Dash_o, True);
2365 Add_Argument (Output_File_Name, True);
2368 -- Transmit some switches to gnatmake
2372 if Compile_Only then
2373 Add_Argument (Dash_c, True);
2379 Add_Argument (Dash_k, True);
2384 if Force_Compilations then
2385 Add_Argument (Dash_f, True);
2390 if Verbose_Mode then
2391 Add_Argument (Dash_v, True);
2396 if Quiet_Output then
2397 Add_Argument (Dash_q, True);
2402 case Current_Verbosity is
2407 Add_Argument (Dash_vP1, True);
2410 Add_Argument (Dash_vP2, True);
2413 -- If there are compiling options for Ada, transmit them to gnatmake
2415 if Comp_Opts.Last (Options (Lang_Ada)) /= 0 then
2416 Add_Argument (Dash_cargs, True);
2418 for Arg in 1 .. Comp_Opts.Last (Options (Lang_Ada)) loop
2419 Add_Argument (Options (Lang_Ada).Table (Arg), True);
2423 if not Compile_Only then
2427 if Linker_Options.Last /= 0 then
2428 Add_Argument (Dash_largs, True);
2430 Add_Argument (Dash_largs, Verbose_Mode);
2435 Add_Archives (For_Gnatmake => True);
2437 -- If there are linking options from the command line,
2438 -- transmit them to gnatmake.
2440 for Arg in 1 .. Linker_Options.Last loop
2441 Add_Argument (Linker_Options.Table (Arg), True);
2445 -- And invoke gnatmake
2448 (Compiler_Names (Lang_Ada).all, Compiler_Paths (Lang_Ada));
2451 (Compiler_Paths (Lang_Ada).all,
2452 Arguments (1 .. Last_Argument),
2455 -- Report an error if call to gnatmake failed
2459 ("invocation of ", Compiler_Names (Lang_Ada).all, " failed");
2462 end Compile_Link_With_Gnatmake;
2464 ---------------------
2465 -- Compile_Sources --
2466 ---------------------
2468 procedure Compile_Sources is
2469 Data : Project_Data;
2470 Source_Id : Other_Source_Id;
2471 Source : Other_Source;
2473 Local_Errors : Boolean := False;
2474 -- Set to True when there is a compilation error. Used only when
2475 -- Keep_Going is True, to inhibit the building of the archive.
2477 Need_To_Compile : Boolean;
2478 -- Set to True when a source needs to be compiled/recompiled.
2480 Need_To_Rebuild_Archive : Boolean := Force_Compilations;
2481 -- True when the archive needs to be built/rebuilt unconditionally
2484 -- Loop through project files
2486 for Project in 1 .. Projects.Last loop
2487 Local_Errors := False;
2488 Data := Projects.Table (Project);
2490 -- Nothing to do when no sources of language other than Ada
2492 if (not Data.Virtual) and then Data.Other_Sources_Present then
2494 -- If the imported directory switches are unknown, compute them
2496 if not Data.Include_Data_Set then
2497 Get_Imported_Directories (Project, Data);
2498 Data.Include_Data_Set := True;
2499 Projects.Table (Project) := Data;
2502 Need_To_Rebuild_Archive := Force_Compilations;
2504 -- Compilation will occur in the object directory
2506 Change_Dir (Get_Name_String (Data.Object_Directory));
2508 Source_Id := Data.First_Other_Source;
2510 -- Process each source one by one
2512 while Source_Id /= No_Other_Source loop
2513 Source := Other_Sources.Table (Source_Id);
2514 Need_To_Compile := Force_Compilations;
2516 -- Check if compilation is needed
2518 if not Need_To_Compile then
2519 Check_Compilation_Needed (Source, Need_To_Compile);
2522 -- Proceed, if compilation is needed
2524 if Need_To_Compile then
2526 -- If a source is compiled/recompiled, of course the
2527 -- archive will need to be built/rebuilt.
2529 Need_To_Rebuild_Archive := True;
2530 Compile (Source_Id, Data, Local_Errors);
2533 -- Next source, if any
2535 Source_Id := Source.Next;
2538 if Need_To_Rebuild_Archive and then (not Data.Library) then
2539 Need_To_Rebuild_Global_Archive := True;
2542 -- If there was no compilation error, build/rebuild the archive
2546 and then Data.Library
2547 and then not Data.Languages (Lang_Ada)
2549 Build_Library (Project, Need_To_Rebuild_Archive);
2553 end Compile_Sources;
2559 procedure Copyright is
2561 -- Only output the Copyright notice once
2563 if not Copyright_Output then
2564 Copyright_Output := True;
2566 Write_Str ("GPRMAKE ");
2567 Write_Str (Gnatvsn.Gnat_Version_String);
2568 Write_Str (" Copyright 2004 Free Software Foundation, Inc.");
2573 ------------------------------------
2574 -- Create_Archive_Dependency_File --
2575 ------------------------------------
2577 procedure Create_Archive_Dependency_File
2579 First_Source : Other_Source_Id)
2581 Source_Id : Other_Source_Id := First_Source;
2582 Source : Other_Source;
2583 Dep_File : Ada.Text_IO.File_Type;
2587 -- Create the file in Append mode, to avoid automatic insertion of
2588 -- an end of line if file is empty.
2590 Create (Dep_File, Append_File, Name);
2592 while Source_Id /= No_Other_Source loop
2593 Source := Other_Sources.Table (Source_Id);
2594 Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
2595 Put_Line (Dep_File, String (Source.Object_TS));
2596 Source_Id := Source.Next;
2603 if Is_Open (Dep_File) then
2606 end Create_Archive_Dependency_File;
2608 -------------------------------------------
2609 -- Create_Global_Archive_Dependency_File --
2610 -------------------------------------------
2612 procedure Create_Global_Archive_Dependency_File (Name : String) is
2613 Source_Id : Other_Source_Id;
2614 Source : Other_Source;
2615 Dep_File : Ada.Text_IO.File_Type;
2620 -- Create the file in Append mode, to avoid automatic insertion of
2621 -- an end of line if file is empty.
2623 Create (Dep_File, Append_File, Name);
2625 -- Get all the object files of non-Ada sources in non-library projects
2627 for Project in 1 .. Projects.Last loop
2628 if not Projects.Table (Project).Library then
2629 Source_Id := Projects.Table (Project).First_Other_Source;
2631 while Source_Id /= No_Other_Source loop
2632 Source := Other_Sources.Table (Source_Id);
2634 -- Put only those object files that are in the global archive
2636 if Is_Included_In_Global_Archive
2637 (Source.Object_Name, Project)
2639 Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
2640 Put_Line (Dep_File, String (Source.Object_TS));
2643 Source_Id := Source.Next;
2652 if Is_Open (Dep_File) then
2655 end Create_Global_Archive_Dependency_File;
2657 ---------------------
2658 -- Display_Command --
2659 ---------------------
2661 procedure Display_Command
2663 Path : String_Access;
2664 CPATH : String_Access := null)
2667 -- Only display the command in Verbose Mode (-v) or when
2668 -- not in Quiet Output (no -q).
2670 if Verbose_Mode or (not Quiet_Output) then
2672 -- In Verbose Mode output the full path of the spawned process
2674 if Verbose_Mode then
2675 if CPATH /= null then
2676 Write_Str ("CPATH = ");
2677 Write_Line (CPATH.all);
2680 Write_Str (Path.all);
2686 -- Display only the arguments for which the display flag is set
2687 -- (in Verbose Mode, the display flag is set for all arguments)
2689 for Arg in 1 .. Last_Argument loop
2690 if Arguments_Displayed (Arg) then
2692 Write_Str (Arguments (Arg).all);
2698 end Display_Command;
2704 procedure Get_Compiler (For_Language : Programming_Language) is
2705 Data : constant Project_Data := Projects.Table (Main_Project);
2707 Ide : constant Package_Id :=
2708 Value_Of (Name_Ide, In_Packages => Data.Decl.Packages);
2709 -- The id of the package IDE in the project file
2711 Compiler : constant Variable_Value :=
2713 (Name => Lang_Name_Ids (For_Language),
2715 Attribute_Or_Array_Name => Name_Compiler_Command,
2717 -- The value of Compiler_Command ("language") in package IDE, if defined
2720 -- No need to do it again if the compiler is known for this language
2722 if Compiler_Names (For_Language) = null then
2724 -- If compiler command is not defined for this language in package
2725 -- IDE, use the default compiler for this language.
2727 if Compiler = Nil_Variable_Value then
2728 Compiler_Names (For_Language) :=
2729 Default_Compiler_Names (For_Language);
2732 Compiler_Names (For_Language) :=
2733 new String'(Get_Name_String (Compiler.Value));
2736 -- Check we have a GCC compiler (name ends with "gcc" or "g++")
2739 Comp_Name : constant String := Compiler_Names (For_Language).all;
2740 Last3 : String (1 .. 3);
2742 if Comp_Name'Length >= 3 then
2743 Last3 := Comp_Name (Comp_Name'Last - 2 .. Comp_Name'Last);
2744 Compiler_Is_Gcc (For_Language) :=
2745 (Last3 = "gcc") or (Last3 = "g++");
2747 Compiler_Is_Gcc (For_Language) := False;
2751 -- Locate the compiler on the path
2753 Compiler_Paths (For_Language) :=
2754 Locate_Exec_On_Path (Compiler_Names (For_Language).all);
2756 -- Fail if compiler cannot be found
2758 if Compiler_Paths (For_Language) = null then
2759 if For_Language = Lang_Ada then
2761 ("unable to locate """,
2762 Compiler_Names (For_Language).all,
2767 ("unable to locate " & Lang_Display_Names (For_Language).all,
2768 " compiler """, Compiler_Names (For_Language).all & '"');
2774 ------------------------------
2775 -- Get_Imported_Directories --
2776 ------------------------------
2778 procedure Get_Imported_Directories
2779 (Project : Project_Id;
2780 Data : in out Project_Data)
2782 Imported_Projects : Project_List := Data.Imported_Projects;
2784 Path_Length : Natural := 0;
2785 Position : Natural := 0;
2787 procedure Add (Source_Dirs : String_List_Id);
2788 -- Add a list of source directories
2790 procedure Recursive_Get_Dirs (Prj : Project_Id);
2791 -- Recursive procedure to get the source directories of this project
2792 -- file and of the project files it imports, in the correct order.
2798 procedure Add (Source_Dirs : String_List_Id) is
2799 Element_Id : String_List_Id := Source_Dirs;
2800 Element : String_Element;
2801 Add_Arg : Boolean := True;
2804 -- Add each source directory path name, preceded by "-I" to Arguments
2806 while Element_Id /= Nil_String loop
2807 Element := String_Elements.Table (Element_Id);
2809 if Element.Value /= No_Name then
2810 Get_Name_String (Element.Value);
2812 if Name_Len > 0 then
2814 Arg : constant String :=
2815 "-I" & Name_Buffer (1 .. Name_Len);
2817 -- Check if directory is already in the list.
2818 -- If it is, no need to put it again.
2820 for Index in 1 .. Last_Argument loop
2821 if Arguments (Index).all = Arg then
2828 if Path_Length /= 0 then
2829 Path_Length := Path_Length + 1;
2832 Path_Length := Path_Length + Name_Len;
2834 Add_Argument (Arg, True);
2840 Element_Id := Element.Next;
2844 ------------------------
2845 -- Recursive_Get_Dirs --
2846 ------------------------
2848 procedure Recursive_Get_Dirs (Prj : Project_Id) is
2849 Data : Project_Data;
2850 Imported : Project_List;
2853 -- Nothing to do if project is undefined
2855 if Prj /= No_Project then
2856 Data := Projects.Table (Prj);
2858 -- Nothing to do if project has already been processed
2860 if not Data.Seen then
2862 -- Mark the project as processed, to avoid multiple processing
2863 -- of the same project.
2865 Projects.Table (Prj).Seen := True;
2867 -- Add the source directories of this project
2869 if not Data.Virtual then
2870 Add (Data.Source_Dirs);
2873 Recursive_Get_Dirs (Data.Extends);
2875 Imported := Data.Imported_Projects;
2877 -- Call itself for all imported projects, if any
2879 while Imported /= Empty_Project_List loop
2880 Recursive_Get_Dirs (Project_Lists.Table (Imported).Project);
2881 Imported := Project_Lists.Table (Imported).Next;
2885 end Recursive_Get_Dirs;
2887 -- Start of processing for Get_Imported_Directories
2890 -- First, mark all project as not processed
2892 for J in 1 .. Projects.Last loop
2893 Projects.Table (J).Seen := False;
2900 -- Process this project individually, project data are already known
2902 Projects.Table (Project).Seen := True;
2904 Add (Data.Source_Dirs);
2906 Recursive_Get_Dirs (Data.Extends);
2908 while Imported_Projects /= Empty_Project_List loop
2909 Recursive_Get_Dirs (Project_Lists.Table (Imported_Projects).Project);
2910 Imported_Projects := Project_Lists.Table (Imported_Projects).Next;
2913 Data.Imported_Directories_Switches :=
2914 new Argument_List'(Arguments (1 .. Last_Argument));
2916 -- Create the Include_Path, from the Arguments
2918 Data.Include_Path := new String (1 .. Path_Length);
2919 Data.Include_Path (1 .. Arguments (1)'Length - 2) :=
2920 Arguments (1)(Arguments (1)'First + 2 .. Arguments (1)'Last);
2921 Position := Arguments (1)'Length - 2;
2923 for Arg in 2 .. Last_Argument loop
2924 Position := Position + 1;
2925 Data.Include_Path (Position) := Path_Separator;
2927 (Position + 1 .. Position + Arguments (Arg)'Length - 2) :=
2928 Arguments (Arg)(Arguments (Arg)'First + 2 .. Arguments (Arg)'Last);
2929 Position := Position + Arguments (Arg)'Length - 2;
2933 end Get_Imported_Directories;
2939 procedure Gprmake is
2943 if Verbose_Mode then
2945 Write_Str ("Parsing Project File """);
2946 Write_Str (Project_File_Name.all);
2951 -- Parse and process project files for other languages (not for Ada)
2954 (Project => Main_Project,
2955 Project_File_Name => Project_File_Name.all,
2956 Packages_To_Check => Packages_To_Check,
2957 Process_Languages => Other_Languages);
2959 -- Fail if parsing/processing was unsuccessful
2961 if Main_Project = No_Project then
2962 Osint.Fail ("""", Project_File_Name.all, """ processing failed");
2965 if Verbose_Mode then
2967 Write_Str ("Parsing of Project File """);
2968 Write_Str (Project_File_Name.all);
2969 Write_Str (""" is finished.");
2973 -- If -f was specified, we will certainly need to link (except when
2974 -- -u or -c were specified, of course).
2976 Need_To_Relink := Force_Compilations;
2978 if Unique_Compile then
2979 if Mains.Number_Of_Mains = 0 then
2981 ("No source specified to compile in 'unique compile' mode");
2983 Compile_Individual_Sources;
2984 Report_Total_Errors ("compilation");
2988 -- First compile sources and build archives for library project,
2993 -- When Keep_Going is True, if we had some errors, fail now,
2994 -- reporting the number of compilation errors.
2995 -- Do not attempt to link.
2997 Report_Total_Errors ("compilation");
2999 -- If -c was not specified, link the executables, if there are any.
3001 if not Compile_Only then
3002 Build_Global_Archive;
3003 Check_For_C_Plus_Plus;
3007 -- When Keep_Going is True, if we had some errors, fail, reporting
3008 -- the number of linking errors.
3010 Report_Total_Errors ("linking");
3018 procedure Initialize is
3020 -- Do some necessary package initializations
3028 -- Set Name_Ide and Name_Compiler_Command
3031 Add_Str_To_Name_Buffer ("ide");
3032 Name_Ide := Name_Find;
3035 Add_Str_To_Name_Buffer ("compiler_command");
3036 Name_Compiler_Command := Name_Find;
3038 -- Make sure the -X switch table is empty
3040 X_Switches.Set_Last (0);
3042 -- Get the command line arguments
3044 Scan_Args : for Next_Arg in 1 .. Argument_Count loop
3045 Scan_Arg (Argument (Next_Arg));
3048 -- Fail if command line ended with "-P"
3050 if Project_File_Name_Expected then
3051 Osint.Fail ("project file name missing after -P");
3053 -- Or if it ended with "-o"
3055 elsif Output_File_Name_Expected then
3056 Osint.Fail ("output file name missing after -o");
3059 -- If no project file was specified, display the usage and fail
3061 if Project_File_Name = null then
3063 Exit_Program (E_Success);
3066 -- To be able of finding libgnat.a in MLib.Tgt, we need to have the
3067 -- default search dirs established in Osint.
3069 Osint.Add_Default_Search_Dirs;
3072 -----------------------------------
3073 -- Is_Included_In_Global_Archive --
3074 -----------------------------------
3076 function Is_Included_In_Global_Archive
3077 (Object_Name : Name_Id;
3078 Project : Project_Id) return Boolean
3080 Data : Project_Data := Projects.Table (Project);
3081 Source : Other_Source_Id;
3084 while Data.Extended_By /= No_Project loop
3085 Data := Projects.Table (Data.Extended_By);
3086 Source := Data.First_Other_Source;
3088 while Source /= No_Other_Source loop
3089 if Other_Sources.Table (Source).Object_Name = Object_Name then
3092 Source := Other_Sources.Table (Source).Next;
3098 end Is_Included_In_Global_Archive;
3100 ----------------------
3101 -- Link_Executables --
3102 ----------------------
3104 procedure Link_Executables is
3105 Data : constant Project_Data := Projects.Table (Main_Project);
3107 Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
3108 -- True if main sources were specified on the command line
3110 Object_Dir : constant String := Get_Name_String (Data.Object_Directory);
3111 -- Path of the object directory of the main project
3113 Source_Id : Other_Source_Id;
3114 Source : Other_Source;
3117 Linker_Name : String_Access;
3118 Linker_Path : String_Access;
3119 -- The linker name and path, when linking is not done by gnatlink
3121 Link_Done : Boolean := False;
3122 -- Set to True when the linker is invoked directly (not through
3123 -- gnatmake) to be able to report if mains were up to date at the end
3126 procedure Add_C_Plus_Plus_Link_For_Gnatmake;
3127 -- Add the --LINK= switch for gnatlink, depending on the C++ compiler
3129 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
3130 -- Check if there is an archive that is more recent than the executable
3131 -- to decide if we need to relink.
3133 procedure Choose_C_Plus_Plus_Link_Process;
3134 -- If the C++ compiler is not g++, create the correct script to link
3136 procedure Link_Foreign
3139 Source : Other_Source);
3140 -- Link a non-Ada main, when there is no Ada code
3142 ---------------------------------------
3143 -- Add_C_Plus_Plus_Link_For_Gnatmake --
3144 ---------------------------------------
3146 procedure Add_C_Plus_Plus_Link_For_Gnatmake is
3148 if Compiler_Is_Gcc (Lang_C_Plus_Plus) then
3150 ("--LINK=" & Compiler_Names (Lang_C_Plus_Plus).all,
3156 Object_Dir & Directory_Separator &
3160 end Add_C_Plus_Plus_Link_For_Gnatmake;
3162 -----------------------
3163 -- Check_Time_Stamps --
3164 -----------------------
3166 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
3167 Prj_Data : Project_Data;
3170 for Prj in 1 .. Projects.Last loop
3171 Prj_Data := Projects.Table (Prj);
3173 -- There is an archive only in project
3174 -- files with sources other than Ada
3177 if Data.Other_Sources_Present then
3179 Archive_Path : constant String :=
3181 (Prj_Data.Object_Directory) &
3182 Directory_Separator &
3184 Get_Name_String (Prj_Data.Name) &
3186 Archive_TS : Time_Stamp_Type;
3189 Add_Str_To_Name_Buffer
3191 Archive_TS := File_Stamp (Name_Find);
3193 -- If the archive is later than the
3194 -- executable, we need to relink.
3196 if Archive_TS /= Empty_Time_Stamp
3198 Exec_Time_Stamp < Archive_TS
3200 Need_To_Relink := True;
3202 if Verbose_Mode then
3204 Write_Str (Archive_Path);
3205 Write_Str (" has time stamp ");
3206 Write_Str ("later than ");
3207 Write_Line ("executable");
3215 end Check_Time_Stamps;
3217 -------------------------------------
3218 -- Choose_C_Plus_Plus_Link_Process --
3219 -------------------------------------
3221 procedure Choose_C_Plus_Plus_Link_Process is
3223 if Compiler_Names (Lang_C_Plus_Plus) = null then
3224 Get_Compiler (Lang_C_Plus_Plus);
3227 if not Compiler_Is_Gcc (Lang_C_Plus_Plus) then
3228 Change_Dir (Object_Dir);
3231 procedure Set_Executable (Name : System.Address);
3233 (C, Set_Executable, "__gnat_set_executable");
3235 Name : constant String := Cpp_Linker & ASCII.NUL;
3237 File : Ada.Text_IO.File_Type;
3241 Create (File, Out_File, Cpp_Linker);
3243 Put_Line (File, "#!/bin/sh");
3245 Put_Line (File, "LIBGCC=`gcc -print-libgcc-file-name`");
3248 Compiler_Names (Lang_C_Plus_Plus).all &
3252 Set_Executable (Name (Name'First)'Address);
3255 end Choose_C_Plus_Plus_Link_Process;
3261 procedure Link_Foreign
3264 Source : Other_Source)
3266 Executable_Name : constant String :=
3269 (Project => Main_Project,
3272 Ada_Main => False));
3273 -- File name of the executable
3275 Executable_Path : constant String :=
3277 (Data.Exec_Directory) &
3278 Directory_Separator &
3280 -- Path name of the executable
3282 Exec_Time_Stamp : Time_Stamp_Type;
3285 -- Now, check if the executable is up to date. It is considered
3286 -- up to date if its time stamp is not earlier that the time stamp
3287 -- of any archive. Only do that if we don't know if we need to link.
3289 if not Need_To_Relink then
3291 -- Get the time stamp of the executable
3294 Add_Str_To_Name_Buffer (Executable_Path);
3295 Exec_Time_Stamp := File_Stamp (Name_Find);
3297 if Verbose_Mode then
3298 Write_Str (" Checking executable ");
3299 Write_Line (Executable_Name);
3302 -- If executable does not exist, we need to link
3304 if Exec_Time_Stamp = Empty_Time_Stamp then
3305 Need_To_Relink := True;
3307 if Verbose_Mode then
3308 Write_Line (" -> not found");
3311 -- Otherwise, get the time stamps of each archive. If one of
3312 -- them is found later than the executable, we need to relink.
3315 Check_Time_Stamps (Exec_Time_Stamp);
3318 -- If Need_To_Relink is False, we are done
3320 if Verbose_Mode and (not Need_To_Relink) then
3321 Write_Line (" -> up to date");
3327 if Need_To_Relink then
3332 -- Specify the executable path name
3334 Add_Argument (Dash_o, True);
3336 (Get_Name_String (Data.Exec_Directory) &
3337 Directory_Separator &
3340 (Project => Main_Project,
3343 Ada_Main => False)),
3346 -- Specify the object file of the main source
3349 (Object_Dir & Directory_Separator &
3350 Get_Name_String (Source.Object_Name),
3353 -- Add all the archives, in a correct order
3355 Add_Archives (For_Gnatmake => False);
3357 -- Add the switches specified in package Linker of
3358 -- the main project.
3363 Language => Source.Language,
3364 File_Name => Main_Id);
3366 -- Add the switches specified in attribute
3367 -- Linker_Options of packages Linker.
3369 if Link_Options_Switches = null then
3370 Link_Options_Switches :=
3372 (Linker_Options_Switches (Main_Project));
3375 Add_Arguments (Link_Options_Switches.all, True);
3377 -- Add the linking options specified on the
3380 for Arg in 1 .. Linker_Options.Last loop
3381 Add_Argument (Linker_Options.Table (Arg), True);
3384 -- If there are shared libraries and the run path
3385 -- option is supported, add the run path switch.
3387 if Lib_Path.Last > 0 then
3390 String (Lib_Path.Table (1 .. Lib_Path.Last)),
3394 -- And invoke the linker
3396 Display_Command (Linker_Name.all, Linker_Path);
3399 Arguments (1 .. Last_Argument),
3403 Report_Error ("could not link ", Main);
3408 -- Start of processing of Link_Executables
3411 -- If no mains specified, get mains from attribute Main, if it exists
3413 if not Mains_Specified then
3415 Element_Id : String_List_Id := Data.Mains;
3416 Element : String_Element;
3419 while Element_Id /= Nil_String loop
3420 Element := String_Elements.Table (Element_Id);
3422 if Element.Value /= No_Name then
3423 Mains.Add_Main (Get_Name_String (Element.Value));
3426 Element_Id := Element.Next;
3431 if Mains.Number_Of_Mains = 0 then
3433 -- If the attribute Main is an empty list or not specified,
3434 -- there is nothing to do.
3436 if Verbose_Mode then
3437 Write_Line ("No main to link");
3442 -- Check if -o was used for several mains
3444 if Output_File_Name /= null and then Mains.Number_Of_Mains > 1 then
3445 Osint.Fail ("cannot specify an executable name for several mains");
3448 -- Check how we are going to do the link
3450 if not Data.Other_Sources_Present then
3452 -- Only Ada sources in the main project, and even maybe not
3454 if not Data.Languages (Lang_Ada) then
3456 -- Fail if the main project has no source of any language
3460 Get_Name_String (Data.Name),
3461 """ has no sources, so no main can be linked");
3464 -- Only Ada sources in the main project, call gnatmake directly
3468 -- Choose correct linker if there is C++ code in other projects
3470 if C_Plus_Plus_Is_Used then
3471 Choose_C_Plus_Plus_Link_Process;
3472 Add_Argument (Dash_largs, Verbose_Mode);
3473 Add_C_Plus_Plus_Link_For_Gnatmake;
3474 Add_Argument (Dash_margs, Verbose_Mode);
3477 Compile_Link_With_Gnatmake (Mains_Specified);
3481 -- There are other language sources. First check if there are also
3484 if Data.Languages (Lang_Ada) then
3486 -- There is a mix of Ada and other language sources in the main
3487 -- project. Any main that is not a source of the other languages
3488 -- will be deemed to be an Ada main.
3490 -- Find the mains of the other languages and the Ada mains.
3493 Ada_Mains.Set_Last (0);
3494 Other_Mains.Set_Last (0);
3500 Main : constant String := Mains.Next_Main;
3504 exit when Main'Length = 0;
3506 -- Get the main file name
3509 Add_Str_To_Name_Buffer (Main);
3510 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3511 Main_Id := Name_Find;
3512 Source_Id := Data.First_Other_Source;
3514 -- Check if it is a source of a language other than Ada
3516 while Source_Id /= No_Other_Source loop
3517 Source := Other_Sources.Table (Source_Id);
3518 exit when Source.File_Name = Main_Id;
3519 Source_Id := Source.Next;
3522 -- If it is not, put it in the list of Ada mains
3524 if Source_Id = No_Other_Source then
3525 Ada_Mains.Increment_Last;
3526 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
3528 -- Otherwise, put it in the list of other mains
3531 Other_Mains.Increment_Last;
3532 Other_Mains.Table (Other_Mains.Last) := Source;
3537 -- If C++ is one of the other language, create the shell script
3540 if C_Plus_Plus_Is_Used then
3541 Choose_C_Plus_Plus_Link_Process;
3544 -- Call gnatmake with the necessary switches for each non-Ada
3545 -- main, if there are some.
3547 for Main in 1 .. Other_Mains.Last loop
3549 Source : constant Other_Source := Other_Mains.Table (Main);
3554 -- Add -o if -o was specified
3556 if Output_File_Name = null then
3557 Add_Argument (Dash_o, True);
3561 (Project => Main_Project,
3562 Main => Other_Mains.Table (Main).File_Name,
3564 Ada_Main => False)),
3568 -- Call gnatmake with the -B switch
3570 Add_Argument (Dash_B, True);
3572 -- Add to the linking options the object file of the source
3574 Add_Argument (Dash_largs, Verbose_Mode);
3576 (Get_Name_String (Source.Object_Name), Verbose_Mode);
3578 -- If C++ is one of the language, add the --LINK switch
3579 -- to the linking switches.
3581 if C_Plus_Plus_Is_Used then
3582 Add_C_Plus_Plus_Link_For_Gnatmake;
3585 -- Add -margs so that the following switches are for
3588 Add_Argument (Dash_margs, Verbose_Mode);
3590 -- And link with gnatmake
3592 Compile_Link_With_Gnatmake (Mains_Specified => False);
3596 -- If there are also Ada mains, call gnatmake for all these mains
3598 if Ada_Mains.Last /= 0 then
3601 -- Put all the Ada mains as the first arguments
3603 for Main in 1 .. Ada_Mains.Last loop
3604 Add_Argument (Ada_Mains.Table (Main).all, True);
3607 -- If C++ is one of the languages, add the --LINK switch to
3608 -- the linking switches.
3610 if Data.Languages (Lang_C_Plus_Plus) then
3611 Add_Argument (Dash_largs, Verbose_Mode);
3612 Add_C_Plus_Plus_Link_For_Gnatmake;
3613 Add_Argument (Dash_margs, Verbose_Mode);
3616 -- And link with gnatmake
3618 Compile_Link_With_Gnatmake (Mains_Specified => False);
3622 -- No Ada source in main project
3624 -- First, get the linker to invoke
3626 if Data.Languages (Lang_C_Plus_Plus) then
3627 Get_Compiler (Lang_C_Plus_Plus);
3628 Linker_Name := Compiler_Names (Lang_C_Plus_Plus);
3629 Linker_Path := Compiler_Paths (Lang_C_Plus_Plus);
3632 Get_Compiler (Lang_C);
3633 Linker_Name := Compiler_Names (Lang_C);
3634 Linker_Path := Compiler_Paths (Lang_C);
3641 -- Get each main, check if it is a source of the main project,
3642 -- and if it is, invoke the linker.
3646 Main : constant String := Mains.Next_Main;
3649 exit when Main'Length = 0;
3651 -- Get the file name of the main
3654 Add_Str_To_Name_Buffer (Main);
3655 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3656 Main_Id := Name_Find;
3657 Source_Id := Data.First_Other_Source;
3659 -- Check if it is a source of the main project file
3661 while Source_Id /= No_Other_Source loop
3662 Source := Other_Sources.Table (Source_Id);
3663 exit when Source.File_Name = Main_Id;
3664 Source_Id := Source.Next;
3667 -- Report an error if it is not
3669 if Source_Id = No_Other_Source then
3671 (Main, "is not a source of project ",
3672 Get_Name_String (Data.Name));
3675 Link_Foreign (Main, Main_Id, Source);
3680 -- If no linking was done, report it, except in Quiet Output
3682 if (Verbose_Mode or (not Quiet_Output)) and (not Link_Done) then
3683 Osint.Write_Program_Name;
3685 if Mains.Number_Of_Mains = 1 then
3687 -- If there is only one executable, report its name too
3693 Main : constant String := Mains.Next_Main;
3697 Add_Str_To_Name_Buffer (Main);
3698 Main_Id := Name_Find;
3702 (Project => Main_Project,
3705 Ada_Main => False)));
3706 Write_Line (""" up to date");
3710 Write_Line (": all executables up to date");
3715 end Link_Executables;
3721 procedure Report_Error
3727 -- If Keep_Going is True, output error message preceded by error header
3730 Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
3731 Write_Str (Error_Header);
3737 -- Otherwise just fail
3740 Osint.Fail (S1, S2, S3);
3744 -------------------------
3745 -- Report_Total_Errors --
3746 -------------------------
3748 procedure Report_Total_Errors (Kind : String) is
3750 if Total_Number_Of_Errors /= 0 then
3751 if Total_Number_Of_Errors = 1 then
3753 ("One ", Kind, " error");
3757 ("Total of" & Total_Number_Of_Errors'Img,
3758 ' ' & Kind & " errors");
3761 end Report_Total_Errors;
3767 procedure Scan_Arg (Arg : String) is
3769 pragma Assert (Arg'First = 1);
3771 if Arg'Length = 0 then
3775 -- If preceding switch was -P, a project file name need to be
3776 -- specified, not a switch.
3778 if Project_File_Name_Expected then
3779 if Arg (1) = '-' then
3780 Osint.Fail ("project file name missing after -P");
3782 Project_File_Name_Expected := False;
3783 Project_File_Name := new String'(Arg);
3786 -- If preceding switch was -o, an executable name need to be
3787 -- specified, not a switch.
3789 elsif Output_File_Name_Expected then
3790 if Arg (1) = '-' then
3791 Osint.Fail ("output file name missing after -o");
3793 Output_File_Name_Expected := False;
3794 Output_File_Name := new String'(Arg);
3797 -- Set the processor/language for the following switches
3799 -- -c???args: Compiler arguments
3801 elsif Arg'Length >= 6
3802 and then Arg (Arg'First .. Arg'First + 1) = "-c"
3803 and then Arg (Arg'Last - 3 .. Arg'Last) = "args"
3806 OK : Boolean := False;
3807 Args_String : constant String :=
3808 Arg (Arg'First + 2 .. Arg'Last - 4);
3811 for Lang in Programming_Language loop
3812 if Args_String = Lang_Args (Lang).all then
3814 Current_Language := Lang;
3820 Current_Processor := Compiler;
3822 Osint.Fail ("illegal option """, Arg, """");
3826 elsif Arg = "-largs" then
3827 Current_Processor := Linker;
3831 elsif Arg = "-gargs" then
3832 Current_Processor := None;
3834 -- A special test is needed for the -o switch within a -largs since
3835 -- that is another way to specify the name of the final executable.
3837 elsif Current_Processor = Linker and then Arg = "-o" then
3839 ("switch -o not allowed within a -largs. Use -o directly.");
3841 -- If current processor is not gprmake directly, store the option in
3842 -- the appropriate table.
3844 elsif Current_Processor /= None then
3847 -- Switches start with '-'
3849 elsif Arg (1) = '-' then
3851 Compile_Only := True;
3853 elsif Arg = "-f" then
3854 Force_Compilations := True;
3856 elsif Arg = "-h" then
3859 elsif Arg = "-k" then
3862 elsif Arg = "-o" then
3863 if Output_File_Name /= null then
3864 Osint.Fail ("cannot specify several -o switches");
3867 Output_File_Name_Expected := True;
3870 elsif Arg'Length >= 2 and then Arg (2) = 'P' then
3871 if Project_File_Name /= null then
3872 Osint.Fail ("cannot have several project files specified");
3874 elsif Arg'Length = 2 then
3875 Project_File_Name_Expected := True;
3878 Project_File_Name := new String'(Arg (3 .. Arg'Last));
3881 elsif Arg = "-q" then
3882 Quiet_Output := True;
3884 elsif Arg = "-u" then
3885 Unique_Compile := True;
3886 Compile_Only := True;
3888 elsif Arg = "-v" then
3889 Verbose_Mode := True;
3892 elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
3893 and then Arg (4) in '0' .. '2'
3897 Current_Verbosity := Prj.Default;
3899 Current_Verbosity := Prj.Medium;
3901 Current_Verbosity := Prj.High;
3906 elsif Arg'Length >= 3 and then Arg (2) = 'X'
3907 and then Is_External_Assignment (Arg)
3909 -- Is_External_Assignment has side effects when it returns True
3911 -- Record the -X switch, so that they can be passed to gnatmake,
3912 -- if gnatmake is called.
3914 X_Switches.Increment_Last;
3915 X_Switches.Table (X_Switches.Last) := new String'(Arg);
3918 Osint.Fail ("illegal option """, Arg, """");
3922 -- Not a switch: must be a main
3924 Mains.Add_Main (Arg);
3932 function Strip_CR_LF (Text : String) return String is
3933 To : String (1 .. Text'Length);
3934 Index_To : Natural := 0;
3937 for Index in Text'Range loop
3938 if (Text (Index) /= ASCII.CR) and then (Text (Index) /= ASCII.LF) then
3939 Index_To := Index_To + 1;
3940 To (Index_To) := Text (Index);
3944 return To (1 .. Index_To);
3953 if not Usage_Output then
3954 Usage_Output := True;
3957 Write_Str ("Usage: ");
3958 Osint.Write_Program_Name;
3959 Write_Str (" -P<project file> [opts] [name] {");
3961 for Lang in Programming_Language loop
3963 Write_Str (Lang_Args (Lang).all);
3964 Write_Str ("args opts] ");
3967 Write_Str ("[-largs opts] [-gargs opts]}");
3970 Write_Str (" name is zero or more file names");
3976 Write_Str ("gprmake switches:");
3981 Write_Str (" -c Compile only");
3986 Write_Str (" -f Force recompilations");
3991 Write_Str (" -k Keep going after compilation errors");
3996 Write_Str (" -o name Choose an alternate executable name");
4001 Write_Str (" -Pproj Use GNAT Project File proj");
4006 Write_Str (" -q Be quiet/terse");
4012 (" -u Unique compilation. Only compile the given files");
4017 Write_Str (" -v Verbose output");
4022 Write_Str (" -vPx Specify verbosity when parsing Project Files");
4027 Write_Str (" -Xnm=val Specify an external reference for " &
4032 -- Lines for -c*args
4034 for Lang in Programming_Language loop
4036 Column : Positive := 13 + Lang_Args (Lang)'Length;
4037 -- " -cargs opts" is the minimum and is 13 character long
4041 Write_Str (Lang_Args (Lang).all);
4042 Write_Str ("args opts");
4046 Column := Column + 1;
4047 exit when Column >= 17;
4050 Write_Str ("opts are passed to the ");
4051 Write_Str (Lang_Display_Names (Lang).all);
4052 Write_Str (" compiler");
4059 Write_Str (" -largs opts opts are passed to the linker");
4064 Write_Str (" -gargs opts opts directly interpreted by gprmake");
4072 Makeutl.Do_Fail := Report_Error'Access;