1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2004-2007, 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 ------------------------------------------------------------------------------
29 with Hostparm; use Hostparm;
30 with Makeutl; use Makeutl;
31 with MLib.Tgt; use MLib.Tgt;
32 with Namet; use Namet;
33 with Output; use Output;
35 with Osint; use Osint;
37 with Prj.Ext; use Prj.Ext;
39 with Prj.Util; use Prj.Util;
40 with Snames; use Snames;
42 with Types; use Types;
44 with Ada.Command_Line; use Ada.Command_Line;
45 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
46 with Ada.Text_IO; use Ada.Text_IO;
47 with Ada.Unchecked_Deallocation;
49 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
50 with GNAT.Dynamic_Tables;
51 with GNAT.Expect; use GNAT.Expect;
53 with GNAT.OS_Lib; use GNAT.OS_Lib;
54 with GNAT.Regpat; use GNAT.Regpat;
57 with System.Case_Util; use System.Case_Util;
59 package body Makegpr is
61 On_Windows : constant Boolean := Directory_Separator = '\';
62 -- True when on Windows. Used in Check_Compilation_Needed when processing
63 -- C/C++ dependency files for backslash handling.
65 Max_In_Archives : constant := 50;
66 -- The maximum number of arguments for a single invocation of the
67 -- Archive Indexer (ar).
69 No_Argument : aliased Argument_List := (1 .. 0 => null);
70 -- Null argument list representing case of no arguments
72 FD : Process_Descriptor;
73 -- The process descriptor used when invoking a non GNU compiler with -M
74 -- and getting the output with GNAT.Expect.
76 Line_Matcher : constant Pattern_Matcher := Compile ("^.*?\n", Single_Line);
77 -- Pattern for GNAT.Expect for the invocation of a non GNU compiler with -M
80 Name_Compiler_Command : Name_Id;
81 -- Names of package IDE and its attribute Compiler_Command.
82 -- Set up by Initialize.
84 Unique_Compile : Boolean := False;
85 -- True when switch -u is used on the command line
87 type Source_Index_Rec is record
90 Found : Boolean := False;
92 -- Used as Source_Indexes component to check if archive needs to be rebuilt
94 type Source_Index_Array is array (Positive range <>) of Source_Index_Rec;
95 type Source_Indexes_Ref is access Source_Index_Array;
97 procedure Free is new Ada.Unchecked_Deallocation
98 (Source_Index_Array, Source_Indexes_Ref);
100 Initial_Source_Index_Count : constant Positive := 20;
101 Source_Indexes : Source_Indexes_Ref :=
102 new Source_Index_Array (1 .. Initial_Source_Index_Count);
103 -- A list of the Other_Source_Ids of a project file, with an indication
104 -- that they have been found in the archive dependency file.
106 Last_Source : Natural := 0;
107 -- The index of the last valid component of Source_Indexes
109 Compiler_Names : array (First_Language_Indexes) of String_Access;
110 -- The names of the compilers to be used. Set up by Get_Compiler.
111 -- Used to display the commands spawned.
113 Gnatmake_String : constant String_Access := new String'("gnatmake");
114 GCC_String : constant String_Access := new String'("gcc");
115 G_Plus_Plus_String : constant String_Access := new String'("g++");
117 Default_Compiler_Names : constant array
118 (First_Language_Indexes range
119 Ada_Language_Index .. C_Plus_Plus_Language_Index)
121 (Ada_Language_Index => Gnatmake_String,
122 C_Language_Index => GCC_String,
123 C_Plus_Plus_Language_Index => G_Plus_Plus_String);
125 Compiler_Paths : array (First_Language_Indexes) of String_Access;
126 -- The path names of the compiler to be used. Set up by Get_Compiler.
127 -- Used to spawn compiling/linking processes.
129 Compiler_Is_Gcc : array (First_Language_Indexes) of Boolean;
130 -- An indication that a compiler is a GCC compiler, to be able to use
131 -- specific GCC switches.
133 Archive_Builder_Path : String_Access := null;
134 -- The path name of the archive builder (ar). To be used when spawning
137 Archive_Indexer_Path : String_Access := null;
138 -- The path name of the archive indexer (ranlib), if it exists
140 Copyright_Output : Boolean := False;
141 Usage_Output : Boolean := False;
142 -- Flags to avoid multiple displays of Copyright notice and of Usage
144 Output_File_Name : String_Access := null;
145 -- The name given after a switch -o
147 Output_File_Name_Expected : Boolean := False;
148 -- True when last switch was -o
150 Project_File_Name : String_Access := null;
151 -- The name of the project file specified with switch -P
153 Project_File_Name_Expected : Boolean := False;
154 -- True when last switch was -P
156 Naming_String : aliased String := "naming";
157 Builder_String : aliased String := "builder";
158 Compiler_String : aliased String := "compiler";
159 Binder_String : aliased String := "binder";
160 Linker_String : aliased String := "linker";
161 -- Name of packages to be checked when parsing/processing project files
163 List_Of_Packages : aliased String_List :=
164 (Naming_String 'Access,
165 Builder_String 'Access,
166 Compiler_String 'Access,
167 Binder_String 'Access,
168 Linker_String 'Access);
169 Packages_To_Check : constant String_List_Access := List_Of_Packages'Access;
170 -- List of the packages to be checked when parsing/processing project files
172 Project_Tree : constant Project_Tree_Ref := new Project_Tree_Data;
174 Main_Project : Project_Id;
175 -- The project id of the main project
177 type Processor is (None, Linker, Compiler);
178 Current_Processor : Processor := None;
179 -- This variable changes when switches -*args are used
181 Current_Language : Language_Index := Ada_Language_Index;
182 -- The compiler language to consider when Processor is Compiler
184 package Comp_Opts is new GNAT.Dynamic_Tables
185 (Table_Component_Type => String_Access,
186 Table_Index_Type => Integer,
187 Table_Low_Bound => 1,
189 Table_Increment => 100);
190 Options : array (First_Language_Indexes) of Comp_Opts.Instance;
191 -- Tables to store compiling options for the different compilers
193 package Linker_Options is new Table.Table
194 (Table_Component_Type => String_Access,
195 Table_Index_Type => Integer,
196 Table_Low_Bound => 1,
198 Table_Increment => 100,
199 Table_Name => "Makegpr.Linker_Options");
200 -- Table to store the linking options
202 package Library_Opts is new Table.Table
203 (Table_Component_Type => String_Access,
204 Table_Index_Type => Integer,
205 Table_Low_Bound => 1,
207 Table_Increment => 100,
208 Table_Name => "Makegpr.Library_Opts");
209 -- Table to store the linking options
211 package Ada_Mains is new Table.Table
212 (Table_Component_Type => String_Access,
213 Table_Index_Type => Integer,
214 Table_Low_Bound => 1,
216 Table_Increment => 100,
217 Table_Name => "Makegpr.Ada_Mains");
218 -- Table to store the Ada mains, either specified on the command line
219 -- or found in attribute Main of the main project file.
221 package Other_Mains is new Table.Table
222 (Table_Component_Type => Other_Source,
223 Table_Index_Type => Integer,
224 Table_Low_Bound => 1,
226 Table_Increment => 100,
227 Table_Name => "Makegpr.Other_Mains");
228 -- Table to store the mains of languages other than Ada, either specified
229 -- on the command line or found in attribute Main of the main project file.
231 package Sources_Compiled is new GNAT.HTable.Simple_HTable
232 (Header_Num => Header_Num,
235 Key => File_Name_Type,
239 package Saved_Switches is new Table.Table
240 (Table_Component_Type => String_Access,
241 Table_Index_Type => Integer,
242 Table_Low_Bound => 1,
244 Table_Increment => 100,
245 Table_Name => "Makegpr.Saved_Switches");
246 -- Table to store the switches to be passed to gnatmake
248 Initial_Argument_Count : constant Positive := 20;
249 type Boolean_Array is array (Positive range <>) of Boolean;
250 type Booleans is access Boolean_Array;
252 procedure Free is new Ada.Unchecked_Deallocation (Boolean_Array, Booleans);
254 Arguments : Argument_List_Access :=
255 new Argument_List (1 .. Initial_Argument_Count);
256 -- Used to store lists of arguments to be used when spawning a process
258 Arguments_Displayed : Booleans :=
259 new Boolean_Array (1 .. Initial_Argument_Count);
260 -- For each argument in Arguments, indicate if the argument should be
261 -- displayed when procedure Display_Command is called.
263 Last_Argument : Natural := 0;
264 -- Index of the last valid argument in Arguments
266 package Cache_Args is new Table.Table
267 (Table_Component_Type => String_Access,
268 Table_Index_Type => Integer,
269 Table_Low_Bound => 1,
270 Table_Initial => 200,
271 Table_Increment => 100,
272 Table_Name => "Makegpr.Cache_Args");
273 -- A table to cache arguments, to avoid multiple allocation of the same
274 -- strings. It is not possible to use a hash table, because String is
275 -- an unconstrained type.
277 -- Various switches used when spawning processes:
279 Dash_B_String : aliased String := "-B";
280 Dash_B : constant String_Access := Dash_B_String'Access;
281 Dash_c_String : aliased String := "-c";
282 Dash_c : constant String_Access := Dash_c_String'Access;
283 Dash_cargs_String : aliased String := "-cargs";
284 Dash_cargs : constant String_Access := Dash_cargs_String'Access;
285 Dash_d_String : aliased String := "-d";
286 Dash_d : constant String_Access := Dash_d_String'Access;
287 Dash_f_String : aliased String := "-f";
288 Dash_f : constant String_Access := Dash_f_String'Access;
289 Dash_k_String : aliased String := "-k";
290 Dash_k : constant String_Access := Dash_k_String'Access;
291 Dash_largs_String : aliased String := "-largs";
292 Dash_largs : constant String_Access := Dash_largs_String'Access;
293 Dash_M_String : aliased String := "-M";
294 Dash_M : constant String_Access := Dash_M_String'Access;
295 Dash_margs_String : aliased String := "-margs";
296 Dash_margs : constant String_Access := Dash_margs_String'Access;
297 Dash_o_String : aliased String := "-o";
298 Dash_o : constant String_Access := Dash_o_String'Access;
299 Dash_P_String : aliased String := "-P";
300 Dash_P : constant String_Access := Dash_P_String'Access;
301 Dash_q_String : aliased String := "-q";
302 Dash_q : constant String_Access := Dash_q_String'Access;
303 Dash_u_String : aliased String := "-u";
304 Dash_u : constant String_Access := Dash_u_String'Access;
305 Dash_v_String : aliased String := "-v";
306 Dash_v : constant String_Access := Dash_v_String'Access;
307 Dash_vP1_String : aliased String := "-vP1";
308 Dash_vP1 : constant String_Access := Dash_vP1_String'Access;
309 Dash_vP2_String : aliased String := "-vP2";
310 Dash_vP2 : constant String_Access := Dash_vP2_String'Access;
311 Dash_x_String : aliased String := "-x";
312 Dash_x : constant String_Access := Dash_x_String'Access;
313 r_String : aliased String := "r";
314 r : constant String_Access := r_String'Access;
316 CPATH : constant String := "CPATH";
317 -- The environment variable to set when compiler is a GCC compiler
318 -- to indicate the include directory path.
320 Current_Include_Paths : array (First_Language_Indexes) of String_Access;
321 -- A cache for the paths of included directories, to avoid setting
322 -- env var CPATH unnecessarily.
324 C_Plus_Plus_Is_Used : Boolean := False;
325 -- True when there are sources in C++
327 Link_Options_Switches : Argument_List_Access := null;
328 -- The link options coming from the attributes Linker'Linker_Options in
329 -- project files imported, directly or indirectly, by the main project.
331 Total_Number_Of_Errors : Natural := 0;
332 -- Used when Keep_Going is True (switch -k) to keep the total number
333 -- of compilation/linking errors, to report at the end of execution.
335 Need_To_Rebuild_Global_Archive : Boolean := False;
337 Error_Header : constant String := "*** ERROR: ";
338 -- The beginning of error message, when Keep_Going is True
340 Need_To_Relink : Boolean := False;
341 -- True when an executable of a language other than Ada need to be linked
343 Global_Archive_Exists : Boolean := False;
344 -- True if there is a non empty global archive, to prevent creation
347 Path_Option : String_Access;
348 -- The path option switch, when supported
350 Project_Of_Current_Object_Directory : Project_Id := No_Project;
351 -- The object directory of the project for the last compilation. Avoid
352 -- calling Change_Dir if the current working directory is already this
355 package Lib_Path is new Table.Table
356 (Table_Component_Type => Character,
357 Table_Index_Type => Integer,
358 Table_Low_Bound => 1,
359 Table_Initial => 200,
360 Table_Increment => 100,
361 Table_Name => "Makegpr.Lib_Path");
362 -- A table to compute the path to put in the path option switch, when it
365 procedure Add_Archives (For_Gnatmake : Boolean);
366 -- Add to Arguments the list of archives for linking an executable
368 procedure Add_Argument (Arg : String_Access; Display : Boolean);
369 procedure Add_Argument (Arg : String; Display : Boolean);
370 -- Add an argument to Arguments. Reallocate if necessary
372 procedure Add_Arguments (Args : Argument_List; Display : Boolean);
373 -- Add a list of arguments to Arguments. Reallocate if necessary
375 procedure Add_Option (Arg : String);
376 -- Add a switch for the Ada, C or C++ compiler, or for the linker.
377 -- The table where this option is stored depends on the values of
378 -- Current_Processor and Current_Language.
380 procedure Add_Search_Directories
381 (Data : Project_Data;
382 Language : First_Language_Indexes);
383 -- Either add to the Arguments the necessary -I switches needed to
384 -- compile, or, when compiler is gcc/g++, set up the C*INCLUDE_PATH
385 -- environment variable, if necessary.
387 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id);
388 -- Add a source id to Source_Indexes, with Found set to False
390 procedure Add_Switches
391 (Data : Project_Data;
393 Language : Language_Index;
394 File_Name : File_Name_Type);
395 -- Add to Arguments the switches, if any, for a source (attribute Switches)
396 -- or language (attribute Default_Switches), coming from package Compiler
397 -- or Linker (depending on Proc) of a specified project file.
399 procedure Build_Global_Archive;
400 -- Build the archive for the main project
402 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean);
403 -- Build the library for a library project. If Unconditionally is
404 -- False, first check if the library is up to date, and build it only
407 procedure Check (Option : String);
408 -- Check that a switch coming from a project file is not the concatenation
409 -- of several valid switch, for example "-g -v". If it is, issue a warning.
411 procedure Check_Archive_Builder;
412 -- Check if the archive builder (ar) is there
414 procedure Check_Compilation_Needed
415 (Source : Other_Source;
416 Need_To_Compile : out Boolean);
417 -- Check if a source of a language other than Ada needs to be compiled or
420 procedure Check_For_C_Plus_Plus;
421 -- Check if C++ is used in at least one project
424 (Source_Id : Other_Source_Id;
426 Local_Errors : in out Boolean);
427 -- Compile one non-Ada source
429 procedure Compile_Individual_Sources;
430 -- Compile the sources specified on the command line, when in
431 -- Unique_Compile mode.
433 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean);
434 -- Compile/Link with gnatmake when there are Ada sources in the main
435 -- project. Arguments may already contain options to be used by
436 -- gnatmake. Used for both Ada mains and mains of other languages.
437 -- When Compile_Only is True, do not use the linking options
439 procedure Compile_Sources;
440 -- Compile the sources of languages other than Ada, if necessary
443 -- Output the Copyright notice
445 procedure Create_Archive_Dependency_File
447 First_Source : Other_Source_Id);
448 -- Create the archive dependency file for a library project
450 procedure Create_Global_Archive_Dependency_File (Name : String);
451 -- Create the archive depenency file for the main project
453 procedure Display_Command
455 Path : String_Access;
456 CPATH : String_Access := null;
457 Ellipse : Boolean := False);
458 -- Display the command for a spawned process, if in Verbose_Mode or not in
459 -- Quiet_Output. In non verbose mode, when Ellipse is True, display "..."
460 -- in place of the first argument that has Display set to False.
462 procedure Get_Compiler (For_Language : First_Language_Indexes);
463 -- Find the compiler name and path name for a specified programming
464 -- language, if not already done. Results are in the corresponding elements
465 -- of arrays Compiler_Names and Compiler_Paths. Name of compiler is found
466 -- in package IDE of the main project, or defaulted. Fail if compiler
467 -- cannot be found on the path. For the Ada language, gnatmake, rather than
468 -- the Ada compiler is returned.
470 procedure Get_Imported_Directories
471 (Project : Project_Id;
472 Data : in out Project_Data);
473 -- Find the necessary switches -I to be used when compiling sources of
474 -- languages other than Ada, in a specified project file. Cache the result
475 -- in component Imported_Directories_Switches of the project data. For
476 -- gcc/g++ compilers, get the value of the C*_INCLUDE_PATH, instead.
478 procedure Initialize;
479 -- Do the necessary package initialization and process the command line
482 function Is_Included_In_Global_Archive
483 (Object_Name : File_Name_Type;
484 Project : Project_Id) return Boolean;
485 -- Return True if the object Object_Name is not overridden by a source
486 -- in a project extending project Project.
488 procedure Link_Executables;
491 procedure Report_Error (S1 : String; S2 : String := ""; S3 : String := "");
492 -- Report an error. If Keep_Going is False, just call Osint.Fail. If
493 -- Keep_Going is True, display the error and increase the total number of
496 procedure Report_Total_Errors (Kind : String);
497 -- If Total_Number_Of_Errors is not zero, report it, and fail
499 procedure Scan_Arg (Arg : String);
500 -- Process one command line argument
502 function Strip_CR_LF (Text : String) return String;
503 -- Remove characters ASCII.CR and ASCII.LF from a String
512 procedure Add_Archives (For_Gnatmake : Boolean) is
513 Last_Arg : constant Natural := Last_Argument;
514 -- The position of the last argument before adding the archives. Used to
515 -- reverse the order of the arguments added when processing the
518 procedure Recursive_Add_Archives (Project : Project_Id);
519 -- Recursive procedure to add the archive of a project file, if any,
520 -- then call itself for the project imported.
522 ----------------------------
523 -- Recursive_Add_Archives --
524 ----------------------------
526 procedure Recursive_Add_Archives (Project : Project_Id) is
528 Imported : Project_List;
531 procedure Add_Archive_Path;
532 -- For a library project or the main project, add the archive
533 -- path to the arguments.
535 ----------------------
536 -- Add_Archive_Path --
537 ----------------------
539 procedure Add_Archive_Path is
540 Increment : Positive;
541 Prev_Last : Positive;
546 -- If it is a library project file, nothing to do if gnatmake
547 -- will be invoked, because gnatmake will take care of it, even
548 -- if the library is not an Ada library.
550 if not For_Gnatmake then
551 if Data.Library_Kind = Static then
553 (Get_Name_String (Data.Display_Library_Dir) &
554 Directory_Separator &
555 "lib" & Get_Name_String (Data.Library_Name) &
560 -- As we first insert in the reverse order,
561 -- -L<dir> is put after -l<lib>
564 ("-l" & Get_Name_String (Data.Library_Name),
567 Get_Name_String (Data.Display_Library_Dir);
570 ("-L" & Name_Buffer (1 .. Name_Len),
573 -- If there is a run path option, prepend this directory
574 -- to the library path. It is probable that the order of
575 -- the directories in the path option is not important,
576 -- but just in case put the directories in the same order
579 if Path_Option /= null then
581 -- If it is not the first directory, make room at the
582 -- beginning of the table, including for a path
585 if Lib_Path.Last > 0 then
586 Increment := Name_Len + 1;
587 Prev_Last := Lib_Path.Last;
588 Lib_Path.Set_Last (Prev_Last + Increment);
590 for Index in reverse 1 .. Prev_Last loop
591 Lib_Path.Table (Index + Increment) :=
592 Lib_Path.Table (Index);
595 Lib_Path.Table (Increment) := Path_Separator;
598 -- If it is the first directory, just set
599 -- Last to the length of the directory.
601 Lib_Path.Set_Last (Name_Len);
604 -- Put the directory at the beginning of the
607 for Index in 1 .. Name_Len loop
608 Lib_Path.Table (Index) := Name_Buffer (Index);
614 -- For a non-library project, the only archive needed is the one
615 -- for the main project, if there is one.
617 elsif Project = Main_Project and then Global_Archive_Exists then
619 (Get_Name_String (Data.Display_Object_Dir) &
620 Directory_Separator &
621 "lib" & Get_Name_String (Data.Display_Name)
625 end Add_Archive_Path;
628 -- Nothing to do when there is no project specified
630 if Project /= No_Project then
631 Data := Project_Tree.Projects.Table (Project);
633 -- Nothing to do if the project has already been processed
635 if not Data.Seen then
637 -- Mark the project as processed, to avoid processing it again
639 Project_Tree.Projects.Table (Project).Seen := True;
641 Recursive_Add_Archives (Data.Extends);
643 Imported := Data.Imported_Projects;
645 -- Call itself recursively for all imported projects
647 while Imported /= Empty_Project_List loop
648 Prj := Project_Tree.Project_Lists.Table
651 if Prj /= No_Project then
652 while Project_Tree.Projects.Table
653 (Prj).Extended_By /= No_Project
655 Prj := Project_Tree.Projects.Table
659 Recursive_Add_Archives (Prj);
662 Imported := Project_Tree.Project_Lists.Table
666 -- If there is sources of language other than Ada in this
667 -- project, add the path of the archive to Arguments.
669 if Project = Main_Project
670 or else Data.Other_Sources_Present
676 end Recursive_Add_Archives;
678 -- Start of processing for Add_Archives
681 -- First, mark all projects as not processed
683 for Project in Project_Table.First ..
684 Project_Table.Last (Project_Tree.Projects)
686 Project_Tree.Projects.Table (Project).Seen := False;
689 -- Take care of the run path option
691 if Path_Option = null then
692 Path_Option := MLib.Linker_Library_Path_Option;
695 Lib_Path.Set_Last (0);
697 -- Add archives in the reverse order
699 Recursive_Add_Archives (Main_Project);
701 -- And reverse the order
706 Temp : String_Access;
709 First := Last_Arg + 1;
710 Last := Last_Argument;
711 while First < Last loop
712 Temp := Arguments (First);
713 Arguments (First) := Arguments (Last);
714 Arguments (Last) := Temp;
725 procedure Add_Argument (Arg : String_Access; Display : Boolean) is
727 -- Nothing to do if no argument is specified or if argument is empty
729 if Arg /= null or else Arg'Length = 0 then
731 -- Reallocate arrays if necessary
733 if Last_Argument = Arguments'Last then
735 New_Arguments : constant Argument_List_Access :=
737 (1 .. Last_Argument +
738 Initial_Argument_Count);
740 New_Arguments_Displayed : constant Booleans :=
742 (1 .. Last_Argument +
743 Initial_Argument_Count);
746 New_Arguments (Arguments'Range) := Arguments.all;
748 -- To avoid deallocating the strings, nullify all components
749 -- of Arguments before calling Free.
751 Arguments.all := (others => null);
754 Arguments := New_Arguments;
756 New_Arguments_Displayed (Arguments_Displayed'Range) :=
757 Arguments_Displayed.all;
758 Free (Arguments_Displayed);
759 Arguments_Displayed := New_Arguments_Displayed;
763 -- Add the argument and its display indication
765 Last_Argument := Last_Argument + 1;
766 Arguments (Last_Argument) := Arg;
767 Arguments_Displayed (Last_Argument) := Display;
771 procedure Add_Argument (Arg : String; Display : Boolean) is
772 Argument : String_Access := null;
775 -- Nothing to do if argument is empty
777 if Arg'Length > 0 then
779 -- Check if the argument is already in the Cache_Args table.
780 -- If it is already there, reuse the allocated value.
782 for Index in 1 .. Cache_Args.Last loop
783 if Cache_Args.Table (Index).all = Arg then
784 Argument := Cache_Args.Table (Index);
789 -- If the argument is not in the cache, create a new entry in the
792 if Argument = null then
793 Argument := new String'(Arg);
794 Cache_Args.Increment_Last;
795 Cache_Args.Table (Cache_Args.Last) := Argument;
798 -- And add the argument
800 Add_Argument (Argument, Display);
808 procedure Add_Arguments (Args : Argument_List; Display : Boolean) is
810 -- Reallocate the arrays, if necessary
812 if Last_Argument + Args'Length > Arguments'Last then
814 New_Arguments : constant Argument_List_Access :=
816 (1 .. Last_Argument + Args'Length +
817 Initial_Argument_Count);
819 New_Arguments_Displayed : constant Booleans :=
821 (1 .. Last_Argument +
823 Initial_Argument_Count);
826 New_Arguments (1 .. Last_Argument) :=
827 Arguments (1 .. Last_Argument);
829 -- To avoid deallocating the strings, nullify all components
830 -- of Arguments before calling Free.
832 Arguments.all := (others => null);
835 Arguments := New_Arguments;
836 New_Arguments_Displayed (1 .. Last_Argument) :=
837 Arguments_Displayed (1 .. Last_Argument);
838 Free (Arguments_Displayed);
839 Arguments_Displayed := New_Arguments_Displayed;
843 -- Add the new arguments and the display indications
845 Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
846 Arguments_Displayed (Last_Argument + 1 .. Last_Argument + Args'Length) :=
848 Last_Argument := Last_Argument + Args'Length;
855 procedure Add_Option (Arg : String) is
856 Option : constant String_Access := new String'(Arg);
859 case Current_Processor is
865 -- Add option to the linker table
867 Linker_Options.Increment_Last;
868 Linker_Options.Table (Linker_Options.Last) := Option;
872 -- Add option to the compiler option table, depending on the
873 -- value of Current_Language.
875 Comp_Opts.Increment_Last (Options (Current_Language));
876 Options (Current_Language).Table
877 (Comp_Opts.Last (Options (Current_Language))) := Option;
886 procedure Add_Source_Id (Project : Project_Id; Id : Other_Source_Id) is
888 -- Reallocate the array, if necessary
890 if Last_Source = Source_Indexes'Last then
892 New_Indexes : constant Source_Indexes_Ref :=
893 new Source_Index_Array
894 (1 .. Source_Indexes'Last +
895 Initial_Source_Index_Count);
897 New_Indexes (Source_Indexes'Range) := Source_Indexes.all;
898 Free (Source_Indexes);
899 Source_Indexes := New_Indexes;
903 Last_Source := Last_Source + 1;
904 Source_Indexes (Last_Source) := (Project, Id, False);
907 ----------------------------
908 -- Add_Search_Directories --
909 ----------------------------
911 procedure Add_Search_Directories
912 (Data : Project_Data;
913 Language : First_Language_Indexes)
916 -- If a GNU compiler is used, set the CPATH environment variable,
917 -- if it does not already has the correct value.
919 if Compiler_Is_Gcc (Language) then
920 if Current_Include_Paths (Language) /= Data.Include_Path then
921 Current_Include_Paths (Language) := Data.Include_Path;
922 Setenv (CPATH, Data.Include_Path.all);
926 Add_Arguments (Data.Imported_Directories_Switches.all, Verbose_Mode);
928 end Add_Search_Directories;
934 procedure Add_Switches
935 (Data : Project_Data;
937 Language : Language_Index;
938 File_Name : File_Name_Type)
940 Switches : Variable_Value;
941 -- The switches, if any, for the file/language
944 -- The id of the package where to look for the switches
946 Defaults : Array_Element_Id;
947 -- The Default_Switches associative array
949 Switches_Array : Array_Element_Id;
950 -- The Switches associative array
952 Element_Id : String_List_Id;
953 Element : String_Element;
956 -- First, choose the proper package
963 Pkg := Value_Of (Name_Linker, Data.Decl.Packages, Project_Tree);
966 Pkg := Value_Of (Name_Compiler, Data.Decl.Packages, Project_Tree);
969 if Pkg /= No_Package then
971 -- Get the Switches ("file name"), if they exist
973 Switches_Array := Prj.Util.Value_Of
974 (Name => Name_Switches,
975 In_Arrays => Project_Tree.Packages.Table
977 In_Tree => Project_Tree);
981 (Index => Name_Id (File_Name),
983 In_Array => Switches_Array,
984 In_Tree => Project_Tree);
986 -- Otherwise, get the Default_Switches ("language"), if they exist
988 if Switches = Nil_Variable_Value then
989 Defaults := Prj.Util.Value_Of
990 (Name => Name_Default_Switches,
991 In_Arrays => Project_Tree.Packages.Table
993 In_Tree => Project_Tree);
994 Switches := Prj.Util.Value_Of
995 (Index => Language_Names.Table (Language),
997 In_Array => Defaults,
998 In_Tree => Project_Tree);
1001 -- If there are switches, add them to Arguments
1003 if Switches /= Nil_Variable_Value then
1004 Element_Id := Switches.Values;
1005 while Element_Id /= Nil_String loop
1006 Element := Project_Tree.String_Elements.Table
1009 if Element.Value /= No_Name then
1010 Get_Name_String (Element.Value);
1012 if not Quiet_Output then
1014 -- When not in quiet output (no -q), check that the
1015 -- switch is not the concatenation of several valid
1016 -- switches, such as "-g -v". If it is, issue a warning.
1018 Check (Option => Name_Buffer (1 .. Name_Len));
1021 Add_Argument (Name_Buffer (1 .. Name_Len), True);
1024 Element_Id := Element.Next;
1030 --------------------------
1031 -- Build_Global_Archive --
1032 --------------------------
1034 procedure Build_Global_Archive is
1035 Data : Project_Data := Project_Tree.Projects.Table (Main_Project);
1036 Source_Id : Other_Source_Id;
1037 S_Id : Other_Source_Id;
1038 Source : Other_Source;
1041 Archive_Name : constant String :=
1043 & Get_Name_String (Data.Display_Name)
1046 -- The name of the archive file for this project
1048 Archive_Dep_Name : constant String :=
1050 & Get_Name_String (Data.Display_Name)
1052 -- The name of the archive dependency file for this project
1054 Need_To_Rebuild : Boolean := Need_To_Rebuild_Global_Archive;
1055 -- When True, archive will be rebuilt
1057 File : Prj.Util.Text_File;
1058 Object_Path : Path_Name_Type;
1059 Time_Stamp : Time_Stamp_Type;
1060 Saved_Last_Argument : Natural;
1061 First_Object : Natural;
1065 Check_Archive_Builder;
1067 if Project_Of_Current_Object_Directory /= Main_Project then
1068 Project_Of_Current_Object_Directory := Main_Project;
1069 Change_Dir (Get_Name_String (Data.Object_Directory));
1071 if Verbose_Mode then
1072 Write_Str ("Changing to object directory of """);
1073 Write_Name (Data.Display_Name);
1074 Write_Str (""": """);
1075 Write_Name (Data.Display_Object_Dir);
1080 if not Need_To_Rebuild then
1081 if Verbose_Mode then
1082 Write_Str (" Checking ");
1083 Write_Line (Archive_Name);
1086 -- If the archive does not exist, of course it needs to be built
1088 if not Is_Regular_File (Archive_Name) then
1089 Need_To_Rebuild := True;
1091 if Verbose_Mode then
1092 Write_Line (" -> archive does not exist");
1095 -- Archive does exist
1098 -- Check the archive dependency file
1100 Open (File, Archive_Dep_Name);
1102 -- If the archive dependency file does not exist, we need to
1103 -- rebuild the archive and to create its dependency file.
1105 if not Is_Valid (File) then
1106 Need_To_Rebuild := True;
1108 if Verbose_Mode then
1109 Write_Str (" -> archive dependency file ");
1110 Write_Str (Archive_Dep_Name);
1111 Write_Line (" does not exist");
1115 -- Put all sources of language other than Ada in Source_Indexes
1118 Local_Data : Project_Data;
1123 for Proj in Project_Table.First ..
1124 Project_Table.Last (Project_Tree.Projects)
1126 Local_Data := Project_Tree.Projects.Table (Proj);
1128 if not Local_Data.Library then
1129 Source_Id := Local_Data.First_Other_Source;
1130 while Source_Id /= No_Other_Source loop
1131 Add_Source_Id (Proj, Source_Id);
1132 Source_Id := Project_Tree.Other_Sources.Table
1139 -- Read the dependency file, line by line
1141 while not End_Of_File (File) loop
1142 Get_Line (File, Name_Buffer, Name_Len);
1144 -- First line is the path of the object file
1146 Object_Path := Name_Find;
1147 Source_Id := No_Other_Source;
1149 -- Check if this object file is for a source of this project
1151 for S in 1 .. Last_Source loop
1152 S_Id := Source_Indexes (S).Id;
1153 Source := Project_Tree.Other_Sources.Table (S_Id);
1155 if (not Source_Indexes (S).Found)
1156 and then Source.Object_Path = Object_Path
1158 -- We have found the object file: get the source data,
1159 -- and mark it as found.
1162 Source_Indexes (S).Found := True;
1167 -- If it is not for a source of this project, then the
1168 -- archive needs to be rebuilt.
1170 if Source_Id = No_Other_Source then
1171 Need_To_Rebuild := True;
1172 if Verbose_Mode then
1174 Write_Str (Get_Name_String (Object_Path));
1175 Write_Line (" is not an object of any project");
1181 -- The second line is the time stamp of the object file. If
1182 -- there is no next line, then the dependency file is
1183 -- truncated, and the archive need to be rebuilt.
1185 if End_Of_File (File) then
1186 Need_To_Rebuild := True;
1188 if Verbose_Mode then
1189 Write_Str (" -> archive dependency file ");
1190 Write_Line (" is truncated");
1196 Get_Line (File, Name_Buffer, Name_Len);
1198 -- If the line has the wrong number of characters, then
1199 -- the dependency file is incorrectly formatted, and the
1200 -- archive needs to be rebuilt.
1202 if Name_Len /= Time_Stamp_Length then
1203 Need_To_Rebuild := True;
1205 if Verbose_Mode then
1206 Write_Str (" -> archive dependency file ");
1207 Write_Line (" is incorrectly formatted (time stamp)");
1213 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1215 -- If the time stamp in the dependency file is different
1216 -- from the time stamp of the object file, then the archive
1217 -- needs to be rebuilt.
1219 if Time_Stamp /= Source.Object_TS then
1220 Need_To_Rebuild := True;
1222 if Verbose_Mode then
1223 Write_Str (" -> time stamp of ");
1224 Write_Str (Get_Name_String (Object_Path));
1225 Write_Str (" is incorrect in the archive");
1226 Write_Line (" dependency file");
1238 if not Need_To_Rebuild then
1239 if Verbose_Mode then
1240 Write_Line (" -> up to date");
1243 -- No need to create a global archive, if there is no object
1244 -- file to put into.
1246 Global_Archive_Exists := Last_Source /= 0;
1248 -- Archive needs to be rebuilt
1251 -- If archive already exists, first delete it
1253 -- Comment needed on why we discard result???
1255 if Is_Regular_File (Archive_Name) then
1256 Delete_File (Archive_Name, Discard);
1261 -- Start with the options found in MLib.Tgt (usually just "rc")
1263 Add_Arguments (Archive_Builder_Options.all, True);
1265 -- Followed by the archive name
1267 Add_Argument (Archive_Name, True);
1269 First_Object := Last_Argument;
1271 -- Followed by all the object files of the non library projects
1273 for Proj in Project_Table.First ..
1274 Project_Table.Last (Project_Tree.Projects)
1276 Data := Project_Tree.Projects.Table (Proj);
1278 if not Data.Library then
1279 Source_Id := Data.First_Other_Source;
1280 while Source_Id /= No_Other_Source loop
1282 Project_Tree.Other_Sources.Table (Source_Id);
1284 -- Only include object file name that have not been
1285 -- overriden in extending projects.
1287 if Is_Included_In_Global_Archive
1288 (Source.Object_Name, Proj)
1291 (Get_Name_String (Source.Object_Path),
1292 Verbose_Mode or (First_Object = Last_Argument));
1295 Source_Id := Source.Next;
1300 -- No need to create a global archive, if there is no object
1301 -- file to put into.
1303 Global_Archive_Exists := Last_Argument > First_Object;
1305 if Global_Archive_Exists then
1307 -- If the archive is built, then linking will need to occur
1310 Need_To_Relink := True;
1312 -- Spawn the archive builder (ar)
1314 Saved_Last_Argument := Last_Argument;
1315 Last_Argument := First_Object + Max_In_Archives;
1317 if Last_Argument > Saved_Last_Argument then
1318 Last_Argument := Saved_Last_Argument;
1323 Archive_Builder_Path,
1327 (Archive_Builder_Path.all,
1328 Arguments (1 .. Last_Argument),
1331 exit when not Success
1332 or else Last_Argument = Saved_Last_Argument;
1335 Arguments (3 .. Saved_Last_Argument - Last_Argument + 2) :=
1336 Arguments (Last_Argument + 1 .. Saved_Last_Argument);
1337 Saved_Last_Argument := Saved_Last_Argument - Last_Argument + 2;
1340 -- If the archive was built, run the archive indexer (ranlib)
1345 if Archive_Indexer_Path /= null then
1347 Add_Argument (Archive_Name, True);
1349 Display_Command (Archive_Indexer, Archive_Indexer_Path);
1352 (Archive_Indexer_Path.all, Arguments (1 .. 1), Success);
1356 -- Running ranlib failed, delete the dependency file,
1359 if Is_Regular_File (Archive_Dep_Name) then
1360 Delete_File (Archive_Dep_Name, Success);
1363 -- And report the error
1366 ("running" & Archive_Indexer & " for project """,
1367 Get_Name_String (Data.Display_Name),
1373 -- The archive was correctly built, create its dependency file
1375 Create_Global_Archive_Dependency_File (Archive_Dep_Name);
1377 -- Building the archive failed, delete dependency file if one
1381 if Is_Regular_File (Archive_Dep_Name) then
1382 Delete_File (Archive_Dep_Name, Success);
1385 -- And report the error
1388 ("building archive for project """,
1389 Get_Name_String (Data.Display_Name),
1394 end Build_Global_Archive;
1400 procedure Build_Library (Project : Project_Id; Unconditionally : Boolean) is
1401 Data : constant Project_Data :=
1402 Project_Tree.Projects.Table (Project);
1403 Source_Id : Other_Source_Id;
1404 Source : Other_Source;
1406 Archive_Name : constant String :=
1407 "lib" & Get_Name_String (Data.Display_Name)
1408 & '.' & Archive_Ext;
1409 -- The name of the archive file for this project
1411 Archive_Dep_Name : constant String :=
1412 "lib" & Get_Name_String (Data.Display_Name)
1414 -- The name of the archive dependency file for this project
1416 Need_To_Rebuild : Boolean := Unconditionally;
1417 -- When True, archive will be rebuilt
1419 File : Prj.Util.Text_File;
1421 Object_Name : File_Name_Type;
1422 Time_Stamp : Time_Stamp_Type;
1423 Driver_Name : Name_Id := No_Name;
1425 Lib_Opts : Argument_List_Access := No_Argument'Access;
1428 Check_Archive_Builder;
1430 -- If Unconditionally is False, check if the archive need to be built
1432 if not Need_To_Rebuild then
1433 if Verbose_Mode then
1434 Write_Str (" Checking ");
1435 Write_Line (Archive_Name);
1438 -- If the archive does not exist, of course it needs to be built
1440 if not Is_Regular_File (Archive_Name) then
1441 Need_To_Rebuild := True;
1443 if Verbose_Mode then
1444 Write_Line (" -> archive does not exist");
1447 -- Archive does exist
1450 -- Check the archive dependency file
1452 Open (File, Archive_Dep_Name);
1454 -- If the archive dependency file does not exist, we need to
1455 -- rebuild the archive and to create its dependency file.
1457 if not Is_Valid (File) then
1458 Need_To_Rebuild := True;
1460 if Verbose_Mode then
1461 Write_Str (" -> archive dependency file ");
1462 Write_Str (Archive_Dep_Name);
1463 Write_Line (" does not exist");
1467 -- Put all sources of language other than Ada in Source_Indexes
1471 Source_Id := Data.First_Other_Source;
1472 while Source_Id /= No_Other_Source loop
1473 Add_Source_Id (Project, Source_Id);
1475 Project_Tree.Other_Sources.Table (Source_Id).Next;
1478 -- Read the dependency file, line by line
1480 while not End_Of_File (File) loop
1481 Get_Line (File, Name_Buffer, Name_Len);
1483 -- First line is the name of an object file
1485 Object_Name := Name_Find;
1486 Source_Id := No_Other_Source;
1488 -- Check if this object file is for a source of this project
1490 for S in 1 .. Last_Source loop
1491 if (not Source_Indexes (S).Found)
1493 Project_Tree.Other_Sources.Table
1494 (Source_Indexes (S).Id).Object_Name = Object_Name
1496 -- We have found the object file: get the source
1497 -- data, and mark it as found.
1499 Source_Id := Source_Indexes (S).Id;
1500 Source := Project_Tree.Other_Sources.Table
1502 Source_Indexes (S).Found := True;
1507 -- If it is not for a source of this project, then the
1508 -- archive needs to be rebuilt.
1510 if Source_Id = No_Other_Source then
1511 Need_To_Rebuild := True;
1513 if Verbose_Mode then
1515 Write_Str (Get_Name_String (Object_Name));
1516 Write_Line (" is not an object of the project");
1522 -- The second line is the time stamp of the object file.
1523 -- If there is no next line, then the dependency file is
1524 -- truncated, and the archive need to be rebuilt.
1526 if End_Of_File (File) then
1527 Need_To_Rebuild := True;
1529 if Verbose_Mode then
1530 Write_Str (" -> archive dependency file ");
1531 Write_Line (" is truncated");
1537 Get_Line (File, Name_Buffer, Name_Len);
1539 -- If the line has the wrong number of character, then
1540 -- the dependency file is incorrectly formatted, and the
1541 -- archive needs to be rebuilt.
1543 if Name_Len /= Time_Stamp_Length then
1544 Need_To_Rebuild := True;
1546 if Verbose_Mode then
1547 Write_Str (" -> archive dependency file ");
1548 Write_Line (" is incorrectly formatted (time stamp)");
1554 Time_Stamp := Time_Stamp_Type (Name_Buffer (1 .. Name_Len));
1556 -- If the time stamp in the dependency file is different
1557 -- from the time stamp of the object file, then the archive
1558 -- needs to be rebuilt.
1560 if Time_Stamp /= Source.Object_TS then
1561 Need_To_Rebuild := True;
1563 if Verbose_Mode then
1564 Write_Str (" -> time stamp of ");
1565 Write_Str (Get_Name_String (Object_Name));
1566 Write_Str (" is incorrect in the archive");
1567 Write_Line (" dependency file");
1576 if not Need_To_Rebuild then
1578 -- Now, check if all object files of the project have been
1579 -- accounted for. If any of them is not in the dependency
1580 -- file, the archive needs to be rebuilt.
1582 for Index in 1 .. Last_Source loop
1583 if not Source_Indexes (Index).Found then
1584 Need_To_Rebuild := True;
1586 if Verbose_Mode then
1587 Source_Id := Source_Indexes (Index).Id;
1588 Source := Project_Tree.Other_Sources.Table
1591 Write_Str (Get_Name_String (Source.Object_Name));
1592 Write_Str (" is not in the archive ");
1593 Write_Line ("dependency file");
1601 if (not Need_To_Rebuild) and Verbose_Mode then
1602 Write_Line (" -> up to date");
1608 -- Build the library if necessary
1610 if Need_To_Rebuild then
1612 -- If a library is built, then linking will need to occur
1615 Need_To_Relink := True;
1619 -- If there are sources in Ada, then gnatmake will build the library,
1620 -- so nothing to do.
1622 if not Data.Languages (Ada_Language_Index) then
1624 -- Get all the object files of the project
1626 Source_Id := Data.First_Other_Source;
1627 while Source_Id /= No_Other_Source loop
1628 Source := Project_Tree.Other_Sources.Table (Source_Id);
1630 (Get_Name_String (Source.Object_Name), Verbose_Mode);
1631 Source_Id := Source.Next;
1634 -- If it is a library, it need to be built it the same way Ada
1635 -- libraries are built.
1637 if Data.Library_Kind = Static then
1639 (Ofiles => Arguments (1 .. Last_Argument),
1640 Afiles => No_Argument,
1641 Output_File => Get_Name_String (Data.Library_Name),
1642 Output_Dir => Get_Name_String (Data.Display_Library_Dir));
1645 -- Link with g++ if C++ is one of the languages, otherwise
1646 -- building the library may fail with unresolved symbols.
1648 if C_Plus_Plus_Is_Used then
1649 if Compiler_Names (C_Plus_Plus_Language_Index) = null then
1650 Get_Compiler (C_Plus_Plus_Language_Index);
1653 if Compiler_Is_Gcc (C_Plus_Plus_Language_Index) then
1655 Add_Str_To_Name_Buffer
1656 (Compiler_Names (C_Plus_Plus_Language_Index).all);
1657 Driver_Name := Name_Find;
1661 -- If Library_Options is specified, add these options
1664 Library_Options : constant Variable_Value :=
1666 (Name_Library_Options,
1667 Data.Decl.Attributes,
1671 if not Library_Options.Default then
1673 Current : String_List_Id;
1674 Element : String_Element;
1677 Current := Library_Options.Values;
1678 while Current /= Nil_String loop
1680 Project_Tree.String_Elements.Table (Current);
1681 Get_Name_String (Element.Value);
1683 if Name_Len /= 0 then
1684 Library_Opts.Increment_Last;
1685 Library_Opts.Table (Library_Opts.Last) :=
1686 new String'(Name_Buffer (1 .. Name_Len));
1689 Current := Element.Next;
1695 new Argument_List'(Argument_List
1696 (Library_Opts.Table (1 .. Library_Opts.Last)));
1699 MLib.Tgt.Build_Dynamic_Library
1700 (Ofiles => Arguments (1 .. Last_Argument),
1701 Foreign => Arguments (1 .. Last_Argument),
1702 Afiles => No_Argument,
1703 Options => No_Argument,
1704 Options_2 => Lib_Opts.all,
1705 Interfaces => No_Argument,
1706 Lib_Filename => Get_Name_String (Data.Library_Name),
1707 Lib_Dir => Get_Name_String (Data.Library_Dir),
1708 Symbol_Data => No_Symbols,
1709 Driver_Name => Driver_Name,
1711 Auto_Init => False);
1715 -- Create fake empty archive, so we can check its time stamp later
1718 Archive : Ada.Text_IO.File_Type;
1720 Create (Archive, Out_File, Archive_Name);
1724 Create_Archive_Dependency_File
1725 (Archive_Dep_Name, Data.First_Other_Source);
1733 procedure Check (Option : String) is
1734 First : Positive := Option'First;
1738 for Index in Option'First + 1 .. Option'Last - 1 loop
1739 if Option (Index) = ' ' and then Option (Index + 1) = '-' then
1740 Write_Str ("warning: switch """);
1742 Write_Str (""" is suspicious; consider using ");
1745 while Last <= Option'Last loop
1746 if Option (Last) = ' ' then
1747 if First /= Option'First then
1752 Write_Str (Option (First .. Last - 1));
1755 while Last <= Option'Last and then Option (Last) = ' ' loop
1762 if Last = Option'Last then
1763 if First /= Option'First then
1768 Write_Str (Option (First .. Last));
1776 Write_Line (" instead");
1782 ---------------------------
1783 -- Check_Archive_Builder --
1784 ---------------------------
1786 procedure Check_Archive_Builder is
1788 -- First, make sure that the archive builder (ar) is on the path
1790 if Archive_Builder_Path = null then
1791 Archive_Builder_Path := Locate_Exec_On_Path (Archive_Builder);
1793 if Archive_Builder_Path = null then
1795 ("unable to locate archive builder """,
1800 -- If there is an archive indexer (ranlib), try to locate it on the
1801 -- path. Don't fail if it is not found.
1803 if Archive_Indexer /= "" then
1804 Archive_Indexer_Path := Locate_Exec_On_Path (Archive_Indexer);
1807 end Check_Archive_Builder;
1809 ------------------------------
1810 -- Check_Compilation_Needed --
1811 ------------------------------
1813 procedure Check_Compilation_Needed
1814 (Source : Other_Source;
1815 Need_To_Compile : out Boolean)
1817 Source_Name : constant String := Get_Name_String (Source.File_Name);
1818 Source_Path : constant String := Get_Name_String (Source.Path_Name);
1819 Object_Name : constant String := Get_Name_String (Source.Object_Name);
1820 Dep_Name : constant String := Get_Name_String (Source.Dep_Name);
1821 C_Source_Path : String := Source_Path;
1823 Source_In_Dependencies : Boolean := False;
1824 -- Set True if source was found in dependency file of its object file
1826 Dep_File : Prj.Util.Text_File;
1830 Looping : Boolean := False;
1831 -- Set to True at the end of the first Big_Loop
1834 Canonical_Case_File_Name (C_Source_Path);
1836 -- Assume the worst, so that statement "return;" may be used if there
1839 Need_To_Compile := True;
1841 if Verbose_Mode then
1842 Write_Str (" Checking ");
1843 Write_Str (Source_Name);
1844 Write_Line (" ... ");
1847 -- If object file does not exist, of course source need to be compiled
1849 if Source.Object_TS = Empty_Time_Stamp then
1850 if Verbose_Mode then
1851 Write_Str (" -> object file ");
1852 Write_Str (Object_Name);
1853 Write_Line (" does not exist");
1859 -- If the object file has been created before the last modification
1860 -- of the source, the source need to be recompiled.
1862 if Source.Object_TS < Source.Source_TS then
1863 if Verbose_Mode then
1864 Write_Str (" -> object file ");
1865 Write_Str (Object_Name);
1866 Write_Line (" has time stamp earlier than source");
1872 -- If there is no dependency file, then the source needs to be
1873 -- recompiled and the dependency file need to be created.
1875 if Source.Dep_TS = Empty_Time_Stamp then
1876 if Verbose_Mode then
1877 Write_Str (" -> dependency file ");
1878 Write_Str (Dep_Name);
1879 Write_Line (" does not exist");
1885 -- The source needs to be recompiled if the source has been modified
1886 -- after the dependency file has been created.
1888 if Source.Dep_TS < Source.Source_TS then
1889 if Verbose_Mode then
1890 Write_Str (" -> dependency file ");
1891 Write_Str (Dep_Name);
1892 Write_Line (" has time stamp earlier than source");
1898 -- Look for all dependencies
1900 Open (Dep_File, Dep_Name);
1902 -- If dependency file cannot be open, we need to recompile the source
1904 if not Is_Valid (Dep_File) then
1905 if Verbose_Mode then
1906 Write_Str (" -> could not open dependency file ");
1907 Write_Line (Dep_Name);
1913 -- Loop Big_Loop is executed several times only when the dependency file
1914 -- contains several times
1915 -- <object file>: <source1> ...
1916 -- When there is only one of such occurence, Big_Loop is exited
1917 -- successfully at the beginning of the second loop.
1922 End_Of_File_Reached : Boolean := False;
1926 if End_Of_File (Dep_File) then
1927 End_Of_File_Reached := True;
1931 Get_Line (Dep_File, Name_Buffer, Name_Len);
1933 exit when Name_Len > 0 and then Name_Buffer (1) /= '#';
1936 -- If dependency file contains only empty lines or comments, then
1937 -- dependencies are unknown, and the source needs to be
1940 if End_Of_File_Reached then
1941 -- If we have reached the end of file after the first loop,
1942 -- there is nothing else to do.
1944 exit Big_Loop when Looping;
1946 if Verbose_Mode then
1947 Write_Str (" -> dependency file ");
1948 Write_Str (Dep_Name);
1949 Write_Line (" is empty");
1958 Finish := Index (Name_Buffer (1 .. Name_Len), ": ");
1960 -- First line must start with name of object file, followed by colon
1962 if Finish = 0 or else
1963 Name_Buffer (1 .. Finish - 1) /= Object_Name
1965 if Verbose_Mode then
1966 Write_Str (" -> dependency file ");
1967 Write_Str (Dep_Name);
1968 Write_Line (" has wrong format");
1975 Start := Finish + 2;
1977 -- Process each line
1981 Line : String := Name_Buffer (1 .. Name_Len);
1982 Last : Natural := Name_Len;
1987 -- Find the beginning of the next source path name
1989 while Start < Last and then Line (Start) = ' ' loop
1993 -- Go to next line when there is a continuation character
1994 -- \ at the end of the line.
1996 exit Name_Loop when Start = Last
1997 and then Line (Start) = '\';
1999 -- We should not be at the end of the line, without
2000 -- a continuation character \.
2002 if Start = Last then
2003 if Verbose_Mode then
2004 Write_Str (" -> dependency file ");
2005 Write_Str (Dep_Name);
2006 Write_Line (" has wrong format");
2013 -- Look for the end of the source path name
2016 while Finish < Last loop
2017 if Line (Finish) = '\' then
2019 -- On Windows, a '\' is part of the path name,
2020 -- except when it is followed by another '\' or by
2021 -- a space. On other platforms, when we are getting
2022 -- a '\' that is not the last character of the
2023 -- line, the next character is part of the path
2024 -- name, even if it is a space.
2027 and then Line (Finish + 1) /= '\'
2028 and then Line (Finish + 1) /= ' '
2030 Finish := Finish + 1;
2033 Line (Finish .. Last - 1) :=
2034 Line (Finish + 1 .. Last);
2039 -- A space that is not preceded by '\' indicates
2040 -- the end of the path name.
2042 exit when Line (Finish + 1) = ' ';
2044 Finish := Finish + 1;
2048 -- Check this source
2051 Src_Name : constant String :=
2054 Line (Start .. Finish),
2055 Resolve_Links => False,
2056 Case_Sensitive => False);
2057 Src_TS : Time_Stamp_Type;
2060 -- If it is original source, set
2061 -- Source_In_Dependencies.
2063 if Src_Name = C_Source_Path then
2064 Source_In_Dependencies := True;
2068 Add_Str_To_Name_Buffer (Src_Name);
2069 Src_TS := File_Stamp (File_Name_Type'(Name_Find));
2071 -- If the source does not exist, we need to recompile
2073 if Src_TS = Empty_Time_Stamp then
2074 if Verbose_Mode then
2075 Write_Str (" -> source ");
2076 Write_Str (Src_Name);
2077 Write_Line (" does not exist");
2083 -- If the source has been modified after the object
2084 -- file, we need to recompile.
2086 elsif Src_TS > Source.Object_TS then
2087 if Verbose_Mode then
2088 Write_Str (" -> source ");
2089 Write_Str (Src_Name);
2091 (" has time stamp later than object file");
2099 -- If the source path name ends the line, we are done
2101 exit Line_Loop when Finish = Last;
2103 -- Go get the next source on the line
2105 Start := Finish + 1;
2109 -- If we are here, we had a continuation character \ at the end
2110 -- of the line, so we continue with the next line.
2112 Get_Line (Dep_File, Name_Buffer, Name_Len);
2117 -- Set Looping at the end of the first loop
2123 -- If the original sources were not in the dependency file, then we
2124 -- need to recompile. It may mean that we are using a different source
2125 -- (different variant) for this object file.
2127 if not Source_In_Dependencies then
2128 if Verbose_Mode then
2129 Write_Str (" -> source ");
2130 Write_Str (Source_Path);
2131 Write_Line (" is not in the dependencies");
2137 -- If we are here, then everything is OK, no need to recompile
2139 if Verbose_Mode then
2140 Write_Line (" -> up to date");
2143 Need_To_Compile := False;
2144 end Check_Compilation_Needed;
2146 ---------------------------
2147 -- Check_For_C_Plus_Plus --
2148 ---------------------------
2150 procedure Check_For_C_Plus_Plus is
2152 C_Plus_Plus_Is_Used := False;
2154 for Project in Project_Table.First ..
2155 Project_Table.Last (Project_Tree.Projects)
2158 Project_Tree.Projects.Table (Project).Languages
2159 (C_Plus_Plus_Language_Index)
2161 C_Plus_Plus_Is_Used := True;
2165 end Check_For_C_Plus_Plus;
2172 (Source_Id : Other_Source_Id;
2173 Data : Project_Data;
2174 Local_Errors : in out Boolean)
2176 Source : Other_Source :=
2177 Project_Tree.Other_Sources.Table (Source_Id);
2179 CPATH : String_Access := null;
2182 -- If the compiler is not known yet, get its path name
2184 if Compiler_Names (Source.Language) = null then
2185 Get_Compiler (Source.Language);
2188 -- For non GCC compilers, get the dependency file, first calling the
2189 -- compiler with the switch -M.
2191 if not Compiler_Is_Gcc (Source.Language) then
2194 -- Add the source name, preceded by -M
2196 Add_Argument (Dash_M, True);
2197 Add_Argument (Get_Name_String (Source.Path_Name), True);
2199 -- Add the compiling switches for this source found in
2200 -- package Compiler of the project file, if they exist.
2203 (Data, Compiler, Source.Language, Source.File_Name);
2205 -- Add the compiling switches for the language specified
2206 -- on the command line, if any.
2209 J in 1 .. Comp_Opts.Last (Options (Source.Language))
2211 Add_Argument (Options (Source.Language).Table (J), True);
2214 -- Finally, add imported directory switches for this project file
2216 Add_Search_Directories (Data, Source.Language);
2218 -- And invoke the compiler using GNAT.Expect
2221 (Compiler_Names (Source.Language).all,
2222 Compiler_Paths (Source.Language));
2227 Compiler_Paths (Source.Language).all,
2228 Arguments (1 .. Last_Argument),
2230 Err_To_Out => True);
2233 Dep_File : Ada.Text_IO.File_Type;
2234 Result : Expect_Match;
2238 -- Create the dependency file
2240 Create (Dep_File, Out_File, Get_Name_String (Source.Dep_Name));
2243 Expect (FD, Result, Line_Matcher);
2245 exit when Result = Expect_Timeout;
2248 S : constant String := Strip_CR_LF (Expect_Out (FD));
2251 -- Each line of the output is put in the dependency
2252 -- file, including errors. If there are errors, the
2253 -- syntax of the dependency file will be incorrect and
2254 -- recompilation will occur automatically the next time
2255 -- the dependencies are checked.
2257 Put_Line (Dep_File, S);
2261 -- If we are here, it means we had a timeout, so the
2262 -- dependency file may be incomplete. It is safer to
2263 -- delete it, otherwise the dependencies may be wrong.
2267 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2270 when Process_Died =>
2272 -- This is the normal outcome. Just close the file
2279 -- Something wrong happened. It is safer to delete the
2280 -- dependency file, otherwise the dependencies may be wrong.
2284 if Is_Open (Dep_File) then
2288 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2292 -- If we cannot spawn the compiler, then the dependencies are
2293 -- not updated. It is safer then to delete the dependency file,
2294 -- otherwise the dependencies may be wrong.
2296 when Invalid_Process =>
2297 Delete_File (Get_Name_String (Source.Dep_Name), Success);
2303 -- For GCC compilers, make sure the language is always specified to
2304 -- to the GCC driver, in case the extension is not recognized by the
2305 -- GCC driver as a source of the language.
2307 if Compiler_Is_Gcc (Source.Language) then
2308 Add_Argument (Dash_x, Verbose_Mode);
2310 (Get_Name_String (Language_Names.Table (Source.Language)),
2314 Add_Argument (Dash_c, True);
2316 -- Add the compiling switches for this source found in package Compiler
2317 -- of the project file, if they exist.
2320 (Data, Compiler, Source.Language, Source.File_Name);
2322 -- Specify the source to be compiled
2324 Add_Argument (Get_Name_String (Source.Path_Name), True);
2326 -- If non static library project, compile with the PIC option if there
2327 -- is one (when there is no PIC option, MLib.Tgt.PIC_Option returns an
2328 -- empty string, and Add_Argument with an empty string has no effect).
2330 if Data.Library and then Data.Library_Kind /= Static then
2331 Add_Argument (PIC_Option, True);
2334 -- Indicate the name of the object
2336 Add_Argument (Dash_o, True);
2337 Add_Argument (Get_Name_String (Source.Object_Name), True);
2339 -- When compiler is GCC, use the magic switch that creates the
2340 -- dependency file in the correct format.
2342 if Compiler_Is_Gcc (Source.Language) then
2344 ("-Wp,-MD," & Get_Name_String (Source.Dep_Name),
2348 -- Add the compiling switches for the language specified on the command
2351 for J in 1 .. Comp_Opts.Last (Options (Source.Language)) loop
2352 Add_Argument (Options (Source.Language).Table (J), True);
2355 -- Finally, add the imported directory switches for this project file
2356 -- (or, for gcc compilers, set up the CPATH env var if needed).
2358 Add_Search_Directories (Data, Source.Language);
2360 -- Set CPATH, if compiler is GCC
2362 if Compiler_Is_Gcc (Source.Language) then
2363 CPATH := Current_Include_Paths (Source.Language);
2366 -- And invoke the compiler
2369 (Name => Compiler_Names (Source.Language).all,
2370 Path => Compiler_Paths (Source.Language),
2374 (Compiler_Paths (Source.Language).all,
2375 Arguments (1 .. Last_Argument),
2378 -- Case of successful compilation
2382 -- Update the time stamp of the object file
2384 Source.Object_TS := File_Stamp (Source.Object_Name);
2386 -- Do some sanity checks
2388 if Source.Object_TS = Empty_Time_Stamp then
2389 Local_Errors := True;
2392 Get_Name_String (Source.Object_Name),
2393 " has not been created");
2395 elsif Source.Object_TS < Source.Source_TS then
2396 Local_Errors := True;
2399 Get_Name_String (Source.Object_Name),
2400 " has not been modified");
2403 -- Everything looks fine, update the Other_Sources table
2405 Project_Tree.Other_Sources.Table (Source_Id) := Source;
2408 -- Compilation failed
2411 Local_Errors := True;
2414 Get_Name_String (Source.Path_Name),
2419 --------------------------------
2420 -- Compile_Individual_Sources --
2421 --------------------------------
2423 procedure Compile_Individual_Sources is
2424 Data : Project_Data :=
2425 Project_Tree.Projects.Table (Main_Project);
2426 Source_Id : Other_Source_Id;
2427 Source : Other_Source;
2428 Source_Name : File_Name_Type;
2429 Project_Name : String := Get_Name_String (Data.Name);
2430 Dummy : Boolean := False;
2432 Ada_Is_A_Language : constant Boolean :=
2433 Data.Languages (Ada_Language_Index);
2437 To_Mixed (Project_Name);
2438 Compile_Only := True;
2440 Get_Imported_Directories (Main_Project, Data);
2441 Project_Tree.Projects.Table (Main_Project) := Data;
2443 -- Compilation will occur in the object directory
2445 if Project_Of_Current_Object_Directory /= Main_Project then
2446 Project_Of_Current_Object_Directory := Main_Project;
2447 Change_Dir (Get_Name_String (Data.Object_Directory));
2449 if Verbose_Mode then
2450 Write_Str ("Changing to object directory of """);
2451 Write_Name (Data.Name);
2452 Write_Str (""": """);
2453 Write_Name (Data.Display_Object_Dir);
2458 if not Data.Other_Sources_Present then
2459 if Ada_Is_A_Language then
2464 Main : constant String := Mains.Next_Main;
2466 exit when Main'Length = 0;
2467 Ada_Mains.Increment_Last;
2468 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2473 Osint.Fail ("project ", Project_Name, " contains no source");
2481 Main : constant String := Mains.Next_Main;
2483 Name_Len := Main'Length;
2484 exit when Name_Len = 0;
2485 Name_Buffer (1 .. Name_Len) := Main;
2486 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
2487 Source_Name := Name_Find;
2489 if not Sources_Compiled.Get (Source_Name) then
2490 Sources_Compiled.Set (Source_Name, True);
2492 Source_Id := Data.First_Other_Source;
2493 while Source_Id /= No_Other_Source loop
2494 Source := Project_Tree.Other_Sources.Table (Source_Id);
2495 exit when Source.File_Name = Source_Name;
2496 Source_Id := Source.Next;
2499 if Source_Id = No_Other_Source then
2500 if Ada_Is_A_Language then
2501 Ada_Mains.Increment_Last;
2502 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
2507 " is not a valid source of project ",
2512 Compile (Source_Id, Data, Dummy);
2519 if Ada_Mains.Last > 0 then
2521 -- Invoke gnatmake for all Ada sources
2524 Add_Argument (Dash_u, True);
2526 for Index in 1 .. Ada_Mains.Last loop
2527 Add_Argument (Ada_Mains.Table (Index), True);
2530 Compile_Link_With_Gnatmake (Mains_Specified => False);
2532 end Compile_Individual_Sources;
2534 --------------------------------
2535 -- Compile_Link_With_Gnatmake --
2536 --------------------------------
2538 procedure Compile_Link_With_Gnatmake (Mains_Specified : Boolean) is
2539 Data : constant Project_Data :=
2540 Project_Tree.Projects.Table (Main_Project);
2544 -- Array Arguments may already contain some arguments, so we don't
2545 -- set Last_Argument to 0.
2547 -- Get the gnatmake to invoke
2549 Get_Compiler (Ada_Language_Index);
2551 -- Specify the project file
2553 Add_Argument (Dash_P, True);
2554 Add_Argument (Get_Name_String (Data.Display_Path_Name), True);
2556 -- Add the saved switches, if any
2558 for Index in 1 .. Saved_Switches.Last loop
2559 Add_Argument (Saved_Switches.Table (Index), True);
2562 -- If Mains_Specified is True, find the mains in package Mains
2564 if Mains_Specified then
2569 Main : constant String := Mains.Next_Main;
2571 exit when Main'Length = 0;
2572 Add_Argument (Main, True);
2577 -- Specify output file name, if any was specified on the command line
2579 if Output_File_Name /= null then
2580 Add_Argument (Dash_o, True);
2581 Add_Argument (Output_File_Name, True);
2584 -- Transmit some switches to gnatmake
2588 if Compile_Only then
2589 Add_Argument (Dash_c, True);
2594 if Display_Compilation_Progress then
2595 Add_Argument (Dash_d, True);
2601 Add_Argument (Dash_k, True);
2606 if Force_Compilations then
2607 Add_Argument (Dash_f, True);
2612 if Verbose_Mode then
2613 Add_Argument (Dash_v, True);
2618 if Quiet_Output then
2619 Add_Argument (Dash_q, True);
2624 case Current_Verbosity is
2629 Add_Argument (Dash_vP1, True);
2632 Add_Argument (Dash_vP2, True);
2635 -- If there are compiling options for Ada, transmit them to gnatmake
2637 if Comp_Opts.Last (Options (Ada_Language_Index)) /= 0 then
2638 Add_Argument (Dash_cargs, True);
2640 for Arg in 1 .. Comp_Opts.Last (Options (Ada_Language_Index)) loop
2641 Add_Argument (Options (Ada_Language_Index).Table (Arg), True);
2645 if not Compile_Only then
2649 if Linker_Options.Last /= 0 then
2650 Add_Argument (Dash_largs, True);
2652 Add_Argument (Dash_largs, Verbose_Mode);
2657 Add_Archives (For_Gnatmake => True);
2659 -- If there are linking options from the command line,
2660 -- transmit them to gnatmake.
2662 for Arg in 1 .. Linker_Options.Last loop
2663 Add_Argument (Linker_Options.Table (Arg), True);
2667 -- And invoke gnatmake
2670 (Compiler_Names (Ada_Language_Index).all,
2671 Compiler_Paths (Ada_Language_Index));
2674 (Compiler_Paths (Ada_Language_Index).all,
2675 Arguments (1 .. Last_Argument),
2678 -- Report an error if call to gnatmake failed
2683 Compiler_Names (Ada_Language_Index).all,
2686 end Compile_Link_With_Gnatmake;
2688 ---------------------
2689 -- Compile_Sources --
2690 ---------------------
2692 procedure Compile_Sources is
2693 Data : Project_Data;
2694 Source_Id : Other_Source_Id;
2695 Source : Other_Source;
2697 Local_Errors : Boolean := False;
2698 -- Set to True when there is a compilation error. Used only when
2699 -- Keep_Going is True, to inhibit the building of the archive.
2701 Need_To_Compile : Boolean;
2702 -- Set to True when a source needs to be compiled/recompiled
2704 Need_To_Rebuild_Archive : Boolean := Force_Compilations;
2705 -- True when the archive needs to be built/rebuilt unconditionally
2707 Total_Number_Of_Sources : Int := 0;
2709 Current_Source_Number : Int := 0;
2712 -- First, get the number of sources
2714 for Project in Project_Table.First ..
2715 Project_Table.Last (Project_Tree.Projects)
2717 Data := Project_Tree.Projects.Table (Project);
2719 if not Data.Virtual and then Data.Other_Sources_Present then
2720 Source_Id := Data.First_Other_Source;
2721 while Source_Id /= No_Other_Source loop
2722 Source := Project_Tree.Other_Sources.Table (Source_Id);
2723 Total_Number_Of_Sources := Total_Number_Of_Sources + 1;
2724 Source_Id := Source.Next;
2729 -- Loop through project files
2731 for Project in Project_Table.First ..
2732 Project_Table.Last (Project_Tree.Projects)
2734 Local_Errors := False;
2735 Data := Project_Tree.Projects.Table (Project);
2737 -- Nothing to do when no sources of language other than Ada
2739 if (not Data.Virtual) and then Data.Other_Sources_Present then
2741 -- If the imported directory switches are unknown, compute them
2743 if not Data.Include_Data_Set then
2744 Get_Imported_Directories (Project, Data);
2745 Data.Include_Data_Set := True;
2746 Project_Tree.Projects.Table (Project) := Data;
2749 Need_To_Rebuild_Archive := Force_Compilations;
2751 -- Compilation will occur in the object directory
2753 if Project_Of_Current_Object_Directory /= Project then
2754 Project_Of_Current_Object_Directory := Project;
2755 Change_Dir (Get_Name_String (Data.Object_Directory));
2757 if Verbose_Mode then
2758 Write_Str ("Changing to object directory of """);
2759 Write_Name (Data.Display_Name);
2760 Write_Str (""": """);
2761 Write_Name (Data.Display_Object_Dir);
2766 -- Process each source one by one
2768 Source_Id := Data.First_Other_Source;
2769 while Source_Id /= No_Other_Source loop
2770 Source := Project_Tree.Other_Sources.Table (Source_Id);
2771 Current_Source_Number := Current_Source_Number + 1;
2772 Need_To_Compile := Force_Compilations;
2774 -- Check if compilation is needed
2776 if not Need_To_Compile then
2777 Check_Compilation_Needed (Source, Need_To_Compile);
2780 -- Proceed, if compilation is needed
2782 if Need_To_Compile then
2784 -- If a source is compiled/recompiled, of course the
2785 -- archive will need to be built/rebuilt.
2787 Need_To_Rebuild_Archive := True;
2788 Compile (Source_Id, Data, Local_Errors);
2791 if Display_Compilation_Progress then
2792 Write_Str ("completed ");
2793 Write_Int (Current_Source_Number);
2794 Write_Str (" out of ");
2795 Write_Int (Total_Number_Of_Sources);
2798 ((Current_Source_Number * 100) / Total_Number_Of_Sources);
2799 Write_Str ("%)...");
2803 -- Next source, if any
2805 Source_Id := Source.Next;
2808 if Need_To_Rebuild_Archive and then (not Data.Library) then
2809 Need_To_Rebuild_Global_Archive := True;
2812 -- If there was no compilation error and -c was not used,
2813 -- build / rebuild the archive if necessary.
2816 and then Data.Library
2817 and then not Data.Languages (Ada_Language_Index)
2818 and then not Compile_Only
2820 Build_Library (Project, Need_To_Rebuild_Archive);
2824 end Compile_Sources;
2830 procedure Copyright is
2832 -- Only output the Copyright notice once
2834 if not Copyright_Output then
2835 Copyright_Output := True;
2837 Write_Str ("GPRMAKE ");
2838 Write_Str (Gnatvsn.Gnat_Version_String);
2839 Write_Str (" Copyright 2004-");
2840 Write_Str (Gnatvsn.Current_Year);
2841 Write_Str (" Free Software Foundation, Inc.");
2846 ------------------------------------
2847 -- Create_Archive_Dependency_File --
2848 ------------------------------------
2850 procedure Create_Archive_Dependency_File
2852 First_Source : Other_Source_Id)
2854 Source_Id : Other_Source_Id;
2855 Source : Other_Source;
2856 Dep_File : Ada.Text_IO.File_Type;
2859 -- Create the file in Append mode, to avoid automatic insertion of
2860 -- an end of line if file is empty.
2862 Create (Dep_File, Append_File, Name);
2864 Source_Id := First_Source;
2865 while Source_Id /= No_Other_Source loop
2866 Source := Project_Tree.Other_Sources.Table (Source_Id);
2867 Put_Line (Dep_File, Get_Name_String (Source.Object_Name));
2868 Put_Line (Dep_File, String (Source.Object_TS));
2869 Source_Id := Source.Next;
2876 if Is_Open (Dep_File) then
2879 end Create_Archive_Dependency_File;
2881 -------------------------------------------
2882 -- Create_Global_Archive_Dependency_File --
2883 -------------------------------------------
2885 procedure Create_Global_Archive_Dependency_File (Name : String) is
2886 Source_Id : Other_Source_Id;
2887 Source : Other_Source;
2888 Dep_File : Ada.Text_IO.File_Type;
2891 -- Create the file in Append mode, to avoid automatic insertion of
2892 -- an end of line if file is empty.
2894 Create (Dep_File, Append_File, Name);
2896 -- Get all the object files of non-Ada sources in non-library projects
2898 for Project in Project_Table.First ..
2899 Project_Table.Last (Project_Tree.Projects)
2901 if not Project_Tree.Projects.Table (Project).Library then
2903 Project_Tree.Projects.Table (Project).First_Other_Source;
2904 while Source_Id /= No_Other_Source loop
2905 Source := Project_Tree.Other_Sources.Table (Source_Id);
2907 -- Put only those object files that are in the global archive
2909 if Is_Included_In_Global_Archive
2910 (Source.Object_Name, Project)
2912 Put_Line (Dep_File, Get_Name_String (Source.Object_Path));
2913 Put_Line (Dep_File, String (Source.Object_TS));
2916 Source_Id := Source.Next;
2925 if Is_Open (Dep_File) then
2928 end Create_Global_Archive_Dependency_File;
2930 ---------------------
2931 -- Display_Command --
2932 ---------------------
2934 procedure Display_Command
2936 Path : String_Access;
2937 CPATH : String_Access := null;
2938 Ellipse : Boolean := False)
2940 Display_Ellipse : Boolean := Ellipse;
2943 -- Only display the command in Verbose Mode (-v) or when
2944 -- not in Quiet Output (no -q).
2946 if Verbose_Mode or (not Quiet_Output) then
2948 -- In Verbose Mode output the full path of the spawned process
2950 if Verbose_Mode then
2951 if CPATH /= null then
2952 Write_Str ("CPATH = ");
2953 Write_Line (CPATH.all);
2956 Write_Str (Path.all);
2962 -- Display only the arguments for which the display flag is set
2963 -- (in Verbose Mode, the display flag is set for all arguments)
2965 for Arg in 1 .. Last_Argument loop
2966 if Arguments_Displayed (Arg) then
2968 Write_Str (Arguments (Arg).all);
2970 elsif Display_Ellipse then
2972 Display_Ellipse := False;
2978 end Display_Command;
2984 procedure Get_Compiler (For_Language : First_Language_Indexes) is
2985 Data : constant Project_Data :=
2986 Project_Tree.Projects.Table (Main_Project);
2988 Ide : constant Package_Id :=
2991 In_Packages => Data.Decl.Packages,
2992 In_Tree => Project_Tree);
2993 -- The id of the package IDE in the project file
2995 Compiler : constant Variable_Value :=
2997 (Name => Language_Names.Table (For_Language),
2999 Attribute_Or_Array_Name => Name_Compiler_Command,
3001 In_Tree => Project_Tree);
3002 -- The value of Compiler_Command ("language") in package IDE, if defined
3005 -- No need to do it again if the compiler is known for this language
3007 if Compiler_Names (For_Language) = null then
3009 -- If compiler command is not defined for this language in package
3010 -- IDE, use the default compiler for this language.
3012 if Compiler = Nil_Variable_Value then
3013 if For_Language in Default_Compiler_Names'Range then
3014 Compiler_Names (For_Language) :=
3015 Default_Compiler_Names (For_Language);
3019 ("unknow compiler name for language """,
3020 Get_Name_String (Language_Names.Table (For_Language)),
3025 Compiler_Names (For_Language) :=
3026 new String'(Get_Name_String (Compiler.Value));
3029 -- Check we have a GCC compiler (name ends with "gcc" or "g++")
3032 Comp_Name : constant String := Compiler_Names (For_Language).all;
3033 Last3 : String (1 .. 3);
3035 if Comp_Name'Length >= 3 then
3036 Last3 := Comp_Name (Comp_Name'Last - 2 .. Comp_Name'Last);
3037 Compiler_Is_Gcc (For_Language) :=
3038 (Last3 = "gcc") or (Last3 = "g++");
3040 Compiler_Is_Gcc (For_Language) := False;
3044 -- Locate the compiler on the path
3046 Compiler_Paths (For_Language) :=
3047 Locate_Exec_On_Path (Compiler_Names (For_Language).all);
3049 -- Fail if compiler cannot be found
3051 if Compiler_Paths (For_Language) = null then
3052 if For_Language = Ada_Language_Index then
3054 ("unable to locate """,
3055 Compiler_Names (For_Language).all,
3060 ("unable to locate " &
3061 Get_Name_String (Language_Names.Table (For_Language)),
3062 " compiler """, Compiler_Names (For_Language).all & '"');
3068 ------------------------------
3069 -- Get_Imported_Directories --
3070 ------------------------------
3072 procedure Get_Imported_Directories
3073 (Project : Project_Id;
3074 Data : in out Project_Data)
3076 Imported_Projects : Project_List := Data.Imported_Projects;
3078 Path_Length : Natural := 0;
3079 Position : Natural := 0;
3081 procedure Add (Source_Dirs : String_List_Id);
3082 -- Add a list of source directories
3084 procedure Recursive_Get_Dirs (Prj : Project_Id);
3085 -- Recursive procedure to get the source directories of this project
3086 -- file and of the project files it imports, in the correct order.
3092 procedure Add (Source_Dirs : String_List_Id) is
3093 Element_Id : String_List_Id;
3094 Element : String_Element;
3095 Add_Arg : Boolean := True;
3098 -- Add each source directory path name, preceded by "-I" to Arguments
3100 Element_Id := Source_Dirs;
3101 while Element_Id /= Nil_String loop
3102 Element := Project_Tree.String_Elements.Table (Element_Id);
3104 if Element.Value /= No_Name then
3105 Get_Name_String (Element.Display_Value);
3107 if Name_Len > 0 then
3109 -- Remove a trailing directory separator: this may cause
3110 -- problems on Windows.
3113 and then Name_Buffer (Name_Len) = Directory_Separator
3115 Name_Len := Name_Len - 1;
3119 Arg : constant String :=
3120 "-I" & Name_Buffer (1 .. Name_Len);
3122 -- Check if directory is already in the list. If it is,
3123 -- no need to put it there again.
3127 for Index in 1 .. Last_Argument loop
3128 if Arguments (Index).all = Arg then
3135 if Path_Length /= 0 then
3136 Path_Length := Path_Length + 1;
3139 Path_Length := Path_Length + Name_Len;
3141 Add_Argument (Arg, True);
3147 Element_Id := Element.Next;
3151 ------------------------
3152 -- Recursive_Get_Dirs --
3153 ------------------------
3155 procedure Recursive_Get_Dirs (Prj : Project_Id) is
3156 Data : Project_Data;
3157 Imported : Project_List;
3160 -- Nothing to do if project is undefined
3162 if Prj /= No_Project then
3163 Data := Project_Tree.Projects.Table (Prj);
3165 -- Nothing to do if project has already been processed
3167 if not Data.Seen then
3169 -- Mark the project as processed, to avoid multiple processing
3170 -- of the same project.
3172 Project_Tree.Projects.Table (Prj).Seen := True;
3174 -- Add the source directories of this project
3176 if not Data.Virtual then
3177 Add (Data.Source_Dirs);
3180 Recursive_Get_Dirs (Data.Extends);
3182 -- Call itself for all imported projects, if any
3184 Imported := Data.Imported_Projects;
3185 while Imported /= Empty_Project_List loop
3187 (Project_Tree.Project_Lists.Table (Imported).Project);
3189 Project_Tree.Project_Lists.Table (Imported).Next;
3193 end Recursive_Get_Dirs;
3195 -- Start of processing for Get_Imported_Directories
3198 -- First, mark all project as not processed
3200 for J in Project_Table.First ..
3201 Project_Table.Last (Project_Tree.Projects)
3203 Project_Tree.Projects.Table (J).Seen := False;
3210 -- Process this project individually, project data are already known
3212 Project_Tree.Projects.Table (Project).Seen := True;
3214 Add (Data.Source_Dirs);
3216 Recursive_Get_Dirs (Data.Extends);
3218 while Imported_Projects /= Empty_Project_List loop
3220 (Project_Tree.Project_Lists.Table
3221 (Imported_Projects).Project);
3222 Imported_Projects := Project_Tree.Project_Lists.Table
3223 (Imported_Projects).Next;
3226 Data.Imported_Directories_Switches :=
3227 new Argument_List'(Arguments (1 .. Last_Argument));
3229 -- Create the Include_Path, from the Arguments
3231 Data.Include_Path := new String (1 .. Path_Length);
3232 Data.Include_Path (1 .. Arguments (1)'Length - 2) :=
3233 Arguments (1)(Arguments (1)'First + 2 .. Arguments (1)'Last);
3234 Position := Arguments (1)'Length - 2;
3236 for Arg in 2 .. Last_Argument loop
3237 Position := Position + 1;
3238 Data.Include_Path (Position) := Path_Separator;
3240 (Position + 1 .. Position + Arguments (Arg)'Length - 2) :=
3241 Arguments (Arg)(Arguments (Arg)'First + 2 .. Arguments (Arg)'Last);
3242 Position := Position + Arguments (Arg)'Length - 2;
3246 end Get_Imported_Directories;
3252 procedure Gprmake is
3256 if Verbose_Mode then
3258 Write_Str ("Parsing project file """);
3259 Write_Str (Project_File_Name.all);
3264 -- Parse and process project files for other languages (not for Ada)
3267 (Project => Main_Project,
3268 In_Tree => Project_Tree,
3269 Project_File_Name => Project_File_Name.all,
3270 Packages_To_Check => Packages_To_Check);
3272 -- Fail if parsing/processing was unsuccessful
3274 if Main_Project = No_Project then
3275 Osint.Fail ("""", Project_File_Name.all, """ processing failed");
3278 if Verbose_Mode then
3280 Write_Str ("Parsing of project file """);
3281 Write_Str (Project_File_Name.all);
3282 Write_Str (""" is finished.");
3286 -- If -f was specified, we will certainly need to link (except when
3287 -- -u or -c were specified, of course).
3289 Need_To_Relink := Force_Compilations;
3291 if Unique_Compile then
3292 if Mains.Number_Of_Mains = 0 then
3294 ("No source specified to compile in 'unique compile' mode");
3296 Compile_Individual_Sources;
3297 Report_Total_Errors ("compilation");
3302 Data : constant Prj.Project_Data :=
3303 Project_Tree.Projects.Table (Main_Project);
3305 if Data.Library and then Mains.Number_Of_Mains /= 0 then
3307 ("Cannot specify mains on the command line " &
3308 "for a Library Project");
3311 -- First check for C++, to link libraries with g++,
3314 Check_For_C_Plus_Plus;
3316 -- Compile sources and build archives for library project,
3321 -- When Keep_Going is True, if we had some errors, fail now,
3322 -- reporting the number of compilation errors.
3323 -- Do not attempt to link.
3325 Report_Total_Errors ("compilation");
3327 -- If -c was not specified, link the executables,
3328 -- if there are any.
3331 and then not Data.Library
3332 and then Data.Object_Directory /= No_Path
3334 Build_Global_Archive;
3338 -- When Keep_Going is True, if we had some errors, fail, reporting
3339 -- the number of linking errors.
3341 Report_Total_Errors ("linking");
3350 procedure Initialize is
3352 -- Do some necessary package initializations
3357 Prj.Initialize (Project_Tree);
3360 -- Add the directory where gprmake is invoked in front of the path,
3361 -- if gprmake is invoked from a bin directory or with directory
3362 -- information. information. Only do this if the platform is not VMS,
3363 -- where the notion of path does not really exist.
3365 -- Below code shares nasty code duplication with make.adb code???
3369 Prefix : constant String := Executable_Prefix_Path;
3370 Command : constant String := Command_Name;
3373 if Prefix'Length > 0 then
3375 PATH : constant String :=
3376 Prefix & Directory_Separator & "bin" &
3378 Getenv ("PATH").all;
3380 Setenv ("PATH", PATH);
3384 for Index in reverse Command'Range loop
3385 if Command (Index) = Directory_Separator then
3387 Absolute_Dir : constant String :=
3389 (Command (Command'First .. Index));
3390 PATH : constant String :=
3393 Getenv ("PATH").all;
3395 Setenv ("PATH", PATH);
3405 -- Set Name_Ide and Name_Compiler_Command
3408 Add_Str_To_Name_Buffer ("ide");
3409 Name_Ide := Name_Find;
3412 Add_Str_To_Name_Buffer ("compiler_command");
3413 Name_Compiler_Command := Name_Find;
3415 -- Make sure the Saved_Switches table is empty
3417 Saved_Switches.Set_Last (0);
3419 -- Get the command line arguments
3421 Scan_Args : for Next_Arg in 1 .. Argument_Count loop
3422 Scan_Arg (Argument (Next_Arg));
3425 -- Fail if command line ended with "-P"
3427 if Project_File_Name_Expected then
3428 Osint.Fail ("project file name missing after -P");
3430 -- Or if it ended with "-o"
3432 elsif Output_File_Name_Expected then
3433 Osint.Fail ("output file name missing after -o");
3436 -- If no project file was specified, display the usage and fail
3438 if Project_File_Name = null then
3440 Exit_Program (E_Success);
3443 -- To be able of finding libgnat.a in MLib.Tgt, we need to have the
3444 -- default search dirs established in Osint.
3446 Osint.Add_Default_Search_Dirs;
3449 -----------------------------------
3450 -- Is_Included_In_Global_Archive --
3451 -----------------------------------
3453 function Is_Included_In_Global_Archive
3454 (Object_Name : File_Name_Type;
3455 Project : Project_Id) return Boolean
3457 Data : Project_Data := Project_Tree.Projects.Table (Project);
3458 Source : Other_Source_Id;
3461 while Data.Extended_By /= No_Project loop
3462 Data := Project_Tree.Projects.Table (Data.Extended_By);
3464 Source := Data.First_Other_Source;
3465 while Source /= No_Other_Source loop
3466 if Project_Tree.Other_Sources.Table (Source).Object_Name =
3472 Project_Tree.Other_Sources.Table (Source).Next;
3478 end Is_Included_In_Global_Archive;
3480 ----------------------
3481 -- Link_Executables --
3482 ----------------------
3484 procedure Link_Executables is
3485 Data : constant Project_Data :=
3486 Project_Tree.Projects.Table (Main_Project);
3488 Mains_Specified : constant Boolean := Mains.Number_Of_Mains /= 0;
3489 -- True if main sources were specified on the command line
3491 Object_Dir : constant String :=
3492 Get_Name_String (Data.Display_Object_Dir);
3493 -- Path of the object directory of the main project
3495 Source_Id : Other_Source_Id;
3496 Source : Other_Source;
3499 Linker_Name : String_Access;
3500 Linker_Path : String_Access;
3501 -- The linker name and path, when linking is not done by gnatlink
3503 Link_Done : Boolean := False;
3504 -- Set to True when the linker is invoked directly (not through
3505 -- gnatmake) to be able to report if mains were up to date at the end
3508 procedure Add_C_Plus_Plus_Link_For_Gnatmake;
3509 -- Add the --LINK= switch for gnatlink, depending on the C++ compiler
3511 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type);
3512 -- Check if there is an archive that is more recent than the executable
3513 -- to decide if we need to relink.
3515 procedure Choose_C_Plus_Plus_Link_Process;
3516 -- If the C++ compiler is not g++, create the correct script to link
3518 procedure Link_Foreign
3520 Main_Id : File_Name_Type;
3521 Source : Other_Source);
3522 -- Link a non-Ada main, when there is no Ada code
3524 ---------------------------------------
3525 -- Add_C_Plus_Plus_Link_For_Gnatmake --
3526 ---------------------------------------
3528 procedure Add_C_Plus_Plus_Link_For_Gnatmake is
3531 ("--LINK=" & Compiler_Names (C_Plus_Plus_Language_Index).all,
3533 end Add_C_Plus_Plus_Link_For_Gnatmake;
3535 -----------------------
3536 -- Check_Time_Stamps --
3537 -----------------------
3539 procedure Check_Time_Stamps (Exec_Time_Stamp : Time_Stamp_Type) is
3540 Prj_Data : Project_Data;
3543 for Prj in Project_Table.First ..
3544 Project_Table.Last (Project_Tree.Projects)
3546 Prj_Data := Project_Tree.Projects.Table (Prj);
3548 -- There is an archive only in project
3549 -- files with sources other than Ada
3552 if Data.Other_Sources_Present then
3554 Archive_Path : constant String := Get_Name_String
3555 (Prj_Data.Display_Object_Dir) & Directory_Separator
3556 & "lib" & Get_Name_String (Prj_Data.Display_Name)
3557 & '.' & Archive_Ext;
3558 Archive_TS : Time_Stamp_Type;
3561 Add_Str_To_Name_Buffer (Archive_Path);
3562 Archive_TS := File_Stamp (File_Name_Type'(Name_Find));
3564 -- If the archive is later than the
3565 -- executable, we need to relink.
3567 if Archive_TS /= Empty_Time_Stamp
3569 Exec_Time_Stamp < Archive_TS
3571 Need_To_Relink := True;
3573 if Verbose_Mode then
3575 Write_Str (Archive_Path);
3576 Write_Str (" has time stamp ");
3577 Write_Str ("later than ");
3578 Write_Line ("executable");
3586 end Check_Time_Stamps;
3588 -------------------------------------
3589 -- Choose_C_Plus_Plus_Link_Process --
3590 -------------------------------------
3592 procedure Choose_C_Plus_Plus_Link_Process is
3594 if Compiler_Names (C_Plus_Plus_Language_Index) = null then
3595 Get_Compiler (C_Plus_Plus_Language_Index);
3597 end Choose_C_Plus_Plus_Link_Process;
3603 procedure Link_Foreign
3605 Main_Id : File_Name_Type;
3606 Source : Other_Source)
3608 Executable_Name : constant String :=
3611 (Project => Main_Project,
3612 In_Tree => Project_Tree,
3615 Ada_Main => False));
3616 -- File name of the executable
3618 Executable_Path : constant String :=
3620 (Data.Display_Exec_Dir) &
3621 Directory_Separator & Executable_Name;
3622 -- Path name of the executable
3624 Exec_Time_Stamp : Time_Stamp_Type;
3627 -- Now, check if the executable is up to date. It is considered
3628 -- up to date if its time stamp is not earlier that the time stamp
3629 -- of any archive. Only do that if we don't know if we need to link.
3631 if not Need_To_Relink then
3633 -- Get the time stamp of the executable
3636 Add_Str_To_Name_Buffer (Executable_Path);
3637 Exec_Time_Stamp := File_Stamp (File_Name_Type'(Name_Find));
3639 if Verbose_Mode then
3640 Write_Str (" Checking executable ");
3641 Write_Line (Executable_Name);
3644 -- If executable does not exist, we need to link
3646 if Exec_Time_Stamp = Empty_Time_Stamp then
3647 Need_To_Relink := True;
3649 if Verbose_Mode then
3650 Write_Line (" -> not found");
3653 -- Otherwise, get the time stamps of each archive. If one of
3654 -- them is found later than the executable, we need to relink.
3657 Check_Time_Stamps (Exec_Time_Stamp);
3660 -- If Need_To_Relink is False, we are done
3662 if Verbose_Mode and (not Need_To_Relink) then
3663 Write_Line (" -> up to date");
3669 if Need_To_Relink then
3674 -- Specify the executable path name
3676 Add_Argument (Dash_o, True);
3678 (Get_Name_String (Data.Display_Exec_Dir) &
3679 Directory_Separator &
3682 (Project => Main_Project,
3683 In_Tree => Project_Tree,
3686 Ada_Main => False)),
3689 -- Specify the object file of the main source
3692 (Object_Dir & Directory_Separator &
3693 Get_Name_String (Source.Object_Name),
3696 -- Add all the archives, in a correct order
3698 Add_Archives (For_Gnatmake => False);
3700 -- Add the switches specified in package Linker of
3701 -- the main project.
3706 Language => Source.Language,
3707 File_Name => Main_Id);
3709 -- Add the switches specified in attribute
3710 -- Linker_Options of packages Linker.
3712 if Link_Options_Switches = null then
3713 Link_Options_Switches :=
3715 (Linker_Options_Switches (Main_Project, Project_Tree));
3718 Add_Arguments (Link_Options_Switches.all, True);
3720 -- Add the linking options specified on the
3723 for Arg in 1 .. Linker_Options.Last loop
3724 Add_Argument (Linker_Options.Table (Arg), True);
3727 -- If there are shared libraries and the run path
3728 -- option is supported, add the run path switch.
3730 if Lib_Path.Last > 0 then
3733 String (Lib_Path.Table (1 .. Lib_Path.Last)),
3737 -- And invoke the linker
3739 Display_Command (Linker_Name.all, Linker_Path);
3742 Arguments (1 .. Last_Argument),
3746 Report_Error ("could not link ", Main);
3751 -- Start of processing of Link_Executables
3754 -- If no mains specified, get mains from attribute Main, if it exists
3756 if not Mains_Specified then
3758 Element_Id : String_List_Id;
3759 Element : String_Element;
3762 Element_Id := Data.Mains;
3763 while Element_Id /= Nil_String loop
3764 Element := Project_Tree.String_Elements.Table (Element_Id);
3766 if Element.Value /= No_Name then
3767 Mains.Add_Main (Get_Name_String (Element.Value));
3770 Element_Id := Element.Next;
3775 if Mains.Number_Of_Mains = 0 then
3777 -- If the attribute Main is an empty list or not specified,
3778 -- there is nothing to do.
3780 if Verbose_Mode then
3781 Write_Line ("No main to link");
3786 -- Check if -o was used for several mains
3788 if Output_File_Name /= null and then Mains.Number_Of_Mains > 1 then
3789 Osint.Fail ("cannot specify an executable name for several mains");
3792 -- Check how we are going to do the link
3794 if not Data.Other_Sources_Present then
3796 -- Only Ada sources in the main project, and even maybe not
3798 if not Data.Languages (Ada_Language_Index) then
3800 -- Fail if the main project has no source of any language
3804 Get_Name_String (Data.Name),
3805 """ has no sources, so no main can be linked");
3808 -- Only Ada sources in the main project, call gnatmake directly
3812 -- Choose correct linker if there is C++ code in other projects
3814 if C_Plus_Plus_Is_Used then
3815 Choose_C_Plus_Plus_Link_Process;
3816 Add_Argument (Dash_largs, Verbose_Mode);
3817 Add_C_Plus_Plus_Link_For_Gnatmake;
3818 Add_Argument (Dash_margs, Verbose_Mode);
3821 Compile_Link_With_Gnatmake (Mains_Specified);
3825 -- There are other language sources. First check if there are also
3828 if Data.Languages (Ada_Language_Index) then
3830 -- There is a mix of Ada and other language sources in the main
3831 -- project. Any main that is not a source of the other languages
3832 -- will be deemed to be an Ada main.
3834 -- Find the mains of the other languages and the Ada mains
3837 Ada_Mains.Set_Last (0);
3838 Other_Mains.Set_Last (0);
3844 Main : constant String := Mains.Next_Main;
3845 Main_Id : File_Name_Type;
3848 exit when Main'Length = 0;
3850 -- Get the main file name
3853 Add_Str_To_Name_Buffer (Main);
3854 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
3855 Main_Id := Name_Find;
3857 -- Check if it is a source of a language other than Ada
3859 Source_Id := Data.First_Other_Source;
3860 while Source_Id /= No_Other_Source loop
3862 Project_Tree.Other_Sources.Table (Source_Id);
3863 exit when Source.File_Name = Main_Id;
3864 Source_Id := Source.Next;
3867 -- If it is not, put it in the list of Ada mains
3869 if Source_Id = No_Other_Source then
3870 Ada_Mains.Increment_Last;
3871 Ada_Mains.Table (Ada_Mains.Last) := new String'(Main);
3873 -- Otherwise, put it in the list of other mains
3876 Other_Mains.Increment_Last;
3877 Other_Mains.Table (Other_Mains.Last) := Source;
3882 -- If C++ is one of the other language, create the shell script
3885 if C_Plus_Plus_Is_Used then
3886 Choose_C_Plus_Plus_Link_Process;
3889 -- Call gnatmake with the necessary switches for each non-Ada
3890 -- main, if there are some.
3892 for Main in 1 .. Other_Mains.Last loop
3894 Source : constant Other_Source := Other_Mains.Table (Main);
3899 -- Add -o if -o was specified
3901 if Output_File_Name = null then
3902 Add_Argument (Dash_o, True);
3906 (Project => Main_Project,
3907 In_Tree => Project_Tree,
3908 Main => Other_Mains.Table (Main).File_Name,
3910 Ada_Main => False)),
3914 -- Call gnatmake with the -B switch
3916 Add_Argument (Dash_B, True);
3918 -- Add to the linking options the object file of the source
3920 Add_Argument (Dash_largs, Verbose_Mode);
3922 (Get_Name_String (Source.Object_Name), Verbose_Mode);
3924 -- If C++ is one of the language, add the --LINK switch
3925 -- to the linking switches.
3927 if C_Plus_Plus_Is_Used then
3928 Add_C_Plus_Plus_Link_For_Gnatmake;
3931 -- Add -margs so that the following switches are for
3934 Add_Argument (Dash_margs, Verbose_Mode);
3936 -- And link with gnatmake
3938 Compile_Link_With_Gnatmake (Mains_Specified => False);
3942 -- If there are also Ada mains, call gnatmake for all these mains
3944 if Ada_Mains.Last /= 0 then
3947 -- Put all the Ada mains as the first arguments
3949 for Main in 1 .. Ada_Mains.Last loop
3950 Add_Argument (Ada_Mains.Table (Main).all, True);
3953 -- If C++ is one of the languages, add the --LINK switch to
3954 -- the linking switches.
3956 if Data.Languages (C_Plus_Plus_Language_Index) then
3957 Add_Argument (Dash_largs, Verbose_Mode);
3958 Add_C_Plus_Plus_Link_For_Gnatmake;
3959 Add_Argument (Dash_margs, Verbose_Mode);
3962 -- And link with gnatmake
3964 Compile_Link_With_Gnatmake (Mains_Specified => False);
3968 -- No Ada source in main project
3970 -- First, get the linker to invoke
3972 if Data.Languages (C_Plus_Plus_Language_Index) then
3973 Get_Compiler (C_Plus_Plus_Language_Index);
3974 Linker_Name := Compiler_Names (C_Plus_Plus_Language_Index);
3975 Linker_Path := Compiler_Paths (C_Plus_Plus_Language_Index);
3978 Get_Compiler (C_Language_Index);
3979 Linker_Name := Compiler_Names (C_Language_Index);
3980 Linker_Path := Compiler_Paths (C_Language_Index);
3987 -- Get each main, check if it is a source of the main project,
3988 -- and if it is, invoke the linker.
3992 Main : constant String := Mains.Next_Main;
3993 Main_Id : File_Name_Type;
3996 exit when Main'Length = 0;
3998 -- Get the file name of the main
4001 Add_Str_To_Name_Buffer (Main);
4002 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
4003 Main_Id := Name_Find;
4005 -- Check if it is a source of the main project file
4007 Source_Id := Data.First_Other_Source;
4008 while Source_Id /= No_Other_Source loop
4010 Project_Tree.Other_Sources.Table (Source_Id);
4011 exit when Source.File_Name = Main_Id;
4012 Source_Id := Source.Next;
4015 -- Report an error if it is not
4017 if Source_Id = No_Other_Source then
4019 (Main, "is not a source of project ",
4020 Get_Name_String (Data.Name));
4023 Link_Foreign (Main, Main_Id, Source);
4028 -- If no linking was done, report it, except in Quiet Output
4030 if (Verbose_Mode or (not Quiet_Output)) and (not Link_Done) then
4031 Osint.Write_Program_Name;
4033 if Mains.Number_Of_Mains = 1 then
4035 -- If there is only one executable, report its name too
4041 Main : constant String := Mains.Next_Main;
4042 Main_Id : File_Name_Type;
4045 Add_Str_To_Name_Buffer (Main);
4046 Main_Id := Name_Find;
4050 (Project => Main_Project,
4051 In_Tree => Project_Tree,
4054 Ada_Main => False)));
4055 Write_Line (""" up to date");
4059 Write_Line (": all executables up to date");
4064 end Link_Executables;
4070 procedure Report_Error
4076 -- If Keep_Going is True, output error message preceded by error header
4079 Total_Number_Of_Errors := Total_Number_Of_Errors + 1;
4080 Write_Str (Error_Header);
4086 -- Otherwise just fail
4089 Osint.Fail (S1, S2, S3);
4093 -------------------------
4094 -- Report_Total_Errors --
4095 -------------------------
4097 procedure Report_Total_Errors (Kind : String) is
4099 if Total_Number_Of_Errors /= 0 then
4100 if Total_Number_Of_Errors = 1 then
4102 ("One ", Kind, " error");
4106 ("Total of" & Total_Number_Of_Errors'Img,
4107 ' ' & Kind & " errors");
4110 end Report_Total_Errors;
4116 procedure Scan_Arg (Arg : String) is
4118 pragma Assert (Arg'First = 1);
4120 if Arg'Length = 0 then
4124 -- If preceding switch was -P, a project file name need to be
4125 -- specified, not a switch.
4127 if Project_File_Name_Expected then
4128 if Arg (1) = '-' then
4129 Osint.Fail ("project file name missing after -P");
4131 Project_File_Name_Expected := False;
4132 Project_File_Name := new String'(Arg);
4135 -- If preceding switch was -o, an executable name need to be
4136 -- specified, not a switch.
4138 elsif Output_File_Name_Expected then
4139 if Arg (1) = '-' then
4140 Osint.Fail ("output file name missing after -o");
4142 Output_File_Name_Expected := False;
4143 Output_File_Name := new String'(Arg);
4146 -- Set the processor/language for the following switches
4148 -- -cargs: Ada compiler arguments
4150 elsif Arg = "-cargs" then
4151 Current_Language := Ada_Language_Index;
4152 Current_Processor := Compiler;
4154 elsif Arg'Length > 7 and then Arg (1 .. 7) = "-cargs:" then
4156 Add_Str_To_Name_Buffer (Arg (8 .. Arg'Last));
4157 To_Lower (Name_Buffer (1 .. Name_Len));
4160 Lang : constant Name_Id := Name_Find;
4162 Current_Language := Language_Indexes.Get (Lang);
4164 if Current_Language = No_Language_Index then
4165 Add_Language_Name (Lang);
4166 Current_Language := Last_Language_Index;
4169 Current_Processor := Compiler;
4172 elsif Arg = "-largs" then
4173 Current_Processor := Linker;
4177 elsif Arg = "-gargs" then
4178 Current_Processor := None;
4180 -- A special test is needed for the -o switch within a -largs since
4181 -- that is another way to specify the name of the final executable.
4183 elsif Current_Processor = Linker and then Arg = "-o" then
4185 ("switch -o not allowed within a -largs. Use -o directly.");
4187 -- If current processor is not gprmake directly, store the option in
4188 -- the appropriate table.
4190 elsif Current_Processor /= None then
4193 -- Switches start with '-'
4195 elsif Arg (1) = '-' then
4196 if Arg'Length > 3 and then Arg (1 .. 3) = "-aP" then
4197 Add_Search_Project_Directory (Arg (4 .. Arg'Last));
4199 -- Record the switch, so that it is passed to gnatmake, if
4200 -- gnatmake is called.
4202 Saved_Switches.Append (new String'(Arg));
4204 elsif Arg = "-c" then
4205 Compile_Only := True;
4207 -- Make sure that when a main is specified and switch -c is used,
4208 -- only the main(s) is/are compiled.
4210 if Mains.Number_Of_Mains > 0 then
4211 Unique_Compile := True;
4214 elsif Arg = "-d" then
4215 Display_Compilation_Progress := True;
4217 elsif Arg = "-f" then
4218 Force_Compilations := True;
4220 elsif Arg = "-h" then
4223 elsif Arg = "-k" then
4226 elsif Arg = "-o" then
4227 if Output_File_Name /= null then
4228 Osint.Fail ("cannot specify several -o switches");
4231 Output_File_Name_Expected := True;
4234 elsif Arg'Length >= 2 and then Arg (2) = 'P' then
4235 if Project_File_Name /= null then
4236 Osint.Fail ("cannot have several project files specified");
4238 elsif Arg'Length = 2 then
4239 Project_File_Name_Expected := True;
4242 Project_File_Name := new String'(Arg (3 .. Arg'Last));
4245 elsif Arg = "-p" or else Arg = "--create-missing-dirs" then
4246 Setup_Projects := True;
4248 elsif Arg = "-q" then
4249 Quiet_Output := True;
4251 elsif Arg = "-u" then
4252 Unique_Compile := True;
4253 Compile_Only := True;
4255 elsif Arg = "-v" then
4256 Verbose_Mode := True;
4259 elsif Arg'Length = 4 and then Arg (1 .. 3) = "-vP"
4260 and then Arg (4) in '0' .. '2'
4264 Current_Verbosity := Prj.Default;
4266 Current_Verbosity := Prj.Medium;
4268 Current_Verbosity := Prj.High;
4273 elsif Arg'Length >= 3 and then Arg (2) = 'X'
4274 and then Is_External_Assignment (Arg)
4276 -- Is_External_Assignment has side effects when it returns True
4278 -- Record the -X switch, so that it will be passed to gnatmake,
4279 -- if gnatmake is called.
4281 Saved_Switches.Append (new String'(Arg));
4284 Osint.Fail ("illegal option """, Arg, """");
4288 -- Not a switch: must be a main
4290 Mains.Add_Main (Arg);
4292 -- Make sure that when a main is specified and switch -c is used,
4293 -- only the main(s) is/are compiled.
4295 if Compile_Only then
4296 Unique_Compile := True;
4305 function Strip_CR_LF (Text : String) return String is
4306 To : String (1 .. Text'Length);
4307 Index_To : Natural := 0;
4310 for Index in Text'Range loop
4311 if (Text (Index) /= ASCII.CR) and then (Text (Index) /= ASCII.LF) then
4312 Index_To := Index_To + 1;
4313 To (Index_To) := Text (Index);
4317 return To (1 .. Index_To);
4326 if not Usage_Output then
4327 Usage_Output := True;
4330 Write_Str ("Usage: ");
4331 Osint.Write_Program_Name;
4332 Write_Str (" -P<project file> [opts] [name] {");
4333 Write_Str ("[-cargs:lang opts] ");
4334 Write_Str ("[-largs opts] [-gargs opts]}");
4337 Write_Str (" name is zero or more file names");
4343 Write_Str ("gprmake switches:");
4348 Write_Str (" -aPdir Add directory dir to project search path");
4353 Write_Str (" -c Compile only");
4358 Write_Str (" -f Force recompilations");
4363 Write_Str (" -k Keep going after compilation errors");
4368 Write_Str (" -o name Choose an alternate executable name");
4373 Write_Str (" -p Create missing obj, lib and exec dirs");
4378 Write_Str (" -Pproj Use GNAT Project File proj");
4383 Write_Str (" -q Be quiet/terse");
4389 (" -u Unique compilation. Only compile the given files");
4394 Write_Str (" -v Verbose output");
4399 Write_Str (" -vPx Specify verbosity when parsing Project Files");
4404 Write_Str (" -Xnm=val Specify an external reference for " &
4411 Write_Line (" -cargs opts opts are passed to the Ada compiler");
4413 -- Line for -cargs:lang
4415 Write_Line (" -cargs:<lang> opts");
4416 Write_Line (" opts are passed to the compiler " &
4417 "for language < lang > ");
4421 Write_Str (" -largs opts opts are passed to the linker");
4426 Write_Str (" -gargs opts opts directly interpreted by gprmake");
4434 Makeutl.Do_Fail := Report_Error'Access;