1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2004-2005 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, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, 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;
50 with Prj.Util; use Prj.Util;
51 with Snames; use Snames;
53 with System.Case_Util; use System.Case_Util;
55 with Types; use Types;
57 package body Makegpr is
59 Max_In_Archives : constant := 50;
60 -- The maximum number of arguments for a single invocation of the
61 -- Archive Indexer (ar).
63 No_Argument : aliased Argument_List := (1 .. 0 => null);
64 -- Null argument list representing case of no arguments
66 FD : Process_Descriptor;
67 -- The process descriptor used when invoking a non GNU compiler with -M
68 -- and getting the output with GNAT.Expect.
70 Line_Matcher : constant Pattern_Matcher := Compile ("^.*?\n", Single_Line);
71 -- Pattern for GNAT.Expect for the invocation of a non GNU compiler with -M
74 Name_Compiler_Command : Name_Id;
75 -- Names of package IDE and its attribute Compiler_Command.
76 -- Set up by Initialize.
78 Unique_Compile : Boolean := False;
79 -- True when switch -u is used on the command line
81 type Source_Index_Rec is record
84 Found : Boolean := False;
86 -- Used as Source_Indexes component to check if archive needs to be rebuilt
88 type Source_Index_Array is array (Positive range <>) of Source_Index_Rec;
89 type Source_Indexes_Ref is access Source_Index_Array;
91 procedure Free is new Ada.Unchecked_Deallocation
92 (Source_Index_Array, Source_Indexes_Ref);
94 Initial_Source_Index_Count : constant Positive := 20;
95 Source_Indexes : Source_Indexes_Ref :=
96 new Source_Index_Array (1 .. Initial_Source_Index_Count);
97 -- A list of the Other_Source_Ids of a project file, with an indication
98 -- that they have been found in the archive dependency file.
100 Last_Source : Natural := 0;
101 -- The index of the last valid component of Source_Indexes
103 Compiler_Names : array (First_Language_Indexes) of String_Access;
104 -- The names of the compilers to be used. Set up by Get_Compiler.
105 -- Used to display the commands spawned.
107 Gnatmake_String : constant String_Access := new String'("gnatmake");
108 GCC_String : constant String_Access := new String'("gcc");
109 G_Plus_Plus_String : constant String_Access := new String'("g++");
111 Default_Compiler_Names : constant array
112 (First_Language_Indexes range
113 Ada_Language_Index .. C_Plus_Plus_Language_Index)
115 (Ada_Language_Index => Gnatmake_String,
116 C_Language_Index => GCC_String,
117 C_Plus_Plus_Language_Index => G_Plus_Plus_String);
119 Compiler_Paths : array (First_Language_Indexes) of String_Access;
120 -- The path names of the compiler to be used. Set up by Get_Compiler.
121 -- Used to spawn compiling/linking processes.
123 Compiler_Is_Gcc : array (First_Language_Indexes) of Boolean;
124 -- An indication that a compiler is a GCC compiler, to be able to use
125 -- specific GCC switches.
127 Archive_Builder_Path : String_Access := null;
128 -- The path name of the archive builder (ar). To be used when spawning
131 Archive_Indexer_Path : String_Access := null;
132 -- The path name of the archive indexer (ranlib), if it exists.
134 Copyright_Output : Boolean := False;
135 Usage_Output : Boolean := False;
136 -- Flags to avoid multiple displays of Copyright notice and of Usage
138 Output_File_Name : String_Access := null;
139 -- The name given after a switch -o
141 Output_File_Name_Expected : Boolean := False;
142 -- True when last switch was -o
144 Project_File_Name : String_Access := null;
145 -- The name of the project file specified with switch -P
147 Project_File_Name_Expected : Boolean := False;
148 -- True when last switch was -P
150 Naming_String : aliased String := "naming";
151 Builder_String : aliased String := "builder";
152 Compiler_String : aliased String := "compiler";
153 Binder_String : aliased String := "binder";
154 Linker_String : aliased String := "linker";
155 -- Name of packages to be checked when parsing/processing project files
157 List_Of_Packages : aliased String_List :=
158 (Naming_String 'Access,
159 Builder_String 'Access,
160 Compiler_String 'Access,
161 Binder_String 'Access,
162 Linker_String 'Access);
163 Packages_To_Check : constant String_List_Access := List_Of_Packages'Access;
164 -- List of the packages to be checked when parsing/processing project files
166 Project_Tree : constant Project_Tree_Ref := new Project_Tree_Data;
168 Main_Project : Project_Id;
169 -- The project id of the main project
171 type Processor is (None, Linker, Compiler);
172 Current_Processor : Processor := None;
173 -- This variable changes when switches -*args are used
175 Current_Language : Language_Index := Ada_Language_Index;
176 -- The compiler language to consider when Processor is Compiler
178 package Comp_Opts is new GNAT.Dynamic_Tables
179 (Table_Component_Type => String_Access,
180 Table_Index_Type => Integer,
181 Table_Low_Bound => 1,
183 Table_Increment => 100);
184 Options : array (First_Language_Indexes) of Comp_Opts.Instance;
185 -- Tables to store compiling options for the different compilers
187 package Linker_Options 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.Linker_Options");
194 -- Table to store the linking options
196 package Library_Opts is new Table.Table
197 (Table_Component_Type => String_Access,
198 Table_Index_Type => Integer,
199 Table_Low_Bound => 1,
201 Table_Increment => 100,
202 Table_Name => "Makegpr.Library_Opts");
203 -- Table to store the linking options
205 package Ada_Mains is new Table.Table
206 (Table_Component_Type => String_Access,
207 Table_Index_Type => Integer,
208 Table_Low_Bound => 1,
210 Table_Increment => 100,
211 Table_Name => "Makegpr.Ada_Mains");
212 -- Table to store the Ada mains, either specified on the command line
213 -- or found in attribute Main of the main project file.
215 package Other_Mains is new Table.Table
216 (Table_Component_Type => Other_Source,
217 Table_Index_Type => Integer,
218 Table_Low_Bound => 1,
220 Table_Increment => 100,
221 Table_Name => "Makegpr.Other_Mains");
222 -- Table to store the mains of languages other than Ada, either specified
223 -- on the command line or found in attribute Main of the main project file.
225 package Sources_Compiled is new GNAT.HTable.Simple_HTable
226 (Header_Num => Header_Num,
233 package X_Switches is new Table.Table
234 (Table_Component_Type => String_Access,
235 Table_Index_Type => Integer,
236 Table_Low_Bound => 1,
238 Table_Increment => 100,
239 Table_Name => "Makegpr.X_Switches");
240 -- Table to store the -X switches to be passed to gnatmake
242 Initial_Argument_Count : constant Positive := 20;
243 type Boolean_Array is array (Positive range <>) of Boolean;
244 type Booleans is access Boolean_Array;
246 procedure Free is new Ada.Unchecked_Deallocation (Boolean_Array, Booleans);
248 Arguments : Argument_List_Access :=
249 new Argument_List (1 .. Initial_Argument_Count);
250 -- Used to store lists of arguments to be used when spawning a process
252 Arguments_Displayed : Booleans :=
253 new Boolean_Array (1 .. Initial_Argument_Count);
254 -- For each argument in Arguments, indicate if the argument should be
255 -- displayed when procedure Display_Command is called.
257 Last_Argument : Natural := 0;
258 -- Index of the last valid argument in Arguments
260 package Cache_Args is new Table.Table
261 (Table_Component_Type => String_Access,
262 Table_Index_Type => Integer,
263 Table_Low_Bound => 1,
264 Table_Initial => 200,
265 Table_Increment => 50,
266 Table_Name => "Makegpr.Cache_Args");
267 -- A table to cache arguments, to avoid multiple allocation of the same
268 -- strings. It is not possible to use a hash table, because String is
269 -- an unconstrained type.
271 -- Various switches used when spawning processes:
273 Dash_B_String : aliased String := "-B";
274 Dash_B : constant String_Access := Dash_B_String'Access;
275 Dash_c_String : aliased String := "-c";
276 Dash_c : constant String_Access := Dash_c_String'Access;
277 Dash_cargs_String : aliased String := "-cargs";
278 Dash_cargs : constant String_Access := Dash_cargs_String'Access;
279 Dash_d_String : aliased String := "-d";
280 Dash_d : constant String_Access := Dash_d_String'Access;
281 Dash_f_String : aliased String := "-f";
282 Dash_f : constant String_Access := Dash_f_String'Access;
283 Dash_k_String : aliased String := "-k";
284 Dash_k : constant String_Access := Dash_k_String'Access;
285 Dash_largs_String : aliased String := "-largs";
286 Dash_largs : constant String_Access := Dash_largs_String'Access;
287 Dash_M_String : aliased String := "-M";
288 Dash_M : constant String_Access := Dash_M_String'Access;
289 Dash_margs_String : aliased String := "-margs";
290 Dash_margs : constant String_Access := Dash_margs_String'Access;
291 Dash_o_String : aliased String := "-o";
292 Dash_o : constant String_Access := Dash_o_String'Access;
293 Dash_P_String : aliased String := "-P";
294 Dash_P : constant String_Access := Dash_P_String'Access;
295 Dash_q_String : aliased String := "-q";
296 Dash_q : constant String_Access := Dash_q_String'Access;
297 Dash_u_String : aliased String := "-u";
298 Dash_u : constant String_Access := Dash_u_String'Access;
299 Dash_v_String : aliased String := "-v";
300 Dash_v : constant String_Access := Dash_v_String'Access;
301 Dash_vP1_String : aliased String := "-vP1";
302 Dash_vP1 : constant String_Access := Dash_vP1_String'Access;
303 Dash_vP2_String : aliased String := "-vP2";
304 Dash_vP2 : constant String_Access := Dash_vP2_String'Access;
305 Dash_x_String : aliased String := "-x";
306 Dash_x : constant String_Access := Dash_x_String'Access;
307 r_String : aliased String := "r";
308 r : constant String_Access := r_String'Access;
310 CPATH : constant String := "CPATH";
311 -- The environment variable to set when compiler is a GCC compiler
312 -- to indicate the include directory path.
314 Current_Include_Paths : array (First_Language_Indexes) of String_Access;
315 -- A cache for the paths of included directories, to avoid setting
316 -- env var CPATH unnecessarily.
318 C_Plus_Plus_Is_Used : Boolean := False;
319 -- True when there are sources in C++
321 Link_Options_Switches : Argument_List_Access := null;
322 -- The link options coming from the attributes Linker'Linker_Options in
323 -- project files imported, directly or indirectly, by the main project.
325 Total_Number_Of_Errors : Natural := 0;
326 -- Used when Keep_Going is True (switch -k) to keep the total number
327 -- of compilation/linking errors, to report at the end of execution.
329 Need_To_Rebuild_Global_Archive : Boolean := False;
331 Error_Header : constant String := "*** ERROR: ";
332 -- The beginning of error message, when Keep_Going is True
334 Need_To_Relink : Boolean := False;
335 -- True when an executable of a language other than Ada need to be linked
337 Global_Archive_Exists : Boolean := False;
338 -- True if there is a non empty global archive, to prevent creation
341 Path_Option : String_Access;
342 -- The path option switch, when supported
344 package Lib_Path is new Table.Table
345 (Table_Component_Type => Character,
346 Table_Index_Type => Integer,
347 Table_Low_Bound => 1,
348 Table_Initial => 200,
349 Table_Increment => 50,
350 Table_Name => "Makegpr.Lib_Path");
351 -- A table to compute the path to put in the path option switch, when it
354 procedure Add_Archives (For_Gnatmake : Boolean);
355 -- Add to Arguments the list of archives for linking an executable
357 procedure Add_Argument (Arg : String_Access; Display : Boolean);
358 procedure Add_Argument (Arg : String; Display : Boolean);
359 -- Add an argument to Arguments. Reallocate if necessary.
361 procedure Add_Arguments (Args : Argument_List; Display : Boolean);
362 -- Add a list of arguments to Arguments. Reallocate if necessary
364 procedure Add_Option (Arg : String);
365 -- Add a switch for the Ada, C or C++ compiler, or for the linker.
366 -- The table where this option is stored depends on the values of
367 -- Current_Processor and Current_Language.
369 procedure Add_Search_Directories
370 (Data : Project_Data;
371 Language : First_Language_Indexes);
372 -- Either add to the Arguments the necessary -I switches needed to
373 -- compile, or, when compiler is gcc/g++, set up the C*INCLUDE_PATH
374 -- environment variable, if necessary.
376 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id);
377 -- Add a source id to Source_Indexes, with Found set to False
379 procedure Add_Switches
380 (Data : Project_Data;
382 Language : Language_Index;
383 File_Name : Name_Id);
384 -- Add to Arguments the switches, if any, for a source (attribute Switches)
385 -- or language (attribute Default_Switches), coming from package Compiler
386 -- or Linker (depending on Proc) of a specified project file.
388 procedure Build_Global_Archive;
389 -- Build the archive for the main project
391 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean);
392 -- Build the library for a library project. If Unconditionally is
393 -- False, first check if the library is up to date, and build it only
396 procedure Check (Option : String);
397 -- Check that a switch coming from a project file is not the concatenation
398 -- of several valid switch, for example "-g -v". If it is, issue a warning.
400 procedure Check_Archive_Builder;
401 -- Check if the archive builder (ar) is there
403 procedure Check_Compilation_Needed
404 (Source : Other_Source;
405 Need_To_Compile : out Boolean);
406 -- Check if a source of a language other than Ada needs to be compiled or
409 procedure Check_For_C_Plus_Plus;
410 -- Check if C++ is used in at least one project
413 (Source_Id : Other_Source_Id;
415 Local_Errors : in out Boolean);
416 -- Compile one non-Ada source
418 procedure Compile_Individual_Sources;
419 -- Compile the sources specified on the command line, when in
420 -- Unique_Compile mode.
422 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean);
423 -- Compile/Link with gnatmake when there are Ada sources in the main
424 -- project. Arguments may already contain options to be used by
425 -- gnatmake. Used for both Ada mains and mains of other languages.
426 -- When Compile_Only is True, do not use the linking options
428 procedure Compile_Sources;
429 -- Compile the sources of languages other than Ada, if necessary
432 -- Output the Copyright notice
434 procedure Create_Archive_Dependency_File
436 First_Source : Other_Source_Id);
437 -- Create the archive dependency file for a library project
439 procedure Create_Global_Archive_Dependency_File (Name : String);
440 -- Create the archive depenency file for the main project
442 procedure Display_Command
444 Path : String_Access;
445 CPATH : String_Access := null);
446 -- Display the command for a spawned process, if in Verbose_Mode or
447 -- not in Quiet_Output.
449 procedure Get_Compiler (For_Language : First_Language_Indexes);
450 -- Find the compiler name and path name for a specified programming
451 -- language, if not already done. Results are in the corresponding
452 -- elements of arrays Compiler_Names and Compiler_Paths. Name of compiler
453 -- is found in package IDE of the main project, or defaulted.
454 -- Fail if compiler cannot be found on the path. For the Ada language,
455 -- gnatmake, rather than the Ada compiler is returned.
457 procedure Get_Imported_Directories
458 (Project : Project_Id;
459 Data : in out Project_Data);
460 -- Find the necessary switches -I to be used when compiling sources
461 -- of languages other than Ada, in a specified project file. Cache the
462 -- result in component Imported_Directories_Switches of the project data.
463 -- For gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
465 procedure Initialize;
466 -- Do the necessary package initialization and process the command line
469 function Is_Included_In_Global_Archive
470 (Object_Name : Name_Id;
471 Project : Project_Id) return Boolean;
472 -- Return True if the object Object_Name is not overridden by a source
473 -- in a project extending project Project.
475 procedure Link_Executables;
478 procedure Report_Error (S1 : String; S2 : String := ""; S3 : String := "");
479 -- Report an error. If Keep_Going is False, just call Osint.Fail.
480 -- If Keep_Going is True, display the error and increase the total number
483 procedure Report_Total_Errors (Kind : String);
484 -- If Total_Number_Of_Errors is not zero, report it, and fail
486 procedure Scan_Arg (Arg : String);
487 -- Process one command line argument
489 function Strip_CR_LF (Text : String) return String;
490 -- Remove characters ASCII.CR and ASCII.LF from a String
499 procedure Add_Archives (For_Gnatmake : Boolean) is
500 Last_Arg : constant Natural := Last_Argument;
501 -- The position of the last argument before adding the archives.
502 -- Used to reverse the order of the arguments added when processing
505 procedure Recursive_Add_Archives (Project : Project_Id);
506 -- Recursive procedure to add the archive of a project file, if any,
507 -- then call itself for the project imported.
509 ----------------------------
510 -- Recursive_Add_Archives --
511 ----------------------------
513 procedure Recursive_Add_Archives (Project : Project_Id) is
515 Imported : Project_List;
518 procedure Add_Archive_Path;
519 -- For a library project or the main project, add the archive
520 -- path to the arguments.
522 ----------------------
523 -- Add_Archive_Path --
524 ----------------------
526 procedure Add_Archive_Path is
527 Increment : Positive;
528 Prev_Last : Positive;
533 -- If it is a library project file, nothing to do if
534 -- gnatmake will be invoked, because gnatmake will take
535 -- care of it, even if the library is not an Ada library.
537 if not For_Gnatmake then
538 if Data.Library_Kind = Static then
540 (Get_Name_String (Data.Library_Dir) &
541 Directory_Separator &
542 "lib" & Get_Name_String (Data.Library_Name) &
547 -- As we first insert in the reverse order,
548 -- -L<dir> is put after -l<lib>
551 ("-l" & Get_Name_String (Data.Library_Name),
554 Get_Name_String (Data.Library_Dir);
557 ("-L" & Name_Buffer (1 .. Name_Len),
560 -- If there is a run path option, prepend this
561 -- directory to the library path. It is probable
562 -- that the order of the directories in the path
563 -- option is not important, but just in case
564 -- put the directories in the same order as the
567 if Path_Option /= null then
569 -- If it is not the first directory, make room
570 -- at the beginning of the table, including
571 -- for a path separator.
573 if Lib_Path.Last > 0 then
574 Increment := Name_Len + 1;
575 Prev_Last := Lib_Path.Last;
576 Lib_Path.Set_Last (Prev_Last + Increment);
578 for Index in reverse 1 .. Prev_Last loop
579 Lib_Path.Table (Index + Increment) :=
580 Lib_Path.Table (Index);
583 Lib_Path.Table (Increment) := Path_Separator;
586 -- If it is the first directory, just set
587 -- Last to the length of the directory.
589 Lib_Path.Set_Last (Name_Len);
592 -- Put the directory at the beginning of the
595 for Index in 1 .. Name_Len loop
596 Lib_Path.Table (Index) := Name_Buffer (Index);
602 -- For a non-library project, the only archive needed
603 -- is the one for the main project, if there is one.
605 elsif Project = Main_Project and then Global_Archive_Exists then
607 (Get_Name_String (Data.Object_Directory) &
608 Directory_Separator &
609 "lib" & Get_Name_String (Data.Name) &
613 end Add_Archive_Path;
616 -- Nothing to do when there is no project specified
618 if Project /= No_Project then
619 Data := Project_Tree.Projects.Table (Project);
621 -- Nothing to do if the project has already been processed
623 if not Data.Seen then
625 -- Mark the project as processed, to avoid processing it again
627 Project_Tree.Projects.Table (Project).Seen := True;
629 Recursive_Add_Archives (Data.Extends);
631 Imported := Data.Imported_Projects;
633 -- Call itself recursively for all imported projects
635 while Imported /= Empty_Project_List loop
636 Prj := Project_Tree.Project_Lists.Table
639 if Prj /= No_Project then
640 while Project_Tree.Projects.Table
641 (Prj).Extended_By /= No_Project
643 Prj := Project_Tree.Projects.Table
647 Recursive_Add_Archives (Prj);
650 Imported := Project_Tree.Project_Lists.Table
654 -- If there is sources of language other than Ada in this
655 -- project, add the path of the archive to Arguments.
657 if Project = Main_Project
658 or else Data.Other_Sources_Present
664 end Recursive_Add_Archives;
666 -- Start of processing for Add_Archives
669 -- First, mark all projects as not processed
671 for Project in Project_Table.First ..
672 Project_Table.Last (Project_Tree.Projects)
674 Project_Tree.Projects.Table (Project).Seen := False;
677 -- Take care of the run path option
679 if Path_Option = null then
680 Path_Option := MLib.Linker_Library_Path_Option;
683 Lib_Path.Set_Last (0);
685 -- Add archives in the reverse order
687 Recursive_Add_Archives (Main_Project);
689 -- And reverse the order
692 First : Positive := Last_Arg + 1;
693 Last : Natural := Last_Argument;
694 Temp : String_Access;
697 while First < Last loop
698 Temp := Arguments (First);
699 Arguments (First) := Arguments (Last);
700 Arguments (Last) := Temp;
711 procedure Add_Argument (Arg : String_Access; Display : Boolean) is
713 -- Nothing to do if no argument is specified or if argument is empty
715 if Arg /= null or else Arg'Length = 0 then
717 -- Reallocate arrays if necessary
719 if Last_Argument = Arguments'Last then
721 New_Arguments : constant Argument_List_Access :=
723 (1 .. Last_Argument +
724 Initial_Argument_Count);
726 New_Arguments_Displayed : constant Booleans :=
728 (1 .. Last_Argument +
729 Initial_Argument_Count);
732 New_Arguments (Arguments'Range) := Arguments.all;
734 -- To avoid deallocating the strings, nullify all components
735 -- of Arguments before calling Free.
737 Arguments.all := (others => null);
740 Arguments := New_Arguments;
742 New_Arguments_Displayed (Arguments_Displayed'Range) :=
743 Arguments_Displayed.all;
744 Free (Arguments_Displayed);
745 Arguments_Displayed := New_Arguments_Displayed;
749 -- Add the argument and its display indication
751 Last_Argument := Last_Argument + 1;
752 Arguments (Last_Argument) := Arg;
753 Arguments_Displayed (Last_Argument) := Display;
757 procedure Add_Argument (Arg : String; Display : Boolean) is
758 Argument : String_Access := null;
761 -- Nothing to do if argument is empty
763 if Arg'Length > 0 then
764 -- Check if the argument is already in the Cache_Args table.
765 -- If it is already there, reuse the allocated value.
767 for Index in 1 .. Cache_Args.Last loop
768 if Cache_Args.Table (Index).all = Arg then
769 Argument := Cache_Args.Table (Index);
774 -- If the argument is not in the cache, create a new entry in the
777 if Argument = null then
778 Argument := new String'(Arg);
779 Cache_Args.Increment_Last;
780 Cache_Args.Table (Cache_Args.Last) := Argument;
783 -- And add the argument
785 Add_Argument (Argument, Display);
793 procedure Add_Arguments (Args : Argument_List; Display : Boolean) is
795 -- Reallocate the arrays, if necessary
797 if Last_Argument + Args'Length > Arguments'Last then
799 New_Arguments : constant Argument_List_Access :=
801 (1 .. Last_Argument + Args'Length +
802 Initial_Argument_Count);
804 New_Arguments_Displayed : constant Booleans :=
806 (1 .. Last_Argument +
808 Initial_Argument_Count);
811 New_Arguments (1 .. Last_Argument) :=
812 Arguments (1 .. Last_Argument);
814 -- To avoid deallocating the strings, nullify all components
815 -- of Arguments before calling Free.
817 Arguments.all := (others => null);
820 Arguments := New_Arguments;
821 New_Arguments_Displayed (1 .. Last_Argument) :=
822 Arguments_Displayed (1 .. Last_Argument);
823 Free (Arguments_Displayed);
824 Arguments_Displayed := New_Arguments_Displayed;
828 -- Add the new arguments and the display indications
830 Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
831 Arguments_Displayed (Last_Argument + 1 .. Last_Argument + Args'Length) :=
833 Last_Argument := Last_Argument + Args'Length;
840 procedure Add_Option (Arg : String) is
841 Option : constant String_Access := new String'(Arg);
844 case Current_Processor is
850 -- Add option to the linker table
852 Linker_Options.Increment_Last;
853 Linker_Options.Table (Linker_Options.Last) := Option;
857 -- Add option to the compiler option table, depending on the
858 -- value of Current_Language.
860 Comp_Opts.Increment_Last (Options (Current_Language));
861 Options (Current_Language).Table
862 (Comp_Opts.Last (Options (Current_Language))) := Option;
871 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id) is
873 -- Reallocate the array, if necessary
875 if Last_Source = Source_Indexes'Last then
877 New_Indexes : constant Source_Indexes_Ref :=
878 new Source_Index_Array
879 (1 .. Source_Indexes'Last +
880 Initial_Source_Index_Count);
882 New_Indexes (Source_Indexes'Range) := Source_Indexes.all;
883 Free (Source_Indexes);
884 Source_Indexes := New_Indexes;
888 Last_Source := Last_Source + 1;
889 Source_Indexes (Last_Source) := (Project, Id, False);
892 ----------------------------
893 -- Add_Search_Directories --
894 ----------------------------
896 procedure Add_Search_Directories
897 (Data : Project_Data;
898 Language : First_Language_Indexes)
901 -- If a GNU compiler is used, set the CPATH environment variable,
902 -- if it does not already has the correct value.
904 if Compiler_Is_Gcc (Language) then
905 if Current_Include_Paths (Language) /= Data.Include_Path then
906 Current_Include_Paths (Language) := Data.Include_Path;
907 Setenv (CPATH, Data.Include_Path.all);
911 Add_Arguments (Data.Imported_Directories_Switches.all, Verbose_Mode);
913 end Add_Search_Directories;
919 procedure Add_Switches
920 (Data : Project_Data;
922 Language : Language_Index;
925 Switches : Variable_Value;
926 -- The switches, if any, for the file/language
929 -- The id of the package where to look for the switches
931 Defaults : Array_Element_Id;
932 -- The Default_Switches associative array
934 Switches_Array : Array_Element_Id;
935 -- The Switches associative array
937 Element_Id : String_List_Id;
938 Element : String_Element;
941 -- First, choose the proper package
948 Pkg := Value_Of (Name_Linker, Data.Decl.Packages, Project_Tree);
951 Pkg := Value_Of (Name_Compiler, Data.Decl.Packages, Project_Tree);
954 if Pkg /= No_Package then
955 -- Get the Switches ("file name"), if they exist
957 Switches_Array := Prj.Util.Value_Of
958 (Name => Name_Switches,
959 In_Arrays => Project_Tree.Packages.Table
961 In_Tree => Project_Tree);
967 In_Array => Switches_Array,
968 In_Tree => Project_Tree);
970 -- Otherwise, get the Default_Switches ("language"), if they exist
972 if Switches = Nil_Variable_Value then
973 Defaults := Prj.Util.Value_Of
974 (Name => Name_Default_Switches,
975 In_Arrays => Project_Tree.Packages.Table
977 In_Tree => Project_Tree);
978 Switches := Prj.Util.Value_Of
979 (Index => Language_Names.Table (Language),
981 In_Array => Defaults,
982 In_Tree => Project_Tree);
985 -- If there are switches, add them to Arguments
987 if Switches /= Nil_Variable_Value then
988 Element_Id := Switches.Values;
989 while Element_Id /= Nil_String loop
990 Element := Project_Tree.String_Elements.Table
993 if Element.Value /= No_Name then
994 Get_Name_String (Element.Value);
996 if not Quiet_Output then
998 -- When not in quiet output (no -q), check that the
999 -- switch is not the concatenation of several valid
1000 -- switches, such as "-g -v". If it is, issue a warning.
1002 Check (Option => Name_Buffer (1 .. Name_Len));
1005 Add_Argument (Name_Buffer (1 .. Name_Len), True);
1008 Element_Id := Element.Next;
1014 --------------------------
1015 -- Build_Global_Archive --
1016 --------------------------
1018 procedure Build_Global_Archive is
1019 Data : Project_Data :=
1020 Project_Tree.Projects.Table (Main_Project);
1021 Source_Id : Other_Source_Id;
1022 S_Id : Other_Source_Id;
1023 Source : Other_Source;
1026 Archive_Name : constant String :=
1027 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
1028 -- The name of the archive file for this project
1030 Archive_Dep_Name : constant String :=
1031 "lib" & Get_Name_String (Data.Name) & ".deps";
1032 -- The name of the archive dependency file for this project
1034 Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
1035 -- When True, archive will be rebuilt
1037 File : Prj.Util.Text_File;
1039 Object_Path : Name_Id;
1040 Time_Stamp : Time_Stamp_Type;
1042 Saved_Last_Argument : Natural;
1043 First_Object : Natural;
1048 Check_Archive_Builder;
1050 Change_Dir (Get_Name_String (Data.Object_Directory));
1052 if not Need_To_Rebuild then
1053 if Verbose_Mode then
1054 Write_Str (" Checking ");
1055 Write_Line (Archive_Name);
1058 -- If the archive does not exist, of course it needs to be built
1060 if not Is_Regular_File (Archive_Name) then
1061 Need_To_Rebuild := True;
1063 if Verbose_Mode then
1064 Write_Line (" -> archive does not exist");
1067 -- Archive does exist
1070 -- Check the archive dependency file
1072 Open (File, Archive_Dep_Name);
1074 -- If the archive dependency file does not exist, we need to
1075 -- to rebuild the archive and to create its dependency file.
1077 if not Is_Valid (File) then
1078 Need_To_Rebuild := True;
1080 if Verbose_Mode then
1081 Write_Str (" -> archive dependency file ");
1082 Write_Str (Archive_Dep_Name);
1083 Write_Line (" does not exist");
1087 -- Put all sources of language other than Ada in
1091 Local_Data : Project_Data;
1096 for Proj in Project_Table.First ..
1097 Project_Table.Last (Project_Tree.Projects)
1099 Local_Data := Project_Tree.Projects.Table (Proj);
1101 if not Local_Data.Library then
1102 Source_Id := Local_Data.First_Other_Source;
1104 while Source_Id /= No_Other_Source loop
1105 Add_Source_Id (Proj, Source_Id);
1106 Source_Id := Project_Tree.Other_Sources.Table
1113 -- Read the dependency file, line by line
1115 while not End_Of_File (File) loop
1116 Get_Line (File, Name_Buffer, Name_Len);
1118 -- First line is the path of the object file
1120 Object_Path := Name_Find;
1121 Source_Id := No_Other_Source;
1123 -- Check if this object file is for a source of this project
1125 for S in 1 .. Last_Source loop
1126 S_Id := Source_Indexes (S).Id;
1127 Source := Project_Tree.Other_Sources.Table (S_Id);
1129 if (not Source_Indexes (S).Found)
1130 and then Source.Object_Path = Object_Path
1132 -- We have found the object file: get the source
1133 -- data, and mark it as found.
1136 Source_Indexes (S).Found := True;
1141 -- If it is not for a source of this project, then the
1142 -- archive needs to be rebuilt.
1144 if Source_Id = No_Other_Source then
1145 Need_To_Rebuild := True;
1146 if Verbose_Mode then
1148 Write_Str (Get_Name_String (Object_Path));
1149 Write_Line (" is not an object of any project");
1155 -- The second line is the time stamp of the object file.
1156 -- If there is no next line, then the dependency file is
1157 -- truncated, and the archive need to be rebuilt.
1159 if End_Of_File (File) then
1160 Need_To_Rebuild := True;
1162 if Verbose_Mode then
1163 Write_Str (" -> archive dependency file ");
1164 Write_Line (" is truncated");
1170 Get_Line (File, Name_Buffer, Name_Len);
1172 -- If the line has the wrong number of characters, then
1173 -- the dependency file is incorrectly formatted, and the
1174 -- archive needs to be rebuilt.
1176 if Name_Len /= Time_Stamp_Length then
1177 Need_To_Rebuild := True;
1179 if Verbose_Mode then
1180 Write_Str (" -> archive dependency file ");
1181 Write_Line (" is incorrectly formatted (time stamp)");
1187 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1189 -- If the time stamp in the dependency file is different
1190 -- from the time stamp of the object file, then the archive
1191 -- needs to be rebuilt.
1193 if Time_Stamp /= Source.Object_TS then
1194 Need_To_Rebuild := True;
1196 if Verbose_Mode then
1197 Write_Str (" -> time stamp of ");
1198 Write_Str (Get_Name_String (Object_Path));
1199 Write_Str (" is incorrect in the archive");
1200 Write_Line (" dependency file");
1212 if not Need_To_Rebuild then
1213 if Verbose_Mode then
1214 Write_Line (" -> up to date");
1217 -- No need to create a global archive, if there is no object
1218 -- file to put into.
1220 Global_Archive_Exists := Last_Source /= 0;
1222 -- Archive needs to be rebuilt
1225 -- If archive already exists, first delete it
1227 -- Comment needed on why we discard result???
1229 if Is_Regular_File (Archive_Name) then
1230 Delete_File (Archive_Name, Discard);
1235 -- Start with the options found in MLib.Tgt (usually just "rc")
1237 Add_Arguments (Archive_Builder_Options.all, True);
1239 -- Followed by the archive name
1241 Add_Argument (Archive_Name, True);
1243 First_Object := Last_Argument;
1245 -- Followed by all the object files of the non library projects
1247 for Proj in Project_Table.First ..
1248 Project_Table.Last (Project_Tree.Projects)
1250 Data := Project_Tree.Projects.Table (Proj);
1252 if not Data.Library then
1253 Source_Id := Data.First_Other_Source;
1255 while Source_Id /= No_Other_Source loop
1257 Project_Tree.Other_Sources.Table (Source_Id);
1259 -- Only include object file name that have not been
1260 -- overriden in extending projects.
1262 if Is_Included_In_Global_Archive
1263 (Source.Object_Name, Proj)
1266 (Get_Name_String (Source.Object_Path), Verbose_Mode);
1269 Source_Id := Source.Next;
1274 -- No need to create a global archive, if there is no object
1275 -- file to put into.
1277 Global_Archive_Exists := Last_Argument > First_Object;
1279 if Global_Archive_Exists then
1281 -- If the archive is built, then linking will need to occur
1284 Need_To_Relink := True;
1286 -- Spawn the archive builder (ar)
1288 Saved_Last_Argument := Last_Argument;
1289 Last_Argument := First_Object + Max_In_Archives;
1291 if Last_Argument > Saved_Last_Argument then
1292 Last_Argument := Saved_Last_Argument;
1295 Display_Command (Archive_Builder, Archive_Builder_Path);
1298 (Archive_Builder_Path.all,
1299 Arguments (1 .. Last_Argument),
1302 exit when not Success;
1304 exit when Last_Argument = Saved_Last_Argument;
1307 Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
1308 Arguments (Last_Argument + 1 .. Saved_Last_Argument);
1309 Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
1312 -- If the archive was built, run the archive indexer (ranlib)
1317 -- If the archive was built, run the archive indexer (ranlib),
1320 if Archive_Indexer_Path /= null then
1322 Add_Argument (Archive_Name, True);
1324 Display_Command (Archive_Indexer, Archive_Indexer_Path);
1327 (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
1331 -- Running ranlib failed, delete the dependency file,
1334 if Is_Regular_File (Archive_Dep_Name) then
1335 Delete_File (Archive_Dep_Name, Success);
1338 -- And report the error
1341 ("running" & Archive_Indexer & " for project """,
1342 Get_Name_String (Data.Name),
1348 -- The archive was correctly built, create its dependency file
1350 Create_Global_Archive_Dependency_File (Archive_Dep_Name);
1352 -- Building the archive failed, delete dependency file if one
1356 if Is_Regular_File (Archive_Dep_Name) then
1357 Delete_File (Archive_Dep_Name, Success);
1360 -- And report the error
1363 ("building archive for project """,
1364 Get_Name_String (Data.Name),
1369 end Build_Global_Archive;
1375 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean) is
1376 Data : constant Project_Data :=
1377 Project_Tree.Projects.Table (Project);
1378 Source_Id : Other_Source_Id;
1379 Source : Other_Source;
1381 Archive_Name : constant String :=
1382 "lib" & Get_Name_String (Data.Name) & '.' & Archive_Ext;
1383 -- The name of the archive file for this project
1385 Archive_Dep_Name : constant String :=
1386 "lib" & Get_Name_String (Data.Name) & ".deps";
1387 -- The name of the archive dependency file for this project
1389 Need_To_Rebuild : Boolean := Unconditionally;
1390 -- When True, archive will be rebuilt
1392 File : Prj.Util.Text_File;
1394 Object_Name : Name_Id;
1395 Time_Stamp : Time_Stamp_Type;
1396 Driver_Name : Name_Id := No_Name;
1398 Lib_Opts : Argument_List_Access := No_Argument'Access;
1400 Check_Archive_Builder;
1402 -- If Unconditionally is False, check if the archive need to be built
1404 if not Need_To_Rebuild then
1405 if Verbose_Mode then
1406 Write_Str (" Checking ");
1407 Write_Line (Archive_Name);
1410 -- If the archive does not exist, of course it needs to be built
1412 if not Is_Regular_File (Archive_Name) then
1413 Need_To_Rebuild := True;
1415 if Verbose_Mode then
1416 Write_Line (" -> archive does not exist");
1419 -- Archive does exist
1422 -- Check the archive dependency file
1424 Open (File, Archive_Dep_Name);
1426 -- If the archive dependency file does not exist, we need to
1427 -- to rebuild the archive and to create its dependency file.
1429 if not Is_Valid (File) then
1430 Need_To_Rebuild := True;
1432 if Verbose_Mode then
1433 Write_Str (" -> archive dependency file ");
1434 Write_Str (Archive_Dep_Name);
1435 Write_Line (" does not exist");
1439 -- Put all sources of language other than Ada in Source_Indexes
1442 Source_Id := Data.First_Other_Source;
1444 while Source_Id /= No_Other_Source loop
1445 Add_Source_Id (Project, Source_Id);
1446 Source_Id := Project_Tree.Other_Sources.Table
1450 -- Read the dependency file, line by line
1452 while not End_Of_File (File) loop
1453 Get_Line (File, Name_Buffer, Name_Len);
1455 -- First line is the name of an object file
1457 Object_Name := Name_Find;
1458 Source_Id := No_Other_Source;
1460 -- Check if this object file is for a source of this project
1462 for S in 1 .. Last_Source loop
1463 if (not Source_Indexes (S).Found)
1465 Project_Tree.Other_Sources.Table
1466 (Source_Indexes (S).Id).Object_Name = Object_Name
1468 -- We have found the object file: get the source
1469 -- data, and mark it as found.
1471 Source_Id := Source_Indexes (S).Id;
1472 Source := Project_Tree.Other_Sources.Table
1474 Source_Indexes (S).Found := True;
1479 -- If it is not for a source of this project, then the
1480 -- archive needs to be rebuilt.
1482 if Source_Id = No_Other_Source then
1483 Need_To_Rebuild := True;
1485 if Verbose_Mode then
1487 Write_Str (Get_Name_String (Object_Name));
1488 Write_Line (" is not an object of the project");
1494 -- The second line is the time stamp of the object file.
1495 -- If there is no next line, then the dependency file is
1496 -- truncated, and the archive need to be rebuilt.
1498 if End_Of_File (File) then
1499 Need_To_Rebuild := True;
1501 if Verbose_Mode then
1502 Write_Str (" -> archive dependency file ");
1503 Write_Line (" is truncated");
1509 Get_Line (File, Name_Buffer, Name_Len);
1511 -- If the line has the wrong number of character, then
1512 -- the dependency file is incorrectly formatted, and the
1513 -- archive needs to be rebuilt.
1515 if Name_Len /= Time_Stamp_Length then
1516 Need_To_Rebuild := True;
1518 if Verbose_Mode then
1519 Write_Str (" -> archive dependency file ");
1520 Write_Line (" is incorrectly formatted (time stamp)");
1526 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1528 -- If the time stamp in the dependency file is different
1529 -- from the time stamp of the object file, then the archive
1530 -- needs to be rebuilt.
1532 if Time_Stamp /= Source.Object_TS then
1533 Need_To_Rebuild := True;
1535 if Verbose_Mode then
1536 Write_Str (" -> time stamp of ");
1537 Write_Str (Get_Name_String (Object_Name));
1538 Write_Str (" is incorrect in the archive");
1539 Write_Line (" dependency file");
1548 if not Need_To_Rebuild then
1550 -- Now, check if all object files of the project have been
1551 -- accounted for. If any of them is not in the dependency
1552 -- file, the archive needs to be rebuilt.
1554 for Index in 1 .. Last_Source loop
1555 if not Source_Indexes (Index).Found then
1556 Need_To_Rebuild := True;
1558 if Verbose_Mode then
1559 Source_Id := Source_Indexes (Index).Id;
1560 Source := Project_Tree.Other_Sources.Table
1563 Write_Str (Get_Name_String (Source.Object_Name));
1564 Write_Str (" is not in the archive ");
1565 Write_Line ("dependency file");
1573 if (not Need_To_Rebuild) and Verbose_Mode then
1574 Write_Line (" -> up to date");
1580 -- Build the library if necessary
1582 if Need_To_Rebuild then
1584 -- If a library is built, then linking will need to occur
1587 Need_To_Relink := True;
1591 -- If there are sources in Ada, then gnatmake will build the
1592 -- library, so nothing to do.
1594 if not Data.Languages (Ada_Language_Index) then
1596 -- Get all the object files of the project
1598 Source_Id := Data.First_Other_Source;
1600 while Source_Id /= No_Other_Source loop
1601 Source := Project_Tree.Other_Sources.Table (Source_Id);
1603 (Get_Name_String (Source.Object_Name), Verbose_Mode);
1604 Source_Id := Source.Next;
1607 -- If it is a library, it need to be built it the same way
1608 -- Ada libraries are built.
1610 if Data.Library_Kind = Static then
1612 (Ofiles => Arguments (1 .. Last_Argument),
1613 Afiles => No_Argument,
1614 Output_File => Get_Name_String (Data.Library_Name),
1615 Output_Dir => Get_Name_String (Data.Library_Dir));
1618 -- Link with g++ if C++ is one of the languages, otherwise
1619 -- building the library may fail with unresolved symbols.
1621 if C_Plus_Plus_Is_Used then
1622 if Compiler_Names (C_Plus_Plus_Language_Index) = null then
1623 Get_Compiler (C_Plus_Plus_Language_Index);
1626 if Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
1628 Add_Str_To_Name_Buffer
1629 (Compiler_Names (C_Plus_Plus_Language_Index).all);
1630 Driver_Name := Name_Find;
1634 -- If Library_Options is specified, add these options
1637 Library_Options : constant Variable_Value :=
1639 (Name_Library_Options,
1640 Data.Decl.Attributes,
1644 if not Library_Options.Default then
1646 Current : String_List_Id := Library_Options.Values;
1647 Element : String_Element;
1650 while Current /= Nil_String loop
1651 Element := Project_Tree.String_Elements.
1653 Get_Name_String (Element.Value);
1655 if Name_Len /= 0 then
1656 Library_Opts.Increment_Last;
1657 Library_Opts.Table (Library_Opts.Last) :=
1658 new String'(Name_Buffer (1 .. Name_Len));
1661 Current := Element.Next;
1667 new Argument_List'(Argument_List
1668 (Library_Opts.Table (1 .. Library_Opts.Last)));
1671 MLib.Tgt.Build_Dynamic_Library
1672 (Ofiles => Arguments (1 .. Last_Argument),
1673 Foreign => Arguments (1 .. Last_Argument),
1674 Afiles => No_Argument,
1675 Options => No_Argument,
1676 Options_2 => Lib_Opts.all,
1677 Interfaces => No_Argument,
1678 Lib_Filename => Get_Name_String (Data.Library_Name),
1679 Lib_Dir => Get_Name_String (Data.Library_Dir),
1680 Symbol_Data => No_Symbols,
1681 Driver_Name => Driver_Name,
1683 Auto_Init => False);
1687 -- Create fake empty archive, so we can check its time stamp later
1690 Archive : Ada.Text_IO.File_Type;
1693 Create (Archive, Out_File, Archive_Name);
1697 Create_Archive_Dependency_File
1698 (Archive_Dep_Name, Data.First_Other_Source);
1706 procedure Check (Option : String) is
1707 First : Positive := Option'First;
1711 for Index in Option'First + 1 .. Option'Last - 1 loop
1712 if Option (Index) = ' ' and then Option (Index + 1) = '-' then
1713 Write_Str ("warning: switch """);
1715 Write_Str (""" is suspicious; consider using ");
1718 while Last <= Option'Last loop
1719 if Option (Last) = ' ' then
1720 if First /= Option'First then
1725 Write_Str (Option (First .. Last - 1));
1728 while Last <= Option'Last and then Option (Last) = ' ' loop
1735 if Last = Option'Last then
1736 if First /= Option'First then
1741 Write_Str (Option (First .. Last));
1749 Write_Line (" instead");
1755 ---------------------------
1756 -- Check_Archive_Builder --
1757 ---------------------------
1759 procedure Check_Archive_Builder is
1761 -- First, make sure that the archive builder (ar) is on the path
1763 if Archive_Builder_Path = null then
1764 Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
1766 if Archive_Builder_Path = null then
1768 ("unable to locate archive builder """,
1773 -- If there is an archive indexer (ranlib), try to locate it on the
1774 -- path. Don't fail if it is not found.
1776 if Archive_Indexer /= "" then
1777 Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
1780 end Check_Archive_Builder;
1782 ------------------------------
1783 -- Check_Compilation_Needed --
1784 ------------------------------
1786 procedure Check_Compilation_Needed
1787 (Source : Other_Source;
1788 Need_To_Compile : out Boolean)
1790 Source_Name : constant String := Get_Name_String (Source.File_Name);
1791 Source_Path : constant String := Get_Name_String (Source.Path_Name);
1792 Object_Name : constant String := Get_Name_String (Source.Object_Name);
1793 Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
1795 Source_In_Dependencies : Boolean := False;
1796 -- Set True if source was found in dependency file of its object file
1798 Dep_File : Prj.Util.Text_File;
1803 -- Assume the worst, so that statement "return;" may be used if there
1806 Need_To_Compile := True;
1808 if Verbose_Mode then
1809 Write_Str (" Checking ");
1810 Write_Str (Source_Name);
1811 Write_Line (" ... ");
1814 -- If object file does not exist, of course source need to be compiled
1816 if Source.Object_TS = Empty_Time_Stamp then
1817 if Verbose_Mode then
1818 Write_Str (" -> object file ");
1819 Write_Str (Object_Name);
1820 Write_Line (" does not exist");
1826 -- If the object file has been created before the last modification
1827 -- of the source, the source need to be recompiled.
1829 if Source.Object_TS < Source.Source_TS then
1830 if Verbose_Mode then
1831 Write_Str (" -> object file ");
1832 Write_Str (Object_Name);
1833 Write_Line (" has time stamp earlier than source");
1839 -- If there is no dependency file, then the source needs to be
1840 -- recompiled and the dependency file need to be created.
1842 if Source.Dep_TS = Empty_Time_Stamp then
1843 if Verbose_Mode then
1844 Write_Str (" -> dependency file ");
1845 Write_Str (Dep_Name);
1846 Write_Line (" does not exist");
1852 -- The source needs to be recompiled if the source has been modified
1853 -- after the dependency file has been created.
1855 if Source.Dep_TS < Source.Source_TS then
1856 if Verbose_Mode then
1857 Write_Str (" -> dependency file ");
1858 Write_Str (Dep_Name);
1859 Write_Line (" has time stamp earlier than source");
1865 -- Look for all dependencies
1867 Open (Dep_File, Dep_Name);
1869 -- If dependency file cannot be open, we need to recompile the source
1871 if not Is_Valid (Dep_File) then
1872 if Verbose_Mode then
1873 Write_Str (" -> could not open dependency file ");
1874 Write_Line (Dep_Name);
1881 End_Of_File_Reached : Boolean := False;
1885 if End_Of_File (Dep_File) then
1886 End_Of_File_Reached := True;
1890 Get_Line (Dep_File, Name_Buffer, Name_Len);
1892 exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
1895 -- If dependency file contains only empty lines or comments, then
1896 -- dependencies are unknown, and the source needs to be recompiled.
1898 if End_Of_File_Reached then
1899 if Verbose_Mode then
1900 Write_Str (" -> dependency file ");
1901 Write_Str (Dep_Name);
1902 Write_Line (" is empty");
1911 Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
1913 -- First line must start with name of object file, followed by colon
1915 if Finish = 0 or else Name_Buffer (1 .. Finish - 1) /= Object_Name then
1916 if Verbose_Mode then
1917 Write_Str (" -> dependency file ");
1918 Write_Str (Dep_Name);
1919 Write_Line (" has wrong format");
1926 Start := Finish + 2;
1928 -- Process each line
1932 Line : constant String := Name_Buffer (1 .. Name_Len);
1933 Last : constant Natural := Name_Len;
1938 -- Find the beginning of the next source path name
1940 while Start < Last and then Line (Start) = ' ' loop
1944 -- Go to next line when there is a continuation character \
1945 -- at the end of the line.
1947 exit Name_Loop when Start = Last
1948 and then Line (Start) = '\';
1950 -- We should not be at the end of the line, without
1951 -- a continuation character \.
1953 if Start = Last then
1954 if Verbose_Mode then
1955 Write_Str (" -> dependency file ");
1956 Write_Str (Dep_Name);
1957 Write_Line (" has wrong format");
1964 -- Look for the end of the source path name
1967 while Finish < Last and then Line (Finish + 1) /= ' ' loop
1968 Finish := Finish + 1;
1971 -- Check this source
1974 Src_Name : constant String :=
1976 (Name => Line (Start .. Finish),
1977 Case_Sensitive => False);
1978 Src_TS : Time_Stamp_Type;
1981 -- If it is original source, set Source_In_Dependencies
1983 if Src_Name = Source_Path then
1984 Source_In_Dependencies := True;
1988 Add_Str_To_Name_Buffer (Src_Name);
1989 Src_TS := File_Stamp (Name_Find);
1991 -- If the source does not exist, we need to recompile
1993 if Src_TS = Empty_Time_Stamp then
1994 if Verbose_Mode then
1995 Write_Str (" -> source ");
1996 Write_Str (Src_Name);
1997 Write_Line (" does not exist");
2003 -- If the source has been modified after the object file,
2004 -- we need to recompile.
2006 elsif Src_TS > Source.Object_TS then
2007 if Verbose_Mode then
2008 Write_Str (" -> source ");
2009 Write_Str (Src_Name);
2011 (" has time stamp later than object file");
2019 -- If the source path name ends the line, we are done.
2021 exit Line_Loop when Finish = Last;
2023 -- Go get the next source on the line
2025 Start := Finish + 1;
2029 -- If we are here, we had a continuation character \ at the end
2030 -- of the line, so we continue with the next line.
2032 Get_Line (Dep_File, Name_Buffer, Name_Len);
2039 -- If the original sources were not in the dependency file, then we
2040 -- need to recompile. It may mean that we are using a different source
2041 -- (different variant) for this object file.
2043 if not Source_In_Dependencies then
2044 if Verbose_Mode then
2045 Write_Str (" -> source ");
2046 Write_Str (Source_Path);
2047 Write_Line (" is not in the dependencies");
2053 -- If we are here, then everything is OK, and we don't need
2056 if Verbose_Mode then
2057 Write_Line (" -> up to date");
2060 Need_To_Compile := False;
2061 end Check_Compilation_Needed;
2063 ---------------------------
2064 -- Check_For_C_Plus_Plus --
2065 ---------------------------
2067 procedure Check_For_C_Plus_Plus is
2069 C_Plus_Plus_Is_Used := False;
2071 for Project in Project_Table.First ..
2072 Project_Table.Last (Project_Tree.Projects)
2075 Project_Tree.Projects.Table (Project).Languages
2076 (C_Plus_Plus_Language_Index)
2078 C_Plus_Plus_Is_Used := True;
2082 end Check_For_C_Plus_Plus;
2089 (Source_Id : Other_Source_Id;
2090 Data : in Project_Data;
2091 Local_Errors : in out Boolean)
2093 Source : Other_Source :=
2094 Project_Tree.Other_Sources.Table (Source_Id);
2096 CPATH : String_Access := null;
2099 -- If the compiler is not known yet, get its path name
2101 if Compiler_Names (Source.Language) = null then
2102 Get_Compiler (Source.Language);
2105 -- For non GCC compilers, get the dependency file, first calling the
2106 -- compiler with the switch -M.
2108 if not Compiler_Is_Gcc (Source.Language) then
2111 -- Add the source name, preceded by -M
2113 Add_Argument (Dash_M, True);
2114 Add_Argument (Get_Name_String (Source.Path_Name), True);
2116 -- Add the compiling switches for this source found in
2117 -- package Compiler of the project file, if they exist.
2120 (Data, Compiler, Source.Language, Source.File_Name);
2122 -- Add the compiling switches for the language specified
2123 -- on the command line, if any.
2126 J in 1 .. Comp_Opts.Last (Options (Source.Language))
2128 Add_Argument (Options (Source.Language).Table (J), True);
2131 -- Finally, add imported directory switches for this project file
2133 Add_Search_Directories (Data, Source.Language);
2135 -- And invoke the compiler using GNAT.Expect
2138 (Compiler_Names (Source.Language).all,
2139 Compiler_Paths (Source.Language));
2144 Compiler_Paths (Source.Language).all,
2145 Arguments (1 .. Last_Argument),
2147 Err_To_Out => True);
2150 Dep_File : Ada.Text_IO.File_Type;
2151 Result : Expect_Match;
2155 -- Create the dependency file
2157 Create (Dep_File, Out_File, Get_Name_String (Source.Dep_Name));
2160 Expect (FD, Result, Line_Matcher);
2162 exit when Result = Expect_Timeout;
2165 S : constant String := Strip_CR_LF (Expect_Out (FD));
2168 -- Each line of the output is put in the dependency
2169 -- file, including errors. If there are errors, the
2170 -- syntax of the dependency file will be incorrect and
2171 -- recompilation will occur automatically the next time
2172 -- the dependencies are checked.
2174 Put_Line (Dep_File, S);
2178 -- If we are here, it means we had a timeout, so the
2179 -- dependency file may be incomplete. It is safer to
2180 -- delete it, otherwise the dependencies may be wrong.
2184 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2187 when Process_Died =>
2189 -- This is the normal outcome. Just close the file
2196 -- Something wrong happened. It is safer to delete the
2197 -- dependency file, otherwise the dependencies may be wrong.
2201 if Is_Open (Dep_File) then
2205 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2209 -- If we cannot spawn the compiler, then the dependencies are
2210 -- not updated. It is safer then to delete the dependency file,
2211 -- otherwise the dependencies may be wrong.
2213 when Invalid_Process =>
2214 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2220 -- For GCC compilers, make sure the language is always specified to
2221 -- to the GCC driver, in case the extension is not recognized by the
2222 -- GCC driver as a source of the language.
2224 if Compiler_Is_Gcc (Source.Language) then
2225 Add_Argument (Dash_x, Verbose_Mode);
2227 (Get_Name_String (Language_Names.Table (Source.Language)),
2231 Add_Argument (Dash_c, True);
2233 -- Add the compiling switches for this source found in
2234 -- package Compiler of the project file, if they exist.
2237 (Data, Compiler, Source.Language, Source.File_Name);
2239 -- Specify the source to be compiled
2241 Add_Argument (Get_Name_String (Source.Path_Name), True);
2243 -- If non static library project, compile with the PIC option if there
2244 -- is one (when there is no PIC option, function MLib.Tgt.PIC_Option
2245 -- returns an empty string, and Add_Argument with an empty string has
2248 if Data.Library and then Data.Library_Kind /= Static then
2249 Add_Argument (PIC_Option, True);
2252 -- Indicate the name of the object
2254 Add_Argument (Dash_o, True);
2255 Add_Argument (Get_Name_String (Source.Object_Name), True);
2257 -- When compiler is GCC, use the magic switch that creates
2258 -- the dependency file in the correct format.
2260 if Compiler_Is_Gcc (Source.Language) then
2262 ("-Wp,-MD," & Get_Name_String (Source.Dep_Name),
2266 -- Add the compiling switches for the language specified
2267 -- on the command line, if any.
2269 for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
2270 Add_Argument (Options (Source.Language).Table (J), True);
2273 -- Finally, add the imported directory switches for this
2274 -- project file (or, for gcc compilers, set up the CPATH env var
2277 Add_Search_Directories (Data, Source.Language);
2279 -- Set CPATH, if compiler is GCC
2281 if Compiler_Is_Gcc (Source.Language) then
2282 CPATH := Current_Include_Paths (Source.Language);
2285 -- And invoke the compiler
2288 (Name => Compiler_Names (Source.Language).all,
2289 Path => Compiler_Paths (Source.Language),
2293 (Compiler_Paths (Source.Language).all,
2294 Arguments (1 .. Last_Argument),
2297 -- Case of successful compilation
2301 -- Update the time stamp of the object file
2303 Source.Object_TS := File_Stamp (Source.Object_Name);
2305 -- Do some sanity checks
2307 if Source.Object_TS = Empty_Time_Stamp then
2308 Local_Errors := True;
2311 Get_Name_String (Source.Object_Name),
2312 " has not been created");
2314 elsif Source.Object_TS < Source.Source_TS then
2315 Local_Errors := True;
2318 Get_Name_String (Source.Object_Name),
2319 " has not been modified");
2322 -- Everything looks fine, update the Other_Sources table
2324 Project_Tree.Other_Sources.Table (Source_Id) := Source;
2327 -- Compilation failed
2330 Local_Errors := True;
2333 Get_Name_String (Source.Path_Name),
2338 --------------------------------
2339 -- Compile_Individual_Sources --
2340 --------------------------------
2342 procedure Compile_Individual_Sources is
2343 Data : Project_Data :=
2344 Project_Tree.Projects.Table (Main_Project);
2345 Source_Id : Other_Source_Id;
2346 Source : Other_Source;
2347 Source_Name : Name_Id;
2348 Project_Name : String := Get_Name_String (Data.Name);
2349 Dummy : Boolean := False;
2351 Ada_Is_A_Language : constant Boolean :=
2352 Data.Languages (Ada_Language_Index);
2356 To_Mixed (Project_Name);
2357 Compile_Only := True;
2359 Get_Imported_Directories (Main_Project, Data);
2360 Project_Tree.Projects.Table (Main_Project) := Data;
2362 -- Compilation will occur in the object directory
2364 Change_Dir (Get_Name_String (Data.Object_Directory));
2366 if not Data.Other_Sources_Present then
2367 if Ada_Is_A_Language then
2372 Main : constant String := Mains.Next_Main;
2374 exit when Main'Length = 0;
2375 Ada_Mains.Increment_Last;
2376 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2382 ("project ", Project_Name, " contains no source");
2390 Main : constant String := Mains.Next_Main;
2392 Name_Len := Main'Length;
2393 exit when Name_Len = 0;
2394 Name_Buffer (1 .. Name_Len) := Main;
2395 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2396 Source_Name := Name_Find;
2398 if not Sources_Compiled.Get (Source_Name) then
2399 Sources_Compiled.Set (Source_Name, True);
2400 Source_Id := Data.First_Other_Source;
2402 while Source_Id /= No_Other_Source loop
2404 Project_Tree.Other_Sources.Table (Source_Id);
2405 exit when Source.File_Name = Source_Name;
2406 Source_Id := Source.Next;
2409 if Source_Id = No_Other_Source then
2410 if Ada_Is_A_Language then
2411 Ada_Mains.Increment_Last;
2412 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2417 " is not a valid source of project ",
2422 Compile (Source_Id, Data, Dummy);
2429 if Ada_Mains.Last > 0 then
2431 -- Invoke gnatmake for all Ada sources
2434 Add_Argument (Dash_u, True);
2436 for Index in 1 .. Ada_Mains.Last loop
2437 Add_Argument (Ada_Mains.Table (Index), True);
2440 Compile_Link_With_Gnatmake (Mains_Specified => False);
2442 end Compile_Individual_Sources;
2444 --------------------------------
2445 -- Compile_Link_With_Gnatmake --
2446 --------------------------------
2448 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean) is
2449 Data : constant Project_Data :=
2450 Project_Tree.Projects.Table (Main_Project);
2454 -- Array Arguments may already contain some arguments, so we don't
2455 -- set Last_Argument to 0.
2457 -- Get the gnatmake to invoke
2459 Get_Compiler (Ada_Language_Index);
2461 -- Specify the project file
2463 Add_Argument (Dash_P, True);
2464 Add_Argument (Get_Name_String (Data.Path_Name), True);
2466 -- Add the -X switches, if any
2468 for Index in 1 .. X_Switches.Last loop
2469 Add_Argument (X_Switches.Table (Index), True);
2472 -- If Mains_Specified is True, find the mains in package Mains
2474 if Mains_Specified then
2479 Main : constant String := Mains.Next_Main;
2481 exit when Main'Length = 0;
2482 Add_Argument (Main, True);
2487 -- Specify output file name, if any was specified on the command line
2489 if Output_File_Name /= null then
2490 Add_Argument (Dash_o, True);
2491 Add_Argument (Output_File_Name, True);
2494 -- Transmit some switches to gnatmake
2498 if Compile_Only then
2499 Add_Argument (Dash_c, True);
2504 if Display_Compilation_Progress then
2505 Add_Argument (Dash_d, True);
2511 Add_Argument (Dash_k, True);
2516 if Force_Compilations then
2517 Add_Argument (Dash_f, True);
2522 if Verbose_Mode then
2523 Add_Argument (Dash_v, True);
2528 if Quiet_Output then
2529 Add_Argument (Dash_q, True);
2534 case Current_Verbosity is
2539 Add_Argument (Dash_vP1, True);
2542 Add_Argument (Dash_vP2, True);
2545 -- If there are compiling options for Ada, transmit them to gnatmake
2547 if Comp_Opts.Last (Options (Ada_Language_Index)) /= 0 then
2548 Add_Argument (Dash_cargs, True);
2550 for Arg in 1 .. Comp_Opts.Last (Options (Ada_Language_Index)) loop
2551 Add_Argument (Options (Ada_Language_Index).Table (Arg), True);
2555 if not Compile_Only then
2559 if Linker_Options.Last /= 0 then
2560 Add_Argument (Dash_largs, True);
2562 Add_Argument (Dash_largs, Verbose_Mode);
2567 Add_Archives (For_Gnatmake => True);
2569 -- If there are linking options from the command line,
2570 -- transmit them to gnatmake.
2572 for Arg in 1 .. Linker_Options.Last loop
2573 Add_Argument (Linker_Options.Table (Arg), True);
2577 -- And invoke gnatmake
2580 (Compiler_Names (Ada_Language_Index).all,
2581 Compiler_Paths (Ada_Language_Index));
2584 (Compiler_Paths (Ada_Language_Index).all,
2585 Arguments (1 .. Last_Argument),
2588 -- Report an error if call to gnatmake failed
2593 Compiler_Names (Ada_Language_Index).all,
2597 end Compile_Link_With_Gnatmake;
2599 ---------------------
2600 -- Compile_Sources --
2601 ---------------------
2603 procedure Compile_Sources is
2604 Data : Project_Data;
2605 Source_Id : Other_Source_Id;
2606 Source : Other_Source;
2608 Local_Errors : Boolean := False;
2609 -- Set to True when there is a compilation error. Used only when
2610 -- Keep_Going is True, to inhibit the building of the archive.
2612 Need_To_Compile : Boolean;
2613 -- Set to True when a source needs to be compiled/recompiled.
2615 Need_To_Rebuild_Archive : Boolean := Force_Compilations;
2616 -- True when the archive needs to be built/rebuilt unconditionally
2618 Total_Number_Of_Sources : Int := 0;
2620 Current_Source_Number : Int := 0;
2623 -- First, get the number of sources
2625 for Project in Project_Table.First ..
2626 Project_Table.Last (Project_Tree.Projects)
2628 Data := Project_Tree.Projects.Table (Project);
2630 if (not Data.Virtual) and then Data.Other_Sources_Present then
2631 Source_Id := Data.First_Other_Source;
2632 while Source_Id /= No_Other_Source loop
2633 Source := Project_Tree.Other_Sources.Table (Source_Id);
2634 Total_Number_Of_Sources := Total_Number_Of_Sources + 1;
2635 Source_Id := Source.Next;
2640 -- Loop through project files
2642 for Project in Project_Table.First ..
2643 Project_Table.Last (Project_Tree.Projects)
2645 Local_Errors := False;
2646 Data := Project_Tree.Projects.Table (Project);
2648 -- Nothing to do when no sources of language other than Ada
2650 if (not Data.Virtual) and then Data.Other_Sources_Present then
2652 -- If the imported directory switches are unknown, compute them
2654 if not Data.Include_Data_Set then
2655 Get_Imported_Directories (Project, Data);
2656 Data.Include_Data_Set := True;
2657 Project_Tree.Projects.Table (Project) := Data;
2660 Need_To_Rebuild_Archive := Force_Compilations;
2662 -- Compilation will occur in the object directory
2664 Change_Dir (Get_Name_String (Data.Object_Directory));
2666 Source_Id := Data.First_Other_Source;
2668 -- Process each source one by one
2670 while Source_Id /= No_Other_Source loop
2672 Source := Project_Tree.Other_Sources.Table (Source_Id);
2673 Current_Source_Number := Current_Source_Number + 1;
2674 Need_To_Compile := Force_Compilations;
2676 -- Check if compilation is needed
2678 if not Need_To_Compile then
2679 Check_Compilation_Needed (Source, Need_To_Compile);
2682 -- Proceed, if compilation is needed
2684 if Need_To_Compile then
2686 -- If a source is compiled/recompiled, of course the
2687 -- archive will need to be built/rebuilt.
2689 Need_To_Rebuild_Archive := True;
2690 Compile (Source_Id, Data, Local_Errors);
2693 if Display_Compilation_Progress then
2694 Write_Str ("completed ");
2695 Write_Int (Current_Source_Number);
2696 Write_Str (" out of ");
2697 Write_Int (Total_Number_Of_Sources);
2700 ((Current_Source_Number * 100) / Total_Number_Of_Sources);
2701 Write_Str ("%)...");
2705 -- Next source, if any
2707 Source_Id := Source.Next;
2710 if Need_To_Rebuild_Archive and then (not Data.Library) then
2711 Need_To_Rebuild_Global_Archive := True;
2714 -- If there was no compilation error and -c was not used,
2715 -- build / rebuild the archive if necessary.
2718 and then Data.Library
2719 and then not Data.Languages (Ada_Language_Index)
2720 and then not Compile_Only
2722 Build_Library (Project, Need_To_Rebuild_Archive);
2726 end Compile_Sources;
2732 procedure Copyright is
2734 -- Only output the Copyright notice once
2736 if not Copyright_Output then
2737 Copyright_Output := True;
2739 Write_Str ("GPRMAKE ");
2740 Write_Str (Gnatvsn.Gnat_Version_String);
2741 Write_Str (" Copyright 2004 Free Software Foundation, Inc.");
2746 ------------------------------------
2747 -- Create_Archive_Dependency_File --
2748 ------------------------------------
2750 procedure Create_Archive_Dependency_File
2752 First_Source : Other_Source_Id)
2754 Source_Id : Other_Source_Id := First_Source;
2755 Source : Other_Source;
2756 Dep_File : Ada.Text_IO.File_Type;
2760 -- Create the file in Append mode, to avoid automatic insertion of
2761 -- an end of line if file is empty.
2763 Create (Dep_File, Append_File, Name);
2765 while Source_Id /= No_Other_Source loop
2766 Source := Project_Tree.Other_Sources.Table (Source_Id);
2767 Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
2768 Put_Line (Dep_File, String (Source.Object_TS));
2769 Source_Id := Source.Next;
2776 if Is_Open (Dep_File) then
2779 end Create_Archive_Dependency_File;
2781 -------------------------------------------
2782 -- Create_Global_Archive_Dependency_File --
2783 -------------------------------------------
2785 procedure Create_Global_Archive_Dependency_File (Name : String) is
2786 Source_Id : Other_Source_Id;
2787 Source : Other_Source;
2788 Dep_File : Ada.Text_IO.File_Type;
2793 -- Create the file in Append mode, to avoid automatic insertion of
2794 -- an end of line if file is empty.
2796 Create (Dep_File, Append_File, Name);
2798 -- Get all the object files of non-Ada sources in non-library projects
2800 for Project in Project_Table.First ..
2801 Project_Table.Last (Project_Tree.Projects)
2803 if not Project_Tree.Projects.Table (Project).Library then
2805 Project_Tree.Projects.Table (Project).First_Other_Source;
2807 while Source_Id /= No_Other_Source loop
2808 Source := Project_Tree.Other_Sources.Table (Source_Id);
2810 -- Put only those object files that are in the global archive
2812 if Is_Included_In_Global_Archive
2813 (Source.Object_Name, Project)
2815 Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
2816 Put_Line (Dep_File, String (Source.Object_TS));
2819 Source_Id := Source.Next;
2828 if Is_Open (Dep_File) then
2831 end Create_Global_Archive_Dependency_File;
2833 ---------------------
2834 -- Display_Command --
2835 ---------------------
2837 procedure Display_Command
2839 Path : String_Access;
2840 CPATH : String_Access := null)
2843 -- Only display the command in Verbose Mode (-v) or when
2844 -- not in Quiet Output (no -q).
2846 if Verbose_Mode or (not Quiet_Output) then
2848 -- In Verbose Mode output the full path of the spawned process
2850 if Verbose_Mode then
2851 if CPATH /= null then
2852 Write_Str ("CPATH = ");
2853 Write_Line (CPATH.all);
2856 Write_Str (Path.all);
2862 -- Display only the arguments for which the display flag is set
2863 -- (in Verbose Mode, the display flag is set for all arguments)
2865 for Arg in 1 .. Last_Argument loop
2866 if Arguments_Displayed (Arg) then
2868 Write_Str (Arguments (Arg).all);
2874 end Display_Command;
2880 procedure Get_Compiler (For_Language : First_Language_Indexes) is
2881 Data : constant Project_Data :=
2882 Project_Tree.Projects.Table (Main_Project);
2884 Ide : constant Package_Id :=
2887 In_Packages => Data.Decl.Packages,
2888 In_Tree => Project_Tree);
2889 -- The id of the package IDE in the project file
2891 Compiler : constant Variable_Value :=
2893 (Name => Language_Names.Table (For_Language),
2895 Attribute_Or_Array_Name => Name_Compiler_Command,
2897 In_Tree => Project_Tree);
2898 -- The value of Compiler_Command ("language") in package IDE, if defined
2901 -- No need to do it again if the compiler is known for this language
2903 if Compiler_Names (For_Language) = null then
2905 -- If compiler command is not defined for this language in package
2906 -- IDE, use the default compiler for this language.
2908 if Compiler = Nil_Variable_Value then
2909 if For_Language in Default_Compiler_Names'Range then
2910 Compiler_Names (For_Language) :=
2911 Default_Compiler_Names (For_Language);
2915 ("unknow compiler name for language """,
2916 Get_Name_String (Language_Names.Table (For_Language)),
2921 Compiler_Names (For_Language) :=
2922 new String'(Get_Name_String (Compiler.Value));
2925 -- Check we have a GCC compiler (name ends with "gcc" or "g++")
2928 Comp_Name : constant String := Compiler_Names (For_Language).all;
2929 Last3 : String (1 .. 3);
2931 if Comp_Name'Length >= 3 then
2932 Last3 := Comp_Name (Comp_Name'Last - 2 .. Comp_Name'Last);
2933 Compiler_Is_Gcc (For_Language) :=
2934 (Last3 = "gcc") or (Last3 = "g++");
2936 Compiler_Is_Gcc (For_Language) := False;
2940 -- Locate the compiler on the path
2942 Compiler_Paths (For_Language) :=
2943 Locate_Exec_On_Path (Compiler_Names (For_Language).all);
2945 -- Fail if compiler cannot be found
2947 if Compiler_Paths (For_Language) = null then
2948 if For_Language = Ada_Language_Index then
2950 ("unable to locate """,
2951 Compiler_Names (For_Language).all,
2956 ("unable to locate " &
2957 Get_Name_String (Language_Names.Table (For_Language)),
2958 " compiler """, Compiler_Names (For_Language).all & '"');
2964 ------------------------------
2965 -- Get_Imported_Directories --
2966 ------------------------------
2968 procedure Get_Imported_Directories
2969 (Project : Project_Id;
2970 Data : in out Project_Data)
2972 Imported_Projects : Project_List := Data.Imported_Projects;
2974 Path_Length : Natural := 0;
2975 Position : Natural := 0;
2977 procedure Add (Source_Dirs : String_List_Id);
2978 -- Add a list of source directories
2980 procedure Recursive_Get_Dirs (Prj : Project_Id);
2981 -- Recursive procedure to get the source directories of this project
2982 -- file and of the project files it imports, in the correct order.
2988 procedure Add (Source_Dirs : String_List_Id) is
2989 Element_Id : String_List_Id := Source_Dirs;
2990 Element : String_Element;
2991 Add_Arg : Boolean := True;
2994 -- Add each source directory path name, preceded by "-I" to Arguments
2996 while Element_Id /= Nil_String loop
2997 Element := Project_Tree.String_Elements.Table (Element_Id);
2999 if Element.Value /= No_Name then
3000 Get_Name_String (Element.Value);
3002 if Name_Len > 0 then
3003 -- Remove a trailing directory separator: this may cause
3004 -- problems on Windows.
3007 and then Name_Buffer (Name_Len) = Directory_Separator
3009 Name_Len := Name_Len - 1;
3013 Arg : constant String :=
3014 "-I" & Name_Buffer (1 .. Name_Len);
3016 -- Check if directory is already in the list.
3017 -- If it is, no need to put it again.
3019 for Index in 1 .. Last_Argument loop
3020 if Arguments (Index).all = Arg then
3027 if Path_Length /= 0 then
3028 Path_Length := Path_Length + 1;
3031 Path_Length := Path_Length + Name_Len;
3033 Add_Argument (Arg, True);
3039 Element_Id := Element.Next;
3043 ------------------------
3044 -- Recursive_Get_Dirs --
3045 ------------------------
3047 procedure Recursive_Get_Dirs (Prj : Project_Id) is
3048 Data : Project_Data;
3049 Imported : Project_List;
3052 -- Nothing to do if project is undefined
3054 if Prj /= No_Project then
3055 Data := Project_Tree.Projects.Table (Prj);
3057 -- Nothing to do if project has already been processed
3059 if not Data.Seen then
3061 -- Mark the project as processed, to avoid multiple processing
3062 -- of the same project.
3064 Project_Tree.Projects.Table (Prj).Seen := True;
3066 -- Add the source directories of this project
3068 if not Data.Virtual then
3069 Add (Data.Source_Dirs);
3072 Recursive_Get_Dirs (Data.Extends);
3074 Imported := Data.Imported_Projects;
3076 -- Call itself for all imported projects, if any
3078 while Imported /= Empty_Project_List loop
3080 (Project_Tree.Project_Lists.Table
3081 (Imported).Project);
3083 Project_Tree.Project_Lists.Table (Imported).Next;
3087 end Recursive_Get_Dirs;
3089 -- Start of processing for Get_Imported_Directories
3092 -- First, mark all project as not processed
3094 for J in Project_Table.First ..
3095 Project_Table.Last (Project_Tree.Projects)
3097 Project_Tree.Projects.Table (J).Seen := False;
3104 -- Process this project individually, project data are already known
3106 Project_Tree.Projects.Table (Project).Seen := True;
3108 Add (Data.Source_Dirs);
3110 Recursive_Get_Dirs (Data.Extends);
3112 while Imported_Projects /= Empty_Project_List loop
3114 (Project_Tree.Project_Lists.Table
3115 (Imported_Projects).Project);
3116 Imported_Projects := Project_Tree.Project_Lists.Table
3117 (Imported_Projects).Next;
3120 Data.Imported_Directories_Switches :=
3121 new Argument_List'(Arguments (1 .. Last_Argument));
3123 -- Create the Include_Path, from the Arguments
3125 Data.Include_Path := new String (1 .. Path_Length);
3126 Data.Include_Path (1 .. Arguments (1)'Length - 2) :=
3127 Arguments (1)(Arguments (1)'First + 2 .. Arguments (1)'Last);
3128 Position := Arguments (1)'Length - 2;
3130 for Arg in 2 .. Last_Argument loop
3131 Position := Position + 1;
3132 Data.Include_Path (Position) := Path_Separator;
3134 (Position + 1 .. Position + Arguments (Arg)'Length - 2) :=
3135 Arguments (Arg)(Arguments (Arg)'First + 2 .. Arguments (Arg)'Last);
3136 Position := Position + Arguments (Arg)'Length - 2;
3140 end Get_Imported_Directories;
3146 procedure Gprmake is
3150 if Verbose_Mode then
3152 Write_Str ("Parsing Project File """);
3153 Write_Str (Project_File_Name.all);
3158 -- Parse and process project files for other languages (not for Ada)
3161 (Project => Main_Project,
3162 In_Tree => Project_Tree,
3163 Project_File_Name => Project_File_Name.all,
3164 Packages_To_Check => Packages_To_Check);
3166 -- Fail if parsing/processing was unsuccessful
3168 if Main_Project = No_Project then
3169 Osint.Fail ("""", Project_File_Name.all, """ processing failed");
3172 if Verbose_Mode then
3174 Write_Str ("Parsing of Project File """);
3175 Write_Str (Project_File_Name.all);
3176 Write_Str (""" is finished.");
3180 -- If -f was specified, we will certainly need to link (except when
3181 -- -u or -c were specified, of course).
3183 Need_To_Relink := Force_Compilations;
3185 if Unique_Compile then
3186 if Mains.Number_Of_Mains = 0 then
3188 ("No source specified to compile in 'unique compile' mode");
3190 Compile_Individual_Sources;
3191 Report_Total_Errors ("compilation");
3196 Data : constant Prj.Project_Data :=
3197 Project_Tree.Projects.Table (Main_Project);
3199 if Data.Library and then Mains.Number_Of_Mains /= 0 then
3201 ("Cannot specify mains on the command line " &
3202 "for a Library Project");
3205 -- First check for C++, to link libraries with g++,
3208 Check_For_C_Plus_Plus;
3210 -- Compile sources and build archives for library project,
3215 -- When Keep_Going is True, if we had some errors, fail now,
3216 -- reporting the number of compilation errors.
3217 -- Do not attempt to link.
3219 Report_Total_Errors ("compilation");
3221 -- If -c was not specified, link the executables,
3222 -- if there are any.
3224 if not Compile_Only and then not Data.Library then
3225 Build_Global_Archive;
3229 -- When Keep_Going is True, if we had some errors, fail, reporting
3230 -- the number of linking errors.
3232 Report_Total_Errors ("linking");
3241 procedure Initialize is
3243 -- Do some necessary package initializations
3248 Prj.Initialize (Project_Tree);
3251 -- Set Name_Ide and Name_Compiler_Command
3254 Add_Str_To_Name_Buffer ("ide");
3255 Name_Ide := Name_Find;
3258 Add_Str_To_Name_Buffer ("compiler_command");
3259 Name_Compiler_Command := Name_Find;
3261 -- Make sure the -X switch table is empty
3263 X_Switches.Set_Last (0);
3265 -- Get the command line arguments
3267 Scan_Args : for Next_Arg in 1 .. Argument_Count loop
3268 Scan_Arg (Argument (Next_Arg));
3271 -- Fail if command line ended with "-P"
3273 if Project_File_Name_Expected then
3274 Osint.Fail ("project file name missing after -P");
3276 -- Or if it ended with "-o"
3278 elsif Output_File_Name_Expected then
3279 Osint.Fail ("output file name missing after -o");
3282 -- If no project file was specified, display the usage and fail
3284 if Project_File_Name = null then
3286 Exit_Program (E_Success);
3289 -- To be able of finding libgnat.a in MLib.Tgt, we need to have the
3290 -- default search dirs established in Osint.
3292 Osint.Add_Default_Search_Dirs;
3295 -----------------------------------
3296 -- Is_Included_In_Global_Archive --
3297 -----------------------------------
3299 function Is_Included_In_Global_Archive
3300 (Object_Name : Name_Id;
3301 Project : Project_Id) return Boolean
3303 Data : Project_Data := Project_Tree.Projects.Table (Project);
3304 Source : Other_Source_Id;
3307 while Data.Extended_By /= No_Project loop
3308 Data := Project_Tree.Projects.Table (Data.Extended_By);
3310 Source := Data.First_Other_Source;
3311 while Source /= No_Other_Source loop
3312 if Project_Tree.Other_Sources.Table (Source).Object_Name =
3318 Project_Tree.Other_Sources.Table (Source).Next;
3324 end Is_Included_In_Global_Archive;
3326 ----------------------
3327 -- Link_Executables --
3328 ----------------------
3330 procedure Link_Executables is
3331 Data : constant Project_Data :=
3332 Project_Tree.Projects.Table (Main_Project);
3334 Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
3335 -- True if main sources were specified on the command line
3337 Object_Dir : constant String := Get_Name_String (Data.Object_Directory);
3338 -- Path of the object directory of the main project
3340 Source_Id : Other_Source_Id;
3341 Source : Other_Source;
3344 Linker_Name : String_Access;
3345 Linker_Path : String_Access;
3346 -- The linker name and path, when linking is not done by gnatlink
3348 Link_Done : Boolean := False;
3349 -- Set to True when the linker is invoked directly (not through
3350 -- gnatmake) to be able to report if mains were up to date at the end
3353 procedure Add_C_Plus_Plus_Link_For_Gnatmake;
3354 -- Add the --LINK= switch for gnatlink, depending on the C++ compiler
3356 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
3357 -- Check if there is an archive that is more recent than the executable
3358 -- to decide if we need to relink.
3360 procedure Choose_C_Plus_Plus_Link_Process;
3361 -- If the C++ compiler is not g++, create the correct script to link
3363 procedure Link_Foreign
3366 Source : Other_Source);
3367 -- Link a non-Ada main, when there is no Ada code
3369 ---------------------------------------
3370 -- Add_C_Plus_Plus_Link_For_Gnatmake --
3371 ---------------------------------------
3373 procedure Add_C_Plus_Plus_Link_For_Gnatmake is
3376 ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
3378 end Add_C_Plus_Plus_Link_For_Gnatmake;
3380 -----------------------
3381 -- Check_Time_Stamps --
3382 -----------------------
3384 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
3385 Prj_Data : Project_Data;
3388 for Prj in Project_Table.First ..
3389 Project_Table.Last (Project_Tree.Projects)
3391 Prj_Data := Project_Tree.Projects.Table (Prj);
3393 -- There is an archive only in project
3394 -- files with sources other than Ada
3397 if Data.Other_Sources_Present then
3399 Archive_Path : constant String :=
3401 (Prj_Data.Object_Directory) &
3402 Directory_Separator &
3404 Get_Name_String (Prj_Data.Name) &
3406 Archive_TS : Time_Stamp_Type;
3409 Add_Str_To_Name_Buffer
3411 Archive_TS := File_Stamp (Name_Find);
3413 -- If the archive is later than the
3414 -- executable, we need to relink.
3416 if Archive_TS /= Empty_Time_Stamp
3418 Exec_Time_Stamp < Archive_TS
3420 Need_To_Relink := True;
3422 if Verbose_Mode then
3424 Write_Str (Archive_Path);
3425 Write_Str (" has time stamp ");
3426 Write_Str ("later than ");
3427 Write_Line ("executable");
3435 end Check_Time_Stamps;
3437 -------------------------------------
3438 -- Choose_C_Plus_Plus_Link_Process --
3439 -------------------------------------
3441 procedure Choose_C_Plus_Plus_Link_Process is
3443 if Compiler_Names (C_Plus_Plus_Language_Index) = null then
3444 Get_Compiler (C_Plus_Plus_Language_Index);
3446 end Choose_C_Plus_Plus_Link_Process;
3452 procedure Link_Foreign
3455 Source : Other_Source)
3457 Executable_Name : constant String :=
3460 (Project => Main_Project,
3461 In_Tree => Project_Tree,
3464 Ada_Main => False));
3465 -- File name of the executable
3467 Executable_Path : constant String :=
3469 (Data.Exec_Directory) &
3470 Directory_Separator &
3472 -- Path name of the executable
3474 Exec_Time_Stamp : Time_Stamp_Type;
3477 -- Now, check if the executable is up to date. It is considered
3478 -- up to date if its time stamp is not earlier that the time stamp
3479 -- of any archive. Only do that if we don't know if we need to link.
3481 if not Need_To_Relink then
3483 -- Get the time stamp of the executable
3486 Add_Str_To_Name_Buffer (Executable_Path);
3487 Exec_Time_Stamp := File_Stamp (Name_Find);
3489 if Verbose_Mode then
3490 Write_Str (" Checking executable ");
3491 Write_Line (Executable_Name);
3494 -- If executable does not exist, we need to link
3496 if Exec_Time_Stamp = Empty_Time_Stamp then
3497 Need_To_Relink := True;
3499 if Verbose_Mode then
3500 Write_Line (" -> not found");
3503 -- Otherwise, get the time stamps of each archive. If one of
3504 -- them is found later than the executable, we need to relink.
3507 Check_Time_Stamps (Exec_Time_Stamp);
3510 -- If Need_To_Relink is False, we are done
3512 if Verbose_Mode and (not Need_To_Relink) then
3513 Write_Line (" -> up to date");
3519 if Need_To_Relink then
3524 -- Specify the executable path name
3526 Add_Argument (Dash_o, True);
3528 (Get_Name_String (Data.Exec_Directory) &
3529 Directory_Separator &
3532 (Project => Main_Project,
3533 In_Tree => Project_Tree,
3536 Ada_Main => False)),
3539 -- Specify the object file of the main source
3542 (Object_Dir & Directory_Separator &
3543 Get_Name_String (Source.Object_Name),
3546 -- Add all the archives, in a correct order
3548 Add_Archives (For_Gnatmake => False);
3550 -- Add the switches specified in package Linker of
3551 -- the main project.
3556 Language => Source.Language,
3557 File_Name => Main_Id);
3559 -- Add the switches specified in attribute
3560 -- Linker_Options of packages Linker.
3562 if Link_Options_Switches = null then
3563 Link_Options_Switches :=
3565 (Linker_Options_Switches (Main_Project, Project_Tree));
3568 Add_Arguments (Link_Options_Switches.all, True);
3570 -- Add the linking options specified on the
3573 for Arg in 1 .. Linker_Options.Last loop
3574 Add_Argument (Linker_Options.Table (Arg), True);
3577 -- If there are shared libraries and the run path
3578 -- option is supported, add the run path switch.
3580 if Lib_Path.Last > 0 then
3583 String (Lib_Path.Table (1 .. Lib_Path.Last)),
3587 -- And invoke the linker
3589 Display_Command (Linker_Name.all, Linker_Path);
3592 Arguments (1 .. Last_Argument),
3596 Report_Error ("could not link ", Main);
3601 -- Start of processing of Link_Executables
3604 -- If no mains specified, get mains from attribute Main, if it exists
3606 if not Mains_Specified then
3608 Element_Id : String_List_Id := Data.Mains;
3609 Element : String_Element;
3612 while Element_Id /= Nil_String loop
3613 Element := Project_Tree.String_Elements.Table
3616 if Element.Value /= No_Name then
3617 Mains.Add_Main (Get_Name_String (Element.Value));
3620 Element_Id := Element.Next;
3625 if Mains.Number_Of_Mains = 0 then
3627 -- If the attribute Main is an empty list or not specified,
3628 -- there is nothing to do.
3630 if Verbose_Mode then
3631 Write_Line ("No main to link");
3636 -- Check if -o was used for several mains
3638 if Output_File_Name /= null and then Mains.Number_Of_Mains > 1 then
3639 Osint.Fail ("cannot specify an executable name for several mains");
3642 -- Check how we are going to do the link
3644 if not Data.Other_Sources_Present then
3646 -- Only Ada sources in the main project, and even maybe not
3648 if not Data.Languages (Ada_Language_Index) then
3650 -- Fail if the main project has no source of any language
3654 Get_Name_String (Data.Name),
3655 """ has no sources, so no main can be linked");
3658 -- Only Ada sources in the main project, call gnatmake directly
3662 -- Choose correct linker if there is C++ code in other projects
3664 if C_Plus_Plus_Is_Used then
3665 Choose_C_Plus_Plus_Link_Process;
3666 Add_Argument (Dash_largs, Verbose_Mode);
3667 Add_C_Plus_Plus_Link_For_Gnatmake;
3668 Add_Argument (Dash_margs, Verbose_Mode);
3671 Compile_Link_With_Gnatmake (Mains_Specified);
3675 -- There are other language sources. First check if there are also
3678 if Data.Languages (Ada_Language_Index) then
3680 -- There is a mix of Ada and other language sources in the main
3681 -- project. Any main that is not a source of the other languages
3682 -- will be deemed to be an Ada main.
3684 -- Find the mains of the other languages and the Ada mains.
3687 Ada_Mains.Set_Last (0);
3688 Other_Mains.Set_Last (0);
3694 Main : constant String := Mains.Next_Main;
3698 exit when Main'Length = 0;
3700 -- Get the main file name
3703 Add_Str_To_Name_Buffer (Main);
3704 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3705 Main_Id := Name_Find;
3706 Source_Id := Data.First_Other_Source;
3708 -- Check if it is a source of a language other than Ada
3710 while Source_Id /= No_Other_Source loop
3712 Project_Tree.Other_Sources.Table (Source_Id);
3713 exit when Source.File_Name = Main_Id;
3714 Source_Id := Source.Next;
3717 -- If it is not, put it in the list of Ada mains
3719 if Source_Id = No_Other_Source then
3720 Ada_Mains.Increment_Last;
3721 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
3723 -- Otherwise, put it in the list of other mains
3726 Other_Mains.Increment_Last;
3727 Other_Mains.Table (Other_Mains.Last) := Source;
3732 -- If C++ is one of the other language, create the shell script
3735 if C_Plus_Plus_Is_Used then
3736 Choose_C_Plus_Plus_Link_Process;
3739 -- Call gnatmake with the necessary switches for each non-Ada
3740 -- main, if there are some.
3742 for Main in 1 .. Other_Mains.Last loop
3744 Source : constant Other_Source := Other_Mains.Table (Main);
3749 -- Add -o if -o was specified
3751 if Output_File_Name = null then
3752 Add_Argument (Dash_o, True);
3756 (Project => Main_Project,
3757 In_Tree => Project_Tree,
3758 Main => Other_Mains.Table (Main).File_Name,
3760 Ada_Main => False)),
3764 -- Call gnatmake with the -B switch
3766 Add_Argument (Dash_B, True);
3768 -- Add to the linking options the object file of the source
3770 Add_Argument (Dash_largs, Verbose_Mode);
3772 (Get_Name_String (Source.Object_Name), Verbose_Mode);
3774 -- If C++ is one of the language, add the --LINK switch
3775 -- to the linking switches.
3777 if C_Plus_Plus_Is_Used then
3778 Add_C_Plus_Plus_Link_For_Gnatmake;
3781 -- Add -margs so that the following switches are for
3784 Add_Argument (Dash_margs, Verbose_Mode);
3786 -- And link with gnatmake
3788 Compile_Link_With_Gnatmake (Mains_Specified => False);
3792 -- If there are also Ada mains, call gnatmake for all these mains
3794 if Ada_Mains.Last /= 0 then
3797 -- Put all the Ada mains as the first arguments
3799 for Main in 1 .. Ada_Mains.Last loop
3800 Add_Argument (Ada_Mains.Table (Main).all, True);
3803 -- If C++ is one of the languages, add the --LINK switch to
3804 -- the linking switches.
3806 if Data.Languages (C_Plus_Plus_Language_Index) then
3807 Add_Argument (Dash_largs, Verbose_Mode);
3808 Add_C_Plus_Plus_Link_For_Gnatmake;
3809 Add_Argument (Dash_margs, Verbose_Mode);
3812 -- And link with gnatmake
3814 Compile_Link_With_Gnatmake (Mains_Specified => False);
3818 -- No Ada source in main project
3820 -- First, get the linker to invoke
3822 if Data.Languages (C_Plus_Plus_Language_Index) then
3823 Get_Compiler (C_Plus_Plus_Language_Index);
3824 Linker_Name := Compiler_Names (C_Plus_Plus_Language_Index);
3825 Linker_Path := Compiler_Paths (C_Plus_Plus_Language_Index);
3828 Get_Compiler (C_Language_Index);
3829 Linker_Name := Compiler_Names (C_Language_Index);
3830 Linker_Path := Compiler_Paths (C_Language_Index);
3837 -- Get each main, check if it is a source of the main project,
3838 -- and if it is, invoke the linker.
3842 Main : constant String := Mains.Next_Main;
3845 exit when Main'Length = 0;
3847 -- Get the file name of the main
3850 Add_Str_To_Name_Buffer (Main);
3851 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3852 Main_Id := Name_Find;
3853 Source_Id := Data.First_Other_Source;
3855 -- Check if it is a source of the main project file
3857 while Source_Id /= No_Other_Source loop
3859 Project_Tree.Other_Sources.Table (Source_Id);
3860 exit when Source.File_Name = Main_Id;
3861 Source_Id := Source.Next;
3864 -- Report an error if it is not
3866 if Source_Id = No_Other_Source then
3868 (Main, "is not a source of project ",
3869 Get_Name_String (Data.Name));
3872 Link_Foreign (Main, Main_Id, Source);
3877 -- If no linking was done, report it, except in Quiet Output
3879 if (Verbose_Mode or (not Quiet_Output)) and (not Link_Done) then
3880 Osint.Write_Program_Name;
3882 if Mains.Number_Of_Mains = 1 then
3884 -- If there is only one executable, report its name too
3890 Main : constant String := Mains.Next_Main;
3894 Add_Str_To_Name_Buffer (Main);
3895 Main_Id := Name_Find;
3899 (Project => Main_Project,
3900 In_Tree => Project_Tree,
3903 Ada_Main => False)));
3904 Write_Line (""" up to date");
3908 Write_Line (": all executables up to date");
3913 end Link_Executables;
3919 procedure Report_Error
3925 -- If Keep_Going is True, output error message preceded by error header
3928 Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
3929 Write_Str (Error_Header);
3935 -- Otherwise just fail
3938 Osint.Fail (S1, S2, S3);
3942 -------------------------
3943 -- Report_Total_Errors --
3944 -------------------------
3946 procedure Report_Total_Errors (Kind : String) is
3948 if Total_Number_Of_Errors /= 0 then
3949 if Total_Number_Of_Errors = 1 then
3951 ("One ", Kind, " error");
3955 ("Total of" & Total_Number_Of_Errors'Img,
3956 ' ' & Kind & " errors");
3959 end Report_Total_Errors;
3965 procedure Scan_Arg (Arg : String) is
3967 pragma Assert (Arg'First = 1);
3969 if Arg'Length = 0 then
3973 -- If preceding switch was -P, a project file name need to be
3974 -- specified, not a switch.
3976 if Project_File_Name_Expected then
3977 if Arg (1) = '-' then
3978 Osint.Fail ("project file name missing after -P");
3980 Project_File_Name_Expected := False;
3981 Project_File_Name := new String'(Arg);
3984 -- If preceding switch was -o, an executable name need to be
3985 -- specified, not a switch.
3987 elsif Output_File_Name_Expected then
3988 if Arg (1) = '-' then
3989 Osint.Fail ("output file name missing after -o");
3991 Output_File_Name_Expected := False;
3992 Output_File_Name := new String'(Arg);
3995 -- Set the processor/language for the following switches
3997 -- -cargs: Ada compiler arguments
3999 elsif Arg = "-cargs" then
4000 Current_Language := Ada_Language_Index;
4001 Current_Processor := Compiler;
4003 elsif Arg'Length > 7 and then Arg (1 .. 7) = "-cargs:" then
4005 Add_Str_To_Name_Buffer (Arg (8 .. Arg'Last));
4006 To_Lower (Name_Buffer (1 .. Name_Len));
4009 Lang : constant Name_Id := Name_Find;
4011 Current_Language := Language_Indexes.Get (Lang);
4013 if Current_Language = No_Language_Index then
4014 Add_Language_Name (Lang);
4015 Current_Language := Last_Language_Index;
4018 Current_Processor := Compiler;
4021 elsif Arg = "-largs" then
4022 Current_Processor := Linker;
4026 elsif Arg = "-gargs" then
4027 Current_Processor := None;
4029 -- A special test is needed for the -o switch within a -largs since
4030 -- that is another way to specify the name of the final executable.
4032 elsif Current_Processor = Linker and then Arg = "-o" then
4034 ("switch -o not allowed within a -largs. Use -o directly.");
4036 -- If current processor is not gprmake directly, store the option in
4037 -- the appropriate table.
4039 elsif Current_Processor /= None then
4042 -- Switches start with '-'
4044 elsif Arg (1) = '-' then
4046 Compile_Only := True;
4048 -- Make sure that when a main is specified and switch -c is used,
4049 -- only the main(s) is/are compiled.
4051 if Mains.Number_Of_Mains > 0 then
4052 Unique_Compile := True;
4055 elsif Arg = "-d" then
4056 Display_Compilation_Progress := True;
4058 elsif Arg = "-f" then
4059 Force_Compilations := True;
4061 elsif Arg = "-h" then
4064 elsif Arg = "-k" then
4067 elsif Arg = "-o" then
4068 if Output_File_Name /= null then
4069 Osint.Fail ("cannot specify several -o switches");
4072 Output_File_Name_Expected := True;
4075 elsif Arg'Length >= 2 and then Arg (2) = 'P' then
4076 if Project_File_Name /= null then
4077 Osint.Fail ("cannot have several project files specified");
4079 elsif Arg'Length = 2 then
4080 Project_File_Name_Expected := True;
4083 Project_File_Name := new String'(Arg (3 .. Arg'Last));
4086 elsif Arg = "-q" then
4087 Quiet_Output := True;
4089 elsif Arg = "-u" then
4090 Unique_Compile := True;
4091 Compile_Only := True;
4093 elsif Arg = "-v" then
4094 Verbose_Mode := True;
4097 elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
4098 and then Arg (4) in '0' .. '2'
4102 Current_Verbosity := Prj.Default;
4104 Current_Verbosity := Prj.Medium;
4106 Current_Verbosity := Prj.High;
4111 elsif Arg'Length >= 3 and then Arg (2) = 'X'
4112 and then Is_External_Assignment (Arg)
4114 -- Is_External_Assignment has side effects when it returns True
4116 -- Record the -X switch, so that they can be passed to gnatmake,
4117 -- if gnatmake is called.
4119 X_Switches.Increment_Last;
4120 X_Switches.Table (X_Switches.Last) := new String'(Arg);
4123 Osint.Fail ("illegal option """, Arg, """");
4127 -- Not a switch: must be a main
4129 Mains.Add_Main (Arg);
4131 -- Make sure that when a main is specified and switch -c is used,
4132 -- only the main(s) is/are compiled.
4134 if Compile_Only then
4135 Unique_Compile := True;
4144 function Strip_CR_LF (Text : String) return String is
4145 To : String (1 .. Text'Length);
4146 Index_To : Natural := 0;
4149 for Index in Text'Range loop
4150 if (Text (Index) /= ASCII.CR) and then (Text (Index) /= ASCII.LF) then
4151 Index_To := Index_To + 1;
4152 To (Index_To) := Text (Index);
4156 return To (1 .. Index_To);
4165 if not Usage_Output then
4166 Usage_Output := True;
4169 Write_Str ("Usage: ");
4170 Osint.Write_Program_Name;
4171 Write_Str (" -P<project file> [opts] [name] {");
4173 for Lang in First_Language_Indexes loop
4174 Write_Str ("[-cargs:lang opts] ");
4177 Write_Str ("[-largs opts] [-gargs opts]}");
4180 Write_Str (" name is zero or more file names");
4186 Write_Str ("gprmake switches:");
4191 Write_Str (" -c Compile only");
4196 Write_Str (" -f Force recompilations");
4201 Write_Str (" -k Keep going after compilation errors");
4206 Write_Str (" -o name Choose an alternate executable name");
4211 Write_Str (" -Pproj Use GNAT Project File proj");
4216 Write_Str (" -q Be quiet/terse");
4222 (" -u Unique compilation. Only compile the given files");
4227 Write_Str (" -v Verbose output");
4232 Write_Str (" -vPx Specify verbosity when parsing Project Files");
4237 Write_Str (" -Xnm=val Specify an external reference for " &
4244 Write_Line (" -cargs opts opts are passed to the Ada compiler");
4246 -- Line for -cargs:lang
4248 Write_Line (" -cargs:<lang> opts");
4249 Write_Line (" opts are passed to the compiler " &
4250 "for language < lang > ");
4254 Write_Str (" -largs opts opts are passed to the linker");
4259 Write_Str (" -gargs opts opts directly interpreted by gprmake");
4267 Makeutl.Do_Fail := Report_Error'Access;